vfs_xattr_tdb: add a module config
authorRalph Boehme <slow@samba.org>
Wed, 27 Jul 2022 09:59:54 +0000 (11:59 +0200)
committerJule Anger <janger@samba.org>
Tue, 6 Sep 2022 07:54:13 +0000 (07:54 +0000)
BUG: https://bugzilla.samba.org/show_bug.cgi?id=15126
MR: https://gitlab.com/samba-team/samba/-/merge_requests/2643

Signed-off-by: Ralph Boehme <slow@samba.org>
Reviewed-by: Volker Lendecke <vl@samba.org>
(cherry picked from commit 451ad315a9bf32c627e1966ec30185542701c87e)

source3/modules/vfs_xattr_tdb.c

index 37d76e22ff63978475f48ff865ebe0c65f799b44..2492e6e5fdbc205921c1100632a83c18a761e69e 100644 (file)
 #undef DBGC_CLASS
 #define DBGC_CLASS DBGC_VFS
 
-static bool xattr_tdb_init(int snum, TALLOC_CTX *mem_ctx, struct db_context **p_db);
+struct xattr_tdb_config {
+       struct db_context *db;
+};
+
+static bool xattr_tdb_init(struct vfs_handle_struct *handle,
+                          struct xattr_tdb_config **_config);
 
 static int xattr_tdb_get_file_id(struct vfs_handle_struct *handle,
                                const char *path, struct file_id *id)
