Merge pull request #1507 from matt335672/drive-redirect-fixes

Drive redirect fixes, including Guacamole
This commit is contained in:
metalefty 2020-03-11 09:33:24 +09:00 committed by GitHub
commit a57e77753f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 140 additions and 98 deletions

View File

@ -36,7 +36,8 @@ enum NTSTATUS
STATUS_ACCESS_DENIED = 0xc0000022, STATUS_ACCESS_DENIED = 0xc0000022,
STATUS_OBJECT_NAME_INVALID = 0xc0000033, STATUS_OBJECT_NAME_INVALID = 0xc0000033,
STATUS_OBJECT_NAME_NOT_FOUND = 0xc0000034, STATUS_OBJECT_NAME_NOT_FOUND = 0xc0000034,
STATUS_SHARING_VIOLATION = 0xc0000043 STATUS_SHARING_VIOLATION = 0xc0000043,
STATUS_NOT_SUPPORTED = 0xc00000bb
}; };
#endif /* MS_ERREF_H */ #endif /* MS_ERREF_H */

View File

@ -78,6 +78,7 @@ void xfuse_devredir_cb_open_file(struct state_open *fip,
tui32 DeviceId, tui32 FileId) tui32 DeviceId, tui32 FileId)
{} {}
void xfuse_devredir_cb_read_file(struct state_read *fip, void xfuse_devredir_cb_read_file(struct state_read *fip,
enum NTSTATUS IoStatus,
const char *buf, size_t length) const char *buf, size_t length)
{} {}
void xfuse_devredir_cb_write_file( void xfuse_devredir_cb_write_file(
@ -637,6 +638,7 @@ int xfuse_create_share(tui32 device_id, const char *dirname)
} }
else else
{ {
xinode->is_redirected = 1;
xinode->device_id = device_id; xinode->device_id = device_id;
result = 0; result = 0;
} }
@ -653,7 +655,7 @@ int xfuse_create_share(tui32 device_id, const char *dirname)
void xfuse_delete_share(tui32 device_id) void xfuse_delete_share(tui32 device_id)
{ {
xfs_delete_entries_with_device_id(g_xfs, device_id); xfs_delete_redirected_entries_with_device_id(g_xfs, device_id);
} }
/** /**
@ -1313,9 +1315,18 @@ void xfuse_devredir_cb_open_file(struct state_open *fip,
} }
void xfuse_devredir_cb_read_file(struct state_read *fip, void xfuse_devredir_cb_read_file(struct state_read *fip,
enum NTSTATUS IoStatus,
const char *buf, size_t length) const char *buf, size_t length)
{ {
fuse_reply_buf(fip->req, buf, length); if (IoStatus != STATUS_SUCCESS)
{
log_error("Read NTSTATUS is %d", (int) IoStatus);
fuse_reply_err(fip->req, EIO);
}
else
{
fuse_reply_buf(fip->req, buf, length);
}
free(fip); free(fip);
} }
@ -1438,7 +1449,7 @@ static void xfuse_cb_lookup(fuse_req_t req, fuse_ino_t parent, const char *name)
} }
else else
{ {
if (parent_xinode->device_id == 0) if (!parent_xinode->is_redirected)
{ {
/* File cannot be remote - we either know about it or we don't */ /* File cannot be remote - we either know about it or we don't */
if ((xinode = xfs_lookup_in_dir(g_xfs, parent, name)) != NULL) if ((xinode = xfs_lookup_in_dir(g_xfs, parent, name)) != NULL)
@ -1673,13 +1684,13 @@ static void xfuse_cb_unlink(fuse_req_t req, fuse_ino_t parent,
fuse_reply_err(req, ENOTEMPTY); fuse_reply_err(req, ENOTEMPTY);
} }
else if (xinode->device_id == 0) else if (!xinode->is_redirected)
{ {
/* specified file is a local resource */ /* specified file is a local resource */
//XFUSE_HANDLE *fh; //XFUSE_HANDLE *fh;
log_debug("LK_TODO: this is still a TODO"); log_debug("LK_TODO: this is still a TODO");
fuse_reply_err(req, EINVAL); fuse_reply_err(req, EROFS);
} }
else else
{ {
@ -1744,26 +1755,27 @@ static void xfuse_cb_rename(fuse_req_t req,
else if (!(new_parent_xinode = xfs_get(g_xfs, new_parent))) else if (!(new_parent_xinode = xfs_get(g_xfs, new_parent)))
{ {
log_error("inode %ld is not valid", new_parent); log_error("inode %ld is not valid", new_parent);
fuse_reply_err(req, EINVAL); fuse_reply_err(req, ENOENT);
} }
else if (!xfs_check_move_entry(g_xfs, old_xinode->inum, else if (!xfs_check_move_entry(g_xfs, old_xinode->inum,
new_parent, new_name)) new_parent, new_name))
{ {
/* Catchall -see rename(2). Fix when logging is improved */
fuse_reply_err(req, EINVAL); fuse_reply_err(req, EINVAL);
} }
else if (new_parent_xinode->device_id != old_xinode->device_id) else if (new_parent_xinode->is_redirected != old_xinode->is_redirected ||
new_parent_xinode->device_id != old_xinode->device_id)
{ {
log_error("rename across file systems not supported"); fuse_reply_err(req, EXDEV);
fuse_reply_err(req, EINVAL);
} }
else if (old_xinode->device_id == 0) else if (!old_xinode->is_redirected)
{ {
/* specified file is a local resource */ /* specified file is a local resource */
log_debug("LK_TODO: this is still a TODO"); log_debug("LK_TODO: this is still a TODO");
fuse_reply_err(req, EINVAL); fuse_reply_err(req, EROFS);
} }
else else
@ -1853,20 +1865,25 @@ static void xfuse_create_dir_or_file(fuse_req_t req, fuse_ino_t parent,
} }
/* is parent inode valid? */ /* is parent inode valid? */
if (parent == FUSE_ROOT_ID || if (parent == FUSE_ROOT_ID)
(xinode = xfs_get(g_xfs, parent)) == NULL || {
(xinode->mode & S_IFDIR) == 0) fuse_reply_err(req, EROFS);
}
else if ((xinode = xfs_get(g_xfs, parent)) == NULL)
{ {
log_error("inode %ld is not valid", parent);
fuse_reply_err(req, ENOENT); fuse_reply_err(req, ENOENT);
} }
else if (xinode->device_id == 0) else if ((xinode->mode & S_IFDIR) == 0)
{
fuse_reply_err(req, ENOTDIR);
}
else if (!xinode->is_redirected)
{ {
/* specified file is a local resource */ /* specified file is a local resource */
//XFUSE_HANDLE *fh; //XFUSE_HANDLE *fh;
log_debug("LK_TODO: this is still a TODO"); log_debug("LK_TODO: this is still a TODO");
fuse_reply_err(req, EINVAL); fuse_reply_err(req, EROFS);
} }
else else
{ {
@ -1945,13 +1962,20 @@ static void xfuse_cb_open(fuse_req_t req, fuse_ino_t ino,
log_debug("Invalid access mode specified"); log_debug("Invalid access mode specified");
fuse_reply_err(req, EINVAL); fuse_reply_err(req, EINVAL);
} }
else if (xinode->device_id == 0) else if (!xinode->is_redirected)
{ {
/* specified file is a local resource */ /* specified file is a local resource */
XFUSE_HANDLE *fh = g_new0(XFUSE_HANDLE, 1); if ((fi->flags & O_ACCMODE) != O_RDONLY)
fh->is_loc_resource = 1; {
fi->fh = (tintptr) fh; fuse_reply_err(req, EROFS);
fuse_reply_open(req, fi); }
else
{
XFUSE_HANDLE *fh = g_new0(XFUSE_HANDLE, 1);
fh->is_loc_resource = 1;
fi->fh = (tintptr) fh;
fuse_reply_open(req, fi);
}
} }
else else
{ {
@ -2017,7 +2041,7 @@ static void xfuse_cb_release(fuse_req_t req, fuse_ino_t ino, struct
log_error("inode %ld is not valid", ino); log_error("inode %ld is not valid", ino);
fuse_reply_err(req, ENOENT); fuse_reply_err(req, ENOENT);
} }
else if (xinode->device_id == 0) else if (!xinode->is_redirected)
{ {
/* specified file is a local resource */ /* specified file is a local resource */
fuse_reply_err(req, 0); fuse_reply_err(req, 0);
@ -2153,7 +2177,7 @@ static void xfuse_cb_write(fuse_req_t req, fuse_ino_t ino, const char *buf,
{ {
/* target file is in .clipboard dir */ /* target file is in .clipboard dir */
log_debug("THIS IS STILL A TODO!"); log_debug("THIS IS STILL A TODO!");
fuse_reply_err(req, EINVAL); fuse_reply_err(req, EROFS);
} }
else else
{ {
@ -2283,7 +2307,7 @@ static void xfuse_cb_setattr(fuse_req_t req, fuse_ino_t ino, struct stat *attr,
/* No changes have been made */ /* No changes have been made */
make_fuse_attr_reply(req, xinode); make_fuse_attr_reply(req, xinode);
} }
else if (xinode->device_id == 0) else if (!xinode->is_redirected)
{ {
/* Update the local fs */ /* Update the local fs */
update_inode_file_attributes(&attrs, change_mask, xinode); update_inode_file_attributes(&attrs, change_mask, xinode);
@ -2349,7 +2373,7 @@ static void xfuse_cb_opendir(fuse_req_t req, fuse_ino_t ino,
log_error("inode %ld is not valid", ino); log_error("inode %ld is not valid", ino);
fuse_reply_err(req, ENOENT); fuse_reply_err(req, ENOENT);
} }
else if (xinode->device_id == 0) else if (!xinode->is_redirected)
{ {
if ((fi->fh = (tintptr) xfs_opendir(g_xfs, ino)) == 0) if ((fi->fh = (tintptr) xfs_opendir(g_xfs, ino)) == 0)
{ {

View File

@ -98,6 +98,7 @@ void xfuse_devredir_cb_open_file(struct state_open *fip,
tui32 DeviceId, tui32 FileId); tui32 DeviceId, tui32 FileId);
void xfuse_devredir_cb_read_file(struct state_read *fip, void xfuse_devredir_cb_read_file(struct state_read *fip,
enum NTSTATUS IoStatus,
const char *buf, size_t length); const char *buf, size_t length);
void xfuse_devredir_cb_write_file( void xfuse_devredir_cb_write_file(
struct state_write *fip, struct state_write *fip,

View File

@ -344,6 +344,7 @@ xfs_create_xfs_fs(mode_t umask, uid_t uid, gid_t gid)
xino1->pub.ctime = xino1->pub.atime; xino1->pub.ctime = xino1->pub.atime;
strcpy(xino1->pub.name, "."); strcpy(xino1->pub.name, ".");
xino1->pub.generation = xfs->generation; xino1->pub.generation = xfs->generation;
xino1->pub.is_redirected = 0;
xino1->pub.device_id = 0; xino1->pub.device_id = 0;
/* /*
@ -365,6 +366,7 @@ xfs_create_xfs_fs(mode_t umask, uid_t uid, gid_t gid)
xino2->pub.ctime = xino2->pub.atime; xino2->pub.ctime = xino2->pub.atime;
strcpy(xino2->pub.name, ".delete-pending"); strcpy(xino2->pub.name, ".delete-pending");
xino2->pub.generation = xfs->generation; xino2->pub.generation = xfs->generation;
xino2->pub.is_redirected = 0;
xino2->pub.device_id = 0; xino2->pub.device_id = 0;
xino2->parent = NULL; xino2->parent = NULL;
@ -469,6 +471,7 @@ xfs_add_entry(struct xfs_fs *xfs, fuse_ino_t parent_inum,
xino->pub.ctime = xino->pub.atime; xino->pub.ctime = xino->pub.atime;
strcpy(xino->pub.name, name); strcpy(xino->pub.name, name);
xino->pub.generation = xfs->generation; xino->pub.generation = xfs->generation;
xino->pub.is_redirected = parent->pub.is_redirected;
xino->pub.device_id = parent->pub.device_id; xino->pub.device_id = parent->pub.device_id;
xino->pub.lindex = 0; xino->pub.lindex = 0;
@ -565,7 +568,7 @@ xfs_get_full_path(struct xfs_fs *xfs, fuse_ino_t inum)
*/ */
size_t len = 0; size_t len = 0;
XFS_INODE_ALL *p; XFS_INODE_ALL *p;
for (p = xino ; p->pub.inum != FUSE_ROOT_ID ; p = p->parent) for (p = xino ; p && p->pub.inum != FUSE_ROOT_ID ; p = p->parent)
{ {
len += strlen(p->pub.name); len += strlen(p->pub.name);
++len; /* Allow for '/' prefix */ ++len; /* Allow for '/' prefix */
@ -578,7 +581,7 @@ xfs_get_full_path(struct xfs_fs *xfs, fuse_ino_t inum)
char *end = result + len; char *end = result + len;
*end = '\0'; *end = '\0';
for (p = xino ; p->pub.inum != FUSE_ROOT_ID ; p = p->parent) for (p = xino ; p && p->pub.inum != FUSE_ROOT_ID ; p = p->parent)
{ {
len = strlen(p->pub.name); len = strlen(p->pub.name);
end -= (len + 1); end -= (len + 1);
@ -816,35 +819,35 @@ xfs_get_file_open_count(struct xfs_fs *xfs, fuse_ino_t inum)
/* ------------------------------------------------------------------------ */ /* ------------------------------------------------------------------------ */
void void
xfs_delete_entries_with_device_id(struct xfs_fs *xfs, tui32 device_id) xfs_delete_redirected_entries_with_device_id(struct xfs_fs *xfs,
tui32 device_id)
{ {
fuse_ino_t inum; fuse_ino_t inum;
XFS_INODE_ALL *xino; XFS_INODE_ALL *xino;
if (device_id != 0) /* Using xfs_remove_entry() is convenient, but it recurses
* in to directories. To make sure all entries are removed, set the
* open_count of all affected files to 0 first
*/
for (inum = FUSE_ROOT_ID; inum < xfs->inode_count; ++inum)
{ {
/* Using xfs_remove_entry() is convenient, but it recurses if ((xino = xfs->inode_table[inum]) != NULL &&
* in to directories. To make sure all entries are removed, set the xino->pub.is_redirected != 0 &&
* open_count of all affected files to 0 first xino->pub.device_id == device_id &&
*/ (xino->pub.mode & S_IFREG) != 0)
for (inum = FUSE_ROOT_ID; inum < xfs->inode_count; ++inum)
{ {
if ((xino = xfs->inode_table[inum]) != NULL && xino->open_count = 0;
xino->pub.device_id == device_id &&
(xino->pub.mode & S_IFREG) != 0)
{
xino->open_count = 0;
}
} }
}
/* Now we can be sure everything will be deleted correctly */ /* Now we can be sure everything will be deleted correctly */
for (inum = FUSE_ROOT_ID; inum < xfs->inode_count; ++inum) for (inum = FUSE_ROOT_ID; inum < xfs->inode_count; ++inum)
{
if ((xino = xfs->inode_table[inum]) != NULL &&
xino->pub.is_redirected != 0 &&
xino->pub.device_id == device_id)
{ {
if ((xino = xfs->inode_table[inum]) != NULL && xfs_remove_entry(xfs, xino->pub.inum);
xino->pub.device_id == device_id)
{
xfs_remove_entry(xfs, xino->pub.inum);
}
} }
} }
} }

View File

@ -49,9 +49,8 @@ typedef struct xfs_inode
time_t ctime; /* Time of last status change. */ time_t ctime; /* Time of last status change. */
char name[XFS_MAXFILENAMELEN + 1]; /* Short name */ char name[XFS_MAXFILENAMELEN + 1]; /* Short name */
tui32 generation; /* Changes if inode is reused */ tui32 generation; /* Changes if inode is reused */
tui32 device_id; /* for file system redirection char is_redirected; /* file is on redirected device */
* Non-redirected devices are guaranteed tui32 device_id; /* device ID of redirected device */
* to have a device_id or zero */
int lindex; /* used in clipboard operations */ int lindex; /* used in clipboard operations */
} XFS_INODE; } XFS_INODE;
@ -271,17 +270,15 @@ unsigned int
xfs_get_file_open_count(struct xfs_fs *xfs, fuse_ino_t inum); xfs_get_file_open_count(struct xfs_fs *xfs, fuse_ino_t inum);
/* /*
* Deletes all entries with the matching device id * Deletes all redirected entries with the matching device id
* *
* Files are deleted even if they are open * Files are deleted even if they are open
* *
* The specified device_id must be non-zero so that the root
* filesystem is not deleted!
*
* @param device_id Device ID * @param device_id Device ID
*/ */
void void
xfs_delete_entries_with_device_id(struct xfs_fs *xfs, tui32 device_id); xfs_delete_redirected_entries_with_device_id(struct xfs_fs *xfs,
tui32 device_id);
/* /*
* Check an entry move will be successful * Check an entry move will be successful

View File

@ -560,7 +560,8 @@ devredir_send_server_user_logged_on(void)
} }
static void static void
devredir_send_server_device_announce_resp(tui32 device_id) devredir_send_server_device_announce_resp(tui32 device_id,
enum NTSTATUS result_code)
{ {
struct stream *s; struct stream *s;
int bytes; int bytes;
@ -571,7 +572,7 @@ devredir_send_server_device_announce_resp(tui32 device_id)
xstream_wr_u16_le(s, RDPDR_CTYP_CORE); xstream_wr_u16_le(s, RDPDR_CTYP_CORE);
xstream_wr_u16_le(s, PAKID_CORE_DEVICE_REPLY); xstream_wr_u16_le(s, PAKID_CORE_DEVICE_REPLY);
xstream_wr_u32_le(s, device_id); xstream_wr_u32_le(s, device_id);
xstream_wr_u32_le(s, 0); /* ResultCode */ xstream_wr_u32_le(s, (tui32)result_code);
/* send to client */ /* send to client */
bytes = xstream_len(s); bytes = xstream_len(s);
@ -811,6 +812,7 @@ devredir_proc_client_devlist_announce_req(struct stream *s)
tui32 device_type; tui32 device_type;
tui32 device_data_len; tui32 device_data_len;
char preferred_dos_name[9]; char preferred_dos_name[9];
enum NTSTATUS response_status;
/* get number of devices being announced */ /* get number of devices being announced */
xstream_rd_u32_le(s, device_count); xstream_rd_u32_le(s, device_count);
@ -821,19 +823,20 @@ devredir_proc_client_devlist_announce_req(struct stream *s)
{ {
xstream_rd_u32_le(s, device_type); xstream_rd_u32_le(s, device_type);
xstream_rd_u32_le(s, g_device_id); xstream_rd_u32_le(s, g_device_id);
/* get preferred DOS name
* DOS names that are 8 chars long are not NULL terminated */
for (j = 0; j < 8; j++)
{
preferred_dos_name[j] = *s->p++;
}
preferred_dos_name[8] = 0;
/* Assume this device isn't supported by us */
response_status = STATUS_NOT_SUPPORTED;
switch (device_type) switch (device_type)
{ {
case RDPDR_DTYP_FILESYSTEM: case RDPDR_DTYP_FILESYSTEM:
/* get preferred DOS name */
for (j = 0; j < 8; j++)
{
preferred_dos_name[j] = *s->p++;
}
/* DOS names that are 8 chars long are not NULL terminated */
preferred_dos_name[8] = 0;
/* get device data len */ /* get device data len */
xstream_rd_u32_le(s, device_data_len); xstream_rd_u32_le(s, device_data_len);
if (device_data_len) if (device_data_len)
@ -847,7 +850,7 @@ devredir_proc_client_devlist_announce_req(struct stream *s)
preferred_dos_name, preferred_dos_name,
device_data_len, g_full_name_for_filesystem); device_data_len, g_full_name_for_filesystem);
devredir_send_server_device_announce_resp(g_device_id); response_status = STATUS_SUCCESS;
/* create share directory in xrdp file system; */ /* create share directory in xrdp file system; */
/* think of this as the mount point for this share */ /* think of this as the mount point for this share */
@ -855,31 +858,44 @@ devredir_proc_client_devlist_announce_req(struct stream *s)
break; break;
case RDPDR_DTYP_SMARTCARD: case RDPDR_DTYP_SMARTCARD:
/* get preferred DOS name */
for (j = 0; j < 8; j++)
{
preferred_dos_name[j] = *s->p++;
}
/* DOS names that are 8 chars long are not NULL terminated */
preferred_dos_name[8] = 0;
/* for smart cards, device data len always 0 */ /* for smart cards, device data len always 0 */
log_debug("device_type=SMARTCARD device_id=0x%x dosname=%s", log_debug("device_type=SMARTCARD device_id=0x%x dosname=%s",
g_device_id, preferred_dos_name); g_device_id, preferred_dos_name);
devredir_send_server_device_announce_resp(g_device_id); response_status = STATUS_SUCCESS;
scard_device_announce(g_device_id); scard_device_announce(g_device_id);
break; break;
/* we don't yet support these devices */
case RDPDR_DTYP_SERIAL: case RDPDR_DTYP_SERIAL:
log_debug(
"device_type=SERIAL device_id=0x%x dosname=%s",
g_device_id, preferred_dos_name);
break;
case RDPDR_DTYP_PARALLEL: case RDPDR_DTYP_PARALLEL:
log_debug(
"device_type=PARALLEL device_id=0x%x dosname=%s",
g_device_id, preferred_dos_name);
break;
case RDPDR_DTYP_PRINT: case RDPDR_DTYP_PRINT:
log_debug("unsupported dev: 0x%x", device_type); log_debug(
"device_type=PRINT device_id=0x%x dosname=%s",
g_device_id, preferred_dos_name);
break;
default:
log_debug(
"device_type=UNKNOWN device_id=0x%x dosname=%s",
g_device_id, preferred_dos_name);
break; break;
} }
/* Tell the client wheth or not we're supporting this one */
devredir_send_server_device_announce_resp(g_device_id,
response_status);
} }
} }
@ -993,6 +1009,7 @@ devredir_proc_device_iocompletion(struct stream *s)
case CID_READ: case CID_READ:
xstream_rd_u32_le(s, Length); xstream_rd_u32_le(s, Length);
xfuse_devredir_cb_read_file((struct state_read *) irp->fuse_info, xfuse_devredir_cb_read_file((struct state_read *) irp->fuse_info,
IoStatus,
s->p, Length); s->p, Length);
devredir_irp_delete(irp); devredir_irp_delete(irp);
break; break;
@ -1511,10 +1528,10 @@ devredir_rmdir_or_file(struct state_remove *fusep, tui32 device_id,
/** /**
* Read data from previously opened file * Read data from previously opened file
* *
* @return 0 on success, -1 on failure * Errors are reported via xfuse_devredir_cb_read_file()
*****************************************************************************/ *****************************************************************************/
int void
devredir_file_read(struct state_read *fusep, tui32 DeviceId, tui32 FileId, devredir_file_read(struct state_read *fusep, tui32 DeviceId, tui32 FileId,
tui32 Length, tui64 Offset) tui32 Length, tui64 Offset)
{ {
@ -1522,7 +1539,6 @@ devredir_file_read(struct state_read *fusep, tui32 DeviceId, tui32 FileId,
IRP *irp; IRP *irp;
IRP *new_irp; IRP *new_irp;
int bytes; int bytes;
int rval = -1;
xstream_new(s, 1024); xstream_new(s, 1024);
@ -1530,14 +1546,14 @@ devredir_file_read(struct state_read *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_read_file(fusep, NULL, 0); xfuse_devredir_cb_read_file(fusep, STATUS_UNSUCCESSFUL, NULL, 0);
xstream_free(s); xstream_free(s);
} }
/* create a new IRP for this request */ /* create a new IRP for this request */
else if ((new_irp = devredir_irp_new()) == NULL) else if ((new_irp = devredir_irp_new()) == NULL)
{ {
/* system out of memory */ /* system out of memory */
xfuse_devredir_cb_read_file(fusep, NULL, 0); xfuse_devredir_cb_read_file(fusep, STATUS_UNSUCCESSFUL, NULL, 0);
xstream_free(s); xstream_free(s);
} }
else else
@ -1563,13 +1579,16 @@ devredir_file_read(struct state_read *fusep, tui32 DeviceId, tui32 FileId,
bytes = xstream_len(s); bytes = xstream_len(s);
send_channel_data(g_rdpdr_chan_id, s->data, bytes); send_channel_data(g_rdpdr_chan_id, s->data, bytes);
xstream_free(s); xstream_free(s);
rval = 0;
} }
return rval;
} }
int /**
* Read data from previously opened file
*
* Errors are reported via xfuse_devredir_cb_write_file()
*****************************************************************************/
void
devredir_file_write(struct state_write *fusep, tui32 DeviceId, tui32 FileId, devredir_file_write(struct state_write *fusep, tui32 DeviceId, tui32 FileId,
const char *buf, int Length, tui64 Offset) const char *buf, int Length, tui64 Offset)
{ {
@ -1577,7 +1596,6 @@ devredir_file_write(struct state_write *fusep, tui32 DeviceId, tui32 FileId,
IRP *irp; IRP *irp;
IRP *new_irp; IRP *new_irp;
int bytes; int bytes;
int rval = -1;
log_debug("DeviceId=%d FileId=%d Length=%d Offset=%lld", log_debug("DeviceId=%d FileId=%d Length=%d Offset=%lld",
DeviceId, FileId, Length, (long long)Offset); DeviceId, FileId, Length, (long long)Offset);
@ -1625,10 +1643,7 @@ devredir_file_write(struct state_write *fusep, tui32 DeviceId, tui32 FileId,
bytes = xstream_len(s); bytes = xstream_len(s);
send_channel_data(g_rdpdr_chan_id, s->data, bytes); send_channel_data(g_rdpdr_chan_id, s->data, bytes);
xstream_free(s); xstream_free(s);
rval = 0;
} }
return rval;
} }

View File

@ -78,12 +78,13 @@ int devredir_file_open(struct state_open *fusep, tui32 device_id,
int devredir_file_close(struct state_close *fusep, tui32 device_id, int devredir_file_close(struct state_close *fusep, tui32 device_id,
tui32 file_id); tui32 file_id);
int devredir_file_read(struct state_read *fusep, tui32 device_id, tui32 FileId, void
tui32 Length, tui64 Offset); devredir_file_read(struct state_read *fusep, tui32 device_id, tui32 FileId,
tui32 Length, tui64 Offset);
int void
devredir_file_write(struct state_write *fusep, tui32 DeviceId, tui32 FileId, devredir_file_write(struct state_write *fusep, tui32 DeviceId, tui32 FileId,
const char *buf, int Length, tui64 Offset); const char *buf, int Length, tui64 Offset);
int devredir_file_rename( int devredir_file_rename(
struct state_rename *fusep, tui32 device_id, struct state_rename *fusep, tui32 device_id,