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_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; }
static ssize_t streams_xattr_pread(vfs_handle_struct *handle, files_struct *fsp, void *data, size_t n, off_t offset) { struct stream_io *sio = (struct stream_io *)VFS_FETCH_FSP_EXTENSION(handle, fsp); struct ea_struct ea; NTSTATUS status; size_t length, overlap; struct smb_filename *smb_fname_base = NULL; DEBUG(10, ("streams_xattr_pread: offset=%d, size=%d\n", (int)offset, (int)n)); if (sio == NULL) { return SMB_VFS_NEXT_PREAD(handle, fsp, data, n, offset); } if (!streams_xattr_recheck(sio)) { return -1; } /* Create an smb_filename with stream_name == NULL. */ smb_fname_base = synthetic_smb_fname(talloc_tos(), sio->base, NULL, NULL, fsp->fsp_name->flags); if (smb_fname_base == NULL) { errno = ENOMEM; return -1; } status = get_ea_value(talloc_tos(), handle->conn, NULL, smb_fname_base, sio->xattr_name, &ea); if (!NT_STATUS_IS_OK(status)) { return -1; } length = ea.value.length-1; DEBUG(10, ("streams_xattr_pread: get_ea_value returned %d bytes\n", (int)length)); /* Attempt to read past EOF. */ if (length <= offset) { return 0; } overlap = (offset + n) > length ? (length - offset) : n; memcpy(data, ea.value.data + offset, overlap); TALLOC_FREE(ea.value.data); return overlap; }
static int prealloc_ftruncate(vfs_handle_struct * handle, files_struct * fsp, SMB_OFF_T offset) { SMB_OFF_T *psize; int ret = SMB_VFS_NEXT_FTRUNCATE(handle, fsp, offset); /* Maintain the allocated space even in the face of truncates. */ if ((psize = VFS_FETCH_FSP_EXTENSION(handle, fsp))) { preallocate_space(fsp->fh->fd, *psize); } return ret; }
static int prealloc_ftruncate(vfs_handle_struct * handle, files_struct * fsp, int fd, SMB_OFF_T offset) { SMB_OFF_T *psize; int ret = SMB_VFS_NEXT_FTRUNCATE(handle, fsp, fd, offset); /* Maintain the allocated space even in the face of truncates. If the * truncate succeeded, we know that the current file size is the size * the caller requested. */ if (ret == 0 ) { if ((psize = VFS_FETCH_FSP_EXTENSION(handle, fsp))) { preallocate_space(fd, offset, *psize); } } return ret; }
static ssize_t streams_xattr_pwrite(vfs_handle_struct *handle, files_struct *fsp, const void *data, size_t n, off_t offset) { struct stream_io *sio = (struct stream_io *)VFS_FETCH_FSP_EXTENSION(handle, fsp); struct ea_struct ea; NTSTATUS status; struct smb_filename *smb_fname_base = NULL; int ret; DEBUG(10, ("streams_xattr_pwrite called for %d bytes\n", (int)n)); if (sio == NULL) { return SMB_VFS_NEXT_PWRITE(handle, fsp, data, n, offset); } if (!streams_xattr_recheck(sio)) { return -1; } /* Create an smb_filename with stream_name == NULL. */ smb_fname_base = synthetic_smb_fname(talloc_tos(), sio->base, NULL, NULL, fsp->fsp_name->flags); if (smb_fname_base == NULL) { errno = ENOMEM; return -1; } status = get_ea_value(talloc_tos(), handle->conn, NULL, smb_fname_base, sio->xattr_name, &ea); if (!NT_STATUS_IS_OK(status)) { return -1; } if ((offset + n) > ea.value.length-1) { uint8_t *tmp; tmp = talloc_realloc(talloc_tos(), ea.value.data, uint8_t, offset + n + 1); if (tmp == NULL) { TALLOC_FREE(ea.value.data); errno = ENOMEM; return -1; } ea.value.data = tmp; ea.value.length = offset + n + 1; ea.value.data[offset+n] = 0; } memcpy(ea.value.data + offset, data, n); ret = SMB_VFS_SETXATTR(fsp->conn, fsp->fsp_name, sio->xattr_name, ea.value.data, ea.value.length, 0); TALLOC_FREE(ea.value.data); if (ret == -1) { return -1; } return n; }