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 */
17static 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
28static void wipe (const char *path);
29
30static 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
39int 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
78static char nameBuffer[PATH_MAX];
79static struct stat statBuffer;
80
81static 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