示例#1
0
/* 
   recursively descend a tree deleting all files
   returns the number of files deleted, or -1 on error
*/
int smbcli_deltree(struct smbcli_tree *tree, const char *dname)
{
	char *mask;
	struct delete_state dstate;
	NTSTATUS status;

	dstate.tree = tree;
	dstate.total_deleted = 0;
	dstate.failed = false;

	/* it might be a file */
	status = smbcli_unlink(tree, dname);
	if (NT_STATUS_IS_OK(smbcli_unlink(tree, dname))) {
		return 1;
	}
	if (NT_STATUS_EQUAL(smbcli_nt_error(tree), NT_STATUS_OBJECT_NAME_NOT_FOUND) ||
	    NT_STATUS_EQUAL(smbcli_nt_error(tree), NT_STATUS_OBJECT_PATH_NOT_FOUND) ||
	    NT_STATUS_EQUAL(smbcli_nt_error(tree), NT_STATUS_NO_SUCH_FILE) ||
	    NT_STATUS_EQUAL(smbcli_nt_error(tree), NT_STATUS_DOS(ERRDOS, ERRbadfile))) {
		return 0;
	}
	if (NT_STATUS_EQUAL(status, NT_STATUS_CANNOT_DELETE)) {
		/* it could be read-only */
		status = smbcli_setatr(tree, dname, FILE_ATTRIBUTE_NORMAL, 0);
		if (NT_STATUS_IS_OK(smbcli_unlink(tree, dname))) {
			return 1;
		}
	}

	asprintf(&mask, "%s\\*", dname);
	smbcli_unlink(dstate.tree, mask);
	smbcli_list(dstate.tree, mask, 
		 FILE_ATTRIBUTE_DIRECTORY|FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM, 
		 delete_fn, &dstate);
	free(mask);

	status = smbcli_rmdir(dstate.tree, dname);
	if (NT_STATUS_EQUAL(status, NT_STATUS_CANNOT_DELETE)) {
		/* it could be read-only */
		status = smbcli_setatr(dstate.tree, dname, FILE_ATTRIBUTE_NORMAL, 0);
		status = smbcli_rmdir(dstate.tree, dname);
	}
	if (NT_STATUS_IS_ERR(status)) {
		DEBUG(2,("Failed to delete %s - %s\n", 
			 dname, smbcli_errstr(dstate.tree)));
		return -1;
	}
	dstate.total_deleted++;

	if (dstate.failed) {
		return -1;
	}

	return dstate.total_deleted;
}
示例#2
0
static int ejs_rmdir(MprVarHandle eid, int argc, MprVar **argv)
{
	struct smbcli_tree *tree;
	NTSTATUS result;

	if (argc != 2) {
		ejsSetErrorMsg(eid, "rmdir(): invalid number of args");
		return -1;
	}

	if (!IS_TREE_HANDLE(argv[0])) {
		ejsSetErrorMsg(eid, "first arg is not a tree handle");
		return -1;
	}

	tree = argv[0]->ptr;

	if (!mprVarIsString(argv[1]->type)) {
		ejsSetErrorMsg(eid, "arg 2 must be a string");
		return -1;
	}
	
	result = smbcli_rmdir(tree, argv[1]->string);

	mpr_Return(eid, mprNTSTATUS(result));

	return 0;
}
示例#3
0
文件: masktest.c 项目: AllardJ/Tomato
static void test_mask(int argc, char *argv[],
					  TALLOC_CTX *mem_ctx,
		      struct smbcli_state *cli)
{
	char *mask, *file;
	int l1, l2, i, l;
	int mc_len = strlen(maskchars);
	int fc_len = strlen(filechars);

	smbcli_mkdir(cli->tree, "\\masktest");

	smbcli_unlink(cli->tree, "\\masktest\\*");

