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> 8 #include <cutils/android_reboot.h> 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"); 66 ret = android_reboot(ANDROID_RB_RESTART, 0, 0); 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 } 177