mirror of
https://github.com/xorgy/mediafire-fuse
synced 2026-01-13 13:14:29 -08:00
Call folder/get_contents for updated folders in device/get_changes
- it is not enough to rely on the parent information of updated files because that misses files and folders that were completely removed (even from trash)
This commit is contained in:
103
fuse/hashtbl.c
103
fuse/hashtbl.c
@@ -913,9 +913,13 @@ static int folder_tree_rebuild_helper(folder_tree * tree, mfconn * conn,
|
|||||||
mffile **file_result;
|
mffile **file_result;
|
||||||
h_entry *entry;
|
h_entry *entry;
|
||||||
int i;
|
int i;
|
||||||
|
const char *key;
|
||||||
|
bool found;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* free the old children array of this folder
|
* free the old children array of this folder to make sure that any
|
||||||
|
* entries that do not exist on the remote are removed locally
|
||||||
|
*
|
||||||
* we don't free the children it references because they might be
|
* we don't free the children it references because they might be
|
||||||
* referenced by someone else
|
* referenced by someone else
|
||||||
*/
|
*/
|
||||||
@@ -941,11 +945,36 @@ static int folder_tree_rebuild_helper(folder_tree * tree, mfconn * conn,
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; folder_result[i] != NULL; i++) {
|
for (i = 0; folder_result[i] != NULL; i++) {
|
||||||
if (folder_get_key(folder_result[i]) == NULL) {
|
key = folder_get_key(folder_result[i]);
|
||||||
|
if (key == NULL) {
|
||||||
fprintf(stderr, "folder_get_key returned NULL\n");
|
fprintf(stderr, "folder_get_key returned NULL\n");
|
||||||
folder_free(folder_result[i]);
|
folder_free(folder_result[i]);
|
||||||
}
|
}
|
||||||
|
/* if this folder existed before, then folder_tree_add_folder will not
|
||||||
|
* add it to this folder's children. Thus we do this now */
|
||||||
|
found = false;
|
||||||
|
if (folder_tree_lookup_key(tree, key) != NULL) {
|
||||||
|
curr_entry->num_children++;
|
||||||
|
curr_entry->children =
|
||||||
|
(h_entry **) realloc(curr_entry->children,
|
||||||
|
curr_entry->num_children *
|
||||||
|
sizeof(h_entry *));
|
||||||
|
if (curr_entry->children == NULL) {
|
||||||
|
fprintf(stderr, "realloc failed\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
found = true;
|
||||||
|
}
|
||||||
entry = folder_tree_add_folder(tree, folder_result[i], curr_entry);
|
entry = folder_tree_add_folder(tree, folder_result[i], curr_entry);
|
||||||
|
/* we are using a new variable "found" here because after doing a
|
||||||
|
* folder_tree_add_folder, folder_tree_lookup_key will always succeed
|
||||||
|
*
|
||||||
|
* if this entry was not present before, then folder_tree_add_folder
|
||||||
|
* already added it to this folder's children
|
||||||
|
*/
|
||||||
|
if (found) {
|
||||||
|
curr_entry->children[curr_entry->num_children - 1] = entry;
|
||||||
|
}
|
||||||
/* recurse */
|
/* recurse */
|
||||||
if (recurse)
|
if (recurse)
|
||||||
folder_tree_rebuild_helper(tree, conn, entry, true);
|
folder_tree_rebuild_helper(tree, conn, entry, true);
|
||||||
@@ -971,11 +1000,36 @@ static int folder_tree_rebuild_helper(folder_tree * tree, mfconn * conn,
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; file_result[i] != NULL; i++) {
|
for (i = 0; file_result[i] != NULL; i++) {
|
||||||
if (file_get_key(file_result[i]) == NULL) {
|
key = file_get_key(file_result[i]);
|
||||||
|
if (key == NULL) {
|
||||||
fprintf(stderr, "file_get_key returned NULL\n");
|
fprintf(stderr, "file_get_key returned NULL\n");
|
||||||
file_free(file_result[i]);
|
file_free(file_result[i]);
|
||||||
}
|
}
|
||||||
|
/* if this folder existed before, then folder_tree_add_folder will not
|
||||||
|
* add it to this folder's children. Thus we do this now */
|
||||||
|
found = false;
|
||||||
|
if (folder_tree_lookup_key(tree, key) != NULL) {
|
||||||
|
curr_entry->num_children++;
|
||||||
|
curr_entry->children =
|
||||||
|
(h_entry **) realloc(curr_entry->children,
|
||||||
|
curr_entry->num_children *
|
||||||
|
sizeof(h_entry *));
|
||||||
|
if (curr_entry->children == NULL) {
|
||||||
|
fprintf(stderr, "realloc failed\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
found = true;
|
||||||
|
}
|
||||||
entry = folder_tree_add_file(tree, file_result[i], curr_entry);
|
entry = folder_tree_add_file(tree, file_result[i], curr_entry);
|
||||||
|
/* we are using a new variable "found" here because after doing a
|
||||||
|
* folder_tree_add_folder, folder_tree_lookup_key will always succeed
|
||||||
|
*
|
||||||
|
* if this entry was not present before, then folder_tree_add_folder
|
||||||
|
* already added it to this folder's children
|
||||||
|
*/
|
||||||
|
if (found) {
|
||||||
|
curr_entry->children[curr_entry->num_children - 1] = entry;
|
||||||
|
}
|
||||||
file_free(file_result[i]);
|
file_free(file_result[i]);
|
||||||
}
|
}
|
||||||
free(file_result);
|
free(file_result);
|
||||||
@@ -1072,6 +1126,7 @@ void folder_tree_update(folder_tree * tree, mfconn * conn)
|
|||||||
uint64_t i;
|
uint64_t i;
|
||||||
struct mfconn_device_change *changes;
|
struct mfconn_device_change *changes;
|
||||||
int retval;
|
int retval;
|
||||||
|
h_entry *tmp_entry;
|
||||||
|
|
||||||
mfconn_api_device_get_status(conn, &revision_remote);
|
mfconn_api_device_get_status(conn, &revision_remote);
|
||||||
mfconn_update_secret_key(conn);
|
mfconn_update_secret_key(conn);
|
||||||
@@ -1082,11 +1137,26 @@ void folder_tree_update(folder_tree * tree, mfconn * conn)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* root never shows up in device_get_changes but since we rely on the
|
* we maintain the information of each entries parent but that does not
|
||||||
* parent information of files and folders, we do not manually retrieve
|
* mean that we can rely on it when fetching updates via
|
||||||
* its content
|
* device/get_changes. If a remote object has been permanently removed
|
||||||
|
* (trash was emptied) then it will not show up in the results of
|
||||||
|
* device/get_changes and thus a remote file will vanish without that file
|
||||||
|
* showing up in the device/get_changes output. The only way to clean up
|
||||||
|
* those removed files is to use folder/get_content for all folders that
|
||||||
|
* changed.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* we have to manually check the root because it never shows up in the
|
||||||
|
* results from device_get_changes
|
||||||
|
*
|
||||||
|
* we don't need to be recursive here because we rely on
|
||||||
|
* device/get_changes reporting all changes to its children
|
||||||
|
*/
|
||||||
|
|
||||||
|
folder_tree_rebuild_helper(tree, conn, &(tree->root), false);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* changes have to be applied in the right order but the result of
|
* changes have to be applied in the right order but the result of
|
||||||
* mfconn_api_device_get_changes is already sorted by revision
|
* mfconn_api_device_get_changes is already sorted by revision
|
||||||
@@ -1100,12 +1170,6 @@ void folder_tree_update(folder_tree * tree, mfconn * conn)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* TODO: before calling remote functions here, check if the revision of
|
|
||||||
* the local object is lower than the one of the reported change
|
|
||||||
*
|
|
||||||
* TODO: only use the latest revision of the same file-/folderkey
|
|
||||||
*/
|
|
||||||
for (i = 0; changes[i].change != MFCONN_DEVICE_CHANGE_END; i++) {
|
for (i = 0; changes[i].change != MFCONN_DEVICE_CHANGE_END; i++) {
|
||||||
switch (changes[i].change) {
|
switch (changes[i].change) {
|
||||||
case MFCONN_DEVICE_CHANGE_DELETED_FOLDER:
|
case MFCONN_DEVICE_CHANGE_DELETED_FOLDER:
|
||||||
@@ -1120,10 +1184,19 @@ void folder_tree_update(folder_tree * tree, mfconn * conn)
|
|||||||
if (strcmp(changes[i].parent, "trash") == 0)
|
if (strcmp(changes[i].parent, "trash") == 0)
|
||||||
continue;
|
continue;
|
||||||
/* if a folder has been updated then its name or location
|
/* if a folder has been updated then its name or location
|
||||||
* might have changed */
|
* might have changed... */
|
||||||
folder_tree_update_folder_info(tree, conn, changes[i].key);
|
folder_tree_update_folder_info(tree, conn, changes[i].key);
|
||||||
/* its content might also have changed but we use the changes
|
/* ...or its contents changed
|
||||||
* to files to update it */
|
* the last call made sure that an entry for this folder has
|
||||||
|
* been added locally, so the following should succeed */
|
||||||
|
tmp_entry = folder_tree_lookup_key(tree, changes[i].key);
|
||||||
|
if (tmp_entry == NULL) {
|
||||||
|
fprintf(stderr, "folder_tree_lookup_key failed\n");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
/* we don't need to be recursive here because we rely on
|
||||||
|
* device/get_changes reporting all changes to its children */
|
||||||
|
folder_tree_rebuild_helper(tree, conn, tmp_entry, false);
|
||||||
break;
|
break;
|
||||||
case MFCONN_DEVICE_CHANGE_UPDATED_FILE:
|
case MFCONN_DEVICE_CHANGE_UPDATED_FILE:
|
||||||
/* ignore files updated in trash */
|
/* ignore files updated in trash */
|
||||||
|
|||||||
@@ -219,7 +219,7 @@ int main(int argc, char *argv[])
|
|||||||
|
|
||||||
//folder_tree_housekeep(tree);
|
//folder_tree_housekeep(tree);
|
||||||
|
|
||||||
//folder_tree_debug(tree, NULL, 0);
|
folder_tree_debug(tree, NULL, 0);
|
||||||
|
|
||||||
return fuse_main(args.argc, args.argv, &mediafirefs_oper, NULL);
|
return fuse_main(args.argc, args.argv, &mediafirefs_oper, NULL);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user