x11: implement all related code to file content request for size and FD_WRITESTIME flag in response , fix include dir for fuse

This commit is contained in:
jackyzy823 2020-12-31 22:40:39 +08:00 committed by akallabeth
parent 2e0b5e07dc
commit a61c185d30
2 changed files with 124 additions and 24 deletions

View File

@ -227,7 +227,7 @@ if(WITH_XFIXES)
endif()
find_package(FUSE REQUIRED)
include_directories(${FUSE_INCLUDE_DIRS})
include_directories(${FUSE_INCLUDE_DIR})
set(${MODULE_PREFIX}_LIBS ${${MODULE_PREFIX}_LIBS} ${FUSE_LIBRARIES})
include_directories(${CMAKE_SOURCE_DIR}/resources)

View File

@ -66,7 +66,11 @@ typedef struct xf_cliprdr_format xfCliprdrFormat;
struct xf_cliprdr_fuse_stream
{
UINT32 stream_id;
/* must be one of FILECONTENTS_SIZE or FILECONTENTS_RANGE*/
UINT32 req_type;
fuse_req_t req;
/*for FILECONTENTS_SIZE must be xfCliprdrFuseInode* */
void* req_data;
};
typedef struct xf_cliprdr_fuse_stream xfCliprdrFuseStream;
@ -77,6 +81,7 @@ struct xf_cliprdr_fuse_inode
size_t lindex;
mode_t st_mode;
off_t st_size;
BOOL size_set;
struct timespec st_mtim;
char* name;
wArrayList* child_inos;
@ -876,7 +881,7 @@ static void xf_cliprdr_clear_cached_data(xfClipboard* clipboard)
xfCliprdrFuseStream* stream;
ArrayList_Lock(clipboard->stream_list);
clipboard->current_stream_id = 0;
/* reply error to all req first */
/* reply error to all req first don't care request type*/
count = ArrayList_Count(clipboard->stream_list);
for (index = 0; index < count; index++)
{
@ -1010,7 +1015,8 @@ static BOOL xf_cliprdr_process_selection_request(xfClipboard* clipboard,
if (!delayRespond)
{
union {
union
{
XEvent* ev;
XSelectionEvent* sev;
} conv;
@ -1230,16 +1236,36 @@ static UINT xf_cliprdr_send_client_format_list_response(xfClipboard* clipboard,
* @return 0 on success, otherwise a Win32 error code
*/
static UINT xf_cliprdr_send_client_file_contents(xfClipboard* clipboard, UINT32 streamId,
UINT32 listIndex, UINT32 nPositionLow,
UINT32 nPositionHigh, UINT32 cbRequested)
UINT32 listIndex, UINT32 dwFlags,
UINT32 nPositionLow, UINT32 nPositionHigh,
UINT32 cbRequested)
{
CLIPRDR_FILE_CONTENTS_REQUEST formatFileContentsRequest;
formatFileContentsRequest.streamId = streamId;
formatFileContentsRequest.listIndex = listIndex;
formatFileContentsRequest.dwFlags = FILECONTENTS_RANGE;
formatFileContentsRequest.nPositionHigh = nPositionHigh;
formatFileContentsRequest.nPositionLow = nPositionLow;
formatFileContentsRequest.cbRequested = cbRequested;
formatFileContentsRequest.dwFlags = dwFlags;
switch (dwFlags)
{
/*
* [MS-RDPECLIP] 2.2.5.3 File Contents Request PDU (CLIPRDR_FILECONTENTS_REQUEST).
*
* A request for the size of the file identified by the lindex field. The size MUST be
* returned as a 64-bit, unsigned integer. The cbRequested field MUST be set to
* 0x00000008 and both the nPositionLow and nPositionHigh fields MUST be
* set to 0x00000000.
*/
case FILECONTENTS_SIZE:
formatFileContentsRequest.cbRequested = sizeof(UINT64);
formatFileContentsRequest.nPositionHigh = 0;
formatFileContentsRequest.nPositionLow = 0;
break;
case FILECONTENTS_RANGE:
formatFileContentsRequest.cbRequested = cbRequested;
formatFileContentsRequest.nPositionHigh = nPositionHigh;
formatFileContentsRequest.nPositionLow = nPositionLow;
break;
}
formatFileContentsRequest.haveClipDataId = FALSE;
return clipboard->context->ClientFileContentsRequest(clipboard->context,
&formatFileContentsRequest);
@ -1260,6 +1286,8 @@ xf_cliprdr_server_file_contents_response(CliprdrClientContext* context,
xfCliprdrFuseStream* stream;
xfClipboard* clipboard = (xfClipboard*)context->custom;
UINT32 stream_id = fileContentsResponse->streamId;
const BYTE* data = fileContentsResponse->requestedData;
size_t data_len = fileContentsResponse->cbRequested;
ArrayList_Lock(clipboard->stream_list);
count = ArrayList_Count(clipboard->stream_list);
@ -1277,8 +1305,35 @@ xf_cliprdr_server_file_contents_response(CliprdrClientContext* context,
ArrayList_Unlock(clipboard->stream_list);
if (found)
{
fuse_reply_buf(stream->req, (const char*)fileContentsResponse->requestedData,
fileContentsResponse->cbRequested);
switch (stream->req_type)
{
case FILECONTENTS_SIZE:
if (data_len != sizeof(UINT64))
{
break;
}
UINT32 size = (UINT32)(data[3] << 24) | (UINT32)(data[2] << 16) |
(UINT32)(data[1] << 8) | (data[0] & 0xFF);
xfCliprdrFuseInode* ino = (xfCliprdrFuseInode*)stream->req_data;
ino->st_size = size;
ino->size_set = TRUE;
struct fuse_entry_param e;
memset(&e, 0, sizeof(e));
e.ino = ino->ino;
e.attr_timeout = 1.0;
e.entry_timeout = 1.0;
e.attr.st_ino = ino->ino;
e.attr.st_mode = ino->st_mode;
e.attr.st_nlink = 1;
e.attr.st_size = ino->st_size;
e.attr.st_mtime = ino->st_mtim.tv_sec;
fuse_reply_entry(stream->req, &e);
break;
case FILECONTENTS_RANGE:
fuse_reply_buf(stream->req, (const char*)data, data_len);
break;
}
ArrayList_RemoveAt(clipboard->stream_list, index);
}
return CHANNEL_RC_OK;
@ -1597,6 +1652,8 @@ xf_cliprdr_server_format_data_response(CliprdrClientContext* context,
rootNode->st_mode = S_IFDIR | 0755;
rootNode->child_inos = ArrayList_New(TRUE);
rootNode->st_mtim.tv_sec = time(NULL);
rootNode->st_size = 0;
rootNode->size_set = TRUE;
ArrayList_Add(clipboard->ino_list, rootNode);
mapDir = HashTable_New(TRUE);
@ -1644,29 +1701,51 @@ xf_cliprdr_server_format_data_response(CliprdrClientContext* context,
ArrayList_Add(parent->child_inos, (void*)inode->ino);
free(dirName);
}
/* TODO: check FD_ATTRIBUTES in dwFlags
However if this flag is not valid how can we determine file/folder?
*/
if ((descriptors[lindex].dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0)
{
inode->st_mode = S_IFDIR | 0755;
inode->child_inos = ArrayList_New(TRUE);
inode->st_size = 0;
inode->size_set = TRUE;
HashTable_Add(mapDir, _strdup(curName), inode);
}
else
{
inode->st_mode = S_IFREG | 0644;
if ((descriptors[lindex].dwFlags & FD_FILESIZE) != 0)
{
inode->st_size =
(((UINT64)descriptors[lindex].nFileSizeHigh) << 32) |
((UINT64)descriptors[lindex].nFileSizeLow);
inode->size_set = TRUE;
}
else
{
inode->size_set = FALSE;
}
}
free(curName);
inode->st_size = (((UINT64)descriptors[lindex].nFileSizeHigh) << 32) |
((UINT64)descriptors[lindex].nFileSizeLow);
ticks =
(((UINT64)descriptors[lindex].ftLastWriteTime.dwHighDateTime << 32) |
((UINT64)descriptors[lindex].ftLastWriteTime.dwLowDateTime)) -
116444736000000000;
inode->st_mtim.tv_sec = ticks / 10000000ULL;
/* tv_nsec Not used for now */
inode->st_mtim.tv_nsec = ticks % 10000000ULL;
if ((descriptors[lindex].dwFlags & FD_WRITESTIME) != 0)
{
ticks = (((UINT64)descriptors[lindex].ftLastWriteTime.dwHighDateTime
<< 32) |
((UINT64)descriptors[lindex].ftLastWriteTime.dwLowDateTime)) -
116444736000000000;
inode->st_mtim.tv_sec = ticks / 10000000ULL;
/* tv_nsec Not used for now */
inode->st_mtim.tv_nsec = ticks % 10000000ULL;
}
else
{
inode->st_mtim.tv_sec = time(NULL);
inode->st_mtim.tv_nsec = 0;
}
ArrayList_Add(clipboard->ino_list, inode);
}
@ -1788,7 +1867,8 @@ xf_cliprdr_server_format_data_response(CliprdrClientContext* context,
xf_cliprdr_provide_data(clipboard, clipboard->respond, pDstData, DstSize);
{
union {
union
{
XEvent* ev;
XSelectionEvent* sev;
} conv;
@ -2102,7 +2182,9 @@ static void xf_cliprdr_fuse_read(fuse_req_t req, fuse_ino_t ino, size_t size, of
ArrayList_Lock(clipboard->stream_list);
stream->req = req;
stream->req_type = FILECONTENTS_RANGE;
stream->stream_id = clipboard->current_stream_id;
stream->req_data = NULL;
clipboard->current_stream_id++;
ArrayList_Add(clipboard->stream_list, stream);
ArrayList_Unlock(clipboard->stream_list);
@ -2110,8 +2192,8 @@ static void xf_cliprdr_fuse_read(fuse_req_t req, fuse_ino_t ino, size_t size, of
UINT32 nPositionLow = (off >> 0) & 0xFFFFFFFF;
UINT32 nPositionHigh = (off >> 32) & 0xFFFFFFFF;
xf_cliprdr_send_client_file_contents(clipboard, stream->stream_id, node->lindex, nPositionLow,
nPositionHigh, size);
xf_cliprdr_send_client_file_contents(clipboard, stream->stream_id, node->lindex,
FILECONTENTS_RANGE, nPositionLow, nPositionHigh, size);
}
static void xf_cliprdr_fuse_lookup(fuse_req_t req, fuse_ino_t parent, const char* name)
@ -2151,6 +2233,24 @@ static void xf_cliprdr_fuse_lookup(fuse_req_t req, fuse_ino_t parent, const char
ArrayList_Unlock(parent_node->child_inos);
if (found == TRUE)
{
if (child_node->size_set != TRUE)
{
xfCliprdrFuseStream* stream =
(xfCliprdrFuseStream*)calloc(1, sizeof(xfCliprdrFuseStream));
ArrayList_Lock(clipboard->stream_list);
stream->req = req;
stream->req_type = FILECONTENTS_SIZE;
stream->stream_id = clipboard->current_stream_id;
stream->req_data = (void*)child_node;
clipboard->current_stream_id++;
ArrayList_Add(clipboard->stream_list, stream);
ArrayList_Unlock(clipboard->stream_list);
xf_cliprdr_send_client_file_contents(clipboard, stream->stream_id, child_node->lindex,
FILECONTENTS_SIZE, 0, 0, 0);
return;
}
memset(&e, 0, sizeof(e));
e.ino = child_node->ino;
e.attr_timeout = 1.0;