| The Android Open Source Project | dd7bc33 | 2009-03-03 19:32:55 -0800 | [diff] [blame] | 1 | #include <stdlib.h> | 
|  | 2 | #include <stdio.h> | 
|  | 3 | #include <unistd.h> | 
|  | 4 | #include <dirent.h> | 
|  | 5 | #include <string.h> | 
|  | 6 | #include <errno.h> | 
|  | 7 | #include <sys/types.h> | 
| Ken Sumrall | e3aeeb4 | 2011-03-07 23:29:42 -0800 | [diff] [blame] | 8 | #include <cutils/android_reboot.h> | 
| The Android Open Source Project | dd7bc33 | 2009-03-03 19:32:55 -0800 | [diff] [blame] | 9 | #include <sys/stat.h> | 
|  | 10 |  | 
|  | 11 | #ifndef PATH_MAX | 
|  | 12 | #define PATH_MAX 4096 | 
|  | 13 | #endif | 
|  | 14 |  | 
|  | 15 |  | 
|  | 16 | /* Directories created by init defined in system/rootdir/init.rc */ | 
|  | 17 | static char *INIT_DIRS[] = { | 
|  | 18 | "/system/etc/ppp", | 
|  | 19 | "/data/misc", | 
|  | 20 | "/data/local", | 
|  | 21 | "/data/local/tmp", | 
|  | 22 | "/data/data", | 
|  | 23 | "/data/app_private", | 
|  | 24 | "/data/app", | 
|  | 25 | NULL | 
|  | 26 | }; | 
|  | 27 |  | 
|  | 28 | static void wipe (const char *path); | 
|  | 29 |  | 
|  | 30 | static int usage() | 
|  | 31 | { | 
|  | 32 | fprintf(stderr, "wipe <system|data|all>\n\n" | 
|  | 33 | "system means '/system'\n" | 
|  | 34 | "data means '/data'\n"); | 
|  | 35 |  | 
|  | 36 | return -1; | 
|  | 37 | } | 
|  | 38 |  | 
|  | 39 | int wipe_main (int argc, char *argv[]) | 
|  | 40 | { | 
|  | 41 | char *whatToWipe; | 
|  | 42 |  | 
|  | 43 | if (argc != 2) return usage(); | 
|  | 44 |  | 
|  | 45 | whatToWipe = argv[1]; | 
|  | 46 |  | 
|  | 47 | if (0 == strcmp (whatToWipe, "system")) { | 
|  | 48 | fprintf(stdout, "Wiping /system\n"); | 
|  | 49 | wipe ("/system"); | 
|  | 50 | fprintf(stdout, "Done wiping /android\n"); | 
|  | 51 | } else if (0 == strcmp (whatToWipe, "data")) { | 
|  | 52 | fprintf(stdout, "Wiping /data\n"); | 
|  | 53 | wipe ("/data"); | 
|  | 54 | fprintf(stdout, "Done wiping /data\n"); | 
|  | 55 | } else if (0 == strcmp (whatToWipe, "all")) { | 
|  | 56 | fprintf(stdout, "Wiping /system and /data\n"); | 
|  | 57 | wipe ("/system"); | 
|  | 58 | wipe ("/data"); | 
|  | 59 | fprintf(stdout, "Done wiping /system and /data\n"); | 
|  | 60 | } else if (0 == strcmp(whatToWipe, "nuke")) { | 
|  | 61 | int ret; | 
|  | 62 | fprintf(stdout, "Nuking the device...\n"); | 
|  | 63 | wipe ("/system"); | 
|  | 64 | wipe ("/data"); | 
|  | 65 | fprintf(stdout, "Device nuked! Rebooting...\n"); | 
| Ken Sumrall | e3aeeb4 | 2011-03-07 23:29:42 -0800 | [diff] [blame] | 66 | ret = android_reboot(ANDROID_RB_RESTART, 0, 0); | 
| The Android Open Source Project | dd7bc33 | 2009-03-03 19:32:55 -0800 | [diff] [blame] | 67 | if (ret < 0) { | 
|  | 68 | fprintf(stderr, "Reboot failed, %s\n", strerror(errno)); | 
|  | 69 | return 1; | 
|  | 70 | } | 
|  | 71 | } else { | 
|  | 72 | return usage(); | 
|  | 73 | } | 
|  | 74 |  | 
|  | 75 | return 0; | 
|  | 76 | } | 
|  | 77 |  | 
|  | 78 | static char nameBuffer[PATH_MAX]; | 
|  | 79 | static struct stat statBuffer; | 
|  | 80 |  | 
|  | 81 | static void wipe (const char *path) | 
|  | 82 | { | 
|  | 83 | DIR *dir; | 
|  | 84 | struct dirent *de; | 
|  | 85 | int ret; | 
|  | 86 |  | 
|  | 87 | dir = opendir(path); | 
|  | 88 |  | 
|  | 89 | if (dir == NULL) { | 
|  | 90 | fprintf (stderr, "Error opendir'ing %s '%s'\n", | 
|  | 91 | path, strerror(errno)); | 
|  | 92 | return; | 
|  | 93 | } | 
|  | 94 |  | 
|  | 95 | char *filenameOffset; | 
|  | 96 |  | 
|  | 97 | strcpy(nameBuffer, path); | 
|  | 98 | strcat(nameBuffer, "/"); | 
|  | 99 |  | 
|  | 100 | filenameOffset = nameBuffer + strlen(nameBuffer); | 
|  | 101 |  | 
|  | 102 | for (;;) { | 
|  | 103 | de = readdir(dir); | 
|  | 104 |  | 
|  | 105 | if (de == NULL) { | 
|  | 106 | break; | 
|  | 107 | } | 
|  | 108 |  | 
|  | 109 | if (0 == strcmp(de->d_name, ".") | 
|  | 110 | || 0 == strcmp(de->d_name, "..") | 
|  | 111 | || 0 == strcmp(de->d_name, "lost+found") | 
|  | 112 | ) { | 
|  | 113 | continue; | 
|  | 114 | } | 
|  | 115 |  | 
|  | 116 | strcpy(filenameOffset, de->d_name); | 
|  | 117 |  | 
|  | 118 | ret = lstat (nameBuffer, &statBuffer); | 
|  | 119 |  | 
|  | 120 | if (ret != 0) { | 
|  | 121 | fprintf(stderr, "stat() error on '%s' '%s'\n", | 
|  | 122 | nameBuffer, strerror(errno)); | 
|  | 123 | } | 
|  | 124 |  | 
|  | 125 | if(S_ISDIR(statBuffer.st_mode)) { | 
|  | 126 | int i; | 
|  | 127 | char *newpath; | 
|  | 128 |  | 
|  | 129 | #if 0 | 
|  | 130 | closedir(dir); | 
|  | 131 | #endif | 
|  | 132 |  | 
|  | 133 | newpath = strdup(nameBuffer); | 
|  | 134 | wipe(newpath); | 
|  | 135 |  | 
|  | 136 | /* Leave directories created by init, they have special permissions. */ | 
|  | 137 | for (i = 0; INIT_DIRS[i]; i++) { | 
|  | 138 | if (strcmp(INIT_DIRS[i], newpath) == 0) { | 
|  | 139 | break; | 
|  | 140 | } | 
|  | 141 | } | 
|  | 142 | if (INIT_DIRS[i] == NULL) { | 
|  | 143 | ret = rmdir(newpath); | 
|  | 144 | if (ret != 0) { | 
|  | 145 | fprintf(stderr, "rmdir() error on '%s' '%s'\n", | 
|  | 146 | newpath, strerror(errno)); | 
|  | 147 | } | 
|  | 148 | } | 
|  | 149 |  | 
|  | 150 | free(newpath); | 
|  | 151 |  | 
|  | 152 | #if 0 | 
|  | 153 | dir = opendir(path); | 
|  | 154 | if (dir == NULL) { | 
|  | 155 | fprintf (stderr, "Error opendir'ing %s '%s'\n", | 
|  | 156 | path, strerror(errno)); | 
|  | 157 | return; | 
|  | 158 | } | 
|  | 159 | #endif | 
|  | 160 |  | 
|  | 161 | strcpy(nameBuffer, path); | 
|  | 162 | strcat(nameBuffer, "/"); | 
|  | 163 |  | 
|  | 164 | } else { | 
|  | 165 | ret = unlink(nameBuffer); | 
|  | 166 |  | 
|  | 167 | if (ret != 0) { | 
|  | 168 | fprintf(stderr, "unlink() error on '%s' '%s'\n", | 
|  | 169 | nameBuffer, strerror(errno)); | 
|  | 170 | } | 
|  | 171 | } | 
|  | 172 | } | 
|  | 173 |  | 
|  | 174 | closedir(dir); | 
|  | 175 |  | 
|  | 176 | } |