s3: smbd: Change open_streams_for_delete() to take a struct smb_filename *.
[samba.git] / source3 / modules / vfs_streams_depot.c
index ae1af24684611498ffd026066b7f00cf530a4e27..ef5ef64dfa0a481ac0cfad8db04f7ec397383487 100644 (file)
@@ -121,9 +121,11 @@ static char *stream_dir(vfs_handle_struct *handle,
        char *tmp;
        char *id_hex;
        struct file_id id;
-       uint8 id_buf[16];
+       uint8_t id_buf[16];
        bool check_valid;
        const char *rootdir;
+       struct smb_filename *rootdir_fname = NULL;
+       struct smb_filename *tmp_fname = NULL;
 
        check_valid = lp_parm_bool(SNUM(handle->conn),
                      "streams_depot", "check_valid", true);
@@ -139,6 +141,15 @@ static char *stream_dir(vfs_handle_struct *handle,
                SNUM(handle->conn), "streams_depot", "directory",
                tmp);
 
+       rootdir_fname = synthetic_smb_fname(talloc_tos(),
+                                       rootdir,
+                                       NULL,
+                                       NULL);
+       if (rootdir_fname == NULL) {
+               errno = ENOMEM;
+               goto fail;
+       }
+
        /* Stat the base file if it hasn't already been done. */
        if (base_sbuf == NULL) {
                struct smb_filename *smb_fname_base;
@@ -222,7 +233,7 @@ static char *stream_dir(vfs_handle_struct *handle,
                              smb_fname_hash->base_name));
                        recursive_rmdir(talloc_tos(), handle->conn,
                                        smb_fname_hash);
-                       SMB_VFS_NEXT_RMDIR(handle, smb_fname_hash->base_name);
+                       SMB_VFS_NEXT_RMDIR(handle, smb_fname_hash);
                } else {
                        newname = talloc_asprintf(talloc_tos(), "lost-%lu",
                                                  random());
@@ -261,7 +272,7 @@ static char *stream_dir(vfs_handle_struct *handle,
                goto fail;
        }
 
-       if ((SMB_VFS_NEXT_MKDIR(handle, rootdir, 0755) != 0)
+       if ((SMB_VFS_NEXT_MKDIR(handle, rootdir_fname, 0755) != 0)
            && (errno != EEXIST)) {
                goto fail;
        }
@@ -272,12 +283,19 @@ static char *stream_dir(vfs_handle_struct *handle,
                goto fail;
        }
 
-       if ((SMB_VFS_NEXT_MKDIR(handle, tmp, 0755) != 0)
+       tmp_fname = synthetic_smb_fname(talloc_tos(), tmp, NULL, NULL);
+       if (tmp_fname == NULL) {
+               errno = ENOMEM;
+               goto fail;
+       }
+
+       if ((SMB_VFS_NEXT_MKDIR(handle, tmp_fname, 0755) != 0)
            && (errno != EEXIST)) {
                goto fail;
        }
 
        TALLOC_FREE(tmp);
+       TALLOC_FREE(tmp_fname);
 
        tmp = talloc_asprintf(result, "%s/%2.2X/%2.2X", rootdir, first,
                              second);
@@ -286,14 +304,22 @@ static char *stream_dir(vfs_handle_struct *handle,
                goto fail;
        }
 
-       if ((SMB_VFS_NEXT_MKDIR(handle, tmp, 0755) != 0)
+       tmp_fname = synthetic_smb_fname(talloc_tos(), tmp, NULL, NULL);
+       if (tmp_fname == NULL) {
+               errno = ENOMEM;
+               goto fail;
+       }
+
+       if ((SMB_VFS_NEXT_MKDIR(handle, tmp_fname, 0755) != 0)
            && (errno != EEXIST)) {
                goto fail;
        }
 
        TALLOC_FREE(tmp);
+       TALLOC_FREE(tmp_fname);
 
-       if ((SMB_VFS_NEXT_MKDIR(handle, result, 0755) != 0)
+       /* smb_fname_hash is the struct smb_filename version of 'result' */
+       if ((SMB_VFS_NEXT_MKDIR(handle, smb_fname_hash, 0755) != 0)
            && (errno != EEXIST)) {
                goto fail;
        }
@@ -302,10 +328,14 @@ static char *stream_dir(vfs_handle_struct *handle,
                goto fail;
        }
 
+       TALLOC_FREE(rootdir_fname);
+       TALLOC_FREE(tmp_fname);
        TALLOC_FREE(smb_fname_hash);
        return result;
 
  fail:
+       TALLOC_FREE(rootdir_fname);
+       TALLOC_FREE(tmp_fname);
        TALLOC_FREE(smb_fname_hash);
        TALLOC_FREE(result);
        return NULL;
@@ -390,6 +420,7 @@ static NTSTATUS walk_streams(vfs_handle_struct *handle,
                             void *private_data)
 {
        char *dirname;
+       struct smb_filename *dir_smb_fname = NULL;
        DIR *dirhandle = NULL;
        const char *dirent = NULL;
        char *talloced = NULL;
@@ -409,7 +440,18 @@ static NTSTATUS walk_streams(vfs_handle_struct *handle,
 
        DEBUG(10, ("walk_streams: dirname=%s\n", dirname));
 
-       dirhandle = SMB_VFS_NEXT_OPENDIR(handle, dirname, NULL, 0);
+       dir_smb_fname = synthetic_smb_fname(talloc_tos(),
+                                       dirname,
+                                       NULL,
+                                       NULL);
+       if (dir_smb_fname == NULL) {
+               TALLOC_FREE(dirname);
+               return NT_STATUS_NO_MEMORY;
+       }
+
+       dirhandle = SMB_VFS_NEXT_OPENDIR(handle, dir_smb_fname, NULL, 0);
+
+       TALLOC_FREE(dir_smb_fname);
 
        if (dirhandle == NULL) {
                TALLOC_FREE(dirname);
@@ -652,7 +694,19 @@ static int streams_depot_unlink(vfs_handle_struct *handle,
                                           &smb_fname_base->st, false);
 
                if (dirname != NULL) {
-                       SMB_VFS_NEXT_RMDIR(handle, dirname);
+                       struct smb_filename *smb_fname_dir =
+                               synthetic_smb_fname(talloc_tos(),
+                                               dirname,
+                                               NULL,
+                                               NULL);
+                       if (smb_fname_dir == NULL) {
+                               TALLOC_FREE(smb_fname_base);
+                               TALLOC_FREE(dirname);
+                               errno = ENOMEM;
+                               return -1;
+                       }
+                       SMB_VFS_NEXT_RMDIR(handle, smb_fname_dir);
+                       TALLOC_FREE(smb_fname_dir);
                }
                TALLOC_FREE(dirname);
        }
@@ -661,18 +715,23 @@ static int streams_depot_unlink(vfs_handle_struct *handle,
        return ret;
 }
 
-static int streams_depot_rmdir(vfs_handle_struct *handle, const char *path)
+static int streams_depot_rmdir(vfs_handle_struct *handle,
+                               const struct smb_filename *smb_fname)
 {
        struct smb_filename *smb_fname_base = NULL;
        int ret = -1;
 
-       DEBUG(10, ("streams_depot_rmdir called for %s\n", path));
+       DEBUG(10, ("streams_depot_rmdir called for %s\n",
+               smb_fname->base_name));
 
        /*
         * We potentially need to delete the per-inode streams directory
         */
 
-       smb_fname_base = synthetic_smb_fname(talloc_tos(), path, NULL, NULL);
+       smb_fname_base = synthetic_smb_fname(talloc_tos(),
+                               smb_fname->base_name,
+                               NULL,
+                               NULL);
        if (smb_fname_base == NULL) {
                errno = ENOMEM;
                return -1;
@@ -689,13 +748,25 @@ static int streams_depot_rmdir(vfs_handle_struct *handle, const char *path)
                return -1;
        }
 
-       ret = SMB_VFS_NEXT_RMDIR(handle, path);
+       ret = SMB_VFS_NEXT_RMDIR(handle, smb_fname_base);
        if (ret == 0) {
                char *dirname = stream_dir(handle, smb_fname_base,
                                           &smb_fname_base->st, false);
 
                if (dirname != NULL) {
-                       SMB_VFS_NEXT_RMDIR(handle, dirname);
+                       struct smb_filename *smb_fname_dir =
+                               synthetic_smb_fname(talloc_tos(),
+                                               dirname,
+                                               NULL,
+                                               NULL);
+                       if (smb_fname_dir == NULL) {
+                               TALLOC_FREE(smb_fname_base);
+                               TALLOC_FREE(dirname);
+                               errno = ENOMEM;
+                               return -1;
+                       }
+                       SMB_VFS_NEXT_RMDIR(handle, smb_fname_dir);
+                       TALLOC_FREE(smb_fname_dir);
                }
                TALLOC_FREE(dirname);
        }
@@ -840,17 +911,20 @@ static bool collect_one_stream(const char *dirname,
 
 static NTSTATUS streams_depot_streaminfo(vfs_handle_struct *handle,
                                         struct files_struct *fsp,
-                                        const char *fname,
+                                        const struct smb_filename *smb_fname,
                                         TALLOC_CTX *mem_ctx,
                                         unsigned int *pnum_streams,
                                         struct stream_struct **pstreams)
 {
-       struct smb_filename *smb_fname_base;
+       struct smb_filename *smb_fname_base = NULL;
        int ret;
        NTSTATUS status;
        struct streaminfo_state state;
 
-       smb_fname_base = synthetic_smb_fname(talloc_tos(), fname, NULL, NULL);
+       smb_fname_base = synthetic_smb_fname(talloc_tos(),
+                                       smb_fname->base_name,
+                                       NULL,
+                                       NULL);
        if (smb_fname_base == NULL) {
                return NT_STATUS_NO_MEMORY;
        }
@@ -877,8 +951,19 @@ static NTSTATUS streams_depot_streaminfo(vfs_handle_struct *handle,
        state.handle = handle;
        state.status = NT_STATUS_OK;
 
-       status = walk_streams(handle, smb_fname_base, NULL, collect_one_stream,
+       if (S_ISLNK(smb_fname_base->st.st_ex_mode)) {
+               /*
+                * Currently we do't have SMB_VFS_LLISTXATTR
+                * inside the VFS which means there's no way
+                * to cope with a symlink when lp_posix_pathnames().
+                * returns true. For now ignore links.
+                * FIXME - by adding SMB_VFS_LLISTXATTR. JRA.
+                */
+               status = NT_STATUS_OK;
+       } else {
+               status = walk_streams(handle, smb_fname_base, NULL, collect_one_stream,
                              &state);
+       }
 
        if (!NT_STATUS_IS_OK(status)) {
                TALLOC_FREE(state.streams);
@@ -893,7 +978,12 @@ static NTSTATUS streams_depot_streaminfo(vfs_handle_struct *handle,
 
        *pnum_streams = state.num_streams;
        *pstreams = state.streams;
-       status = SMB_VFS_NEXT_STREAMINFO(handle, fsp, fname, mem_ctx, pnum_streams, pstreams);
+       status = SMB_VFS_NEXT_STREAMINFO(handle,
+                               fsp,
+                               smb_fname_base,
+                               mem_ctx,
+                               pnum_streams,
+                               pstreams);
 
  out:
        TALLOC_FREE(smb_fname_base);