Not yet used.
Default is NTSTATUS version of parent_smb_fname(). Now
to replace all users of parent_smb_fname() with
SMB_VFS_PARENT_PATHNAME() and then remove parent_smb_fname().
Needed due to snapdirseverywhere code in vfs_shadow_copy2.
Signed-off-by: Jeremy Allison <jra@samba.org>
Reviewed-by: Ralph Boehme <slow@samba.org>
return NT_STATUS_NOT_IMPLEMENTED;
}
+static NTSTATUS skel_parent_pathname(struct vfs_handle_struct *handle,
+ TALLOC_CTX *mem_ctx,
+ const struct smb_filename *smb_fname_in,
+ struct smb_filename **parent_dir_out,
+ struct smb_filename **atname_out)
+{
+ return NT_STATUS_NOT_IMPLEMENTED;
+}
+
static NTSTATUS skel_fsctl(struct vfs_handle_struct *handle,
struct files_struct *fsp,
TALLOC_CTX *ctx,
.brl_unlock_windows_fn = skel_brl_unlock_windows,
.strict_lock_check_fn = skel_strict_lock_check,
.translate_name_fn = skel_translate_name,
+ .parent_pathname_fn = skel_parent_pathname,
.fsctl_fn = skel_fsctl,
.freaddir_attr_fn = skel_freaddir_attr,
.audit_file_fn = skel_audit_file,
mem_ctx, pmapped_name);
}
+static NTSTATUS skel_parent_pathname(struct vfs_handle_struct *handle,
+ TALLOC_CTX *mem_ctx,
+ const struct smb_filename *smb_fname_in,
+ struct smb_filename **parent_dir_out,
+ struct smb_filename **atname_out)
+{
+ return SMB_VFS_NEXT_PARENT_PATHNAME(handle,
+ mem_ctx,
+ smb_fname_in,
+ parent_dir_out,
+ atname_out);
+}
+
static NTSTATUS skel_fsctl(struct vfs_handle_struct *handle,
struct files_struct *fsp,
TALLOC_CTX *ctx,
.brl_unlock_windows_fn = skel_brl_unlock_windows,
.strict_lock_check_fn = skel_strict_lock_check,
.translate_name_fn = skel_translate_name,
+ .parent_pathname_fn = skel_parent_pathname,
.fsctl_fn = skel_fsctl,
.freaddir_attr_fn = skel_freaddir_attr,
.audit_file_fn = skel_audit_file,
* Version 45 - Remove SMB_VFS_READDIR_ATTR
* Version 45 - Add SMB_VFS_SYS_ACL_DELETE_DEF_FD
* Version 45 - Remove SMB_VFS_SYS_ACL_DELETE_DEF_FILE
+ * Version 45 - Add SMB_VFS_PARENT_PATHNAME
*/
#define SMB_VFS_INTERFACE_VERSION 45
TALLOC_CTX *mem_ctx,
char **mapped_name);
+ NTSTATUS (*parent_pathname_fn)(struct vfs_handle_struct *handle,
+ TALLOC_CTX *mem_ctx,
+ const struct smb_filename *smb_fname_in,
+ struct smb_filename **parent_dir_out,
+ struct smb_filename **atname_out);
+
NTSTATUS (*fsctl_fn)(struct vfs_handle_struct *handle,
struct files_struct *fsp,
TALLOC_CTX *ctx,
enum vfs_translate_direction direction,
TALLOC_CTX *mem_ctx,
char **mapped_name);
+NTSTATUS smb_vfs_call_parent_pathname(struct vfs_handle_struct *handle,
+ TALLOC_CTX *mem_ctx,
+ const struct smb_filename *smb_fname_in,
+ struct smb_filename **parent_dir_out,
+ struct smb_filename **atname_out);
NTSTATUS smb_vfs_call_fsctl(struct vfs_handle_struct *handle,
struct files_struct *fsp,
TALLOC_CTX *ctx,
const char *mapped_name,
enum vfs_translate_direction direction,
TALLOC_CTX *mem_ctx, char **pmapped_name);
+NTSTATUS vfs_not_implemented_parent_pathname(struct vfs_handle_struct *handle,
+ TALLOC_CTX *mem_ctx,
+ const struct smb_filename *smb_fname_in,
+ struct smb_filename **parent_dir_out,
+ struct smb_filename **atname_out);
NTSTATUS vfs_not_implemented_fsctl(struct vfs_handle_struct *handle,
struct files_struct *fsp,
TALLOC_CTX *ctx,
#define SMB_VFS_NEXT_TRANSLATE_NAME(handle, name, direction, mem_ctx, mapped_name) \
smb_vfs_call_translate_name((handle)->next, (name), (direction), (mem_ctx), (mapped_name))
+#define SMB_VFS_PARENT_PATHNAME(conn, mem_ctx, smb_fname_in, parent_dir_out, atname_out) \
+ smb_vfs_call_parent_pathname((conn)->vfs_handles, (mem_ctx), (smb_fname_in), (parent_dir_out), (atname_out))
+#define SMB_VFS_NEXT_PARENT_PATHNAME(handle, mem_ctx, smb_fname_in, parent_dir_out, atname_out) \
+ smb_vfs_call_parent_pathname((handle)->next, (mem_ctx), (smb_fname_in), (parent_dir_out), (atname_out))
+
#define SMB_VFS_FSCTL(fsp, ctx, function, req_flags, in_data, in_len, out_data, max_out_len, out_len) \
smb_vfs_call_fsctl((fsp)->conn->vfs_handles, (fsp), (ctx), (function), (req_flags), (in_data), (in_len), (out_data), (max_out_len), (out_len))
return NT_STATUS_NONE_MAPPED;
}
+/**
+ * Return allocated parent directory and basename of path
+ *
+ * Note: if requesting name, it is returned as talloc child of the
+ * parent. Freeing the parent is thus sufficient to free both.
+ */
+static NTSTATUS vfswrap_parent_pathname(struct vfs_handle_struct *handle,
+ TALLOC_CTX *mem_ctx,
+ const struct smb_filename *smb_fname_in,
+ struct smb_filename **parent_dir_out,
+ struct smb_filename **atname_out)
+{
+ TALLOC_CTX *frame = talloc_stackframe();
+ struct smb_filename *parent = NULL;
+ struct smb_filename *name = NULL;
+ char *p = NULL;
+
+ parent = cp_smb_filename(frame, smb_fname_in);
+ if (parent == NULL) {
+ TALLOC_FREE(frame);
+ return NT_STATUS_NO_MEMORY;
+ }
+ TALLOC_FREE(parent->stream_name);
+ SET_STAT_INVALID(parent->st);
+
+ p = strrchr_m(parent->base_name, '/'); /* Find final '/', if any */
+ if (p == NULL) {
+ TALLOC_FREE(parent->base_name);
+ parent->base_name = talloc_strdup(parent, ".");
+ if (parent->base_name == NULL) {
+ TALLOC_FREE(frame);
+ return NT_STATUS_NO_MEMORY;
+ }
+ p = smb_fname_in->base_name;
+ } else {
+ *p = '\0';
+ p++;
+ }
+
+ if (atname_out == NULL) {
+ *parent_dir_out = talloc_move(mem_ctx, &parent);
+ TALLOC_FREE(frame);
+ return NT_STATUS_OK;
+ }
+
+ name = cp_smb_filename(frame, smb_fname_in);
+ if (name == NULL) {
+ TALLOC_FREE(frame);
+ return NT_STATUS_NO_MEMORY;
+ }
+ TALLOC_FREE(name->base_name);
+
+ name->base_name = talloc_strdup(name, p);
+ if (name->base_name == NULL) {
+ TALLOC_FREE(frame);
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ *parent_dir_out = talloc_move(mem_ctx, &parent);
+ *atname_out = talloc_move(*parent_dir_out, &name);
+ TALLOC_FREE(frame);
+ return NT_STATUS_OK;
+}
+
/*
* Implement the default fsctl operation.
*/
.brl_unlock_windows_fn = vfswrap_brl_unlock_windows,
.strict_lock_check_fn = vfswrap_strict_lock_check,
.translate_name_fn = vfswrap_translate_name,
+ .parent_pathname_fn = vfswrap_parent_pathname,
.fsctl_fn = vfswrap_fsctl,
.fset_dos_attributes_fn = vfswrap_fset_dos_attributes,
.get_dos_attributes_send_fn = vfswrap_get_dos_attributes_send,
SMB_VFS_OP_BRL_UNLOCK_WINDOWS,
SMB_VFS_OP_STRICT_LOCK_CHECK,
SMB_VFS_OP_TRANSLATE_NAME,
+ SMB_VFS_OP_PARENT_PATHNAME,
SMB_VFS_OP_FSCTL,
SMB_VFS_OP_OFFLOAD_READ_SEND,
SMB_VFS_OP_OFFLOAD_READ_RECV,
{ SMB_VFS_OP_BRL_UNLOCK_WINDOWS, "brl_unlock_windows" },
{ SMB_VFS_OP_STRICT_LOCK_CHECK, "strict_lock_check" },
{ SMB_VFS_OP_TRANSLATE_NAME, "translate_name" },
+ { SMB_VFS_OP_PARENT_PATHNAME, "parent_pathname" },
{ SMB_VFS_OP_FSCTL, "fsctl" },
{ SMB_VFS_OP_OFFLOAD_READ_SEND, "offload_read_send" },
{ SMB_VFS_OP_OFFLOAD_READ_RECV, "offload_read_recv" },
return result;
}
+static NTSTATUS smb_full_audit_parent_pathname(struct vfs_handle_struct *handle,
+ TALLOC_CTX *mem_ctx,
+ const struct smb_filename *smb_fname_in,
+ struct smb_filename **parent_dir_out,
+ struct smb_filename **atname_out)
+{
+ NTSTATUS result;
+
+ result = SMB_VFS_NEXT_PARENT_PATHNAME(handle,
+ mem_ctx,
+ smb_fname_in,
+ parent_dir_out,
+ atname_out);
+ do_log(SMB_VFS_OP_CONNECTPATH,
+ NT_STATUS_IS_OK(result),
+ handle,
+ "%s",
+ smb_fname_str_do_log(handle->conn, smb_fname_in));
+
+ return result;
+}
+
static NTSTATUS smb_full_audit_fsctl(struct vfs_handle_struct *handle,
struct files_struct *fsp,
TALLOC_CTX *ctx,
.brl_unlock_windows_fn = smb_full_audit_brl_unlock_windows,
.strict_lock_check_fn = smb_full_audit_strict_lock_check,
.translate_name_fn = smb_full_audit_translate_name,
+ .parent_pathname_fn = smb_full_audit_parent_pathname,
.fsctl_fn = smb_full_audit_fsctl,
.get_dos_attributes_send_fn = smb_full_audit_get_dos_attributes_send,
.get_dos_attributes_recv_fn = smb_full_audit_get_dos_attributes_recv,
return NT_STATUS_NOT_IMPLEMENTED;
}
+NTSTATUS vfs_not_implemented_parent_pathname(struct vfs_handle_struct *handle,
+ TALLOC_CTX *mem_ctx,
+ const struct smb_filename *smb_fname_in,
+ struct smb_filename **parent_dir_out,
+ struct smb_filename **atname_out)
+{
+ return NT_STATUS_NOT_IMPLEMENTED;
+}
+
NTSTATUS vfs_not_implemented_fsctl(struct vfs_handle_struct *handle,
struct files_struct *fsp,
TALLOC_CTX *ctx,
.brl_unlock_windows_fn = vfs_not_implemented_brl_unlock_windows,
.strict_lock_check_fn = vfs_not_implemented_strict_lock_check,
.translate_name_fn = vfs_not_implemented_translate_name,
+ .parent_pathname_fn = vfs_not_implemented_parent_pathname,
.fsctl_fn = vfs_not_implemented_fsctl,
.freaddir_attr_fn = vfs_not_implemented_freaddir_attr,
.audit_file_fn = vfs_not_implemented_audit_file,
return result;
}
+static NTSTATUS smb_time_audit_parent_pathname(struct vfs_handle_struct *handle,
+ TALLOC_CTX *mem_ctx,
+ const struct smb_filename *smb_fname_in,
+ struct smb_filename **parent_dir_out,
+ struct smb_filename **atname_out)
+{
+ NTSTATUS result;
+ struct timespec ts1,ts2;
+ double timediff;
+
+ clock_gettime_mono(&ts1);
+ result = SMB_VFS_NEXT_PARENT_PATHNAME(handle,
+ mem_ctx,
+ smb_fname_in,
+ parent_dir_out,
+ atname_out);
+ clock_gettime_mono(&ts2);
+ timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
+
+ if (timediff > audit_timeout) {
+ smb_time_audit_log_fname("parent_pathname",
+ timediff,
+ smb_fname_in->base_name);
+ }
+
+ return result;
+}
+
static NTSTATUS smb_time_audit_fsctl(struct vfs_handle_struct *handle,
struct files_struct *fsp,
TALLOC_CTX *ctx,
.brl_unlock_windows_fn = smb_time_audit_brl_unlock_windows,
.strict_lock_check_fn = smb_time_audit_strict_lock_check,
.translate_name_fn = smb_time_audit_translate_name,
+ .parent_pathname_fn = smb_time_audit_parent_pathname,
.fsctl_fn = smb_time_audit_fsctl,
.get_dos_attributes_send_fn = smb_time_audit_get_dos_attributes_send,
.get_dos_attributes_recv_fn = smb_time_audit_get_dos_attributes_recv,
mapped_name);
}
+NTSTATUS smb_vfs_call_parent_pathname(struct vfs_handle_struct *handle,
+ TALLOC_CTX *mem_ctx,
+ const struct smb_filename *smb_fname_in,
+ struct smb_filename **parent_dir_out,
+ struct smb_filename **atname_out)
+{
+ VFS_FIND(parent_pathname);
+ return handle->fns->parent_pathname_fn(handle,
+ mem_ctx,
+ smb_fname_in,
+ parent_dir_out,
+ atname_out);
+}
+
NTSTATUS smb_vfs_call_fsctl(struct vfs_handle_struct *handle,
struct files_struct *fsp,
TALLOC_CTX *ctx,