#include #include #include #include #include #include #include int sceKernelDebugOutText(int class, const char *text); #define DBG_CLASS 0x80 static void dbg(const char *fmt, ...) { char buf[512]; va_list args; va_start(args, fmt); vsnprintf(buf, sizeof buf, fmt, args); va_end(args); sceKernelDebugOutText(DBG_CLASS, buf); } typedef struct notify_request { char useless1[45]; char message[3075]; } notify_request_t; int sceKernelSendNotificationRequest(int, notify_request_t *, size_t, int); static void notify(const char *fmt, ...) { notify_request_t req; char buf[512]; va_list args; va_start(args, fmt); vsnprintf(buf, sizeof buf, fmt, args); va_end(args); sceKernelDebugOutText(DBG_CLASS, buf); __builtin_memset(&req, 0, sizeof req); snprintf(req.message, sizeof req.message, "%s", buf); sceKernelSendNotificationRequest(0, &req, sizeof req, 0); } typedef struct { const char *label; const char *relative_path; } cache_file_t; static const cache_file_t CACHE_FILES[] = { // cookies { "Cookies", "webkit/shell/NKCookie.jar.db" }, { "Cookies", "webkit/shell/NKCookie.jar.db-shm" }, { "Cookies", "webkit/shell/NKCookie.jar.db-wal" }, // appcache { "AppCache", "webkit/shell/appcache/ApplicationCache.db" }, { "AppCache", "webkit/shell/appcache/ApplicationCache.db-shm" }, { "AppCache", "webkit/shell/appcache/ApplicationCache.db-wal" }, // localstorage { "Local", "webkit/shell/local/https_manuals.playstation.net_0.localstorage" }, { "Local", "webkit/shell/local/https_manuals.playstation.net_0.localstorage-shm" }, { "Local", "webkit/shell/local/https_manuals.playstation.net_0.localstorage-wal" }, // resource stats { "ResStats", "webkit/shell/resourceloadstatistics/full_browsing_session_resourceLog.plist" }, }; #define NUM_FILES (sizeof(CACHE_FILES) / sizeof(CACHE_FILES[0])) static int delete_user_files(const char *userfolder) { char path[512]; struct stat st; int removed = 0; const char *last_label = NULL; dbg("[appcache] processing user: %s\n", userfolder); notify("AppCache Remove\nRemoving for user: %s", userfolder); for (size_t i = 0; i < NUM_FILES; i++) { const cache_file_t *f = &CACHE_FILES[i]; int n = snprintf(path, sizeof path, "/user/home/%s/%s", userfolder, f->relative_path); if (n < 0 || (size_t)n >= sizeof path) { dbg("[appcache] skip (path too long): %s/%s\n", userfolder, f->relative_path); continue; } // toast once per label group if (!last_label || strcmp(last_label, f->label) != 0) { notify("AppCache Remove\nRemoving %s...", f->label); last_label = f->label; } if (stat(path, &st) != 0) { dbg("[appcache] not found: %s\n", path); continue; } if (remove(path) == 0) { dbg("[appcache] deleted: %s\n", path); removed++; } else { dbg("[appcache] failed (errno %d): %s\n", errno, path); notify("AppCache Remove\nFailed to remove %s\n(errno %d)", f->label, errno); } } dbg("[appcache] user %s: %d file(s) removed\n", userfolder, removed); return removed; } static void process_all_users(void) { DIR *dir; struct dirent *entry; int total = 0, users = 0; dir = opendir("/user/home"); if (!dir) { dbg("[appcache] opendir failed, errno %d\n", errno); notify("AppCache Remove\nFailed to open /user/home\n(errno %d)", errno); return; } while ((entry = readdir(dir)) != NULL) { if (entry->d_name[0] == '.' && (entry->d_name[1] == '\0' || (entry->d_name[1] == '.' && entry->d_name[2] == '\0'))) continue; users++; total += delete_user_files(entry->d_name); } closedir(dir); if (!users) { notify("AppCache Remove\nNo user folders found under /user/home."); } else { dbg("[appcache] done: %d file(s) across %d user(s)\n", total, users); notify("AppCache Remove: Done!\nRemoved %d file(s) across %d user(s).", total, users); } } int main(void) { dbg("[appcache] started\n"); notify("AppCache Remove " VERSION_STR "\nRemoving for all Users..."); process_all_users(); dbg("[appcache] done\n"); return 0; }