mirror of
https://github.com/libretro/RetroArch
synced 2025-03-29 22:20:21 +00:00
Merge pull request #2497 from heuripedes/master
Avoid file corruption when downloading or decompressing files
This commit is contained in:
commit
edf09365b0
@ -36,6 +36,8 @@ bool net_http_connection_done(struct http_connection_t *conn);
|
||||
|
||||
void net_http_connection_free(struct http_connection_t *conn);
|
||||
|
||||
const char *net_http_connection_url(struct http_connection_t *conn);
|
||||
|
||||
struct http_t *net_http_new(struct http_connection_t *conn);
|
||||
|
||||
/* You can use this to call net_http_update
|
||||
|
@ -260,6 +260,11 @@ void net_http_connection_free(struct http_connection_t *conn)
|
||||
free(conn);
|
||||
}
|
||||
|
||||
const char *net_http_connection_url(struct http_connection_t *conn)
|
||||
{
|
||||
return conn->urlcopy;
|
||||
}
|
||||
|
||||
struct http_t *net_http_new(struct http_connection_t *conn)
|
||||
{
|
||||
bool error;
|
||||
|
@ -113,6 +113,16 @@ task_finished:
|
||||
free(dec);
|
||||
}
|
||||
|
||||
static bool rarch_task_decompress_finder(rarch_task_t *task, void *user_data)
|
||||
{
|
||||
decompress_state_t *dec = (decompress_state_t*)task->state;
|
||||
|
||||
if (task->handler != rarch_task_decompress_handler)
|
||||
return false;
|
||||
|
||||
return strcmp(dec->source_file, (const char*)user_data) == 0;
|
||||
}
|
||||
|
||||
bool rarch_task_push_decompress(const char *source_file, const char *target_dir,
|
||||
const char *valid_ext, rarch_task_callback_t cb, void *user_data)
|
||||
{
|
||||
@ -137,6 +147,12 @@ bool rarch_task_push_decompress(const char *source_file, const char *target_dir,
|
||||
if (!valid_ext || !valid_ext[0])
|
||||
valid_ext = NULL;
|
||||
|
||||
if (rarch_task_find(rarch_task_decompress_finder, (void*)source_file))
|
||||
{
|
||||
RARCH_LOG("[decompress] File '%s' already being decompressed.\n", source_file);
|
||||
return false;
|
||||
}
|
||||
|
||||
s = (decompress_state_t*)calloc(1, sizeof(*s));
|
||||
|
||||
s->source_file = strdup(source_file);
|
||||
|
@ -92,7 +92,7 @@ static int cb_http_conn_default(void *data_, size_t len)
|
||||
|
||||
if (!http->handle)
|
||||
{
|
||||
RARCH_ERR("Could not create new HTTP session handle.\n");
|
||||
RARCH_ERR("[http] Could not create new HTTP session handle.\n");
|
||||
http->error = true;
|
||||
return -1;
|
||||
}
|
||||
@ -193,6 +193,18 @@ task_finished:
|
||||
free(http);
|
||||
}
|
||||
|
||||
static bool rarch_task_http_finder(rarch_task_t *task, void *user_data)
|
||||
{
|
||||
http_handle_t *http = (http_handle_t*)task->state;
|
||||
const char *handle_url;
|
||||
if (task->handler != rarch_task_http_transfer_handler)
|
||||
return false;
|
||||
|
||||
handle_url = net_http_connection_url(http->connection.handle);
|
||||
|
||||
return strcmp(handle_url, (const char*)user_data) == 0;
|
||||
}
|
||||
|
||||
bool rarch_task_push_http_transfer(const char *url, const char *type, rarch_task_callback_t cb, void *user_data)
|
||||
{
|
||||
rarch_task_t *t;
|
||||
@ -203,6 +215,13 @@ bool rarch_task_push_http_transfer(const char *url, const char *type, rarch_task
|
||||
if (!url || !*url)
|
||||
return false;
|
||||
|
||||
/* Concurrent download of the same file is not allowed */
|
||||
if (rarch_task_find(rarch_task_http_finder, (void*)url))
|
||||
{
|
||||
RARCH_LOG("[http] '%s'' is already being downloaded.\n", url);
|
||||
return false;
|
||||
}
|
||||
|
||||
conn = net_http_connection_new(url);
|
||||
|
||||
if (!conn)
|
||||
|
@ -17,9 +17,10 @@ typedef struct {
|
||||
|
||||
struct rarch_task_impl {
|
||||
void (*push_running)(rarch_task_t *);
|
||||
void (*cancel)(void);
|
||||
void (*reset)(void);
|
||||
void (*wait)(void);
|
||||
void (*gather)(void);
|
||||
bool (*find)(rarch_task_finder_t, void*);
|
||||
void (*init)(void);
|
||||
void (*deinit)(void);
|
||||
};
|
||||
@ -132,7 +133,7 @@ static void regular_wait(void)
|
||||
regular_gather();
|
||||
}
|
||||
|
||||
static void regular_cancel()
|
||||
static void regular_reset()
|
||||
{
|
||||
rarch_task_t *task;
|
||||
|
||||
@ -148,11 +149,25 @@ static void regular_deinit(void)
|
||||
{
|
||||
}
|
||||
|
||||
static bool regular_find(rarch_task_finder_t func, void *user_data)
|
||||
{
|
||||
rarch_task_t *task;
|
||||
|
||||
for (task = tasks_running.front; task; task = task->next)
|
||||
{
|
||||
if (func(task, user_data))
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static struct rarch_task_impl impl_regular = {
|
||||
regular_push_running,
|
||||
regular_cancel,
|
||||
regular_reset,
|
||||
regular_wait,
|
||||
regular_gather,
|
||||
regular_find,
|
||||
regular_init,
|
||||
regular_deinit
|
||||
};
|
||||
@ -199,7 +214,7 @@ static void threaded_wait(void)
|
||||
} while (wait);
|
||||
}
|
||||
|
||||
static void threaded_cancel(void)
|
||||
static void threaded_reset(void)
|
||||
{
|
||||
rarch_task_t *task;
|
||||
|
||||
@ -262,6 +277,21 @@ static void threaded_worker(void *userdata)
|
||||
slock_unlock(running_lock);
|
||||
}
|
||||
|
||||
static bool threaded_find(rarch_task_finder_t func, void *user_data)
|
||||
{
|
||||
rarch_task_t *task;
|
||||
|
||||
slock_lock(running_lock);
|
||||
for (task = tasks_running.front; task; task = task->next)
|
||||
{
|
||||
if (func(task, user_data))
|
||||
return true;
|
||||
}
|
||||
slock_unlock(running_lock);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static void threaded_init(void)
|
||||
{
|
||||
running_lock = slock_new();
|
||||
@ -296,9 +326,10 @@ static void threaded_deinit(void)
|
||||
|
||||
static struct rarch_task_impl impl_threaded = {
|
||||
threaded_push_running,
|
||||
threaded_cancel,
|
||||
threaded_reset,
|
||||
threaded_wait,
|
||||
threaded_gather,
|
||||
threaded_find,
|
||||
threaded_init,
|
||||
threaded_deinit
|
||||
};
|
||||
@ -358,5 +389,10 @@ void rarch_task_wait(void)
|
||||
|
||||
void rarch_task_reset(void)
|
||||
{
|
||||
impl_current->cancel();
|
||||
impl_current->reset();
|
||||
}
|
||||
|
||||
bool rarch_task_find(rarch_task_finder_t func, void *user_data)
|
||||
{
|
||||
return impl_current->find(func, user_data);
|
||||
}
|
||||
|
@ -32,6 +32,7 @@ extern "C" {
|
||||
typedef struct rarch_task rarch_task_t;
|
||||
typedef void (*rarch_task_callback_t)(void *task_data, void *user_data, const char *error);
|
||||
typedef void (*rarch_task_handler_t)(rarch_task_t *task);
|
||||
typedef bool (*rarch_task_finder_t)(rarch_task_t *task, void *user_data);
|
||||
|
||||
struct rarch_task {
|
||||
rarch_task_handler_t handler;
|
||||
@ -107,6 +108,15 @@ void rarch_task_reset(void);
|
||||
*/
|
||||
void rarch_task_wait(void);
|
||||
|
||||
/**
|
||||
* @brief Calls func for every running task until it returns true.
|
||||
*
|
||||
* @param func
|
||||
* @param user_data
|
||||
* @return a task or NULL if not found.
|
||||
*/
|
||||
bool rarch_task_find(rarch_task_finder_t func, void *user_data);
|
||||
|
||||
/**
|
||||
* @brief Pushes a task
|
||||
*
|
||||
|
Loading…
x
Reference in New Issue
Block a user