smbd: Fix a typo in a few places
[samba.git] / source3 / modules / vfs_syncops.c
index 22044f99469d9adb6ad6eb4f3ba76e877272d114..a0d9809329683a6c94866e54b5b6944d233f3b9e 100644 (file)
@@ -22,6 +22,7 @@
 #include "includes.h"
 #include "system/filesys.h"
 #include "smbd/smbd.h"
+#include "source3/smbd/dir.h"
 
 /*
 
@@ -71,39 +72,50 @@ static char *parent_dir(TALLOC_CTX *mem_ctx, const char *name)
 /*
   fsync a directory by name
  */
-static void syncops_sync_directory(const char *dname)
+static void syncops_sync_directory(connection_struct *conn,
+                                  char *dname)
 {
-#ifdef O_DIRECTORY
-       int fd = open(dname, O_DIRECTORY|O_RDONLY);
-       if (fd != -1) {
-               fsync(fd);
-               close(fd);
-       }
-#else
-       DIR *d = opendir(dname);
-       if (d != NULL) {
-               fsync(dirfd(d));
-               closedir(d);
+       struct smb_Dir *dir_hnd = NULL;
+       struct files_struct *dirfsp = NULL;
+       struct smb_filename smb_dname = { .base_name = dname };
+       NTSTATUS status;
+
+       status = OpenDir(talloc_tos(),
+                        conn,
+                        &smb_dname,
+                        "*",
+                        0,
+                        &dir_hnd);
+       if (!NT_STATUS_IS_OK(status)) {
+               errno = map_errno_from_nt_status(status);
+               return;
        }
-#endif
+
+       dirfsp = dir_hnd_fetch_fsp(dir_hnd);
+
+       smb_vfs_fsync_sync(dirfsp);
+
+       TALLOC_FREE(dir_hnd);
 }
 
 /*
   sync two meta data changes for 2 names
  */
-static void syncops_two_names(const char *name1, const char *name2)
+static void syncops_two_names(connection_struct *conn,
+                             const struct smb_filename *name1,
+                             const struct smb_filename *name2)
 {
        TALLOC_CTX *tmp_ctx = talloc_new(NULL);
        char *parent1, *parent2;
-       parent1 = parent_dir(tmp_ctx, name1);
-       parent2 = parent_dir(tmp_ctx, name2);
+       parent1 = parent_dir(tmp_ctx, name1->base_name);
+       parent2 = parent_dir(tmp_ctx, name2->base_name);
        if (!parent1 || !parent2) {
                talloc_free(tmp_ctx);
                return;
        }
-       syncops_sync_directory(parent1);
+       syncops_sync_directory(conn, parent1);
        if (strcmp(parent1, parent2) != 0) {
-               syncops_sync_directory(parent2);                
+               syncops_sync_directory(conn, parent2);
        }
        talloc_free(tmp_ctx);
 }
@@ -111,120 +123,221 @@ static void syncops_two_names(const char *name1, const char *name2)
 /*
   sync two meta data changes for 1 names
  */
-static void syncops_name(const char *name)
+static void syncops_smb_fname(connection_struct *conn,
+                             const struct smb_filename *smb_fname)
 {
-       char *parent;
-       parent = parent_dir(NULL, name);
-       if (parent) {
-               syncops_sync_directory(parent);
-               talloc_free(parent);
-       }
-}
-
-/*
-  sync two meta data changes for 1 names
- */
-static void syncops_smb_fname(const struct smb_filename *smb_fname)
-{
-       char *parent;
-       parent = parent_dir(NULL, smb_fname->base_name);
-       if (parent) {
-               syncops_sync_directory(parent);
-               talloc_free(parent);
+       char *parent = NULL;
+       if (smb_fname != NULL) {
+               parent = parent_dir(NULL, smb_fname->base_name);
+               if (parent != NULL) {
+                       syncops_sync_directory(conn, parent);
+                       talloc_free(parent);
+               }
        }
 }
 
 
 /*
-  rename needs special handling, as we may need to fsync two directories
+  renameat needs special handling, as we may need to fsync two directories
  */
-static int syncops_rename(vfs_handle_struct *handle,
-                         const struct smb_filename *smb_fname_src,
-                         const struct smb_filename *smb_fname_dst)
+static int syncops_renameat(vfs_handle_struct *handle,
+                       files_struct *srcfsp,
+                       const struct smb_filename *smb_fname_src,
+                       files_struct *dstfsp,
+                       const struct smb_filename *smb_fname_dst)
 {
 
        int ret;
+       struct smb_filename *full_fname_src = NULL;
+       struct smb_filename *full_fname_dst = NULL;
        struct syncops_config_data *config;
 
        SMB_VFS_HANDLE_GET_DATA(handle, config,
                                struct syncops_config_data,
                                return -1);
 
-       ret = SMB_VFS_NEXT_RENAME(handle, smb_fname_src, smb_fname_dst);
-       if (ret == 0 && config->onmeta && !config->disable) {
-               syncops_two_names(smb_fname_src->base_name,
-                                 smb_fname_dst->base_name);
+       ret = SMB_VFS_NEXT_RENAMEAT(handle,
+                       srcfsp,
+                       smb_fname_src,
+                       dstfsp,
+                       smb_fname_dst);
+       if (ret == -1) {
+               return ret;
+       }
+       if (config->disable) {
+               return ret;
+       }
+       if (!config->onmeta) {
+               return ret;
+       }
+
+       full_fname_src = full_path_from_dirfsp_atname(talloc_tos(),
+                                                     srcfsp,
+                                                     smb_fname_src);
+       if (full_fname_src == NULL) {
+               errno = ENOMEM;
+               return ret;
        }
+       full_fname_dst = full_path_from_dirfsp_atname(talloc_tos(),
+                                                     dstfsp,
+                                                     smb_fname_dst);
+       if (full_fname_dst == NULL) {
+               TALLOC_FREE(full_fname_src);
+               errno = ENOMEM;
+               return ret;
+       }
+       syncops_two_names(handle->conn,
+                         full_fname_src,
+                         full_fname_dst);
+       TALLOC_FREE(full_fname_src);
+       TALLOC_FREE(full_fname_dst);
        return ret;
 }
 
-/* handle the rest with a macro */
-#define SYNCOPS_NEXT(op, fname, args) do {   \
-       int ret; \
-       struct syncops_config_data *config; \
-       SMB_VFS_HANDLE_GET_DATA(handle, config, \
-                               struct syncops_config_data, \
-                               return -1); \
-       ret = SMB_VFS_NEXT_ ## op args; \
-       if (ret == 0 \
-               && config->onmeta && !config->disable  \
-               && fname) syncops_name(fname); \
-       return ret; \
-} while (0)
-
 #define SYNCOPS_NEXT_SMB_FNAME(op, fname, args) do {   \
        int ret; \
+       struct smb_filename *full_fname = NULL; \
        struct syncops_config_data *config; \
        SMB_VFS_HANDLE_GET_DATA(handle, config, \
                                struct syncops_config_data, \
                                return -1); \
        ret = SMB_VFS_NEXT_ ## op args; \
-       if (ret == 0 \
-       && config->onmeta && !config->disable \
-       && fname) syncops_smb_fname(fname); \
+       if (ret != 0) { \
+               return ret; \
+       } \
+       if (config->disable) { \
+               return ret; \
+       } \
+       if (!config->onmeta) { \
+               return ret; \
+       } \
+       full_fname = full_path_from_dirfsp_atname(talloc_tos(), \
+                               dirfsp, \
+                               smb_fname); \
+       if (full_fname == NULL) { \
+               return ret; \
+       } \
+       syncops_smb_fname(dirfsp->conn, full_fname); \
+       TALLOC_FREE(full_fname); \
        return ret; \
 } while (0)
 
-static int syncops_symlink(vfs_handle_struct *handle,
-                          const char *oldname, const char *newname)
+static int syncops_symlinkat(vfs_handle_struct *handle,
+                       const struct smb_filename *link_contents,
+                       struct files_struct *dirfsp,
+                       const struct smb_filename *smb_fname)
 {
-       SYNCOPS_NEXT(SYMLINK, newname, (handle, oldname, newname));
+       SYNCOPS_NEXT_SMB_FNAME(SYMLINKAT,
+                       smb_fname,
+                               (handle,
+                               link_contents,
+                               dirfsp,
+                               smb_fname));
 }
 
-static int syncops_link(vfs_handle_struct *handle,
-                        const char *oldname, const char *newname)
+static int syncops_linkat(vfs_handle_struct *handle,
+                       files_struct *srcfsp,
+                       const struct smb_filename *old_smb_fname,
+                       files_struct *dstfsp,
+                       const struct smb_filename *new_smb_fname,
+                       int flags)
 {
-       SYNCOPS_NEXT(LINK, newname, (handle, oldname, newname));
-}
+       int ret;
+       struct syncops_config_data *config;
+       struct smb_filename *old_full_fname = NULL;
+       struct smb_filename *new_full_fname = NULL;
 
-static int syncops_open(vfs_handle_struct *handle,
-                       struct smb_filename *smb_fname, files_struct *fsp,
-                       int flags, mode_t mode)
-{
-       SYNCOPS_NEXT_SMB_FNAME(OPEN, (flags&O_CREAT?smb_fname:NULL),
-                              (handle, smb_fname, fsp, flags, mode));
+       SMB_VFS_HANDLE_GET_DATA(handle, config,
+                               struct syncops_config_data,
+                               return -1);
+
+       ret = SMB_VFS_NEXT_LINKAT(handle,
+                       srcfsp,
+                       old_smb_fname,
+                       dstfsp,
+                       new_smb_fname,
+                       flags);
+
+       if (ret == -1) {
+               return ret;
+       }
+       if (config->disable) {
+               return ret;
+       }
+       if (!config->onmeta) {
+               return ret;
+       }
+
+       old_full_fname = full_path_from_dirfsp_atname(talloc_tos(),
+                                                     srcfsp,
+                                                     old_smb_fname);
+       if (old_full_fname == NULL) {
+               return ret;
+       }
+       new_full_fname = full_path_from_dirfsp_atname(talloc_tos(),
+                                                     dstfsp,
+                                                     new_smb_fname);
+       if (new_full_fname == NULL) {
+               TALLOC_FREE(old_full_fname);
+               return ret;
+       }
+       syncops_two_names(handle->conn,
+                         old_full_fname,
+                         new_full_fname);
+       TALLOC_FREE(old_full_fname);
+       TALLOC_FREE(new_full_fname);
+       return ret;
 }
 
-static int syncops_unlink(vfs_handle_struct *handle,
-                         const struct smb_filename *smb_fname)
+static int syncops_openat(struct vfs_handle_struct *handle,
+                         const struct files_struct *dirfsp,
+                         const struct smb_filename *smb_fname,
+                         struct files_struct *fsp,
+                         const struct vfs_open_how *how)
 {
-        SYNCOPS_NEXT_SMB_FNAME(UNLINK, smb_fname, (handle, smb_fname));
+       SYNCOPS_NEXT_SMB_FNAME(OPENAT, (how->flags & O_CREAT ? smb_fname : NULL),
+                              (handle, dirfsp, smb_fname, fsp, how));
 }
 
-static int syncops_mknod(vfs_handle_struct *handle,
-                        const char *fname, mode_t mode, SMB_DEV_T dev)
+static int syncops_unlinkat(vfs_handle_struct *handle,
+                       files_struct *dirfsp,
+                       const struct smb_filename *smb_fname,
+                       int flags)
 {
-        SYNCOPS_NEXT(MKNOD, fname, (handle, fname, mode, dev));
+        SYNCOPS_NEXT_SMB_FNAME(UNLINKAT,
+                       smb_fname,
+                               (handle,
+                               dirfsp,
+                               smb_fname,
+                               flags));
 }
 
-static int syncops_mkdir(vfs_handle_struct *handle,  const char *fname, mode_t mode)
+static int syncops_mknodat(vfs_handle_struct *handle,
+                       files_struct *dirfsp,
+                       const struct smb_filename *smb_fname,
+                       mode_t mode,
+                       SMB_DEV_T dev)
 {
-        SYNCOPS_NEXT(MKDIR, fname, (handle, fname, mode));
+        SYNCOPS_NEXT_SMB_FNAME(MKNODAT,
+                       smb_fname,
+                               (handle,
+                               dirfsp,
+                               smb_fname,
+                               mode,
+                               dev));
 }
 
-static int syncops_rmdir(vfs_handle_struct *handle,  const char *fname)
+static int syncops_mkdirat(vfs_handle_struct *handle,
+                       struct files_struct *dirfsp,
+                       const struct smb_filename *smb_fname,
+                       mode_t mode)
 {
-        SYNCOPS_NEXT(RMDIR, fname, (handle, fname));
+        SYNCOPS_NEXT_SMB_FNAME(MKDIRAT,
+                       full_fname,
+                               (handle,
+                               dirfsp,
+                               smb_fname,
+                               mode));
 }
 
 /* close needs to be handled specially */
@@ -236,10 +349,10 @@ static int syncops_close(vfs_handle_struct *handle, files_struct *fsp)
                                struct syncops_config_data,
                                return -1);
 
