{
struct posix_file* file = NULL;
struct stat statbuf;
-
file = calloc(1, sizeof(*file));
+
if (!file)
return NULL;
file->fd = -1;
file->offset = 0;
-
file->local_name = _strdup(local_name);
file->remote_name = _wcsdup(remote_name);
file->is_directory = S_ISDIR(statbuf.st_mode);
file->size = statbuf.st_size;
-
return file;
-
error:
free(file->local_name);
free(file->remote_name);
free(file);
-
return NULL;
}
*value |= hex_to_dec(str[1], &valid);
*value <<= 4;
*value |= hex_to_dec(str[2], &valid);
-
return valid;
}
char* next = NULL;
const char* cur = str;
const char* lim = str + len;
-
/* Percent decoding shrinks data length, so len bytes will be enough. */
buffer = calloc(len + 1, sizeof(char));
+
if (!buffer)
return NULL;
}
return buffer;
-
error:
free(buffer);
-
return NULL;
}
}
return remote_name;
-
error:
free(remote_name);
return NULL;
size_t len_dir = 0;
size_t len_file = 0;
char* buffer = NULL;
-
len_dir = strlen(dir);
len_file = strlen(file);
-
buffer = calloc(len_dir + 1 + len_file + 1, sizeof(char));
+
if (!buffer)
return NULL;
memcpy(buffer, dir, len_dir * sizeof(char));
buffer[len_dir] = '/';
memcpy(buffer + len_dir + 1, file, len_file * sizeof(char));
-
return buffer;
}
size_t len_dir = 0;
size_t len_file = 0;
WCHAR* buffer = NULL;
-
len_dir = _wcslen(dir);
len_file = _wcslen(file);
-
buffer = calloc(len_dir + 1 + len_file + 1, sizeof(WCHAR));
+
if (!buffer)
return NULL;
memcpy(buffer, dir, len_dir * sizeof(WCHAR));
buffer[len_dir] = L'\\';
memcpy(buffer + len_dir + 1, file, len_file * sizeof(WCHAR));
-
return buffer;
}
static BOOL add_file_to_list(const char* local_name, const WCHAR* remote_name, wArrayList* files);
static BOOL add_directory_entry_to_list(const char* local_dir_name, const WCHAR* remote_dir_name,
- const struct dirent* entry, wArrayList* files)
+ const struct dirent* entry, wArrayList* files)
{
BOOL result = FALSE;
char* local_name = NULL;
return TRUE;
remote_base_name = convert_local_name_component_to_remote(entry->d_name);
+
if (!remote_base_name)
return FALSE;
free(remote_base_name);
free(remote_name);
free(local_name);
-
return result;
}
static BOOL do_add_directory_contents_to_list(const char* local_name, const WCHAR* remote_name,
- DIR* dirp, wArrayList* files)
+ DIR* dirp, wArrayList* files)
{
/*
* For some reason POSIX does not require readdir() to be thread-safe.
* musl). We should not be breaking people's builds because of that,
* so we do nothing and proceed with fingers crossed.
*/
-
for (;;)
{
struct dirent* entry = NULL;
-
errno = 0;
entry = readdir(dirp);
+
if (!entry)
{
int err = errno;
+
if (!err)
break;
}
static BOOL add_directory_contents_to_list(const char* local_name, const WCHAR* remote_name,
- wArrayList* files)
+ wArrayList* files)
{
BOOL result = FALSE;
DIR* dirp = NULL;
-
WLog_VRB(TAG, "adding directory: %s", local_name);
-
dirp = opendir(local_name);
+
if (!dirp)
{
int err = errno;
int err = errno;
WLog_WARN(TAG, "failed to close directory: %s", strerror(err));
}
+
out:
return result;
}
static BOOL add_file_to_list(const char* local_name, const WCHAR* remote_name, wArrayList* files)
{
struct posix_file* file = NULL;
-
WLog_VRB(TAG, "adding file: %s", local_name);
-
file = make_posix_file(local_name, remote_name);
+
if (!file)
return FALSE;
if (ArrayList_Add(files, file) < 0)
{
free_posix_file(file);
-
return FALSE;
}
BOOL result = FALSE;
const char* base_name = NULL;
WCHAR* remote_name = NULL;
-
/*
* Start with the base name of the file. text/uri-list contains the
* exact files selected by the user, and we want the remote files
* to have names relative to that selection.
*/
base_name = get_basename(local_name);
-
remote_name = convert_local_name_component_to_remote(base_name);
+
if (!remote_name)
return FALSE;
result = add_file_to_list(local_name, remote_name, files);
-
free(remote_name);
-
return result;
}
{
BOOL result = FALSE;
char* name = NULL;
-
WLog_VRB(TAG, "processing URI: %.*s", uri_len, uri);
if ((uri_len < strlen("file://")) || strncmp(uri, "file://", strlen("file://")))
}
name = decode_percent_encoded_string(uri + strlen("file://"), uri_len - strlen("file://"));
+
if (!name)
goto out;
result = process_file_name(name, files);
out:
free(name);
-
return result;
}
const char* lim = data + length;
const char* start = NULL;
const char* stop = NULL;
-
WLog_VRB(TAG, "processing URI list:\n%.*s", length, data);
-
ArrayList_Clear(files);
/*
while (cur < lim)
{
BOOL comment = (*cur == '#');
-
start = cur;
- stop = cur;
for (stop = cur; stop < lim; stop++)
{
cur = stop + 2;
else
cur = stop + 1;
+
break;
}
+
if (*stop == '\n')
{
cur = stop + 1;
break;
}
}
+
if (stop == lim)
cur = lim;
}
static BOOL convert_local_file_to_filedescriptor(const struct posix_file* file,
- FILEDESCRIPTOR* descriptor)
+ FILEDESCRIPTOR* descriptor)
{
size_t remote_len = 0;
-
descriptor->dwFlags = FD_ATTRIBUTES | FD_FILESIZE | FD_SHOWPROGRESSUI;
if (file->is_directory)
}
remote_len = _wcslen(file->remote_name);
+
if (remote_len + 1 > ARRAYSIZE(descriptor->cFileName))
{
WLog_ERR(TAG, "file name too long (%"PRIuz" characters)", remote_len);
}
memcpy(descriptor->cFileName, file->remote_name, remote_len * sizeof(WCHAR));
-
return TRUE;
}
int i;
int count = 0;
FILEDESCRIPTOR* descriptors = NULL;
-
count = ArrayList_Count(files);
-
descriptors = calloc(count, sizeof(descriptors[0]));
+
if (!descriptors)
goto error;
}
return descriptors;
-
error:
free(descriptors);
-
return NULL;
}
static void* convert_uri_list_to_filedescriptors(wClipboard* clipboard, UINT32 formatId,
- const void* data, UINT32* pSize)
+ const void* data, UINT32* pSize)
{
FILEDESCRIPTOR* descriptors = NULL;
return NULL;
descriptors = convert_local_file_list_to_filedescriptors(clipboard->localFiles);
+
if (!descriptors)
return NULL;
*pSize = ArrayList_Count(clipboard->localFiles) * sizeof(FILEDESCRIPTOR);
-
clipboard->fileListSequenceNumber = clipboard->sequenceNumber;
-
return descriptors;
}
{
UINT32 file_group_format_id;
UINT32 local_file_format_id;
-
file_group_format_id = ClipboardRegisterFormat(clipboard, "FileGroupDescriptorW");
local_file_format_id = ClipboardRegisterFormat(clipboard, "text/uri-list");
+
if (!file_group_format_id || !local_file_format_id)
goto error;
clipboard->localFiles = ArrayList_New(FALSE);
+
if (!clipboard->localFiles)
goto error;
ArrayList_Object(clipboard->localFiles)->fnObjectFree = free_posix_file;
if (!ClipboardRegisterSynthesizer(clipboard,
- local_file_format_id, file_group_format_id,
- convert_uri_list_to_filedescriptors))
+ local_file_format_id, file_group_format_id,
+ convert_uri_list_to_filedescriptors))
goto error_free_local_files;
return TRUE;
-
error_free_local_files:
ArrayList_Free(clipboard->localFiles);
clipboard->localFiles = NULL;
}
*size = statbuf.st_size;
-
return NO_ERROR;
}
static UINT posix_file_request_size(wClipboardDelegate* delegate,
- const wClipboardFileSizeRequest* request)
+ const wClipboardFileSizeRequest* request)
{
UINT error = NO_ERROR;
INT64 size = 0;
return ERROR_INVALID_STATE;
file = ArrayList_GetItem(delegate->clipboard->localFiles, request->listIndex);
+
if (!file)
return ERROR_INDEX_ABSENT;
return NO_ERROR;
file->fd = open(file->local_name, O_RDONLY);
+
if (file->fd < 0)
{
int err = errno;
file->offset = 0;
file->size = statbuf.st_size;
-
WLog_VRB(TAG, "open file %d -> %s", file->fd, file->local_name);
WLog_VRB(TAG, "file %d size: %"PRIu64" bytes", file->fd, file->size);
-
return NO_ERROR;
}
return NO_ERROR;
WLog_VRB(TAG, "file %d force seeking to %"PRIu64", current %"PRIu64, file->fd,
- offset, file->offset);
+ offset, file->offset);
if (lseek(file->fd, offset, SEEK_SET) < 0)
{
}
static UINT posix_file_read_perform(struct posix_file* file, UINT32 size,
- BYTE** actual_data, UINT32* actual_size)
+ BYTE** actual_data, UINT32* actual_size)
{
BYTE* buffer = NULL;
ssize_t amount = 0;
-
WLog_VRB(TAG, "file %d request read %"PRIu32" bytes", file->fd, size);
-
buffer = malloc(size);
+
if (!buffer)
{
WLog_ERR(TAG, "failed to allocate %"PRIu32" buffer bytes", size);
}
amount = read(file->fd, buffer, size);
+
if (amount < 0)
{
int err = errno;
*actual_data = buffer;
*actual_size = amount;
file->offset += amount;
-
WLog_VRB(TAG, "file %d actual read %"PRIu32" bytes (offset %"PRIu64")", file->fd,
- amount, file->offset);
-
+ amount, file->offset);
return NO_ERROR;
-
error:
free(buffer);
-
return ERROR_READ_FAULT;
}
int err = errno;
WLog_WARN(TAG, "failed to close fd %d: %s", file->fd, strerror(err));
}
+
file->fd = -1;
}
}
static UINT posix_file_get_range(struct posix_file* file, UINT64 offset, UINT32 size,
- BYTE** actual_data, UINT32* actual_size)
+ BYTE** actual_data, UINT32* actual_size)
{
UINT error = NO_ERROR;
-
error = posix_file_read_open(file);
+
if (error)
goto out;
error = posix_file_read_seek(file, offset);
+
if (error)
goto out;
error = posix_file_read_perform(file, size, actual_data, actual_size);
+
if (error)
goto out;
error = posix_file_read_close(file);
+
if (error)
goto out;
+
out:
return error;
}
static UINT posix_file_request_range(wClipboardDelegate* delegate,
- const wClipboardFileRangeRequest* request)
+ const wClipboardFileRangeRequest* request)
{
UINT error = 0;
BYTE* data = NULL;
return ERROR_INVALID_STATE;
file = ArrayList_GetItem(delegate->clipboard->localFiles, request->listIndex);
+
if (!file)
return ERROR_INDEX_ABSENT;
WLog_WARN(TAG, "failed to report file range result: 0x%08X", error);
free(data);
-
return NO_ERROR;
}
-static UINT dummy_file_size_success(wClipboardDelegate* delegate, const wClipboardFileSizeRequest* request, UINT64 fileSize)
+static UINT dummy_file_size_success(wClipboardDelegate* delegate,
+ const wClipboardFileSizeRequest* request, UINT64 fileSize)
{
return ERROR_NOT_SUPPORTED;
}
-static UINT dummy_file_size_failure(wClipboardDelegate* delegate, const wClipboardFileSizeRequest* request, UINT errorCode)
+static UINT dummy_file_size_failure(wClipboardDelegate* delegate,
+ const wClipboardFileSizeRequest* request, UINT errorCode)
{
return ERROR_NOT_SUPPORTED;
}
-static UINT dummy_file_range_success(wClipboardDelegate* delegate, const wClipboardFileRangeRequest* request, const BYTE* data, UINT32 size)
+static UINT dummy_file_range_success(wClipboardDelegate* delegate,
+ const wClipboardFileRangeRequest* request, const BYTE* data, UINT32 size)
{
return ERROR_NOT_SUPPORTED;
}
-static UINT dummy_file_range_failure(wClipboardDelegate* delegate, const wClipboardFileRangeRequest* request, UINT errorCode)
+static UINT dummy_file_range_failure(wClipboardDelegate* delegate,
+ const wClipboardFileRangeRequest* request, UINT errorCode)
{
return ERROR_NOT_SUPPORTED;
}
delegate->ClientRequestFileSize = posix_file_request_size;
delegate->ClipboardFileSizeSuccess = dummy_file_size_success;
delegate->ClipboardFileSizeFailure = dummy_file_size_failure;
-
delegate->ClientRequestFileRange = posix_file_request_range;
delegate->ClipboardFileRangeSuccess = dummy_file_range_success;
delegate->ClipboardFileRangeFailure = dummy_file_range_failure;
return FALSE;
setup_delegate(&clipboard->delegate);
-
return TRUE;
}