예제 #1
0
파일: vfs_cifs.c 프로젝트: srimalik/samba
/*
  rename a set of files
*/
static NTSTATUS cvfs_rename(struct ntvfs_module_context *ntvfs, 
			    struct ntvfs_request *req, union smb_rename *ren)
{
	struct cvfs_private *p = ntvfs->private_data;
	struct smbcli_request *c_req;

	SETUP_PID;

	if (ren->nttrans.level == RAW_RENAME_NTTRANS) {
		struct cvfs_file *f;
		f = ntvfs_handle_get_backend_data(ren->nttrans.in.file.ntvfs, ntvfs);
		if (!f) return NT_STATUS_INVALID_HANDLE;
		ren->nttrans.in.file.fnum = f->fnum;
	}

	if (!(req->async_states->state & NTVFS_ASYNC_STATE_MAY_ASYNC)) {
		return smb_raw_rename(p->tree, ren);
	}

	c_req = smb_raw_rename_send(p->tree, ren);

	SIMPLE_ASYNC_TAIL;
}
예제 #2
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;
}
예제 #3
0
파일: rename.c 프로젝트: endisd/samba
/*
  test SMBmv ops
*/
static bool test_mv(struct torture_context *tctx,
                    struct smbcli_state *cli)
{
    union smb_rename io;
    NTSTATUS status;
    bool ret = true;
    int fnum = -1;
    const char *fname1 = BASEDIR "\\test1.txt";
    const char *fname2 = BASEDIR "\\test2.txt";
    const char *Fname1 = BASEDIR "\\Test1.txt";
    union smb_fileinfo finfo;
    union smb_open op;

    torture_comment(tctx, "Testing SMBmv\n");

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

    torture_comment(tctx, "Trying simple rename\n");

    op.generic.level = RAW_OPEN_NTCREATEX;
    op.ntcreatex.in.root_fid.fnum = 0;
    op.ntcreatex.in.flags = 0;
    op.ntcreatex.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
    op.ntcreatex.in.create_options = 0;
    op.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
    op.ntcreatex.in.share_access =
        NTCREATEX_SHARE_ACCESS_READ |
        NTCREATEX_SHARE_ACCESS_WRITE;
    op.ntcreatex.in.alloc_size = 0;
    op.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
    op.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
    op.ntcreatex.in.security_flags = 0;
    op.ntcreatex.in.fname = fname1;

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

    io.generic.level = RAW_RENAME_RENAME;
    io.rename.in.pattern1 = fname1;
    io.rename.in.pattern2 = fname2;
    io.rename.in.attrib = 0;

    torture_comment(tctx, "trying rename while first file open\n");
    status = smb_raw_rename(cli->tree, &io);
    CHECK_STATUS(status, NT_STATUS_SHARING_VIOLATION);

    smbcli_close(cli->tree, fnum);

    op.ntcreatex.in.access_mask = SEC_FILE_READ_DATA;
    op.ntcreatex.in.share_access =
        NTCREATEX_SHARE_ACCESS_DELETE |
        NTCREATEX_SHARE_ACCESS_READ |
        NTCREATEX_SHARE_ACCESS_WRITE;
    status = smb_raw_open(cli->tree, tctx, &op);
    CHECK_STATUS(status, NT_STATUS_OK);
    fnum = op.ntcreatex.out.file.fnum;

    torture_comment(tctx, "trying rename while first file open with SHARE_ACCESS_DELETE\n");
    status = smb_raw_rename(cli->tree, &io);
    CHECK_STATUS(status, NT_STATUS_OK);

    io.rename.in.pattern1 = fname2;
    io.rename.in.pattern2 = fname1;
    status = smb_raw_rename(cli->tree, &io);
    CHECK_STATUS(status, NT_STATUS_OK);

    torture_comment(tctx, "Trying case-changing rename\n");
    io.rename.in.pattern1 = fname1;
    io.rename.in.pattern2 = Fname1;
    status = smb_raw_rename(cli->tree, &io);
    CHECK_STATUS(status, NT_STATUS_OK);

    finfo.generic.level = RAW_FILEINFO_ALL_INFO;
    finfo.all_info.in.file.path = fname1;
    status = smb_raw_pathinfo(cli->tree, tctx, &finfo);
    CHECK_STATUS(status, NT_STATUS_OK);
    if (strcmp(finfo.all_info.out.fname.s, Fname1) != 0) {
        torture_warning(tctx, "(%s) Incorrect filename [%s] after case-changing "
                        "rename, should be [%s]\n", __location__,
                        finfo.all_info.out.fname.s, Fname1);
    }

    io.rename.in.pattern1 = fname1;
    io.rename.in.pattern2 = fname2;

    torture_comment(tctx, "trying rename while not open\n");
    smb_raw_exit(cli->session);
    status = smb_raw_rename(cli->tree, &io);
    CHECK_STATUS(status, NT_STATUS_OK);