-       if (fsp->can_write && config->onclose) {
+       if (fsp->fsp_flags.can_write && config->onclose) {
                /* ideally we'd only do this if we have written some
                 data, but there is no flag for that in fsp yet. */
-               fsync(fsp->fh->fd);
+               fsync(fsp_get_io_fd(fsp));
        }
        return SMB_VFS_NEXT_CLOSE(handle, fsp);
 }
@@ -280,18 +393,18 @@ static int syncops_connect(struct vfs_handle_struct *handle, const char *service
 
 static struct vfs_fn_pointers vfs_syncops_fns = {
        .connect_fn = syncops_connect,
-        .mkdir = syncops_mkdir,
-        .rmdir = syncops_rmdir,
-        .open = syncops_open,
-        .rename = syncops_rename,
-        .unlink = syncops_unlink,
-        .symlink = syncops_symlink,
-        .link = syncops_link,
-        .mknod = syncops_mknod,
+       .mkdirat_fn = syncops_mkdirat,
+       .openat_fn = syncops_openat,
+       .renameat_fn = syncops_renameat,
+       .unlinkat_fn = syncops_unlinkat,
+       .symlinkat_fn = syncops_symlinkat,
+       .linkat_fn = syncops_linkat,
+       .mknodat_fn = syncops_mknodat,
        .close_fn = syncops_close,
 };
 
-NTSTATUS vfs_syncops_init(void)
+static_decl_vfs;
+NTSTATUS vfs_syncops_init(TALLOC_CTX *ctx)
 {
        NTSTATUS ret;