summaryrefslogtreecommitdiff
path: root/source3
diff options
context:
space:
mode:
Diffstat (limited to 'source3')
-rw-r--r--source3/modules/vfs_streams_xattr.c61
-rw-r--r--source3/smbd/open.c61
2 files changed, 106 insertions, 16 deletions
diff --git a/source3/modules/vfs_streams_xattr.c b/source3/modules/vfs_streams_xattr.c
index b74c4f7902..9df88e5e19 100644
--- a/source3/modules/vfs_streams_xattr.c
+++ b/source3/modules/vfs_streams_xattr.c
@@ -624,7 +624,7 @@ static ssize_t streams_xattr_pread(vfs_handle_struct *handle,
(struct stream_io *)VFS_FETCH_FSP_EXTENSION(handle, fsp);
struct ea_struct ea;
NTSTATUS status;
- size_t length, overlap;
+ size_t length, overlap;
if (sio == NULL) {
return SMB_VFS_NEXT_PREAD(handle, fsp, data, n, offset);
@@ -651,6 +651,63 @@ static ssize_t streams_xattr_pread(vfs_handle_struct *handle,
return overlap;
}
+static int streams_xattr_ftruncate(struct vfs_handle_struct *handle,
+ struct files_struct *fsp,
+ SMB_OFF_T offset)
+{
+ int ret;
+ uint8 *tmp;
+ struct ea_struct ea;
+ NTSTATUS status;
+ struct stream_io *sio =
+ (struct stream_io *)VFS_FETCH_FSP_EXTENSION(handle, fsp);
+
+ DEBUG(10, ("streams_xattr_ftruncate called for file %s offset %.0f\n",
+ fsp->fsp_name,
+ (double)offset ));
+
+ if (sio == NULL) {
+ return SMB_VFS_NEXT_FTRUNCATE(handle, fsp, offset);
+ }
+
+ status = get_ea_value(talloc_tos(), handle->conn, fsp->base_fsp,
+ sio->base, sio->xattr_name, &ea);
+ if (!NT_STATUS_IS_OK(status)) {
+ return -1;
+ }
+
+ tmp = TALLOC_REALLOC_ARRAY(talloc_tos(), ea.value.data, uint8,
+ offset + 1);
+
+ if (tmp == NULL) {
+ TALLOC_FREE(ea.value.data);
+ errno = ENOMEM;
+ return -1;
+ }
+
+ /* Did we expand ? */
+ if (ea.value.length < offset + 1) {
+ memset(&tmp[ea.value.length], '\0',
+ offset + 1 - ea.value.length);
+ }
+
+ ea.value.data = tmp;
+ ea.value.length = offset + 1;
+ ea.value.data[offset] = 0;
+
+ ret = SMB_VFS_SETXATTR(fsp->conn, fsp->base_fsp->fsp_name,
+ sio->xattr_name,
+ ea.value.data, ea.value.length, 0);
+
+ TALLOC_FREE(ea.value.data);
+
+ if (ret == -1) {
+ return -1;
+ }
+
+ return 0;
+}
+
/* VFS operations structure */
static vfs_op_tuple streams_xattr_ops[] = {
@@ -672,6 +729,8 @@ static vfs_op_tuple streams_xattr_ops[] = {
SMB_VFS_LAYER_TRANSPARENT},
{SMB_VFS_OP(streams_xattr_unlink), SMB_VFS_OP_UNLINK,
SMB_VFS_LAYER_TRANSPARENT},
+ {SMB_VFS_OP(streams_xattr_ftruncate), SMB_VFS_OP_FTRUNCATE,
+ SMB_VFS_LAYER_TRANSPARENT},
{SMB_VFS_OP(streams_xattr_streaminfo), SMB_VFS_OP_STREAMINFO,
SMB_VFS_LAYER_OPAQUE},
{SMB_VFS_OP(NULL), SMB_VFS_OP_NOOP, SMB_VFS_LAYER_NOOP}
diff --git a/source3/smbd/open.c b/source3/smbd/open.c
index aca64917b5..a6867e077c 100644
--- a/source3/smbd/open.c
+++ b/source3/smbd/open.c
@@ -1651,7 +1651,7 @@ static NTSTATUS open_file_ntcreate_internal(connection_struct *conn,
share_access,
create_options);
- if (!NT_STATUS_IS_OK(status)) {
+ if (NT_STATUS_IS_OK(status)) {
TALLOC_FREE(lck);
if (pinfo) {
*pinfo = FILE_WAS_OPENED;
@@ -2878,10 +2878,42 @@ NTSTATUS create_file_unixpath(connection_struct *conn,
* Ordinary file case.
*/
- status = open_file_ntcreate(
- conn, req, fname, &sbuf, access_mask, share_access,
- create_disposition, create_options, file_attributes,
- oplock_request, &info, &fsp);
+ if (base_fsp) {
+ /*
+ * We're opening the stream element of a base_fsp
+ * we already opened. We need to initialize
+ * the fsp first, and set up the base_fsp pointer.
+ */
+ status = file_new(req, conn, &fsp);
+ if(!NT_STATUS_IS_OK(status)) {
+ goto fail;
+ }
+
+ fsp->base_fsp = base_fsp;
+
+ status = open_file_ntcreate_internal(conn,
+ req,
+ fname,
+ &sbuf,
+ access_mask,
+ share_access,
+ create_disposition,
+ create_options,
+ file_attributes,
+ oplock_request,
+ &info,
+ fsp);
+
+ if(!NT_STATUS_IS_OK(status)) {
+ file_free(req, fsp);
+ fsp = NULL;
+ }
+ } else {
+ status = open_file_ntcreate(
+ conn, req, fname, &sbuf, access_mask, share_access,
+ create_disposition, create_options, file_attributes,
+ oplock_request, &info, &fsp);
+ }
if (NT_STATUS_EQUAL(status, NT_STATUS_FILE_IS_A_DIRECTORY)) {
@@ -2908,6 +2940,8 @@ NTSTATUS create_file_unixpath(connection_struct *conn,
goto fail;
}
+ fsp->base_fsp = base_fsp;
+
/*
* According to the MS documentation, the only time the security
* descriptor is applied to the opened file is iff we *created* the
@@ -2994,16 +3028,6 @@ NTSTATUS create_file_unixpath(connection_struct *conn,
DEBUG(10, ("create_file_unixpath: info=%d\n", info));
- /*
- * Set fsp->base_fsp late enough that we can't "goto fail" anymore. In
- * the fail: branch we call close_file(fsp, ERROR_CLOSE) which would
- * also close fsp->base_fsp which we have to also do explicitly in
- * this routine here, as not in all "goto fail:" we have the fsp set
- * up already to be initialized with the base_fsp.
- */
-
- fsp->base_fsp = base_fsp;
-
*result = fsp;
if (pinfo != NULL) {
*pinfo = info;
@@ -3022,6 +3046,13 @@ NTSTATUS create_file_unixpath(connection_struct *conn,
DEBUG(10, ("create_file_unixpath: %s\n", nt_errstr(status)));
if (fsp != NULL) {
+ if (base_fsp && fsp->base_fsp == base_fsp) {
+ /*
+ * The close_file below will close
+ * fsp->base_fsp.
+ */
+ base_fsp = NULL;
+ }
close_file(req, fsp, ERROR_CLOSE);
fsp = NULL;
}