1
0
mirror of https://github.com/samba-team/samba.git synced 2025-01-15 23:24:37 +03:00

Merge branch 'v4-0-test' of ssh://git.samba.org/data/git/samba into v4-0-test

This commit is contained in:
Jelmer Vernooij 2008-02-29 15:34:45 +01:00
commit 18c683d7e8
11 changed files with 341 additions and 37 deletions

View File

@ -542,6 +542,25 @@ static NTSTATUS odb_ctdb_rename(struct odb_lock *lck, const char *path)
return odb_push_record(lck, &file); return odb_push_record(lck, &file);
} }
/*
get the path of an open file
*/
static NTSTATUS odb_ctdb_get_path(struct odb_lock *lck, const char **path)
{
struct opendb_file file;
NTSTATUS status;
*path = NULL;
status = odb_pull_record(lck, &file);
/* we don't ignore NT_STATUS_OBJECT_NAME_NOT_FOUND here */
NT_STATUS_NOT_OK_RETURN(status);
*path = file.path;
return NT_STATUS_OK;
}
/* /*
update delete on close flag on an open file update delete on close flag on an open file
*/ */
@ -653,6 +672,7 @@ static const struct opendb_ops opendb_ctdb_ops = {
.odb_close_file = odb_ctdb_close_file, .odb_close_file = odb_ctdb_close_file,
.odb_remove_pending = odb_ctdb_remove_pending, .odb_remove_pending = odb_ctdb_remove_pending,
.odb_rename = odb_ctdb_rename, .odb_rename = odb_ctdb_rename,
.odb_get_path = odb_ctdb_get_path,
.odb_set_delete_on_close = odb_ctdb_set_delete_on_close, .odb_set_delete_on_close = odb_ctdb_set_delete_on_close,
.odb_get_delete_on_close = odb_ctdb_get_delete_on_close, .odb_get_delete_on_close = odb_ctdb_get_delete_on_close,
.odb_can_open = odb_ctdb_can_open, .odb_can_open = odb_ctdb_can_open,

View File

@ -142,6 +142,14 @@ _PUBLIC_ NTSTATUS odb_rename(struct odb_lock *lck, const char *path)
return ops->odb_rename(lck, path); return ops->odb_rename(lck, path);
} }
/*
get back the path of an open file
*/
_PUBLIC_ NTSTATUS odb_get_path(struct odb_lock *lck, const char **path)
{
return ops->odb_get_path(lck, path);
}
/* /*
update delete on close flag on an open file update delete on close flag on an open file
*/ */

View File

@ -36,6 +36,7 @@ struct opendb_ops {
const char **delete_path); const char **delete_path);
NTSTATUS (*odb_remove_pending)(struct odb_lock *lck, void *private); NTSTATUS (*odb_remove_pending)(struct odb_lock *lck, void *private);
NTSTATUS (*odb_rename)(struct odb_lock *lck, const char *path); NTSTATUS (*odb_rename)(struct odb_lock *lck, const char *path);
NTSTATUS (*odb_get_path)(struct odb_lock *lck, const char **path);
NTSTATUS (*odb_set_delete_on_close)(struct odb_lock *lck, bool del_on_close); NTSTATUS (*odb_set_delete_on_close)(struct odb_lock *lck, bool del_on_close);
NTSTATUS (*odb_get_delete_on_close)(struct odb_context *odb, NTSTATUS (*odb_get_delete_on_close)(struct odb_context *odb,
DATA_BLOB *key, bool *del_on_close); DATA_BLOB *key, bool *del_on_close);

View File

