| #include <stdlib.h> |
| #include <stdio.h> |
| #include <unistd.h> |
| #include <dirent.h> |
| #include <string.h> |
| #include <errno.h> |
| #include <sys/types.h> |
| #include <cutils/android_reboot.h> |
| #include <sys/stat.h> |
| |
| #ifndef PATH_MAX |
| #define PATH_MAX 4096 |
| #endif |
| |
| |
| /* Directories created by init defined in system/rootdir/init.rc */ |
| static char *INIT_DIRS[] = { |
| "/system/etc/ppp", |
| "/data/misc", |
| "/data/local", |
| "/data/local/tmp", |
| "/data/data", |
| "/data/app_private", |
| "/data/app", |
| NULL |
| }; |
| |
| static void wipe (const char *path); |
| |
| static int usage() |
| { |
| fprintf(stderr, "wipe <system|data|all>\n\n" |
| "system means '/system'\n" |
| "data means '/data'\n"); |
| |
| return -1; |
| } |
| |
| int wipe_main (int argc, char *argv[]) |
| { |
| char *whatToWipe; |
| |
| if (argc != 2) return usage(); |
| |
| whatToWipe = argv[1]; |
| |
| if (0 == strcmp (whatToWipe, "system")) { |
| fprintf(stdout, "Wiping /system\n"); |
| wipe ("/system"); |
| fprintf(stdout, "Done wiping /android\n"); |
| } else if (0 == strcmp (whatToWipe, "data")) { |
| fprintf(stdout, "Wiping /data\n"); |
| wipe ("/data"); |
| fprintf(stdout, "Done wiping /data\n"); |
| } else if (0 == strcmp (whatToWipe, "all")) { |
| fprintf(stdout, "Wiping /system and /data\n"); |
| wipe ("/system"); |
| wipe ("/data"); |
| fprintf(stdout, "Done wiping /system and /data\n"); |
| } else if (0 == strcmp(whatToWipe, "nuke")) { |
| int ret; |
| fprintf(stdout, "Nuking the device...\n"); |
| wipe ("/system"); |
| wipe ("/data"); |
| fprintf(stdout, "Device nuked! Rebooting...\n"); |
| ret = android_reboot(ANDROID_RB_RESTART, 0, 0); |
| if (ret < 0) { |
| fprintf(stderr, "Reboot failed, %s\n", strerror(errno)); |
| return 1; |
| } |
| } else { |
| return usage(); |
| } |
| |
| return 0; |
| } |
| |
| static char nameBuffer[PATH_MAX]; |
| static struct stat statBuffer; |
| |
| static void wipe (const char *path) |
| { |
| DIR *dir; |
| struct dirent *de; |
| int ret; |
| |
| dir = opendir(path); |
| |
| if (dir == NULL) { |
| fprintf (stderr, "Error opendir'ing %s '%s'\n", |
| path, strerror(errno)); |
| return; |
| } |
| |
| char *filenameOffset; |
| |
| strcpy(nameBuffer, path); |
| strcat(nameBuffer, "/"); |
| |
| filenameOffset = nameBuffer + strlen(nameBuffer); |
| |
| for (;;) { |
| de = readdir(dir); |
| |
| if (de == NULL) { |
| break; |
| } |
| |
| if (0 == strcmp(de->d_name, ".") |
| || 0 == strcmp(de->d_name, "..") |
| || 0 == strcmp(de->d_name, "lost+found") |
| ) { |
| continue; |
| } |
| |
| strcpy(filenameOffset, de->d_name); |
| |
| ret = lstat (nameBuffer, &statBuffer); |
| |
| if (ret != 0) { |
| fprintf(stderr, "stat() error on '%s' '%s'\n", |
| nameBuffer, strerror(errno)); |
| } |
| |
| if(S_ISDIR(statBuffer.st_mode)) { |
| int i; |
| char *newpath; |
| |
| #if 0 |
| closedir(dir); |
| #endif |
| |
| newpath = strdup(nameBuffer); |
| wipe(newpath); |
| |
| /* Leave directories created by init, they have special permissions. */ |
| for (i = 0; INIT_DIRS[i]; i++) { |
| if (strcmp(INIT_DIRS[i], newpath) == 0) { |
| break; |
| } |
| } |
| if (INIT_DIRS[i] == NULL) { |
| ret = rmdir(newpath); |
| if (ret != 0) { |
| fprintf(stderr, "rmdir() error on '%s' '%s'\n", |
| newpath, strerror(errno)); |
| } |
| } |
| |
| free(newpath); |
| |
| #if 0 |
| dir = opendir(path); |
| if (dir == NULL) { |
| fprintf (stderr, "Error opendir'ing %s '%s'\n", |
| path, strerror(errno)); |
| return; |
| } |
| #endif |
| |
| strcpy(nameBuffer, path); |
| strcat(nameBuffer, "/"); |
| |
| } else { |
| ret = unlink(nameBuffer); |
| |
| if (ret != 0) { |
| fprintf(stderr, "unlink() error on '%s' '%s'\n", |
| nameBuffer, strerror(errno)); |
| } |
| } |
| } |
| |
| closedir(dir); |
| |
| } |