	if (argc >= 2) {
		while (argc >= 2) {
			mask = talloc_strdup(mem_ctx, "\\masktest\\");
			file = talloc_strdup(mem_ctx, "\\masktest\\");
			mask = talloc_strdup_append(mask, argv[0]);
			file = talloc_strdup_append(file, argv[1]);
			testpair(mem_ctx, cli, mask, file);
			argv += 2;
			argc -= 2;
		}
		goto finished;
	}

	while (1) {
		l1 = 1 + random() % max_length;
		l2 = 1 + random() % max_length;
		mask = talloc_strdup(mem_ctx, "\\masktest\\");
		file = talloc_strdup(mem_ctx, "\\masktest\\");
		mask = talloc_realloc_size(mem_ctx, mask, strlen(mask)+l1+1);
		file = talloc_realloc_size(mem_ctx, file, strlen(file)+l2+1);
		l = strlen(mask);
		for (i=0;i<l1;i++) {
			mask[i+l] = maskchars[random() % mc_len];
		}
		mask[l+l1] = 0;

		for (i=0;i<l2;i++) {
			file[i+l] = filechars[random() % fc_len];
		}
		file[l+l2] = 0;

		if (ISDOT(file+l) || ISDOTDOT(file+l) || ISDOTDOT(mask+l)) {
			continue;
		}

		if (strspn(file+l, ".") == strlen(file+l)) continue;

		testpair(mem_ctx, cli, mask, file);
		if (NumLoops && (--NumLoops == 0))
			break;
	}

 finished:
	smbcli_rmdir(cli->tree, "\\masktest");
	talloc_free(mem_ctx);
}
示例#4
0
BOOL torture_mangle(struct torture_context *torture, 
					struct smbcli_state *cli)
{
	extern int torture_numops;
	int i;

	/* we will use an internal tdb to store the names we have used */
	tdb = tdb_open(NULL, 100000, TDB_INTERNAL, 0, 0);
	if (!tdb) {
		printf("ERROR: Failed to open tdb\n");
		return False;
	}

	if (!torture_setup_dir(cli, "\\mangle_test")) {
		return False;
	}

	for (i=0;i<torture_numops;i++) {
		fstring name;

		ZERO_STRUCT(name);

		gen_name(name);

		if (!test_one(cli, name)) {
			break;
		}
		if (total && total % 100 == 0) {
			printf("collisions %u/%u  - %.2f%%   (%u failures)\r",
			       collisions, total, (100.0*collisions) / total, failures);
		}
	}

	smbcli_unlink(cli->tree, "\\mangle_test\\*");
	if (NT_STATUS_IS_ERR(smbcli_rmdir(cli->tree, "\\mangle_test"))) {
		printf("ERROR: Failed to remove directory\n");
		return False;
	}

	printf("\nTotal collisions %u/%u  - %.2f%%   (%u failures)\n",
	       collisions, total, (100.0*collisions) / total, failures);