@ -713,6 +713,25 @@ static NTSTATUS odb_tdb_rename(struct odb_lock *lck, const char *path)
return odb_push_record(lck, &file); return odb_push_record(lck, &file);
} }
/*
get the path of an open file
*/
static NTSTATUS odb_tdb_get_path(struct odb_lock *lck, const char **path)
{
struct opendb_file file;
NTSTATUS status;
*path = NULL;
status = odb_pull_record(lck, &file);
/* we don't ignore NT_STATUS_OBJECT_NAME_NOT_FOUND here */
NT_STATUS_NOT_OK_RETURN(status);
*path = file.path;
return NT_STATUS_OK;
}
/* /*
update delete on close flag on an open file update delete on close flag on an open file
*/ */
@ -802,6 +821,7 @@ static const struct opendb_ops opendb_tdb_ops = {
.odb_close_file = odb_tdb_close_file, .odb_close_file = odb_tdb_close_file,
.odb_remove_pending = odb_tdb_remove_pending, .odb_remove_pending = odb_tdb_remove_pending,
.odb_rename = odb_tdb_rename, .odb_rename = odb_tdb_rename,
.odb_get_path = odb_tdb_get_path,
.odb_set_delete_on_close = odb_tdb_set_delete_on_close, .odb_set_delete_on_close = odb_tdb_set_delete_on_close,
.odb_get_delete_on_close = odb_tdb_get_delete_on_close, .odb_get_delete_on_close = odb_tdb_get_delete_on_close,
.odb_can_open = odb_tdb_can_open, .odb_can_open = odb_tdb_can_open,

View File

@ -144,8 +144,8 @@ static NTSTATUS pvfs_open_setup_eas_acl(struct pvfs_state *pvfs,
form the lock context used for opendb locking. Note that we must form the lock context used for opendb locking. Note that we must
zero here to take account of possible padding on some architectures zero here to take account of possible padding on some architectures
*/ */
static NTSTATUS pvfs_locking_key(struct pvfs_filename *name, NTSTATUS pvfs_locking_key(struct pvfs_filename *name,
TALLOC_CTX *mem_ctx, DATA_BLOB *key) TALLOC_CTX *mem_ctx, DATA_BLOB *key)
{ {
struct { struct {
dev_t device; dev_t device;

View File

@ -368,7 +368,7 @@ NTSTATUS pvfs_qfileinfo(struct ntvfs_module_context *ntvfs,
} }
/* update the file information */ /* update the file information */
status = pvfs_resolve_name_fd(pvfs, h->fd, h->name); status = pvfs_resolve_name_handle(pvfs, h);
if (!NT_STATUS_IS_OK(status)) { if (!NT_STATUS_IS_OK(status)) {
return status; return status;
} }

View File

@ -265,8 +265,15 @@ static NTSTATUS pvfs_unix_path(struct pvfs_state *pvfs, const char *cifs_name,
of a name */ of a name */
return NT_STATUS_ILLEGAL_CHARACTER; return NT_STATUS_ILLEGAL_CHARACTER;
} }
if (p > p_start && p[1] == 0) { if (p > p_start && (p[1] == '\\' || p[1] == '\0')) {
*p = 0; /* see if it is definately a "\\" or
* a trailing "\". If it is then fail here,
* and let the next layer up try again after
* pvfs_reduce_name() if it wants to. This is
* much more efficient on average than always
* scanning for these separately
*/
return NT_STATUS_OBJECT_PATH_SYNTAX_BAD;
} else { } else {
*p = '/'; *p = '/';
} }
@ -399,7 +406,7 @@ static NTSTATUS pvfs_reduce_name(TALLOC_CTX *mem_ctx,
if (ISDOTDOT(components[i])) { if (ISDOTDOT(components[i])) {
if (i < 1) return NT_STATUS_OBJECT_PATH_SYNTAX_BAD; if (i < 1) return NT_STATUS_OBJECT_PATH_SYNTAX_BAD;
memmove(&components[i-1], &components[i+1], memmove(&components[i-1], &components[i+1],
sizeof(char *)*(num_components-(i+1))); sizeof(char *)*(num_components-i));
i -= 2; i -= 2;
continue; continue;
} }
@ -616,6 +623,86 @@ NTSTATUS pvfs_resolve_name_fd(struct pvfs_state *pvfs, int fd,
return pvfs_fill_dos_info(pvfs, name, fd); return pvfs_fill_dos_info(pvfs, name, fd);
} }
/*
fill in the pvfs_filename info for an open file, given the current
info for a (possibly) non-open file. This is used by places that need
to update the pvfs_filename stat information, and the path
after a possible rename on a different handle.
*/
NTSTATUS pvfs_resolve_name_handle(struct pvfs_state *pvfs,
struct pvfs_file_handle *h)
{
NTSTATUS status;
if (h->have_opendb_entry) {
struct odb_lock *lck;
const char *name = NULL;
lck = odb_lock(h, h->pvfs->odb_context, &h->odb_locking_key);
if (lck == NULL) {
DEBUG(0,("%s: failed to lock file '%s' in opendb\n",
__FUNCTION__, h->name->full_name));
/* we were supposed to do a blocking lock, so something
is badly wrong! */
return NT_STATUS_INTERNAL_DB_CORRUPTION;
}
status = odb_get_path(lck, &name);
if (NT_STATUS_IS_OK(status)) {
/*
* This relies an the fact that
* renames of open files are only
* allowed by setpathinfo() and setfileinfo()
* and there're only renames within the same
* directory supported
*/
if (strcmp(h->name->full_name, name) != 0) {
const char *orig_dir;
const char *new_file;
const char *new_orig;
char *delim;
delim = strrchr(name, '/');
if (!delim) {
talloc_free(lck);
return NT_STATUS_INTERNAL_ERROR;
}
new_file = delim + 1;
delim = strrchr(h->name->original_name, '\\');
if (delim) {
delim[0] = '\0';
orig_dir = h->name->original_name;
new_orig = talloc_asprintf(h->name, "%s\\%s",
orig_dir, new_file);
if (!new_orig) {
talloc_free(lck);
return NT_STATUS_NO_MEMORY;
}
} else {
new_orig = talloc_strdup(h->name, new_file);
if (!new_orig) {
talloc_free(lck);
return NT_STATUS_NO_MEMORY;
}
}
talloc_free(h->name->original_name);
talloc_free(h->name->full_name);
h->name->full_name = talloc_steal(h->name, name);
h->name->original_name = new_orig;
}
}
talloc_free(lck);
}
status = pvfs_resolve_name_fd(pvfs, h->fd, h->name);
NT_STATUS_NOT_OK_RETURN(status);
return NT_STATUS_OK;
}
/* /*
resolve the parent of a given name resolve the parent of a given name

View File

@ -82,11 +82,13 @@ static uint32_t pvfs_setfileinfo_access(union smb_setfileinfo *info)
static NTSTATUS pvfs_setfileinfo_rename(struct pvfs_state *pvfs, static NTSTATUS pvfs_setfileinfo_rename(struct pvfs_state *pvfs,
struct ntvfs_request *req, struct ntvfs_request *req,
struct pvfs_filename *name, struct pvfs_filename *name,
DATA_BLOB *odb_locking_key,
union smb_setfileinfo *info) union smb_setfileinfo *info)
{ {
NTSTATUS status; NTSTATUS status;
struct pvfs_filename *name2; struct pvfs_filename *name2;
char *new_name, *p; char *new_name, *p;
struct odb_lock *lck = NULL;
/* renames are only allowed within a directory */ /* renames are only allowed within a directory */
if (strchr_m(info->rename_information.in.new_name, '\\') && if (strchr_m(info->rename_information.in.new_name, '\\') &&
@ -94,11 +96,6 @@ static NTSTATUS pvfs_setfileinfo_rename(struct pvfs_state *pvfs,
return NT_STATUS_NOT_SUPPORTED; return NT_STATUS_NOT_SUPPORTED;
} }
if (name->dos.attrib & FILE_ATTRIBUTE_DIRECTORY) {
/* don't allow this for now */
return NT_STATUS_FILE_IS_A_DIRECTORY;
}
/* don't allow stream renames for now */ /* don't allow stream renames for now */
if (name->stream_name) { if (name->stream_name) {
return NT_STATUS_INVALID_PARAMETER; return NT_STATUS_INVALID_PARAMETER;
@ -168,7 +165,18 @@ static NTSTATUS pvfs_setfileinfo_rename(struct pvfs_state *pvfs,
return status; return status;
} }
lck = odb_lock(req, pvfs->odb_context, odb_locking_key);
if (lck == NULL) {
DEBUG(0,("Unable to lock opendb for can_stat\n"));
return NT_STATUS_INTERNAL_DB_CORRUPTION;
}
status = pvfs_do_rename(pvfs, name, name2->full_name); status = pvfs_do_rename(pvfs, name, name2->full_name);
if (NT_STATUS_IS_OK(status)) {
status = odb_rename(lck, name2->full_name);
}
talloc_free(lck);
NT_STATUS_NOT_OK_RETURN(status);
if (NT_STATUS_IS_OK(status)) { if (NT_STATUS_IS_OK(status)) {
name->full_name = talloc_steal(name, name2->full_name); name->full_name = talloc_steal(name, name2->full_name);
name->original_name = talloc_steal(name, name2->original_name); name->original_name = talloc_steal(name, name2->original_name);
@ -289,7 +297,7 @@ NTSTATUS pvfs_setfileinfo(struct ntvfs_module_context *ntvfs,
} }
/* update the file information */ /* update the file information */
status = pvfs_resolve_name_fd(pvfs, h->fd, h->name); status = pvfs_resolve_name_handle(pvfs, h);
if (!NT_STATUS_IS_OK(status)) { if (!NT_STATUS_IS_OK(status)) {
return status; return status;
} }
@ -391,7 +399,8 @@ NTSTATUS pvfs_setfileinfo(struct ntvfs_module_context *ntvfs,
case RAW_SFILEINFO_RENAME_INFORMATION: case RAW_SFILEINFO_RENAME_INFORMATION:
case RAW_SFILEINFO_RENAME_INFORMATION_SMB2: case RAW_SFILEINFO_RENAME_INFORMATION_SMB2:
return pvfs_setfileinfo_rename(pvfs, req, h->name, return pvfs_setfileinfo_rename(pvfs, req, h->name,
&h->odb_locking_key,
info); info);
case RAW_SFILEINFO_SEC_DESC: case RAW_SFILEINFO_SEC_DESC:
@ -565,6 +574,7 @@ NTSTATUS pvfs_setpathinfo(struct ntvfs_module_context *ntvfs,
uint32_t access_needed; uint32_t access_needed;
uint32_t change_mask = 0; uint32_t change_mask = 0;
struct odb_lock *lck = NULL; struct odb_lock *lck = NULL;
DATA_BLOB odb_locking_key;
/* resolve the cifs name to a posix name */ /* resolve the cifs name to a posix name */
status = pvfs_resolve_name(pvfs, req, info->generic.in.file.path, status = pvfs_resolve_name(pvfs, req, info->generic.in.file.path,
@ -696,8 +706,12 @@ NTSTATUS pvfs_setpathinfo(struct ntvfs_module_context *ntvfs,
case RAW_SFILEINFO_RENAME_INFORMATION: case RAW_SFILEINFO_RENAME_INFORMATION:
case RAW_SFILEINFO_RENAME_INFORMATION_SMB2: case RAW_SFILEINFO_RENAME_INFORMATION_SMB2:
return pvfs_setfileinfo_rename(pvfs, req, name, status = pvfs_locking_key(name, name, &odb_locking_key);
info); NT_STATUS_NOT_OK_RETURN(status);
status = pvfs_setfileinfo_rename(pvfs, req, name,
&odb_locking_key, info);
NT_STATUS_NOT_OK_RETURN(status);
return NT_STATUS_OK;
case RAW_SFILEINFO_DISPOSITION_INFO: case RAW_SFILEINFO_DISPOSITION_INFO:
case RAW_SFILEINFO_DISPOSITION_INFORMATION: case RAW_SFILEINFO_DISPOSITION_INFORMATION:

View File

@ -3,8 +3,6 @@ local.iconv.*.next_codepoint()
base.delaywrite.finfo update on close base.delaywrite.finfo update on close
base.delete.*.deltest20a base.delete.*.deltest20a
base.delete.*.deltest20b base.delete.*.deltest20b
raw.oplock.*BATCH19
raw.oplock.*BATCH20
rpc.winreg rpc.winreg
local.registry.*.security # Not implemented yet local.registry.*.security # Not implemented yet
rpc.wkssvc rpc.wkssvc

View File

@ -54,24 +54,68 @@ static NTSTATUS single_search(struct smbcli_state *cli,
return status; return status;
} }
static bool test_path(struct smbcli_state *cli, const char *path, NTSTATUS expected, NTSTATUS dos_expected) static bool test_path_ex(struct smbcli_state *cli, struct torture_context *tctx,
const char *path, const char *path_expected,
NTSTATUS expected, NTSTATUS dos_expected)
{ {
union smb_chkpath io; union smb_chkpath io;
union smb_fileinfo finfo;
NTSTATUS status; NTSTATUS status;
io.chkpath.in.path = path; io.chkpath.in.path = path;
status = smb_raw_chkpath(cli->tree, &io); status = smb_raw_chkpath(cli->tree, &io);
if (!NT_STATUS_EQUAL(status, expected) && !NT_STATUS_EQUAL(status, dos_expected)) { if (!NT_STATUS_EQUAL(status, expected) && !NT_STATUS_EQUAL(status, dos_expected)) {
printf("%-40s FAILED %s should be %s or %s\n", printf("FAILED %-30s chkpath %s should be %s or %s\n",
path, nt_errstr(status), nt_errstr(expected), nt_errstr(dos_expected)); path, nt_errstr(status), nt_errstr(expected), nt_errstr(dos_expected));
return false; return false;
} else { } else {
printf("%-40s correct (%s)\n", path, nt_errstr(status)); printf("%-30s chkpath correct (%s)\n", path, nt_errstr(status));
} }
if (NT_STATUS_EQUAL(expected, NT_STATUS_NOT_A_DIRECTORY)) {
expected = NT_STATUS_OK;
}
ZERO_STRUCT(finfo);
finfo.generic.level = RAW_FILEINFO_NAME_INFO;
finfo.generic.in.file.path = path;
status = smb_raw_pathinfo(cli->tree, cli, &finfo);
if (!NT_STATUS_EQUAL(status, expected) && !NT_STATUS_EQUAL(status, dos_expected)) {
printf("FAILED: %-30s pathinfo %s should be %s or %s\n",
path, nt_errstr(status), nt_errstr(expected), nt_errstr(dos_expected));
return false;
}
if (!NT_STATUS_IS_OK(status)) {
printf("%-30s chkpath correct (%s)\n", path, nt_errstr(status));
return true;
}
if (path_expected &&
(!finfo.name_info.out.fname.s ||
strcmp(finfo.name_info.out.fname.s, path_expected) != 0)) {
if (tctx && torture_setting_bool(tctx, "samba4", false)) {
printf("IGNORE: %-30s => %-20s should be %s\n",
path, finfo.name_info.out.fname.s, path_expected);
return true;
}
printf("FAILED: %-30s => %-20s should be %s\n",
path, finfo.name_info.out.fname.s, path_expected);
return false;
}
printf("%-30s => %-20s correct\n",
path, finfo.name_info.out.fname.s);
return true; return true;
} }
static bool test_chkpath(struct smbcli_state *cli, TALLOC_CTX *mem_ctx) static bool test_path(struct smbcli_state *cli, const char *path,
NTSTATUS expected, NTSTATUS dos_expected)
{
return test_path_ex(cli, NULL, path, path, expected, dos_expected);
}
static bool test_chkpath(struct smbcli_state *cli, struct torture_context *tctx)
{ {
union smb_chkpath io; union smb_chkpath io;
NTSTATUS status; NTSTATUS status;
@ -86,7 +130,7 @@ static bool test_chkpath(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
ret &= test_path(cli, BASEDIR "\\nodir", NT_STATUS_OBJECT_NAME_NOT_FOUND, NT_STATUS_DOS(ERRDOS,ERRbadpath)); ret &= test_path(cli, BASEDIR "\\nodir", NT_STATUS_OBJECT_NAME_NOT_FOUND, NT_STATUS_DOS(ERRDOS,ERRbadpath));
fnum = create_complex_file(cli, mem_ctx, BASEDIR "\\test.txt.."); fnum = create_complex_file(cli, tctx, BASEDIR "\\test.txt..");
if (fnum == -1) { if (fnum == -1) {
printf("failed to open test.txt - %s\n", smbcli_errstr(cli->tree)); printf("failed to open test.txt - %s\n", smbcli_errstr(cli->tree));
ret = false; ret = false;
@ -101,9 +145,20 @@ static bool test_chkpath(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
goto done; goto done;
} }
ret &= test_path(cli, BASEDIR, NT_STATUS_OK, NT_STATUS_OK); ret &= test_path_ex(cli, tctx, BASEDIR, BASEDIR, NT_STATUS_OK, NT_STATUS_OK);
ret &= test_path(cli, BASEDIR "\\foo\\..\\test.txt..", NT_STATUS_NOT_A_DIRECTORY, NT_STATUS_DOS(ERRDOS,ERRbadpath)); ret &= test_path_ex(cli, tctx, ((char *)BASEDIR) + 1, BASEDIR, NT_STATUS_OK, NT_STATUS_OK);
ret &= test_path(cli, "", NT_STATUS_OK, NT_STATUS_OK); ret &= test_path_ex(cli, tctx, ((char *)BASEDIR"\\\\") + 1, BASEDIR, NT_STATUS_OK, NT_STATUS_OK);
ret &= test_path_ex(cli, tctx, ((char *)BASEDIR"\\foo\\..") + 1, BASEDIR, NT_STATUS_OK, NT_STATUS_OK);
ret &= test_path_ex(cli, tctx, ((char *)BASEDIR"\\f\\o\\o\\..\\..\\..") + 1, BASEDIR, NT_STATUS_OK, NT_STATUS_OK);
ret &= test_path_ex(cli, tctx, ((char *)BASEDIR"\\foo\\\\\..\\\\") + 1, BASEDIR, NT_STATUS_OK, NT_STATUS_OK);
ret &= test_path_ex(cli, tctx, BASEDIR"\\", BASEDIR, NT_STATUS_OK, NT_STATUS_OK);
ret &= test_path_ex(cli, tctx, BASEDIR"\\\\..\\"BASEDIR, BASEDIR, NT_STATUS_OK, NT_STATUS_OK);
ret &= test_path_ex(cli, tctx, BASEDIR"\\\\\\", BASEDIR, NT_STATUS_OK, NT_STATUS_OK);
ret &= test_path_ex(cli, tctx, "\\\\\\\\"BASEDIR"\\\\\\\\", BASEDIR, NT_STATUS_OK, NT_STATUS_OK);
ret &= test_path_ex(cli, tctx, "\\\\\\\\"BASEDIR, BASEDIR, NT_STATUS_OK, NT_STATUS_OK);
ret &= test_path_ex(cli, tctx, BASEDIR "\\foo\\..\\test.txt..", BASEDIR "\\test.txt..",
NT_STATUS_NOT_A_DIRECTORY, NT_STATUS_DOS(ERRDOS,ERRbadpath));
ret &= test_path_ex(cli, tctx, "", "\\", NT_STATUS_OK, NT_STATUS_OK);
ret &= test_path(cli, ".", NT_STATUS_OBJECT_NAME_INVALID, NT_STATUS_DOS(ERRDOS,ERRbadpath)); ret &= test_path(cli, ".", NT_STATUS_OBJECT_NAME_INVALID, NT_STATUS_DOS(ERRDOS,ERRbadpath));
ret &= test_path(cli, ".\\", NT_STATUS_OBJECT_NAME_INVALID, NT_STATUS_DOS(ERRDOS,ERRbadpath)); ret &= test_path(cli, ".\\", NT_STATUS_OBJECT_NAME_INVALID, NT_STATUS_DOS(ERRDOS,ERRbadpath));
ret &= test_path(cli, "\\\\\\.\\", NT_STATUS_OBJECT_NAME_INVALID, NT_STATUS_DOS(ERRDOS,ERRbadpath)); ret &= test_path(cli, "\\\\\\.\\", NT_STATUS_OBJECT_NAME_INVALID, NT_STATUS_DOS(ERRDOS,ERRbadpath));
@ -122,7 +177,7 @@ static bool test_chkpath(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
give different NT status returns for chkpth and findfirst. */ give different NT status returns for chkpth and findfirst. */
printf("testing findfirst on %s\n", "\\.\\\\\\\\\\\\."); printf("testing findfirst on %s\n", "\\.\\\\\\\\\\\\.");
status = single_search(cli, mem_ctx, "\\.\\\\\\\\\\\\."); status = single_search(cli, tctx, "\\.\\\\\\\\\\\\.");
CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_INVALID,NT_STATUS_DOS(ERRDOS,ERRinvalidname)); CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_INVALID,NT_STATUS_DOS(ERRDOS,ERRinvalidname));
ret &= test_path(cli, "\\.\\\\\\\\\\\\.", NT_STATUS_OBJECT_PATH_NOT_FOUND,NT_STATUS_DOS(ERRDOS,ERRbadpath)); ret &= test_path(cli, "\\.\\\\\\\\\\\\.", NT_STATUS_OBJECT_PATH_NOT_FOUND,NT_STATUS_DOS(ERRDOS,ERRbadpath));
@ -164,7 +219,7 @@ static bool test_chkpath(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
ret &= test_path(cli, "\\..\\", NT_STATUS_OBJECT_PATH_SYNTAX_BAD,NT_STATUS_DOS(ERRDOS,ERRinvalidpath)); ret &= test_path(cli, "\\..\\", NT_STATUS_OBJECT_PATH_SYNTAX_BAD,NT_STATUS_DOS(ERRDOS,ERRinvalidpath));
ret &= test_path(cli, "\\..", NT_STATUS_OBJECT_PATH_SYNTAX_BAD,NT_STATUS_DOS(ERRDOS,ERRinvalidpath)); ret &= test_path(cli, "\\..", NT_STATUS_OBJECT_PATH_SYNTAX_BAD,NT_STATUS_DOS(ERRDOS,ERRinvalidpath));
ret &= test_path(cli, BASEDIR "\\.", NT_STATUS_OBJECT_NAME_INVALID,NT_STATUS_DOS(ERRDOS,ERRbadpath)); ret &= test_path(cli, BASEDIR "\\.", NT_STATUS_OBJECT_NAME_INVALID,NT_STATUS_DOS(ERRDOS,ERRbadpath));
ret &= test_path(cli, BASEDIR "\\..", NT_STATUS_OK,NT_STATUS_OK); ret &= test_path_ex(cli, tctx, BASEDIR "\\..", "\\", NT_STATUS_OK,NT_STATUS_OK);
ret &= test_path(cli, BASEDIR "\\nt\\V S\\VB98\\vb600", NT_STATUS_OBJECT_NAME_NOT_FOUND,NT_STATUS_DOS(ERRDOS,ERRbadpath)); ret &= test_path(cli, BASEDIR "\\nt\\V S\\VB98\\vb600", NT_STATUS_OBJECT_NAME_NOT_FOUND,NT_STATUS_DOS(ERRDOS,ERRbadpath));
ret &= test_path(cli, BASEDIR "\\nt\\V S\\VB98\\vb6.exe", NT_STATUS_NOT_A_DIRECTORY,NT_STATUS_DOS(ERRDOS,ERRbadpath)); ret &= test_path(cli, BASEDIR "\\nt\\V S\\VB98\\vb6.exe", NT_STATUS_NOT_A_DIRECTORY,NT_STATUS_DOS(ERRDOS,ERRbadpath));
@ -183,7 +238,7 @@ static bool test_chkpath(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
CHECK_STATUS(status, NT_STATUS_OBJECT_PATH_NOT_FOUND,NT_STATUS_DOS(ERRDOS,ERRbadpath)); CHECK_STATUS(status, NT_STATUS_OBJECT_PATH_NOT_FOUND,NT_STATUS_DOS(ERRDOS,ERRbadpath));
printf("testing findfirst on %s\n", BASEDIR".\\.\\.\\.\\foo\\..\\.\\"); printf("testing findfirst on %s\n", BASEDIR".\\.\\.\\.\\foo\\..\\.\\");
status = single_search(cli, mem_ctx, BASEDIR".\\.\\.\\.\\foo\\..\\.\\"); status = single_search(cli, tctx, BASEDIR".\\.\\.\\.\\foo\\..\\.\\");
CHECK_STATUS(status, NT_STATUS_OBJECT_PATH_NOT_FOUND,NT_STATUS_DOS(ERRDOS,ERRbadpath)); CHECK_STATUS(status, NT_STATUS_OBJECT_PATH_NOT_FOUND,NT_STATUS_DOS(ERRDOS,ERRbadpath));
/* We expect this open to fail with the same error code as the chkpath below. */ /* We expect this open to fail with the same error code as the chkpath below. */

View File

@ -453,6 +453,10 @@ bool torture_raw_sfileinfo_rename(struct torture_context *torture,
char *fnum_fname_new; char *fnum_fname_new;
char *path_fname; char *path_fname;
char *path_fname_new; char *path_fname_new;
char *path_dname;
char *path_dname_new;
char *saved_name;
char *saved_name_new;
union smb_fileinfo finfo1, finfo2; union smb_fileinfo finfo1, finfo2;
union smb_setfileinfo sfinfo; union smb_setfileinfo sfinfo;
NTSTATUS status, status2; NTSTATUS status, status2;
@ -464,6 +468,8 @@ bool torture_raw_sfileinfo_rename(struct torture_context *torture,
asprintf(&path_fname_new, BASEDIR "\\fname_test_new_%d.txt", n); asprintf(&path_fname_new, BASEDIR "\\fname_test_new_%d.txt", n);
asprintf(&fnum_fname, BASEDIR "\\fnum_test_%d.txt", n); asprintf(&fnum_fname, BASEDIR "\\fnum_test_%d.txt", n);
asprintf(&fnum_fname_new, BASEDIR "\\fnum_test_new_%d.txt", n); asprintf(&fnum_fname_new, BASEDIR "\\fnum_test_new_%d.txt", n);
asprintf(&path_dname, BASEDIR "\\dname_test_%d", n);
asprintf(&path_dname_new, BASEDIR "\\dname_test_new_%d", n);
if (!torture_setup_dir(cli, BASEDIR)) { if (!torture_setup_dir(cli, BASEDIR)) {
return false; return false;
@ -553,17 +559,112 @@ bool torture_raw_sfileinfo_rename(struct torture_context *torture,
sfinfo.rename_information.in.root_fid = d_fnum; sfinfo.rename_information.in.root_fid = d_fnum;
CHECK_CALL_FNUM(RENAME_INFORMATION, NT_STATUS_INVALID_PARAMETER); CHECK_CALL_FNUM(RENAME_INFORMATION, NT_STATUS_INVALID_PARAMETER);
CHECK_STR(NAME_INFO, name_info, fname.s, fnum_fname); CHECK_STR(NAME_INFO, name_info, fname.s, fnum_fname);
smbcli_close(cli->tree, d_fnum);
printf("Trying rename directory\n");
if (!torture_setup_dir(cli, path_dname)) {
ret = false;
goto done;
}
saved_name = path_fname;
saved_name_new = path_fname_new;
path_fname = path_dname;
path_fname_new = path_dname_new;
sfinfo.rename_information.in.new_name = path_dname_new+strlen(BASEDIR)+1;
sfinfo.rename_information.in.overwrite = 0;
sfinfo.rename_information.in.root_fid = 0;
CHECK_CALL_PATH(RENAME_INFORMATION, NT_STATUS_OK);
CHECK_STR(NAME_INFO, name_info, fname.s, path_dname_new);
path_fname = saved_name;
path_fname_new = saved_name_new;
if (torture_setting_bool(torture, "samba3", false)) {
printf("SKIP: Trying rename directory with a handle\n");
printf("SKIP: Trying rename by path while a handle is open\n");
printf("SKIP: Trying rename directory by path while a handle is open\n");
goto done;
}
printf("Trying rename directory with a handle\n");
status = create_directory_handle(cli->tree, path_dname_new, &d_fnum);
fnum_saved = fnum;
fnum = d_fnum;
saved_name = fnum_fname;
saved_name_new = fnum_fname_new;
fnum_fname = path_dname;
fnum_fname_new = path_dname_new;
sfinfo.rename_information.in.new_name = path_dname+strlen(BASEDIR)+1;
sfinfo.rename_information.in.overwrite = 0;
sfinfo.rename_information.in.root_fid = 0;
CHECK_CALL_FNUM(RENAME_INFORMATION, NT_STATUS_OK);
CHECK_STR(NAME_INFO, name_info, fname.s, path_dname);
smbcli_close(cli->tree, d_fnum);
fnum = fnum_saved;
fnum_fname = saved_name;
fnum_fname_new = saved_name_new;
printf("Trying rename by path while a handle is open\n");
fnum_saved = fnum;
fnum = create_complex_file(cli, torture, path_fname);
sfinfo.rename_information.in.new_name = path_fname_new+strlen(BASEDIR)+1;
sfinfo.rename_information.in.overwrite = 0;
sfinfo.rename_information.in.root_fid = 0;
CHECK_CALL_PATH(RENAME_INFORMATION, NT_STATUS_OK);
CHECK_STR(NAME_INFO, name_info, fname.s, path_fname_new);
/* check that the handle returns the same name */
check_fnum = true;
CHECK_STR(NAME_INFO, name_info, fname.s, path_fname_new);
/* rename it back on the handle */
sfinfo.rename_information.in.new_name = path_fname+strlen(BASEDIR)+1;
CHECK_CALL_FNUM(RENAME_INFORMATION, NT_STATUS_OK);
CHECK_STR(NAME_INFO, name_info, fname.s, path_fname);
check_fnum = false;
CHECK_STR(NAME_INFO, name_info, fname.s, path_fname);
smbcli_close(cli->tree, fnum);
fnum = fnum_saved;
printf("Trying rename directory by path while a handle is open\n");
status = create_directory_handle(cli->tree, path_dname, &d_fnum);
fnum_saved = fnum;
fnum = d_fnum;
saved_name = path_fname;
saved_name_new = path_fname_new;
path_fname = path_dname;
path_fname_new = path_dname_new;
sfinfo.rename_information.in.new_name = path_dname_new+strlen(BASEDIR)+1;
sfinfo.rename_information.in.overwrite = 0;
sfinfo.rename_information.in.root_fid = 0;
CHECK_CALL_PATH(RENAME_INFORMATION, NT_STATUS_OK);
CHECK_STR(NAME_INFO, name_info, fname.s, path_dname_new);
path_fname = saved_name;
path_fname_new = saved_name_new;
saved_name = fnum_fname;
saved_name_new = fnum_fname_new;
fnum_fname = path_dname;
fnum_fname_new = path_dname_new;
/* check that the handle returns the same name */
check_fnum = true;
CHECK_STR(NAME_INFO, name_info, fname.s, path_dname_new);
/* rename it back on the handle */
sfinfo.rename_information.in.new_name = path_dname+strlen(BASEDIR)+1;
CHECK_CALL_FNUM(RENAME_INFORMATION, NT_STATUS_OK);
CHECK_STR(NAME_INFO, name_info, fname.s, path_dname);
fnum_fname = saved_name;
fnum_fname_new = saved_name_new;
saved_name = path_fname;
saved_name_new = path_fname_new;
path_fname = path_dname;
path_fname_new = path_dname_new;
check_fnum = false;
CHECK_STR(NAME_INFO, name_info, fname.s, path_dname);
smbcli_close(cli->tree, d_fnum);
fnum = fnum_saved;
path_fname = saved_name;
path_fname_new = saved_name_new;
done: done:
smb_raw_exit(cli->session); smb_raw_exit(cli->session);
smbcli_close(cli->tree, fnum); smbcli_deltree(cli->tree, BASEDIR);
if (NT_STATUS_IS_ERR(smbcli_unlink(cli->tree, fnum_fname))) {
printf("Failed to delete %s - %s\n", fnum_fname, smbcli_errstr(cli->tree));
}
if (NT_STATUS_IS_ERR(smbcli_unlink(cli->tree, path_fname))) {
printf("Failed to delete %s - %s\n", path_fname, smbcli_errstr(cli->tree));
}
return ret; return ret;
} }