[client,common] fix file copy client to server
This commit is contained in:
parent
9fb4465722
commit
39c06a4683
@ -76,6 +76,7 @@ typedef struct
|
|||||||
fuse_req_t req;
|
fuse_req_t req;
|
||||||
/*for FILECONTENTS_SIZE must be ino number* */
|
/*for FILECONTENTS_SIZE must be ino number* */
|
||||||
size_t req_ino;
|
size_t req_ino;
|
||||||
|
UINT32 lockId;
|
||||||
} CliprdrFuseStream;
|
} CliprdrFuseStream;
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
@ -89,7 +90,7 @@ typedef struct
|
|||||||
struct timespec st_mtim;
|
struct timespec st_mtim;
|
||||||
char* name;
|
char* name;
|
||||||
wArrayList* child_inos;
|
wArrayList* child_inos;
|
||||||
UINT32 streamID;
|
INT64 lockID;
|
||||||
} CliprdrFuseInode;
|
} CliprdrFuseInode;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -97,12 +98,12 @@ typedef struct
|
|||||||
{
|
{
|
||||||
char* name;
|
char* name;
|
||||||
FILE* fp;
|
FILE* fp;
|
||||||
|
INT64 size;
|
||||||
} CliprdrLocalFile;
|
} CliprdrLocalFile;
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
UINT32 streamID;
|
UINT32 lockId;
|
||||||
|
|
||||||
BOOL locked;
|
BOOL locked;
|
||||||
size_t count;
|
size_t count;
|
||||||
CliprdrLocalFile* files;
|
CliprdrLocalFile* files;
|
||||||
@ -126,14 +127,15 @@ struct cliprdr_file_context
|
|||||||
BOOL file_formats_registered;
|
BOOL file_formats_registered;
|
||||||
UINT32 file_capability_flags;
|
UINT32 file_capability_flags;
|
||||||
|
|
||||||
UINT32 local_stream_id;
|
UINT32 local_lock_id;
|
||||||
UINT32 remote_stream_id;
|
UINT32 remote_lock_id;
|
||||||
|
|
||||||
wHashTable* local_streams;
|
wHashTable* local_streams;
|
||||||
wLog* log;
|
wLog* log;
|
||||||
void* clipboard;
|
void* clipboard;
|
||||||
CliprdrClientContext* context;
|
CliprdrClientContext* context;
|
||||||
char* path;
|
char* path;
|
||||||
|
char* current_path;
|
||||||
BYTE hash[WINPR_SHA256_DIGEST_LENGTH];
|
BYTE hash[WINPR_SHA256_DIGEST_LENGTH];
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -144,7 +146,7 @@ static BOOL local_stream_discard(const void* key, void* value, void* arg);
|
|||||||
#if defined(WITH_FUSE2) || defined(WITH_FUSE3)
|
#if defined(WITH_FUSE2) || defined(WITH_FUSE3)
|
||||||
static BOOL cliprdr_fuse_repopulate(CliprdrFileContext* file, wArrayList* list);
|
static BOOL cliprdr_fuse_repopulate(CliprdrFileContext* file, wArrayList* list);
|
||||||
static UINT cliprdr_file_send_client_file_contents(CliprdrFileContext* file, UINT32 streamId,
|
static UINT cliprdr_file_send_client_file_contents(CliprdrFileContext* file, UINT32 streamId,
|
||||||
UINT32 listIndex, UINT32 dwFlags,
|
UINT32 lockId, UINT32 listIndex, UINT32 dwFlags,
|
||||||
UINT32 nPositionLow, UINT32 nPositionHigh,
|
UINT32 nPositionLow, UINT32 nPositionHigh,
|
||||||
UINT32 cbRequested);
|
UINT32 cbRequested);
|
||||||
|
|
||||||
@ -195,14 +197,14 @@ static void cliprdr_file_fuse_node_free(void* obj)
|
|||||||
free(inode);
|
free(inode);
|
||||||
}
|
}
|
||||||
|
|
||||||
static CliprdrFuseInode* cliprdr_file_fuse_node_new(UINT32 streamID, size_t lindex, size_t ino,
|
static CliprdrFuseInode* cliprdr_file_fuse_node_new(UINT32 lockID, size_t lindex, size_t ino,
|
||||||
size_t parent, const char* path, mode_t mode)
|
size_t parent, const char* path, mode_t mode)
|
||||||
{
|
{
|
||||||
CliprdrFuseInode* node = (CliprdrFuseInode*)calloc(1, sizeof(CliprdrFuseInode));
|
CliprdrFuseInode* node = (CliprdrFuseInode*)calloc(1, sizeof(CliprdrFuseInode));
|
||||||
if (!node)
|
if (!node)
|
||||||
goto fail;
|
goto fail;
|
||||||
|
|
||||||
node->streamID = streamID;
|
node->lockID = lockID;
|
||||||
node->ino = ino;
|
node->ino = ino;
|
||||||
node->parent_ino = parent;
|
node->parent_ino = parent;
|
||||||
node->lindex = lindex;
|
node->lindex = lindex;
|
||||||
@ -327,7 +329,8 @@ error:
|
|||||||
|
|
||||||
static int cliprdr_file_fuse_util_get_and_update_stream_list(CliprdrFileContext* file,
|
static int cliprdr_file_fuse_util_get_and_update_stream_list(CliprdrFileContext* file,
|
||||||
fuse_req_t req, size_t ino,
|
fuse_req_t req, size_t ino,
|
||||||
UINT32 type, UINT32* stream_id)
|
UINT32 type, UINT32* stream_id,
|
||||||
|
UINT32* lockId)
|
||||||
{
|
{
|
||||||
int rc = ENOMEM;
|
int rc = ENOMEM;
|
||||||
|
|
||||||
@ -339,16 +342,17 @@ static int cliprdr_file_fuse_util_get_and_update_stream_list(CliprdrFileContext*
|
|||||||
CliprdrFuseInode* node = cliprdr_file_fuse_util_get_inode(file->ino_list, ino);
|
CliprdrFuseInode* node = cliprdr_file_fuse_util_get_inode(file->ino_list, ino);
|
||||||
if (node)
|
if (node)
|
||||||
{
|
{
|
||||||
CliprdrFuseStream* stream = HashTable_GetItemValue(file->remote_streams, &node->streamID);
|
CliprdrFuseStream* stream = HashTable_GetItemValue(file->remote_streams, &node->lockID);
|
||||||
if (stream)
|
if (stream)
|
||||||
{
|
{
|
||||||
CliprdrFuseStream* request =
|
CliprdrFuseStream* request =
|
||||||
cliprdr_fuse_stream_new(node->streamID, req, stream->req_ino, type);
|
cliprdr_fuse_stream_new(node->lockID, req, stream->req_ino, type);
|
||||||
if (request)
|
if (request)
|
||||||
{
|
{
|
||||||
if (Queue_Enqueue(file->requests_in_flight, stream))
|
if (Queue_Enqueue(file->requests_in_flight, stream))
|
||||||
{
|
{
|
||||||
*stream_id = node->streamID;
|
*stream_id = node->lockID;
|
||||||
|
*lockId = node->lockID;
|
||||||
rc = 0;
|
rc = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -369,7 +373,7 @@ static int cliprdr_file_fuse_util_add_stream_list(CliprdrFileContext* file)
|
|||||||
if (!stream)
|
if (!stream)
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
const BOOL res = HashTable_Insert(file->remote_streams, &stream->stream_id, stream);
|
const BOOL res = HashTable_Insert(file->remote_streams, &stream->lockId, stream);
|
||||||
if (!res)
|
if (!res)
|
||||||
{
|
{
|
||||||
cliprdr_fuse_stream_free(stream);
|
cliprdr_fuse_stream_free(stream);
|
||||||
@ -533,8 +537,9 @@ void cliprdr_file_fuse_read(fuse_req_t req, fuse_ino_t ino, size_t size, off_t o
|
|||||||
{
|
{
|
||||||
int err;
|
int err;
|
||||||
CliprdrFileContext* file = (CliprdrFileContext*)fuse_req_userdata(req);
|
CliprdrFileContext* file = (CliprdrFileContext*)fuse_req_userdata(req);
|
||||||
UINT32 lindex;
|
UINT32 lindex = 0;
|
||||||
UINT32 stream_id;
|
UINT32 stream_id = 0;
|
||||||
|
UINT32 lock_id = 0;
|
||||||
|
|
||||||
WINPR_ASSERT(file);
|
WINPR_ASSERT(file);
|
||||||
|
|
||||||
@ -546,7 +551,7 @@ void cliprdr_file_fuse_read(fuse_req_t req, fuse_ino_t ino, size_t size, off_t o
|
|||||||
}
|
}
|
||||||
|
|
||||||
err = cliprdr_file_fuse_util_get_and_update_stream_list(file, req, ino, FILECONTENTS_RANGE,
|
err = cliprdr_file_fuse_util_get_and_update_stream_list(file, req, ino, FILECONTENTS_RANGE,
|
||||||
&stream_id);
|
&stream_id, &lock_id);
|
||||||
if (err)
|
if (err)
|
||||||
{
|
{
|
||||||
fuse_reply_err(req, err);
|
fuse_reply_err(req, err);
|
||||||
@ -556,7 +561,7 @@ void cliprdr_file_fuse_read(fuse_req_t req, fuse_ino_t ino, size_t size, off_t o
|
|||||||
UINT32 nPositionLow = (off >> 0) & 0xFFFFFFFF;
|
UINT32 nPositionLow = (off >> 0) & 0xFFFFFFFF;
|
||||||
UINT32 nPositionHigh = (off >> 32) & 0xFFFFFFFF;
|
UINT32 nPositionHigh = (off >> 32) & 0xFFFFFFFF;
|
||||||
|
|
||||||
cliprdr_file_send_client_file_contents(file, stream_id, lindex, FILECONTENTS_RANGE,
|
cliprdr_file_send_client_file_contents(file, stream_id, lock_id, lindex, FILECONTENTS_RANGE,
|
||||||
nPositionLow, nPositionHigh, size);
|
nPositionLow, nPositionHigh, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -612,14 +617,16 @@ void cliprdr_file_fuse_lookup(fuse_req_t req, fuse_ino_t parent, const char* nam
|
|||||||
if (!size_set)
|
if (!size_set)
|
||||||
{
|
{
|
||||||
UINT32 streamID = 0;
|
UINT32 streamID = 0;
|
||||||
|
UINT32 lockId = 0;
|
||||||
const int err = cliprdr_file_fuse_util_get_and_update_stream_list(
|
const int err = cliprdr_file_fuse_util_get_and_update_stream_list(
|
||||||
file, req, ino, FILECONTENTS_SIZE, &streamID);
|
file, req, ino, FILECONTENTS_SIZE, &streamID, &lockId);
|
||||||
if (err != 0)
|
if (err != 0)
|
||||||
{
|
{
|
||||||
fuse_reply_err(req, err);
|
fuse_reply_err(req, err);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
cliprdr_file_send_client_file_contents(file, streamID, lindex, FILECONTENTS_SIZE, 0, 0, 0);
|
cliprdr_file_send_client_file_contents(file, streamID, lockId, lindex, FILECONTENTS_SIZE, 0,
|
||||||
|
0, 0);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
e.ino = ino;
|
e.ino = ino;
|
||||||
@ -748,12 +755,11 @@ static BOOL add_stream_node(const void* key, void* value, void* arg)
|
|||||||
WINPR_ASSERT(node_arg->root);
|
WINPR_ASSERT(node_arg->root);
|
||||||
|
|
||||||
char name[10] = { 0 };
|
char name[10] = { 0 };
|
||||||
_snprintf(name, sizeof(name), "%08" PRIx32, stream->stream_id);
|
_snprintf(name, sizeof(name), "%08" PRIx32, stream->lockId);
|
||||||
|
|
||||||
const size_t idx = ArrayList_Count(node_arg->list);
|
const size_t idx = ArrayList_Count(node_arg->list);
|
||||||
CliprdrFuseInode* node =
|
CliprdrFuseInode* node = cliprdr_file_fuse_node_new(
|
||||||
cliprdr_file_fuse_node_new(stream->stream_id, idx, FUSE_ROOT_ID + 1 + stream->stream_id,
|
stream->lockId, idx, FUSE_ROOT_ID + 1 + stream->lockId, FUSE_ROOT_ID, name, S_IFDIR | 0700);
|
||||||
FUSE_ROOT_ID, name, S_IFDIR | 0700);
|
|
||||||
if (!node)
|
if (!node)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
node->size_set = TRUE;
|
node->size_set = TRUE;
|
||||||
@ -799,14 +805,17 @@ fail:
|
|||||||
* @return 0 on success, otherwise a Win32 error code
|
* @return 0 on success, otherwise a Win32 error code
|
||||||
*/
|
*/
|
||||||
static UINT cliprdr_file_send_client_file_contents(CliprdrFileContext* file, UINT32 streamId,
|
static UINT cliprdr_file_send_client_file_contents(CliprdrFileContext* file, UINT32 streamId,
|
||||||
UINT32 listIndex, UINT32 dwFlags,
|
UINT32 lockId, UINT32 listIndex, UINT32 dwFlags,
|
||||||
UINT32 nPositionLow, UINT32 nPositionHigh,
|
UINT32 nPositionLow, UINT32 nPositionHigh,
|
||||||
UINT32 cbRequested)
|
UINT32 cbRequested)
|
||||||
{
|
{
|
||||||
CLIPRDR_FILE_CONTENTS_REQUEST formatFileContentsRequest = { 0 };
|
CLIPRDR_FILE_CONTENTS_REQUEST formatFileContentsRequest = {
|
||||||
formatFileContentsRequest.streamId = streamId;
|
.streamId = streamId,
|
||||||
formatFileContentsRequest.listIndex = listIndex;
|
.clipDataId = lockId,
|
||||||
formatFileContentsRequest.dwFlags = dwFlags;
|
.haveClipDataId = cliprdr_file_context_current_flags(file) & CB_CAN_LOCK_CLIPDATA,
|
||||||
|
.listIndex = listIndex,
|
||||||
|
.dwFlags = dwFlags
|
||||||
|
};
|
||||||
|
|
||||||
WINPR_ASSERT(file);
|
WINPR_ASSERT(file);
|
||||||
switch (dwFlags)
|
switch (dwFlags)
|
||||||
@ -1001,7 +1010,8 @@ static BOOL cliprdr_file_fuse_create_nodes(CliprdrFileContext* file, wStream* s,
|
|||||||
char curName[ARRAYSIZE(descriptor.cFileName)] = { 0 };
|
char curName[ARRAYSIZE(descriptor.cFileName)] = { 0 };
|
||||||
char dirName[ARRAYSIZE(descriptor.cFileName)] = { 0 };
|
char dirName[ARRAYSIZE(descriptor.cFileName)] = { 0 };
|
||||||
|
|
||||||
Stream_Read(s, &descriptor, sizeof(FILEDESCRIPTORW));
|
if (!cliprdr_read_filedescriptor(s, &descriptor))
|
||||||
|
goto fail;
|
||||||
|
|
||||||
ConvertWCharNToUtf8(descriptor.cFileName, ARRAYSIZE(descriptor.cFileName), curName,
|
ConvertWCharNToUtf8(descriptor.cFileName, ARRAYSIZE(descriptor.cFileName), curName,
|
||||||
ARRAYSIZE(curName));
|
ARRAYSIZE(curName));
|
||||||
@ -1015,7 +1025,7 @@ static BOOL cliprdr_file_fuse_create_nodes(CliprdrFileContext* file, wStream* s,
|
|||||||
CliprdrFuseInode* inode = NULL;
|
CliprdrFuseInode* inode = NULL;
|
||||||
if (split_point == NULL)
|
if (split_point == NULL)
|
||||||
{
|
{
|
||||||
inode = cliprdr_file_fuse_node_new(rootNode->streamID, lindex, nextIno++, rootNode->ino,
|
inode = cliprdr_file_fuse_node_new(rootNode->lockID, lindex, nextIno++, rootNode->ino,
|
||||||
curName, 0700);
|
curName, 0700);
|
||||||
if (!ArrayList_Append(file->ino_list, inode))
|
if (!ArrayList_Append(file->ino_list, inode))
|
||||||
goto fail;
|
goto fail;
|
||||||
@ -1032,7 +1042,7 @@ static BOOL cliprdr_file_fuse_create_nodes(CliprdrFileContext* file, wStream* s,
|
|||||||
parent = (CliprdrFuseInode*)HashTable_GetItemValue(mapDir, dirName);
|
parent = (CliprdrFuseInode*)HashTable_GetItemValue(mapDir, dirName);
|
||||||
if (!parent)
|
if (!parent)
|
||||||
goto fail;
|
goto fail;
|
||||||
inode = cliprdr_file_fuse_node_new(rootNode->streamID, lindex, nextIno++, parent->ino,
|
inode = cliprdr_file_fuse_node_new(rootNode->lockID, lindex, nextIno++, parent->ino,
|
||||||
baseName, 0700);
|
baseName, 0700);
|
||||||
if (!inode)
|
if (!inode)
|
||||||
goto fail;
|
goto fail;
|
||||||
@ -1172,33 +1182,52 @@ static UINT cliprdr_file_context_send_contents(CliprdrClientContext* context,
|
|||||||
return context->ClientFileContentsResponse(context, &response);
|
return context->ClientFileContentsResponse(context, &response);
|
||||||
}
|
}
|
||||||
|
|
||||||
static FILE* file_for_request(CliprdrFileContext* file, UINT32 streamId, UINT32 listIndex)
|
static CliprdrLocalFile* file_info_for_request(CliprdrFileContext* file, UINT32 lockId,
|
||||||
|
UINT32 listIndex)
|
||||||
{
|
{
|
||||||
FILE* fp = NULL;
|
WINPR_ASSERT(file);
|
||||||
HashTable_Lock(file->local_streams);
|
|
||||||
|
|
||||||
CliprdrLocalStream* cur = HashTable_GetItemValue(file->local_streams, &streamId);
|
CliprdrLocalStream* cur = HashTable_GetItemValue(file->local_streams, &lockId);
|
||||||
if (cur)
|
if (cur)
|
||||||
{
|
{
|
||||||
if (listIndex < cur->count)
|
if (listIndex < cur->count)
|
||||||
{
|
{
|
||||||
CliprdrLocalFile* f = &cur->files[listIndex];
|
CliprdrLocalFile* f = &cur->files[listIndex];
|
||||||
if (f->fp)
|
WLog_INFO("xxxx", "got %s [%" PRIu32 "]", f->name, listIndex);
|
||||||
fp = f->fp;
|
return f;
|
||||||
else
|
|
||||||
{
|
|
||||||
if (strncmp("file://", f->name, 7) == 0)
|
|
||||||
fp = fopen(&f->name[7], "rb");
|
|
||||||
else
|
|
||||||
fp = fopen(f->name, "rb");
|
|
||||||
f->fp = fp;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
HashTable_Unlock(file->local_streams);
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
return fp;
|
static CliprdrLocalFile* file_for_request(CliprdrFileContext* file, UINT32 lockId, UINT32 listIndex)
|
||||||
|
{
|
||||||
|
CliprdrLocalFile* f = file_info_for_request(file, lockId, listIndex);
|
||||||
|
if (f)
|
||||||
|
{
|
||||||
|
if (!f->fp)
|
||||||
|
{
|
||||||
|
const char* name = f->name;
|
||||||
|
f->fp = winpr_fopen(name, "rb");
|
||||||
|
}
|
||||||
|
if (!f->fp)
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return f;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void cliprdr_local_file_try_close(CliprdrLocalFile* file, UINT res, UINT64 offset,
|
||||||
|
UINT64 size)
|
||||||
|
{
|
||||||
|
WINPR_ASSERT(file);
|
||||||
|
|
||||||
|
if ((res != 0) || ((file->size > 0) && (offset + size >= file->size)))
|
||||||
|
{
|
||||||
|
fclose(file->fp);
|
||||||
|
file->fp = NULL;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static UINT cliprdr_file_context_server_file_size_request(
|
static UINT cliprdr_file_context_server_file_size_request(
|
||||||
@ -1217,15 +1246,23 @@ static UINT cliprdr_file_context_server_file_size_request(
|
|||||||
fileContentsRequest->cbRequested);
|
fileContentsRequest->cbRequested);
|
||||||
}
|
}
|
||||||
|
|
||||||
FILE* fp =
|
HashTable_Lock(file->local_streams);
|
||||||
file_for_request(file, fileContentsRequest->streamId, fileContentsRequest->listIndex);
|
|
||||||
if (!fp)
|
|
||||||
return cliprdr_file_context_send_file_contents_failure(file->context, fileContentsRequest);
|
|
||||||
|
|
||||||
if (_fseeki64(fp, 0, SEEK_END) < 0)
|
UINT res = CHANNEL_RC_OK;
|
||||||
return cliprdr_file_context_send_file_contents_failure(file->context, fileContentsRequest);
|
CliprdrLocalFile* rfile =
|
||||||
|
file_for_request(file, fileContentsRequest->clipDataId, fileContentsRequest->listIndex);
|
||||||
|
if (!rfile)
|
||||||
|
res = cliprdr_file_context_send_file_contents_failure(file->context, fileContentsRequest);
|
||||||
|
|
||||||
const INT64 size = _ftelli64(fp);
|
if (_fseeki64(rfile->fp, 0, SEEK_END) < 0)
|
||||||
|
res = cliprdr_file_context_send_file_contents_failure(file->context, fileContentsRequest);
|
||||||
|
|
||||||
|
const INT64 size = _ftelli64(rfile->fp);
|
||||||
|
rfile->size = size;
|
||||||
|
cliprdr_local_file_try_close(rfile, res, 0, 0);
|
||||||
|
HashTable_Unlock(file->local_streams);
|
||||||
|
if (res != CHANNEL_RC_OK)
|
||||||
|
return res;
|
||||||
return cliprdr_file_context_send_contents(file->context, fileContentsRequest, &size,
|
return cliprdr_file_context_send_contents(file->context, fileContentsRequest, &size,
|
||||||
sizeof(size));
|
sizeof(size));
|
||||||
}
|
}
|
||||||
@ -1234,52 +1271,71 @@ static UINT cliprdr_file_context_server_file_range_request(
|
|||||||
CliprdrFileContext* file, const CLIPRDR_FILE_CONTENTS_REQUEST* fileContentsRequest)
|
CliprdrFileContext* file, const CLIPRDR_FILE_CONTENTS_REQUEST* fileContentsRequest)
|
||||||
{
|
{
|
||||||
BYTE* data = NULL;
|
BYTE* data = NULL;
|
||||||
wClipboardFileRangeRequest request = { 0 };
|
|
||||||
|
|
||||||
WINPR_ASSERT(fileContentsRequest);
|
WINPR_ASSERT(fileContentsRequest);
|
||||||
|
|
||||||
request.streamId = fileContentsRequest->streamId;
|
HashTable_Lock(file->local_streams);
|
||||||
request.listIndex = fileContentsRequest->listIndex;
|
|
||||||
request.nPositionLow = fileContentsRequest->nPositionLow;
|
|
||||||
request.nPositionHigh = fileContentsRequest->nPositionHigh;
|
|
||||||
request.cbRequested = fileContentsRequest->cbRequested;
|
|
||||||
FILE* fp =
|
|
||||||
file_for_request(file, fileContentsRequest->streamId, fileContentsRequest->listIndex);
|
|
||||||
if (!fp)
|
|
||||||
goto fail;
|
|
||||||
|
|
||||||
const UINT64 offset = (((UINT64)fileContentsRequest->nPositionHigh) << 32) |
|
const UINT64 offset = (((UINT64)fileContentsRequest->nPositionHigh) << 32) |
|
||||||
((UINT64)fileContentsRequest->nPositionLow);
|
((UINT64)fileContentsRequest->nPositionLow);
|
||||||
if (_fseeki64(fp, offset, SEEK_SET) < 0)
|
|
||||||
|
CliprdrLocalFile* rfile =
|
||||||
|
file_for_request(file, fileContentsRequest->clipDataId, fileContentsRequest->listIndex);
|
||||||
|
if (!rfile)
|
||||||
|
goto fail;
|
||||||
|
|
||||||
|
if (_fseeki64(rfile->fp, offset, SEEK_SET) < 0)
|
||||||
goto fail;
|
goto fail;
|
||||||
|
|
||||||
data = malloc(fileContentsRequest->cbRequested);
|
data = malloc(fileContentsRequest->cbRequested);
|
||||||
if (!data)
|
if (!data)
|
||||||
goto fail;
|
goto fail;
|
||||||
|
|
||||||
const size_t r = fread(data, 1, fileContentsRequest->cbRequested, fp);
|
const size_t r = fread(data, 1, fileContentsRequest->cbRequested, rfile->fp);
|
||||||
const UINT rc = cliprdr_file_context_send_contents(file->context, fileContentsRequest, data, r);
|
const UINT rc = cliprdr_file_context_send_contents(file->context, fileContentsRequest, data, r);
|
||||||
free(data);
|
free(data);
|
||||||
|
|
||||||
|
cliprdr_local_file_try_close(rfile, rc, offset, fileContentsRequest->cbRequested);
|
||||||
|
HashTable_Unlock(file->local_streams);
|
||||||
return rc;
|
return rc;
|
||||||
fail:
|
fail:
|
||||||
|
cliprdr_local_file_try_close(rfile, ERROR_INTERNAL_ERROR, offset,
|
||||||
|
fileContentsRequest->cbRequested);
|
||||||
free(data);
|
free(data);
|
||||||
|
HashTable_Unlock(file->local_streams);
|
||||||
return cliprdr_file_context_send_file_contents_failure(file->context, fileContentsRequest);
|
return cliprdr_file_context_send_file_contents_failure(file->context, fileContentsRequest);
|
||||||
}
|
}
|
||||||
|
|
||||||
static UINT change_lock(CliprdrFileContext* file, UINT32 streamID, BOOL lock)
|
static BOOL update_sub_path(CliprdrFileContext* file, UINT32 lockID)
|
||||||
|
{
|
||||||
|
WINPR_ASSERT(file);
|
||||||
|
WINPR_ASSERT(file->path);
|
||||||
|
|
||||||
|
char lockstr[32] = { 0 };
|
||||||
|
_snprintf(lockstr, sizeof(lockstr), "%08" PRIx32, lockID);
|
||||||
|
|
||||||
|
free(file->current_path);
|
||||||
|
file->current_path = GetCombinedPath(file->path, lockstr);
|
||||||
|
return file->current_path != NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static UINT change_lock(CliprdrFileContext* file, UINT32 lockId, BOOL lock)
|
||||||
{
|
{
|
||||||
WINPR_ASSERT(file);
|
WINPR_ASSERT(file);
|
||||||
|
|
||||||
HashTable_Lock(file->local_streams);
|
HashTable_Lock(file->local_streams);
|
||||||
CliprdrLocalStream* stream = HashTable_GetItemValue(file->local_streams, &streamID);
|
CliprdrLocalStream* stream = HashTable_GetItemValue(file->local_streams, &lockId);
|
||||||
if (lock && !stream)
|
if (lock && !stream)
|
||||||
{
|
{
|
||||||
stream = cliprdr_local_stream_new(streamID, NULL, 0);
|
stream = cliprdr_local_stream_new(lockId, NULL, 0);
|
||||||
HashTable_Insert(file->local_streams, &streamID, stream);
|
HashTable_Insert(file->local_streams, &lockId, stream);
|
||||||
file->local_stream_id = streamID;
|
file->local_lock_id = lockId;
|
||||||
}
|
}
|
||||||
if (stream)
|
if (stream)
|
||||||
|
{
|
||||||
stream->locked = lock;
|
stream->locked = lock;
|
||||||
|
stream->lockId = lockId;
|
||||||
|
update_sub_path(file, lockId);
|
||||||
|
}
|
||||||
|
|
||||||
if (!lock)
|
if (!lock)
|
||||||
HashTable_Foreach(file->local_streams, local_stream_discard, file);
|
HashTable_Foreach(file->local_streams, local_stream_discard, file);
|
||||||
@ -1432,7 +1488,7 @@ void* cliprdr_file_context_get_context(CliprdrFileContext* file)
|
|||||||
return file->clipboard;
|
return file->clipboard;
|
||||||
}
|
}
|
||||||
|
|
||||||
const char* cliprdr_file_context_base_path(CliprdrFileContext* file)
|
static const char* cliprdr_file_context_base_path(CliprdrFileContext* file)
|
||||||
{
|
{
|
||||||
WINPR_ASSERT(file);
|
WINPR_ASSERT(file);
|
||||||
return file->path;
|
return file->path;
|
||||||
@ -1474,6 +1530,7 @@ void cliprdr_file_context_free(CliprdrFileContext* file)
|
|||||||
HashTable_Free(file->local_streams);
|
HashTable_Free(file->local_streams);
|
||||||
winpr_RemoveDirectory(file->path);
|
winpr_RemoveDirectory(file->path);
|
||||||
free(file->path);
|
free(file->path);
|
||||||
|
free(file->current_path);
|
||||||
free(file);
|
free(file);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1482,12 +1539,15 @@ static BOOL create_base_path(CliprdrFileContext* file)
|
|||||||
WINPR_ASSERT(file);
|
WINPR_ASSERT(file);
|
||||||
|
|
||||||
char base[64] = { 0 };
|
char base[64] = { 0 };
|
||||||
_snprintf(base, sizeof(base), "/.xfreerdp.cliprdr.%" PRIu32, GetCurrentProcessId());
|
_snprintf(base, sizeof(base), "com.freerdp.client.cliprdr.%" PRIu32, GetCurrentProcessId());
|
||||||
|
|
||||||
file->path = GetKnownSubPath(KNOWN_PATH_TEMP, base);
|
file->path = GetKnownSubPath(KNOWN_PATH_TEMP, base);
|
||||||
if (!file->path)
|
if (!file->path)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
|
if (!update_sub_path(file, 0))
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
if (!winpr_PathFileExists(file->path) && !winpr_PathMakePath(file->path, 0))
|
if (!winpr_PathFileExists(file->path) && !winpr_PathMakePath(file->path, 0))
|
||||||
{
|
{
|
||||||
WLog_Print(file->log, WLOG_ERROR, "Failed to create directory '%s'", file->path);
|
WLog_Print(file->log, WLOG_ERROR, "Failed to create directory '%s'", file->path);
|
||||||
@ -1498,32 +1558,150 @@ static BOOL create_base_path(CliprdrFileContext* file)
|
|||||||
|
|
||||||
static void cliprdr_local_file_free(CliprdrLocalFile* file)
|
static void cliprdr_local_file_free(CliprdrLocalFile* file)
|
||||||
{
|
{
|
||||||
|
const CliprdrLocalFile empty = { 0 };
|
||||||
if (!file)
|
if (!file)
|
||||||
return;
|
return;
|
||||||
if (file->fp)
|
if (file->fp)
|
||||||
fclose(file->fp);
|
fclose(file->fp);
|
||||||
free(file->name);
|
free(file->name);
|
||||||
|
*file = empty;
|
||||||
|
}
|
||||||
|
|
||||||
|
static BOOL cliprdr_local_file_new(CliprdrLocalFile* f, const char* path)
|
||||||
|
{
|
||||||
|
const CliprdrLocalFile empty = { 0 };
|
||||||
|
WINPR_ASSERT(f);
|
||||||
|
WINPR_ASSERT(path);
|
||||||
|
|
||||||
|
*f = empty;
|
||||||
|
f->name = _strdup(path);
|
||||||
|
if (!f->name)
|
||||||
|
goto fail;
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
fail:
|
||||||
|
cliprdr_local_file_free(f);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void cliprdr_local_files_free(CliprdrLocalStream* stream)
|
||||||
|
{
|
||||||
|
WINPR_ASSERT(stream);
|
||||||
|
|
||||||
|
for (size_t x = 0; x < stream->count; x++)
|
||||||
|
cliprdr_local_file_free(&stream->files[x]);
|
||||||
|
free(stream->files);
|
||||||
|
|
||||||
|
stream->files = NULL;
|
||||||
|
stream->count = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void cliprdr_local_stream_free(void* obj)
|
static void cliprdr_local_stream_free(void* obj)
|
||||||
{
|
{
|
||||||
CliprdrLocalStream* stream = (CliprdrLocalStream*)obj;
|
CliprdrLocalStream* stream = (CliprdrLocalStream*)obj;
|
||||||
if (stream)
|
if (stream)
|
||||||
{
|
cliprdr_local_files_free(stream);
|
||||||
for (size_t x = 0; x < stream->count; x++)
|
|
||||||
cliprdr_local_file_free(&stream->files[x]);
|
|
||||||
free(stream->files);
|
|
||||||
}
|
|
||||||
free(stream);
|
free(stream);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static BOOL append_entry(CliprdrLocalStream* stream, const char* path)
|
||||||
|
{
|
||||||
|
CliprdrLocalFile* tmp = realloc(stream->files, sizeof(CliprdrLocalFile) * (stream->count + 1));
|
||||||
|
if (!tmp)
|
||||||
|
return FALSE;
|
||||||
|
stream->files = tmp;
|
||||||
|
CliprdrLocalFile* f = &stream->files[stream->count++];
|
||||||
|
|
||||||
|
return cliprdr_local_file_new(f, path);
|
||||||
|
}
|
||||||
|
|
||||||
|
static BOOL is_directory(const char* path)
|
||||||
|
{
|
||||||
|
WCHAR* wpath = ConvertUtf8ToWCharAlloc(path, NULL);
|
||||||
|
if (!wpath)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
HANDLE hFile =
|
||||||
|
CreateFileW(wpath, 0, FILE_SHARE_DELETE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
|
||||||
|
free(wpath);
|
||||||
|
|
||||||
|
if (hFile == INVALID_HANDLE_VALUE)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
BY_HANDLE_FILE_INFORMATION fileInformation = { 0 };
|
||||||
|
const BOOL status = GetFileInformationByHandle(hFile, &fileInformation);
|
||||||
|
CloseHandle(hFile);
|
||||||
|
if (!status)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
return fileInformation.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY;
|
||||||
|
}
|
||||||
|
|
||||||
|
static BOOL add_directory(CliprdrLocalStream* stream, const char* path)
|
||||||
|
{
|
||||||
|
char* wildcardpath = GetCombinedPath(path, "*");
|
||||||
|
if (!wildcardpath)
|
||||||
|
return FALSE;
|
||||||
|
WCHAR* wpath = ConvertUtf8ToWCharAlloc(wildcardpath, NULL);
|
||||||
|
free(wildcardpath);
|
||||||
|
if (!wpath)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
WIN32_FIND_DATAW FindFileData = { 0 };
|
||||||
|
HANDLE hFind = FindFirstFileW(wpath, &FindFileData);
|
||||||
|
free(wpath);
|
||||||
|
|
||||||
|
if (hFind == INVALID_HANDLE_VALUE)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
BOOL rc = FALSE;
|
||||||
|
char* next = NULL;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
const WCHAR dot[] = { '.', '\0' };
|
||||||
|
const WCHAR dotdot[] = { '.', '.', '\0' };
|
||||||
|
|
||||||
|
if (_wcscmp(FindFileData.cFileName, dot) == 0)
|
||||||
|
continue;
|
||||||
|
if (_wcscmp(FindFileData.cFileName, dotdot) == 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
char cFileName[MAX_PATH] = { 0 };
|
||||||
|
ConvertWCharNToUtf8(FindFileData.cFileName, ARRAYSIZE(FindFileData.cFileName), cFileName,
|
||||||
|
ARRAYSIZE(cFileName));
|
||||||
|
|
||||||
|
free(next);
|
||||||
|
next = GetCombinedPath(path, cFileName);
|
||||||
|
if (!next)
|
||||||
|
goto fail;
|
||||||
|
|
||||||
|
if (!append_entry(stream, next))
|
||||||
|
goto fail;
|
||||||
|
if (is_directory(next))
|
||||||
|
{
|
||||||
|
if (!add_directory(stream, next))
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
} while (FindNextFileW(hFind, &FindFileData));
|
||||||
|
|
||||||
|
rc = TRUE;
|
||||||
|
fail:
|
||||||
|
free(next);
|
||||||
|
FindClose(hFind);
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
static BOOL cliprdr_local_stream_update(CliprdrLocalStream* stream, const char* data, size_t size)
|
static BOOL cliprdr_local_stream_update(CliprdrLocalStream* stream, const char* data, size_t size)
|
||||||
{
|
{
|
||||||
|
BOOL rc = FALSE;
|
||||||
WINPR_ASSERT(stream);
|
WINPR_ASSERT(stream);
|
||||||
if (size == 0)
|
if (size == 0)
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
|
||||||
free(stream->files);
|
cliprdr_local_files_free(stream);
|
||||||
|
|
||||||
stream->files = calloc(size, sizeof(CliprdrLocalFile));
|
stream->files = calloc(size, sizeof(CliprdrLocalFile));
|
||||||
if (!stream->files)
|
if (!stream->files)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
@ -1534,14 +1712,31 @@ static BOOL cliprdr_local_stream_update(CliprdrLocalStream* stream, const char*
|
|||||||
char* ptr = strtok(copy, "\r\n");
|
char* ptr = strtok(copy, "\r\n");
|
||||||
while (ptr)
|
while (ptr)
|
||||||
{
|
{
|
||||||
stream->files[stream->count++].name = _strdup(ptr);
|
const char* name = ptr;
|
||||||
|
if (strncmp("file:///", ptr, 8) == 0)
|
||||||
|
name = &ptr[7];
|
||||||
|
else if (strncmp("file:/", ptr, 6) == 0)
|
||||||
|
name = &ptr[5];
|
||||||
|
|
||||||
|
if (!append_entry(stream, name))
|
||||||
|
goto fail;
|
||||||
|
|
||||||
|
if (is_directory(name))
|
||||||
|
{
|
||||||
|
const BOOL res = add_directory(stream, name);
|
||||||
|
if (!res)
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
ptr = strtok(NULL, "\r\n");
|
ptr = strtok(NULL, "\r\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
rc = TRUE;
|
||||||
|
fail:
|
||||||
free(copy);
|
free(copy);
|
||||||
return TRUE;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
CliprdrLocalStream* cliprdr_local_stream_new(UINT32 streamID, const char* data, size_t size)
|
CliprdrLocalStream* cliprdr_local_stream_new(UINT32 lockId, const char* data, size_t size)
|
||||||
{
|
{
|
||||||
CliprdrLocalStream* stream = calloc(1, sizeof(CliprdrLocalStream));
|
CliprdrLocalStream* stream = calloc(1, sizeof(CliprdrLocalStream));
|
||||||
if (!stream)
|
if (!stream)
|
||||||
@ -1550,7 +1745,7 @@ CliprdrLocalStream* cliprdr_local_stream_new(UINT32 streamID, const char* data,
|
|||||||
if (!cliprdr_local_stream_update(stream, data, size))
|
if (!cliprdr_local_stream_update(stream, data, size))
|
||||||
goto fail;
|
goto fail;
|
||||||
|
|
||||||
stream->streamID = streamID;
|
stream->lockId = lockId;
|
||||||
return stream;
|
return stream;
|
||||||
|
|
||||||
fail:
|
fail:
|
||||||
@ -1587,6 +1782,7 @@ static void* UINTPointerClone(const void* other)
|
|||||||
*copy = *src;
|
*copy = *src;
|
||||||
return copy;
|
return copy;
|
||||||
}
|
}
|
||||||
|
|
||||||
CliprdrFileContext* cliprdr_file_context_new(void* context)
|
CliprdrFileContext* cliprdr_file_context_new(void* context)
|
||||||
{
|
{
|
||||||
CliprdrFileContext* file = calloc(1, sizeof(CliprdrFileContext));
|
CliprdrFileContext* file = calloc(1, sizeof(CliprdrFileContext));
|
||||||
@ -1680,6 +1876,7 @@ BOOL local_stream_discard(const void* key, void* value, void* arg)
|
|||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if defined(WITH_FUSE2) || defined(WITH_FUSE3)
|
||||||
static BOOL remote_stream_discard(const void* key, void* value, void* arg)
|
static BOOL remote_stream_discard(const void* key, void* value, void* arg)
|
||||||
{
|
{
|
||||||
CliprdrFuseStream* stream = (CliprdrFuseStream*)value;
|
CliprdrFuseStream* stream = (CliprdrFuseStream*)value;
|
||||||
@ -1691,6 +1888,7 @@ static BOOL remote_stream_discard(const void* key, void* value, void* arg)
|
|||||||
fuse_reply_err(stream->req, EIO);
|
fuse_reply_err(stream->req, EIO);
|
||||||
return HashTable_Remove(file->remote_streams, key);
|
return HashTable_Remove(file->remote_streams, key);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
BOOL cliprdr_file_context_clear(CliprdrFileContext* file)
|
BOOL cliprdr_file_context_clear(CliprdrFileContext* file)
|
||||||
{
|
{
|
||||||
@ -1706,17 +1904,17 @@ BOOL cliprdr_file_context_update_client_data(CliprdrFileContext* file, const cha
|
|||||||
size_t size)
|
size_t size)
|
||||||
{
|
{
|
||||||
BOOL rc = FALSE;
|
BOOL rc = FALSE;
|
||||||
UINT32 streamID = file->local_stream_id++;
|
UINT32 lockId = file->local_lock_id;
|
||||||
|
|
||||||
HashTable_Lock(file->local_streams);
|
HashTable_Lock(file->local_streams);
|
||||||
CliprdrLocalStream* stream = HashTable_GetItemValue(file->local_streams, &streamID);
|
CliprdrLocalStream* stream = HashTable_GetItemValue(file->local_streams, &lockId);
|
||||||
|
|
||||||
if (stream)
|
if (stream)
|
||||||
rc = cliprdr_local_stream_update(stream, data, size);
|
rc = cliprdr_local_stream_update(stream, data, size);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
stream = cliprdr_local_stream_new(streamID, data, size);
|
stream = cliprdr_local_stream_new(lockId, data, size);
|
||||||
rc = HashTable_Insert(file->local_streams, &streamID, stream);
|
rc = HashTable_Insert(file->local_streams, &stream->lockId, stream);
|
||||||
}
|
}
|
||||||
HashTable_Unlock(file->local_streams);
|
HashTable_Unlock(file->local_streams);
|
||||||
return rc;
|
return rc;
|
||||||
@ -1755,3 +1953,12 @@ UINT32 cliprdr_file_context_remote_get_flags(CliprdrFileContext* file)
|
|||||||
WINPR_ASSERT(file);
|
WINPR_ASSERT(file);
|
||||||
return file->file_capability_flags;
|
return file->file_capability_flags;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BOOL cliprdr_file_context_update_base(CliprdrFileContext* file, wClipboard* clip)
|
||||||
|
{
|
||||||
|
wClipboardDelegate* delegate = ClipboardGetDelegate(clip);
|
||||||
|
if (!delegate)
|
||||||
|
return FALSE;
|
||||||
|
delegate->basePath = file->current_path;
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
@ -41,7 +41,8 @@ extern "C"
|
|||||||
FREERDP_API UINT32 cliprdr_file_context_current_flags(CliprdrFileContext* file);
|
FREERDP_API UINT32 cliprdr_file_context_current_flags(CliprdrFileContext* file);
|
||||||
|
|
||||||
FREERDP_API void* cliprdr_file_context_get_context(CliprdrFileContext* file);
|
FREERDP_API void* cliprdr_file_context_get_context(CliprdrFileContext* file);
|
||||||
FREERDP_API const char* cliprdr_file_context_base_path(CliprdrFileContext* file);
|
|
||||||
|
FREERDP_API BOOL cliprdr_file_context_update_base(CliprdrFileContext* file, wClipboard* clip);
|
||||||
|
|
||||||
FREERDP_API BOOL cliprdr_file_context_init(CliprdrFileContext* file,
|
FREERDP_API BOOL cliprdr_file_context_init(CliprdrFileContext* file,
|
||||||
CliprdrClientContext* cliprdr);
|
CliprdrClientContext* cliprdr);
|
||||||
|
Loading…
Reference in New Issue
Block a user