	return (failures == 0);
}
示例#5
0
/* 
   callback function for torture_deltree() 
*/
static void delete_fn(struct clilist_file_info *finfo, const char *name, void *state)
{
	struct delete_state *dstate = (struct delete_state *)state;
	char *s, *n;
	if (ISDOT(finfo->name) || ISDOTDOT(finfo->name)) {
		return;
	}

	n = strdup(name);
	n[strlen(n)-1] = 0;
	asprintf(&s, "%s%s", n, finfo->name);

	if (finfo->attrib & FILE_ATTRIBUTE_READONLY) {
		if (NT_STATUS_IS_ERR(smbcli_setatr(dstate->tree, s, 0, 0))) {
			DEBUG(2,("Failed to remove READONLY on %s - %s\n",
				 s, smbcli_errstr(dstate->tree)));			
		}
	}

	if (finfo->attrib & FILE_ATTRIBUTE_DIRECTORY) {
		char *s2;
		asprintf(&s2, "%s\\*", s);
		smbcli_unlink(dstate->tree, s2);
		smbcli_list(dstate->tree, s2, 
			 FILE_ATTRIBUTE_DIRECTORY|FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM, 
			 delete_fn, state);
		free(s2);
		if (NT_STATUS_IS_ERR(smbcli_rmdir(dstate->tree, s))) {
			DEBUG(2,("Failed to delete %s - %s\n", 
				 s, smbcli_errstr(dstate->tree)));
			dstate->failed = true;
		}
		dstate->total_deleted++;
	} else {
		if (NT_STATUS_IS_ERR(smbcli_unlink(dstate->tree, s))) {
			DEBUG(2,("Failed to delete %s - %s\n", 
				 s, smbcli_errstr(dstate->tree)));
			dstate->failed = true;
		}
		dstate->total_deleted++;
	}
	free(s);
	free(n);
}
示例#6
0
文件: rename.c 项目: endisd/samba
/*
  test dir rename.
*/
static bool test_dir_rename(struct torture_context *tctx, struct smbcli_state *cli)
{
    union smb_open io;
    union smb_rename ren_io;
    NTSTATUS status;
    const char *dname1 = BASEDIR "\\dir_for_rename";
    const char *dname2 = BASEDIR "\\renamed_dir";
    const char *dname1_long = BASEDIR "\\dir_for_rename_long";
    const char *fname = BASEDIR "\\dir_for_rename\\file.txt";
    const char *sname = BASEDIR "\\renamed_dir:a stream:$DATA";
    bool ret = true;
    int fnum = -1;

    torture_comment(tctx, "Checking rename on a directory containing an open file.\n");

    if (!torture_setup_dir(cli, BASEDIR)) {
        return false;
    }

    /* create a directory */
    smbcli_rmdir(cli->tree, dname1);
    smbcli_rmdir(cli->tree, dname2);
    smbcli_rmdir(cli->tree, dname1_long);
    smbcli_unlink(cli->tree, dname1);
    smbcli_unlink(cli->tree, dname2);
    smbcli_unlink(cli->tree, dname1_long);

    ZERO_STRUCT(io);
    io.generic.level = RAW_OPEN_NTCREATEX;
    io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
    io.ntcreatex.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
    io.ntcreatex.in.alloc_size = 0;
    io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
    io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ | NTCREATEX_SHARE_ACCESS_WRITE;
    io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
    io.ntcreatex.in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
    io.ntcreatex.in.fname = dname1;
    status = smb_raw_open(cli->tree, tctx, &io);
    CHECK_STATUS(status, NT_STATUS_OK);

    fnum = io.ntcreatex.out.file.fnum;
    smbcli_close(cli->tree, fnum);

    /* create the longname directory */
    io.ntcreatex.in.fname = dname1_long;
    status = smb_raw_open(cli->tree, tctx, &io);
    CHECK_STATUS(status, NT_STATUS_OK);

    fnum = io.ntcreatex.out.file.fnum;
    smbcli_close(cli->tree, fnum);

    /* Now create and hold open a file. */
    ZERO_STRUCT(io);

    io.generic.level = RAW_OPEN_NTCREATEX;
    io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED;
    io.ntcreatex.in.root_fid.fnum = 0;
    io.ntcreatex.in.alloc_size = 0;
    io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
    io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
    io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ | NTCREATEX_SHARE_ACCESS_WRITE | NTCREATEX_SHARE_ACCESS_DELETE;
    io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
    io.ntcreatex.in.create_options = 0;
    io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
    io.ntcreatex.in.security_flags = 0;
    io.ntcreatex.in.fname = fname;

    /* Create the file. */

    status = smb_raw_open(cli->tree, tctx, &io);
    CHECK_STATUS(status, NT_STATUS_OK);
    fnum = io.ntcreatex.out.file.fnum;

    /* Now try and rename the directory. */

    ZERO_STRUCT(ren_io);
    ren_io.generic.level = RAW_RENAME_RENAME;
    ren_io.rename.in.pattern1 = dname1;
    ren_io.rename.in.pattern2 = dname2;
    ren_io.rename.in.attrib = 0;

    status = smb_raw_rename(cli->tree, &ren_io);
    CHECK_STATUS(status, NT_STATUS_ACCESS_DENIED);

    /* Close the file and try the rename. */
    smbcli_close(cli->tree, fnum);

    status = smb_raw_rename(cli->tree, &ren_io);
    CHECK_STATUS(status, NT_STATUS_OK);

    /*
     * Now try just holding a second handle on the directory and holding
     * it open across a rename.  This should be allowed.
     */
    io.ntcreatex.in.fname = dname2;
    io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;

    io.ntcreatex.in.access_mask = SEC_STD_READ_CONTROL |
                                  SEC_FILE_READ_ATTRIBUTE | SEC_FILE_READ_EA | SEC_FILE_READ_DATA;

    status = smb_raw_open(cli->tree, tctx, &io);
    CHECK_STATUS(status, NT_STATUS_OK);
    fnum = io.ntcreatex.out.file.fnum;

    ren_io.generic.level = RAW_RENAME_RENAME;
    ren_io.rename.in.pattern1 = dname2;
    ren_io.rename.in.pattern2 = dname1;
    ren_io.rename.in.attrib = 0;

    status = smb_raw_rename(cli->tree, &ren_io);
    CHECK_STATUS(status, NT_STATUS_OK);

    /* close our handle to the directory. */
    smbcli_close(cli->tree, fnum);

    /* Open a handle on the long name, and then
     * try a rename. This would catch a regression
     * in bug #6781.
     */
    io.ntcreatex.in.fname = dname1_long;
    io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;

    io.ntcreatex.in.access_mask = SEC_STD_READ_CONTROL |
                                  SEC_FILE_READ_ATTRIBUTE | SEC_FILE_READ_EA | SEC_FILE_READ_DATA;

    status = smb_raw_open(cli->tree, tctx, &io);
    CHECK_STATUS(status, NT_STATUS_OK);
    fnum = io.ntcreatex.out.file.fnum;

    ren_io.generic.level = RAW_RENAME_RENAME;
    ren_io.rename.in.pattern1 = dname1;
    ren_io.rename.in.pattern2 = dname2;
    ren_io.rename.in.attrib = 0;

    status = smb_raw_rename(cli->tree, &ren_io);
    CHECK_STATUS(status, NT_STATUS_OK);

    /* close our handle to the longname directory. */
    smbcli_close(cli->tree, fnum);

    /*
     * Now try opening a stream on the directory and holding it open
     * across a rename.  This should be allowed.
     */
    io.ntcreatex.in.fname = sname;

    status = smb_raw_open(cli->tree, tctx, &io);
    CHECK_STATUS(status, NT_STATUS_OK);
    fnum = io.ntcreatex.out.file.fnum;

    ren_io.generic.level = RAW_RENAME_RENAME;
    ren_io.rename.in.pattern1 = dname2;
    ren_io.rename.in.pattern2 = dname1;
    ren_io.rename.in.attrib = 0;

    status = smb_raw_rename(cli->tree, &ren_io);
    CHECK_STATUS(status, NT_STATUS_OK);

done:

    if (fnum != -1) {
        smbcli_close(cli->tree, fnum);
    }
    smb_raw_exit(cli->session);
    smbcli_deltree(cli->tree, BASEDIR);
    return ret;
}
示例#7
0
文件: scanner.c 项目: AIdrifter/samba
/****************************************************************************
check for existance of a nttrans call
****************************************************************************/
static bool scan_nttrans(struct smbcli_state *cli, int op, int level,
			int fnum, int dnum, const char *fname)
{
	int data_len = 0;
	int param_len = 0;
	int rparam_len, rdata_len;
	uint8_t *param, *data;
	NTSTATUS status;
	TALLOC_CTX *mem_ctx;

	mem_ctx = talloc_init("scan_nttrans");

	param = talloc_array(mem_ctx, uint8_t, PARAM_SIZE);
	data = talloc_array(mem_ctx, uint8_t, PARAM_SIZE);
	memset(data, 0, PARAM_SIZE);
	data_len = 4;

	/* try with a info level only */
	param_len = 2;
	SSVAL(param, 0, level);
	status = try_nttrans_len(cli, "void", op, level, param, data, param_len,
			&data_len, &rparam_len, &rdata_len);
	if (NT_STATUS_IS_OK(status)) {
		talloc_free(mem_ctx);
		return true;
	}

	/* try with a file descriptor */
	param_len = 6;
	SSVAL(param, 0, fnum);
	SSVAL(param, 2, level);
	SSVAL(param, 4, 0);
	status = try_nttrans_len(cli, "fnum", op, level, param, data, param_len,
			&data_len, &rparam_len, &rdata_len);
	if (NT_STATUS_IS_OK(status)) {
		talloc_free(mem_ctx);
		return true;
	}

	/* try with a notify style */
	param_len = 6;
	SSVAL(param, 0, dnum);
	SSVAL(param, 2, dnum);
	SSVAL(param, 4, level);
	status = try_nttrans_len(cli, "notify", op, level, param, data,
			param_len, &data_len, &rparam_len, &rdata_len);
	if (NT_STATUS_IS_OK(status)) {
		talloc_free(mem_ctx);
		return true;
	}

	/* try with a file name */
	param_len = 6;
	SSVAL(param, 0, level);
	SSVAL(param, 2, 0);
	SSVAL(param, 4, 0);
	param_len += push_string(
			&param[6], fname, PARAM_SIZE,
			STR_TERMINATE | STR_UNICODE);

	status = try_nttrans_len(cli, "fname", op, level, param, data,
			param_len, &data_len, &rparam_len, &rdata_len);
	if (NT_STATUS_IS_OK(status)) {
		talloc_free(mem_ctx);
		return true;
	}

	/* try with a new file name */
	param_len = 6;
	SSVAL(param, 0, level);
	SSVAL(param, 2, 0);
	SSVAL(param, 4, 0);
	param_len += push_string(
			&param[6], "\\newfile.dat", PARAM_SIZE,
			STR_TERMINATE | STR_UNICODE);

	status = try_nttrans_len(cli, "newfile", op, level, param, data,
			param_len, &data_len, &rparam_len, &rdata_len);
	smbcli_unlink(cli->tree, "\\newfile.dat");
	smbcli_rmdir(cli->tree, "\\newfile.dat");
	if (NT_STATUS_IS_OK(status)) {
		talloc_free(mem_ctx);
		return true;
	}

	/* try dfs style  */
	smbcli_mkdir(cli->tree, "\\testdir");
	param_len = 2;
	SSVAL(param, 0, level);
	param_len += push_string(&param[2], "\\testdir", PARAM_SIZE,
			STR_TERMINATE | STR_UNICODE);

	status = try_nttrans_len(cli, "dfs", op, level, param, data, param_len,
			&data_len, &rparam_len, &rdata_len);
	smbcli_rmdir(cli->tree, "\\testdir");
	if (NT_STATUS_IS_OK(status)) {
		talloc_free(mem_ctx);
		return true;
	}

	talloc_free(mem_ctx);
	return false;
}
示例#8
0
文件: utable.c 项目: 0x24bin/winexe-1
bool torture_utable(struct torture_context *tctx, 
					struct smbcli_state *cli)
{
	char fname[256];
	const char *alt_name;
	int fnum;
	uint8_t c2[4];
	int c, fd;
	size_t len;
	int chars_allowed=0, alt_allowed=0;
	uint8_t valid[0x10000];