    torture_comment(tctx, "Trying self rename\n");
    io.rename.in.pattern1 = fname2;
    io.rename.in.pattern2 = fname2;
    status = smb_raw_rename(cli->tree, &io);
    CHECK_STATUS(status, NT_STATUS_OK);

    io.rename.in.pattern1 = fname1;
    io.rename.in.pattern2 = fname1;
    status = smb_raw_rename(cli->tree, &io);
    CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_NOT_FOUND);


    torture_comment(tctx, "trying wildcard rename\n");
    io.rename.in.pattern1 = BASEDIR "\\*.txt";
    io.rename.in.pattern2 = fname1;

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

    torture_comment(tctx, "and again\n");
    status = smb_raw_rename(cli->tree, &io);
    CHECK_STATUS(status, NT_STATUS_OK);

    torture_comment(tctx, "Trying extension change\n");
    io.rename.in.pattern1 = BASEDIR "\\*.txt";
    io.rename.in.pattern2 = BASEDIR "\\*.bak";
    status = smb_raw_rename(cli->tree, &io);
    CHECK_STATUS(status, NT_STATUS_OK);

    status = smb_raw_rename(cli->tree, &io);
    CHECK_STATUS(status, NT_STATUS_NO_SUCH_FILE);

    torture_comment(tctx, "Checking attrib handling\n");
    torture_set_file_attribute(cli->tree, BASEDIR "\\test1.bak", FILE_ATTRIBUTE_HIDDEN);
    io.rename.in.pattern1 = BASEDIR "\\test1.bak";
    io.rename.in.pattern2 = BASEDIR "\\*.txt";
    io.rename.in.attrib = 0;
    status = smb_raw_rename(cli->tree, &io);
    CHECK_STATUS(status, NT_STATUS_NO_SUCH_FILE);

    io.rename.in.attrib = FILE_ATTRIBUTE_HIDDEN;
    status = smb_raw_rename(cli->tree, &io);
    CHECK_STATUS(status, NT_STATUS_OK);

done:
    smbcli_close(cli->tree, fnum);
    smb_raw_exit(cli->session);
    smbcli_deltree(cli->tree, BASEDIR);
    return ret;
}
예제 #4
0
파일: rename.c 프로젝트: endisd/samba
/*
  test SMBntrename ops
*/
static bool test_ntrename(struct torture_context *tctx,
                          struct smbcli_state *cli)
{
    union smb_rename io;
    NTSTATUS status;
    bool ret = true;
    int fnum, i;
    const char *fname1 = BASEDIR "\\test1.txt";
    const char *fname2 = BASEDIR "\\test2.txt";
    union smb_fileinfo finfo;

    torture_comment(tctx, "Testing SMBntrename\n");

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

    torture_comment(tctx, "Trying simple rename\n");

    fnum = create_complex_file(cli, tctx, fname1);

    io.generic.level = RAW_RENAME_NTRENAME;
    io.ntrename.in.old_name = fname1;
    io.ntrename.in.new_name = fname2;
    io.ntrename.in.attrib = 0;
    io.ntrename.in.cluster_size = 0;
    io.ntrename.in.flags = RENAME_FLAG_RENAME;

    status = smb_raw_rename(cli->tree, &io);
    CHECK_STATUS(status, NT_STATUS_SHARING_VIOLATION);

    smbcli_close(cli->tree, fnum);
    status = smb_raw_rename(cli->tree, &io);
    CHECK_STATUS(status, NT_STATUS_OK);

    torture_comment(tctx, "Trying self rename\n");
    io.ntrename.in.old_name = fname2;
    io.ntrename.in.new_name = fname2;
    status = smb_raw_rename(cli->tree, &io);
    CHECK_STATUS(status, NT_STATUS_OK);

