s3: smbd: vfs: Remove any stale xattr values during file/directory create in vfs_xatt...
authorJeremy Allison <jra@samba.org>
Wed, 20 Jul 2016 23:40:53 +0000 (16:40 -0700)
committerAndrew Bartlett <abartlet@samba.org>
Sat, 23 Jul 2016 04:04:11 +0000 (06:04 +0200)
Pair-programmed-with: Andrew Bartlett <abartlet@samba.org>
Signed-off-by: Jeremy Allison <jra@samba.org>
Reviewed-by: Andrew Bartlett <abartlet@samba.org>
source3/modules/vfs_xattr_tdb.c

index c40f1e14997d47e83de1f80b943084c17efdcae5..b32fbc1e9eb1047dea4baef324ecc1bcf3e2ca3c 100644 (file)
@@ -338,6 +338,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
  */
@@ -490,6 +589,8 @@ 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,