	torture_comment(tctx, "Generating valid character table\n");

	memset(valid, 0, sizeof(valid));

	torture_assert(tctx, torture_setup_dir(cli, "\\utable"),
				   "Setting up dir \\utable failed");

	for (c=1; c < 0x10000; c++) {
		char *p;

		SSVAL(c2, 0, c);
		strncpy(fname, "\\utable\\x", sizeof(fname)-1);
		p = fname+strlen(fname);
		convert_string_convenience(lp_iconv_convenience(tctx->lp_ctx), CH_UTF16, CH_UNIX, 
				     c2, 2, 
				     p, sizeof(fname)-strlen(fname), &len, false);
		p[len] = 0;
		strncat(fname,"_a_long_extension",sizeof(fname)-1);

		fnum = smbcli_open(cli->tree, fname, O_RDWR | O_CREAT | O_TRUNC, 
				DENY_NONE);
		if (fnum == -1) continue;

		chars_allowed++;

		smbcli_qpathinfo_alt_name(cli->tree, fname, &alt_name);

		if (strncmp(alt_name, "X_A_L", 5) != 0) {
			alt_allowed++;
			valid[c] = 1;
			torture_comment(tctx, "fname=[%s] alt_name=[%s]\n", fname, alt_name);
		}

		smbcli_close(cli->tree, fnum);
		smbcli_unlink(cli->tree, fname);

		if (c % 100 == 0) {
			if (torture_setting_bool(tctx, "progress", true)) {
				torture_comment(tctx, "%d (%d/%d)\r", c, chars_allowed, alt_allowed);
				fflush(stdout);
			}
		}
	}
	torture_comment(tctx, "%d (%d/%d)\n", c, chars_allowed, alt_allowed);