    io.ntrename.in.old_name = fname1;
    io.ntrename.in.new_name = fname1;
    status = smb_raw_rename(cli->tree, &io);
    CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_NOT_FOUND);

    torture_comment(tctx, "trying wildcard rename\n");
    io.ntrename.in.old_name = BASEDIR "\\*.txt";
    io.ntrename.in.new_name = fname1;

    status = smb_raw_rename(cli->tree, &io);
    CHECK_STATUS(status, NT_STATUS_OBJECT_PATH_SYNTAX_BAD);

    torture_comment(tctx, "Checking attrib handling\n");
    torture_set_file_attribute(cli->tree, fname2, FILE_ATTRIBUTE_HIDDEN);
    io.ntrename.in.old_name = fname2;
    io.ntrename.in.new_name = fname1;
    io.ntrename.in.attrib = 0;
    status = smb_raw_rename(cli->tree, &io);
    CHECK_STATUS(status, NT_STATUS_NO_SUCH_FILE);

    io.ntrename.in.attrib = FILE_ATTRIBUTE_HIDDEN;
    status = smb_raw_rename(cli->tree, &io);
    CHECK_STATUS(status, NT_STATUS_OK);

    torture_set_file_attribute(cli->tree, fname1, FILE_ATTRIBUTE_NORMAL);

    torture_comment(tctx, "Checking hard link\n");
    io.ntrename.in.old_name = fname1;
    io.ntrename.in.new_name = fname2;
    io.ntrename.in.attrib = 0;
    io.ntrename.in.flags = RENAME_FLAG_HARD_LINK;
    status = smb_raw_rename(cli->tree, &io);
    CHECK_STATUS(status, NT_STATUS_OK);

    torture_set_file_attribute(cli->tree, fname1, FILE_ATTRIBUTE_SYSTEM);

    finfo.generic.level = RAW_FILEINFO_ALL_INFO;
    finfo.generic.in.file.path = fname2;
    status = smb_raw_pathinfo(cli->tree, tctx, &finfo);
    CHECK_STATUS(status, NT_STATUS_OK);
    CHECK_VALUE(finfo.all_info.out.nlink, 2);
    CHECK_VALUE(finfo.all_info.out.attrib, FILE_ATTRIBUTE_SYSTEM);

    finfo.generic.in.file.path = fname1;
    status = smb_raw_pathinfo(cli->tree, tctx, &finfo);
    CHECK_STATUS(status, NT_STATUS_OK);
    CHECK_VALUE(finfo.all_info.out.nlink, 2);
    CHECK_VALUE(finfo.all_info.out.attrib, FILE_ATTRIBUTE_SYSTEM);

    torture_set_file_attribute(cli->tree, fname1, FILE_ATTRIBUTE_NORMAL);

    smbcli_unlink(cli->tree, fname2);

    finfo.generic.in.file.path = fname1;
    status = smb_raw_pathinfo(cli->tree, tctx, &finfo);
    CHECK_STATUS(status, NT_STATUS_OK);
    CHECK_VALUE(finfo.all_info.out.nlink, 1);
    CHECK_VALUE(finfo.all_info.out.attrib, FILE_ATTRIBUTE_NORMAL);

    torture_comment(tctx, "Checking copy\n");
    io.ntrename.in.old_name = fname1;
    io.ntrename.in.new_name = fname2;
    io.ntrename.in.attrib = 0;
    io.ntrename.in.flags = RENAME_FLAG_COPY;
    status = smb_raw_rename(cli->tree, &io);
    CHECK_STATUS(status, NT_STATUS_OK);

    finfo.generic.level = RAW_FILEINFO_ALL_INFO;
    finfo.generic.in.file.path = fname1;
    status = smb_raw_pathinfo(cli->tree, tctx, &finfo);
    CHECK_STATUS(status, NT_STATUS_OK);
    CHECK_VALUE(finfo.all_info.out.nlink, 1);
    CHECK_VALUE(finfo.all_info.out.attrib, FILE_ATTRIBUTE_NORMAL);

    finfo.generic.level = RAW_FILEINFO_ALL_INFO;
    finfo.generic.in.file.path = fname2;
    status = smb_raw_pathinfo(cli->tree, tctx, &finfo);
    CHECK_STATUS(status, NT_STATUS_OK);
    CHECK_VALUE(finfo.all_info.out.nlink, 1);
    CHECK_VALUE(finfo.all_info.out.attrib, FILE_ATTRIBUTE_NORMAL);

    torture_set_file_attribute(cli->tree, fname1, FILE_ATTRIBUTE_SYSTEM);

    finfo.generic.level = RAW_FILEINFO_ALL_INFO;
    finfo.generic.in.file.path = fname2;
    status = smb_raw_pathinfo(cli->tree, tctx, &finfo);
    CHECK_STATUS(status, NT_STATUS_OK);
    CHECK_VALUE(finfo.all_info.out.nlink, 1);
    CHECK_VALUE(finfo.all_info.out.attrib, FILE_ATTRIBUTE_NORMAL);

    finfo.generic.in.file.path = fname1;
    status = smb_raw_pathinfo(cli->tree, tctx, &finfo);
    CHECK_STATUS(status, NT_STATUS_OK);
    CHECK_VALUE(finfo.all_info.out.nlink, 1);
    CHECK_VALUE(finfo.all_info.out.attrib, FILE_ATTRIBUTE_SYSTEM);

    torture_set_file_attribute(cli->tree, fname1, FILE_ATTRIBUTE_NORMAL);

    smbcli_unlink(cli->tree, fname2);

    finfo.generic.in.file.path = fname1;
    status = smb_raw_pathinfo(cli->tree, tctx, &finfo);
    CHECK_STATUS(status, NT_STATUS_OK);
    CHECK_VALUE(finfo.all_info.out.nlink, 1);

    torture_comment(tctx, "Checking invalid flags\n");
    io.ntrename.in.old_name = fname1;
    io.ntrename.in.new_name = fname2;
    io.ntrename.in.attrib = 0;
    io.ntrename.in.flags = 0;
    status = smb_raw_rename(cli->tree, &io);
    if (TARGET_IS_WIN7(tctx)) {
        CHECK_STATUS(status, NT_STATUS_INVALID_PARAMETER);
    } else {
        CHECK_STATUS(status, NT_STATUS_ACCESS_DENIED);
    }

    io.ntrename.in.flags = 300;
    status = smb_raw_rename(cli->tree, &io);
    if (TARGET_IS_WIN7(tctx)) {
        CHECK_STATUS(status, NT_STATUS_INVALID_PARAMETER);
    } else {
        CHECK_STATUS(status, NT_STATUS_ACCESS_DENIED);
    }

    io.ntrename.in.flags = 0x106;
    status = smb_raw_rename(cli->tree, &io);
    if (TARGET_IS_WIN7(tctx)) {
        CHECK_STATUS(status, NT_STATUS_INVALID_PARAMETER);
    } else {
        CHECK_STATUS(status, NT_STATUS_ACCESS_DENIED);
    }

    torture_comment(tctx, "Checking unknown field\n");
    io.ntrename.in.old_name = fname1;
    io.ntrename.in.new_name = fname2;
    io.ntrename.in.attrib = 0;
    io.ntrename.in.flags = RENAME_FLAG_RENAME;
    io.ntrename.in.cluster_size = 0xff;
    status = smb_raw_rename(cli->tree, &io);
    CHECK_STATUS(status, NT_STATUS_OK);

    torture_comment(tctx, "Trying RENAME_FLAG_MOVE_CLUSTER_INFORMATION\n");

    io.ntrename.in.old_name = fname2;
    io.ntrename.in.new_name = fname1;
    io.ntrename.in.attrib = 0;
    io.ntrename.in.flags = RENAME_FLAG_MOVE_CLUSTER_INFORMATION;
    io.ntrename.in.cluster_size = 1;
    status = smb_raw_rename(cli->tree, &io);
    CHECK_STATUS(status, NT_STATUS_INVALID_PARAMETER);

    io.ntrename.in.flags = RENAME_FLAG_COPY;
    status = smb_raw_rename(cli->tree, &io);
    CHECK_STATUS(status, NT_STATUS_OK);

