From 4e3656b8d1d0bf8c0c4ade01332e7384ea890810 Mon Sep 17 00:00:00 2001 From: Tim Prouty Date: Tue, 16 Jun 2009 12:01:13 -0700 Subject: s3: Change SMB_VFS_OPEN to take an smb_filename struct This was a little messy because of all of the vfs modules I had to touch. Most of them were pretty straight forward, but the streams modules required a little attention to handle smb_filename. Since the use of smb_filename enables the vfs modules to access the raw, over-the-wire stream, a little bit of the handling that was being done by split_ntfs_stream_name has now been shifted into the individual stream modules. It may be a little more code, but overall it gives more flexibility to the streams modules, while also allowing correct stream handling. --- examples/VFS/skel_opaque.c | 5 +- examples/VFS/skel_transparent.c | 5 +- source3/include/proto.h | 1 + source3/include/vfs.h | 7 +- source3/modules/vfs_acl_tdb.c | 20 ++++-- source3/modules/vfs_acl_xattr.c | 20 ++++-- source3/modules/vfs_audit.c | 10 +-- source3/modules/vfs_cap.c | 22 ++++-- source3/modules/vfs_catia.c | 18 ++++- source3/modules/vfs_commit.c | 6 +- source3/modules/vfs_default.c | 22 +++++- source3/modules/vfs_extd_audit.c | 12 ++-- source3/modules/vfs_full_audit.c | 9 +-- source3/modules/vfs_onefs.c | 5 +- source3/modules/vfs_onefs_shadow_copy.c | 11 +-- source3/modules/vfs_prealloc.c | 13 ++-- source3/modules/vfs_preopen.c | 17 ++--- source3/modules/vfs_shadow_copy2.c | 31 ++++++++- source3/modules/vfs_streams_depot.c | 111 +++++++++++++++++++++++------- source3/modules/vfs_streams_xattr.c | 117 ++++++++++++++++++++++---------- source3/modules/vfs_syncops.c | 25 ++++++- source3/smbd/filename.c | 5 +- source3/smbd/nttrans.c | 16 +++++ source3/smbd/open.c | 8 +-- source3/torture/cmd_vfs.c | 13 +++- 25 files changed, 398 insertions(+), 131 deletions(-) diff --git a/examples/VFS/skel_opaque.c b/examples/VFS/skel_opaque.c index 118a5b9da7..d1000f15b9 100644 --- a/examples/VFS/skel_opaque.c +++ b/examples/VFS/skel_opaque.c @@ -122,9 +122,10 @@ static int skel_closedir(vfs_handle_struct *handle, SMB_STRUCT_DIR *dir) return vfswrap_closedir(NULL, dir); } -static int skel_open(vfs_handle_struct *handle, const char *fname, files_struct *fsp, int flags, mode_t mode) +static int skel_open(vfs_handle_struct *handle, struct smb_fname *smb_fname, + files_struct *fsp, int flags, mode_t mode) { - return vfswrap_open(NULL, fname, flags, mode); + return vfswrap_open(NULL, smb_fname, flags, mode); } static int skel_close(vfs_handle_struct *handle, files_struct *fsp) diff --git a/examples/VFS/skel_transparent.c b/examples/VFS/skel_transparent.c index a95b5ae6cd..101951b0f9 100644 --- a/examples/VFS/skel_transparent.c +++ b/examples/VFS/skel_transparent.c @@ -116,9 +116,10 @@ static int skel_closedir(vfs_handle_struct *handle, SMB_STRUCT_DIR *dir) return SMB_VFS_NEXT_CLOSEDIR(handle, dir); } -static int skel_open(vfs_handle_struct *handle, const char *fname, files_struct *fsp, int flags, mode_t mode) +static int skel_open(vfs_handle_struct *handle, struct smb_filename *smb_fname, + files_struct *fsp, int flags, mode_t mode) { - return SMB_VFS_NEXT_OPEN(handle, fname, fsp, flags, mode); + return SMB_VFS_NEXT_OPEN(handle, smb_fname, fsp, flags, mode); } static int skel_close(vfs_handle_struct *handle, files_struct *fsp) diff --git a/source3/include/proto.h b/source3/include/proto.h index 8435b790a8..4ae141e89d 100644 --- a/source3/include/proto.h +++ b/source3/include/proto.h @@ -6583,6 +6583,7 @@ void send_nt_replies(connection_struct *conn, char *pdata, int datasize); bool is_ntfs_stream_name(const char *fname); bool is_ntfs_stream_smb_fname(const struct smb_filename *smb_fname); +bool is_ntfs_default_stream_smb_fname(const struct smb_filename *smb_fname); void reply_ntcreate_and_X(struct smb_request *req); void reply_ntcancel(struct smb_request *req); void reply_ntrename(struct smb_request *req); diff --git a/source3/include/vfs.h b/source3/include/vfs.h index e0e022877a..53a4798d37 100644 --- a/source3/include/vfs.h +++ b/source3/include/vfs.h @@ -117,7 +117,8 @@ /* Leave at 25 - not yet released. Add init_search_op call. - sdann */ /* Leave at 25 - not yet released. Add locking calls. -- zkirsch. */ /* Leave at 25 - not yet released. Add strict locking calls. -- drichards. */ -/* Changed to version 26 - Plumb struct smb_filename to SMB_VFS_CREATE_FILE. */ +/* Changed to version 26 - Plumb struct smb_filename to SMB_VFS_CREATE_FILE, + SMB_VFS_OPEN. */ #define SMB_VFS_INTERFACE_VERSION 26 @@ -330,7 +331,9 @@ struct vfs_ops { /* File operations */ - int (*open)(struct vfs_handle_struct *handle, const char *fname, files_struct *fsp, int flags, mode_t mode); + int (*open)(struct vfs_handle_struct *handle, + struct smb_filename *smb_fname, files_struct *fsp, + int flags, mode_t mode); NTSTATUS (*create_file)(struct vfs_handle_struct *handle, struct smb_request *req, uint16_t root_dir_fid, diff --git a/source3/modules/vfs_acl_tdb.c b/source3/modules/vfs_acl_tdb.c index 463250a9ed..e0a5b14c67 100644 --- a/source3/modules/vfs_acl_tdb.c +++ b/source3/modules/vfs_acl_tdb.c @@ -549,7 +549,7 @@ static NTSTATUS inherit_new_acl(vfs_handle_struct *handle, *********************************************************************/ static int open_acl_tdb(vfs_handle_struct *handle, - const char *fname, + struct smb_filename *smb_fname, files_struct *fsp, int flags, mode_t mode) @@ -557,7 +557,17 @@ static int open_acl_tdb(vfs_handle_struct *handle, uint32_t access_granted = 0; struct security_descriptor *pdesc = NULL; bool file_existed = true; - NTSTATUS status = get_nt_acl_tdb_internal(handle, + char *fname = NULL; + NTSTATUS status; + + status = get_full_smb_filename(talloc_tos(), smb_fname, + &fname); + if (!NT_STATUS_IS_OK(status)) { + errno = map_errno_from_nt_status(status); + return -1; + } + + status = get_nt_acl_tdb_internal(handle, NULL, fname, (OWNER_SECURITY_INFORMATION | @@ -573,7 +583,7 @@ static int open_acl_tdb(vfs_handle_struct *handle, if (!NT_STATUS_IS_OK(status)) { DEBUG(10,("open_acl_tdb: file %s open " "refused with error %s\n", - fname, + smb_fname_str_dbg(smb_fname), nt_errstr(status) )); errno = map_errno_from_nt_status(status); return -1; @@ -584,10 +594,10 @@ static int open_acl_tdb(vfs_handle_struct *handle, DEBUG(10,("open_acl_tdb: get_nt_acl_attr_internal for " "file %s returned %s\n", - fname, + smb_fname_str_dbg(smb_fname), nt_errstr(status) )); - fsp->fh->fd = SMB_VFS_NEXT_OPEN(handle, fname, fsp, flags, mode); + fsp->fh->fd = SMB_VFS_NEXT_OPEN(handle, smb_fname, fsp, flags, mode); if (!file_existed && fsp->fh->fd != -1) { /* File was created. Inherit from parent directory. */ diff --git a/source3/modules/vfs_acl_xattr.c b/source3/modules/vfs_acl_xattr.c index 05156f8456..efcc87740a 100644 --- a/source3/modules/vfs_acl_xattr.c +++ b/source3/modules/vfs_acl_xattr.c @@ -417,7 +417,7 @@ static NTSTATUS inherit_new_acl(vfs_handle_struct *handle, *********************************************************************/ static int open_acl_xattr(vfs_handle_struct *handle, - const char *fname, + struct smb_filename *smb_fname, files_struct *fsp, int flags, mode_t mode) @@ -425,7 +425,17 @@ static int open_acl_xattr(vfs_handle_struct *handle, uint32_t access_granted = 0; struct security_descriptor *pdesc = NULL; bool file_existed = true; - NTSTATUS status = get_nt_acl_xattr_internal(handle, + char *fname = NULL; + NTSTATUS status; + + status = get_full_smb_filename(talloc_tos(), smb_fname, + &fname); + if (!NT_STATUS_IS_OK(status)) { + errno = map_errno_from_nt_status(status); + return -1; + } + + status = get_nt_acl_xattr_internal(handle, NULL, fname, (OWNER_SECURITY_INFORMATION | @@ -441,7 +451,7 @@ static int open_acl_xattr(vfs_handle_struct *handle, if (!NT_STATUS_IS_OK(status)) { DEBUG(10,("open_acl_xattr: file %s open " "refused with error %s\n", - fname, + smb_fname_str_dbg(smb_fname), nt_errstr(status) )); errno = map_errno_from_nt_status(status); return -1; @@ -452,10 +462,10 @@ static int open_acl_xattr(vfs_handle_struct *handle, DEBUG(10,("open_acl_xattr: get_nt_acl_attr_internal for " "file %s returned %s\n", - fname, + smb_fname_str_dbg(smb_fname), nt_errstr(status) )); - fsp->fh->fd = SMB_VFS_NEXT_OPEN(handle, fname, fsp, flags, mode); + fsp->fh->fd = SMB_VFS_NEXT_OPEN(handle, smb_fname, fsp, flags, mode); if (!file_existed && fsp->fh->fd != -1) { /* File was created. Inherit from parent directory. */ diff --git a/source3/modules/vfs_audit.c b/source3/modules/vfs_audit.c index 4000580c42..2897cefb96 100644 --- a/source3/modules/vfs_audit.c +++ b/source3/modules/vfs_audit.c @@ -33,7 +33,7 @@ static void audit_disconnect(vfs_handle_struct *handle); static SMB_STRUCT_DIR *audit_opendir(vfs_handle_struct *handle, const char *fname, const char *mask, uint32 attr); static int audit_mkdir(vfs_handle_struct *handle, const char *path, mode_t mode); static int audit_rmdir(vfs_handle_struct *handle, const char *path); -static int audit_open(vfs_handle_struct *handle, const char *fname, files_struct *fsp, int flags, mode_t mode); +static int audit_open(vfs_handle_struct *handle, struct smb_filename *smb_fname, files_struct *fsp, int flags, mode_t mode); static int audit_close(vfs_handle_struct *handle, files_struct *fsp); static int audit_rename(vfs_handle_struct *handle, const char *oldname, const char *newname); static int audit_unlink(vfs_handle_struct *handle, const char *path); @@ -187,14 +187,16 @@ static int audit_rmdir(vfs_handle_struct *handle, const char *path) return result; } -static int audit_open(vfs_handle_struct *handle, const char *fname, files_struct *fsp, int flags, mode_t mode) +static int audit_open(vfs_handle_struct *handle, + struct smb_filename *smb_fname, files_struct *fsp, + int flags, mode_t mode) { int result; - result = SMB_VFS_NEXT_OPEN(handle, fname, fsp, flags, mode); + result = SMB_VFS_NEXT_OPEN(handle, smb_fname, fsp, flags, mode); syslog(audit_syslog_priority(handle), "open %s (fd %d) %s%s%s\n", - fname, result, + smb_fname_str_dbg(smb_fname), result, ((flags & O_WRONLY) || (flags & O_RDWR)) ? "for writing " : "", (result < 0) ? "failed: " : "", (result < 0) ? strerror(errno) : ""); diff --git a/source3/modules/vfs_cap.c b/source3/modules/vfs_cap.c index e26d29d667..4525fa1da3 100644 --- a/source3/modules/vfs_cap.c +++ b/source3/modules/vfs_cap.c @@ -106,16 +106,30 @@ static int cap_rmdir(vfs_handle_struct *handle, const char *path) return SMB_VFS_NEXT_RMDIR(handle, cappath); } -static int cap_open(vfs_handle_struct *handle, const char *fname, files_struct *fsp, int flags, mode_t mode) +static int cap_open(vfs_handle_struct *handle, struct smb_filename *smb_fname, + files_struct *fsp, int flags, mode_t mode) { - char *cappath = capencode(talloc_tos(), fname); + char *cappath; + char *tmp_base_name = NULL; + int ret; + + cappath = capencode(talloc_tos(), smb_fname->base_name); if (!cappath) { errno = ENOMEM; return -1; } - DEBUG(3,("cap: cap_open for %s\n", fname)); - return SMB_VFS_NEXT_OPEN(handle, cappath, fsp, flags, mode); + + tmp_base_name = smb_fname->base_name; + smb_fname->base_name = cappath; + + DEBUG(3,("cap: cap_open for %s\n", smb_fname_str_dbg(smb_fname))); + ret = SMB_VFS_NEXT_OPEN(handle, smb_fname, fsp, flags, mode); + + smb_fname->base_name = tmp_base_name; + TALLOC_FREE(cappath); + + return ret; } static int cap_rename(vfs_handle_struct *handle, const char *oldname, const char *newname) diff --git a/source3/modules/vfs_catia.c b/source3/modules/vfs_catia.c index 2870254bfb..8d1c87a9fc 100644 --- a/source3/modules/vfs_catia.c +++ b/source3/modules/vfs_catia.c @@ -133,18 +133,30 @@ static SMB_STRUCT_DIRENT *catia_readdir(vfs_handle_struct *handle, } static int catia_open(vfs_handle_struct *handle, - const char *fname, + struct smb_filename *smb_fname, files_struct *fsp, int flags, mode_t mode) { - char *name = to_unix(talloc_tos(), fname); + char *name; + char *tmp_base_name; + int ret; + name = to_unix(talloc_tos(), smb_fname->base_name); if (!name) { errno = ENOMEM; return -1; } - return SMB_VFS_NEXT_OPEN(handle, name, fsp, flags, mode); + + tmp_base_name = smb_fname->base_name; + smb_fname->base_name = name; + + ret = SMB_VFS_NEXT_OPEN(handle, name, fsp, flags, mode); + + smb_fname->base_name = tmp_base_name; + TALLOC_FREE(name); + + return ret; } static int catia_rename(vfs_handle_struct *handle, diff --git a/source3/modules/vfs_commit.c b/source3/modules/vfs_commit.c index c22e8161d7..6c363229d3 100644 --- a/source3/modules/vfs_commit.c +++ b/source3/modules/vfs_commit.c @@ -167,7 +167,7 @@ static int commit_connect( static int commit_open( vfs_handle_struct * handle, - const char * fname, + struct smb_filename *smb_fname, files_struct * fsp, int flags, mode_t mode) @@ -179,7 +179,7 @@ static int commit_open( /* Don't bother with read-only files. */ if ((flags & O_ACCMODE) == O_RDONLY) { - return SMB_VFS_NEXT_OPEN(handle, fname, fsp, flags, mode); + return SMB_VFS_NEXT_OPEN(handle, smb_fname, fsp, flags, mode); } /* Read and check module configuration */ @@ -208,7 +208,7 @@ static int commit_open( } } - fd = SMB_VFS_NEXT_OPEN(handle, fname, fsp, flags, mode); + fd = SMB_VFS_NEXT_OPEN(handle, smb_fname, fsp, flags, mode); if (fd == -1) { VFS_REMOVE_FSP_EXTENSION(handle, fsp); return fd; diff --git a/source3/modules/vfs_default.c b/source3/modules/vfs_default.c index 28adce5768..0e7ba05632 100644 --- a/source3/modules/vfs_default.c +++ b/source3/modules/vfs_default.c @@ -214,13 +214,31 @@ static void vfswrap_init_search_op(vfs_handle_struct *handle, /* File operations */ -static int vfswrap_open(vfs_handle_struct *handle, const char *fname, - files_struct *fsp, int flags, mode_t mode) +static int vfswrap_open(vfs_handle_struct *handle, + struct smb_filename *smb_fname, + files_struct *fsp, int flags, mode_t mode) { int result; + NTSTATUS status; + char *fname = NULL; START_PROFILE(syscall_open); + + /* + * XXX: Should an error be returned if there is a stream rather than + * trying to open a filename with a ':'? + */ + status = get_full_smb_filename(talloc_tos(), smb_fname, + &fname); + if (!NT_STATUS_IS_OK(status)) { + errno = map_errno_from_nt_status(status); + return -1; + } + result = sys_open(fname, flags, mode); + + TALLOC_FREE(fname); + END_PROFILE(syscall_open); return result; } diff --git a/source3/modules/vfs_extd_audit.c b/source3/modules/vfs_extd_audit.c index b59a780f52..763f1545d7 100644 --- a/source3/modules/vfs_extd_audit.c +++ b/source3/modules/vfs_extd_audit.c @@ -36,7 +36,7 @@ static void audit_disconnect(vfs_handle_struct *handle); static SMB_STRUCT_DIR *audit_opendir(vfs_handle_struct *handle, const char *fname, const char *mask, uint32 attr); static int audit_mkdir(vfs_handle_struct *handle, const char *path, mode_t mode); static int audit_rmdir(vfs_handle_struct *handle, const char *path); -static int audit_open(vfs_handle_struct *handle, const char *fname, files_struct *fsp, int flags, mode_t mode); +static int audit_open(vfs_handle_struct *handle, struct smb_filename *smb_fname, files_struct *fsp, int flags, mode_t mode); static int audit_close(vfs_handle_struct *handle, files_struct *fsp); static int audit_rename(vfs_handle_struct *handle, const char *oldname, const char *newname); static int audit_unlink(vfs_handle_struct *handle, const char *path); @@ -216,21 +216,23 @@ static int audit_rmdir(vfs_handle_struct *handle, const char *path) return result; } -static int audit_open(vfs_handle_struct *handle, const char *fname, files_struct *fsp, int flags, mode_t mode) +static int audit_open(vfs_handle_struct *handle, + struct smb_filename *smb_fname, files_struct *fsp, + int flags, mode_t mode) { int result; - result = SMB_VFS_NEXT_OPEN(handle, fname, fsp, flags, mode); + result = SMB_VFS_NEXT_OPEN(handle, smb_fname, fsp, flags, mode); if (lp_syslog() > 0) { syslog(audit_syslog_priority(handle), "open %s (fd %d) %s%s%s\n", - fname, result, + smb_fname_str_dbg(smb_fname), result, ((flags & O_WRONLY) || (flags & O_RDWR)) ? "for writing " : "", (result < 0) ? "failed: " : "", (result < 0) ? strerror(errno) : ""); } DEBUG(2, ("vfs_extd_audit: open %s %s %s\n", - fname, + smb_fname_str_dbg(smb_fname), (result < 0) ? "failed: " : "", (result < 0) ? strerror(errno) : "")); diff --git a/source3/modules/vfs_full_audit.c b/source3/modules/vfs_full_audit.c index e2d08b440f..5558b2f9b5 100644 --- a/source3/modules/vfs_full_audit.c +++ b/source3/modules/vfs_full_audit.c @@ -111,7 +111,7 @@ static int smb_full_audit_closedir(vfs_handle_struct *handle, static void smb_full_audit_init_search_op(vfs_handle_struct *handle, SMB_STRUCT_DIR *dirp); static int smb_full_audit_open(vfs_handle_struct *handle, - const char *fname, files_struct *fsp, int flags, mode_t mode); + struct smb_filename *smb_fnmae, files_struct *fsp, int flags, mode_t mode); static NTSTATUS smb_full_audit_create_file(vfs_handle_struct *handle, struct smb_request *req, uint16_t root_dir_fid, @@ -1179,15 +1179,16 @@ static void smb_full_audit_init_search_op(vfs_handle_struct *handle, } static int smb_full_audit_open(vfs_handle_struct *handle, - const char *fname, files_struct *fsp, int flags, mode_t mode) + struct smb_filename *smb_fname, + files_struct *fsp, int flags, mode_t mode) { int result; - result = SMB_VFS_NEXT_OPEN(handle, fname, fsp, flags, mode); + result = SMB_VFS_NEXT_OPEN(handle, smb_fname, fsp, flags, mode); do_log(SMB_VFS_OP_OPEN, (result >= 0), handle, "%s|%s", ((flags & O_WRONLY) || (flags & O_RDWR))?"w":"r", - fname); + smb_fname_str_dbg(smb_fname)); return result; } diff --git a/source3/modules/vfs_onefs.c b/source3/modules/vfs_onefs.c index 7414f16cf9..c143fcf54b 100644 --- a/source3/modules/vfs_onefs.c +++ b/source3/modules/vfs_onefs.c @@ -47,12 +47,13 @@ static int onefs_mkdir(vfs_handle_struct *handle, const char *path, return SMB_VFS_NEXT_MKDIR(handle, path, mode); } -static int onefs_open(vfs_handle_struct *handle, const char *fname, +static int onefs_open(vfs_handle_struct *handle, + struct smb_filename *smb_fname, files_struct *fsp, int flags, mode_t mode) { /* SMB_VFS_OPEN should never be called in vfs_onefs */ SMB_ASSERT(false); - return SMB_VFS_NEXT_OPEN(handle, fname, fsp, flags, mode); + return SMB_VFS_NEXT_OPEN(handle, smb_fname, fsp, flags, mode); } static ssize_t onefs_sendfile(vfs_handle_struct *handle, int tofd, diff --git a/source3/modules/vfs_onefs_shadow_copy.c b/source3/modules/vfs_onefs_shadow_copy.c index 3d4ffc9084..45860fa90d 100644 --- a/source3/modules/vfs_onefs_shadow_copy.c +++ b/source3/modules/vfs_onefs_shadow_copy.c @@ -214,12 +214,13 @@ onefs_shadow_copy_rmdir(vfs_handle_struct *handle, const char *path) } static int -onefs_shadow_copy_open(vfs_handle_struct *handle, const char *path, - files_struct *fsp, int flags, mode_t mode) +onefs_shadow_copy_open(vfs_handle_struct *handle, + struct smb_filename *smb_fname, files_struct *fsp, + int flags, mode_t mode) { - SHADOW_NEXT(OPEN, - (handle, cpath ?: path, fsp, flags, mode), - int); + SHADOW_NEXT_SMB_FNAME(OPEN, + (handle, smb_fname, fsp, flags, mode), + int); } static NTSTATUS diff --git a/source3/modules/vfs_prealloc.c b/source3/modules/vfs_prealloc.c index 299f6548a1..2f65e94ea7 100644 --- a/source3/modules/vfs_prealloc.c +++ b/source3/modules/vfs_prealloc.c @@ -108,7 +108,7 @@ static int prealloc_connect( } static int prealloc_open(vfs_handle_struct* handle, - const char * fname, + struct smb_filename *smb_fname, files_struct * fsp, int flags, mode_t mode) @@ -127,7 +127,7 @@ static int prealloc_open(vfs_handle_struct* handle, } *fext = '\0'; - dot = strrchr(fname, '.'); + dot = strrchr(smb_fname->base_name, '.'); if (dot && *++dot) { if (strlen(dot) < sizeof(fext)) { strncpy(fext, dot, sizeof(fext)); @@ -152,7 +152,7 @@ static int prealloc_open(vfs_handle_struct* handle, goto normal_open; } - fd = SMB_VFS_NEXT_OPEN(handle, fname, fsp, flags, mode); + fd = SMB_VFS_NEXT_OPEN(handle, smb_fname, fsp, flags, mode); if (fd < 0) { return fd; } @@ -171,7 +171,8 @@ static int prealloc_open(vfs_handle_struct* handle, DEBUG(module_debug, ("%s: preallocating %s (fd=%d) to %lld bytes\n", - MODULE, fname, fd, (long long)size)); + MODULE, smb_fname_str_dbg(smb_fname), fd, + (long long)size)); *psize = size; if (preallocate_space(fd, *psize) < 0) { @@ -186,8 +187,8 @@ normal_open: * preallocation. */ DEBUG(module_debug, ("%s: skipping preallocation for %s\n", - MODULE, fname)); - return SMB_VFS_NEXT_OPEN(handle, fname, fsp, flags, mode); + MODULE, smb_fname_str_dbg(smb_fname))); + return SMB_VFS_NEXT_OPEN(handle, smb_fname, fsp, flags, mode); } static int prealloc_ftruncate(vfs_handle_struct * handle, diff --git a/source3/modules/vfs_preopen.c b/source3/modules/vfs_preopen.c index 25b9e7f3e4..dcc1ae18c1 100644 --- a/source3/modules/vfs_preopen.c +++ b/source3/modules/vfs_preopen.c @@ -371,21 +371,22 @@ static bool preopen_parse_fname(const char *fname, unsigned long *pnum, return true; } -static int preopen_open(vfs_handle_struct *handle, const char *fname, - files_struct *fsp, int flags, mode_t mode) +static int preopen_open(vfs_handle_struct *handle, + struct smb_filename *smb_fname, files_struct *fsp, + int flags, mode_t mode) { struct preopen_state *state; int res; unsigned long num; - DEBUG(10, ("preopen_open called on %s\n", fname)); + DEBUG(10, ("preopen_open called on %s\n", smb_fname_str_dbg(smb_fname))); state = preopen_state_get(handle); if (state == NULL) { - return SMB_VFS_NEXT_OPEN(handle, fname, fsp, flags, mode); + return SMB_VFS_NEXT_OPEN(handle, smb_fname, fsp, flags, mode); } - res = SMB_VFS_NEXT_OPEN(handle, fname, fsp, flags, mode); + res = SMB_VFS_NEXT_OPEN(handle, smb_fname, fsp, flags, mode); if (res == -1) { return -1; } @@ -394,15 +395,15 @@ static int preopen_open(vfs_handle_struct *handle, const char *fname, return res; } - if (!is_in_path(fname, state->preopen_names, true)) { + if (!is_in_path(smb_fname->base_name, state->preopen_names, true)) { DEBUG(10, ("%s does not match the preopen:names list\n", - fname)); + smb_fname_str_dbg(smb_fname))); return res; } TALLOC_FREE(state->template_fname); state->template_fname = talloc_asprintf( - state, "%s/%s", fsp->conn->connectpath, fname); + state, "%s/%s", fsp->conn->connectpath, smb_fname->base_name); if (state->template_fname == NULL) { return res; diff --git a/source3/modules/vfs_shadow_copy2.c b/source3/modules/vfs_shadow_copy2.c index 030d3e2b01..7b5b85d4be 100644 --- a/source3/modules/vfs_shadow_copy2.c +++ b/source3/modules/vfs_shadow_copy2.c @@ -115,6 +115,28 @@ static inline bool shadow_copy2_match_name(const char *name) } \ } while (0) +#define _SHADOW2_NEXT_SMB_FNAME(op, args, rtype, eret, extra) do { \ + if (shadow_copy2_match_name(smb_fname->base_name)) { \ + char *name2; \ + char *smb_base_name_tmp = NULL; \ + rtype ret; \ + name2 = convert_shadow2_name(handle, smb_fname->base_name); \ + if (name2 == NULL) { \ + errno = EINVAL; \ + return eret; \ + } \ + smb_base_name_tmp = smb_fname->base_name; \ + smb_fname->base_name = name2; \ + ret = SMB_VFS_NEXT_ ## op args; \ + smb_fname->base_name = smb_base_name_tmp; \ + talloc_free(name2); \ + if (ret != eret) extra; \ + return ret; \ + } else { \ + return SMB_VFS_NEXT_ ## op args; \ + } \ +} while (0) + /* convert a name to the shadow directory: NTSTATUS-specific handling */ @@ -143,6 +165,8 @@ static inline bool shadow_copy2_match_name(const char *name) #define SHADOW2_NEXT(op, args, rtype, eret) _SHADOW2_NEXT(op, args, rtype, eret, ) +#define SHADOW2_NEXT_SMB_FNAME(op, args, rtype, eret) _SHADOW2_NEXT_SMB_FNAME(op, args, rtype, eret, ) + #define SHADOW2_NEXT2(op, args) do { \ if (shadow_copy2_match_name(oldname) || shadow_copy2_match_name(newname)) { \ errno = EROFS; \ @@ -337,9 +361,12 @@ static int shadow_copy2_link(vfs_handle_struct *handle, } static int shadow_copy2_open(vfs_handle_struct *handle, - const char *fname, files_struct *fsp, int flags, mode_t mode) + struct smb_filename *smb_fname, files_struct *fsp, + int flags, mode_t mode) { - SHADOW2_NEXT(OPEN, (handle, name, fsp, flags, mode), int, -1); + SHADOW2_NEXT_SMB_FNAME(OPEN, + (handle, smb_fname, fsp, flags, mode), + int, -1); } static SMB_STRUCT_DIR *shadow_copy2_opendir(vfs_handle_struct *handle, diff --git a/source3/modules/vfs_streams_depot.c b/source3/modules/vfs_streams_depot.c index 72affe402a..7d37af0181 100644 --- a/source3/modules/vfs_streams_depot.c +++ b/source3/modules/vfs_streams_depot.c @@ -267,6 +267,69 @@ static char *stream_dir(vfs_handle_struct *handle, const char *base_path, TALLOC_FREE(result); return NULL; } +/** + * Given a stream name, populate smb_fname_out with the actual location of the + * stream. + */ +static NTSTATUS stream_smb_fname(vfs_handle_struct *handle, + const struct smb_filename *smb_fname, + struct smb_filename **smb_fname_out, + bool create_dir) +{ + char *dirname, *stream_fname; + const char *stype; + NTSTATUS status; + + *smb_fname_out = NULL; + + dirname = stream_dir(handle, smb_fname->base_name, NULL, create_dir); + + if (dirname == NULL) { + status = map_nt_error_from_unix(errno); + goto fail; + } + + stype = strchr_m(smb_fname->stream_name + 1, ':'); + + stream_fname = talloc_asprintf(talloc_tos(), "%s/%s", dirname, + smb_fname->stream_name); + + if (stream_fname == NULL) { + status = NT_STATUS_NO_MEMORY; + goto fail; + } + + if (stype == NULL) { + /* Append an explicit stream type if one wasn't specified. */ + stream_fname = talloc_asprintf(talloc_tos(), "%s:$DATA", + stream_fname); + if (stream_fname == NULL) { + status = NT_STATUS_NO_MEMORY; + goto fail; + } + } else { + /* Normalize the stream type to upercase. */ + strupper_m(strrchr_m(stream_fname, ':') + 1); + } + + DEBUG(10, ("stream filename = %s\n", stream_fname)); + + /* Create an smb_filename with stream_name == NULL. */ + status = create_synthetic_smb_fname(talloc_tos(), + stream_fname, + NULL, NULL, + smb_fname_out); + if (!NT_STATUS_IS_OK(status)) { + return status; + } + + return NT_STATUS_OK; + + fail: + DEBUG(5, ("stream_name failed: %s\n", strerror(errno))); + TALLOC_FREE(*smb_fname_out); + return status; +} static char *stream_name(vfs_handle_struct *handle, const char *fname, bool create_dir) @@ -422,50 +485,52 @@ static int streams_depot_lstat(vfs_handle_struct *handle, const char *fname, return ret; } -static int streams_depot_open(vfs_handle_struct *handle, const char *fname, +static int streams_depot_open(vfs_handle_struct *handle, + struct smb_filename *smb_fname, files_struct *fsp, int flags, mode_t mode) { - TALLOC_CTX *frame; - char *base = NULL; - char *sname = NULL; + struct smb_filename *smb_fname_stream = NULL; SMB_STRUCT_STAT base_sbuf; - char *stream_fname; + NTSTATUS status; int ret = -1; - if (!is_ntfs_stream_name(fname)) { - return SMB_VFS_NEXT_OPEN(handle, fname, fsp, flags, mode); + if (!is_ntfs_stream_smb_fname(smb_fname)) { + ret = SMB_VFS_NEXT_OPEN(handle, smb_fname, fsp, flags, mode); + return ret; } - frame = talloc_stackframe(); + /* If the default stream is requested, just open the base file. */ + if (is_ntfs_default_stream_smb_fname(smb_fname)) { + char *tmp_stream_name; - if (!NT_STATUS_IS_OK(split_ntfs_stream_name(talloc_tos(), fname, - &base, &sname))) { - errno = ENOMEM; - goto done; - } + tmp_stream_name = smb_fname->stream_name; + smb_fname->stream_name = NULL; - if (!sname) { - ret = SMB_VFS_NEXT_OPEN(handle, base, fsp, flags, mode); - goto done; + ret = SMB_VFS_NEXT_OPEN(handle, smb_fname, fsp, flags, mode); + + smb_fname->stream_name = tmp_stream_name; + + return ret; } - ret = SMB_VFS_NEXT_STAT(handle, base, &base_sbuf); + /* Ensure the base file still exists. */ + ret = SMB_VFS_NEXT_STAT(handle, smb_fname->base_name, &base_sbuf); if (ret == -1) { goto done; } - TALLOC_FREE(base); - - stream_fname = stream_name(handle, fname, true); - if (stream_fname == NULL) { + status = stream_smb_fname(handle, smb_fname, &smb_fname_stream, true); + if (!NT_STATUS_IS_OK(status)) { + ret = -1; + errno = map_errno_from_nt_status(status); goto done; } - ret = SMB_VFS_NEXT_OPEN(handle, stream_fname, fsp, flags, mode); + ret = SMB_VFS_NEXT_OPEN(handle, smb_fname_stream, fsp, flags, mode); done: - TALLOC_FREE(frame); + TALLOC_FREE(smb_fname_stream); return ret; } diff --git a/source3/modules/vfs_streams_xattr.c b/source3/modules/vfs_streams_xattr.c index ebc51e79e3..715e1a7baf 100644 --- a/source3/modules/vfs_streams_xattr.c +++ b/source3/modules/vfs_streams_xattr.c @@ -88,6 +88,43 @@ static ssize_t get_xattr_size(connection_struct *conn, return result; } +/** + * Given a stream name, populate xattr_name with the xattr name to use for + * accessing the stream. + */ +static NTSTATUS streams_xattr_get_name(TALLOC_CTX *ctx, + const char *stream_name, + char **xattr_name) +{ + char *stype; + + stype = strchr_m(stream_name + 1, ':'); + + *xattr_name = talloc_asprintf(ctx, "%s%s", + SAMBA_XATTR_DOSSTREAM_PREFIX, + stream_name + 1); + if (*xattr_name == NULL) { + return NT_STATUS_NO_MEMORY; + } + + if (stype == NULL) { + /* Append an explicit stream type if one wasn't specified. */ + *xattr_name = talloc_asprintf(ctx, "%s:$DATA", + *xattr_name); + if (*xattr_name == NULL) { + return NT_STATUS_NO_MEMORY; + } + } else { + /* Normalize the stream type to upercase. */ + strupper_m(strrchr_m(*xattr_name, ':') + 1); + } + + DEBUG(10, ("xattr_name: %s, stream_name: %s\n", *xattr_name, + stream_name)); + + return NT_STATUS_OK; +} + static bool streams_xattr_recheck(struct stream_io *sio) { NTSTATUS status; @@ -277,43 +314,54 @@ static int streams_xattr_lstat(vfs_handle_struct *handle, const char *fname, return result; } -static int streams_xattr_open(vfs_handle_struct *handle, const char *fname, +static int streams_xattr_open(vfs_handle_struct *handle, + struct smb_filename *smb_fname, files_struct *fsp, int flags, mode_t mode) { - TALLOC_CTX *frame; NTSTATUS status; + struct smb_filename *smb_fname_base = NULL; struct stream_io *sio; - char *base, *sname; struct ea_struct ea; - char *xattr_name; + char *xattr_name = NULL; int baseflags; int hostfd = -1; - DEBUG(10, ("streams_xattr_open called for %s\n", fname)); + DEBUG(10, ("streams_xattr_open called for %s\n", + smb_fname_str_dbg(smb_fname))); - if (!is_ntfs_stream_name(fname)) { - return SMB_VFS_NEXT_OPEN(handle, fname, fsp, flags, mode); + if (!is_ntfs_stream_smb_fname(smb_fname)) { + return SMB_VFS_NEXT_OPEN(handle, smb_fname, fsp, flags, mode); } - frame = talloc_stackframe(); + /* If the default stream is requested, just open the base file. */ + if (is_ntfs_default_stream_smb_fname(smb_fname)) { + char *tmp_stream_name; + int ret; - status = split_ntfs_stream_name(talloc_tos(), fname, - &base, &sname); - if (!NT_STATUS_IS_OK(status)) { - errno = EINVAL; - goto fail; + tmp_stream_name = smb_fname->stream_name; + smb_fname->stream_name = NULL; + + ret = SMB_VFS_NEXT_OPEN(handle, smb_fname, fsp, flags, mode); + + smb_fname->stream_name = tmp_stream_name; + + return ret; } - if (sname == NULL) { - hostfd = SMB_VFS_NEXT_OPEN(handle, base, fsp, flags, mode); - talloc_free(frame); - return hostfd; + status = streams_xattr_get_name(talloc_tos(), smb_fname->stream_name, + &xattr_name); + if (!NT_STATUS_IS_OK(status)) { + errno = map_errno_from_nt_status(status); + goto fail; } - xattr_name = talloc_asprintf(talloc_tos(), "%s%s", - SAMBA_XATTR_DOSSTREAM_PREFIX, sname); - if (xattr_name == NULL) { - errno = ENOMEM; + /* Create an smb_filename with stream_name == NULL. */ + status = create_synthetic_smb_fname(talloc_tos(), + smb_fname->base_name, + NULL, NULL, + &smb_fname_base); + if (!NT_STATUS_IS_OK(status)) { + errno = map_errno_from_nt_status(status); goto fail; } @@ -326,7 +374,10 @@ static int streams_xattr_open(vfs_handle_struct *handle, const char *fname, baseflags &= ~O_EXCL; baseflags &= ~O_CREAT; - hostfd = SMB_VFS_OPEN(handle->conn, base, fsp, baseflags, mode); + hostfd = SMB_VFS_OPEN(handle->conn, smb_fname_base, fsp, + baseflags, mode); + + TALLOC_FREE(smb_fname_base); /* It is legit to open a stream on a directory, but the base * fd has to be read-only. @@ -334,7 +385,7 @@ static int streams_xattr_open(vfs_handle_struct *handle, const char *fname, if ((hostfd == -1) && (errno == EISDIR)) { baseflags &= ~O_ACCMODE; baseflags |= O_RDONLY; - hostfd = SMB_VFS_OPEN(handle->conn, fname, fsp, baseflags, + hostfd = SMB_VFS_OPEN(handle->conn, smb_fname, fsp, baseflags, mode); } @@ -342,8 +393,8 @@ static int streams_xattr_open(vfs_handle_struct *handle, const char *fname, goto fail; } - status = get_ea_value(talloc_tos(), handle->conn, NULL, base, - xattr_name, &ea); + status = get_ea_value(talloc_tos(), handle->conn, NULL, + smb_fname->base_name, xattr_name, &ea); DEBUG(10, ("get_ea_value returned %s\n", nt_errstr(status))); @@ -355,7 +406,7 @@ static int streams_xattr_open(vfs_handle_struct *handle, const char *fname, * file for us. */ DEBUG(10, ("streams_xattr_open: base file %s not around, " - "returning ENOENT\n", base)); + "returning ENOENT\n", smb_fname->base_name)); errno = ENOENT; goto fail; } @@ -372,7 +423,7 @@ static int streams_xattr_open(vfs_handle_struct *handle, const char *fname, char null = '\0'; DEBUG(10, ("creating attribute %s on file %s\n", - xattr_name, base)); + xattr_name, smb_fname->base_name)); if (fsp->base_fsp->fh->fd != -1) { if (SMB_VFS_FSETXATTR( @@ -383,8 +434,8 @@ static int streams_xattr_open(vfs_handle_struct *handle, const char *fname, } } else { if (SMB_VFS_SETXATTR( - handle->conn, base, xattr_name, - &null, sizeof(null), + handle->conn, smb_fname->base_name, + xattr_name, &null, sizeof(null), flags & O_EXCL ? XATTR_CREATE : 0) == -1) { goto fail; } @@ -403,8 +454,8 @@ static int streams_xattr_open(vfs_handle_struct *handle, const char *fname, } } else { if (SMB_VFS_SETXATTR( - handle->conn, base, xattr_name, - &null, sizeof(null), + handle->conn, smb_fname->base_name, + xattr_name, &null, sizeof(null), flags & O_EXCL ? XATTR_CREATE : 0) == -1) { goto fail; } @@ -422,7 +473,7 @@ static int streams_xattr_open(vfs_handle_struct *handle, const char *fname, sio->xattr_name = talloc_strdup(VFS_MEMCTX_FSP_EXTENSION(handle, fsp), xattr_name); sio->base = talloc_strdup(VFS_MEMCTX_FSP_EXTENSION(handle, fsp), - base); + smb_fname->base_name); sio->fsp_name_ptr = fsp->fsp_name; sio->handle = handle; sio->fsp = fsp; @@ -432,7 +483,6 @@ static int streams_xattr_open(vfs_handle_struct *handle, const char *fname, goto fail; } - TALLOC_FREE(frame); return hostfd; fail: @@ -444,7 +494,6 @@ static int streams_xattr_open(vfs_handle_struct *handle, const char *fname, SMB_VFS_CLOSE(fsp); } - TALLOC_FREE(frame); return -1; } diff --git a/source3/modules/vfs_syncops.c b/source3/modules/vfs_syncops.c index d3f7868400..562195cbda 100644 --- a/source3/modules/vfs_syncops.c +++ b/source3/modules/vfs_syncops.c @@ -104,6 +104,19 @@ static void syncops_name(const char *name) } } +/* + sync two meta data changes for 1 names + */ +static void syncops_smb_fname(struct smb_filename *smb_fname) +{ + char *parent; + parent = parent_dir(NULL, smb_fname->base_name); + if (parent) { + syncops_sync_directory(parent); + talloc_free(parent); + } +} + /* rename needs special handling, as we may need to fsync two directories @@ -125,6 +138,12 @@ static int syncops_rename(vfs_handle_struct *handle, return ret; \ } while (0) +#define SYNCOPS_NEXT_SMB_FNAME(op, fname, args) do { \ + int ret = SMB_VFS_NEXT_ ## op args; \ + if (ret == 0 && fname) syncops_smb_fname(fname); \ + return ret; \ +} while (0) + static int syncops_symlink(vfs_handle_struct *handle, const char *oldname, const char *newname) { @@ -138,9 +157,11 @@ static int syncops_link(vfs_handle_struct *handle, } static int syncops_open(vfs_handle_struct *handle, - const char *fname, files_struct *fsp, int flags, mode_t mode) + struct smb_filename *smb_fname, files_struct *fsp, + int flags, mode_t mode) { - SYNCOPS_NEXT(OPEN, (flags&O_CREAT?fname:NULL), (handle, fname, fsp, flags, mode)); + SYNCOPS_NEXT_SMB_FNAME(OPEN, (flags&O_CREAT?smb_fname:NULL), + (handle, smb_fname, fsp, flags, mode)); } static int syncops_unlink(vfs_handle_struct *handle, const char *fname) diff --git a/source3/smbd/filename.c b/source3/smbd/filename.c index 0f69ce4820..456caf590b 100644 --- a/source3/smbd/filename.c +++ b/source3/smbd/filename.c @@ -115,8 +115,6 @@ NTSTATUS create_synthetic_smb_fname(TALLOC_CTX *ctx, const char *base_name, { struct smb_filename smb_fname_loc; - SMB_ASSERT(psbuf); - ZERO_STRUCT(smb_fname_loc); /* Setup the base_name/stream_name. */ @@ -124,7 +122,8 @@ NTSTATUS create_synthetic_smb_fname(TALLOC_CTX *ctx, const char *base_name, smb_fname_loc.stream_name = CONST_DISCARD(char *, stream_name); /* Copy the psbuf if one was given. */ - smb_fname_loc.st = *psbuf; + if (psbuf) + smb_fname_loc.st = *psbuf; /* Let copy_smb_filename() do the heavy lifting. */ return copy_smb_filename(ctx, &smb_fname_loc, smb_fname_out); diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index d2a052dd55..c4d0374e99 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -317,6 +317,22 @@ bool is_ntfs_stream_smb_fname(const struct smb_filename *smb_fname) return smb_fname->stream_name; } +/**************************************************************************** + Returns true if the filename's stream == "::$DATA" + ***************************************************************************/ +bool is_ntfs_default_stream_smb_fname(const struct smb_filename *smb_fname) +{ + if (lp_posix_pathnames()) { + return false; + } + + if (!smb_fname->stream_name) { + return false; + } + + return StrCaseCmp(smb_fname->stream_name, "::$DATA") == 0; +} + /**************************************************************************** Reply to an NT create and X call on a pipe ****************************************************************************/ diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 7b2fc19a6c..5d82738f6a 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -119,7 +119,7 @@ static NTSTATUS check_open_rights(struct connection_struct *conn, ****************************************************************************/ static NTSTATUS fd_open(struct connection_struct *conn, - const char *fname, + struct smb_filename *smb_fname, files_struct *fsp, int flags, mode_t mode) @@ -137,7 +137,7 @@ static NTSTATUS fd_open(struct connection_struct *conn, } #endif - fsp->fh->fd = SMB_VFS_OPEN(conn,fname,fsp,flags,mode); + fsp->fh->fd = SMB_VFS_OPEN(conn, smb_fname, fsp, flags, mode); if (fsp->fh->fd == -1) { status = map_nt_error_from_unix(errno); if (errno == EMFILE) { @@ -155,7 +155,7 @@ static NTSTATUS fd_open(struct connection_struct *conn, } DEBUG(10,("fd_open: name %s, flags = 0%o mode = 0%o, fd = %d. %s\n", - fname, flags, (int)mode, fsp->fh->fd, + smb_fname_str_dbg(smb_fname), flags, (int)mode, fsp->fh->fd, (fsp->fh->fd == -1) ? strerror(errno) : "" )); return status; @@ -422,7 +422,7 @@ static NTSTATUS open_file(files_struct *fsp, } /* Actually do the open */ - status = fd_open(conn, path, fsp, local_flags, unx_mode); + status = fd_open(conn, smb_fname, fsp, local_flags, unx_mode); if (!NT_STATUS_IS_OK(status)) { DEBUG(3,("Error opening file %s (%s) (local_flags=%d) " "(flags=%d)\n", smb_fname_str_dbg(smb_fname), diff --git a/source3/torture/cmd_vfs.c b/source3/torture/cmd_vfs.c index 1664f9a94d..f1f4aed77c 100644 --- a/source3/torture/cmd_vfs.c +++ b/source3/torture/cmd_vfs.c @@ -236,6 +236,8 @@ static NTSTATUS cmd_open(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc, c mode_t mode; const char *flagstr; files_struct *fsp; + struct smb_filename *smb_fname = NULL; + NTSTATUS status; mode = 00400; @@ -328,7 +330,16 @@ static NTSTATUS cmd_open(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc, c } fsp->conn = vfs->conn; - fsp->fh->fd = SMB_VFS_OPEN(vfs->conn, argv[1], fsp, flags, mode); + status = create_synthetic_smb_fname_split(mem_ctx, argv[1], NULL, + &smb_fname); + if (!NT_STATUS_IS_OK(status)) { + SAFE_FREE(fsp->fsp_name); + SAFE_FREE(fsp); + return status; + } + + fsp->fh->fd = SMB_VFS_OPEN(vfs->conn, smb_fname, fsp, flags, mode); + TALLOC_FREE(smb_fname); if (fsp->fh->fd == -1) { printf("open: error=%d (%s)\n", errno, strerror(errno)); SAFE_FREE(fsp->fh); -- cgit