	smbcli_rmdir(cli->tree, "\\utable");

	torture_comment(tctx, "%d chars allowed   %d alt chars allowed\n", chars_allowed, alt_allowed);

	fd = open("valid.dat", O_WRONLY|O_CREAT|O_TRUNC, 0644);
	torture_assert(tctx, fd != -1, 
		talloc_asprintf(tctx, 
		"Failed to create valid.dat - %s", strerror(errno)));
	write(fd, valid, 0x10000);
	close(fd);
	torture_comment(tctx, "wrote valid.dat\n");

	return true;
}
示例#9
0
文件: utable.c 项目: 0x24bin/winexe-1
bool torture_casetable(struct torture_context *tctx, 
					   struct smbcli_state *cli)
{
	char *fname;
	int fnum;
	int c, i;
#define MAX_EQUIVALENCE 8
	codepoint_t equiv[0x10000][MAX_EQUIVALENCE];

	torture_comment(tctx, "Determining upper/lower case table\n");

	memset(equiv, 0, sizeof(equiv));

	torture_assert(tctx, torture_setup_dir(cli, "\\utable"),
				   "Error setting up dir \\utable");

	for (c=1; c < 0x10000; c++) {
		size_t size;

		if (c == '.' || c == '\\') continue;

		torture_comment(tctx, "%04x (%c)\n", c, isprint(c)?c:'.');

		fname = form_name(lp_iconv_convenience(tctx->lp_ctx), c);
		fnum = smbcli_nt_create_full(cli->tree, fname, 0,
#if 0
					     SEC_RIGHT_MAXIMUM_ALLOWED, 
#else
					     SEC_RIGHTS_FILE_ALL,
#endif
					     FILE_ATTRIBUTE_NORMAL,
					     NTCREATEX_SHARE_ACCESS_NONE,
					     NTCREATEX_DISP_OPEN_IF, 0, 0);

		torture_assert(tctx, fnum != -1, 
					   talloc_asprintf(tctx, 
			"Failed to create file with char %04x\n", c));

		size = 0;

		if (NT_STATUS_IS_ERR(smbcli_qfileinfo(cli->tree, fnum, NULL, &size, 
						   NULL, NULL, NULL, NULL, NULL))) continue;

		if (size > 0) {
			/* found a character equivalence! */
			int c2[MAX_EQUIVALENCE];

			if (size/sizeof(int) >= MAX_EQUIVALENCE) {
				torture_comment(tctx, "too many chars match?? size=%d c=0x%04x\n",
				       (int)size, c);
				smbcli_close(cli->tree, fnum);
				return false;
			}

			smbcli_read(cli->tree, fnum, c2, 0, size);
			torture_comment(tctx, "%04x: ", c);
			equiv[c][0] = c;
			for (i=0; i<size/sizeof(int); i++) {
				torture_comment(tctx, "%04x ", c2[i]);
				equiv[c][i+1] = c2[i];
			}
			torture_comment(tctx, "\n");
		}

		smbcli_write(cli->tree, fnum, 0, &c, size, sizeof(c));
		smbcli_close(cli->tree, fnum);
	}

