lib: modules: Change XXX_init interface from XXX_init(void) to XXX_init(TALLOC_CTX *)
[kai/samba-autobuild/.git] / source3 / modules / vfs_xattr_tdb.c
index 939be825c53eab38b5cbbc672843e5b748f8b0d8..12ccbca59200671fa583ab055ebc807f3b76a2c0 100644 (file)
@@ -35,12 +35,12 @@ static int xattr_tdb_get_file_id(struct vfs_handle_struct *handle,
 {
        int ret;
        TALLOC_CTX *frame = talloc_stackframe();
-       struct smb_filename *smb_fname = NULL;
-       NTSTATUS status = create_synthetic_smb_fname_split(frame, path, NULL,
-                                                 &smb_fname);
-       if (!NT_STATUS_IS_OK(status)) {
-               errno = map_errno_from_nt_status(status);
-               TALLOC_FREE(frame); 
+       struct smb_filename *smb_fname;
+
+       smb_fname = synthetic_smb_fname(frame, path, NULL, NULL, 0);
+       if (smb_fname == NULL) {
+               TALLOC_FREE(frame);
+               errno = ENOMEM;
                return -1;
        }
 
@@ -85,6 +85,12 @@ static ssize_t xattr_tdb_getxattr(struct vfs_handle_struct *handle,
                TALLOC_FREE(frame);
                return -1;
        }
+
+       if (size == 0) {
+               TALLOC_FREE(frame);
+               return xattr_size;
+       }
+
        if (blob.length > size) {
                TALLOC_FREE(frame);
                errno = ERANGE;
@@ -125,6 +131,12 @@ static ssize_t xattr_tdb_fgetxattr(struct vfs_handle_struct *handle,
                TALLOC_FREE(frame);
                return -1;
        }
+
+       if (size == 0) {
+               TALLOC_FREE(frame);
+               return xattr_size;
+       }
+
        if (blob.length > size) {
                TALLOC_FREE(frame);
                errno = ERANGE;
@@ -320,7 +332,7 @@ static bool xattr_tdb_init(int snum, TALLOC_CTX *mem_ctx, struct db_context **p_
 
        become_root();
        db = db_open(NULL, dbname, 0, TDB_DEFAULT, O_RDWR|O_CREAT, 0600,
-                    DBWRAP_LOCK_ORDER_2);
+                    DBWRAP_LOCK_ORDER_2, DBWRAP_FLAG_NONE);
        unbecome_root();
 
        if (db == NULL) {
@@ -338,6 +350,105 @@ static bool xattr_tdb_init(int snum, TALLOC_CTX *mem_ctx, struct db_context **p_
        return true;
 }
 
+static int xattr_tdb_open(vfs_handle_struct *handle,
+                       struct smb_filename *smb_fname,
+                       files_struct *fsp,
+                       int flags,
+                       mode_t mode)
+{
+       struct db_context *db = NULL;
+       TALLOC_CTX *frame = NULL;
+       int ret;
+
+       fsp->fh->fd = SMB_VFS_NEXT_OPEN(handle,
+                               smb_fname, fsp,
+                               flags,
+                               mode);
+
+       if (fsp->fh->fd < 0) {
+               return fsp->fh->fd;
+       }
+
+       if ((flags & (O_CREAT|O_EXCL)) != (O_CREAT|O_EXCL)) {
+               return fsp->fh->fd;
+       }
+
+       /*
+        * We know we used O_CREAT|O_EXCL and it worked.
+        * We must have created the file.
+        */
+
+       ret = SMB_VFS_FSTAT(fsp, &smb_fname->st);
+       if (ret == -1) {
+               /* Can't happen... */
+               DBG_WARNING("SMB_VFS_FSTAT failed on file %s (%s)\n",
+                       smb_fname_str_dbg(smb_fname),
+                       strerror(errno));
+               return -1;
+       }
+       fsp->file_id = SMB_VFS_FILE_ID_CREATE(fsp->conn, &smb_fname->st);
+
+       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);
+       TALLOC_FREE(frame);
+       return fsp->fh->fd;
+}
+
+static int xattr_tdb_mkdir(vfs_handle_struct *handle,
+               const struct smb_filename *smb_fname,
+               mode_t mode)
+{
+       struct db_context *db = NULL;
+       TALLOC_CTX *frame = NULL;
+       struct file_id fileid;
+       int ret;
+       struct smb_filename *smb_fname_tmp = NULL;
+
+       ret = SMB_VFS_NEXT_MKDIR(handle, smb_fname, mode);
+       if (ret < 0) {
+               return ret;
+       }
+
+       frame = talloc_stackframe();
+       smb_fname_tmp = cp_smb_filename(frame, smb_fname);
+       if (smb_fname_tmp == NULL) {
+               TALLOC_FREE(frame);
+               errno = ENOMEM;
+               return -1;
+       }
+
+       /* Always use LSTAT here - we just creaded the directory. */
+       ret = SMB_VFS_LSTAT(handle->conn, smb_fname_tmp);
+       if (ret == -1) {
+               /* Rename race. Let upper level take care of it. */
+               TALLOC_FREE(frame);
+               return -1;
+       }
+       if (!S_ISDIR(smb_fname_tmp->st.st_ex_mode)) {
+               /* Rename race. Let upper level take care of it. */
+               TALLOC_FREE(frame);
+               return -1;
+       }
+
+       fileid = SMB_VFS_FILE_ID_CREATE(handle->conn, &smb_fname_tmp->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);
+       TALLOC_FREE(frame);
+       return 0;
+}
+
 /*
  * On unlink we need to delete the tdb record
  */
@@ -364,7 +475,7 @@ static int xattr_tdb_unlink(vfs_handle_struct *handle,
                return -1;
        }
 
-       if (lp_posix_pathnames()) {
+       if (smb_fname_tmp->flags & SMB_FILENAME_POSIX_PATH) {
                ret = SMB_VFS_NEXT_LSTAT(handle, smb_fname_tmp);
        } else {
                ret = SMB_VFS_NEXT_STAT(handle, smb_fname_tmp);
@@ -400,7 +511,8 @@ static int xattr_tdb_unlink(vfs_handle_struct *handle,
 /*
  * On rmdir we need to delete the tdb record
  */
-static int xattr_tdb_rmdir(vfs_handle_struct *handle, const char *path)
+static int xattr_tdb_rmdir(vfs_handle_struct *handle,
+                       const struct smb_filename *smb_fname)
 {
        SMB_STRUCT_STAT sbuf;
        struct file_id id;
@@ -414,12 +526,14 @@ static int xattr_tdb_rmdir(vfs_handle_struct *handle, const char *path)
                                        TALLOC_FREE(frame); return -1;
                                });
 
-       if (vfs_stat_smb_fname(handle->conn, path, &sbuf) == -1) {
+       if (vfs_stat_smb_basename(handle->conn,
+                               smb_fname,
+                               &sbuf) == -1) {
                TALLOC_FREE(frame);
                return -1;
        }
 
-       ret = SMB_VFS_NEXT_RMDIR(handle, path);
+       ret = SMB_VFS_NEXT_RMDIR(handle, smb_fname);
 
        if (ret == -1) {
                TALLOC_FREE(frame);
@@ -487,13 +601,15 @@ static struct vfs_fn_pointers vfs_xattr_tdb_fns = {
        .flistxattr_fn = xattr_tdb_flistxattr,
        .removexattr_fn = xattr_tdb_removexattr,
        .fremovexattr_fn = xattr_tdb_fremovexattr,
+       .open_fn = xattr_tdb_open,
+       .mkdir_fn = xattr_tdb_mkdir,
        .unlink_fn = xattr_tdb_unlink,
        .rmdir_fn = xattr_tdb_rmdir,
        .connect_fn = xattr_tdb_connect,
 };
 
-NTSTATUS vfs_xattr_tdb_init(void);
-NTSTATUS vfs_xattr_tdb_init(void)
+NTSTATUS vfs_xattr_tdb_init(TALLOC_CTX *);
+NTSTATUS vfs_xattr_tdb_init(TALLOC_CTX *ctx)
 {
        return smb_register_vfs(SMB_VFS_INTERFACE_VERSION, "xattr_tdb",
                                &vfs_xattr_tdb_fns);