#if 0
    {
        char buf[16384];
        fnum = smbcli_open(cli->tree, fname1, O_RDWR, DENY_NONE);
        memset(buf, 1, sizeof(buf));
        smbcli_write(cli->tree, fnum, 0, buf, 0, sizeof(buf));
        smbcli_close(cli->tree, fnum);

        fnum = smbcli_open(cli->tree, fname2, O_RDWR, DENY_NONE);
        memset(buf, 1, sizeof(buf));
        smbcli_write(cli->tree, fnum, 0, buf, 0, sizeof(buf)-1);
        smbcli_close(cli->tree, fnum);

        torture_all_info(cli->tree, fname1);
        torture_all_info(cli->tree, fname2);
    }


    io.ntrename.in.flags = RENAME_FLAG_MOVE_CLUSTER_INFORMATION;
    status = smb_raw_rename(cli->tree, &io);
    CHECK_STATUS(status, NT_STATUS_INVALID_PARAMETER);

    for (i=0; i<20000; i++) {
        io.ntrename.in.cluster_size = i;
        status = smb_raw_rename(cli->tree, &io);
        if (!NT_STATUS_EQUAL(status, NT_STATUS_INVALID_PARAMETER)) {
            torture_warning(tctx, "i=%d status=%s\n", i, nt_errstr(status));
        }
    }
#endif

    torture_comment(tctx, "Checking other flags\n");

    for (i=0; i<0xFFF; i++) {
        if (i == RENAME_FLAG_RENAME ||
                i == RENAME_FLAG_HARD_LINK ||
                i == RENAME_FLAG_COPY) {
            continue;
        }

        io.ntrename.in.old_name = fname2;
        io.ntrename.in.new_name = fname1;
        io.ntrename.in.flags = i;
        io.ntrename.in.attrib = 0;
        io.ntrename.in.cluster_size = 0;
        status = smb_raw_rename(cli->tree, &io);
        if (TARGET_IS_WIN7(tctx)) {
            if (!NT_STATUS_EQUAL(status,
                                 NT_STATUS_INVALID_PARAMETER)) {
                torture_warning(tctx, "flags=0x%x status=%s\n",
                                i, nt_errstr(status));
            }
        } else {
            if (!NT_STATUS_EQUAL(status,
                                 NT_STATUS_ACCESS_DENIED)) {
                torture_warning(tctx, "flags=0x%x status=%s\n",
                                i, nt_errstr(status));
            }
        }
    }

