]> git.ipfire.org Git - thirdparty/samba.git/commitdiff
vfs_commit: implement SMB_VFS_OPENAT()
authorRalph Boehme <slow@samba.org>
Wed, 20 May 2020 21:01:16 +0000 (23:01 +0200)
committerJeremy Allison <jra@samba.org>
Thu, 21 May 2020 20:38:32 +0000 (20:38 +0000)
Signed-off-by: Ralph Boehme <slow@samba.org>
Reviewed-by: Jeremy Allison <jra@samba.org>
source3/modules/vfs_commit.c

index 408c90c46a018686a51f8acfcf3bb7fa1b3d20fd..010a86cab95c7fd1d1821627873abc3f3f609ee1 100644 (file)
@@ -248,6 +248,82 @@ static int commit_open(
         return fd;
 }
 
+static int commit_openat(struct vfs_handle_struct *handle,
+                        const struct files_struct *dirfsp,
+                        const struct smb_filename *smb_fname,
+                        files_struct *fsp,
+                        int flags,
+                        mode_t mode)
+{
+        off_t dthresh;
+       const char *eof_mode;
+        struct commit_info *c = NULL;
+        int fd;
+
+        /* Don't bother with read-only files. */
+        if ((flags & O_ACCMODE) == O_RDONLY) {
+                return SMB_VFS_NEXT_OPENAT(handle,
+                                          dirfsp,
+                                          smb_fname,
+                                          fsp,
+                                          flags,
+                                          mode);
+        }
+
+        /* Read and check module configuration */
+        dthresh = conv_str_size(lp_parm_const_string(SNUM(handle->conn),
+                                        MODULE, "dthresh", NULL));
+
+       eof_mode = lp_parm_const_string(SNUM(handle->conn),
+                                        MODULE, "eof mode", "none");
+
+        if (dthresh > 0 || !strequal(eof_mode, "none")) {
+                c = VFS_ADD_FSP_EXTENSION(
+                       handle, fsp, struct commit_info, NULL);
+                /* Process main tunables */
+                if (c) {
+                        c->dthresh = dthresh;
+                        c->dbytes = 0;
+                        c->on_eof = EOF_NONE;
+                        c->eof = 0;
+                }
+        }
+        /* Process eof_mode tunable */
+        if (c) {
+                if (strequal(eof_mode, "hinted")) {
+                        c->on_eof = EOF_HINTED;
+                } else if (strequal(eof_mode, "growth")) {
+                        c->on_eof = EOF_GROWTH;
+                }
+        }
+
+        fd = SMB_VFS_NEXT_OPENAT(handle, dirfsp, smb_fname, fsp, flags, mode);
+       if (fd == -1) {
+               VFS_REMOVE_FSP_EXTENSION(handle, fsp);
+               return fd;
+       }
+
+        /* EOF commit modes require us to know the initial file size. */
+        if (c && (c->on_eof != EOF_NONE)) {
+                SMB_STRUCT_STAT st;
+               /*
+                * Setting the fd of the FSP is a hack
+                * but also practiced elsewhere -
+                * needed for calling the VFS.
+                */
+               fsp->fh->fd = fd;
+               if (SMB_VFS_FSTAT(fsp, &st) == -1) {
+                       int saved_errno = errno;
+                       SMB_VFS_CLOSE(fsp);
+                       errno = saved_errno;
+                        return -1;
+                }
+               c->eof = st.st_ex_size;
+        }
+
+        return fd;
+}
+
 static ssize_t commit_pwrite(
         vfs_handle_struct * handle,
         files_struct *      fsp,
@@ -376,6 +452,7 @@ static int commit_ftruncate(
 
 static struct vfs_fn_pointers vfs_commit_fns = {
         .open_fn = commit_open,
+        .openat_fn = commit_openat,
         .close_fn = commit_close,
         .pwrite_fn = commit_pwrite,
         .pwrite_send_fn = commit_pwrite_send,