cloud sync: clean up directory/filename mapping, log errors (#15561)

This commit is contained in:
Eric Warmenhoven 2023-08-07 14:43:22 -04:00 committed by GitHub
parent fa80e5e6be
commit 3ef31d2eee
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 85 additions and 36 deletions

View File

@ -439,6 +439,16 @@ static char *webdav_get_auth_header(const char *method, const char *url)
return webdav_st->digest_auth_header; return webdav_st->digest_auth_header;
} }
static void webdav_log_http_failure(const char *path, http_transfer_data_t *data)
{
int i;
RARCH_WARN("webdav failed: %s: HTTP %d\n", path, data->status);
for (i = 0; data->headers && i < data->headers->size; i++)
RARCH_WARN("%s\n", data->headers->elems[i].data);
if (data->data)
RARCH_WARN("%s\n", data->data);
}
static void webdav_stat_cb(retro_task_t *task, void *task_data, void *user_data, const char *err) static void webdav_stat_cb(retro_task_t *task, void *task_data, void *user_data, const char *err)
{ {
webdav_state_t *webdav_st = webdav_state_get_ptr(); webdav_state_t *webdav_st = webdav_state_get_ptr();
@ -465,9 +475,14 @@ static void webdav_stat_cb(retro_task_t *task, void *task_data, void *user_data,
webdav_stat_cb, webdav_cb_st); webdav_stat_cb, webdav_cb_st);
return; return;
} }
else
RARCH_WARN("failure creating WWW-Authenticate: Digest header\n");
} }
} }
if (!success && data)
webdav_log_http_failure(webdav_st->url, data);
webdav_cb_st->cb(webdav_cb_st->user_data, NULL, success, NULL); webdav_cb_st->cb(webdav_cb_st->user_data, NULL, success, NULL);
free(webdav_cb_st); free(webdav_cb_st);
} }
@ -477,6 +492,7 @@ static bool webdav_sync_begin(cloud_sync_complete_handler_t cb, void *user_data)
settings_t *settings = config_get_ptr(); settings_t *settings = config_get_ptr();
const char *url = settings->arrays.webdav_url; const char *url = settings->arrays.webdav_url;
webdav_state_t *webdav_st = webdav_state_get_ptr(); webdav_state_t *webdav_st = webdav_state_get_ptr();
size_t len = 0;
const char *auth_header; const char *auth_header;
if (string_is_empty(url)) if (string_is_empty(url))
@ -484,7 +500,9 @@ static bool webdav_sync_begin(cloud_sync_complete_handler_t cb, void *user_data)
// TODO: LOCK? // TODO: LOCK?
strlcpy(webdav_st->url, url, sizeof(webdav_st->url)); if (!strstr(url, "://"))
len += strlcpy(webdav_st->url, "http://", STRLEN_CONST("http://"));
strlcpy(webdav_st->url + len, url, sizeof(webdav_st->url) - len);
fill_pathname_slash(webdav_st->url, sizeof(webdav_st->url)); fill_pathname_slash(webdav_st->url, sizeof(webdav_st->url));
/* url/username/password may have changed, redo auth check */ /* url/username/password may have changed, redo auth check */
@ -529,8 +547,11 @@ static void webdav_read_cb(retro_task_t *task, void *task_data, void *user_data,
success = (data && success = (data &&
((data->status >= 200 && data->status < 300) || data->status == 404)); ((data->status >= 200 && data->status < 300) || data->status == 404));
if (!success && data)
webdav_log_http_failure(webdav_cb_st->path, data);
// TODO: it's possible we get a 401 here and need to redo the auth check with this request // TODO: it's possible we get a 401 here and need to redo the auth check with this request
if (data && data->data && webdav_cb_st) if (success && data->data && webdav_cb_st)
{ {
// TODO: it would be better if writing to the file happened during the network reads // TODO: it would be better if writing to the file happened during the network reads
file = filestream_open(webdav_cb_st->file, file = filestream_open(webdav_cb_st->file,
@ -582,6 +603,8 @@ static void webdav_mkdir_cb(retro_task_t *task, void *task_data, void *user_data
// TODO: it's possible we get a 401 here and need to redo the auth check with this request // TODO: it's possible we get a 401 here and need to redo the auth check with this request
if (!data || data->status < 200 || data->status >= 400) if (!data || data->status < 200 || data->status >= 400)
{ {
if (data)
webdav_log_http_failure(webdav_mkdir_st->url, data);
webdav_mkdir_st->cb(false, webdav_mkdir_st->cb_st); webdav_mkdir_st->cb(false, webdav_mkdir_st->cb_st);
free(webdav_mkdir_st); free(webdav_mkdir_st);
return; return;
@ -627,6 +650,9 @@ static void webdav_update_cb(retro_task_t *task, void *task_data, void *user_dat
http_transfer_data_t *data = (http_transfer_data_t*)task_data; http_transfer_data_t *data = (http_transfer_data_t*)task_data;
bool success = (data && data->status >= 200 && data->status < 300); bool success = (data && data->status >= 200 && data->status < 300);
if (!success && data)
webdav_log_http_failure(webdav_cb_st->path, data);
// TODO: it's possible we get a 401 here and need to redo the auth check with this request // TODO: it's possible we get a 401 here and need to redo the auth check with this request
if (webdav_cb_st) if (webdav_cb_st)
{ {
@ -697,6 +723,9 @@ static void webdav_delete_cb(retro_task_t *task, void *task_data, void *user_dat
http_transfer_data_t *data = (http_transfer_data_t*)task_data; http_transfer_data_t *data = (http_transfer_data_t*)task_data;
bool success = (data != NULL && data->status >= 200 && data->status < 300); bool success = (data != NULL && data->status >= 200 && data->status < 300);
if (!success && data)
webdav_log_http_failure(webdav_cb_st->path, data);
// TODO: it's possible we get a 401 here and need to redo the auth check with this request // TODO: it's possible we get a 401 here and need to redo the auth check with this request
if (webdav_cb_st) if (webdav_cb_st)
{ {
@ -711,6 +740,9 @@ static void webdav_backup_cb(retro_task_t *task, void *task_data, void *user_dat
http_transfer_data_t *data = (http_transfer_data_t*)task_data; http_transfer_data_t *data = (http_transfer_data_t*)task_data;
bool success = (data != NULL && data->status >= 200 && data->status < 300); bool success = (data != NULL && data->status >= 200 && data->status < 300);
if (!success && data)
webdav_log_http_failure(webdav_cb_st->path, data);
// TODO: it's possible we get a 401 here and need to redo the auth check with this request // TODO: it's possible we get a 401 here and need to redo the auth check with this request
if (webdav_cb_st) if (webdav_cb_st)
{ {

View File

@ -274,9 +274,33 @@ static void task_cloud_sync_manifest_append_dir(file_list_t *manifest,
} }
} }
static struct string_list *task_cloud_sync_directory_map(void)
{
static struct string_list *list = NULL;
if (!list)
{
union string_list_elem_attr attr = {0};
char dir[PATH_MAX_LENGTH];
list = string_list_new();
string_list_append(list, "config", attr);
fill_pathname_application_special(dir,
sizeof(dir), APPLICATION_SPECIAL_DIRECTORY_CONFIG);
list->elems[list->size - 1].userdata = strdup(dir);
string_list_append(list, "saves", attr);
list->elems[list->size - 1].userdata = strdup(dir_get_ptr(RARCH_DIR_SAVEFILE));
string_list_append(list, "states", attr);
list->elems[list->size - 1].userdata = strdup(dir_get_ptr(RARCH_DIR_SAVESTATE));
}
return list;
}
static void task_cloud_sync_build_current_manifest(task_cloud_sync_state_t *sync_state) static void task_cloud_sync_build_current_manifest(task_cloud_sync_state_t *sync_state)
{ {
char config_dir[PATH_MAX_LENGTH]; struct string_list *dirlist = task_cloud_sync_directory_map();
int i;
sync_state->current_manifest = (file_list_t *)calloc(1, sizeof(file_list_t)); sync_state->current_manifest = (file_list_t *)calloc(1, sizeof(file_list_t));
if (!sync_state->current_manifest) if (!sync_state->current_manifest)
@ -297,13 +321,9 @@ static void task_cloud_sync_build_current_manifest(task_cloud_sync_state_t *sync
return; return;
} }
fill_pathname_application_special(config_dir, for (i = 0; i < dirlist->size; i++)
sizeof(config_dir), task_cloud_sync_manifest_append_dir(sync_state->current_manifest,
APPLICATION_SPECIAL_DIRECTORY_CONFIG); dirlist->elems[i].userdata, dirlist->elems[i].data);
task_cloud_sync_manifest_append_dir(sync_state->current_manifest, config_dir, "config");
task_cloud_sync_manifest_append_dir(sync_state->current_manifest, dir_get_ptr(RARCH_DIR_SAVEFILE), "saves");
task_cloud_sync_manifest_append_dir(sync_state->current_manifest, dir_get_ptr(RARCH_DIR_SAVESTATE), "states");
file_list_sort_on_alt(sync_state->current_manifest); file_list_sort_on_alt(sync_state->current_manifest);
sync_state->phase = CLOUD_SYNC_PHASE_DIFF; sync_state->phase = CLOUD_SYNC_PHASE_DIFF;
@ -431,19 +451,11 @@ static void task_cloud_sync_fetch_cb(void *user_data, const char *path, bool suc
hash = task_cloud_sync_md5_rfile(file); hash = task_cloud_sync_md5_rfile(file);
filestream_close(file); filestream_close(file);
RARCH_LOG(CSPFX "successfully fetched %s\n", path); RARCH_LOG(CSPFX "successfully fetched %s\n", path);
task_cloud_sync_add_to_updated_manifest(sync_state, path, hash, true);
task_cloud_sync_add_to_updated_manifest(sync_state, path, hash, false); task_cloud_sync_add_to_updated_manifest(sync_state, path, hash, false);
/* no need to mark need_manifest_uploaded, nothing changed */
} }
else else
{ {
/* on failure, don't add it to local manifest, that will cause a fetch again next time */ /* on failure, don't add it to local manifest, that will cause a fetch again next time */
size_t idx;
if (file_list_search(sync_state->server_manifest, path, &idx))
{
struct item_file *server_file = &sync_state->server_manifest->list[idx];
task_cloud_sync_add_to_updated_manifest(sync_state, path, CS_FILE_HASH(server_file), true);
}
if (!success) if (!success)
RARCH_WARN(CSPFX "failed to fetch %s\n", path); RARCH_WARN(CSPFX "failed to fetch %s\n", path);
else else
@ -455,27 +467,34 @@ static void task_cloud_sync_fetch_cb(void *user_data, const char *path, bool suc
static void task_cloud_sync_fetch_server_file(task_cloud_sync_state_t *sync_state) static void task_cloud_sync_fetch_server_file(task_cloud_sync_state_t *sync_state)
{ {
char filename[PATH_MAX_LENGTH]; struct string_list *dirlist = task_cloud_sync_directory_map();
struct item_file *server_file = &sync_state->server_manifest->list[sync_state->server_idx]; struct item_file *server_file = &sync_state->server_manifest->list[sync_state->server_idx];
const char *key = CS_FILE_KEY(server_file); const char *key = CS_FILE_KEY(server_file);
const char *path = strchr(key, PATH_DEFAULT_SLASH_C()) + 1; const char *path = strchr(key, PATH_DEFAULT_SLASH_C()) + 1;
char directory[PATH_MAX_LENGTH]; char directory[PATH_MAX_LENGTH];
settings_t *settings = config_get_ptr(); char filename[PATH_MAX_LENGTH];
settings_t *settings = config_get_ptr();
int i;
RARCH_LOG(CSPFX "fetching %s\n", key); RARCH_LOG(CSPFX "fetching %s\n", key);
/* we're just fetching a file the server has, we can update this now */
task_cloud_sync_add_to_updated_manifest(sync_state, key, CS_FILE_HASH(server_file), true);
/* no need to mark need_manifest_uploaded, nothing changed */
if (string_starts_with(key, "config")) filename[0] = '\0';
for (i = 0; i < dirlist->size; i++)
{ {
char config_dir[PATH_MAX_LENGTH]; if (!string_starts_with(key, dirlist->elems[i].data))
fill_pathname_application_special(config_dir, continue;
sizeof(config_dir), fill_pathname_join_special(filename, dirlist->elems[i].userdata, path, sizeof(filename));
APPLICATION_SPECIAL_DIRECTORY_CONFIG); break;
fill_pathname_join_special(filename, config_dir, path, sizeof(filename)); }
if (string_is_empty(filename))
{
/* how did this end up here? we don't know where to put it... */
RARCH_WARN(CSPFX "don't know where to put %s!\n", key);
return;
} }
else if (string_starts_with(key, "saves"))
fill_pathname_join_special(filename, dir_get_ptr(RARCH_DIR_SAVEFILE), path, sizeof(filename));
else if (string_starts_with(key, "states"))
fill_pathname_join_special(filename, dir_get_ptr(RARCH_DIR_SAVESTATE), path, sizeof(filename));
if (!settings->bools.cloud_sync_destructive && path_is_valid(filename)) if (!settings->bools.cloud_sync_destructive && path_is_valid(filename))
{ {
@ -492,8 +511,6 @@ static void task_cloud_sync_fetch_server_file(task_cloud_sync_state_t *sync_stat
{ {
RARCH_WARN(CSPFX "wanted to fetch %s but failed\n", key); RARCH_WARN(CSPFX "wanted to fetch %s but failed\n", key);
sync_state->failures = true; sync_state->failures = true;
task_cloud_sync_add_to_updated_manifest(sync_state, key, CS_FILE_HASH(server_file), true);
/* no need to mark need_manifest_uploaded, nothing changed */
} }
} }