x11: refactor fuse code

This commit is contained in:
jackyzy823 2021-01-16 07:14:36 +00:00 committed by akallabeth
parent e7d2f62ce6
commit b972d70a9e
3 changed files with 367 additions and 279 deletions

View File

@ -42,7 +42,6 @@
#include <sys/stat.h> #include <sys/stat.h>
#include <errno.h> #include <errno.h>
#include <time.h> #include <time.h>
#define WIN32_FILETIME_TO_UNIX_EPOCH_USEC UINT64_C(116444736000000000)
#endif #endif
#include <winpr/crt.h> #include <winpr/crt.h>
@ -61,6 +60,7 @@
#define TAG CLIENT_TAG("x11") #define TAG CLIENT_TAG("x11")
#define MAX_CLIPBOARD_FORMATS 255 #define MAX_CLIPBOARD_FORMATS 255
#define WIN32_FILETIME_TO_UNIX_EPOCH_USEC UINT64_C(116444736000000000)
struct xf_cliprdr_format struct xf_cliprdr_format
{ {
@ -77,8 +77,8 @@ struct xf_cliprdr_fuse_stream
/* must be one of FILECONTENTS_SIZE or FILECONTENTS_RANGE*/ /* must be one of FILECONTENTS_SIZE or FILECONTENTS_RANGE*/
UINT32 req_type; UINT32 req_type;
fuse_req_t req; fuse_req_t req;
/*for FILECONTENTS_SIZE must be xfCliprdrFuseInode* */ /*for FILECONTENTS_SIZE must be ino number* */
void* req_data; size_t req_ino;
}; };
typedef struct xf_cliprdr_fuse_stream xfCliprdrFuseStream; typedef struct xf_cliprdr_fuse_stream xfCliprdrFuseStream;
@ -108,8 +108,9 @@ void xf_cliprdr_fuse_inode_free(void* obj)
inode->name = NULL; inode->name = NULL;
inode->child_inos = NULL; inode->child_inos = NULL;
free(inode); free(inode);
inode = NULL;
} }
static inline xfCliprdrFuseInode* xf_cliprdr_fuse_util_get_inode(wArrayList* ino_list,
fuse_ino_t ino);
#endif #endif
struct xf_clipboard struct xf_clipboard
@ -1323,23 +1324,46 @@ xf_cliprdr_server_file_contents_response(CliprdrClientContext* context,
break; break;
} }
} }
if (!found)
if (found)
{ {
switch (stream->req_type) ArrayList_Unlock(clipboard->stream_list);
return CHANNEL_RC_OK;
}
fuse_req_t req = stream->req;
UINT32 req_type = stream->req_type;
size_t req_ino = stream->req_ino;
ArrayList_RemoveAt(clipboard->stream_list, index);
ArrayList_Unlock(clipboard->stream_list);
switch (req_type)
{ {
case FILECONTENTS_SIZE: case FILECONTENTS_SIZE:
ino = (xfCliprdrFuseInode*)stream->req_data; /* fileContentsResponse->cbRequested should be 64bit*/
/** ino must be exists and fileContentsResponse->cbRequested should be 64bit */ if (data_len != sizeof(UINT64))
if (!ino || data_len != sizeof(UINT64))
{ {
fuse_reply_err(stream->req, EIO); fuse_reply_err(req, EIO);
break; break;
} }
UINT64 size; UINT64 size;
wStream* s = Stream_New((BYTE*)data, data_len); wStream* s = Stream_New((BYTE*)data, data_len);
if (!s)
{
fuse_reply_err(req, ENOMEM);
break;
}
Stream_Read_UINT64(s, size); Stream_Read_UINT64(s, size);
Stream_Free(s, FALSE); Stream_Free(s, FALSE);
ArrayList_Lock(clipboard->ino_list);
ino = xf_cliprdr_fuse_util_get_inode(clipboard->ino_list, req_ino);
/* ino must be exists and */
if (!ino)
{
ArrayList_Unlock(clipboard->ino_list);
fuse_reply_err(req, EIO);
break;
}
ino->st_size = size; ino->st_size = size;
ino->size_set = TRUE; ino->size_set = TRUE;
@ -1353,15 +1377,13 @@ xf_cliprdr_server_file_contents_response(CliprdrClientContext* context,
e.attr.st_nlink = 1; e.attr.st_nlink = 1;
e.attr.st_size = ino->st_size; e.attr.st_size = ino->st_size;
e.attr.st_mtime = ino->st_mtim.tv_sec; e.attr.st_mtime = ino->st_mtim.tv_sec;
fuse_reply_entry(stream->req, &e); ArrayList_Unlock(clipboard->ino_list);
fuse_reply_entry(req, &e);
break; break;
case FILECONTENTS_RANGE: case FILECONTENTS_RANGE:
fuse_reply_buf(stream->req, (const char*)data, data_len); fuse_reply_buf(req, (const char*)data, data_len);
break; break;
} }
ArrayList_RemoveAt(clipboard->stream_list, index);
}
ArrayList_Unlock(clipboard->stream_list);
return CHANNEL_RC_OK; return CHANNEL_RC_OK;
} }
#endif #endif
@ -1611,22 +1633,31 @@ static char* xf_cliprdr_fuse_split_basename(char* name, int len)
return NULL; return NULL;
} }
/** static xfCliprdrFuseInode* xf_cliprdr_fuse_create_root_node()
* Generate inode list for fuse
*
* @return TRUE on success, FALSE on fail
*/
static BOOL xf_cliprdr_fuse_generate_list(xfClipboard* clipboard, const BYTE* data, UINT32 size)
{ {
if (size < 4) xfCliprdrFuseInode* rootNode = (xfCliprdrFuseInode*)calloc(1, sizeof(xfCliprdrFuseInode));
{ if (!rootNode)
WLog_ERR(TAG, "size of format data response invalid"); return NULL;
return FALSE; rootNode->ino = 1;
} rootNode->parent_ino = 1;
rootNode->st_mode = S_IFDIR | 0755;
rootNode->name = _strdup("/");
rootNode->child_inos = ArrayList_New(TRUE);
rootNode->st_mtim.tv_sec = time(NULL);
rootNode->st_size = 0;
rootNode->size_set = TRUE;
if (!rootNode->child_inos || !rootNode->name)
{
xf_cliprdr_fuse_inode_free(rootNode);
WLog_ERR(TAG, "fail to alloc rootNode's member");
return NULL;
}
return rootNode;
}
static BOOL xf_cliprdr_fuse_check_stream(wStream* s, size_t count)
{
UINT32 nrDescriptors; UINT32 nrDescriptors;
size_t count = (size - 4) / sizeof(FILEDESCRIPTORW);
wStream* s = Stream_New((BYTE*)data, size);
if (Stream_GetRemainingLength(s) < sizeof(UINT32)) if (Stream_GetRemainingLength(s) < sizeof(UINT32))
{ {
WLog_ERR(TAG, "too short serialized format list"); WLog_ERR(TAG, "too short serialized format list");
@ -1634,52 +1665,28 @@ static BOOL xf_cliprdr_fuse_generate_list(xfClipboard* clipboard, const BYTE* da
} }
Stream_Read_UINT32(s, nrDescriptors); Stream_Read_UINT32(s, nrDescriptors);
if (count < 1 || count != nrDescriptors) if (count != nrDescriptors)
{ {
WLog_WARN(TAG, "format data response mismatch"); WLog_WARN(TAG, "format data response mismatch");
goto error; return FALSE;
} }
return TRUE;
}
size_t lindex; static BOOL xf_cliprdr_fuse_create_nodes(xfClipboard* clipboard, wStream* s, size_t count,
wHashTable* mapDir; xfCliprdrFuseInode* rootNode)
/* prevent conflict between fuse_thread and this */ {
ArrayList_Lock(clipboard->ino_list); BOOL status = FALSE;
xfCliprdrFuseInode* rootNode = (xfCliprdrFuseInode*)calloc(1, sizeof(xfCliprdrFuseInode)); size_t lindex = 0;
if (!rootNode) char* curName = NULL;
{ char* dirName = NULL;
WLog_ERR(TAG, "fail to alloc rootNode"); char* baseName = NULL;
goto error; xfCliprdrFuseInode* inode;
} wHashTable* mapDir = HashTable_New(TRUE);
rootNode->ino = 1;
rootNode->parent_ino = 1;
rootNode->name = _strdup("/");
if (!rootNode->name)
{
goto error;
}
rootNode->st_mode = S_IFDIR | 0755;
rootNode->child_inos = ArrayList_New(TRUE);
if (!rootNode->child_inos || !rootNode->name)
{
xf_cliprdr_fuse_inode_free(rootNode);
WLog_ERR(TAG, "fail to alloc rootNode's member");
goto error;
}
rootNode->st_mtim.tv_sec = time(NULL);
rootNode->st_size = 0;
rootNode->size_set = TRUE;
if (ArrayList_Add(clipboard->ino_list, rootNode) < 0)
{
xf_cliprdr_fuse_inode_free(rootNode);
WLog_ERR(TAG, "fail to alloc rootNode to ino_list");
goto error;
}
mapDir = HashTable_New(TRUE);
if (!mapDir) if (!mapDir)
{ {
WLog_ERR(TAG, "fail to alloc hashtable"); WLog_ERR(TAG, "fail to alloc hashtable");
goto error2; return FALSE;
} }
mapDir->keyFree = HashTable_StringFree; mapDir->keyFree = HashTable_StringFree;
mapDir->keyClone = HashTable_StringClone; mapDir->keyClone = HashTable_StringClone;
@ -1690,38 +1697,30 @@ static BOOL xf_cliprdr_fuse_generate_list(xfClipboard* clipboard, const BYTE* da
if (!descriptor) if (!descriptor)
{ {
WLog_ERR(TAG, "fail to alloc FILEDESCRIPTORW"); WLog_ERR(TAG, "fail to alloc FILEDESCRIPTORW");
goto error3; goto error;
} }
char* curName;
char* dirName;
xfCliprdrFuseInode* inode;
/* here we assume that parent folder always appears before its children */ /* here we assume that parent folder always appears before its children */
for (lindex = 0; lindex < count; lindex++) for (; lindex < count; lindex++)
{ {
Stream_Read(s, descriptor, sizeof(FILEDESCRIPTORW)); Stream_Read(s, descriptor, sizeof(FILEDESCRIPTORW));
inode = (xfCliprdrFuseInode*)calloc(1, sizeof(xfCliprdrFuseInode)); inode = (xfCliprdrFuseInode*)calloc(1, sizeof(xfCliprdrFuseInode));
if (!inode) if (!inode)
{ {
WLog_ERR(TAG, "fail to alloc ino"); WLog_ERR(TAG, "fail to alloc ino");
goto error4; break;
} }
size_t curLen = _wcsnlen(descriptor->cFileName, ARRAYSIZE(descriptor->cFileName)); size_t curLen = _wcsnlen(descriptor->cFileName, ARRAYSIZE(descriptor->cFileName));
curName = NULL;
int newLen = ConvertFromUnicode(CP_UTF8, 0, descriptor->cFileName, (int)curLen, &curName, 0, int newLen = ConvertFromUnicode(CP_UTF8, 0, descriptor->cFileName, (int)curLen, &curName, 0,
NULL, NULL); NULL, NULL);
if (!curName) if (!curName)
{ break;
goto error5;
}
char* split_point = xf_cliprdr_fuse_split_basename(curName, newLen); char* split_point = xf_cliprdr_fuse_split_basename(curName, newLen);
char* baseName = NULL;
UINT64 ticks; UINT64 ticks;
xfCliprdrFuseInode* parent; xfCliprdrFuseInode* parent;
dirName = NULL;
inode->lindex = lindex; inode->lindex = lindex;
inode->ino = lindex + 2; inode->ino = lindex + 2;
@ -1729,43 +1728,32 @@ static BOOL xf_cliprdr_fuse_generate_list(xfClipboard* clipboard, const BYTE* da
{ {
baseName = _strdup(curName); baseName = _strdup(curName);
if (!baseName) if (!baseName)
{ break;
goto error6;
}
inode->parent_ino = 1; inode->parent_ino = 1;
inode->name = baseName; inode->name = baseName;
if (ArrayList_Add(rootNode->child_inos, (void*)inode->ino) < 0) if (ArrayList_Add(rootNode->child_inos, (void*)inode->ino) < 0)
{ break;
goto error6;
}
} }
else else
{ {
dirName = calloc(split_point - curName + 1, sizeof(char)); dirName = calloc(split_point - curName + 1, sizeof(char));
if (!dirName) if (!dirName)
{ break;
goto error6;
}
_snprintf(dirName, split_point - curName + 1, "%s", curName); _snprintf(dirName, split_point - curName + 1, "%s", curName);
/* drop last '\\' */ /* drop last '\\' */
baseName = _strdup(split_point + 1); baseName = _strdup(split_point + 1);
if (!baseName) if (!baseName)
{ break;
goto error7;
}
parent = (xfCliprdrFuseInode*)HashTable_GetItemValue(mapDir, dirName); parent = (xfCliprdrFuseInode*)HashTable_GetItemValue(mapDir, dirName);
if (!parent) if (!parent)
{ break;
goto error7;
}
inode->parent_ino = parent->ino; inode->parent_ino = parent->ino;
inode->name = baseName; inode->name = baseName;
if (ArrayList_Add(parent->child_inos, (void*)inode->ino) < 0) if (ArrayList_Add(parent->child_inos, (void*)inode->ino) < 0)
{ break;
goto error7;
}
free(dirName); free(dirName);
dirName = NULL;
} }
/* TODO: check FD_ATTRIBUTES in dwFlags /* TODO: check FD_ATTRIBUTES in dwFlags
However if this flag is not valid how can we determine file/folder? However if this flag is not valid how can we determine file/folder?
@ -1775,20 +1763,16 @@ static BOOL xf_cliprdr_fuse_generate_list(xfClipboard* clipboard, const BYTE* da
inode->st_mode = S_IFDIR | 0755; inode->st_mode = S_IFDIR | 0755;
inode->child_inos = ArrayList_New(TRUE); inode->child_inos = ArrayList_New(TRUE);
if (!inode->child_inos) if (!inode->child_inos)
{ break;
goto error6;
}
inode->st_size = 0; inode->st_size = 0;
inode->size_set = TRUE; inode->size_set = TRUE;
char* tmpName = _strdup(curName); char* tmpName = _strdup(curName);
if (!tmpName) if (!tmpName)
{ break;
goto error6;
}
if (HashTable_Add(mapDir, tmpName, inode) < 0) if (HashTable_Add(mapDir, tmpName, inode) < 0)
{ {
free(tmpName); free(tmpName);
goto error6; break;
} }
} }
else else
@ -1807,6 +1791,7 @@ static BOOL xf_cliprdr_fuse_generate_list(xfClipboard* clipboard, const BYTE* da
} }
free(curName); free(curName);
curName = NULL;
if ((descriptor->dwFlags & FD_WRITESTIME) != 0) if ((descriptor->dwFlags & FD_WRITESTIME) != 0)
{ {
@ -1824,32 +1809,71 @@ static BOOL xf_cliprdr_fuse_generate_list(xfClipboard* clipboard, const BYTE* da
} }
if (ArrayList_Add(clipboard->ino_list, inode) < 0) if (ArrayList_Add(clipboard->ino_list, inode) < 0)
break;
}
/* clean up incomplete ino_list*/
if (lindex != count)
{ {
goto error5;
}
}
ArrayList_Unlock(clipboard->ino_list);
free(descriptor);
HashTable_Free(mapDir);
Stream_Free(s, FALSE);
return TRUE;
error7:
free(dirName); free(dirName);
error6:
free(curName); free(curName);
error5: /* baseName is freed in xf_cliprdr_fuse_inode_free*/
xf_cliprdr_fuse_inode_free(inode); xf_cliprdr_fuse_inode_free(inode);
error4:
free(descriptor);
error3:
HashTable_Free(mapDir);
error2:
ArrayList_Clear(clipboard->ino_list); ArrayList_Clear(clipboard->ino_list);
}
else
{
status = TRUE;
}
free(descriptor);
error: error:
ArrayList_Unlock(clipboard->ino_list); HashTable_Free(mapDir);
Stream_Free(s, FALSE); return status;
}
/**
* Generate inode list for fuse
*
* @return TRUE on success, FALSE on fail
*/
static BOOL xf_cliprdr_fuse_generate_list(xfClipboard* clipboard, const BYTE* data, UINT32 size)
{
BOOL status = FALSE;
if (size < 4)
{
WLog_ERR(TAG, "size of format data response invalid : %d", size);
return FALSE; return FALSE;
}
size_t count = (size - 4) / sizeof(FILEDESCRIPTORW);
if (count < 1)
return FALSE;
wStream* s = Stream_New((BYTE*)data, size);
if (!s || !xf_cliprdr_fuse_check_stream(s, count))
{
WLog_ERR(TAG, "Stream_New failed");
goto error;
}
/* prevent conflict between fuse_thread and this */
ArrayList_Lock(clipboard->ino_list);
xfCliprdrFuseInode* rootNode = xf_cliprdr_fuse_create_root_node();
if (!rootNode || ArrayList_Add(clipboard->ino_list, rootNode) < 0)
{
xf_cliprdr_fuse_inode_free(rootNode);
WLog_ERR(TAG, "fail to alloc rootNode to ino_list");
goto error2;
}
status = xf_cliprdr_fuse_create_nodes(clipboard, s, count, rootNode);
error2:
ArrayList_Unlock(clipboard->ino_list);
error:
Stream_Free(s, FALSE);
return status;
} }
#endif #endif
@ -1875,6 +1899,12 @@ xf_cliprdr_server_format_data_response(CliprdrClientContext* context,
xfClipboard* clipboard = (xfClipboard*)context->custom; xfClipboard* clipboard = (xfClipboard*)context->custom;
xfContext* xfc = clipboard->xfc; xfContext* xfc = clipboard->xfc;
if (formatDataResponse->msgFlags == CB_RESPONSE_FAIL)
{
WLog_WARN(TAG, "Format Data Response PDU msgFlags is CB_RESPONSE_FAIL");
return CHANNEL_RC_OK;
}
if (!clipboard->respond) if (!clipboard->respond)
return CHANNEL_RC_OK; return CHANNEL_RC_OK;
@ -1902,7 +1932,7 @@ xf_cliprdr_server_format_data_response(CliprdrClientContext* context,
{ {
#ifdef WITH_FUSE #ifdef WITH_FUSE
/* Build inode table for FILEDESCRIPTORW*/ /* Build inode table for FILEDESCRIPTORW*/
if (xf_cliprdr_fuse_generate_list(clipboard, data, size) == FALSE) if (!xf_cliprdr_fuse_generate_list(clipboard, data, size))
{ {
/* just continue */ /* just continue */
WLog_WARN(TAG, "fail to generate list for FILEDESCRIPTOR"); WLog_WARN(TAG, "fail to generate list for FILEDESCRIPTOR");
@ -2166,37 +2196,121 @@ static UINT xf_cliprdr_clipboard_file_range_failure(wClipboardDelegate* delegate
#ifdef WITH_FUSE #ifdef WITH_FUSE
/* For better understanding the relationship between ino and index of arraylist*/ /* For better understanding the relationship between ino and index of arraylist*/
static inline xfCliprdrFuseInode* xf_cliprdr_get_inode(wArrayList* ino_list, fuse_ino_t ino) static inline xfCliprdrFuseInode* xf_cliprdr_fuse_util_get_inode(wArrayList* ino_list,
fuse_ino_t ino)
{ {
size_t list_index = ino - 1; size_t list_index = ino - 1;
return (xfCliprdrFuseInode*)ArrayList_GetItem(ino_list, list_index); return (xfCliprdrFuseInode*)ArrayList_GetItem(ino_list, list_index);
} }
static void xf_cliprdr_fuse_getattr(fuse_req_t req, fuse_ino_t ino, struct fuse_file_info* fi) /* fuse helper functions*/
static int xf_cliprdr_fuse_util_stat(xfClipboard* clipboard, fuse_ino_t ino, struct stat* stbuf)
{ {
double timeout = 0; int err = 0;
struct stat stbuf;
xfCliprdrFuseInode* node; xfCliprdrFuseInode* node;
xfClipboard* clipboard = (xfClipboard*)fuse_req_userdata(req);
ArrayList_Lock(clipboard->ino_list); ArrayList_Lock(clipboard->ino_list);
node = xf_cliprdr_get_inode(clipboard->ino_list, ino);
node = xf_cliprdr_fuse_util_get_inode(clipboard->ino_list, ino);
if (!node) if (!node)
{ {
ArrayList_Unlock(clipboard->ino_list); err = ENOENT;
fuse_reply_err(req, ENOENT); goto error;
} }
else memset(stbuf, 0, sizeof(*stbuf));
stbuf->st_ino = ino;
stbuf->st_mode = node->st_mode;
stbuf->st_mtime = node->st_mtim.tv_sec;
stbuf->st_nlink = 1;
error:
ArrayList_Unlock(clipboard->ino_list);
return err;
}
static int xf_cliprdr_fuse_util_stmode(xfClipboard* clipboard, fuse_ino_t ino, mode_t* mode)
{
int err = 0;
xfCliprdrFuseInode* node;
ArrayList_Lock(clipboard->ino_list);
node = xf_cliprdr_fuse_util_get_inode(clipboard->ino_list, ino);
if (!node)
{ {
memset(&stbuf, 0, sizeof(stbuf)); err = ENOENT;
stbuf.st_ino = ino; goto error;
stbuf.st_mode = node->st_mode;
stbuf.st_mtime = node->st_mtim.tv_sec;
stbuf.st_nlink = 1;
ArrayList_Unlock(clipboard->ino_list);
fuse_reply_attr(req, &stbuf, timeout);
} }
*mode = node->st_mode;
error:
ArrayList_Unlock(clipboard->ino_list);
return err;
}
static int xf_cliprdr_fuse_util_lindex(xfClipboard* clipboard, fuse_ino_t ino, UINT32* lindex)
{
int err = 0;
xfCliprdrFuseInode* node;
ArrayList_Lock(clipboard->ino_list);
node = xf_cliprdr_fuse_util_get_inode(clipboard->ino_list, ino);
if (!node)
{
err = ENOENT;
goto error;
}
if ((node->st_mode & S_IFDIR) != 0)
{
err = EISDIR;
goto error;
}
*lindex = node->lindex;
error:
ArrayList_Unlock(clipboard->ino_list);
return err;
}
static int xf_cliprdr_fuse_util_add_stream_list(xfClipboard* clipboard, fuse_req_t req,
UINT32* stream_id)
{
int err = 0;
xfCliprdrFuseStream* stream = (xfCliprdrFuseStream*)calloc(1, sizeof(xfCliprdrFuseStream));
if (!stream)
{
err = ENOMEM;
return err;
}
ArrayList_Lock(clipboard->stream_list);
stream->req = req;
stream->req_type = FILECONTENTS_RANGE;
stream->stream_id = clipboard->current_stream_id;
*stream_id = stream->stream_id;
stream->req_ino = 0;
clipboard->current_stream_id++;
if (ArrayList_Add(clipboard->stream_list, stream) < 0)
{
err = ENOMEM;
goto error;
}
error:
ArrayList_Unlock(clipboard->stream_list);
return err;
}
static void xf_cliprdr_fuse_getattr(fuse_req_t req, fuse_ino_t ino, struct fuse_file_info* fi)
{
int err;
struct stat stbuf;
xfClipboard* clipboard = (xfClipboard*)fuse_req_userdata(req);
err = xf_cliprdr_fuse_util_stat(clipboard, ino, &stbuf);
if (err)
{
fuse_reply_err(req, err);
return;
}
fuse_reply_attr(req, &stbuf, 0);
} }
static void xf_cliprdr_fuse_readdir(fuse_req_t req, fuse_ino_t ino, size_t size, off_t off, static void xf_cliprdr_fuse_readdir(fuse_req_t req, fuse_ino_t ino, size_t size, off_t off,
@ -2214,7 +2328,7 @@ static void xf_cliprdr_fuse_readdir(fuse_req_t req, fuse_ino_t ino, size_t size,
xfClipboard* clipboard = (xfClipboard*)fuse_req_userdata(req); xfClipboard* clipboard = (xfClipboard*)fuse_req_userdata(req);
ArrayList_Lock(clipboard->ino_list); ArrayList_Lock(clipboard->ino_list);
node = xf_cliprdr_get_inode(clipboard->ino_list, ino); node = xf_cliprdr_fuse_util_get_inode(clipboard->ino_list, ino);
if (!node || !node->child_inos) if (!node || !node->child_inos)
{ {
@ -2272,7 +2386,7 @@ static void xf_cliprdr_fuse_readdir(fuse_req_t req, fuse_ino_t ino, size_t size,
/* execlude . and .. */ /* execlude . and .. */
child_ino = (size_t)ArrayList_GetItem(node->child_inos, index - 2); child_ino = (size_t)ArrayList_GetItem(node->child_inos, index - 2);
/* previous lock for ino_list still work*/ /* previous lock for ino_list still work*/
child_node = xf_cliprdr_get_inode(clipboard->ino_list, child_ino); child_node = xf_cliprdr_fuse_util_get_inode(clipboard->ino_list, child_ino);
if (!child_node) if (!child_node)
break; break;
stbuf.st_ino = child_node->ino; stbuf.st_ino = child_node->ino;
@ -2294,24 +2408,23 @@ static void xf_cliprdr_fuse_readdir(fuse_req_t req, fuse_ino_t ino, size_t size,
static void xf_cliprdr_fuse_open(fuse_req_t req, fuse_ino_t ino, struct fuse_file_info* fi) static void xf_cliprdr_fuse_open(fuse_req_t req, fuse_ino_t ino, struct fuse_file_info* fi)
{ {
xfCliprdrFuseInode* node; int err;
mode_t mode = 0;
xfClipboard* clipboard = (xfClipboard*)fuse_req_userdata(req); xfClipboard* clipboard = (xfClipboard*)fuse_req_userdata(req);
ArrayList_Lock(clipboard->ino_list); err = xf_cliprdr_fuse_util_stmode(clipboard, ino, &mode);
node = xf_cliprdr_get_inode(clipboard->ino_list, ino); if (err)
if (!node)
{ {
ArrayList_Unlock(clipboard->ino_list); fuse_reply_err(req, err);
fuse_reply_err(req, ENOENT); return;
} }
else if ((node->st_mode & S_IFDIR) != 0)
if ((mode & S_IFDIR) != 0)
{ {
ArrayList_Unlock(clipboard->ino_list);
fuse_reply_err(req, EISDIR); fuse_reply_err(req, EISDIR);
} }
else else
{ {
ArrayList_Unlock(clipboard->ino_list);
/* Important for KDE to get file correctly*/ /* Important for KDE to get file correctly*/
fi->direct_io = 1; fi->direct_io = 1;
fuse_reply_open(req, fi); fuse_reply_open(req, fi);
@ -2326,48 +2439,24 @@ static void xf_cliprdr_fuse_read(fuse_req_t req, fuse_ino_t ino, size_t size, of
fuse_reply_err(req, ENONET); fuse_reply_err(req, ENONET);
return; return;
} }
xfCliprdrFuseInode* node; int err;
xfClipboard* clipboard = (xfClipboard*)fuse_req_userdata(req); xfClipboard* clipboard = (xfClipboard*)fuse_req_userdata(req);
UINT32 lindex; UINT32 lindex;
UINT32 stream_id; UINT32 stream_id;
ArrayList_Lock(clipboard->ino_list); err = xf_cliprdr_fuse_util_lindex(clipboard, ino, &lindex);
node = xf_cliprdr_get_inode(clipboard->ino_list, ino); if (err)
if (!node)
{ {
ArrayList_Unlock(clipboard->ino_list); fuse_reply_err(req, err);
fuse_reply_err(req, ENONET);
return; return;
} }
else if ((node->st_mode & S_IFDIR) != 0)
{
ArrayList_Unlock(clipboard->ino_list);
fuse_reply_err(req, EISDIR);
return;
}
lindex = node->lindex;
ArrayList_Unlock(clipboard->ino_list);
xfCliprdrFuseStream* stream = (xfCliprdrFuseStream*)calloc(1, sizeof(xfCliprdrFuseStream)); err = xf_cliprdr_fuse_util_add_stream_list(clipboard, req, &stream_id);
if (!stream) if (err)
{ {
fuse_reply_err(req, ENOMEM); fuse_reply_err(req, err);
return; return;
} }
ArrayList_Lock(clipboard->stream_list);
stream->req = req;
stream->req_type = FILECONTENTS_RANGE;
stream->stream_id = clipboard->current_stream_id;
stream_id = stream->stream_id;
stream->req_data = NULL;
clipboard->current_stream_id++;
if (ArrayList_Add(clipboard->stream_list, stream) < 0)
{
ArrayList_Unlock(clipboard->stream_list);
fuse_reply_err(req, ENOMEM);
return;
}
ArrayList_Unlock(clipboard->stream_list);
UINT32 nPositionLow = (off >> 0) & 0xFFFFFFFF; UINT32 nPositionLow = (off >> 0) & 0xFFFFFFFF;
UINT32 nPositionHigh = (off >> 32) & 0xFFFFFFFF; UINT32 nPositionHigh = (off >> 32) & 0xFFFFFFFF;
@ -2388,7 +2477,7 @@ static void xf_cliprdr_fuse_lookup(fuse_req_t req, fuse_ino_t parent, const char
xfClipboard* clipboard = (xfClipboard*)fuse_req_userdata(req); xfClipboard* clipboard = (xfClipboard*)fuse_req_userdata(req);
ArrayList_Lock(clipboard->ino_list); ArrayList_Lock(clipboard->ino_list);
parent_node = xf_cliprdr_get_inode(clipboard->ino_list, parent); parent_node = xf_cliprdr_fuse_util_get_inode(clipboard->ino_list, parent);
if (!parent_node || !parent_node->child_inos) if (!parent_node || !parent_node->child_inos)
{ {
@ -2402,7 +2491,7 @@ static void xf_cliprdr_fuse_lookup(fuse_req_t req, fuse_ino_t parent, const char
for (index = 0; index < count; index++) for (index = 0; index < count; index++)
{ {
child_ino = (size_t)ArrayList_GetItem(parent_node->child_inos, index); child_ino = (size_t)ArrayList_GetItem(parent_node->child_inos, index);
child_node = xf_cliprdr_get_inode(clipboard->ino_list, child_ino); child_node = xf_cliprdr_fuse_util_get_inode(clipboard->ino_list, child_ino);
if (child_node && strcmp(name, child_node->name) == 0) if (child_node && strcmp(name, child_node->name) == 0)
{ {
found = TRUE; found = TRUE;
@ -2410,8 +2499,15 @@ static void xf_cliprdr_fuse_lookup(fuse_req_t req, fuse_ino_t parent, const char
} }
} }
ArrayList_Unlock(parent_node->child_inos); ArrayList_Unlock(parent_node->child_inos);
if (found == TRUE)
if (!found)
{ {
ArrayList_Unlock(clipboard->ino_list);
fuse_reply_err(req, ENOENT);
return;
}
int res;
UINT32 stream_id; UINT32 stream_id;
BOOL size_set = child_node->size_set; BOOL size_set = child_node->size_set;
size_t lindex = child_node->lindex; size_t lindex = child_node->lindex;
@ -2420,10 +2516,10 @@ static void xf_cliprdr_fuse_lookup(fuse_req_t req, fuse_ino_t parent, const char
off_t st_size = child_node->st_size; off_t st_size = child_node->st_size;
time_t tv_sec = child_node->st_mtim.tv_sec; time_t tv_sec = child_node->st_mtim.tv_sec;
ArrayList_Unlock(clipboard->ino_list); ArrayList_Unlock(clipboard->ino_list);
if (size_set != TRUE)
if (!size_set)
{ {
xfCliprdrFuseStream* stream = xfCliprdrFuseStream* stream = (xfCliprdrFuseStream*)calloc(1, sizeof(xfCliprdrFuseStream));
(xfCliprdrFuseStream*)calloc(1, sizeof(xfCliprdrFuseStream));
if (!stream) if (!stream)
{ {
fuse_reply_err(req, ENOMEM); fuse_reply_err(req, ENOMEM);
@ -2434,19 +2530,17 @@ static void xf_cliprdr_fuse_lookup(fuse_req_t req, fuse_ino_t parent, const char
stream->req_type = FILECONTENTS_SIZE; stream->req_type = FILECONTENTS_SIZE;
stream->stream_id = clipboard->current_stream_id; stream->stream_id = clipboard->current_stream_id;
stream_id = stream->stream_id; stream_id = stream->stream_id;
/* child_node is not guaranteed to be valid */ stream->req_ino = ino;
stream->req_data = (void*)child_node;
clipboard->current_stream_id++; clipboard->current_stream_id++;
if (ArrayList_Add(clipboard->stream_list, stream) < 0) res = ArrayList_Add(clipboard->stream_list, stream);
{
ArrayList_Unlock(clipboard->stream_list); ArrayList_Unlock(clipboard->stream_list);
if (res < 0)
{
fuse_reply_err(req, ENOMEM); fuse_reply_err(req, ENOMEM);
return; return;
} }
ArrayList_Unlock(clipboard->stream_list); xf_cliprdr_send_client_file_contents(clipboard, stream_id, lindex, FILECONTENTS_SIZE, 0, 0,
0);
xf_cliprdr_send_client_file_contents(clipboard, stream_id, lindex, FILECONTENTS_SIZE, 0,
0, 0);
return; return;
} }
memset(&e, 0, sizeof(e)); memset(&e, 0, sizeof(e));
@ -2460,34 +2554,28 @@ static void xf_cliprdr_fuse_lookup(fuse_req_t req, fuse_ino_t parent, const char
e.attr.st_size = st_size; e.attr.st_size = st_size;
e.attr.st_mtime = tv_sec; e.attr.st_mtime = tv_sec;
fuse_reply_entry(req, &e); fuse_reply_entry(req, &e);
} return;
else
{
ArrayList_Unlock(clipboard->ino_list);
fuse_reply_err(req, ENOENT);
}
} }
static void xf_cliprdr_fuse_opendir(fuse_req_t req, fuse_ino_t ino, struct fuse_file_info* fi) static void xf_cliprdr_fuse_opendir(fuse_req_t req, fuse_ino_t ino, struct fuse_file_info* fi)
{ {
xfCliprdrFuseInode* node; int err;
mode_t mode = 0;
xfClipboard* clipboard = (xfClipboard*)fuse_req_userdata(req); xfClipboard* clipboard = (xfClipboard*)fuse_req_userdata(req);
ArrayList_Lock(clipboard->ino_list); err = xf_cliprdr_fuse_util_stmode(clipboard, ino, &mode);
node = xf_cliprdr_get_inode(clipboard->ino_list, ino); if (err)
if (!node)
{ {
ArrayList_Unlock(clipboard->ino_list); fuse_reply_err(req, err);
fuse_reply_err(req, ENOENT); return;
} }
else if ((node->st_mode & S_IFDIR) == 0)
if ((mode & S_IFDIR) == 0)
{ {
ArrayList_Unlock(clipboard->ino_list);
fuse_reply_err(req, ENOTDIR); fuse_reply_err(req, ENOTDIR);
} }
else else
{ {
ArrayList_Unlock(clipboard->ino_list);
fuse_reply_open(req, fi); fuse_reply_open(req, fi);
} }
} }
@ -2505,7 +2593,6 @@ static DWORD WINAPI xf_cliprdr_fuse_thread(LPVOID arg)
{ {
xfClipboard* clipboard = (xfClipboard*)arg; xfClipboard* clipboard = (xfClipboard*)arg;
/* TODO: set up a filesystem base path for local URI */
/* TODO get basePath from config or use default*/ /* TODO get basePath from config or use default*/
UINT32 basePathSize; UINT32 basePathSize;
char* basePath; char* basePath;
@ -2813,7 +2900,7 @@ void xf_clipboard_free(xfClipboard* clipboard)
CloseHandle(clipboard->fuse_thread); CloseHandle(clipboard->fuse_thread);
} }
if (clipboard->delegate->basePath) if (clipboard->delegate)
free(clipboard->delegate->basePath); free(clipboard->delegate->basePath);
// fuse related // fuse related

View File

@ -4,10 +4,9 @@
# FUSE_LIBRARIES - List of libraries when using FUSE. # FUSE_LIBRARIES - List of libraries when using FUSE.
# FUSE_FOUND - True if FUSE lib is found. # FUSE_FOUND - True if FUSE lib is found.
# check if already in cache, be silent unset(FUSE_LIBRARIES CACHE)
IF (FUSE_INCLUDE_DIR) unset(FUSE_INCLUDE_DIR CACHE)
SET (FUSE_FIND_QUIETLY TRUE) unset(FUSE_API_VERSION CACHE)
ENDIF (FUSE_INCLUDE_DIR)
include(FindPackageHandleStandardArgs) include(FindPackageHandleStandardArgs)
@ -79,6 +78,7 @@ else()
endif() endif()
endif() endif()
find_package_handle_standard_args ("FUSE" DEFAULT_MSG find_package_handle_standard_args ("FUSE" DEFAULT_MSG
FUSE_LIBRARIES FUSE_INCLUDE_DIR FUSE_API_VERSION) FUSE_LIBRARIES FUSE_INCLUDE_DIR FUSE_API_VERSION)

View File

@ -665,6 +665,7 @@ static void* convert_filedescriptors_to_file_list(wClipboard* clipboard, UINT32
size_t curLen = _wcsnlen(descriptors[x].cFileName, ARRAYSIZE(descriptors[x].cFileName)); size_t curLen = _wcsnlen(descriptors[x].cFileName, ARRAYSIZE(descriptors[x].cFileName));
alloc += WideCharToMultiByte(CP_UTF8, 0, descriptors[x].cFileName, (int)curLen, NULL, 0, alloc += WideCharToMultiByte(CP_UTF8, 0, descriptors[x].cFileName, (int)curLen, NULL, 0,
NULL, NULL); NULL, NULL);
/* # (1 char) -> %23 (3 chars) , the first char is replaced inplace */
alloc += count_special_chars(descriptors[x].cFileName) * 2; alloc += count_special_chars(descriptors[x].cFileName) * 2;
alloc += decoration_len; alloc += decoration_len;
} }