From e129384d7c1df664e447186673dd107e190e2894 Mon Sep 17 00:00:00 2001 From: Tim Prouty Date: Mon, 22 Jun 2009 15:26:56 -0700 Subject: s3: Plumb smb_filename through SMB_VFS_STAT and SMB_VFS_LSTAT This patch introduces two new temporary helper functions vfs_stat_smb_fname and vfs_lstat_smb_fname. They basically allowed me to call the new smb_filename version of stat, while avoiding plumbing it through callers that are still too inconvenient. As the conversion moves along, I will be able to remove callers of this, with the goal being to remove all callers. There was also a bug in create_synthetic_smb_fname_split (also a temporary utility function) that caused it to incorrectly handle filenames with ':'s in them when in posix mode. This is now fixed. --- source3/modules/nfs4_acls.c | 2 +- source3/modules/vfs_acl_tdb.c | 46 +++-- source3/modules/vfs_acl_xattr.c | 14 +- source3/modules/vfs_afsacl.c | 2 +- source3/modules/vfs_cap.c | 38 +++- source3/modules/vfs_catia.c | 36 +++- source3/modules/vfs_default.c | 38 +++- source3/modules/vfs_fake_perms.c | 15 +- source3/modules/vfs_full_audit.c | 18 +- source3/modules/vfs_gpfs.c | 36 ++-- source3/modules/vfs_hpuxacl.c | 2 +- source3/modules/vfs_recycle.c | 8 +- source3/modules/vfs_shadow_copy2.c | 12 +- source3/modules/vfs_solarisacl.c | 2 +- source3/modules/vfs_streams_depot.c | 338 ++++++++++++++++++++++++------------ source3/modules/vfs_streams_xattr.c | 160 ++++++++++------- source3/modules/vfs_xattr_tdb.c | 12 +- 17 files changed, 524 insertions(+), 255 deletions(-) (limited to 'source3/modules') diff --git a/source3/modules/nfs4_acls.c b/source3/modules/nfs4_acls.c index 10a3733c14..320f9da337 100644 --- a/source3/modules/nfs4_acls.c +++ b/source3/modules/nfs4_acls.c @@ -168,7 +168,7 @@ static int smbacl4_GetFileOwner(struct connection_struct *conn, memset(psbuf, 0, sizeof(SMB_STRUCT_STAT)); /* Get the stat struct for the owner info. */ - if (SMB_VFS_STAT(conn, filename, psbuf) != 0) + if (vfs_stat_smb_fname(conn, filename, psbuf) != 0) { DEBUG(8, ("SMB_VFS_STAT failed with error %s\n", strerror(errno))); diff --git a/source3/modules/vfs_acl_tdb.c b/source3/modules/vfs_acl_tdb.c index e0a5b14c67..9f0b0b317a 100644 --- a/source3/modules/vfs_acl_tdb.c +++ b/source3/modules/vfs_acl_tdb.c @@ -196,9 +196,9 @@ static NTSTATUS get_acl_blob(TALLOC_CTX *ctx, ret = SMB_VFS_FSTAT(fsp, &sbuf); } else { if (fsp && fsp->posix_open) { - ret = SMB_VFS_LSTAT(handle->conn, name, &sbuf); + ret = vfs_lstat_smb_fname(handle->conn, name, &sbuf); } else { - ret = SMB_VFS_STAT(handle->conn, name, &sbuf); + ret = vfs_stat_smb_fname(handle->conn, name, &sbuf); } } @@ -288,9 +288,11 @@ static NTSTATUS store_acl_blob_fsp(vfs_handle_struct *handle, ret = SMB_VFS_FSTAT(fsp, &sbuf); } else { if (fsp->posix_open) { - ret = SMB_VFS_LSTAT(handle->conn, fsp->fsp_name, &sbuf); + ret = vfs_lstat_smb_fname(handle->conn, fsp->fsp_name, + &sbuf); } else { - ret = SMB_VFS_STAT(handle->conn, fsp->fsp_name, &sbuf); + ret = vfs_stat_smb_fname(handle->conn, fsp->fsp_name, + &sbuf); } } @@ -338,9 +340,9 @@ static NTSTATUS store_acl_blob_pathname(vfs_handle_struct *handle, return NT_STATUS_INTERNAL_DB_CORRUPTION); if (lp_posix_pathnames()) { - ret = SMB_VFS_LSTAT(handle->conn, fname, &sbuf); + ret = vfs_lstat_smb_fname(handle->conn, fname, &sbuf); } else { - ret = SMB_VFS_STAT(handle->conn, fname, &sbuf); + ret = vfs_stat_smb_fname(handle->conn, fname, &sbuf); } if (ret == -1) { @@ -514,9 +516,11 @@ static NTSTATUS inherit_new_acl(vfs_handle_struct *handle, ret = SMB_VFS_FSTAT(fsp, &sbuf); } else { if (fsp && fsp->posix_open) { - ret = SMB_VFS_LSTAT(handle->conn,fname, &sbuf); + ret = vfs_lstat_smb_fname(handle->conn,fname, + &sbuf); } else { - ret = SMB_VFS_STAT(handle->conn,fname, &sbuf); + ret = vfs_stat_smb_fname(handle->conn,fname, + &sbuf); } } if (ret == -1) { @@ -621,9 +625,9 @@ static int unlink_acl_tdb(vfs_handle_struct *handle, const char *path) SMB_VFS_HANDLE_GET_DATA(handle, db, struct db_context, return -1); if (lp_posix_pathnames()) { - ret = SMB_VFS_LSTAT(handle->conn, path, &sbuf); + ret = vfs_lstat_smb_fname(handle->conn, path, &sbuf); } else { - ret = SMB_VFS_STAT(handle->conn, path, &sbuf); + ret = vfs_stat_smb_fname(handle->conn, path, &sbuf); } if (ret == -1) { @@ -670,9 +674,9 @@ static int rmdir_acl_tdb(vfs_handle_struct *handle, const char *path) SMB_VFS_HANDLE_GET_DATA(handle, db, struct db_context, return -1); if (lp_posix_pathnames()) { - ret = SMB_VFS_LSTAT(handle->conn, path, &sbuf); + ret = vfs_lstat_smb_fname(handle->conn, path, &sbuf); } else { - ret = SMB_VFS_STAT(handle->conn, path, &sbuf); + ret = vfs_stat_smb_fname(handle->conn, path, &sbuf); } if (ret == -1) { @@ -774,9 +778,13 @@ static NTSTATUS fset_nt_acl_tdb(vfs_handle_struct *handle, files_struct *fsp, } if (fsp->is_directory || fsp->fh->fd == -1) { if (fsp->posix_open) { - ret = SMB_VFS_LSTAT(fsp->conn,fsp->fsp_name, &sbuf); + ret = vfs_lstat_smb_fname(fsp->conn, + fsp->fsp_name, + &sbuf); } else { - ret = SMB_VFS_STAT(fsp->conn,fsp->fsp_name, &sbuf); + ret = vfs_stat_smb_fname(fsp->conn, + fsp->fsp_name, + &sbuf); } } else { ret = SMB_VFS_FSTAT(fsp, &sbuf); @@ -867,9 +875,9 @@ static int sys_acl_set_file_tdb(vfs_handle_struct *handle, SMB_VFS_HANDLE_GET_DATA(handle, db, struct db_context, return -1); if (lp_posix_pathnames()) { - ret = SMB_VFS_LSTAT(handle->conn, path, &sbuf); + ret = vfs_lstat_smb_fname(handle->conn, path, &sbuf); } else { - ret = SMB_VFS_STAT(handle->conn, path, &sbuf); + ret = vfs_stat_smb_fname(handle->conn, path, &sbuf); } if (ret == -1) { @@ -904,9 +912,11 @@ static int sys_acl_set_fd_tdb(vfs_handle_struct *handle, if (fsp->is_directory || fsp->fh->fd == -1) { if (fsp->posix_open) { - ret = SMB_VFS_LSTAT(fsp->conn,fsp->fsp_name, &sbuf); + ret = vfs_lstat_smb_fname(fsp->conn,fsp->fsp_name, + &sbuf); } else { - ret = SMB_VFS_STAT(fsp->conn,fsp->fsp_name, &sbuf); + ret = vfs_stat_smb_fname(fsp->conn,fsp->fsp_name, + &sbuf); } } else { ret = SMB_VFS_FSTAT(fsp, &sbuf); diff --git a/source3/modules/vfs_acl_xattr.c b/source3/modules/vfs_acl_xattr.c index efcc87740a..66bf21c4f7 100644 --- a/source3/modules/vfs_acl_xattr.c +++ b/source3/modules/vfs_acl_xattr.c @@ -382,9 +382,11 @@ static NTSTATUS inherit_new_acl(vfs_handle_struct *handle, ret = SMB_VFS_FSTAT(fsp, &sbuf); } else { if (fsp && fsp->posix_open) { - ret = SMB_VFS_LSTAT(handle->conn,fname, &sbuf); + ret = vfs_lstat_smb_fname(handle->conn, fname, + &sbuf); } else { - ret = SMB_VFS_STAT(handle->conn,fname, &sbuf); + ret = vfs_stat_smb_fname(handle->conn, fname, + &sbuf); } } if (ret == -1) { @@ -574,9 +576,13 @@ static NTSTATUS fset_nt_acl_xattr(vfs_handle_struct *handle, files_struct *fsp, } if (fsp->is_directory || fsp->fh->fd == -1) { if (fsp->posix_open) { - ret = SMB_VFS_LSTAT(fsp->conn,fsp->fsp_name, &sbuf); + ret = vfs_lstat_smb_fname(fsp->conn, + fsp->fsp_name, + &sbuf); } else { - ret = SMB_VFS_STAT(fsp->conn,fsp->fsp_name, &sbuf); + ret = vfs_stat_smb_fname(fsp->conn, + fsp->fsp_name, + &sbuf); } } else { ret = SMB_VFS_FSTAT(fsp, &sbuf); diff --git a/source3/modules/vfs_afsacl.c b/source3/modules/vfs_afsacl.c index e537f01b03..55371c60f5 100644 --- a/source3/modules/vfs_afsacl.c +++ b/source3/modules/vfs_afsacl.c @@ -662,7 +662,7 @@ static size_t afs_to_nt_acl(struct afs_acl *afs_acl, SMB_STRUCT_STAT sbuf; /* Get the stat struct for the owner info. */ - if(SMB_VFS_STAT(conn, name, &sbuf) != 0) { + if(vfs_stat_smb_fname(conn, name, &sbuf) != 0) { return 0; } diff --git a/source3/modules/vfs_cap.c b/source3/modules/vfs_cap.c index 4525fa1da3..12a88750ee 100644 --- a/source3/modules/vfs_cap.c +++ b/source3/modules/vfs_cap.c @@ -144,26 +144,52 @@ static int cap_rename(vfs_handle_struct *handle, const char *oldname, const char return SMB_VFS_NEXT_RENAME(handle, capold, capnew); } -static int cap_stat(vfs_handle_struct *handle, const char *path, SMB_STRUCT_STAT *sbuf) +static int cap_stat(vfs_handle_struct *handle, struct smb_filename *smb_fname) { - char *cappath = capencode(talloc_tos(), path); + char *cappath; + char *tmp_base_name = NULL; + int ret; + + cappath = capencode(talloc_tos(), smb_fname->base_name); if (!cappath) { errno = ENOMEM; return -1; } - return SMB_VFS_NEXT_STAT(handle, cappath, sbuf); + + tmp_base_name = smb_fname->base_name; + smb_fname->base_name = cappath; + + ret = SMB_VFS_NEXT_STAT(handle, smb_fname); + + smb_fname->base_name = tmp_base_name; + TALLOC_FREE(cappath); + + return ret; } -static int cap_lstat(vfs_handle_struct *handle, const char *path, SMB_STRUCT_STAT *sbuf) +static int cap_lstat(vfs_handle_struct *handle, struct smb_filename *smb_fname) { - char *cappath = capencode(talloc_tos(), path); + char *cappath; + char *tmp_base_name = NULL; + int ret; + + cappath = capencode(talloc_tos(), smb_fname->base_name); if (!cappath) { errno = ENOMEM; return -1; } - return SMB_VFS_NEXT_LSTAT(handle, cappath, sbuf); + + tmp_base_name = smb_fname->base_name; + smb_fname->base_name = cappath; + + ret = SMB_VFS_NEXT_LSTAT(handle, smb_fname); + + smb_fname->base_name = tmp_base_name; + TALLOC_FREE(cappath); + + return ret; } static int cap_unlink(vfs_handle_struct *handle, const char *path) diff --git a/source3/modules/vfs_catia.c b/source3/modules/vfs_catia.c index 8d1c87a9fc..c8c340d0a5 100644 --- a/source3/modules/vfs_catia.c +++ b/source3/modules/vfs_catia.c @@ -177,27 +177,51 @@ static int catia_rename(vfs_handle_struct *handle, } static int catia_stat(vfs_handle_struct *handle, - const char *fname, SMB_STRUCT_STAT *sbuf) + struct smb_filename *smb_fname) { - char *name = to_unix(talloc_tos(), fname); + char *name; + char *tmp_base_name; + int ret; + name = to_unix(talloc_tos(), smb_fname->base_name); if (!name) { errno = ENOMEM; return -1; } - return SMB_VFS_NEXT_STAT(handle, name, sbuf); + + tmp_base_name = smb_fname->base_name; + smb_fname->base_name = name; + + ret = SMB_VFS_NEXT_STAT(handle, smb_fname); + + smb_fname->base_name = tmp_base_name; + TALLOC_FREE(name); + + return ret; } static int catia_lstat(vfs_handle_struct *handle, - const char *path, SMB_STRUCT_STAT *sbuf) + struct smb_filename *smb_fname) { - char *name = to_unix(talloc_tos(), path); + char *name; + char *tmp_base_name; + int ret; + name = to_unix(talloc_tos(), smb_fname->base_name); if (!name) { errno = ENOMEM; return -1; } - return SMB_VFS_NEXT_LSTAT(handle, name, sbuf); + + tmp_base_name = smb_fname->base_name; + smb_fname->base_name = name; + + ret = SMB_VFS_NEXT_LSTAT(handle, smb_fname); + + smb_fname->base_name = tmp_base_name; + TALLOC_FREE(name); + + return ret; } static int catia_unlink(vfs_handle_struct *handle, const char *path) diff --git a/source3/modules/vfs_default.c b/source3/modules/vfs_default.c index 0e7ba05632..cd792aba32 100644 --- a/source3/modules/vfs_default.c +++ b/source3/modules/vfs_default.c @@ -549,12 +549,26 @@ static int vfswrap_fsync(vfs_handle_struct *handle, files_struct *fsp) #endif } -static int vfswrap_stat(vfs_handle_struct *handle, const char *fname, SMB_STRUCT_STAT *sbuf) +static int vfswrap_stat(vfs_handle_struct *handle, + struct smb_filename *smb_fname) { int result; + NTSTATUS status; + char *fname = NULL; START_PROFILE(syscall_stat); - result = sys_stat(fname, sbuf); + + status = get_full_smb_filename(talloc_tos(), smb_fname, + &fname); + if (!NT_STATUS_IS_OK(status)) { + errno = map_errno_from_nt_status(status); + return -1; + } + + result = sys_stat(fname, &smb_fname->st); + + TALLOC_FREE(fname); + END_PROFILE(syscall_stat); return result; } @@ -569,12 +583,26 @@ static int vfswrap_fstat(vfs_handle_struct *handle, files_struct *fsp, SMB_STRUC return result; } -int vfswrap_lstat(vfs_handle_struct *handle, const char *path, SMB_STRUCT_STAT *sbuf) +static int vfswrap_lstat(vfs_handle_struct *handle, + struct smb_filename *smb_fname) { int result; + NTSTATUS status; + char *fname = NULL; START_PROFILE(syscall_lstat); - result = sys_lstat(path, sbuf); + + status = get_full_smb_filename(talloc_tos(), smb_fname, + &fname); + if (!NT_STATUS_IS_OK(status)) { + errno = map_errno_from_nt_status(status); + return -1; + } + + result = sys_lstat(fname, &smb_fname->st); + + TALLOC_FREE(fname); + END_PROFILE(syscall_lstat); return result; } @@ -1097,7 +1125,7 @@ static NTSTATUS vfswrap_streaminfo(vfs_handle_struct *handle, ret = SMB_VFS_FSTAT(fsp, &sbuf); } else { - ret = SMB_VFS_STAT(handle->conn, fname, &sbuf); + ret = vfs_stat_smb_fname(handle->conn, fname, &sbuf); } if (ret == -1) { diff --git a/source3/modules/vfs_fake_perms.c b/source3/modules/vfs_fake_perms.c index cc3ab6220d..2740b612ca 100644 --- a/source3/modules/vfs_fake_perms.c +++ b/source3/modules/vfs_fake_perms.c @@ -26,19 +26,20 @@ #undef DBGC_CLASS #define DBGC_CLASS DBGC_VFS -static int fake_perms_stat(vfs_handle_struct *handle, const char *fname, SMB_STRUCT_STAT *sbuf) +static int fake_perms_stat(vfs_handle_struct *handle, + struct smb_filename *smb_fname) { int ret = -1; - ret = SMB_VFS_NEXT_STAT(handle, fname, sbuf); + ret = SMB_VFS_NEXT_STAT(handle, smb_fname); if (ret == 0) { - if (S_ISDIR(sbuf->st_ex_mode)) { - sbuf->st_ex_mode = S_IFDIR | S_IRWXU; + if (S_ISDIR(smb_fname->st.st_ex_mode)) { + smb_fname->st.st_ex_mode = S_IFDIR | S_IRWXU; } else { - sbuf->st_ex_mode = S_IRWXU; + smb_fname->st.st_ex_mode = S_IRWXU; } - sbuf->st_ex_uid = handle->conn->server_info->utok.uid; - sbuf->st_ex_gid = handle->conn->server_info->utok.gid; + smb_fname->st.st_ex_uid = handle->conn->server_info->utok.uid; + smb_fname->st.st_ex_gid = handle->conn->server_info->utok.gid; } return ret; diff --git a/source3/modules/vfs_full_audit.c b/source3/modules/vfs_full_audit.c index 5558b2f9b5..e47609d0a9 100644 --- a/source3/modules/vfs_full_audit.c +++ b/source3/modules/vfs_full_audit.c @@ -151,11 +151,11 @@ static int smb_full_audit_rename(vfs_handle_struct *handle, const char *oldname, const char *newname); static int smb_full_audit_fsync(vfs_handle_struct *handle, files_struct *fsp); static int smb_full_audit_stat(vfs_handle_struct *handle, - const char *fname, SMB_STRUCT_STAT *sbuf); + struct smb_filename *smb_fname); static int smb_full_audit_fstat(vfs_handle_struct *handle, files_struct *fsp, SMB_STRUCT_STAT *sbuf); static int smb_full_audit_lstat(vfs_handle_struct *handle, - const char *path, SMB_STRUCT_STAT *sbuf); + struct smb_filename *smb_fname); static int smb_full_audit_get_alloc_size(vfs_handle_struct *handle, files_struct *fsp, const SMB_STRUCT_STAT *sbuf); static int smb_full_audit_unlink(vfs_handle_struct *handle, @@ -1361,13 +1361,14 @@ static int smb_full_audit_fsync(vfs_handle_struct *handle, files_struct *fsp) } static int smb_full_audit_stat(vfs_handle_struct *handle, - const char *fname, SMB_STRUCT_STAT *sbuf) + struct smb_filename *smb_fname) { int result; - result = SMB_VFS_NEXT_STAT(handle, fname, sbuf); + result = SMB_VFS_NEXT_STAT(handle, smb_fname); - do_log(SMB_VFS_OP_STAT, (result >= 0), handle, "%s", fname); + do_log(SMB_VFS_OP_STAT, (result >= 0), handle, "%s", + smb_fname_str_dbg(smb_fname)); return result; } @@ -1385,13 +1386,14 @@ static int smb_full_audit_fstat(vfs_handle_struct *handle, files_struct *fsp, } static int smb_full_audit_lstat(vfs_handle_struct *handle, - const char *path, SMB_STRUCT_STAT *sbuf) + struct smb_filename *smb_fname) { int result; - result = SMB_VFS_NEXT_LSTAT(handle, path, sbuf); + result = SMB_VFS_NEXT_LSTAT(handle, smb_fname); - do_log(SMB_VFS_OP_LSTAT, (result >= 0), handle, "%s", path); + do_log(SMB_VFS_OP_LSTAT, (result >= 0), handle, "%s", + smb_fname_str_dbg(smb_fname)); return result; } diff --git a/source3/modules/vfs_gpfs.c b/source3/modules/vfs_gpfs.c index 26f9688909..47858cb352 100644 --- a/source3/modules/vfs_gpfs.c +++ b/source3/modules/vfs_gpfs.c @@ -966,20 +966,28 @@ static size_t gpfs_get_xattr(struct vfs_handle_struct *handle, const char *path return size; } -static int vfs_gpfs_stat(struct vfs_handle_struct *handle, const char *fname, - SMB_STRUCT_STAT *sbuf) +static int vfs_gpfs_stat(struct vfs_handle_struct *handle, + struct smb_filename *smb_fname) { struct gpfs_winattr attrs; + char *fname = NULL; + NTSTATUS status; int ret; - ret = SMB_VFS_NEXT_STAT(handle, fname, sbuf); + ret = SMB_VFS_NEXT_STAT(handle, smb_fname); if (ret == -1) { return -1; } + status = get_full_smb_filename(talloc_tos(), smb_fname, &fname); + if (!NT_STATUS_IS_OK) { + errno = map_errno_from_nt_status(status); + return -1; + } ret = get_gpfs_winattrs(CONST_DISCARD(char *, fname), &attrs); + TALLOC_FREE(fname); if (ret == 0) { - sbuf->st_ex_btime.tv_sec = attrs.creationTime.tv_sec; - sbuf->st_ex_btime.tv_nsec = attrs.creationTime.tv_nsec; + smb_fname->st.st_ex_btime.tv_sec = attrs.creationTime.tv_sec; + smb_fname->st.st_ex_btime.tv_nsec = attrs.creationTime.tv_nsec; } return 0; } @@ -1005,20 +1013,28 @@ static int vfs_gpfs_fstat(struct vfs_handle_struct *handle, return 0; } -static int vfs_gpfs_lstat(struct vfs_handle_struct *handle, const char *path, - SMB_STRUCT_STAT *sbuf) +static int vfs_gpfs_lstat(struct vfs_handle_struct *handle, + struct smb_filename *smb_fname) { struct gpfs_winattr attrs; + char *path = NULL; + NTSTATUS status; int ret; - ret = SMB_VFS_NEXT_LSTAT(handle, path, sbuf); + ret = SMB_VFS_NEXT_LSTAT(handle, smb_fname); if (ret == -1) { return -1; } + status = get_full_smb_filename(talloc_tos(), smb_fname, &path); + if (!NT_STATUS_IS_OK) { + errno = map_errno_from_nt_status(status); + return -1; + } ret = get_gpfs_winattrs(CONST_DISCARD(char *, path), &attrs); + TALLOC_FREE(path); if (ret == 0) { - sbuf->st_ex_btime.tv_sec = attrs.creationTime.tv_sec; - sbuf->st_ex_btime.tv_nsec = attrs.creationTime.tv_nsec; + smb_fname->st.st_ex_btime.tv_sec = attrs.creationTime.tv_sec; + smb_fname->st.st_ex_btime.tv_nsec = attrs.creationTime.tv_nsec; } return 0; } diff --git a/source3/modules/vfs_hpuxacl.c b/source3/modules/vfs_hpuxacl.c index 7d20a73d7b..35341a5c3e 100644 --- a/source3/modules/vfs_hpuxacl.c +++ b/source3/modules/vfs_hpuxacl.c @@ -248,7 +248,7 @@ int hpuxacl_sys_acl_set_file(vfs_handle_struct *handle, * that has _not_ been specified in "type" from the file first * and concatenate it with the acl provided. */ - if (SMB_VFS_STAT(handle->conn, name, &s) != 0) { + if (vfs_stat_smb_fname(handle->conn, name, &s) != 0) { DEBUG(10, ("Error in stat call: %s\n", strerror(errno))); goto done; } diff --git a/source3/modules/vfs_recycle.c b/source3/modules/vfs_recycle.c index f1791aa6b1..f42fab72f7 100644 --- a/source3/modules/vfs_recycle.c +++ b/source3/modules/vfs_recycle.c @@ -214,7 +214,7 @@ static bool recycle_directory_exist(vfs_handle_struct *handle, const char *dname { SMB_STRUCT_STAT st; - if (SMB_VFS_NEXT_STAT(handle, dname, &st) == 0) { + if (vfs_stat_smb_fname(handle->conn, dname, &st) == 0) { if (S_ISDIR(st.st_ex_mode)) { return True; } @@ -227,7 +227,7 @@ static bool recycle_file_exist(vfs_handle_struct *handle, const char *fname) { SMB_STRUCT_STAT st; - if (SMB_VFS_NEXT_STAT(handle, fname, &st) == 0) { + if (vfs_stat_smb_fname(handle->conn, fname, &st) == 0) { if (S_ISREG(st.st_ex_mode)) { return True; } @@ -246,7 +246,7 @@ static SMB_OFF_T recycle_get_file_size(vfs_handle_struct *handle, const char *fn { SMB_STRUCT_STAT st; - if (SMB_VFS_NEXT_STAT(handle, fname, &st) != 0) { + if (vfs_stat_smb_fname(handle->conn, fname, &st) != 0) { DEBUG(0,("recycle: stat for %s returned %s\n", fname, strerror(errno))); return (SMB_OFF_T)0; } @@ -396,7 +396,7 @@ static void recycle_do_touch(vfs_handle_struct *handle, const char *fname, ZERO_STRUCT(ft); - if (SMB_VFS_NEXT_STAT(handle, fname, &st) != 0) { + if (vfs_stat_smb_fname(handle->conn, fname, &st) != 0) { DEBUG(0,("recycle: stat for %s returned %s\n", fname, strerror(errno))); return; diff --git a/source3/modules/vfs_shadow_copy2.c b/source3/modules/vfs_shadow_copy2.c index 7b5b85d4be..03a8fd24ea 100644 --- a/source3/modules/vfs_shadow_copy2.c +++ b/source3/modules/vfs_shadow_copy2.c @@ -376,15 +376,19 @@ static SMB_STRUCT_DIR *shadow_copy2_opendir(vfs_handle_struct *handle, } static int shadow_copy2_stat(vfs_handle_struct *handle, - const char *fname, SMB_STRUCT_STAT *sbuf) + struct smb_filename *smb_fname) { - _SHADOW2_NEXT(STAT, (handle, name, sbuf), int, -1, convert_sbuf(handle, fname, sbuf)); + _SHADOW2_NEXT_SMB_FNAME(STAT, (handle, smb_fname), int, -1, + convert_sbuf(handle, smb_fname->base_name, + &smb_fname->st)); } static int shadow_copy2_lstat(vfs_handle_struct *handle, - const char *fname, SMB_STRUCT_STAT *sbuf) + struct smb_filename *smb_fname) { - _SHADOW2_NEXT(LSTAT, (handle, name, sbuf), int, -1, convert_sbuf(handle, fname, sbuf)); + _SHADOW2_NEXT_SMB_FNAME(LSTAT, (handle, smb_fname), int, -1, + convert_sbuf(handle, smb_fname->base_name, + &smb_fname->st)); } static int shadow_copy2_fstat(vfs_handle_struct *handle, files_struct *fsp, SMB_STRUCT_STAT *sbuf) diff --git a/source3/modules/vfs_solarisacl.c b/source3/modules/vfs_solarisacl.c index fbfe664c6e..dabb35c0c0 100644 --- a/source3/modules/vfs_solarisacl.c +++ b/source3/modules/vfs_solarisacl.c @@ -165,7 +165,7 @@ int solarisacl_sys_acl_set_file(vfs_handle_struct *handle, * that has not been specified in "type" from the file first * and concatenate it with the acl provided. */ - if (SMB_VFS_STAT(handle->conn, name, &s) != 0) { + if (vfs_stat_smb_fname(handle->conn, name, &s) != 0) { DEBUG(10, ("Error in stat call: %s\n", strerror(errno))); goto done; } diff --git a/source3/modules/vfs_streams_depot.c b/source3/modules/vfs_streams_depot.c index 7d37af0181..5f850174d8 100644 --- a/source3/modules/vfs_streams_depot.c +++ b/source3/modules/vfs_streams_depot.c @@ -115,12 +115,18 @@ static bool mark_file_valid(vfs_handle_struct *handle, const char *path, return true; } -static char *stream_dir(vfs_handle_struct *handle, const char *base_path, +/** + * Given an smb_filename, determine the stream directory using the file's + * base_name. + */ +static char *stream_dir(vfs_handle_struct *handle, + const struct smb_filename *smb_fname, const SMB_STRUCT_STAT *base_sbuf, bool create_it) { uint32_t hash; + struct smb_filename *smb_fname_hash = NULL; char *result = NULL; - SMB_STRUCT_STAT sbuf; + SMB_STRUCT_STAT base_sbuf_tmp; uint8_t first, second; char *tmp; char *id_hex; @@ -128,6 +134,7 @@ static char *stream_dir(vfs_handle_struct *handle, const char *base_path, uint8 id_buf[16]; bool check_valid; const char *rootdir; + NTSTATUS status; check_valid = lp_parm_bool(SNUM(handle->conn), "streams_depot", "check_valid", true); @@ -143,17 +150,29 @@ static char *stream_dir(vfs_handle_struct *handle, const char *base_path, SNUM(handle->conn), "streams_depot", "directory", tmp); + /* Stat the base file if it hasn't already been done. */ if (base_sbuf == NULL) { - if (SMB_VFS_NEXT_STAT(handle, base_path, &sbuf) == -1) { - /* - * base file is not there - */ + struct smb_filename *smb_fname_base = NULL; + + status = create_synthetic_smb_fname(talloc_tos(), + smb_fname->base_name, + NULL, NULL, + &smb_fname_base); + if (!NT_STATUS_IS_OK(status)) { + errno = map_errno_from_nt_status(status); + goto fail; + } + if (SMB_VFS_NEXT_STAT(handle, smb_fname_base) == -1) { + TALLOC_FREE(smb_fname_base); goto fail; } - base_sbuf = &sbuf; + base_sbuf_tmp = smb_fname_base->st; + TALLOC_FREE(smb_fname_base); + } else { + base_sbuf_tmp = *base_sbuf; } - id = SMB_VFS_FILE_ID_CREATE(handle->conn, base_sbuf); + id = SMB_VFS_FILE_ID_CREATE(handle->conn, &base_sbuf_tmp); push_file_id_16((char *)id_buf, &id); @@ -179,15 +198,22 @@ static char *stream_dir(vfs_handle_struct *handle, const char *base_path, return NULL; } - if (SMB_VFS_NEXT_STAT(handle, result, &sbuf) == 0) { + status = create_synthetic_smb_fname(talloc_tos(), result, NULL, NULL, + &smb_fname_hash); + if (!NT_STATUS_IS_OK(status)) { + errno = map_errno_from_nt_status(status); + goto fail; + } + + if (SMB_VFS_NEXT_STAT(handle, smb_fname_hash) == 0) { char *newname; - if (!S_ISDIR(sbuf.st_ex_mode)) { + if (!S_ISDIR(smb_fname_hash->st.st_ex_mode)) { errno = EINVAL; goto fail; } - if (file_is_valid(handle, base_path, check_valid)) { + if (file_is_valid(handle, smb_fname->base_name, check_valid)) { return result; } @@ -257,13 +283,15 @@ static char *stream_dir(vfs_handle_struct *handle, const char *base_path, goto fail; } - if (!mark_file_valid(handle, base_path, check_valid)) { + if (!mark_file_valid(handle, smb_fname->base_name, check_valid)) { goto fail; } + TALLOC_FREE(smb_fname_hash); return result; fail: + TALLOC_FREE(smb_fname_hash); TALLOC_FREE(result); return NULL; } @@ -282,7 +310,7 @@ static NTSTATUS stream_smb_fname(vfs_handle_struct *handle, *smb_fname_out = NULL; - dirname = stream_dir(handle, smb_fname->base_name, NULL, create_dir); + dirname = stream_dir(handle, smb_fname, NULL, create_dir); if (dirname == NULL) { status = map_nt_error_from_unix(errno); @@ -315,10 +343,8 @@ static NTSTATUS stream_smb_fname(vfs_handle_struct *handle, DEBUG(10, ("stream filename = %s\n", stream_fname)); /* Create an smb_filename with stream_name == NULL. */ - status = create_synthetic_smb_fname(talloc_tos(), - stream_fname, - NULL, NULL, - smb_fname_out); + status = create_synthetic_smb_fname(talloc_tos(), stream_fname, NULL, + NULL, smb_fname_out); if (!NT_STATUS_IS_OK(status)) { return status; } @@ -331,58 +357,47 @@ static NTSTATUS stream_smb_fname(vfs_handle_struct *handle, return status; } +/* + * XXX: This function should be removed after the other vfs ops take + * smb_filename structs + */ static char *stream_name(vfs_handle_struct *handle, const char *fname, bool create_dir) { - char *base = NULL; + struct smb_filename *smb_fname = NULL; + struct smb_filename *smb_fname_stream = NULL; char *sname = NULL; - char *id_hex = NULL; - char *dirname, *stream_fname; - - if (!NT_STATUS_IS_OK(split_ntfs_stream_name(talloc_tos(), fname, - &base, &sname))) { - DEBUG(10, ("split_ntfs_stream_name failed\n")); - errno = ENOMEM; - goto fail; - } + NTSTATUS status; - /* if it's the ::$DATA stream just return the base file name */ - if (!sname) { - return base; + status = create_synthetic_smb_fname_split(talloc_tos(), fname, + NULL, &smb_fname); + if (!NT_STATUS_IS_OK(status)) { + errno = map_errno_from_nt_status(status); + goto out; } - dirname = stream_dir(handle, base, NULL, create_dir); - - if (dirname == NULL) { - goto fail; + status = stream_smb_fname(handle, smb_fname, &smb_fname_stream, + create_dir); + if (!NT_STATUS_IS_OK(status)) { + errno = map_errno_from_nt_status(status); + goto out; } - stream_fname = talloc_asprintf(talloc_tos(), "%s/:%s", dirname, sname); - - if (stream_fname == NULL) { - errno = ENOMEM; - goto fail; + status = get_full_smb_filename(talloc_tos(), smb_fname_stream, + &sname); + if (!NT_STATUS_IS_OK(status)) { + errno = map_errno_from_nt_status(status); + goto out; } + out: + TALLOC_FREE(smb_fname); + TALLOC_FREE(smb_fname_stream); - DEBUG(10, ("stream filename = %s\n", stream_fname)); - - TALLOC_FREE(base); - TALLOC_FREE(sname); - TALLOC_FREE(id_hex); - - return stream_fname; - - fail: - DEBUG(5, ("stream_name failed: %s\n", strerror(errno))); - TALLOC_FREE(base); - TALLOC_FREE(sname); - TALLOC_FREE(id_hex); - return NULL; + return sname; } static NTSTATUS walk_streams(vfs_handle_struct *handle, - const char *fname, - const SMB_STRUCT_STAT *sbuf, + struct smb_filename *smb_fname_base, char **pdirname, bool (*fn)(const char *dirname, const char *dirent, @@ -393,7 +408,8 @@ static NTSTATUS walk_streams(vfs_handle_struct *handle, SMB_STRUCT_DIR *dirhandle = NULL; char *dirent; - dirname = stream_dir(handle, fname, sbuf, false); + dirname = stream_dir(handle, smb_fname_base, &smb_fname_base->st, + false); if (dirname == NULL) { if (errno == ENOENT) { @@ -439,49 +455,99 @@ static NTSTATUS walk_streams(vfs_handle_struct *handle, return NT_STATUS_OK; } -static int streams_depot_stat(vfs_handle_struct *handle, const char *fname, - SMB_STRUCT_STAT *sbuf) +/** + * Helper to stat/lstat the base file of an smb_fname. This will actually + * fills in the stat struct in smb_filename. + */ +static int streams_depot_stat_base(vfs_handle_struct *handle, + struct smb_filename *smb_fname, + bool follow_links) { - char *stream_fname; + char *tmp_stream_name; + int result; + + tmp_stream_name = smb_fname->stream_name; + smb_fname->stream_name = NULL; + if (follow_links) { + result = SMB_VFS_NEXT_STAT(handle, smb_fname); + } else { + result = SMB_VFS_NEXT_LSTAT(handle, smb_fname); + } + smb_fname->stream_name = tmp_stream_name; + return result; +} + +static int streams_depot_stat(vfs_handle_struct *handle, + struct smb_filename *smb_fname) +{ + struct smb_filename *smb_fname_stream = NULL; + NTSTATUS status; int ret = -1; - DEBUG(10, ("streams_depot_stat called for [%s]\n", fname)); + DEBUG(10, ("streams_depot_stat called for [%s]\n", + smb_fname_str_dbg(smb_fname))); - if (!is_ntfs_stream_name(fname)) { - return SMB_VFS_NEXT_STAT(handle, fname, sbuf); + if (!is_ntfs_stream_smb_fname(smb_fname)) { + return SMB_VFS_NEXT_STAT(handle, smb_fname); } - stream_fname = stream_name(handle, fname, false); - if (stream_fname == NULL) { + /* If the default stream is requested, just stat the base file. */ + if (is_ntfs_default_stream_smb_fname(smb_fname)) { + return streams_depot_stat_base(handle, smb_fname, true); + } + + /* Stat the actual stream now. */ + status = stream_smb_fname(handle, smb_fname, &smb_fname_stream, + false); + if (!NT_STATUS_IS_OK(status)) { + ret = -1; + errno = map_errno_from_nt_status(status); goto done; } - ret = SMB_VFS_NEXT_STAT(handle, stream_fname, sbuf); + ret = SMB_VFS_NEXT_STAT(handle, smb_fname_stream); + /* Update the original smb_fname with the stat info. */ + smb_fname->st = smb_fname_stream->st; done: - TALLOC_FREE(stream_fname); + TALLOC_FREE(smb_fname_stream); return ret; } -static int streams_depot_lstat(vfs_handle_struct *handle, const char *fname, - SMB_STRUCT_STAT *sbuf) + + +static int streams_depot_lstat(vfs_handle_struct *handle, + struct smb_filename *smb_fname) { - char *stream_fname; + struct smb_filename *smb_fname_stream = NULL; + NTSTATUS status; int ret = -1; - if (!is_ntfs_stream_name(fname)) { - return SMB_VFS_NEXT_LSTAT(handle, fname, sbuf); + DEBUG(10, ("streams_depot_lstat called for [%s]\n", + smb_fname_str_dbg(smb_fname))); + + if (!is_ntfs_stream_smb_fname(smb_fname)) { + return SMB_VFS_NEXT_LSTAT(handle, smb_fname); } - stream_fname = stream_name(handle, fname, false); - if (stream_fname == NULL) { + /* If the default stream is requested, just stat the base file. */ + if (is_ntfs_default_stream_smb_fname(smb_fname)) { + return streams_depot_stat_base(handle, smb_fname, false); + } + + /* Stat the actual stream now. */ + status = stream_smb_fname(handle, smb_fname, &smb_fname_stream, + false); + if (!NT_STATUS_IS_OK(status)) { + ret = -1; + errno = map_errno_from_nt_status(status); goto done; } - ret = SMB_VFS_NEXT_LSTAT(handle, stream_fname, sbuf); + ret = SMB_VFS_NEXT_LSTAT(handle, smb_fname_stream); done: - TALLOC_FREE(stream_fname); + TALLOC_FREE(smb_fname_stream); return ret; } @@ -490,7 +556,7 @@ static int streams_depot_open(vfs_handle_struct *handle, files_struct *fsp, int flags, mode_t mode) { struct smb_filename *smb_fname_stream = NULL; - SMB_STRUCT_STAT base_sbuf; + struct smb_filename *smb_fname_base = NULL; NTSTATUS status; int ret = -1; @@ -505,21 +571,29 @@ static int streams_depot_open(vfs_handle_struct *handle, tmp_stream_name = smb_fname->stream_name; smb_fname->stream_name = NULL; - ret = SMB_VFS_NEXT_OPEN(handle, smb_fname, fsp, flags, mode); - smb_fname->stream_name = tmp_stream_name; return ret; } /* Ensure the base file still exists. */ - ret = SMB_VFS_NEXT_STAT(handle, smb_fname->base_name, &base_sbuf); + status = create_synthetic_smb_fname(talloc_tos(), + smb_fname->base_name, + NULL, NULL, + &smb_fname_base); + if (!NT_STATUS_IS_OK(status)) { + ret = -1; + errno = map_errno_from_nt_status(status); + goto done; + } + ret = SMB_VFS_NEXT_STAT(handle, smb_fname_base); if (ret == -1) { goto done; } + /* Determine the stream name, and then open it. */ status = stream_smb_fname(handle, smb_fname, &smb_fname_stream, true); if (!NT_STATUS_IS_OK(status)) { ret = -1; @@ -531,13 +605,15 @@ static int streams_depot_open(vfs_handle_struct *handle, done: TALLOC_FREE(smb_fname_stream); + TALLOC_FREE(smb_fname_base); return ret; } static int streams_depot_unlink(vfs_handle_struct *handle, const char *fname) { + struct smb_filename *smb_fname_base = NULL; + NTSTATUS status; int ret = -1; - SMB_STRUCT_STAT sbuf; DEBUG(10, ("streams_depot_unlink called for %s\n", fname)); @@ -559,18 +635,27 @@ static int streams_depot_unlink(vfs_handle_struct *handle, const char *fname) * We potentially need to delete the per-inode streams directory */ + status = create_synthetic_smb_fname(talloc_tos(), fname, NULL, NULL, + &smb_fname_base); + if (!NT_STATUS_IS_OK(status)) { + errno = map_errno_from_nt_status(status); + return -1; + } + if (lp_posix_pathnames()) { - ret = SMB_VFS_NEXT_LSTAT(handle, fname, &sbuf); + ret = SMB_VFS_NEXT_LSTAT(handle, smb_fname_base); } else { - ret = SMB_VFS_NEXT_STAT(handle, fname, &sbuf); + ret = SMB_VFS_NEXT_STAT(handle, smb_fname_base); } if (ret == -1) { + TALLOC_FREE(smb_fname_base); return -1; } - if (sbuf.st_ex_nlink == 1) { - char *dirname = stream_dir(handle, fname, &sbuf, false); + if (smb_fname_base->st.st_ex_nlink == 1) { + char *dirname = stream_dir(handle, smb_fname_base, + &smb_fname_base->st, false); if (dirname != NULL) { SMB_VFS_NEXT_RMDIR(handle, dirname); @@ -578,6 +663,8 @@ static int streams_depot_unlink(vfs_handle_struct *handle, const char *fname) TALLOC_FREE(dirname); } + TALLOC_FREE(smb_fname_base); + return SMB_VFS_NEXT_UNLINK(handle, fname); } @@ -699,32 +786,48 @@ static bool collect_one_stream(const char *dirname, { struct streaminfo_state *state = (struct streaminfo_state *)private_data; - char *full_sname; - SMB_STRUCT_STAT sbuf; + struct smb_filename *smb_fname = NULL; + char *sname = NULL; + NTSTATUS status; + bool ret; - if (asprintf(&full_sname, "%s/%s", dirname, dirent) == -1) { + sname = talloc_asprintf(talloc_tos(), "%s/%s", dirname, dirent); + if (sname == NULL) { state->status = NT_STATUS_NO_MEMORY; - return false; + ret = false; + goto out; } - if (SMB_VFS_NEXT_STAT(state->handle, full_sname, &sbuf) == -1) { - DEBUG(10, ("Could not stat %s: %s\n", full_sname, - strerror(errno))); - SAFE_FREE(full_sname); - return true; + + status = create_synthetic_smb_fname(talloc_tos(), sname, NULL, + NULL, &smb_fname); + if (!NT_STATUS_IS_OK(status)) { + state->status = status; + ret = false; + goto out; } - SAFE_FREE(full_sname); + if (SMB_VFS_NEXT_STAT(state->handle, smb_fname) == -1) { + DEBUG(10, ("Could not stat %s: %s\n", sname, + strerror(errno))); + ret = true; + goto out; + } if (!add_one_stream(state->mem_ctx, &state->num_streams, &state->streams, - dirent, sbuf.st_ex_size, + dirent, smb_fname->st.st_ex_size, SMB_VFS_GET_ALLOC_SIZE(state->handle->conn, NULL, - &sbuf))) { + &smb_fname->st))) { state->status = NT_STATUS_NO_MEMORY; - return false; + ret = false; + goto out; } - return true; + ret = true; + out: + TALLOC_FREE(sname); + TALLOC_FREE(smb_fname); + return ret; } static NTSTATUS streams_depot_streaminfo(vfs_handle_struct *handle, @@ -734,42 +837,50 @@ static NTSTATUS streams_depot_streaminfo(vfs_handle_struct *handle, unsigned int *pnum_streams, struct stream_struct **pstreams) { - SMB_STRUCT_STAT sbuf; + struct smb_filename *smb_fname_base = NULL; int ret; NTSTATUS status; struct streaminfo_state state; + status = create_synthetic_smb_fname(talloc_tos(), fname, NULL, NULL, + &smb_fname_base); + if (!NT_STATUS_IS_OK(status)) { + return status; + } + if ((fsp != NULL) && (fsp->fh->fd != -1)) { if (is_ntfs_stream_name(fsp->fsp_name)) { return NT_STATUS_INVALID_PARAMETER; } - ret = SMB_VFS_NEXT_FSTAT(handle, fsp, &sbuf); + ret = SMB_VFS_NEXT_FSTAT(handle, fsp, &smb_fname_base->st); } else { if (is_ntfs_stream_name(fname)) { return NT_STATUS_INVALID_PARAMETER; } if (lp_posix_pathnames()) { - ret = SMB_VFS_NEXT_LSTAT(handle, fname, &sbuf); + ret = SMB_VFS_NEXT_LSTAT(handle, smb_fname_base); } else { - ret = SMB_VFS_NEXT_STAT(handle, fname, &sbuf); + ret = SMB_VFS_NEXT_STAT(handle, smb_fname_base); } } if (ret == -1) { - return map_nt_error_from_unix(errno); + status = map_nt_error_from_unix(errno); + goto out; } state.streams = NULL; state.num_streams = 0; - if (!S_ISDIR(sbuf.st_ex_mode)) { + if (!S_ISDIR(smb_fname_base->st.st_ex_mode)) { if (!add_one_stream(mem_ctx, &state.num_streams, &state.streams, - "::$DATA", sbuf.st_ex_size, + "::$DATA", smb_fname_base->st.st_ex_size, SMB_VFS_GET_ALLOC_SIZE(handle->conn, fsp, - &sbuf))) { - return NT_STATUS_NO_MEMORY; + &smb_fname_base->st))) { + status = NT_STATUS_NO_MEMORY; + goto out; } } @@ -777,22 +888,27 @@ static NTSTATUS streams_depot_streaminfo(vfs_handle_struct *handle, state.handle = handle; state.status = NT_STATUS_OK; - status = walk_streams(handle, fname, &sbuf, NULL, collect_one_stream, + status = walk_streams(handle, smb_fname_base, NULL, collect_one_stream, &state); if (!NT_STATUS_IS_OK(status)) { TALLOC_FREE(state.streams); - return status; + goto out; } if (!NT_STATUS_IS_OK(state.status)) { TALLOC_FREE(state.streams); - return state.status; + status = state.status; + goto out; } *pnum_streams = state.num_streams; *pstreams = state.streams; - return NT_STATUS_OK; + status = NT_STATUS_OK; + + out: + TALLOC_FREE(smb_fname_base); + return status; } static uint32_t streams_depot_fs_capabilities(struct vfs_handle_struct *handle) diff --git a/source3/modules/vfs_streams_xattr.c b/source3/modules/vfs_streams_xattr.c index 715e1a7baf..e87d60ec60 100644 --- a/source3/modules/vfs_streams_xattr.c +++ b/source3/modules/vfs_streams_xattr.c @@ -169,9 +169,32 @@ static bool streams_xattr_recheck(struct stream_io *sio) return true; } +/** + * Helper to stat/lstat the base file of an smb_fname. + */ +static int streams_xattr_stat_base(vfs_handle_struct *handle, + struct smb_filename *smb_fname, + bool follow_links) +{ + char *tmp_stream_name; + int result; + + tmp_stream_name = smb_fname->stream_name; + smb_fname->stream_name = NULL; + if (follow_links) { + result = SMB_VFS_NEXT_STAT(handle, smb_fname); + } else { + result = SMB_VFS_NEXT_LSTAT(handle, smb_fname); + } + smb_fname->stream_name = tmp_stream_name; + return result; +} + static int streams_xattr_fstat(vfs_handle_struct *handle, files_struct *fsp, SMB_STRUCT_STAT *sbuf) { + struct smb_filename *smb_fname_base = NULL; + NTSTATUS status; int ret = -1; struct stream_io *io = (struct stream_io *) VFS_FETCH_FSP_EXTENSION(handle, fsp); @@ -186,11 +209,23 @@ static int streams_xattr_fstat(vfs_handle_struct *handle, files_struct *fsp, return -1; } + /* Create an smb_filename with stream_name == NULL. */ + status = create_synthetic_smb_fname(talloc_tos(), + io->base, + NULL, NULL, + &smb_fname_base); + if (!NT_STATUS_IS_OK(status)) { + errno = map_errno_from_nt_status(status); + return -1; + } + if (lp_posix_pathnames()) { - ret = SMB_VFS_LSTAT(handle->conn, io->base, sbuf); + ret = SMB_VFS_LSTAT(handle->conn, smb_fname_base); } else { - ret = SMB_VFS_STAT(handle->conn, io->base, sbuf); + ret = SMB_VFS_STAT(handle->conn, smb_fname_base); } + *sbuf = smb_fname_base->st; + TALLOC_FREE(smb_fname_base); if (ret == -1) { return -1; @@ -212,105 +247,106 @@ static int streams_xattr_fstat(vfs_handle_struct *handle, files_struct *fsp, return 0; } -static int streams_xattr_stat(vfs_handle_struct *handle, const char *fname, - SMB_STRUCT_STAT *sbuf) +static int streams_xattr_stat(vfs_handle_struct *handle, + struct smb_filename *smb_fname) { NTSTATUS status; - char *base = NULL, *sname = NULL; int result = -1; - char *xattr_name; - - if (!is_ntfs_stream_name(fname)) { - return SMB_VFS_NEXT_STAT(handle, fname, sbuf); - } + char *xattr_name = NULL; - status = split_ntfs_stream_name(talloc_tos(), fname, &base, &sname); - if (!NT_STATUS_IS_OK(status)) { - errno = EINVAL; - return -1; + if (!is_ntfs_stream_smb_fname(smb_fname)) { + return SMB_VFS_NEXT_STAT(handle, smb_fname); } - if (sname == NULL){ - return SMB_VFS_NEXT_STAT(handle, base, sbuf); + /* If the default stream is requested, just stat the base file. */ + if (is_ntfs_default_stream_smb_fname(smb_fname)) { + return streams_xattr_stat_base(handle, smb_fname, true); } - if (SMB_VFS_STAT(handle->conn, base, sbuf) == -1) { - goto fail; + /* Populate the stat struct with info from the base file. */ + if (streams_xattr_stat_base(handle, smb_fname, true) == -1) { + return -1; } - xattr_name = talloc_asprintf(talloc_tos(), "%s%s", - SAMBA_XATTR_DOSSTREAM_PREFIX, sname); - if (xattr_name == NULL) { - errno = ENOMEM; - goto fail; + /* Derive the xattr name to lookup. */ + status = streams_xattr_get_name(talloc_tos(), smb_fname->stream_name, + &xattr_name); + if (!NT_STATUS_IS_OK(status)) { + errno = map_errno_from_nt_status(status); + return -1; } - sbuf->st_ex_size = get_xattr_size(handle->conn, NULL, base, xattr_name); - if (sbuf->st_ex_size == -1) { + /* Augment the base file's stat information before returning. */ + smb_fname->st.st_ex_size = get_xattr_size(handle->conn, NULL, + smb_fname->base_name, + xattr_name); + if (smb_fname->st.st_ex_size == -1) { errno = ENOENT; + result = -1; goto fail; } - sbuf->st_ex_ino = stream_inode(sbuf, xattr_name); - sbuf->st_ex_mode &= ~S_IFMT; - sbuf->st_ex_mode |= S_IFREG; - sbuf->st_ex_blocks = sbuf->st_ex_size % STAT_ST_BLOCKSIZE + 1; + smb_fname->st.st_ex_ino = stream_inode(&smb_fname->st, xattr_name); + smb_fname->st.st_ex_mode &= ~S_IFMT; + smb_fname->st.st_ex_mode |= S_IFREG; + smb_fname->st.st_ex_blocks = + smb_fname->st.st_ex_size % STAT_ST_BLOCKSIZE + 1; result = 0; fail: - TALLOC_FREE(base); - TALLOC_FREE(sname); + TALLOC_FREE(xattr_name); return result; } -static int streams_xattr_lstat(vfs_handle_struct *handle, const char *fname, - SMB_STRUCT_STAT *sbuf) +static int streams_xattr_lstat(vfs_handle_struct *handle, + struct smb_filename *smb_fname) { NTSTATUS status; - char *base, *sname; int result = -1; - char *xattr_name; - - if (!is_ntfs_stream_name(fname)) { - return SMB_VFS_NEXT_LSTAT(handle, fname, sbuf); - } + char *xattr_name = NULL; - status = split_ntfs_stream_name(talloc_tos(), fname, &base, &sname); - if (!NT_STATUS_IS_OK(status)) { - errno = EINVAL; - goto fail; + if (!is_ntfs_stream_smb_fname(smb_fname)) { + return SMB_VFS_NEXT_LSTAT(handle, smb_fname); } - if (sname == NULL){ - return SMB_VFS_NEXT_LSTAT(handle, base, sbuf); + /* If the default stream is requested, just stat the base file. */ + if (is_ntfs_default_stream_smb_fname(smb_fname)) { + return streams_xattr_stat_base(handle, smb_fname, false); } - if (SMB_VFS_LSTAT(handle->conn, base, sbuf) == -1) { - goto fail; + /* Populate the stat struct with info from the base file. */ + if (streams_xattr_stat_base(handle, smb_fname, false) == -1) { + return -1; } - xattr_name = talloc_asprintf(talloc_tos(), "%s%s", - SAMBA_XATTR_DOSSTREAM_PREFIX, sname); - if (xattr_name == NULL) { - errno = ENOMEM; - goto fail; + /* Derive the xattr name to lookup. */ + status = streams_xattr_get_name(talloc_tos(), smb_fname->stream_name, + &xattr_name); + if (!NT_STATUS_IS_OK(status)) { + errno = map_errno_from_nt_status(status); + return -1; } - sbuf->st_ex_size = get_xattr_size(handle->conn, NULL, base, xattr_name); - if (sbuf->st_ex_size == -1) { + /* Augment the base file's stat information before returning. */ + smb_fname->st.st_ex_size = get_xattr_size(handle->conn, NULL, + smb_fname->base_name, + xattr_name); + if (smb_fname->st.st_ex_size == -1) { errno = ENOENT; + result = -1; goto fail; } - sbuf->st_ex_ino = stream_inode(sbuf, xattr_name); - sbuf->st_ex_mode &= ~S_IFMT; - sbuf->st_ex_mode |= S_IFREG; - sbuf->st_ex_blocks = sbuf->st_ex_size % STAT_ST_BLOCKSIZE + 1; + smb_fname->st.st_ex_ino = stream_inode(&smb_fname->st, xattr_name); + smb_fname->st.st_ex_mode &= ~S_IFMT; + smb_fname->st.st_ex_mode |= S_IFREG; + smb_fname->st.st_ex_blocks = + smb_fname->st.st_ex_size % STAT_ST_BLOCKSIZE + 1; result = 0; + fail: - TALLOC_FREE(base); - TALLOC_FREE(sname); + TALLOC_FREE(xattr_name); return result; } @@ -776,9 +812,9 @@ static NTSTATUS streams_xattr_streaminfo(vfs_handle_struct *handle, return NT_STATUS_INVALID_PARAMETER; } if (lp_posix_pathnames()) { - ret = SMB_VFS_LSTAT(handle->conn, fname, &sbuf); + ret = vfs_lstat_smb_fname(handle->conn, fname, &sbuf); } else { - ret = SMB_VFS_STAT(handle->conn, fname, &sbuf); + ret = vfs_stat_smb_fname(handle->conn, fname, &sbuf); } } diff --git a/source3/modules/vfs_xattr_tdb.c b/source3/modules/vfs_xattr_tdb.c index 4e37ed6477..39adfdfe15 100644 --- a/source3/modules/vfs_xattr_tdb.c +++ b/source3/modules/vfs_xattr_tdb.c @@ -215,7 +215,7 @@ static ssize_t xattr_tdb_getxattr(struct vfs_handle_struct *handle, SMB_VFS_HANDLE_GET_DATA(handle, db, struct db_context, return -1); - if (SMB_VFS_STAT(handle->conn, path, &sbuf) == -1) { + if (vfs_stat_smb_fname(handle->conn, path, &sbuf) == -1) { return -1; } @@ -337,7 +337,7 @@ static int xattr_tdb_setxattr(struct vfs_handle_struct *handle, SMB_VFS_HANDLE_GET_DATA(handle, db, struct db_context, return -1); - if (SMB_VFS_STAT(handle->conn, path, &sbuf) == -1) { + if (vfs_stat_smb_fname(handle->conn, path, &sbuf) == -1) { return -1; } @@ -442,7 +442,7 @@ static ssize_t xattr_tdb_listxattr(struct vfs_handle_struct *handle, SMB_VFS_HANDLE_GET_DATA(handle, db, struct db_context, return -1); - if (SMB_VFS_STAT(handle->conn, path, &sbuf) == -1) { + if (vfs_stat_smb_fname(handle->conn, path, &sbuf) == -1) { return -1; } @@ -542,7 +542,7 @@ static int xattr_tdb_removexattr(struct vfs_handle_struct *handle, SMB_VFS_HANDLE_GET_DATA(handle, db, struct db_context, return -1); - if (SMB_VFS_STAT(handle->conn, path, &sbuf) == -1) { + if (vfs_stat_smb_fname(handle->conn, path, &sbuf) == -1) { return -1; } @@ -621,7 +621,7 @@ static int xattr_tdb_unlink(vfs_handle_struct *handle, const char *path) SMB_VFS_HANDLE_GET_DATA(handle, db, struct db_context, return -1); - if (SMB_VFS_STAT(handle->conn, path, &sbuf) == -1) { + if (vfs_stat_smb_fname(handle->conn, path, &sbuf) == -1) { return -1; } @@ -660,7 +660,7 @@ static int xattr_tdb_rmdir(vfs_handle_struct *handle, const char *path) SMB_VFS_HANDLE_GET_DATA(handle, db, struct db_context, return -1); - if (SMB_VFS_STAT(handle->conn, path, &sbuf) == -1) { + if (vfs_stat_smb_fname(handle->conn, path, &sbuf) == -1) { return -1; } -- cgit