]> git.ipfire.org Git - thirdparty/samba.git/commitdiff
s3/lib: add parent_smb_fname()
authorRalph Boehme <slow@samba.org>
Tue, 28 Apr 2020 10:55:26 +0000 (12:55 +0200)
committerJeremy Allison <jra@samba.org>
Wed, 29 Apr 2020 16:39:39 +0000 (16:39 +0000)
Signed-off-by: Ralph Boehme <slow@samba.org>
Reviewed-by: Jeremy Allison <jra@samba.org>
source3/include/proto.h
source3/lib/filename_util.c

index 6ac0c3d1935087773420af50d952235b9c3245b7..0fd6e64fee397f97bcc0669265f18143566d99a0 100644 (file)
@@ -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);
index 1f2e4d31072fc8541bcbab411a8a3dabae3cb0af..64677e54e3bdcb681d6d53424a730636c34e200b 100644 (file)
@@ -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. */