summaryrefslogtreecommitdiff
path: root/source3/modules/vfs_streams_xattr.c
diff options
context:
space:
mode:
authorTim Prouty <tprouty@samba.org>2009-06-22 15:26:56 -0700
committerTim Prouty <tprouty@samba.org>2009-06-24 21:15:25 -0700
commite129384d7c1df664e447186673dd107e190e2894 (patch)
tree166c08e9d2ee0bbb8a88fb2ad76ed226a62f83dc /source3/modules/vfs_streams_xattr.c
parent36c10191750c845a2a7cd6cc62149b1095c0b651 (diff)
downloadsamba-e129384d7c1df664e447186673dd107e190e2894.tar.gz
samba-e129384d7c1df664e447186673dd107e190e2894.tar.bz2
samba-e129384d7c1df664e447186673dd107e190e2894.zip
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.
Diffstat (limited to 'source3/modules/vfs_streams_xattr.c')
-rw-r--r--source3/modules/vfs_streams_xattr.c160
1 files changed, 98 insertions, 62 deletions
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);
}
}