From 187412f3da4fbc6feeca15bd0c2527534255964e Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Mon, 15 Nov 2004 06:57:26 +0000 Subject: r3747: - added some of the infrastructure needed for streams support in pvfs (the IDL, and the load/save meta-data logic) - changed pvfs_resolve_name() to default to non-wildcard, needing PVFS_RESOLVE_WILDCARD to enable wildcards. Most callers don't want wildcards, so defaulting this way makes more sense. - fixed deletion of EAs (This used to be commit e7afd4403cc1b7e0928776929f8988aa6f15640b) --- source4/include/structs.h | 1 + source4/librpc/idl/xattr.idl | 19 +++++++++++++++++ source4/ntvfs/posix/config.mk | 1 + source4/ntvfs/posix/pvfs_mkdir.c | 6 ++---- source4/ntvfs/posix/pvfs_open.c | 17 ++++++++-------- source4/ntvfs/posix/pvfs_qfileinfo.c | 3 +-- source4/ntvfs/posix/pvfs_rename.c | 10 ++++----- source4/ntvfs/posix/pvfs_resolve.c | 4 ++-- source4/ntvfs/posix/pvfs_search.c | 4 ++-- source4/ntvfs/posix/pvfs_setfileinfo.c | 16 ++++++++++++--- source4/ntvfs/posix/pvfs_streams.c | 27 +++++++++++++++++++++++++ source4/ntvfs/posix/pvfs_unlink.c | 3 ++- source4/ntvfs/posix/pvfs_xattr.c | 37 ++++++++++++++++++++++++++++++++++ source4/ntvfs/posix/vfs_posix.c | 3 +-- source4/ntvfs/posix/vfs_posix.h | 2 +- 15 files changed, 122 insertions(+), 31 deletions(-) create mode 100644 source4/ntvfs/posix/pvfs_streams.c (limited to 'source4') diff --git a/source4/include/structs.h b/source4/include/structs.h index 424b7a0e7a..229c489072 100644 --- a/source4/include/structs.h +++ b/source4/include/structs.h @@ -110,6 +110,7 @@ struct net_context; struct file_info; struct xattr_DosEAs; +struct xattr_DosStreams; struct test_join; diff --git a/source4/librpc/idl/xattr.idl b/source4/librpc/idl/xattr.idl index 0fc965c825..be587ffb88 100644 --- a/source4/librpc/idl/xattr.idl +++ b/source4/librpc/idl/xattr.idl @@ -47,4 +47,23 @@ interface xattr uint16 num_eas; [size_is(num_eas)] xattr_EA *eas; } xattr_DosEAs; + + /* we store stream information in this xattr structure. Then + the streams themselves are stored in + user.DosStream.STREAMNAME or in external files, according + to the flags */ + const string XATTR_DOSSTREAMS_NAME = "user.DosStreams"; + + const int XATTR_STREAM_FLAG_INTERNAL = 0x00000001; + + typedef struct { + utf8string name; + uint64 size; + uint32 flags; + } xattr_DosStream; + + typedef [public] struct { + uint32 num_streams; + [size_is(num_streams)] xattr_DosStream *streams; + } xattr_DosStreams; } diff --git a/source4/ntvfs/posix/config.mk b/source4/ntvfs/posix/config.mk index 74e991d9bd..1d33d8b381 100644 --- a/source4/ntvfs/posix/config.mk +++ b/source4/ntvfs/posix/config.mk @@ -27,6 +27,7 @@ ADD_OBJ_FILES = \ ntvfs/posix/pvfs_seek.o \ ntvfs/posix/pvfs_ioctl.o \ ntvfs/posix/pvfs_xattr.o \ + ntvfs/posix/pvfs_streams.o \ ntvfs/common/opendb.o \ ntvfs/common/brlock.o # End MODULE ntvfs_posix diff --git a/source4/ntvfs/posix/pvfs_mkdir.c b/source4/ntvfs/posix/pvfs_mkdir.c index 3b5204c934..1bc0fa569e 100644 --- a/source4/ntvfs/posix/pvfs_mkdir.c +++ b/source4/ntvfs/posix/pvfs_mkdir.c @@ -39,8 +39,7 @@ NTSTATUS pvfs_mkdir(struct ntvfs_module_context *ntvfs, } /* resolve the cifs name to a posix name */ - status = pvfs_resolve_name(pvfs, req, md->mkdir.in.path, - PVFS_RESOLVE_NO_WILDCARD, &name); + status = pvfs_resolve_name(pvfs, req, md->mkdir.in.path, 0, &name); if (!NT_STATUS_IS_OK(status)) { return status; } @@ -69,8 +68,7 @@ NTSTATUS pvfs_rmdir(struct ntvfs_module_context *ntvfs, struct pvfs_filename *name; /* resolve the cifs name to a posix name */ - status = pvfs_resolve_name(pvfs, req, rd->in.path, - PVFS_RESOLVE_NO_WILDCARD, &name); + status = pvfs_resolve_name(pvfs, req, rd->in.path, 0, &name); if (!NT_STATUS_IS_OK(status)) { return status; } diff --git a/source4/ntvfs/posix/pvfs_open.c b/source4/ntvfs/posix/pvfs_open.c index 9bb3487679..4f089a8c07 100644 --- a/source4/ntvfs/posix/pvfs_open.c +++ b/source4/ntvfs/posix/pvfs_open.c @@ -103,6 +103,10 @@ static NTSTATUS pvfs_open_directory(struct pvfs_state *pvfs, NTSTATUS status; uint32_t create_action; + if (name->stream_name) { + return NT_STATUS_OBJECT_NAME_INVALID; + } + /* if the client says it must be a directory, and it isn't, then fail */ if (name->exists && !(name->dos.attrib & FILE_ATTRIBUTE_DIRECTORY)) { @@ -180,8 +184,7 @@ static NTSTATUS pvfs_open_directory(struct pvfs_state *pvfs, if (mkdir(name->full_name, mode) == -1) { return pvfs_map_errno(pvfs,errno); } - status = pvfs_resolve_name(pvfs, req, io->ntcreatex.in.fname, - PVFS_RESOLVE_NO_WILDCARD, &name); + status = pvfs_resolve_name(pvfs, req, io->ntcreatex.in.fname, 0, &name); if (!NT_STATUS_IS_OK(status)) { return status; } @@ -684,8 +687,7 @@ static NTSTATUS pvfs_open_t2open(struct ntvfs_module_context *ntvfs, struct pvfs_filename *name; NTSTATUS status; - status = pvfs_resolve_name(pvfs, req, io->t2open.in.fname, - PVFS_RESOLVE_NO_WILDCARD, &name); + status = pvfs_resolve_name(pvfs, req, io->t2open.in.fname, 0, &name); if (!NT_STATUS_IS_OK(status)) { return status; } @@ -735,8 +737,8 @@ NTSTATUS pvfs_open(struct ntvfs_module_context *ntvfs, } /* resolve the cifs name to a posix name */ - status = pvfs_resolve_name(pvfs, req, io->ntcreatex.in.fname, - PVFS_RESOLVE_NO_WILDCARD, &name); + status = pvfs_resolve_name(pvfs, req, io->ntcreatex.in.fname, + PVFS_RESOLVE_STREAMS, &name); if (!NT_STATUS_IS_OK(status)) { return status; } @@ -826,8 +828,7 @@ NTSTATUS pvfs_open(struct ntvfs_module_context *ntvfs, } /* try re-resolving the name */ - status = pvfs_resolve_name(pvfs, req, io->ntcreatex.in.fname, - PVFS_RESOLVE_NO_WILDCARD, &name); + status = pvfs_resolve_name(pvfs, req, io->ntcreatex.in.fname, 0, &name); if (!NT_STATUS_IS_OK(status)) { return status; } diff --git a/source4/ntvfs/posix/pvfs_qfileinfo.c b/source4/ntvfs/posix/pvfs_qfileinfo.c index c8134939a3..3eaa7865e8 100644 --- a/source4/ntvfs/posix/pvfs_qfileinfo.c +++ b/source4/ntvfs/posix/pvfs_qfileinfo.c @@ -219,8 +219,7 @@ NTSTATUS pvfs_qpathinfo(struct ntvfs_module_context *ntvfs, NTSTATUS status; /* resolve the cifs name to a posix name */ - status = pvfs_resolve_name(pvfs, req, info->generic.in.fname, - PVFS_RESOLVE_NO_WILDCARD, &name); + status = pvfs_resolve_name(pvfs, req, info->generic.in.fname, 0, &name); if (!NT_STATUS_IS_OK(status)) { return status; } diff --git a/source4/ntvfs/posix/pvfs_rename.c b/source4/ntvfs/posix/pvfs_rename.c index aae17f327c..efaf63ba9d 100644 --- a/source4/ntvfs/posix/pvfs_rename.c +++ b/source4/ntvfs/posix/pvfs_rename.c @@ -250,12 +250,14 @@ static NTSTATUS pvfs_rename_mv(struct ntvfs_module_context *ntvfs, struct pvfs_filename *name1, *name2; /* resolve the cifs name to a posix name */ - status = pvfs_resolve_name(pvfs, req, ren->rename.in.pattern1, 0, &name1); + status = pvfs_resolve_name(pvfs, req, ren->rename.in.pattern1, + PVFS_RESOLVE_WILDCARD, &name1); if (!NT_STATUS_IS_OK(status)) { return status; } - status = pvfs_resolve_name(pvfs, req, ren->rename.in.pattern2, 0, &name2); + status = pvfs_resolve_name(pvfs, req, ren->rename.in.pattern2, + PVFS_RESOLVE_WILDCARD, &name2); if (!NT_STATUS_IS_OK(status)) { return status; } @@ -325,10 +327,6 @@ static NTSTATUS pvfs_rename_nt(struct ntvfs_module_context *ntvfs, return status; } - if (name1->has_wildcard || name2->has_wildcard) { - return NT_STATUS_OBJECT_PATH_SYNTAX_BAD; - } - if (!name1->exists) { return NT_STATUS_OBJECT_NAME_NOT_FOUND; } diff --git a/source4/ntvfs/posix/pvfs_resolve.c b/source4/ntvfs/posix/pvfs_resolve.c index 354cdd4bb4..576b0d9db4 100644 --- a/source4/ntvfs/posix/pvfs_resolve.c +++ b/source4/ntvfs/posix/pvfs_resolve.c @@ -253,7 +253,7 @@ static NTSTATUS pvfs_unix_path(struct pvfs_state *pvfs, const char *cifs_name, case '<': case '?': case '"': - if (flags & PVFS_RESOLVE_NO_WILDCARD) { + if (!(flags & PVFS_RESOLVE_WILDCARD)) { return NT_STATUS_OBJECT_NAME_INVALID; } name->has_wildcard = True; @@ -341,7 +341,7 @@ static NTSTATUS pvfs_reduce_name(TALLOC_CTX *mem_ctx, const char **fname, uint_t } } if (err_count) { - if (!(flags & PVFS_RESOLVE_NO_WILDCARD)) err_count--; + if (flags & PVFS_RESOLVE_WILDCARD) err_count--; if (err_count==1) { return NT_STATUS_OBJECT_NAME_INVALID; diff --git a/source4/ntvfs/posix/pvfs_search.c b/source4/ntvfs/posix/pvfs_search.c index 831b799716..f805f201f6 100644 --- a/source4/ntvfs/posix/pvfs_search.c +++ b/source4/ntvfs/posix/pvfs_search.c @@ -300,7 +300,7 @@ static NTSTATUS pvfs_search_first_old(struct ntvfs_module_context *ntvfs, pattern = io->search_first.in.pattern; /* resolve the cifs name to a posix name */ - status = pvfs_resolve_name(pvfs, req, pattern, 0, &name); + status = pvfs_resolve_name(pvfs, req, pattern, PVFS_RESOLVE_WILDCARD, &name); if (!NT_STATUS_IS_OK(status)) { return status; } @@ -436,7 +436,7 @@ NTSTATUS pvfs_search_first(struct ntvfs_module_context *ntvfs, max_count = io->t2ffirst.in.max_count; /* resolve the cifs name to a posix name */ - status = pvfs_resolve_name(pvfs, req, pattern, 0, &name); + status = pvfs_resolve_name(pvfs, req, pattern, PVFS_RESOLVE_WILDCARD, &name); if (!NT_STATUS_IS_OK(status)) { return status; } diff --git a/source4/ntvfs/posix/pvfs_setfileinfo.c b/source4/ntvfs/posix/pvfs_setfileinfo.c index b9ed592bf4..7ba64979c3 100644 --- a/source4/ntvfs/posix/pvfs_setfileinfo.c +++ b/source4/ntvfs/posix/pvfs_setfileinfo.c @@ -70,7 +70,7 @@ static NTSTATUS pvfs_setfileinfo_rename(struct pvfs_state *pvfs, } /* resolve the new name */ - status = pvfs_resolve_name(pvfs, name, new_name, PVFS_RESOLVE_NO_WILDCARD, &name2); + status = pvfs_resolve_name(pvfs, name, new_name, 0, &name2); if (!NT_STATUS_IS_OK(status)) { return status; } @@ -144,6 +144,17 @@ static NTSTATUS pvfs_setfileinfo_ea_set(struct pvfs_state *pvfs, ealist->num_eas++; save: + /* pull out any null EAs */ + for (i=0;inum_eas;i++) { + if (ealist->eas[i].value.length == 0) { + memmove(&ealist->eas[i], + &ealist->eas[i+1], + (ealist->num_eas-(i+1)) * sizeof(ealist->eas[i])); + ealist->num_eas--; + i--; + } + } + status = pvfs_doseas_save(pvfs, name, fd, ealist); if (!NT_STATUS_IS_OK(status)) { return status; @@ -348,8 +359,7 @@ NTSTATUS pvfs_setpathinfo(struct ntvfs_module_context *ntvfs, struct utimbuf unix_times; /* resolve the cifs name to a posix name */ - status = pvfs_resolve_name(pvfs, req, info->generic.file.fname, - PVFS_RESOLVE_NO_WILDCARD, &name); + status = pvfs_resolve_name(pvfs, req, info->generic.file.fname, 0, &name); if (!NT_STATUS_IS_OK(status)) { return status; } diff --git a/source4/ntvfs/posix/pvfs_streams.c b/source4/ntvfs/posix/pvfs_streams.c new file mode 100644 index 0000000000..b71ff640e5 --- /dev/null +++ b/source4/ntvfs/posix/pvfs_streams.c @@ -0,0 +1,27 @@ +/* + Unix SMB/CIFS implementation. + + POSIX NTVFS backend - alternate data streams + + Copyright (C) Andrew Tridgell 2004 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include "includes.h" +#include "system/filesys.h" +#include "vfs_posix.h" +#include "librpc/gen_ndr/ndr_xattr.h" + diff --git a/source4/ntvfs/posix/pvfs_unlink.c b/source4/ntvfs/posix/pvfs_unlink.c index ab8f1abf62..8dc9f60ad8 100644 --- a/source4/ntvfs/posix/pvfs_unlink.c +++ b/source4/ntvfs/posix/pvfs_unlink.c @@ -85,7 +85,8 @@ NTSTATUS pvfs_unlink(struct ntvfs_module_context *ntvfs, uint_t ofs; /* resolve the cifs name to a posix name */ - status = pvfs_resolve_name(pvfs, req, unl->in.pattern, 0, &name); + status = pvfs_resolve_name(pvfs, req, unl->in.pattern, + PVFS_RESOLVE_WILDCARD, &name); if (!NT_STATUS_IS_OK(status)) { return status; } diff --git a/source4/ntvfs/posix/pvfs_xattr.c b/source4/ntvfs/posix/pvfs_xattr.c index d5a7d17a31..269a2cc863 100644 --- a/source4/ntvfs/posix/pvfs_xattr.c +++ b/source4/ntvfs/posix/pvfs_xattr.c @@ -276,3 +276,40 @@ NTSTATUS pvfs_doseas_save(struct pvfs_state *pvfs, struct pvfs_filename *name, i return pvfs_xattr_ndr_save(pvfs, name->full_name, fd, XATTR_DOSEAS_NAME, eas, (ndr_push_flags_fn_t)ndr_push_xattr_DosEAs); } + + +/* + load the set of streams from extended attributes +*/ +NTSTATUS pvfs_streams_load(struct pvfs_state *pvfs, struct pvfs_filename *name, int fd, + struct xattr_DosStreams *streams) +{ + NTSTATUS status; + ZERO_STRUCTP(streams); + if (!(pvfs->flags & PVFS_FLAG_XATTR_ENABLE)) { + return NT_STATUS_OK; + } + status = pvfs_xattr_ndr_load(pvfs, streams, name->full_name, fd, + XATTR_DOSSTREAMS_NAME, + streams, + (ndr_pull_flags_fn_t)ndr_pull_xattr_DosStreams); + if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_FOUND)) { + return NT_STATUS_OK; + } + return status; +} + +/* + save the set of streams into filesystem xattr +*/ +NTSTATUS pvfs_streams_save(struct pvfs_state *pvfs, struct pvfs_filename *name, int fd, + struct xattr_DosStreams *streams) +{ + if (!(pvfs->flags & PVFS_FLAG_XATTR_ENABLE)) { + return NT_STATUS_OK; + } + return pvfs_xattr_ndr_save(pvfs, name->full_name, fd, + XATTR_DOSSTREAMS_NAME, + streams, + (ndr_push_flags_fn_t)ndr_push_xattr_DosStreams); +} diff --git a/source4/ntvfs/posix/vfs_posix.c b/source4/ntvfs/posix/vfs_posix.c index e5712e3e7d..2b4eef04ba 100644 --- a/source4/ntvfs/posix/vfs_posix.c +++ b/source4/ntvfs/posix/vfs_posix.c @@ -161,8 +161,7 @@ static NTSTATUS pvfs_chkpath(struct ntvfs_module_context *ntvfs, NTSTATUS status; /* resolve the cifs name to a posix name */ - status = pvfs_resolve_name(pvfs, req, cp->in.path, - PVFS_RESOLVE_NO_WILDCARD, &name); + status = pvfs_resolve_name(pvfs, req, cp->in.path, 0, &name); if (!NT_STATUS_IS_OK(status)) { return status; } diff --git a/source4/ntvfs/posix/vfs_posix.h b/source4/ntvfs/posix/vfs_posix.h index 46cc38c1f8..645d293a6d 100644 --- a/source4/ntvfs/posix/vfs_posix.h +++ b/source4/ntvfs/posix/vfs_posix.h @@ -169,7 +169,7 @@ struct pvfs_mangle_context { /* flags to pvfs_resolve_name() */ -#define PVFS_RESOLVE_NO_WILDCARD (1<<0) +#define PVFS_RESOLVE_WILDCARD (1<<0) #define PVFS_RESOLVE_STREAMS (1<<1) /* flags in pvfs->flags */ -- cgit