1
0
mirror of https://github.com/samba-team/samba.git synced 2025-01-11 05:18:09 +03:00

r3717: - expanded the RAW-RENAME test a little

- added support for wildcard rename in pvfs

- made more consistent use of pvfs_map_errno()
(This used to be commit e255d1c3a8)
This commit is contained in:
Andrew Tridgell 2004-11-13 05:47:27 +00:00 committed by Gerald (Jerry) Carter
parent 1158268287
commit 1c59d825af
6 changed files with 291 additions and 22 deletions

View File

@ -937,7 +937,7 @@ NTSTATUS pvfs_open(struct ntvfs_module_context *ntvfs,
mode_t mode = pvfs_fileperms(pvfs, attrib);
if (fchmod(fd, mode) == -1) {
talloc_free(lck);
return map_nt_error_from_unix(errno);
return pvfs_map_errno(pvfs, errno);
}
name->dos.attrib = attrib;
status = pvfs_dosattrib_save(pvfs, name, fd);

View File

@ -23,6 +23,223 @@
#include "includes.h"
#include "vfs_posix.h"
/*
resolve a wildcard rename pattern. This works on one component of the name
*/
static const char *pvfs_resolve_wildcard_component(TALLOC_CTX *mem_ctx,
const char *fname,
const char *pattern)
{
const char *p1, *p2;
char *dest, *d;
/* the length is bounded by the length of the two strings combined */
dest = talloc(mem_ctx, strlen(fname) + strlen(pattern) + 1);
if (dest == NULL) {
return NULL;
}
p1 = fname;
p2 = pattern;
d = dest;
while (*p2) {
codepoint_t c1, c2;
size_t c_size1, c_size2;
c1 = next_codepoint(p1, &c_size1);
c2 = next_codepoint(p2, &c_size2);
if (c2 == '?') {
d += push_codepoint(d, c1);
} else if (c2 == '*') {
memcpy(d, p1, strlen(p1));
d += strlen(p1);
break;
} else {
d += push_codepoint(d, c2);
}
p1 += c_size1;
p2 += c_size2;
}
*d = 0;
return dest;
}
/*
resolve a wildcard rename pattern.
*/
static const char *pvfs_resolve_wildcard(TALLOC_CTX *mem_ctx,
const char *fname,
const char *pattern)
{
const char *base1, *base2;
const char *ext1, *ext2;
char *p;
/* break into base part plus extension */
p = strrchr_m(fname, '.');
if (p == NULL) {
ext1 = "";
base1 = fname;
} else {
ext1 = talloc_strdup(mem_ctx, p+1);
base1 = talloc_strndup(mem_ctx, fname, p-fname);
}
if (ext1 == NULL || base1 == NULL) {
return NULL;
}
p = strrchr_m(pattern, '.');
if (p == NULL) {
ext2 = "";
base2 = fname;
} else {
ext2 = talloc_strdup(mem_ctx, p+1);
base2 = talloc_strndup(mem_ctx, pattern, p-pattern);
}
if (ext2 == NULL || base2 == NULL) {
return NULL;
}
base1 = pvfs_resolve_wildcard_component(mem_ctx, base1, base2);
ext1 = pvfs_resolve_wildcard_component(mem_ctx, ext1, ext2);
if (base1 == NULL || ext1 == NULL) {
return NULL;
}
if (*ext1 == 0) {
return base1;
}
return talloc_asprintf(mem_ctx, "%s.%s", base1, ext1);
}
/*
rename one file from a wildcard set
*/
static NTSTATUS pvfs_rename_one(struct pvfs_state *pvfs,
struct smbsrv_request *req,
const char *dir_path,
const char *fname1,
const char *fname2,
uint16_t attrib)
{
struct pvfs_filename *name1, *name2;
TALLOC_CTX *mem_ctx = talloc(req, 0);
NTSTATUS status;
/* resolve the wildcard pattern for this name */
fname2 = pvfs_resolve_wildcard(mem_ctx, fname1, fname2);
if (fname2 == NULL) {
return NT_STATUS_NO_MEMORY;
}
/* get a pvfs_filename source object */
status = pvfs_resolve_partial(pvfs, mem_ctx,
dir_path, fname1, &name1);
if (!NT_STATUS_IS_OK(status)) {
talloc_free(mem_ctx);
return status;
}
/* make sure its matches the given attributes */
status = pvfs_match_attrib(pvfs, name1, attrib, 0);
if (!NT_STATUS_IS_OK(status)) {
talloc_free(mem_ctx);
return status;
}
status = pvfs_can_rename(pvfs, name1);
if (!NT_STATUS_IS_OK(status)) {
talloc_free(mem_ctx);
return status;
}
/* get a pvfs_filename dest object */
status = pvfs_resolve_partial(pvfs, mem_ctx,
dir_path, fname2, &name2);
if (NT_STATUS_IS_OK(status)) {
status = pvfs_can_delete(pvfs, name2);
if (!NT_STATUS_IS_OK(status)) {
talloc_free(mem_ctx);
return status;
}
}
fname2 = talloc_asprintf(mem_ctx, "%s/%s", dir_path, fname2);
if (fname2 == NULL) {
return NT_STATUS_NO_MEMORY;
}
/* finally try the actual rename */
if (rename(name1->full_name, fname2) == -1) {
talloc_free(mem_ctx);
return pvfs_map_errno(pvfs, errno);
}
talloc_free(mem_ctx);
return NT_STATUS_OK;
}
/*
rename a set of files with wildcards
*/
static NTSTATUS pvfs_rename_wildcard(struct pvfs_state *pvfs,
struct smbsrv_request *req,
union smb_rename *ren,
struct pvfs_filename *name1,
struct pvfs_filename *name2)
{
struct pvfs_dir *dir;
NTSTATUS status;
uint_t ofs = 0;
const char *fname, *fname2, *dir_path;
uint16_t attrib = ren->rename.in.attrib;
int total_renamed = 0;
/* get list of matching files */
status = pvfs_list_start(pvfs, name1, req, &dir);
if (!NT_STATUS_IS_OK(status)) {
return status;
}
status = NT_STATUS_NO_SUCH_FILE;
dir_path = pvfs_list_unix_path(dir);
/* only allow wildcard renames within a directory */
if (strncmp(dir_path, name2->full_name, strlen(dir_path)) != 0 ||
name2->full_name[strlen(dir_path)] != '/' ||
strchr(name2->full_name + strlen(dir_path) + 1, '/')) {
return NT_STATUS_INVALID_PARAMETER;
}
fname2 = talloc_strdup(name2, name2->full_name + strlen(dir_path) + 1);
if (fname2 == NULL) {
return NT_STATUS_NO_MEMORY;
}
while ((fname = pvfs_list_next(dir, &ofs))) {
status = pvfs_rename_one(pvfs, req,
dir_path,
fname, fname2, attrib);
if (NT_STATUS_IS_OK(status)) {
total_renamed++;
}
}
if (total_renamed == 0) {
return status;
}
return NT_STATUS_OK;
}
/*
rename a set of files
*/
@ -49,15 +266,17 @@ NTSTATUS pvfs_rename(struct ntvfs_module_context *ntvfs,
}
if (name1->has_wildcard || name2->has_wildcard) {
DEBUG(3,("Rejecting wildcard rename '%s' -> '%s'\n",
ren->rename.in.pattern1, ren->rename.in.pattern2));
return NT_STATUS_NOT_SUPPORTED;
return pvfs_rename_wildcard(pvfs, req, ren, name1, name2);
}
if (!name1->exists) {
return NT_STATUS_OBJECT_NAME_NOT_FOUND;
}
if (strcmp(name1->full_name, name2->full_name) == 0) {
return NT_STATUS_OK;
}
if (name2->exists) {
return NT_STATUS_OBJECT_NAME_COLLISION;
}

View File

@ -96,7 +96,7 @@ static NTSTATUS pvfs_setfileinfo_rename(struct pvfs_state *pvfs,
}
if (rename(name->full_name, name2->full_name) == -1) {
return map_nt_error_from_unix(errno);
return pvfs_map_errno(pvfs, errno);
}
name->full_name = talloc_steal(name, name2->full_name);

View File

@ -68,7 +68,7 @@ NTSTATUS pvfs_write(struct ntvfs_module_context *ntvfs,
if (errno == EFBIG) {
return NT_STATUS_INVALID_PARAMETER;
}
return map_nt_error_from_unix(errno);
return pvfs_map_errno(pvfs, errno);
}
f->handle->seek_offset = wr->writex.in.offset + ret;

View File

@ -28,7 +28,8 @@
/*
pull a xattr as a blob, from either a file or a file descriptor
*/
static NTSTATUS pull_xattr_blob(TALLOC_CTX *mem_ctx,
static NTSTATUS pull_xattr_blob(struct pvfs_state *pvfs,
TALLOC_CTX *mem_ctx,
const char *attr_name,
const char *fname,
int fd,
@ -61,7 +62,7 @@ again:
if (ret == -1) {
data_blob_free(blob);
return map_nt_error_from_unix(errno);
return pvfs_map_errno(pvfs, errno);
}
blob->length = ret;
@ -75,7 +76,8 @@ again:
/*
push a xattr as a blob, from either a file or a file descriptor
*/
static NTSTATUS push_xattr_blob(const char *attr_name,
static NTSTATUS push_xattr_blob(struct pvfs_state *pvfs,
const char *attr_name,
const char *fname,
int fd,
const DATA_BLOB *blob)
@ -89,7 +91,7 @@ static NTSTATUS push_xattr_blob(const char *attr_name,
ret = setxattr(fname, attr_name, blob->data, blob->length, 0);
}
if (ret == -1) {
return map_nt_error_from_unix(errno);
return pvfs_map_errno(pvfs, errno);
}
return NT_STATUS_OK;
@ -101,14 +103,15 @@ static NTSTATUS push_xattr_blob(const char *attr_name,
/*
load a NDR structure from a xattr
*/
static NTSTATUS pvfs_xattr_ndr_load(TALLOC_CTX *mem_ctx,
static NTSTATUS pvfs_xattr_ndr_load(struct pvfs_state *pvfs,
TALLOC_CTX *mem_ctx,
const char *fname, int fd, const char *attr_name,
void *p, ndr_pull_flags_fn_t pull_fn)
{
NTSTATUS status;
DATA_BLOB blob;
status = pull_xattr_blob(mem_ctx, attr_name, fname,
status = pull_xattr_blob(pvfs, mem_ctx, attr_name, fname,
fd, XATTR_DOSATTRIB_ESTIMATED_SIZE, &blob);
if (!NT_STATUS_IS_OK(status)) {
return status;
@ -125,7 +128,8 @@ static NTSTATUS pvfs_xattr_ndr_load(TALLOC_CTX *mem_ctx,
/*
save a NDR structure into a xattr
*/
static NTSTATUS pvfs_xattr_ndr_save(const char *fname, int fd, const char *attr_name,
static NTSTATUS pvfs_xattr_ndr_save(struct pvfs_state *pvfs,
const char *fname, int fd, const char *attr_name,
void *p, ndr_push_flags_fn_t push_fn)
{
TALLOC_CTX *mem_ctx = talloc(NULL, 0);
@ -138,7 +142,7 @@ static NTSTATUS pvfs_xattr_ndr_save(const char *fname, int fd, const char *attr_
return status;
}
status = push_xattr_blob(attr_name, fname, fd, &blob);
status = push_xattr_blob(pvfs, attr_name, fname, fd, &blob);
talloc_free(mem_ctx);
return status;
@ -159,8 +163,10 @@ NTSTATUS pvfs_dosattrib_load(struct pvfs_state *pvfs, struct pvfs_filename *name
return NT_STATUS_OK;
}
status = pvfs_xattr_ndr_load(mem_ctx, name->full_name, fd, XATTR_DOSATTRIB_NAME,
&attrib, (ndr_pull_flags_fn_t)ndr_pull_xattr_DosAttrib);
status = pvfs_xattr_ndr_load(pvfs, mem_ctx, name->full_name,
fd, XATTR_DOSATTRIB_NAME,
&attrib,
(ndr_pull_flags_fn_t)ndr_pull_xattr_DosAttrib);
/* if the filesystem doesn't support them, then tell pvfs not to try again */
if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_SUPPORTED)) {
@ -233,7 +239,8 @@ NTSTATUS pvfs_dosattrib_save(struct pvfs_state *pvfs, struct pvfs_filename *name
info1->create_time = name->dos.create_time;
info1->change_time = name->dos.change_time;
return pvfs_xattr_ndr_save(name->full_name, fd, XATTR_DOSATTRIB_NAME, &attrib,
return pvfs_xattr_ndr_save(pvfs, name->full_name, fd,
XATTR_DOSATTRIB_NAME, &attrib,
(ndr_push_flags_fn_t)ndr_push_xattr_DosAttrib);
}
@ -249,7 +256,7 @@ NTSTATUS pvfs_doseas_load(struct pvfs_state *pvfs, struct pvfs_filename *name, i
if (!(pvfs->flags & PVFS_FLAG_XATTR_ENABLE)) {
return NT_STATUS_OK;
}
status = pvfs_xattr_ndr_load(eas, name->full_name, fd, XATTR_DOSEAS_NAME,
status = pvfs_xattr_ndr_load(pvfs, eas, name->full_name, fd, XATTR_DOSEAS_NAME,
eas, (ndr_pull_flags_fn_t)ndr_pull_xattr_DosEAs);
if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_FOUND)) {
return NT_STATUS_OK;
@ -266,6 +273,6 @@ NTSTATUS pvfs_doseas_save(struct pvfs_state *pvfs, struct pvfs_filename *name, i
if (!(pvfs->flags & PVFS_FLAG_XATTR_ENABLE)) {
return NT_STATUS_OK;
}
return pvfs_xattr_ndr_save(name->full_name, fd, XATTR_DOSEAS_NAME, eas,
return pvfs_xattr_ndr_save(pvfs, name->full_name, fd, XATTR_DOSEAS_NAME, eas,
(ndr_push_flags_fn_t)ndr_push_xattr_DosEAs);
}

View File

@ -48,6 +48,7 @@ static BOOL test_mv(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
int fnum;
const char *fname1 = BASEDIR "\\test1.txt";
const char *fname2 = BASEDIR "\\test2.txt";
union smb_open op;
printf("Testing SMBmv\n");
@ -57,16 +58,58 @@ static BOOL test_mv(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
printf("Trying simple rename\n");
fnum = create_complex_file(cli, mem_ctx, fname1);
op.generic.level = RAW_OPEN_NTCREATEX;
op.ntcreatex.in.root_fid = 0;
op.ntcreatex.in.flags = 0;
op.ntcreatex.in.access_mask = SEC_RIGHT_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, mem_ctx, &op);
CHECK_STATUS(status, NT_STATUS_OK);
fnum = op.ntcreatex.out.fnum;
io.generic.level = RAW_RENAME_RENAME;
io.rename.in.pattern1 = fname1;
io.rename.in.pattern2 = fname2;
io.rename.in.attrib = 0;
printf("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 = GENERIC_RIGHTS_FILE_READ;
op.ntcreatex.in.share_access =
NTCREATEX_SHARE_ACCESS_DELETE |
NTCREATEX_SHARE_ACCESS_READ |
NTCREATEX_SHARE_ACCESS_WRITE;
status = smb_raw_open(cli->tree, mem_ctx, &op);
CHECK_STATUS(status, NT_STATUS_OK);
fnum = op.ntcreatex.out.fnum;
printf("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);
io.rename.in.pattern1 = fname1;
io.rename.in.pattern2 = fname2;
printf("trying rename while not open\n");
smb_raw_exit(cli->session);
status = smb_raw_rename(cli->tree, &io);
CHECK_STATUS(status, NT_STATUS_OK);