static int streams_xattr_fstat(vfs_handle_struct *handle, files_struct *fsp, SMB_STRUCT_STAT *sbuf) { struct smb_filename *smb_fname_base = NULL; int ret = -1; struct stream_io *io = (struct stream_io *) VFS_FETCH_FSP_EXTENSION(handle, fsp); if (io == NULL || fsp->base_fsp == NULL) { return SMB_VFS_NEXT_FSTAT(handle, fsp, sbuf); } DBG_DEBUG("streams_xattr_fstat called for %s\n", fsp_str_dbg(io->fsp)); if (!streams_xattr_recheck(io)) { return -1; } /* Create an smb_filename with stream_name == NULL. */ smb_fname_base = synthetic_smb_fname(talloc_tos(), io->base, NULL, NULL, fsp->fsp_name->flags); if (smb_fname_base == NULL) { errno = ENOMEM; return -1; } if (smb_fname_base->flags & SMB_FILENAME_POSIX_PATH) { ret = SMB_VFS_LSTAT(handle->conn, smb_fname_base); } else { ret = SMB_VFS_STAT(handle->conn, smb_fname_base); } *sbuf = smb_fname_base->st; if (ret == -1) { TALLOC_FREE(smb_fname_base); return -1; } sbuf->st_ex_size = get_xattr_size(handle->conn, smb_fname_base, io->xattr_name); if (sbuf->st_ex_size == -1) { TALLOC_FREE(smb_fname_base); SET_STAT_INVALID(*sbuf); return -1; } DEBUG(10, ("sbuf->st_ex_size = %d\n", (int)sbuf->st_ex_size)); sbuf->st_ex_ino = stream_inode(sbuf, io->xattr_name); sbuf->st_ex_mode &= ~S_IFMT; sbuf->st_ex_mode &= ~S_IFDIR; sbuf->st_ex_mode |= S_IFREG; sbuf->st_ex_blocks = sbuf->st_ex_size / STAT_ST_BLOCKSIZE + 1; TALLOC_FREE(smb_fname_base); return 0; }
static int streams_xattr_stat(vfs_handle_struct *handle, struct smb_filename *smb_fname) { NTSTATUS status; int result = -1; char *xattr_name = NULL; if (!is_ntfs_stream_smb_fname(smb_fname)) { return SMB_VFS_NEXT_STAT(handle, smb_fname); } /* Note if lp_posix_paths() is true, we can never * get here as is_ntfs_stream_smb_fname() is * always false. So we never need worry about * not following links here. */ /* 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); } /* Populate the stat struct with info from the base file. */ if (streams_xattr_stat_base(handle, smb_fname, true) == -1) { return -1; } /* Derive the xattr name to lookup. */ status = streams_xattr_get_name(handle, talloc_tos(), smb_fname->stream_name, &xattr_name); if (!NT_STATUS_IS_OK(status)) { errno = map_errno_from_nt_status(status); return -1; } /* Augment the base file's stat information before returning. */ smb_fname->st.st_ex_size = get_xattr_size(handle->conn, smb_fname, xattr_name); if (smb_fname->st.st_ex_size == -1) { SET_STAT_INVALID(smb_fname->st); errno = ENOENT; result = -1; goto fail; } 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_IFDIR; 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(xattr_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); DEBUG(10, ("streams_xattr_fstat called for %d\n", fsp->fh->fd)); if (io == NULL || fsp->base_fsp == NULL) { return SMB_VFS_NEXT_FSTAT(handle, fsp, sbuf); } if (!streams_xattr_recheck(io)) { 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, smb_fname_base); } else { ret = SMB_VFS_STAT(handle->conn, smb_fname_base); } *sbuf = smb_fname_base->st; TALLOC_FREE(smb_fname_base); if (ret == -1) { return -1; } sbuf->st_ex_size = get_xattr_size(handle->conn, fsp->base_fsp, io->base, io->xattr_name); if (sbuf->st_ex_size == -1) { return -1; } DEBUG(10, ("sbuf->st_ex_size = %d\n", (int)sbuf->st_ex_size)); sbuf->st_ex_ino = stream_inode(sbuf, io->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; return 0; }