mirror of https://github.com/neutrinolabs/xrdp
Implement O_WRONLY option for open file
Allows files to be overwritten on Linux without EIO Logging improved on failed write
This commit is contained in:
parent
c43c9cd551
commit
ef9013b4d9
|
@ -72,7 +72,7 @@ int xfuse_file_contents_size(int stream_id, int file_size) { r
|
||||||
int xfuse_add_clip_dir_item(const char *filename, int flags, int size, int lindex) { return 0; }
|
int xfuse_add_clip_dir_item(const char *filename, int flags, int size, int lindex) { return 0; }
|
||||||
int xfuse_create_share(tui32 device_id, const char *dirname) { return 0; }
|
int xfuse_create_share(tui32 device_id, const char *dirname) { return 0; }
|
||||||
void xfuse_devredir_cb_open_file(void *vp, tui32 IoStatus, tui32 DeviceId, tui32 FileId) {}
|
void xfuse_devredir_cb_open_file(void *vp, tui32 IoStatus, tui32 DeviceId, tui32 FileId) {}
|
||||||
void xfuse_devredir_cb_write_file(void *vp, const char *buf, size_t length) {}
|
void xfuse_devredir_cb_write_file(void *vp, tui32 IoStatus, const char *buf, size_t length) {}
|
||||||
void xfuse_devredir_cb_read_file(void *vp, const char *buf, size_t length) {}
|
void xfuse_devredir_cb_read_file(void *vp, const char *buf, size_t length) {}
|
||||||
int xfuse_devredir_cb_enum_dir(void *vp, struct xrdp_inode *xinode) { return 0; }
|
int xfuse_devredir_cb_enum_dir(void *vp, struct xrdp_inode *xinode) { return 0; }
|
||||||
void xfuse_devredir_cb_enum_dir_done(void *vp, tui32 IoStatus) {}
|
void xfuse_devredir_cb_enum_dir_done(void *vp, tui32 IoStatus) {}
|
||||||
|
@ -1639,12 +1639,12 @@ void xfuse_devredir_cb_open_file(void *vp, tui32 IoStatus, tui32 DeviceId,
|
||||||
{
|
{
|
||||||
switch (IoStatus)
|
switch (IoStatus)
|
||||||
{
|
{
|
||||||
case 0xC0000022:
|
case NT_STATUS_ACCESS_DENIED:
|
||||||
fuse_reply_err(fip->req, EACCES);
|
fuse_reply_err(fip->req, EACCES);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0xC0000033:
|
case NT_STATUS_OBJECT_NAME_INVALID:
|
||||||
case 0xC0000034:
|
case NT_STATUS_OBJECT_NAME_NOT_FOUND:
|
||||||
fuse_reply_err(fip->req, ENOENT);
|
fuse_reply_err(fip->req, ENOENT);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -1762,7 +1762,10 @@ void xfuse_devredir_cb_read_file(void *vp, const char *buf, size_t length)
|
||||||
free(fip);
|
free(fip);
|
||||||
}
|
}
|
||||||
|
|
||||||
void xfuse_devredir_cb_write_file(void *vp, const char *buf, size_t length)
|
void xfuse_devredir_cb_write_file(void *vp,
|
||||||
|
tui32 IoStatus,
|
||||||
|
const char *buf,
|
||||||
|
size_t length)
|
||||||
{
|
{
|
||||||
XRDP_INODE *xinode;
|
XRDP_INODE *xinode;
|
||||||
XFUSE_INFO *fip;
|
XFUSE_INFO *fip;
|
||||||
|
@ -1771,20 +1774,34 @@ void xfuse_devredir_cb_write_file(void *vp, const char *buf, size_t length)
|
||||||
if ((fip == NULL) || (fip->req == NULL) || (fip->fi == NULL))
|
if ((fip == NULL) || (fip->req == NULL) || (fip->fi == NULL))
|
||||||
{
|
{
|
||||||
log_error("fip, fip->req or fip->fi is NULL");
|
log_error("fip, fip->req or fip->fi is NULL");
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
log_debug("+++ XFUSE_INFO=%p, XFUSE_INFO->fi=%p XFUSE_INFO->fi->fh=0x%llx",
|
|
||||||
fip, fip->fi, (long long) fip->fi->fh);
|
|
||||||
|
|
||||||
fuse_reply_write(fip->req, length);
|
|
||||||
|
|
||||||
/* update file size */
|
|
||||||
if ((xinode = g_xrdp_fs.inode_table[fip->inode]) != NULL)
|
|
||||||
xinode->size += length;
|
|
||||||
else
|
else
|
||||||
log_error("inode at inode_table[%ld] is NULL", fip->inode);
|
{
|
||||||
|
log_debug(
|
||||||
|
"+++ XFUSE_INFO=%p, XFUSE_INFO->fi=%p XFUSE_INFO->fi->fh=0x%llx",
|
||||||
|
fip, fip->fi, (long long) fip->fi->fh);
|
||||||
|
|
||||||
|
if (IoStatus != NT_STATUS_SUCCESS)
|
||||||
|
{
|
||||||
|
log_error("Write NTSTATUS is %d", (int) IoStatus);
|
||||||
|
fuse_reply_err(fip->req, EIO);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
fuse_reply_write(fip->req, length);
|
||||||
|
|
||||||
|
/* update file size */
|
||||||
|
if ((xinode = g_xrdp_fs.inode_table[fip->inode]) != NULL)
|
||||||
|
{
|
||||||
|
xinode->size += length;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
log_error("inode at inode_table[%ld] is NULL", fip->inode);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
free(fip);
|
free(fip);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2551,11 +2568,24 @@ static void xfuse_cb_open(fuse_req_t req, fuse_ino_t ino,
|
||||||
}
|
}
|
||||||
if (xinode->mode & S_IFDIR)
|
if (xinode->mode & S_IFDIR)
|
||||||
{
|
{
|
||||||
log_debug("reading a dir not allowed!");
|
log_debug("reading/writing a dir not allowed!");
|
||||||
fuse_reply_err(req, EISDIR);
|
fuse_reply_err(req, EISDIR);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
switch (fi->flags & O_ACCMODE)
|
||||||
|
{
|
||||||
|
case O_RDONLY:
|
||||||
|
case O_WRONLY:
|
||||||
|
case O_RDWR:
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
log_debug("Invalid access mode specified");
|
||||||
|
fuse_reply_err(req, EINVAL);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
device_id = xfuse_get_device_id_for_inode(ino, full_path);
|
device_id = xfuse_get_device_id_for_inode(ino, full_path);
|
||||||
|
|
||||||
if (xinode->is_loc_resource)
|
if (xinode->is_loc_resource)
|
||||||
|
@ -2594,7 +2624,12 @@ static void xfuse_cb_open(fuse_req_t req, fuse_ino_t ino,
|
||||||
{
|
{
|
||||||
cptr = "\\";
|
cptr = "\\";
|
||||||
}
|
}
|
||||||
/* get dev_redir to open the remote file */
|
/* get dev_redir to open the remote file
|
||||||
|
*
|
||||||
|
* For a successful call, if the caller has set O_TRUNC when writing
|
||||||
|
* the file, fuse should call us back via fuse_cb_setattr() to set
|
||||||
|
* the size to zero - we don't need to do this ourselves.
|
||||||
|
*/
|
||||||
if (dev_redir_file_open((void *) fip, device_id, cptr,
|
if (dev_redir_file_open((void *) fip, device_id, cptr,
|
||||||
fi->flags, S_IFREG, NULL))
|
fi->flags, S_IFREG, NULL))
|
||||||
{
|
{
|
||||||
|
|
|
@ -58,7 +58,11 @@ int xfuse_add_clip_dir_item(const char *filename, int flags, int size, int linde
|
||||||
int xfuse_devredir_cb_enum_dir(void *vp, struct xrdp_inode *xinode);
|
int xfuse_devredir_cb_enum_dir(void *vp, struct xrdp_inode *xinode);
|
||||||
void xfuse_devredir_cb_enum_dir_done(void *vp, tui32 IoStatus);
|
void xfuse_devredir_cb_enum_dir_done(void *vp, tui32 IoStatus);
|
||||||
void xfuse_devredir_cb_open_file(void *vp, tui32 IoStatus, tui32 DeviceId, tui32 FileId);
|
void xfuse_devredir_cb_open_file(void *vp, tui32 IoStatus, tui32 DeviceId, tui32 FileId);
|
||||||
void xfuse_devredir_cb_write_file(void *vp, const char *buf, size_t length);
|
void xfuse_devredir_cb_write_file(
|
||||||
|
void *vp,
|
||||||
|
tui32 IoStatus,
|
||||||
|
const char *buf,
|
||||||
|
size_t length);
|
||||||
void xfuse_devredir_cb_read_file(void *vp, const char *buf, size_t length);
|
void xfuse_devredir_cb_read_file(void *vp, const char *buf, size_t length);
|
||||||
void xfuse_devredir_cb_rmdir_or_file(void *vp, tui32 IoStatus);
|
void xfuse_devredir_cb_rmdir_or_file(void *vp, tui32 IoStatus);
|
||||||
void xfuse_devredir_cb_rename_file(void *vp, tui32 IoStatus);
|
void xfuse_devredir_cb_rename_file(void *vp, tui32 IoStatus);
|
||||||
|
|
|
@ -822,7 +822,8 @@ dev_redir_proc_device_iocompletion(struct stream *s)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
xfuse_devredir_cb_write_file(fuse_data->data_ptr, s->p, Length);
|
xfuse_devredir_cb_write_file(fuse_data->data_ptr, IoStatus,
|
||||||
|
s->p, Length);
|
||||||
devredir_irp_delete(irp);
|
devredir_irp_delete(irp);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -1107,14 +1108,30 @@ dev_redir_file_open(void *fusep, tui32 device_id, const char *path,
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
log_debug("open file in O_RDWR");
|
|
||||||
#if 1
|
#if 1
|
||||||
/* without the 0x00000010 rdesktop opens files in */
|
switch(mode & O_ACCMODE)
|
||||||
/* O_RDONLY instead of O_RDWR mode */
|
{
|
||||||
if (mode & O_RDWR)
|
case O_RDONLY:
|
||||||
DesiredAccess = DA_FILE_READ_DATA | DA_FILE_WRITE_DATA | DA_SYNCHRONIZE | 0x00000010;
|
log_debug("open file in O_RDONLY");
|
||||||
else
|
DesiredAccess = DA_FILE_READ_DATA | DA_SYNCHRONIZE;
|
||||||
DesiredAccess = DA_FILE_READ_DATA | DA_SYNCHRONIZE;
|
break;
|
||||||
|
|
||||||
|
case O_WRONLY:
|
||||||
|
log_debug("open file in O_WRONLY");
|
||||||
|
DesiredAccess = DA_FILE_WRITE_DATA | DA_SYNCHRONIZE;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
/*
|
||||||
|
* The access mode could conceivably be invalid here,
|
||||||
|
* but we assume this has been checked by the caller
|
||||||
|
*/
|
||||||
|
log_debug("open file in O_RDWR");
|
||||||
|
/* without the 0x00000010 rdesktop opens files in */
|
||||||
|
/* O_RDONLY instead of O_RDWR mode */
|
||||||
|
DesiredAccess = DA_FILE_READ_DATA | DA_FILE_WRITE_DATA |
|
||||||
|
DA_SYNCHRONIZE | 0x00000010;
|
||||||
|
}
|
||||||
|
|
||||||
CreateOptions = CO_FILE_SYNCHRONOUS_IO_NONALERT;
|
CreateOptions = CO_FILE_SYNCHRONOUS_IO_NONALERT;
|
||||||
CreateDisposition = CD_FILE_OPEN; // WAS 1
|
CreateDisposition = CD_FILE_OPEN; // WAS 1
|
||||||
|
@ -1283,7 +1300,7 @@ dev_redir_file_write(void *fusep, tui32 DeviceId, tui32 FileId,
|
||||||
if ((irp = devredir_irp_find_by_fileid(FileId)) == NULL)
|
if ((irp = devredir_irp_find_by_fileid(FileId)) == NULL)
|
||||||
{
|
{
|
||||||
log_error("no IRP found with FileId = %d", FileId);
|
log_error("no IRP found with FileId = %d", FileId);
|
||||||
xfuse_devredir_cb_write_file(fusep, NULL, 0);
|
xfuse_devredir_cb_write_file(fusep, NT_STATUS_UNSUCCESSFUL, NULL, 0);
|
||||||
xstream_free(s);
|
xstream_free(s);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
@ -1292,7 +1309,7 @@ dev_redir_file_write(void *fusep, tui32 DeviceId, tui32 FileId,
|
||||||
if ((new_irp = devredir_irp_clone(irp)) == NULL)
|
if ((new_irp = devredir_irp_clone(irp)) == NULL)
|
||||||
{
|
{
|
||||||
/* system out of memory */
|
/* system out of memory */
|
||||||
xfuse_devredir_cb_write_file(fusep, NULL, 0);
|
xfuse_devredir_cb_write_file(fusep, NT_STATUS_UNSUCCESSFUL, NULL, 0);
|
||||||
xstream_free(s);
|
xstream_free(s);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
|
@ -260,6 +260,9 @@ enum CREATE_OPTIONS
|
||||||
|
|
||||||
#define NT_STATUS_SUCCESS 0x00000000
|
#define NT_STATUS_SUCCESS 0x00000000
|
||||||
#define NT_STATUS_UNSUCCESSFUL 0xC0000001
|
#define NT_STATUS_UNSUCCESSFUL 0xC0000001
|
||||||
|
#define NT_STATUS_ACCESS_DENIED 0xC0000022
|
||||||
|
#define NT_STATUS_OBJECT_NAME_INVALID 0xC0000033
|
||||||
|
#define NT_STATUS_OBJECT_NAME_NOT_FOUND 0xC0000034
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* File system ioctl codes
|
* File system ioctl codes
|
||||||
|
|
Loading…
Reference in New Issue