summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGravatar Nikias Bassen2018-10-29 07:09:08 +0100
committerGravatar Nikias Bassen2018-10-29 07:09:08 +0100
commitd72b747e590044f9970ef26827f3af3ea9c1eb4a (patch)
tree995396756ac8ec84778393b990b8327cfedd7e8e
parentb34e3435c21d06b3e5a4e7b5246fb6ddb6641a9f (diff)
downloadlibimobiledevice-d72b747e590044f9970ef26827f3af3ea9c1eb4a.tar.gz
libimobiledevice-d72b747e590044f9970ef26827f3af3ea9c1eb4a.tar.bz2
idevicebackup2: Fix rmdir_recursive() not deleting all files/directories (esp. on network filesystems)
-rw-r--r--tools/idevicebackup2.c75
1 files changed, 55 insertions, 20 deletions
diff --git a/tools/idevicebackup2.c b/tools/idevicebackup2.c
index 6d4785b..02611a1 100644
--- a/tools/idevicebackup2.c
+++ b/tools/idevicebackup2.c
@@ -2,8 +2,8 @@
* idevicebackup2.c
* Command line interface to use the device's backup and restore service
*
+ * Copyright (c) 2010-2018 Nikias Bassen All Rights Reserved.
* Copyright (c) 2009-2010 Martin Szulecki All Rights Reserved.
- * Copyright (c) 2010 Nikias Bassen All Rights Reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -238,7 +238,12 @@ static int remove_directory(const char* path)
return e;
}
-static int rmdir_recursive(const char* path)
+struct entry {
+ char *name;
+ struct entry *next;
+};
+
+static void scan_directory(const char *path, struct entry **files, struct entry **directories)
{
DIR* cur_dir = opendir(path);
if (cur_dir) {
@@ -249,31 +254,61 @@ static int rmdir_recursive(const char* path)
}
char *fpath = string_build_path(path, ep->d_name, NULL);
if (fpath) {
- struct stat st;
- if (stat(fpath, &st) == 0) {
- int res = 0;
- if (S_ISDIR(st.st_mode)) {
- res = rmdir_recursive(fpath);
- } else {
- res = remove_file(fpath);
- }
- if (res != 0) {
- free(fpath);
- closedir(cur_dir);
- return res;
- }
+ if (ep->d_type & DT_DIR) {
+ struct entry *ent = malloc(sizeof(struct entry));
+ if (!ent) return;
+ ent->name = fpath;
+ ent->next = *directories;
+ *directories = ent;
+ scan_directory(fpath, files, directories);
+ fpath = NULL;
} else {
- free(fpath);
- closedir(cur_dir);
- return errno;
+ struct entry *ent = malloc(sizeof(struct entry));
+ if (!ent) return;
+ ent->name = fpath;
+ ent->next = *files;
+ *files = ent;
+ fpath = NULL;
}
}
- free(fpath);
}
closedir(cur_dir);
}
+}
+
+static int rmdir_recursive(const char* path)
+{
+ int res = 0;
+ struct entry *files = NULL;
+ struct entry *directories = NULL;
+ struct entry *ent;
+
+ ent = malloc(sizeof(struct entry));
+ if (!ent) return ENOMEM;
+ ent->name = strdup(path);
+ ent->next = NULL;
+ directories = ent;
+
+ scan_directory(path, &files, &directories);
+
+ ent = files;
+ while (ent) {
+ struct entry *del = ent;
+ res = remove_file(ent->name);
+ free(ent->name);
+ ent = ent->next;
+ free(del);
+ }
+ ent = directories;
+ while (ent) {
+ struct entry *del = ent;
+ res = remove_directory(ent->name);
+ free(ent->name);
+ ent = ent->next;
+ free(del);
+ }
- return remove_directory(path);
+ return res;
}
static char* get_uuid()