From 5fe180e751093bb10f847137f879a961db245689 Mon Sep 17 00:00:00 2001 From: Ralph Boehme Date: Tue, 28 Apr 2020 12:55:26 +0200 Subject: [PATCH] s3/lib: add parent_smb_fname() Signed-off-by: Ralph Boehme Reviewed-by: Jeremy Allison --- source3/include/proto.h | 4 +++ source3/lib/filename_util.c | 63 +++++++++++++++++++++++++++++++++++++ 2 files changed, 67 insertions(+) diff --git a/source3/include/proto.h b/source3/include/proto.h index 6ac0c3d1935..0fd6e64fee3 100644 --- a/source3/include/proto.h +++ b/source3/include/proto.h @@ -392,6 +392,10 @@ char *myhostname_upper(void); #include "lib/util_path.h" bool parent_dirname(TALLOC_CTX *mem_ctx, const char *dir, char **parent, const char **name); +bool parent_smb_fname(TALLOC_CTX *mem_ctx, + const struct smb_filename *path, + struct smb_filename **_parent, + struct smb_filename **_name); bool ms_has_wild(const char *s); bool ms_has_wild_w(const smb_ucs2_t *s); bool mask_match(const char *string, const char *pattern, bool is_case_sensitive); diff --git a/source3/lib/filename_util.c b/source3/lib/filename_util.c index 1f2e4d31072..64677e54e3b 100644 --- a/source3/lib/filename_util.c +++ b/source3/lib/filename_util.c @@ -228,6 +228,69 @@ struct smb_filename *cp_smb_filename(TALLOC_CTX *mem_ctx, return out; } +/** + * Return allocated parent directory and basename of path + * + * Note: if requesting name, it is returned as talloc child of the + * parent. Freeing the parent is thus sufficient to free both. + */ +bool parent_smb_fname(TALLOC_CTX *mem_ctx, + const struct smb_filename *path, + struct smb_filename **_parent, + struct smb_filename **_name) +{ + TALLOC_CTX *frame = talloc_stackframe(); + struct smb_filename *parent = NULL; + struct smb_filename *name = NULL; + char *p = NULL; + + parent = cp_smb_filename(frame, path); + if (parent == NULL) { + TALLOC_FREE(frame); + return false; + } + TALLOC_FREE(parent->stream_name); + SET_STAT_INVALID(parent->st); + + p = strrchr_m(parent->base_name, '/'); /* Find final '/', if any */ + if (p == NULL) { + TALLOC_FREE(parent->base_name); + parent->base_name = talloc_strdup(parent, "."); + if (parent->base_name == NULL) { + TALLOC_FREE(frame); + return false; + } + p = path->base_name; + } else { + *p = '\0'; + p++; + } + + if (_name == NULL) { + *_parent = talloc_move(mem_ctx, &parent); + TALLOC_FREE(frame); + return true; + } + + name = cp_smb_filename(frame, path); + if (name == NULL) { + TALLOC_FREE(frame); + return false; + } + TALLOC_FREE(name->base_name); + + name->base_name = talloc_strdup(mem_ctx, p); + if (name == NULL) { + TALLOC_FREE(frame); + return false; + } + + *_parent = talloc_move(mem_ctx, &parent); + *_name = talloc_move(*_parent, &name); + TALLOC_FREE(frame); + return true; +} + static void assert_valid_stream_smb_fname(const struct smb_filename *smb_fname) { /* stream_name must always be NULL if there is no stream. */ -- 2.34.1