	smbcli_unlink(cli->tree, "\\utable\\*");
	smbcli_rmdir(cli->tree, "\\utable");

	return true;
}
示例#10
0
文件: rename.c 项目: gojdic/samba
/*
  test dir rename.
*/
static bool test_dir_rename(struct torture_context *tctx, struct smbcli_state *cli)
{
        union smb_open io;
	union smb_rename ren_io;
	NTSTATUS status;
        const char *dname1 = BASEDIR "\\dir_for_rename";
        const char *dname2 = BASEDIR "\\renamed_dir";
        const char *fname = BASEDIR "\\dir_for_rename\\file.txt";
	bool ret = true;
	int fnum = -1;

        printf("Checking rename on a directory containing an open file.\n");

	if (!torture_setup_dir(cli, BASEDIR)) {
		return false;
	}

        /* create a directory */
        smbcli_rmdir(cli->tree, dname1);
        smbcli_rmdir(cli->tree, dname2);
        smbcli_unlink(cli->tree, dname1);
        smbcli_unlink(cli->tree, dname2);

        ZERO_STRUCT(io);
        io.generic.level = RAW_OPEN_NTCREATEX;
        io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
        io.ntcreatex.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
        io.ntcreatex.in.alloc_size = 0;
        io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
        io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ | NTCREATEX_SHARE_ACCESS_WRITE;
        io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
        io.ntcreatex.in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
        io.ntcreatex.in.fname = dname1;
        status = smb_raw_open(cli->tree, tctx, &io);
        CHECK_STATUS(status, NT_STATUS_OK);

        fnum = io.ntcreatex.out.file.fnum;
	smbcli_close(cli->tree, fnum);

        /* Now create and hold open a file. */
        ZERO_STRUCT(io);

        io.generic.level = RAW_OPEN_NTCREATEX;
        io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED;
        io.ntcreatex.in.root_fid = 0;
        io.ntcreatex.in.alloc_size = 0;
        io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
        io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
        io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ | NTCREATEX_SHARE_ACCESS_WRITE | NTCREATEX_SHARE_ACCESS_DELETE;
        io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
        io.ntcreatex.in.create_options = 0;
        io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
        io.ntcreatex.in.security_flags = 0;
        io.ntcreatex.in.fname = fname;

        /* Create the file. */

        status = smb_raw_open(cli->tree, tctx, &io);
        CHECK_STATUS(status, NT_STATUS_OK);
        fnum = io.ntcreatex.out.file.fnum;

        /* Now try and rename the directory. */

        ZERO_STRUCT(ren_io);
	ren_io.generic.level = RAW_RENAME_RENAME;
	ren_io.rename.in.pattern1 = dname1;
	ren_io.rename.in.pattern2 = dname2;
	ren_io.rename.in.attrib = 0;
	
	status = smb_raw_rename(cli->tree, &ren_io);
	CHECK_STATUS(status, NT_STATUS_ACCESS_DENIED);

done:
	
	if (fnum != -1) {
		smbcli_close(cli->tree, fnum);
	}
	smb_raw_exit(cli->session);
	smbcli_deltree(cli->tree, BASEDIR);
	return ret;
}