From 771e2248b25fdb9acc5471dc7bdcaad607928675 Mon Sep 17 00:00:00 2001 From: Laxmikant Rashinkar Date: Sun, 5 May 2013 18:42:17 -0700 Subject: [PATCH] file system redirection: made changes to support rdesktop --- sesman/chansrv/chansrv_fuse.c | 62 ++++++++++++++++++++++++++++------- sesman/chansrv/chansrv_fuse.h | 35 ++++++++++---------- sesman/chansrv/devredir.c | 53 +++++++++++++++++++----------- 3 files changed, 101 insertions(+), 49 deletions(-) diff --git a/sesman/chansrv/chansrv_fuse.c b/sesman/chansrv/chansrv_fuse.c index 1e77eebc..7ae15e49 100644 --- a/sesman/chansrv/chansrv_fuse.c +++ b/sesman/chansrv/chansrv_fuse.c @@ -196,6 +196,7 @@ struct xfuse_handle { tui32 DeviceId; tui32 FileId; + int is_loc_resource; /* this is not a redirected resource */ }; typedef struct xfuse_handle XFUSE_HANDLE; @@ -684,6 +685,7 @@ int xfuse_add_clip_dir_item(char *filename, int flags, int size, int lindex) S_IFREG); xinode->size = size; xinode->lindex = lindex; + xinode->is_loc_resource = 1; return 0; } @@ -840,6 +842,7 @@ static int xfuse_init_xrdp_fs() xino->atime = time(0); xino->mtime = time(0); xino->ctime = time(0); + xino->is_loc_resource = 1; strcpy(xino->name, ".clipboard"); g_xrdp_fs.max_entries = 4096; @@ -961,9 +964,9 @@ static void xfuse_dump_fs() if ((xinode = g_xrdp_fs.inode_table[i]) == NULL) continue; - log_debug("pinode=%d inode=%d nentries=%d dev_id=%d is_synced=%d name=%s", + log_debug("pinode=%d inode=%d nentries=%d nopen=%d is_synced=%d name=%s", (int) xinode->parent_inode, (int) xinode->inode, - xinode->nentries, xinode->device_id, xinode->is_synced, + xinode->nentries, xinode->nopen, xinode->is_synced, xinode->name); } log_debug(""); @@ -1466,6 +1469,7 @@ void xfuse_devredir_cb_enum_dir(void *vp, struct xrdp_inode *xinode) return; } + log_debug("fip->req=%p", fip->req); if (!xfuse_is_inode_valid(fip->inode)) { @@ -1527,6 +1531,8 @@ void xfuse_devredir_cb_enum_dir_done(void *vp, tui32 IoStatus) goto done; } + log_debug("fip->req=%p", fip->req); + if (IoStatus != 0) { /* command failed */ @@ -1586,18 +1592,23 @@ void xfuse_devredir_cb_enum_dir_done(void *vp, tui32 IoStatus) fuse_reply_buf(fip->req, b.p + fip->off, min(b.size - fip->off, fip->size)); #else + log_debug("calling fuse_reply_buf() with data..."); fuse_reply_buf(fip->req, b.buf, b.bytes_in_buf); + log_debug("calling fuse_reply_buf() with data...done"); #endif - fuse_reply_buf(fip->req, NULL, 0); } else { + log_debug("calling fuse_reply_buf() with NULL..."); fuse_reply_buf(fip->req, NULL, 0); + log_debug("calling fuse_reply_buf() with NULL...done"); } } else { + log_debug("calling fuse_reply_err()..."); fuse_reply_err(fip->req, ENOENT); + log_debug("calling fuse_reply_err()...done"); } done: @@ -1608,7 +1619,7 @@ done: #endif if (!fip) - printf("###### %s : %s : %d: fip is NULL\n", __FILE__, __func__, __LINE__); + log_error("fip is NULL"); if (fip) free(fip); @@ -1815,10 +1826,14 @@ void xfuse_devredir_cb_write_file(void *vp, char *buf, size_t length) XRDP_INODE *xinode; XFUSE_INFO *fip; + log_debug("entered: length=%lld", (long long) length); + fip = (XFUSE_INFO *) vp; if (fip == NULL) return; + log_debug("letting FUSE know that we wrote %lld bytes", (long long) length); + fuse_reply_write(fip->req, length); /* update file size */ @@ -1878,6 +1893,7 @@ void xfuse_devredir_cb_rename_file(void *vp, tui32 IoStatus) if (IoStatus != 0) { + log_debug("rename failed with IoStatus=0x%x", IoStatus); fuse_reply_err(fip->req, EEXIST); free(fip); return; @@ -1904,6 +1920,7 @@ void xfuse_devredir_cb_rename_file(void *vp, tui32 IoStatus) old_xinode = xfuse_get_inode_from_pinode_name(fip->inode, fip->name); if (old_xinode == NULL) { + log_debug("rename failed"); fuse_reply_err(fip->req, EBADF); free(fip); return; @@ -1942,7 +1959,10 @@ void xfuse_devredir_cb_file_close(void *vp) xinode->nopen--; if ((xinode->nopen == 0) && fip->fi && fip->fi->fh) + { free((char *) fip->fi->fh); + fip->fi->fh = NULL; + } fuse_reply_err(fip->req, 0); } @@ -2106,8 +2126,16 @@ static void xfuse_cb_readdir(fuse_req_t req, fuse_ino_t ino, size_t size, return; } + if (ino == 1) + { + /* special case; enumerate top level dir */ + log_debug("enumerating top level dir"); + xfuse_enum_dir(req, ino, size, off, fi); + return; + } + xinode = g_xrdp_fs.inode_table[ino]; - if (xinode->device_id == 0) + if (xinode->is_loc_resource) { /* enumerate local resources */ xfuse_enum_dir(req, ino, size, off, fi); @@ -2152,6 +2180,8 @@ do_remote_lookup: fip->invoke_fuse = 1; fip->device_id = device_id; + log_debug("fip->req=%p", fip->req); + /* we want path minus 'root node of the share' */ if ((cptr = strchr(full_path, '/')) == NULL) { @@ -2277,7 +2307,7 @@ static void xfuse_remove_dir_or_file(fuse_req_t req, fuse_ino_t parent, strcat(full_path, "/"); strcat(full_path, name); - if (device_id == 0) + if (xinode->is_loc_resource) { /* specified file is a local resource */ //XFUSE_HANDLE *fh; @@ -2402,7 +2432,7 @@ static void xfuse_cb_rename(fuse_req_t req, return; } - if (old_xinode->device_id == 0) + if (old_xinode->is_loc_resource) { /* specified file is a local resource */ log_debug("LK_TODO: this is still a TODO"); @@ -2508,7 +2538,8 @@ static void xfuse_create_dir_or_file(fuse_req_t req, fuse_ino_t parent, strcat(full_path, "/"); strcat(full_path, name); - if (device_id == 0) + XRDP_INODE *xinode = g_xrdp_fs.inode_table[parent]; + if (xinode->is_loc_resource) { /* specified file is a local resource */ //XFUSE_HANDLE *fh; @@ -2574,6 +2605,8 @@ static void xfuse_cb_open(fuse_req_t req, fuse_ino_t ino, char full_path[4096]; tui32 device_id; + log_debug("entered: ino=%d", (int) ino); + if (!xfuse_is_inode_valid(ino)) { log_error("inode %d is not valid", ino); @@ -2591,10 +2624,12 @@ static void xfuse_cb_open(fuse_req_t req, fuse_ino_t ino, } device_id = xfuse_get_device_id_for_inode((tui32) ino, full_path); - if (device_id == 0) + + if (xinode->is_loc_resource) { /* specified file is a local resource */ XFUSE_HANDLE *fh = calloc(1, sizeof(XFUSE_HANDLE)); + fh->is_loc_resource = 1; fi->fh = (uint64_t) ((long) fh); fuse_reply_open(req, fi); return; @@ -2647,6 +2682,8 @@ static void xfuse_cb_flush(fuse_req_t req, fuse_ino_t ino, struct XFUSE_INFO *fip = NULL; XFUSE_HANDLE *handle = (XFUSE_HANDLE *) fi->fh; + log_debug("ino=%d", (int) ino); + if (!xfuse_is_inode_valid(ino)) { log_error("inode %d is not valid", ino); @@ -2654,7 +2691,8 @@ static void xfuse_cb_flush(fuse_req_t req, fuse_ino_t ino, struct return; } - if (handle->DeviceId == 0) + XRDP_INODE *xinode = g_xrdp_fs.inode_table[ino]; + if (xinode->is_loc_resource) { /* specified file is a local resource */ fuse_reply_err(req, 0); @@ -2706,7 +2744,7 @@ static void xfuse_cb_read(fuse_req_t req, fuse_ino_t ino, size_t size, handle = fi->fh; fh = (XFUSE_HANDLE *) handle; - if (fh->DeviceId == 0) + if (fh->is_loc_resource) { /* target file is in .clipboard dir */ @@ -2776,7 +2814,7 @@ static void xfuse_cb_write(fuse_req_t req, fuse_ino_t ino, const char *buf, handle = fi->fh; fh = (XFUSE_HANDLE *) handle; - if (fh->DeviceId == 0) + if (fh->is_loc_resource) { /* target file is in .clipboard dir */ log_debug(">>>>>>>>>>>>>>>>> THIS IS STILL A TODO!"); diff --git a/sesman/chansrv/chansrv_fuse.h b/sesman/chansrv/chansrv_fuse.h index de4edc0b..bd7917e2 100644 --- a/sesman/chansrv/chansrv_fuse.h +++ b/sesman/chansrv/chansrv_fuse.h @@ -22,23 +22,24 @@ /* a file or dir entry in the xrdp file system */ struct xrdp_inode { - tui32 parent_inode; /* Parent serial number. */ - tui32 inode; /* File serial number. */ - tui32 mode; /* File mode. */ - tui32 nlink; /* symbolic link count. */ - tui32 nentries; /* number of entries in a dir */ - tui32 nopen; /* number of simultaneous opens */ - tui32 uid; /* User ID of the file's owner. */ - tui32 gid; /* Group ID of the file's group. */ - size_t size; /* Size of file, in bytes. */ - time_t atime; /* Time of last access. */ - time_t mtime; /* Time of last modification. */ - time_t ctime; /* Time of last status change. */ - char name[256]; /* Dir or filename */ - tui32 device_id; /* for file system redirection */ - char is_synced; /* dir struct has been read from */ - /* remote device, done just once */ - int lindex; /* used in clipboard operations */ + tui32 parent_inode; /* Parent serial number. */ + tui32 inode; /* File serial number. */ + tui32 mode; /* File mode. */ + tui32 nlink; /* symbolic link count. */ + tui32 nentries; /* number of entries in a dir */ + tui32 nopen; /* number of simultaneous opens */ + tui32 uid; /* User ID of the file's owner. */ + tui32 gid; /* Group ID of the file's group. */ + size_t size; /* Size of file, in bytes. */ + time_t atime; /* Time of last access. */ + time_t mtime; /* Time of last modification. */ + time_t ctime; /* Time of last status change. */ + char name[256]; /* Dir or filename */ + tui32 device_id; /* for file system redirection */ + char is_synced; /* dir struct has been read from */ + /* remote device, done just once */ + int lindex; /* used in clipboard operations */ + int is_loc_resource; /* this is not a redirected resource */ }; typedef struct xrdp_inode XRDP_INODE; // LK_TODO use this instead of using struct xrdp_inode diff --git a/sesman/chansrv/devredir.c b/sesman/chansrv/devredir.c index 50e1d961..bb203d2b 100644 --- a/sesman/chansrv/devredir.c +++ b/sesman/chansrv/devredir.c @@ -400,7 +400,7 @@ int dev_redir_send_drive_create_request(tui32 device_id, char *path, stream_wr_u32_le(s, 0); /* AllocationSize high unused */ stream_wr_u32_le(s, 0); /* AllocationSize low unused */ stream_wr_u32_le(s, 0); /* FileAttributes */ - stream_wr_u32_le(s, 0); /* SharedAccess */ + stream_wr_u32_le(s, 3); /* SharedAccess LK_TODO */ stream_wr_u32_le(s, CreateDisposition); /* CreateDisposition */ stream_wr_u32_le(s, CreateOptions); /* CreateOptions */ stream_wr_u32_le(s, len); /* PathLength */ @@ -443,6 +443,7 @@ int dev_redir_send_drive_close_request(tui16 Component, tui16 PacketId, send_channel_data(g_rdpdr_chan_id, s->data, bytes); stream_free(s); + log_debug("sent close request; expect CID_FILE_CLOSE"); return 0; } @@ -905,6 +906,8 @@ int dev_redir_get_dir_listing(void *fusep, tui32 device_id, char *path) int rval; IRP *irp; + log_debug("fusep=%p", fusep); + if ((irp = dev_redir_irp_new()) == NULL) return -1; @@ -971,7 +974,7 @@ int dev_redir_file_open(void *fusep, tui32 device_id, char *path, if (mode & O_CREAT) { log_debug("open file in O_CREAT"); - DesiredAccess = DA_FILE_READ_DATA | DA_FILE_WRITE_DATA | DA_SYNCHRONIZE; + DesiredAccess = 0x0016019f; /* got this value from windows */ if (type & S_IFDIR) { @@ -982,27 +985,27 @@ int dev_redir_file_open(void *fusep, tui32 device_id, char *path, else { log_debug("creating file"); - CreateOptions = CO_FILE_SYNCHRONOUS_IO_NONALERT; + CreateOptions = 0x44; /* got this value from windows */ } - CreateDisposition = CD_FILE_CREATE; + //CreateDisposition = CD_FILE_CREATE; + CreateDisposition = 0x02; /* got this value from windows */ } else //if (mode & O_RDWR) { log_debug("open file in O_RDWR"); +#if 1 DesiredAccess = DA_FILE_READ_DATA | DA_FILE_WRITE_DATA | DA_SYNCHRONIZE; CreateOptions = CO_FILE_SYNCHRONOUS_IO_NONALERT; CreateDisposition = CD_FILE_OPEN; // WAS 1 - } -#if 0 - else - { - log_debug("open file in O_RDONLY"); - DesiredAccess = DA_FILE_READ_DATA | DA_SYNCHRONIZE; - CreateOptions = CO_FILE_SYNCHRONOUS_IO_NONALERT; - CreateDisposition = CD_FILE_OPEN; - } +#else + /* got this value from windows */ + DesiredAccess = 0x00120089; + CreateOptions = 0x20060; + CreateDisposition = 0x01; #endif + } + rval = dev_redir_send_drive_create_request(device_id, path, DesiredAccess, CreateOptions, CreateDisposition, @@ -1015,6 +1018,8 @@ int devredir_file_close(void *fusep, tui32 device_id, tui32 FileId) { IRP *irp; + log_debug("entered"); + #if 0 if ((irp = dev_redir_irp_new()) == NULL) return -1; @@ -1041,7 +1046,7 @@ int devredir_file_close(void *fusep, tui32 device_id, tui32 FileId) } /** - * Remove (delete) a directory + * Remove (delete) a directory or file *****************************************************************************/ int devredir_rmdir_or_file(void *fusep, tui32 device_id, char *path, int mode) @@ -1061,14 +1066,15 @@ int devredir_rmdir_or_file(void *fusep, tui32 device_id, char *path, int mode) strcpy(irp->pathname, path); dev_redir_fuse_data_enqueue(irp, fusep); - // LK_TODO - //DesiredAccess = DA_DELETE | DA_FILE_READ_DATA | DA_FILE_WRITE_DATA | DA_SYNCHRONIZE; - DesiredAccess = DA_DELETE | DA_FILE_READ_ATTRIBUTES | DA_SYNCHRONIZE; + //DesiredAccess = DA_DELETE | DA_FILE_READ_ATTRIBUTES | DA_SYNCHRONIZE; + DesiredAccess = 0x00100080; /* got this value from windows */ - CreateOptions = CO_FILE_DELETE_ON_CLOSE | CO_FILE_DIRECTORY_FILE | - CO_FILE_SYNCHRONOUS_IO_NONALERT; + //CreateOptions = CO_FILE_DELETE_ON_CLOSE | CO_FILE_DIRECTORY_FILE | + // CO_FILE_SYNCHRONOUS_IO_NONALERT; + CreateOptions = 0x020; /* got this value from windows */ - CreateDisposition = CD_FILE_OPEN; // WAS 1 + //CreateDisposition = CD_FILE_OPEN; // WAS 1 + CreateDisposition = 0x01; /* got this value from windows */ rval = dev_redir_send_drive_create_request(device_id, path, DesiredAccess, CreateOptions, @@ -1128,6 +1134,9 @@ int dev_redir_file_write(void *fusep, tui32 DeviceId, tui32 FileId, IRP *irp; int bytes; + log_debug("DeviceId=%d FileId=%d Length=%d Offset=%lld", + DeviceId, FileId, Length, Offset); + stream_new(s, 1024 + Length); if ((irp = dev_redir_irp_find_by_fileid(FileId)) == NULL) @@ -1562,6 +1571,8 @@ void devredir_proc_cid_rename_file(IRP *irp, tui32 IoStatus) if (IoStatus != NT_STATUS_SUCCESS) { + log_debug("rename returned with IoStatus=0x%x", IoStatus); + FUSE_DATA *fuse_data = dev_redir_fuse_data_dequeue(irp); if (fuse_data) { @@ -1605,6 +1616,8 @@ void devredir_proc_cid_rename_file_resp(IRP *irp, tui32 IoStatus) { FUSE_DATA *fuse_data; + log_debug("entered"); + fuse_data = dev_redir_fuse_data_dequeue(irp); if (fuse_data) {