x11: refactor fuse code
This commit is contained in:
parent
e7d2f62ce6
commit
b972d70a9e
@ -42,7 +42,6 @@
|
||||
#include <sys/stat.h>
|
||||
#include <errno.h>
|
||||
#include <time.h>
|
||||
#define WIN32_FILETIME_TO_UNIX_EPOCH_USEC UINT64_C(116444736000000000)
|
||||
#endif
|
||||
|
||||
#include <winpr/crt.h>
|
||||
@ -61,6 +60,7 @@
|
||||
#define TAG CLIENT_TAG("x11")
|
||||
|
||||
#define MAX_CLIPBOARD_FORMATS 255
|
||||
#define WIN32_FILETIME_TO_UNIX_EPOCH_USEC UINT64_C(116444736000000000)
|
||||
|
||||
struct xf_cliprdr_format
|
||||
{
|
||||
@ -77,8 +77,8 @@ struct xf_cliprdr_fuse_stream
|
||||
/* 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;
|
||||
/*for FILECONTENTS_SIZE must be ino number* */
|
||||
size_t req_ino;
|
||||
};
|
||||
typedef struct xf_cliprdr_fuse_stream xfCliprdrFuseStream;
|
||||
|
||||
@ -108,8 +108,9 @@ void xf_cliprdr_fuse_inode_free(void* obj)
|
||||
inode->name = NULL;
|
||||
inode->child_inos = NULL;
|
||||
free(inode);
|
||||
inode = NULL;
|
||||
}
|
||||
static inline xfCliprdrFuseInode* xf_cliprdr_fuse_util_get_inode(wArrayList* ino_list,
|
||||
fuse_ino_t ino);
|
||||
#endif
|
||||
|
||||
struct xf_clipboard
|
||||
@ -1323,45 +1324,66 @@ xf_cliprdr_server_file_contents_response(CliprdrClientContext* context,
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (found)
|
||||
if (!found)
|
||||
{
|
||||
switch (stream->req_type)
|
||||
{
|
||||
case FILECONTENTS_SIZE:
|
||||
ino = (xfCliprdrFuseInode*)stream->req_data;
|
||||
/** ino must be exists and fileContentsResponse->cbRequested should be 64bit */
|
||||
if (!ino || data_len != sizeof(UINT64))
|
||||
{
|
||||
fuse_reply_err(stream->req, EIO);
|
||||
break;
|
||||
}
|
||||
UINT64 size;
|
||||
wStream* s = Stream_New((BYTE*)data, data_len);
|
||||
Stream_Read_UINT64(s, size);
|
||||
Stream_Free(s, FALSE);
|
||||
|
||||
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);
|
||||
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:
|
||||
/* fileContentsResponse->cbRequested should be 64bit*/
|
||||
if (data_len != sizeof(UINT64))
|
||||
{
|
||||
fuse_reply_err(req, EIO);
|
||||
break;
|
||||
}
|
||||
UINT64 size;
|
||||
wStream* s = Stream_New((BYTE*)data, data_len);
|
||||
if (!s)
|
||||
{
|
||||
fuse_reply_err(req, ENOMEM);
|
||||
break;
|
||||
}
|
||||
Stream_Read_UINT64(s, size);
|
||||
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->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;
|
||||
ArrayList_Unlock(clipboard->ino_list);
|
||||
fuse_reply_entry(req, &e);
|
||||
break;
|
||||
case FILECONTENTS_RANGE:
|
||||
fuse_reply_buf(req, (const char*)data, data_len);
|
||||
break;
|
||||
}
|
||||
return CHANNEL_RC_OK;
|
||||
}
|
||||
#endif
|
||||
@ -1611,22 +1633,31 @@ static char* xf_cliprdr_fuse_split_basename(char* name, int len)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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)
|
||||
static xfCliprdrFuseInode* xf_cliprdr_fuse_create_root_node()
|
||||
{
|
||||
if (size < 4)
|
||||
{
|
||||
WLog_ERR(TAG, "size of format data response invalid");
|
||||
return FALSE;
|
||||
}
|
||||
xfCliprdrFuseInode* rootNode = (xfCliprdrFuseInode*)calloc(1, sizeof(xfCliprdrFuseInode));
|
||||
if (!rootNode)
|
||||
return NULL;
|
||||
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;
|
||||
size_t count = (size - 4) / sizeof(FILEDESCRIPTORW);
|
||||
wStream* s = Stream_New((BYTE*)data, size);
|
||||
if (Stream_GetRemainingLength(s) < sizeof(UINT32))
|
||||
{
|
||||
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);
|
||||
if (count < 1 || count != nrDescriptors)
|
||||
if (count != nrDescriptors)
|
||||
{
|
||||
WLog_WARN(TAG, "format data response mismatch");
|
||||
goto error;
|
||||
return FALSE;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
size_t lindex;
|
||||
wHashTable* mapDir;
|
||||
/* prevent conflict between fuse_thread and this */
|
||||
ArrayList_Lock(clipboard->ino_list);
|
||||
xfCliprdrFuseInode* rootNode = (xfCliprdrFuseInode*)calloc(1, sizeof(xfCliprdrFuseInode));
|
||||
if (!rootNode)
|
||||
{
|
||||
WLog_ERR(TAG, "fail to alloc rootNode");
|
||||
goto error;
|
||||
}
|
||||
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);
|
||||
static BOOL xf_cliprdr_fuse_create_nodes(xfClipboard* clipboard, wStream* s, size_t count,
|
||||
xfCliprdrFuseInode* rootNode)
|
||||
{
|
||||
BOOL status = FALSE;
|
||||
size_t lindex = 0;
|
||||
char* curName = NULL;
|
||||
char* dirName = NULL;
|
||||
char* baseName = NULL;
|
||||
xfCliprdrFuseInode* inode;
|
||||
wHashTable* mapDir = HashTable_New(TRUE);
|
||||
if (!mapDir)
|
||||
{
|
||||
WLog_ERR(TAG, "fail to alloc hashtable");
|
||||
goto error2;
|
||||
return FALSE;
|
||||
}
|
||||
mapDir->keyFree = HashTable_StringFree;
|
||||
mapDir->keyClone = HashTable_StringClone;
|
||||
@ -1690,38 +1697,30 @@ static BOOL xf_cliprdr_fuse_generate_list(xfClipboard* clipboard, const BYTE* da
|
||||
if (!descriptor)
|
||||
{
|
||||
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 */
|
||||
for (lindex = 0; lindex < count; lindex++)
|
||||
for (; lindex < count; lindex++)
|
||||
{
|
||||
Stream_Read(s, descriptor, sizeof(FILEDESCRIPTORW));
|
||||
inode = (xfCliprdrFuseInode*)calloc(1, sizeof(xfCliprdrFuseInode));
|
||||
if (!inode)
|
||||
{
|
||||
WLog_ERR(TAG, "fail to alloc ino");
|
||||
goto error4;
|
||||
break;
|
||||
}
|
||||
|
||||
size_t curLen = _wcsnlen(descriptor->cFileName, ARRAYSIZE(descriptor->cFileName));
|
||||
curName = NULL;
|
||||
int newLen = ConvertFromUnicode(CP_UTF8, 0, descriptor->cFileName, (int)curLen, &curName, 0,
|
||||
NULL, NULL);
|
||||
if (!curName)
|
||||
{
|
||||
goto error5;
|
||||
}
|
||||
break;
|
||||
|
||||
char* split_point = xf_cliprdr_fuse_split_basename(curName, newLen);
|
||||
|
||||
char* baseName = NULL;
|
||||
UINT64 ticks;
|
||||
xfCliprdrFuseInode* parent;
|
||||
|
||||
dirName = NULL;
|
||||
|
||||
inode->lindex = lindex;
|
||||
inode->ino = lindex + 2;
|
||||
|
||||
@ -1729,43 +1728,32 @@ static BOOL xf_cliprdr_fuse_generate_list(xfClipboard* clipboard, const BYTE* da
|
||||
{
|
||||
baseName = _strdup(curName);
|
||||
if (!baseName)
|
||||
{
|
||||
goto error6;
|
||||
}
|
||||
break;
|
||||
inode->parent_ino = 1;
|
||||
inode->name = baseName;
|
||||
if (ArrayList_Add(rootNode->child_inos, (void*)inode->ino) < 0)
|
||||
{
|
||||
goto error6;
|
||||
}
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
dirName = calloc(split_point - curName + 1, sizeof(char));
|
||||
if (!dirName)
|
||||
{
|
||||
goto error6;
|
||||
}
|
||||
break;
|
||||
_snprintf(dirName, split_point - curName + 1, "%s", curName);
|
||||
/* drop last '\\' */
|
||||
baseName = _strdup(split_point + 1);
|
||||
if (!baseName)
|
||||
{
|
||||
goto error7;
|
||||
}
|
||||
break;
|
||||
|
||||
parent = (xfCliprdrFuseInode*)HashTable_GetItemValue(mapDir, dirName);
|
||||
if (!parent)
|
||||
{
|
||||
goto error7;
|
||||
}
|
||||
break;
|
||||
inode->parent_ino = parent->ino;
|
||||
inode->name = baseName;
|
||||
if (ArrayList_Add(parent->child_inos, (void*)inode->ino) < 0)
|
||||
{
|
||||
goto error7;
|
||||
}
|
||||
break;
|
||||
free(dirName);
|
||||
dirName = NULL;
|
||||
}
|
||||
/* TODO: check FD_ATTRIBUTES in dwFlags
|
||||
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->child_inos = ArrayList_New(TRUE);
|
||||
if (!inode->child_inos)
|
||||
{
|
||||
goto error6;
|
||||
}
|
||||
break;
|
||||
inode->st_size = 0;
|
||||
inode->size_set = TRUE;
|
||||
char* tmpName = _strdup(curName);
|
||||
if (!tmpName)
|
||||
{
|
||||
goto error6;
|
||||
}
|
||||
break;
|
||||
if (HashTable_Add(mapDir, tmpName, inode) < 0)
|
||||
{
|
||||
free(tmpName);
|
||||
goto error6;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
@ -1807,6 +1791,7 @@ static BOOL xf_cliprdr_fuse_generate_list(xfClipboard* clipboard, const BYTE* da
|
||||
}
|
||||
|
||||
free(curName);
|
||||
curName = NULL;
|
||||
|
||||
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)
|
||||
{
|
||||
goto error5;
|
||||
}
|
||||
break;
|
||||
}
|
||||
/* clean up incomplete ino_list*/
|
||||
if (lindex != count)
|
||||
{
|
||||
free(dirName);
|
||||
free(curName);
|
||||
/* baseName is freed in xf_cliprdr_fuse_inode_free*/
|
||||
xf_cliprdr_fuse_inode_free(inode);
|
||||
ArrayList_Clear(clipboard->ino_list);
|
||||
}
|
||||
else
|
||||
{
|
||||
status = TRUE;
|
||||
}
|
||||
ArrayList_Unlock(clipboard->ino_list);
|
||||
free(descriptor);
|
||||
HashTable_Free(mapDir);
|
||||
|
||||
Stream_Free(s, FALSE);
|
||||
return TRUE;
|
||||
error7:
|
||||
free(dirName);
|
||||
error6:
|
||||
free(curName);
|
||||
error5:
|
||||
xf_cliprdr_fuse_inode_free(inode);
|
||||
error4:
|
||||
free(descriptor);
|
||||
error3:
|
||||
HashTable_Free(mapDir);
|
||||
error2:
|
||||
ArrayList_Clear(clipboard->ino_list);
|
||||
|
||||
error:
|
||||
HashTable_Free(mapDir);
|
||||
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;
|
||||
}
|
||||
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 FALSE;
|
||||
return status;
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -1875,6 +1899,12 @@ xf_cliprdr_server_format_data_response(CliprdrClientContext* context,
|
||||
xfClipboard* clipboard = (xfClipboard*)context->custom;
|
||||
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)
|
||||
return CHANNEL_RC_OK;
|
||||
|
||||
@ -1902,7 +1932,7 @@ xf_cliprdr_server_format_data_response(CliprdrClientContext* context,
|
||||
{
|
||||
#ifdef WITH_FUSE
|
||||
/* 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 */
|
||||
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
|
||||
/* 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;
|
||||
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;
|
||||
struct stat stbuf;
|
||||
|
||||
int err = 0;
|
||||
xfCliprdrFuseInode* node;
|
||||
xfClipboard* clipboard = (xfClipboard*)fuse_req_userdata(req);
|
||||
|
||||
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)
|
||||
{
|
||||
ArrayList_Unlock(clipboard->ino_list);
|
||||
fuse_reply_err(req, ENOENT);
|
||||
err = 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));
|
||||
stbuf.st_ino = ino;
|
||||
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);
|
||||
err = ENOENT;
|
||||
goto error;
|
||||
}
|
||||
*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,
|
||||
@ -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);
|
||||
|
||||
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)
|
||||
{
|
||||
@ -2272,7 +2386,7 @@ static void xf_cliprdr_fuse_readdir(fuse_req_t req, fuse_ino_t ino, size_t size,
|
||||
/* execlude . and .. */
|
||||
child_ino = (size_t)ArrayList_GetItem(node->child_inos, index - 2);
|
||||
/* 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)
|
||||
break;
|
||||
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)
|
||||
{
|
||||
xfCliprdrFuseInode* node;
|
||||
int err;
|
||||
mode_t mode = 0;
|
||||
xfClipboard* clipboard = (xfClipboard*)fuse_req_userdata(req);
|
||||
|
||||
ArrayList_Lock(clipboard->ino_list);
|
||||
node = xf_cliprdr_get_inode(clipboard->ino_list, ino);
|
||||
if (!node)
|
||||
err = xf_cliprdr_fuse_util_stmode(clipboard, ino, &mode);
|
||||
if (err)
|
||||
{
|
||||
ArrayList_Unlock(clipboard->ino_list);
|
||||
fuse_reply_err(req, ENOENT);
|
||||
fuse_reply_err(req, err);
|
||||
return;
|
||||
}
|
||||
else if ((node->st_mode & S_IFDIR) != 0)
|
||||
|
||||
if ((mode & S_IFDIR) != 0)
|
||||
{
|
||||
ArrayList_Unlock(clipboard->ino_list);
|
||||
fuse_reply_err(req, EISDIR);
|
||||
}
|
||||
else
|
||||
{
|
||||
ArrayList_Unlock(clipboard->ino_list);
|
||||
/* Important for KDE to get file correctly*/
|
||||
fi->direct_io = 1;
|
||||
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);
|
||||
return;
|
||||
}
|
||||
xfCliprdrFuseInode* node;
|
||||
int err;
|
||||
xfClipboard* clipboard = (xfClipboard*)fuse_req_userdata(req);
|
||||
UINT32 lindex;
|
||||
UINT32 stream_id;
|
||||
|
||||
ArrayList_Lock(clipboard->ino_list);
|
||||
node = xf_cliprdr_get_inode(clipboard->ino_list, ino);
|
||||
if (!node)
|
||||
err = xf_cliprdr_fuse_util_lindex(clipboard, ino, &lindex);
|
||||
if (err)
|
||||
{
|
||||
ArrayList_Unlock(clipboard->ino_list);
|
||||
fuse_reply_err(req, ENONET);
|
||||
fuse_reply_err(req, err);
|
||||
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));
|
||||
if (!stream)
|
||||
err = xf_cliprdr_fuse_util_add_stream_list(clipboard, req, &stream_id);
|
||||
if (err)
|
||||
{
|
||||
fuse_reply_err(req, ENOMEM);
|
||||
fuse_reply_err(req, err);
|
||||
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 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);
|
||||
|
||||
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)
|
||||
{
|
||||
@ -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++)
|
||||
{
|
||||
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)
|
||||
{
|
||||
found = TRUE;
|
||||
@ -2410,84 +2499,83 @@ 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)
|
||||
{
|
||||
UINT32 stream_id;
|
||||
BOOL size_set = child_node->size_set;
|
||||
size_t lindex = child_node->lindex;
|
||||
size_t ino = child_node->ino;
|
||||
mode_t st_mode = child_node->st_mode;
|
||||
off_t st_size = child_node->st_size;
|
||||
time_t tv_sec = child_node->st_mtim.tv_sec;
|
||||
ArrayList_Unlock(clipboard->ino_list);
|
||||
if (size_set != TRUE)
|
||||
{
|
||||
xfCliprdrFuseStream* stream =
|
||||
(xfCliprdrFuseStream*)calloc(1, sizeof(xfCliprdrFuseStream));
|
||||
if (!stream)
|
||||
{
|
||||
fuse_reply_err(req, ENOMEM);
|
||||
return;
|
||||
}
|
||||
ArrayList_Lock(clipboard->stream_list);
|
||||
stream->req = req;
|
||||
stream->req_type = FILECONTENTS_SIZE;
|
||||
stream->stream_id = clipboard->current_stream_id;
|
||||
stream_id = stream->stream_id;
|
||||
/* child_node is not guaranteed to be valid */
|
||||
stream->req_data = (void*)child_node;
|
||||
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);
|
||||
|
||||
xf_cliprdr_send_client_file_contents(clipboard, stream_id, lindex, FILECONTENTS_SIZE, 0,
|
||||
0, 0);
|
||||
return;
|
||||
}
|
||||
memset(&e, 0, sizeof(e));
|
||||
e.ino = ino;
|
||||
e.attr_timeout = 1.0;
|
||||
e.entry_timeout = 1.0;
|
||||
e.attr.st_ino = ino;
|
||||
e.attr.st_mode = st_mode;
|
||||
e.attr.st_nlink = 1;
|
||||
|
||||
e.attr.st_size = st_size;
|
||||
e.attr.st_mtime = tv_sec;
|
||||
fuse_reply_entry(req, &e);
|
||||
}
|
||||
else
|
||||
if (!found)
|
||||
{
|
||||
ArrayList_Unlock(clipboard->ino_list);
|
||||
fuse_reply_err(req, ENOENT);
|
||||
return;
|
||||
}
|
||||
|
||||
int res;
|
||||
UINT32 stream_id;
|
||||
BOOL size_set = child_node->size_set;
|
||||
size_t lindex = child_node->lindex;
|
||||
size_t ino = child_node->ino;
|
||||
mode_t st_mode = child_node->st_mode;
|
||||
off_t st_size = child_node->st_size;
|
||||
time_t tv_sec = child_node->st_mtim.tv_sec;
|
||||
ArrayList_Unlock(clipboard->ino_list);
|
||||
|
||||
if (!size_set)
|
||||
{
|
||||
xfCliprdrFuseStream* stream = (xfCliprdrFuseStream*)calloc(1, sizeof(xfCliprdrFuseStream));
|
||||
if (!stream)
|
||||
{
|
||||
fuse_reply_err(req, ENOMEM);
|
||||
return;
|
||||
}
|
||||
ArrayList_Lock(clipboard->stream_list);
|
||||
stream->req = req;
|
||||
stream->req_type = FILECONTENTS_SIZE;
|
||||
stream->stream_id = clipboard->current_stream_id;
|
||||
stream_id = stream->stream_id;
|
||||
stream->req_ino = ino;
|
||||
clipboard->current_stream_id++;
|
||||
res = ArrayList_Add(clipboard->stream_list, stream);
|
||||
ArrayList_Unlock(clipboard->stream_list);
|
||||
if (res < 0)
|
||||
{
|
||||
fuse_reply_err(req, ENOMEM);
|
||||
return;
|
||||
}
|
||||
xf_cliprdr_send_client_file_contents(clipboard, stream_id, lindex, FILECONTENTS_SIZE, 0, 0,
|
||||
0);
|
||||
return;
|
||||
}
|
||||
memset(&e, 0, sizeof(e));
|
||||
e.ino = ino;
|
||||
e.attr_timeout = 1.0;
|
||||
e.entry_timeout = 1.0;
|
||||
e.attr.st_ino = ino;
|
||||
e.attr.st_mode = st_mode;
|
||||
e.attr.st_nlink = 1;
|
||||
|
||||
e.attr.st_size = st_size;
|
||||
e.attr.st_mtime = tv_sec;
|
||||
fuse_reply_entry(req, &e);
|
||||
return;
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
ArrayList_Lock(clipboard->ino_list);
|
||||
node = xf_cliprdr_get_inode(clipboard->ino_list, ino);
|
||||
if (!node)
|
||||
err = xf_cliprdr_fuse_util_stmode(clipboard, ino, &mode);
|
||||
if (err)
|
||||
{
|
||||
ArrayList_Unlock(clipboard->ino_list);
|
||||
fuse_reply_err(req, ENOENT);
|
||||
fuse_reply_err(req, err);
|
||||
return;
|
||||
}
|
||||
else if ((node->st_mode & S_IFDIR) == 0)
|
||||
|
||||
if ((mode & S_IFDIR) == 0)
|
||||
{
|
||||
ArrayList_Unlock(clipboard->ino_list);
|
||||
fuse_reply_err(req, ENOTDIR);
|
||||
}
|
||||
else
|
||||
{
|
||||
ArrayList_Unlock(clipboard->ino_list);
|
||||
fuse_reply_open(req, fi);
|
||||
}
|
||||
}
|
||||
@ -2505,7 +2593,6 @@ static DWORD WINAPI xf_cliprdr_fuse_thread(LPVOID arg)
|
||||
{
|
||||
xfClipboard* clipboard = (xfClipboard*)arg;
|
||||
|
||||
/* TODO: set up a filesystem base path for local URI */
|
||||
/* TODO get basePath from config or use default*/
|
||||
UINT32 basePathSize;
|
||||
char* basePath;
|
||||
@ -2813,7 +2900,7 @@ void xf_clipboard_free(xfClipboard* clipboard)
|
||||
CloseHandle(clipboard->fuse_thread);
|
||||
}
|
||||
|
||||
if (clipboard->delegate->basePath)
|
||||
if (clipboard->delegate)
|
||||
free(clipboard->delegate->basePath);
|
||||
|
||||
// fuse related
|
||||
|
@ -4,10 +4,9 @@
|
||||
# FUSE_LIBRARIES - List of libraries when using FUSE.
|
||||
# FUSE_FOUND - True if FUSE lib is found.
|
||||
|
||||
# check if already in cache, be silent
|
||||
IF (FUSE_INCLUDE_DIR)
|
||||
SET (FUSE_FIND_QUIETLY TRUE)
|
||||
ENDIF (FUSE_INCLUDE_DIR)
|
||||
unset(FUSE_LIBRARIES CACHE)
|
||||
unset(FUSE_INCLUDE_DIR CACHE)
|
||||
unset(FUSE_API_VERSION CACHE)
|
||||
|
||||
include(FindPackageHandleStandardArgs)
|
||||
|
||||
@ -79,6 +78,7 @@ else()
|
||||
endif()
|
||||
endif()
|
||||
|
||||
|
||||
find_package_handle_standard_args ("FUSE" DEFAULT_MSG
|
||||
FUSE_LIBRARIES FUSE_INCLUDE_DIR FUSE_API_VERSION)
|
||||
|
||||
|
@ -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));
|
||||
alloc += WideCharToMultiByte(CP_UTF8, 0, descriptors[x].cFileName, (int)curLen, NULL, 0,
|
||||
NULL, NULL);
|
||||
/* # (1 char) -> %23 (3 chars) , the first char is replaced inplace */
|
||||
alloc += count_special_chars(descriptors[x].cFileName) * 2;
|
||||
alloc += decoration_len;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user