From dce28a7368151fc1af2665f731fe8934915b9c68 Mon Sep 17 00:00:00 2001 From: Frank Lahm Date: Thu, 13 Oct 2011 15:41:53 -0700 Subject: [PATCH 1/2] Add support for VFS op streaminfo chaining in all relevant VFS modules. Autobuild-User: Jeremy Allison Autobuild-Date: Fri Oct 14 03:26:06 CEST 2011 on sn-devel-104 (cherry picked from commit 7a0b5d6fc51d5d212529e82e5ed8e21516bfbe27) --- source3/modules/onefs_streams.c | 17 +++-------------- source3/modules/vfs_default.c | 25 ++++++++++--------------- source3/modules/vfs_streams_depot.c | 18 +++--------------- source3/modules/vfs_streams_xattr.c | 18 ++++-------------- source3/smbd/close.c | 4 ++-- source3/smbd/filename.c | 2 +- source3/smbd/nttrans.c | 4 ++-- source3/smbd/open.c | 6 +++--- source3/smbd/trans2.c | 4 ++-- 9 files changed, 30 insertions(+), 68 deletions(-) diff --git a/source3/modules/onefs_streams.c b/source3/modules/onefs_streams.c index 85ab256..ac88573 100644 --- a/source3/modules/onefs_streams.c +++ b/source3/modules/onefs_streams.c @@ -736,25 +736,14 @@ NTSTATUS onefs_streaminfo(vfs_handle_struct *handle, return map_nt_error_from_unix(errno); } - state.streams = NULL; - state.num_streams = 0; + state.streams = *pstreams; + state.num_streams = *pnum_streams; if (lp_parm_bool(SNUM(handle->conn), PARM_ONEFS_TYPE, PARM_IGNORE_STREAMS, PARM_IGNORE_STREAMS_DEFAULT)) { goto out; } - /* Add the default stream. */ - if (S_ISREG(sbuf.st_ex_mode)) { - if (!add_one_stream(mem_ctx, - &state.num_streams, &state.streams, - "", sbuf.st_ex_size, - SMB_VFS_GET_ALLOC_SIZE(handle->conn, fsp, - &sbuf))) { - return NT_STATUS_NO_MEMORY; - } - } - state.mem_ctx = mem_ctx; state.handle = handle; state.status = NT_STATUS_OK; @@ -778,5 +767,5 @@ NTSTATUS onefs_streaminfo(vfs_handle_struct *handle, out: *num_streams = state.num_streams; *streams = state.streams; - return NT_STATUS_OK; + return SMB_VFS_NEXT_STREAMINFO(handle, fsp, fname, mem_ctx, pnum_streams, pstreams); } diff --git a/source3/modules/vfs_default.c b/source3/modules/vfs_default.c index 4d06a10..27e9b9b 100644 --- a/source3/modules/vfs_default.c +++ b/source3/modules/vfs_default.c @@ -1182,8 +1182,7 @@ static NTSTATUS vfswrap_streaminfo(vfs_handle_struct *handle, struct stream_struct **pstreams) { SMB_STRUCT_STAT sbuf; - unsigned int num_streams = 0; - struct stream_struct *streams = NULL; + struct stream_struct *tmp_streams = NULL; int ret; if ((fsp != NULL) && (fsp->is_directory)) { @@ -1218,25 +1217,21 @@ static NTSTATUS vfswrap_streaminfo(vfs_handle_struct *handle, goto done; } - streams = talloc(mem_ctx, struct stream_struct); - - if (streams == NULL) { + tmp_streams = talloc_realloc(mem_ctx, *pstreams, struct stream_struct, + (*pnum_streams) + 1); + if (tmp_streams == NULL) { return NT_STATUS_NO_MEMORY; } - - streams->size = sbuf.st_ex_size; - streams->alloc_size = SMB_VFS_GET_ALLOC_SIZE(handle->conn, fsp, &sbuf); - - streams->name = talloc_strdup(streams, "::$DATA"); - if (streams->name == NULL) { - TALLOC_FREE(streams); + tmp_streams[*pnum_streams].name = talloc_strdup(tmp_streams, "::$DATA"); + if (tmp_streams[*pnum_streams].name == NULL) { return NT_STATUS_NO_MEMORY; } + tmp_streams[*pnum_streams].size = sbuf.st_ex_size; + tmp_streams[*pnum_streams].alloc_size = SMB_VFS_GET_ALLOC_SIZE(handle->conn, fsp, &sbuf); - num_streams = 1; + *pnum_streams += 1; + *pstreams = tmp_streams; done: - *pnum_streams = num_streams; - *pstreams = streams; return NT_STATUS_OK; } diff --git a/source3/modules/vfs_streams_depot.c b/source3/modules/vfs_streams_depot.c index 01851cd..708a90b 100644 --- a/source3/modules/vfs_streams_depot.c +++ b/source3/modules/vfs_streams_depot.c @@ -827,20 +827,8 @@ static NTSTATUS streams_depot_streaminfo(vfs_handle_struct *handle, goto out; } - state.streams = NULL; - state.num_streams = 0; - - if (!S_ISDIR(smb_fname_base->st.st_ex_mode)) { - if (!add_one_stream(mem_ctx, - &state.num_streams, &state.streams, - "::$DATA", smb_fname_base->st.st_ex_size, - SMB_VFS_GET_ALLOC_SIZE(handle->conn, fsp, - &smb_fname_base->st))) { - status = NT_STATUS_NO_MEMORY; - goto out; - } - } - + state.streams = *pstreams; + state.num_streams = *pnum_streams; state.mem_ctx = mem_ctx; state.handle = handle; state.status = NT_STATUS_OK; @@ -861,7 +849,7 @@ static NTSTATUS streams_depot_streaminfo(vfs_handle_struct *handle, *pnum_streams = state.num_streams; *pstreams = state.streams; - status = NT_STATUS_OK; + status = SMB_VFS_NEXT_STREAMINFO(handle, fsp, fname, mem_ctx, pnum_streams, pstreams); out: TALLOC_FREE(smb_fname_base); diff --git a/source3/modules/vfs_streams_xattr.c b/source3/modules/vfs_streams_xattr.c index 34e01b0..08d8d14 100644 --- a/source3/modules/vfs_streams_xattr.c +++ b/source3/modules/vfs_streams_xattr.c @@ -810,19 +810,8 @@ static NTSTATUS streams_xattr_streaminfo(vfs_handle_struct *handle, return map_nt_error_from_unix(errno); } - state.streams = NULL; - state.num_streams = 0; - - if (!S_ISDIR(sbuf.st_ex_mode)) { - if (!add_one_stream(mem_ctx, - &state.num_streams, &state.streams, - "::$DATA", sbuf.st_ex_size, - SMB_VFS_GET_ALLOC_SIZE(handle->conn, fsp, - &sbuf))) { - return NT_STATUS_NO_MEMORY; - } - } - + state.streams = *pstreams; + state.num_streams = *pnum_streams; state.mem_ctx = mem_ctx; state.handle = handle; state.status = NT_STATUS_OK; @@ -842,7 +831,8 @@ static NTSTATUS streams_xattr_streaminfo(vfs_handle_struct *handle, *pnum_streams = state.num_streams; *pstreams = state.streams; - return NT_STATUS_OK; + + return SMB_VFS_NEXT_STREAMINFO(handle, fsp, fname, mem_ctx, pnum_streams, pstreams); } static uint32_t streams_xattr_fs_capabilities(struct vfs_handle_struct *handle, diff --git a/source3/smbd/close.c b/source3/smbd/close.c index aeed4e3..603cfff 100644 --- a/source3/smbd/close.c +++ b/source3/smbd/close.c @@ -201,9 +201,9 @@ static void notify_deferred_opens(struct messaging_context *msg_ctx, NTSTATUS delete_all_streams(connection_struct *conn, const char *fname) { - struct stream_struct *stream_info; + struct stream_struct *stream_info = NULL; int i; - unsigned int num_streams; + unsigned int num_streams = 0; TALLOC_CTX *frame = talloc_stackframe(); NTSTATUS status; diff --git a/source3/smbd/filename.c b/source3/smbd/filename.c index 08bc79d..ec9ca20 100644 --- a/source3/smbd/filename.c +++ b/source3/smbd/filename.c @@ -1170,7 +1170,7 @@ static NTSTATUS build_stream_path(TALLOC_CTX *mem_ctx, struct smb_filename *smb_fname) { NTSTATUS status; - unsigned int i, num_streams; + unsigned int i, num_streams = 0; struct stream_struct *streams = NULL; if (SMB_VFS_STAT(conn, smb_fname) == 0) { diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index f21b62b..8f5a4c5 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -693,7 +693,7 @@ void reply_ntcreate_and_X(struct smb_request *req) if (flags & EXTENDED_RESPONSE_REQUIRED) { uint16_t file_status = (NO_EAS|NO_SUBSTREAMS|NO_REPARSETAG); size_t num_names = 0; - unsigned int num_streams; + unsigned int num_streams = 0; struct stream_struct *streams = NULL; /* Do we have any EA's ? */ @@ -1274,7 +1274,7 @@ static void call_nt_transact_create(connection_struct *conn, if (flags & EXTENDED_RESPONSE_REQUIRED) { uint16_t file_status = (NO_EAS|NO_SUBSTREAMS|NO_REPARSETAG); size_t num_names = 0; - unsigned int num_streams; + unsigned int num_streams = 0; struct stream_struct *streams = NULL; /* Do we have any EA's ? */ diff --git a/source3/smbd/open.c b/source3/smbd/open.c index e30d36e..0813496 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -2967,10 +2967,10 @@ void msg_file_was_renamed(struct messaging_context *msg, NTSTATUS open_streams_for_delete(connection_struct *conn, const char *fname) { - struct stream_struct *stream_info; - files_struct **streams; + struct stream_struct *stream_info = NULL; + files_struct **streams = NULL; int i; - unsigned int num_streams; + unsigned int num_streams = 0; TALLOC_CTX *frame = talloc_stackframe(); NTSTATUS status; diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 114f688..ffa7309 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -4673,8 +4673,8 @@ NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn, */ case SMB_QUERY_FILE_STREAM_INFO: case SMB_FILE_STREAM_INFORMATION: { - unsigned int num_streams; - struct stream_struct *streams; + unsigned int num_streams = 0; + struct stream_struct *streams = NULL; DEBUG(10,("smbd_do_qfilepathinfo: " "SMB_FILE_STREAM_INFORMATION\n")); -- 1.7.3.1 From 71dbf6c9842a99b540cf5e18c83f5e9342f41a0c Mon Sep 17 00:00:00 2001 From: Frank Lahm Date: Mon, 17 Oct 2011 11:10:29 -0700 Subject: [PATCH 2/2] First part of fix for bug #8419 - Make VFS op "streaminfo" stackable. Autobuild-User: Jeremy Allison Autobuild-Date: Mon Oct 17 21:39:32 CEST 2011 on sn-devel-104 (cherry picked from commit c3bdcab5161107be8155a7913d9cb325383a781d) --- source3/lib/filename_util.c | 2 +- source3/smbd/close.c | 6 +++--- source3/smbd/filename.c | 4 ++-- source3/smbd/nttrans.c | 4 ++-- source3/smbd/open.c | 6 +++--- source3/smbd/proto.h | 6 ++++++ source3/smbd/trans2.c | 5 ++--- source3/smbd/vfs.c | 15 +++++++++++++++ 8 files changed, 34 insertions(+), 14 deletions(-) diff --git a/source3/lib/filename_util.c b/source3/lib/filename_util.c index aad8a08..e22a97a 100644 --- a/source3/lib/filename_util.c +++ b/source3/lib/filename_util.c @@ -47,7 +47,7 @@ NTSTATUS get_full_smb_filename(TALLOC_CTX *ctx, /** * There are actually legitimate callers of this such as functions that - * enumerate streams using the SMB_VFS_STREAMINFO interface and then want to + * enumerate streams using the vfs_streaminfo interface and then want to * operate on each stream. */ NTSTATUS create_synthetic_smb_fname(TALLOC_CTX *ctx, const char *base_name, diff --git a/source3/smbd/close.c b/source3/smbd/close.c index 603cfff..25c8b46 100644 --- a/source3/smbd/close.c +++ b/source3/smbd/close.c @@ -207,8 +207,8 @@ NTSTATUS delete_all_streams(connection_struct *conn, const char *fname) TALLOC_CTX *frame = talloc_stackframe(); NTSTATUS status; - status = SMB_VFS_STREAMINFO(conn, NULL, fname, talloc_tos(), - &num_streams, &stream_info); + status = vfs_streaminfo(conn, NULL, fname, talloc_tos(), + &num_streams, &stream_info); if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_IMPLEMENTED)) { DEBUG(10, ("no streams around\n")); @@ -217,7 +217,7 @@ NTSTATUS delete_all_streams(connection_struct *conn, const char *fname) } if (!NT_STATUS_IS_OK(status)) { - DEBUG(10, ("SMB_VFS_STREAMINFO failed: %s\n", + DEBUG(10, ("vfs_streaminfo failed: %s\n", nt_errstr(status))); goto fail; } diff --git a/source3/smbd/filename.c b/source3/smbd/filename.c index ec9ca20..25301e6 100644 --- a/source3/smbd/filename.c +++ b/source3/smbd/filename.c @@ -1185,8 +1185,8 @@ static NTSTATUS build_stream_path(TALLOC_CTX *mem_ctx, } /* Fall back to a case-insensitive scan of all streams on the file. */ - status = SMB_VFS_STREAMINFO(conn, NULL, smb_fname->base_name, mem_ctx, - &num_streams, &streams); + status = vfs_streaminfo(conn, NULL, smb_fname->base_name, mem_ctx, + &num_streams, &streams); if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) { SET_STAT_INVALID(smb_fname->st); diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index 8f5a4c5..81e850c 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -702,7 +702,7 @@ void reply_ntcreate_and_X(struct smb_request *req) if (NT_STATUS_IS_OK(status) && num_names) { file_status &= ~NO_EAS; } - status = SMB_VFS_STREAMINFO(conn, NULL, smb_fname->base_name, ctx, + status = vfs_streaminfo(conn, NULL, smb_fname->base_name, ctx, &num_streams, &streams); /* There is always one stream, ::$DATA. */ if (NT_STATUS_IS_OK(status) && num_streams > 1) { @@ -1283,7 +1283,7 @@ static void call_nt_transact_create(connection_struct *conn, if (NT_STATUS_IS_OK(status) && num_names) { file_status &= ~NO_EAS; } - status = SMB_VFS_STREAMINFO(conn, NULL, smb_fname->base_name, ctx, + status = vfs_streaminfo(conn, NULL, smb_fname->base_name, ctx, &num_streams, &streams); /* There is always one stream, ::$DATA. */ if (NT_STATUS_IS_OK(status) && num_streams > 1) { diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 0813496..09716d9 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -2974,8 +2974,8 @@ NTSTATUS open_streams_for_delete(connection_struct *conn, TALLOC_CTX *frame = talloc_stackframe(); NTSTATUS status; - status = SMB_VFS_STREAMINFO(conn, NULL, fname, talloc_tos(), - &num_streams, &stream_info); + status = vfs_streaminfo(conn, NULL, fname, talloc_tos(), + &num_streams, &stream_info); if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_IMPLEMENTED) || NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) { @@ -2985,7 +2985,7 @@ NTSTATUS open_streams_for_delete(connection_struct *conn, } if (!NT_STATUS_IS_OK(status)) { - DEBUG(10, ("SMB_VFS_STREAMINFO failed: %s\n", + DEBUG(10, ("vfs_streaminfo failed: %s\n", nt_errstr(status))); goto fail; } diff --git a/source3/smbd/proto.h b/source3/smbd/proto.h index 6cbbcfa..c455ffe 100644 --- a/source3/smbd/proto.h +++ b/source3/smbd/proto.h @@ -1167,6 +1167,12 @@ int vfs_lstat_smb_fname(struct connection_struct *conn, const char *fname, SMB_STRUCT_STAT *psbuf); NTSTATUS vfs_stat_fsp(files_struct *fsp); NTSTATUS vfs_chown_fsp(files_struct *fsp, uid_t uid, gid_t gid); +NTSTATUS vfs_streaminfo(connection_struct *conn, + struct files_struct *fsp, + const char *fname, + TALLOC_CTX *mem_ctx, + unsigned int *num_streams, + struct stream_struct **streams); /* The following definitions come from smbd/avahi_register.c */ diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index ffa7309..0931fff 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -4683,9 +4683,8 @@ NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn, return NT_STATUS_INVALID_PARAMETER; } - status = SMB_VFS_STREAMINFO( - conn, fsp, smb_fname->base_name, talloc_tos(), - &num_streams, &streams); + status = vfs_streaminfo(conn, fsp, smb_fname->base_name, + talloc_tos(), &num_streams, &streams); if (!NT_STATUS_IS_OK(status)) { DEBUG(10, ("could not get stream info: %s\n", diff --git a/source3/smbd/vfs.c b/source3/smbd/vfs.c index 35a8331..6c56964 100644 --- a/source3/smbd/vfs.c +++ b/source3/smbd/vfs.c @@ -1125,6 +1125,21 @@ NTSTATUS vfs_stat_fsp(files_struct *fsp) return NT_STATUS_OK; } +/** + * Initialize num_streams and streams, then call VFS op streaminfo + */ +NTSTATUS vfs_streaminfo(connection_struct *conn, + struct files_struct *fsp, + const char *fname, + TALLOC_CTX *mem_ctx, + unsigned int *num_streams, + struct stream_struct **streams) +{ + *num_streams = 0; + *streams = NULL; + return SMB_VFS_STREAMINFO(conn, fsp, fname, mem_ctx, num_streams, streams); +} + /* generate a file_id from a stat structure */ -- 1.7.3.1