From 161e182b65ceda833e0bebc48ef404cdd399f8d7 Mon Sep 17 00:00:00 2001 From: Tim Prouty Date: Wed, 8 Jul 2009 14:08:04 -0700 Subject: s3: Remove is_ntfs_stream_name() and split_ntfs_stream_name() Actually I moved split_ntfs_stream_name into torture.c which is the one consumer of it. This could probably be changed at some point. --- source3/include/proto.h | 3 -- source3/lib/util.c | 90 ------------------------------------- source3/modules/onefs_streams.c | 48 -------------------- source3/modules/vfs_streams_xattr.c | 21 +++++---- source3/smbd/nttrans.c | 49 +------------------- source3/smbd/trans2.c | 3 +- source3/torture/torture.c | 90 +++++++++++++++++++++++++++++++++++++ 7 files changed, 105 insertions(+), 199 deletions(-) diff --git a/source3/include/proto.h b/source3/include/proto.h index 471084c264..aaedc15726 100644 --- a/source3/include/proto.h +++ b/source3/include/proto.h @@ -1202,8 +1202,6 @@ void *_talloc_memdup_zeronull(const void *t, const void *p, size_t size, const c void *_talloc_array_zeronull(const void *ctx, size_t el_size, unsigned count, const char *name); void *_talloc_zero_array_zeronull(const void *ctx, size_t el_size, unsigned count, const char *name); void *talloc_zeronull(const void *context, size_t size, const char *name); -NTSTATUS split_ntfs_stream_name(TALLOC_CTX *mem_ctx, const char *fname, - char **pbase, char **pstream); bool is_valid_policy_hnd(const struct policy_handle *hnd); bool policy_hnd_equal(const struct policy_handle *hnd1, const struct policy_handle *hnd2); @@ -6548,7 +6546,6 @@ void send_nt_replies(connection_struct *conn, struct smb_request *req, NTSTATUS nt_error, char *params, int paramsize, 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); diff --git a/source3/lib/util.c b/source3/lib/util.c index 77af939f37..835e4c00da 100644 --- a/source3/lib/util.c +++ b/source3/lib/util.c @@ -3001,96 +3001,6 @@ void *talloc_zeronull(const void *context, size_t size, const char *name) } #endif -/* Split a path name into filename and stream name components. Canonicalise - * such that an implicit $DATA token is always explicit. - * - * The "specification" of this function can be found in the - * run_local_stream_name() function in torture.c, I've tried those - * combinations against a W2k3 server. - */ - -NTSTATUS split_ntfs_stream_name(TALLOC_CTX *mem_ctx, const char *fname, - char **pbase, char **pstream) -{ - char *base = NULL; - char *stream = NULL; - char *sname; /* stream name */ - const char *stype; /* stream type */ - - DEBUG(10, ("split_ntfs_stream_name called for [%s]\n", fname)); - - sname = strchr_m(fname, ':'); - - if (lp_posix_pathnames() || (sname == NULL)) { - if (pbase != NULL) { - base = talloc_strdup(mem_ctx, fname); - NT_STATUS_HAVE_NO_MEMORY(base); - } - goto done; - } - - if (pbase != NULL) { - base = talloc_strndup(mem_ctx, fname, PTR_DIFF(sname, fname)); - NT_STATUS_HAVE_NO_MEMORY(base); - } - - sname += 1; - - stype = strchr_m(sname, ':'); - - if (stype == NULL) { - sname = talloc_strdup(mem_ctx, sname); - stype = "$DATA"; - } - else { - if (StrCaseCmp(stype, ":$DATA") != 0) { - /* - * If there is an explicit stream type, so far we only - * allow $DATA. Is there anything else allowed? -- vl - */ - DEBUG(10, ("[%s] is an invalid stream type\n", stype)); - TALLOC_FREE(base); - return NT_STATUS_OBJECT_NAME_INVALID; - } - sname = talloc_strndup(mem_ctx, sname, PTR_DIFF(stype, sname)); - stype += 1; - } - - if (sname == NULL) { - TALLOC_FREE(base); - return NT_STATUS_NO_MEMORY; - } - - if (sname[0] == '\0') { - /* - * no stream name, so no stream - */ - goto done; - } - - if (pstream != NULL) { - stream = talloc_asprintf(mem_ctx, "%s:%s", sname, stype); - if (stream == NULL) { - TALLOC_FREE(sname); - TALLOC_FREE(base); - return NT_STATUS_NO_MEMORY; - } - /* - * upper-case the type field - */ - strupper_m(strchr_m(stream, ':')+1); - } - - done: - if (pbase != NULL) { - *pbase = base; - } - if (pstream != NULL) { - *pstream = stream; - } - return NT_STATUS_OK; -} - bool is_valid_policy_hnd(const struct policy_handle *hnd) { struct policy_handle tmp; diff --git a/source3/modules/onefs_streams.c b/source3/modules/onefs_streams.c index d33d9f30a2..ded7dc672d 100644 --- a/source3/modules/onefs_streams.c +++ b/source3/modules/onefs_streams.c @@ -25,35 +25,6 @@ #include -/* - * OneFS stores streams without the explicit :$DATA at the end, so this strips - * it off. All onefs_stream functions must call through this instead of - * split_ntfs_stream_name directly. - */ -NTSTATUS onefs_split_ntfs_stream_name(TALLOC_CTX *mem_ctx, const char *fname, - char **pbase, char **pstream) -{ - NTSTATUS status; - char *stream; - - status = split_ntfs_stream_name(mem_ctx, fname, pbase, pstream); - if (!NT_STATUS_IS_OK(status)) { - return status; - } - - /* Default $DATA stream. */ - if (pstream == NULL || *pstream == NULL) { - return NT_STATUS_OK; - } - - /* Strip off the $DATA. */ - stream = strrchr_m(*pstream, ':'); - SMB_ASSERT(stream); - stream[0] = '\0'; - - return NT_STATUS_OK; -} - NTSTATUS onefs_stream_prep_smb_fname(TALLOC_CTX *ctx, const struct smb_filename *smb_fname_in, struct smb_filename **smb_fname_out) @@ -100,25 +71,6 @@ NTSTATUS onefs_stream_prep_smb_fname(TALLOC_CTX *ctx, return status; } -int onefs_is_stream(const char *path, char **pbase, char **pstream, - bool *is_stream) -{ - (*is_stream) = is_ntfs_stream_name(path); - - if (!(*is_stream)) { - return 0; - } - - if (!NT_STATUS_IS_OK(onefs_split_ntfs_stream_name(talloc_tos(), path, - pbase, pstream))) { - DEBUG(10, ("onefs_split_ntfs_stream_name failed\n")); - errno = ENOMEM; - return -1; - } - - return 0; -} - int onefs_close(vfs_handle_struct *handle, struct files_struct *fsp) { int ret2, ret = 0; diff --git a/source3/modules/vfs_streams_xattr.c b/source3/modules/vfs_streams_xattr.c index 74b14ff93f..eccc2379c9 100644 --- a/source3/modules/vfs_streams_xattr.c +++ b/source3/modules/vfs_streams_xattr.c @@ -128,29 +128,29 @@ static NTSTATUS streams_xattr_get_name(TALLOC_CTX *ctx, static bool streams_xattr_recheck(struct stream_io *sio) { NTSTATUS status; - char *base = NULL; - char *sname = NULL; + struct smb_filename *smb_fname = NULL; char *xattr_name = NULL; if (sio->fsp->fsp_name == sio->fsp_name_ptr) { return true; } - status = split_ntfs_stream_name(talloc_tos(), sio->fsp->fsp_name, - &base, &sname); + status = create_synthetic_smb_fname_split(talloc_tos(), + sio->fsp->fsp_name, NULL, + &smb_fname); if (!NT_STATUS_IS_OK(status)) { return false; } - if (sname == NULL) { + if (smb_fname->stream_name == NULL) { /* how can this happen */ errno = EINVAL; return false; } - xattr_name = talloc_asprintf(talloc_tos(), "%s%s", - SAMBA_XATTR_DOSSTREAM_PREFIX, sname); - if (xattr_name == NULL) { + status = streams_xattr_get_name(talloc_tos(), smb_fname->stream_name, + &xattr_name); + if (!NT_STATUS_IS_OK(status)) { return false; } @@ -159,9 +159,12 @@ static bool streams_xattr_recheck(struct stream_io *sio) sio->xattr_name = talloc_strdup(VFS_MEMCTX_FSP_EXTENSION(sio->handle, sio->fsp), xattr_name); sio->base = talloc_strdup(VFS_MEMCTX_FSP_EXTENSION(sio->handle, sio->fsp), - base); + smb_fname->base_name); sio->fsp_name_ptr = sio->fsp->fsp_name; + TALLOC_FREE(smb_fname); + TALLOC_FREE(xattr_name); + if ((sio->xattr_name == NULL) || (sio->base == NULL)) { return false; } diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index e28e6f3a84..b65af26eca 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -271,53 +271,6 @@ void send_nt_replies(connection_struct *conn, } } -/**************************************************************************** - Is it an NTFS stream name ? - An NTFS file name is .:: - $DATA can be used as both a stream name and a stream type. A missing stream - name or type implies $DATA. - - Both Windows stream names and POSIX files can contain the ':' character. - This function first checks for the existence of a colon in the last component - of the given name. If the name contains a colon we differentiate between a - stream and POSIX file by checking if the latter exists through a POSIX stat. - - Function assumes we've already chdir() to the "root" directory of fname. -****************************************************************************/ - -bool is_ntfs_stream_name(const char *fname) -{ - const char *lastcomp; - SMB_STRUCT_STAT sbuf; - - /* If all pathnames are treated as POSIX we ignore streams. */ - if (lp_posix_pathnames()) { - return false; - } - - /* Find the last component of the name. */ - if ((lastcomp = strrchr_m(fname, '/')) != NULL) - ++lastcomp; - else - lastcomp = fname; - - /* If there is no colon in the last component, it's not a stream. */ - if (strchr_m(lastcomp, ':') == NULL) - return false; - - /* - * If file already exists on disk, it's not a stream. The stat must - * bypass the vfs layer so streams modules don't intefere. - */ - if (sys_stat(fname, &sbuf) == 0) { - DEBUG(5, ("is_ntfs_stream_name: file %s contains a ':' but is " - "not a stream\n", fname)); - return false; - } - - return true; -} - /**************************************************************************** Simple check to determine if the filename is a stream. ***************************************************************************/ @@ -1454,7 +1407,7 @@ void reply_ntrename(struct smb_request *req) } /* The new name must begin with a ':' if the old name is a stream. */ - if (is_ntfs_stream_name(oldname) && (newname[0] != ':')) { + if (is_ntfs_stream_smb_fname(smb_fname_old) && (newname[0] != ':')) { reply_nterror(req, NT_STATUS_INVALID_PARAMETER); END_PROFILE(SMBntrename); return; diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 62280ddde0..f22700deaa 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -1421,6 +1421,7 @@ static bool get_lanman2_dir_entry(TALLOC_CTX *ctx, &smb_fname); if (!NT_STATUS_IS_OK(status)) { TALLOC_FREE(fname); + return false; } if (INFO_LEVEL_IS_UNIX(info_level)) { @@ -5554,7 +5555,7 @@ static NTSTATUS smb_file_rename_information(connection_struct *conn, } } else { /* newname must *not* be a stream name. */ - if (is_ntfs_stream_name(newname)) { + if (newname[0] == ':') { return NT_STATUS_NOT_SUPPORTED; } diff --git a/source3/torture/torture.c b/source3/torture/torture.c index 012f8939c5..aa7e83bcc8 100644 --- a/source3/torture/torture.c +++ b/source3/torture/torture.c @@ -5939,6 +5939,96 @@ static bool run_local_rbtree(int dummy) return ret; } +/* Split a path name into filename and stream name components. Canonicalise + * such that an implicit $DATA token is always explicit. + * + * The "specification" of this function can be found in the + * run_local_stream_name() function in torture.c, I've tried those + * combinations against a W2k3 server. + */ + +static NTSTATUS split_ntfs_stream_name(TALLOC_CTX *mem_ctx, const char *fname, + char **pbase, char **pstream) +{ + char *base = NULL; + char *stream = NULL; + char *sname; /* stream name */ + const char *stype; /* stream type */ + + DEBUG(10, ("split_ntfs_stream_name called for [%s]\n", fname)); + + sname = strchr_m(fname, ':'); + + if (lp_posix_pathnames() || (sname == NULL)) { + if (pbase != NULL) { + base = talloc_strdup(mem_ctx, fname); + NT_STATUS_HAVE_NO_MEMORY(base); + } + goto done; + } + + if (pbase != NULL) { + base = talloc_strndup(mem_ctx, fname, PTR_DIFF(sname, fname)); + NT_STATUS_HAVE_NO_MEMORY(base); + } + + sname += 1; + + stype = strchr_m(sname, ':'); + + if (stype == NULL) { + sname = talloc_strdup(mem_ctx, sname); + stype = "$DATA"; + } + else { + if (StrCaseCmp(stype, ":$DATA") != 0) { + /* + * If there is an explicit stream type, so far we only + * allow $DATA. Is there anything else allowed? -- vl + */ + DEBUG(10, ("[%s] is an invalid stream type\n", stype)); + TALLOC_FREE(base); + return NT_STATUS_OBJECT_NAME_INVALID; + } + sname = talloc_strndup(mem_ctx, sname, PTR_DIFF(stype, sname)); + stype += 1; + } + + if (sname == NULL) { + TALLOC_FREE(base); + return NT_STATUS_NO_MEMORY; + } + + if (sname[0] == '\0') { + /* + * no stream name, so no stream + */ + goto done; + } + + if (pstream != NULL) { + stream = talloc_asprintf(mem_ctx, "%s:%s", sname, stype); + if (stream == NULL) { + TALLOC_FREE(sname); + TALLOC_FREE(base); + return NT_STATUS_NO_MEMORY; + } + /* + * upper-case the type field + */ + strupper_m(strchr_m(stream, ':')+1); + } + + done: + if (pbase != NULL) { + *pbase = base; + } + if (pstream != NULL) { + *pstream = stream; + } + return NT_STATUS_OK; +} + static bool test_stream_name(const char *fname, const char *expected_base, const char *expected_stream, NTSTATUS expected_status) -- cgit