done:
    smb_raw_exit(cli->session);
    smbcli_deltree(cli->tree, BASEDIR);
    return ret;
}
예제 #5
0
파일: rename.c 프로젝트: endisd/samba
static bool test_osxrename(struct torture_context *tctx,
                           struct smbcli_state *cli)
{
    union smb_rename io;
    union smb_unlink io_un;
    NTSTATUS status;
    bool ret = true;
    int fnum = -1;
    const char *fname1 = BASEDIR "\\test1";
    const char *FNAME1 = BASEDIR "\\TEST1";
    union smb_fileinfo finfo;
    union smb_open op;

    torture_comment(tctx, "\nTesting OSX Rename\n");
    if (!torture_setup_dir(cli, BASEDIR)) {
        return false;
    }
    op.generic.level = RAW_OPEN_NTCREATEX;
    op.ntcreatex.in.root_fid.fnum = 0;
    op.ntcreatex.in.flags = 0;
    op.ntcreatex.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
    op.ntcreatex.in.create_options = 0;
    op.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
    op.ntcreatex.in.share_access =
        NTCREATEX_SHARE_ACCESS_READ |
        NTCREATEX_SHARE_ACCESS_WRITE;
    op.ntcreatex.in.alloc_size = 0;
    op.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
    op.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
    op.ntcreatex.in.security_flags = 0;
    op.ntcreatex.in.fname = fname1;

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

    io.generic.level = RAW_RENAME_RENAME;
    io.rename.in.attrib = 0;

    smbcli_close(cli->tree, fnum);

    /* Rename by changing case. First check for the
     * existence of the file with the "newname".
     * If we find one and both the output and input are same case,
     * delete it. */

    torture_comment(tctx, "Checking os X rename (case changing)\n");

    finfo.generic.level = RAW_FILEINFO_ALL_INFO;
    finfo.all_info.in.file.path = FNAME1;
    torture_comment(tctx, "Looking for file %s \n",FNAME1);
    status = smb_raw_pathinfo(cli->tree, tctx, &finfo);

    if (NT_STATUS_EQUAL(status, NT_STATUS_OK)) {
        torture_comment(tctx, "Name of the file found %s \n", finfo.all_info.out.fname.s);
        if (strcmp(finfo.all_info.out.fname.s, finfo.all_info.in.file.path) == 0) {
            /* If file is found with the same case delete it */
            torture_comment(tctx, "Deleting File %s \n", finfo.all_info.out.fname.s);
            io_un.unlink.in.pattern = finfo.all_info.out.fname.s;
            io_un.unlink.in.attrib = 0;
            status = smb_raw_unlink(cli->tree, &io_un);
            CHECK_STATUS(status, NT_STATUS_OK);
        }
    }

    io.rename.in.pattern1 = fname1;
    io.rename.in.pattern2 = FNAME1;
    status = smb_raw_rename(cli->tree, &io);
    CHECK_STATUS(status, NT_STATUS_OK);