@@ -77,16 +82,20 @@ static struct tevent_req *xattr_tdb_getxattrat_send(
                        const char *xattr_name,
                        size_t alloc_hint)
 {
+       struct xattr_tdb_config *config = NULL;
        struct tevent_req *req = NULL;
        struct xattr_tdb_getxattrat_state *state = NULL;
        struct smb_filename *cwd = NULL;
-       struct db_context *db = NULL;
        struct file_id id;
        int ret;
        int error;
        int cwd_ret;
        DATA_BLOB xattr_blob;
 
+       if (!xattr_tdb_init(handle, &config)) {
+               return NULL;
+       }
+
        req = tevent_req_create(mem_ctx, &state,
                                struct xattr_tdb_getxattrat_state);
        if (req == NULL) {
@@ -94,11 +103,6 @@ static struct tevent_req *xattr_tdb_getxattrat_send(
        }
        state->xattr_size = -1;
 
-       SMB_VFS_HANDLE_GET_DATA(handle, db, struct db_context,
-                               if (!xattr_tdb_init(-1, state, &db)) {
-                                       tevent_req_error(req, EIO);
-                                       return tevent_req_post(req, ev);
-                               });
 
        cwd = SMB_VFS_GETWD(dir_fsp->conn, state);
        if (tevent_req_nomem(cwd, req)) {
@@ -122,7 +126,7 @@ static struct tevent_req *xattr_tdb_getxattrat_send(
                return tevent_req_post(req, ev);
        }
 
-       state->xattr_size = xattr_tdb_getattr(db,
+       state->xattr_size = xattr_tdb_getattr(config->db,
                                              state,
                                              &id,
                                              xattr_name,
@@ -194,27 +198,27 @@ static ssize_t xattr_tdb_fgetxattr(struct vfs_handle_struct *handle,
                                   struct files_struct *fsp,
                                   const char *name, void *value, size_t size)
 {
+       struct xattr_tdb_config *config = NULL;
        SMB_STRUCT_STAT sbuf;
        struct file_id id;
-       struct db_context *db;
        ssize_t xattr_size;
        DATA_BLOB blob;
-       TALLOC_CTX *frame = talloc_stackframe();
+       TALLOC_CTX *frame = NULL;
+
+       if (!xattr_tdb_init(handle, &config)) {
+               return -1;
+       }
 
-       SMB_VFS_HANDLE_GET_DATA(handle, db, struct db_context,
-                               if (!xattr_tdb_init(-1, frame, &db))
-                               {
-                                       TALLOC_FREE(frame); return -1;
-                               });
 
        if (SMB_VFS_NEXT_FSTAT(handle, fsp, &sbuf) == -1) {
-               TALLOC_FREE(frame);
                return -1;
        }
 
+       frame = talloc_stackframe();
+
        id = SMB_VFS_NEXT_FILE_ID_CREATE(handle, &sbuf);
 
-       xattr_size = xattr_tdb_getattr(db, frame, &id, name, &blob);
+       xattr_size = xattr_tdb_getattr(config->db, frame, &id, name, &blob);
        if (xattr_size < 0) {
                errno = ENOATTR;
                TALLOC_FREE(frame);
@@ -241,27 +245,22 @@ static int xattr_tdb_fsetxattr(struct vfs_handle_struct *handle,
                               const char *name, const void *value,
                               size_t size, int flags)
 {
+       struct xattr_tdb_config *config = NULL;
        SMB_STRUCT_STAT sbuf;
        struct file_id id;
-       struct db_context *db;
        int ret;
-       TALLOC_CTX *frame = talloc_stackframe();
 
-       SMB_VFS_HANDLE_GET_DATA(handle, db, struct db_context,
-                               if (!xattr_tdb_init(-1, frame, &db))
-                               {
-                                       TALLOC_FREE(frame); return -1;
-                               });
+       if (!xattr_tdb_init(handle, &config)) {
+               return -1;
+       }
 
        if (SMB_VFS_NEXT_FSTAT(handle, fsp, &sbuf) == -1) {
-               TALLOC_FREE(frame);
                return -1;
        }
 
        id = SMB_VFS_NEXT_FILE_ID_CREATE(handle, &sbuf);
 
-       ret = xattr_tdb_setattr(db, &id, name, value, size, flags);
-       TALLOC_FREE(frame);
+       ret = xattr_tdb_setattr(config->db, &id, name, value, size, flags);
        return ret;
 
 }
@@ -270,105 +269,120 @@ static ssize_t xattr_tdb_flistxattr(struct vfs_handle_struct *handle,
                                    struct files_struct *fsp, char *list,
                                    size_t size)
 {
+       struct xattr_tdb_config *config = NULL;
        SMB_STRUCT_STAT sbuf;
        struct file_id id;
-       struct db_context *db;
-       int ret;
-       TALLOC_CTX *frame = talloc_stackframe();
 
-       SMB_VFS_HANDLE_GET_DATA(handle, db, struct db_context,
-                               if (!xattr_tdb_init(-1, frame, &db))
-                               {
-                                       TALLOC_FREE(frame); return -1;
-                               });
+       if (!xattr_tdb_init(handle, &config)) {
+               return -1;
+       }
 
        if (SMB_VFS_NEXT_FSTAT(handle, fsp, &sbuf) == -1) {
-               TALLOC_FREE(frame);
                return -1;
        }
 
        id = SMB_VFS_NEXT_FILE_ID_CREATE(handle, &sbuf);
 
-       ret = xattr_tdb_listattr(db, &id, list, size);
-       TALLOC_FREE(frame);
-       return ret;
+       return xattr_tdb_listattr(config->db, &id, list, size);
 }
 
 static int xattr_tdb_fremovexattr(struct vfs_handle_struct *handle,
                                  struct files_struct *fsp, const char *name)
 {
+       struct xattr_tdb_config *config = NULL;
        SMB_STRUCT_STAT sbuf;
        struct file_id id;
-       struct db_context *db;
-       int ret;
-       TALLOC_CTX *frame = talloc_stackframe();
 
-       SMB_VFS_HANDLE_GET_DATA(handle, db, struct db_context,
-                               if (!xattr_tdb_init(-1, frame, &db))
-                               {
-                                       TALLOC_FREE(frame); return -1;
-                               });
+       if (!xattr_tdb_init(handle, &config)) {
+               return -1;
+       }
 
        if (SMB_VFS_NEXT_FSTAT(handle, fsp, &sbuf) == -1) {
-               TALLOC_FREE(frame);
                return -1;
        }
 
        id = SMB_VFS_NEXT_FILE_ID_CREATE(handle, &sbuf);
 
-       ret = xattr_tdb_removeattr(db, &id, name);
-       TALLOC_FREE(frame);
-       return ret;
+       return xattr_tdb_removeattr(config->db, &id, name);
 }
 
 /*
  * Destructor for the VFS private data
  */
 
-static void close_xattr_db(void **data)
+static void config_destructor(void **data)
 {
-       struct db_context **p_db = (struct db_context **)data;
-       TALLOC_FREE(*p_db);
+       struct xattr_tdb_config **config = (struct xattr_tdb_config **)data;
+       TALLOC_FREE((*config)->db);
 }
 
 /*
  * Open the tdb file upon VFS_CONNECT
  */
 
-static bool xattr_tdb_init(int snum, TALLOC_CTX *mem_ctx, struct db_context **p_db)
+static bool xattr_tdb_init(struct vfs_handle_struct *handle,
+                          struct xattr_tdb_config **_config)
 {
-       struct db_context *db;
+       struct xattr_tdb_config *config = NULL;
        const char *dbname;
        char *def_dbname;
 
+       if (SMB_VFS_HANDLE_TEST_DATA(handle)) {
+               SMB_VFS_HANDLE_GET_DATA(handle, config, struct xattr_tdb_config,
+                                       return false);
+               if (_config != NULL) {
+                       *_config = config;
+               }
+               return true;
+       }
+
+       config = talloc_zero(handle->conn, struct xattr_tdb_config);
+       if (config == NULL) {
+               errno = ENOMEM;
+               goto error;
+       }
+
        def_dbname = state_path(talloc_tos(), "xattr.tdb");
        if (def_dbname == NULL) {
                errno = ENOSYS;
-               return false;
+               goto error;
        }
 
-       dbname = lp_parm_const_string(snum, "xattr_tdb", "file", def_dbname);
+       dbname = lp_parm_const_string(SNUM(handle->conn),
+                                     "xattr_tdb",
+                                     "file",
+                                     def_dbname);
 
        /* now we know dbname is not NULL */
 
        become_root();
-       db = db_open(NULL, dbname, 0, TDB_DEFAULT, O_RDWR|O_CREAT, 0600,
-                    DBWRAP_LOCK_ORDER_2, DBWRAP_FLAG_NONE);
+       config->db = db_open(handle, dbname, 0, TDB_DEFAULT, O_RDWR|O_CREAT, 0600,
+                            DBWRAP_LOCK_ORDER_2, DBWRAP_FLAG_NONE);
        unbecome_root();
 
-       if (db == NULL) {
+       if (config->db == NULL) {
 #if defined(ENOTSUP)
                errno = ENOTSUP;
 #else
                errno = ENOSYS;
 #endif
                TALLOC_FREE(def_dbname);
-               return false;
+               goto error;
        }
-
-       *p_db = db;
        TALLOC_FREE(def_dbname);
+
+       SMB_VFS_HANDLE_SET_DATA(handle, config, config_destructor,
+                               struct xattr_tdb_config, return false);
+
+       if (_config != NULL) {
+               *_config = config;
+       }
        return true;
+
+error:
+       DBG_WARNING("Failed to initialize config: %s\n", strerror(errno));
+       lp_do_parameter(SNUM(handle->conn), "ea support", "False");
+       return false;
 }
 
 static int xattr_tdb_openat(struct vfs_handle_struct *handle,
@@ -378,12 +392,15 @@ static int xattr_tdb_openat(struct vfs_handle_struct *handle,
                            int flags,
                            mode_t mode)
 {
-       struct db_context *db = NULL;
-       TALLOC_CTX *frame = NULL;
+       struct xattr_tdb_config *config = NULL;
        SMB_STRUCT_STAT sbuf;
        int fd;
        int ret;
 
+       if (!xattr_tdb_init(handle, &config)) {
+               return -1;
+       }
+
        fd = SMB_VFS_NEXT_OPENAT(handle,
                                 dirfsp,
                                 smb_fname,
@@ -417,17 +434,8 @@ static int xattr_tdb_openat(struct vfs_handle_struct *handle,
 
        fsp->file_id = SMB_VFS_FILE_ID_CREATE(fsp->conn, &sbuf);
 
-       frame = talloc_stackframe();
-
-       SMB_VFS_HANDLE_GET_DATA(handle, db, struct db_context,
-                               if (!xattr_tdb_init(-1, frame, &db))
-                               {
-                                       TALLOC_FREE(frame); return -1;
-                               });
-
-       xattr_tdb_remove_all_attrs(db, &fsp->file_id);
+       xattr_tdb_remove_all_attrs(config->db, &fsp->file_id);
 
-       TALLOC_FREE(frame);
        return fd;
 }
 
@@ -436,12 +444,16 @@ static int xattr_tdb_mkdirat(vfs_handle_struct *handle,
                const struct smb_filename *smb_fname,
                mode_t mode)
 {
-       struct db_context *db = NULL;
+       struct xattr_tdb_config *config = NULL;
        TALLOC_CTX *frame = NULL;
        struct file_id fileid;
        int ret;
        struct smb_filename *full_fname = NULL;
 
+       if (!xattr_tdb_init(handle, &config)) {
+               return -1;
+       }
+
        ret = SMB_VFS_NEXT_MKDIRAT(handle,
                                dirfsp,
                                smb_fname,
@@ -475,13 +487,7 @@ static int xattr_tdb_mkdirat(vfs_handle_struct *handle,
 
        fileid = SMB_VFS_FILE_ID_CREATE(handle->conn, &full_fname->st);
 
-       SMB_VFS_HANDLE_GET_DATA(handle, db, struct db_context,
-                               if (!xattr_tdb_init(-1, frame, &db))
-                               {
-                                       TALLOC_FREE(frame); return -1;
-                               });
-
-       xattr_tdb_remove_all_attrs(db, &fileid);
+       xattr_tdb_remove_all_attrs(config->db, &fileid);
        TALLOC_FREE(frame);
        return 0;
 }
@@ -494,19 +500,19 @@ static int xattr_tdb_unlinkat(vfs_handle_struct *handle,
                        const struct smb_filename *smb_fname,
                        int flags)
 {
+       struct xattr_tdb_config *config = NULL;
        struct smb_filename *smb_fname_tmp = NULL;
        struct smb_filename *full_fname = NULL;
        struct file_id id;
-       struct db_context *db;
        int ret = -1;
        bool remove_record = false;
-       TALLOC_CTX *frame = talloc_stackframe();
+       TALLOC_CTX *frame = NULL;
+
+       if (!xattr_tdb_init(handle, &config)) {
+               return -1;
+       }
 
-       SMB_VFS_HANDLE_GET_DATA(handle, db, struct db_context,
-                               if (!xattr_tdb_init(-1, frame, &db))
-                               {
-                                       TALLOC_FREE(frame); return -1;
-                               });
+       frame = talloc_stackframe();
 
        smb_fname_tmp = cp_smb_filename(frame, smb_fname);
        if (smb_fname_tmp == NULL) {
@@ -571,7 +577,7 @@ static int xattr_tdb_unlinkat(vfs_handle_struct *handle,
 
        id = SMB_VFS_NEXT_FILE_ID_CREATE(handle, &smb_fname_tmp->st);
 
-       xattr_tdb_remove_all_attrs(db, &id);
+       xattr_tdb_remove_all_attrs(config->db, &id);
 
  out:
        TALLOC_FREE(frame);
@@ -583,7 +589,6 @@ static int xattr_tdb_connect(vfs_handle_struct *handle, const char *service,
 {
        char *sname = NULL;
        int res, snum;
-       struct db_context *db;
 
        res = SMB_VFS_NEXT_CONNECT(handle, service, user);
        if (res < 0) {
@@ -598,7 +603,7 @@ static int xattr_tdb_connect(vfs_handle_struct *handle, const char *service,
                return 0;
        }
 
-       if (!xattr_tdb_init(snum, NULL, &db)) {
+       if (!xattr_tdb_init(handle, NULL)) {
                DEBUG(5, ("Could not init xattr tdb\n"));
                lp_do_parameter(snum, "ea support", "False");
                return 0;
@@ -606,9 +611,6 @@ static int xattr_tdb_connect(vfs_handle_struct *handle, const char *service,
 
        lp_do_parameter(snum, "ea support", "True");
 
-       SMB_VFS_HANDLE_SET_DATA(handle, db, close_xattr_db,
-                               struct db_context, return -1);
-
        return 0;
 }