    finfo.generic.level = RAW_FILEINFO_ALL_INFO;
    finfo.all_info.in.file.path = fname1;
    status = smb_raw_pathinfo(cli->tree, tctx, &finfo);
    CHECK_STATUS(status, NT_STATUS_OK);
    torture_comment(tctx, "File name after rename %s \n",finfo.all_info.out.fname.s);

done:
    smbcli_close(cli->tree, fnum);
    smb_raw_exit(cli->session);
    smbcli_deltree(cli->tree, BASEDIR);
    return ret;
}
예제 #6
0
bool torture_samba3_badpath(struct torture_context *torture)
{
	struct smbcli_state *cli_nt = NULL;
	struct smbcli_state *cli_dos = NULL;
	const char *fname = "test.txt";
	const char *fname1 = "test1.txt";
	const char *dirname = "testdir";
	char *fpath;
	char *fpath1;
	int fnum;
	NTSTATUS status;
	bool ret = true;
	TALLOC_CTX *mem_ctx;
	bool nt_status_support;

	torture_assert(torture, mem_ctx = talloc_init("torture_samba3_badpath"), "talloc_init failed");

	nt_status_support = lpcfg_nt_status_support(torture->lp_ctx);

	torture_assert_goto(torture, lpcfg_set_cmdline(torture->lp_ctx, "nt status support", "yes"), ret, fail, "Could not set 'nt status support = yes'\n");

	torture_assert_goto(torture, torture_open_connection(&cli_nt, torture, 0), ret, fail, "Could not open NTSTATUS connection\n");

	torture_assert_goto(torture, lpcfg_set_cmdline(torture->lp_ctx, "nt status support", "no"), ret, fail, "Could not set 'nt status support = no'\n");

	torture_assert_goto(torture, torture_open_connection(&cli_dos, torture, 1), ret, fail, "Could not open DOS connection\n");

	torture_assert_goto(torture, lpcfg_set_cmdline(torture->lp_ctx, "nt status support",
						       nt_status_support ? "yes":"no"), 
			    ret, fail, "Could not set 'nt status support' back to where it was\n");

	torture_assert(torture, torture_setup_dir(cli_nt, dirname), "creating test directory");

	status = smbcli_chkpath(cli_nt->tree, dirname);
	CHECK_STATUS(torture, status, NT_STATUS_OK);

	status = smbcli_chkpath(cli_nt->tree,
				talloc_asprintf(mem_ctx, "%s\\bla", dirname));
	CHECK_STATUS(torture, status, NT_STATUS_OBJECT_NAME_NOT_FOUND);

	status = smbcli_chkpath(cli_dos->tree,
				talloc_asprintf(mem_ctx, "%s\\bla", dirname));
	CHECK_STATUS(torture, status, NT_STATUS_DOS(ERRDOS, ERRbadpath));

	status = smbcli_chkpath(cli_nt->tree,
				talloc_asprintf(mem_ctx, "%s\\bla\\blub",
						dirname));
	CHECK_STATUS(torture, status, NT_STATUS_OBJECT_PATH_NOT_FOUND);
	status = smbcli_chkpath(cli_dos->tree,
				talloc_asprintf(mem_ctx, "%s\\bla\\blub",
						dirname));
	CHECK_STATUS(torture, status, NT_STATUS_DOS(ERRDOS, ERRbadpath));

	torture_assert_goto(torture, fpath = talloc_asprintf(mem_ctx, "%s\\%s", dirname, fname), 
			    ret, fail, "Could not allocate fpath\n");

	fnum = smbcli_open(cli_nt->tree, fpath, O_RDWR | O_CREAT, DENY_NONE);
	if (fnum == -1) {
		torture_result(torture, TORTURE_FAIL, "Could not create file %s: %s\n", fpath,
			 smbcli_errstr(cli_nt->tree));
		goto fail;
	}
	smbcli_close(cli_nt->tree, fnum);

	if (!(fpath1 = talloc_asprintf(mem_ctx, "%s\\%s", dirname, fname1))) {
		goto fail;
	}
	fnum = smbcli_open(cli_nt->tree, fpath1, O_RDWR | O_CREAT, DENY_NONE);
	if (fnum == -1) {
		torture_result(torture, TORTURE_FAIL, "Could not create file %s: %s\n", fpath1,
			 smbcli_errstr(cli_nt->tree));
		goto fail;
	}
	smbcli_close(cli_nt->tree, fnum);

	/*
	 * Do a whole bunch of error code checks on chkpath
	 */

	status = smbcli_chkpath(cli_nt->tree, fpath);
	CHECK_STATUS(torture, status, NT_STATUS_NOT_A_DIRECTORY);
	status = smbcli_chkpath(cli_dos->tree, fpath);
	CHECK_STATUS(torture, status, NT_STATUS_DOS(ERRDOS, ERRbadpath));

	status = smbcli_chkpath(cli_nt->tree, "..");
	CHECK_STATUS(torture, status, NT_STATUS_OBJECT_PATH_SYNTAX_BAD);
	status = smbcli_chkpath(cli_dos->tree, "..");
	CHECK_STATUS(torture, status, NT_STATUS_DOS(ERRDOS, ERRinvalidpath));

	status = smbcli_chkpath(cli_nt->tree, ".");
	CHECK_STATUS(torture, status, NT_STATUS_OBJECT_NAME_INVALID);
	status = smbcli_chkpath(cli_dos->tree, ".");
	CHECK_STATUS(torture, status, NT_STATUS_DOS(ERRDOS, ERRbadpath));

	status = smbcli_chkpath(cli_nt->tree, "\t");
	CHECK_STATUS(torture, status, NT_STATUS_OBJECT_NAME_INVALID);
	status = smbcli_chkpath(cli_dos->tree, "\t");
	CHECK_STATUS(torture, status, NT_STATUS_DOS(ERRDOS, ERRbadpath));

	status = smbcli_chkpath(cli_nt->tree, "\t\\bla");
	CHECK_STATUS(torture, status, NT_STATUS_OBJECT_NAME_INVALID);
	status = smbcli_chkpath(cli_dos->tree, "\t\\bla");
	CHECK_STATUS(torture, status, NT_STATUS_DOS(ERRDOS, ERRbadpath));

	status = smbcli_chkpath(cli_nt->tree, "<");
	CHECK_STATUS(torture, status, NT_STATUS_OBJECT_NAME_INVALID);
	status = smbcli_chkpath(cli_dos->tree, "<");
	CHECK_STATUS(torture, status, NT_STATUS_DOS(ERRDOS, ERRbadpath));

	status = smbcli_chkpath(cli_nt->tree, "<\\bla");
	CHECK_STATUS(torture, status, NT_STATUS_OBJECT_NAME_INVALID);
	status = smbcli_chkpath(cli_dos->tree, "<\\bla");
	CHECK_STATUS(torture, status, NT_STATUS_DOS(ERRDOS, ERRbadpath));

	/*
	 * .... And the same gang against getatr. Note that the DOS error codes
	 * differ....
	 */

	status = smbcli_getatr(cli_nt->tree, fpath, NULL, NULL, NULL);
	CHECK_STATUS(torture, status, NT_STATUS_OK);
	status = smbcli_getatr(cli_dos->tree, fpath, NULL, NULL, NULL);
	CHECK_STATUS(torture, status, NT_STATUS_OK);

	status = smbcli_getatr(cli_nt->tree, "..", NULL, NULL, NULL);
	CHECK_STATUS(torture, status, NT_STATUS_OBJECT_PATH_SYNTAX_BAD);
	status = smbcli_getatr(cli_dos->tree, "..", NULL, NULL, NULL);
	CHECK_STATUS(torture, status, NT_STATUS_DOS(ERRDOS, ERRinvalidpath));

	status = smbcli_getatr(cli_nt->tree, ".", NULL, NULL, NULL);
	CHECK_STATUS(torture, status, NT_STATUS_OBJECT_NAME_INVALID);
	status = smbcli_getatr(cli_dos->tree, ".", NULL, NULL, NULL);
	CHECK_STATUS(torture, status, NT_STATUS_DOS(ERRDOS, ERRinvalidname));

	status = smbcli_getatr(cli_nt->tree, "\t", NULL, NULL, NULL);
	CHECK_STATUS(torture, status, NT_STATUS_OBJECT_NAME_INVALID);
	status = smbcli_getatr(cli_dos->tree, "\t", NULL, NULL, NULL);
	CHECK_STATUS(torture, status, NT_STATUS_DOS(ERRDOS, ERRinvalidname));

	status = smbcli_getatr(cli_nt->tree, "\t\\bla", NULL, NULL, NULL);
	CHECK_STATUS(torture, status, NT_STATUS_OBJECT_NAME_INVALID);
	status = smbcli_getatr(cli_dos->tree, "\t\\bla", NULL, NULL, NULL);
	CHECK_STATUS(torture, status, NT_STATUS_DOS(ERRDOS, ERRinvalidname));

	status = smbcli_getatr(cli_nt->tree, "<", NULL, NULL, NULL);
	CHECK_STATUS(torture, status, NT_STATUS_OBJECT_NAME_INVALID);
	status = smbcli_getatr(cli_dos->tree, "<", NULL, NULL, NULL);
	CHECK_STATUS(torture, status, NT_STATUS_DOS(ERRDOS, ERRinvalidname));

	status = smbcli_getatr(cli_nt->tree, "<\\bla", NULL, NULL, NULL);
	CHECK_STATUS(torture, status, NT_STATUS_OBJECT_NAME_INVALID);
	status = smbcli_getatr(cli_dos->tree, "<\\bla", NULL, NULL, NULL);
	CHECK_STATUS(torture, status, NT_STATUS_DOS(ERRDOS, ERRinvalidname));

	/* Try the same set with openX. */

	status = raw_smbcli_open(cli_nt->tree, "..", O_RDONLY, DENY_NONE, NULL);
	CHECK_STATUS(torture, status, NT_STATUS_OBJECT_PATH_SYNTAX_BAD);
	status = raw_smbcli_open(cli_dos->tree, "..", O_RDONLY, DENY_NONE, NULL);
	CHECK_STATUS(torture, status, NT_STATUS_DOS(ERRDOS, ERRinvalidpath));

	status = raw_smbcli_open(cli_nt->tree, ".", O_RDONLY, DENY_NONE, NULL);
	CHECK_STATUS(torture, status, NT_STATUS_OBJECT_NAME_INVALID);
	status = raw_smbcli_open(cli_dos->tree, ".", O_RDONLY, DENY_NONE, NULL);
	CHECK_STATUS(torture, status, NT_STATUS_DOS(ERRDOS, ERRinvalidname));

	status = raw_smbcli_open(cli_nt->tree, "\t", O_RDONLY, DENY_NONE, NULL);
	CHECK_STATUS(torture, status, NT_STATUS_OBJECT_NAME_INVALID);
	status = raw_smbcli_open(cli_dos->tree, "\t", O_RDONLY, DENY_NONE, NULL);
	CHECK_STATUS(torture, status, NT_STATUS_DOS(ERRDOS, ERRinvalidname));

	status = raw_smbcli_open(cli_nt->tree, "\t\\bla", O_RDONLY, DENY_NONE, NULL);
	CHECK_STATUS(torture, status, NT_STATUS_OBJECT_NAME_INVALID);
	status = raw_smbcli_open(cli_dos->tree, "\t\\bla", O_RDONLY, DENY_NONE, NULL);
	CHECK_STATUS(torture, status, NT_STATUS_DOS(ERRDOS, ERRinvalidname));

	status = raw_smbcli_open(cli_nt->tree, "<", O_RDONLY, DENY_NONE, NULL);
	CHECK_STATUS(torture, status, NT_STATUS_OBJECT_NAME_INVALID);
	status = raw_smbcli_open(cli_dos->tree, "<", O_RDONLY, DENY_NONE, NULL);
	CHECK_STATUS(torture, status, NT_STATUS_DOS(ERRDOS, ERRinvalidname));

	status = raw_smbcli_open(cli_nt->tree, "<\\bla", O_RDONLY, DENY_NONE, NULL);
	CHECK_STATUS(torture, status, NT_STATUS_OBJECT_NAME_INVALID);
	status = raw_smbcli_open(cli_dos->tree, "<\\bla", O_RDONLY, DENY_NONE, NULL);
	CHECK_STATUS(torture, status, NT_STATUS_DOS(ERRDOS, ERRinvalidname));

	/* Let's test EEXIST error code mapping. */
	status = raw_smbcli_open(cli_nt->tree, fpath, O_RDONLY | O_CREAT| O_EXCL, DENY_NONE, NULL);
	CHECK_STATUS(torture, status, NT_STATUS_OBJECT_NAME_COLLISION);
	status = raw_smbcli_open(cli_dos->tree, fpath, O_RDONLY | O_CREAT| O_EXCL, DENY_NONE, NULL);
	CHECK_STATUS(torture, status, NT_STATUS_DOS(ERRDOS,ERRfilexists));

	status = raw_smbcli_t2open(cli_nt->tree, fpath, O_RDONLY | O_CREAT| O_EXCL, DENY_NONE, NULL);
	if (!NT_STATUS_EQUAL(status, NT_STATUS_EAS_NOT_SUPPORTED)
	    || !torture_setting_bool(torture, "samba3", false)) {
		/* Against samba3, treat EAS_NOT_SUPPORTED as acceptable */
		CHECK_STATUS(torture, status, NT_STATUS_OBJECT_NAME_COLLISION);
	}
	status = raw_smbcli_t2open(cli_dos->tree, fpath, O_RDONLY | O_CREAT| O_EXCL, DENY_NONE, NULL);
	if (!NT_STATUS_EQUAL(status, NT_STATUS_DOS(ERRDOS,ERReasnotsupported))
	    || !torture_setting_bool(torture, "samba3", false)) {
		/* Against samba3, treat EAS_NOT_SUPPORTED as acceptable */
		CHECK_STATUS(torture, status, NT_STATUS_DOS(ERRDOS,ERRfilexists));
	}

	status = raw_smbcli_ntcreate(cli_nt->tree, fpath, NULL);
	CHECK_STATUS(torture, status, NT_STATUS_OBJECT_NAME_COLLISION);
	status = raw_smbcli_ntcreate(cli_dos->tree, fpath, NULL);
	CHECK_STATUS(torture, status, NT_STATUS_DOS(ERRDOS,ERRfilexists));

	/* Try the rename test. */
	{
		union smb_rename io;
		memset(&io, '\0', sizeof(io));
		io.rename.in.pattern1 = fpath1;
		io.rename.in.pattern2 = fpath;

		/* Try with SMBmv rename. */
		status = smb_raw_rename(cli_nt->tree, &io);
		CHECK_STATUS(torture, status, NT_STATUS_OBJECT_NAME_COLLISION);
		status = smb_raw_rename(cli_dos->tree, &io);
		CHECK_STATUS(torture, status, NT_STATUS_DOS(ERRDOS,ERRrename));

		/* Try with NT rename. */
		io.generic.level = RAW_RENAME_NTRENAME;
		io.ntrename.in.old_name = fpath1;
		io.ntrename.in.new_name = fpath;
		io.ntrename.in.attrib = 0;
		io.ntrename.in.cluster_size = 0;
		io.ntrename.in.flags = RENAME_FLAG_RENAME;

		status = smb_raw_rename(cli_nt->tree, &io);
		CHECK_STATUS(torture, status, NT_STATUS_OBJECT_NAME_COLLISION);
		status = smb_raw_rename(cli_dos->tree, &io);
		CHECK_STATUS(torture, status, NT_STATUS_DOS(ERRDOS,ERRrename));
	}

	goto done;

 fail:
	ret = false;

 done:
	if (cli_nt != NULL) {
		smbcli_deltree(cli_nt->tree, dirname);
		torture_close_connection(cli_nt);
	}
	if (cli_dos != NULL) {
		torture_close_connection(cli_dos);
	}
	talloc_free(mem_ctx);

	return ret;
}
예제 #7
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;
}