void clear_cache_files(cache_t* cache, int64_t free_size) { size_t i; int skip = 0; char path[PATH_MAX]; ALOGI("Collected cache files: %d directories, %d files", cache->numDirs, cache->numFiles); CACHE_NOISY(ALOGI("Sorting files...")); qsort(cache->files, cache->numFiles, sizeof(cache_file_t*), cache_modtime_sort); CACHE_NOISY(ALOGI("Cleaning empty directories...")); for (i=cache->numDirs; i>0; i--) { cache_dir_t* dir = cache->dirs[i-1]; if (dir->childCount <= 0 && !dir->deleted) { delete_cache_dir(path, dir); } } CACHE_NOISY(ALOGI("Trimming files...")); for (i=0; i<cache->numFiles; i++) { skip++; if (skip > 10) { if (data_disk_free() > free_size) { return; } skip = 0; } cache_file_t* file = cache->files[i]; strcpy(create_dir_path(path, file->dir), file->name); ALOGI("DEL (mod %d) %s\n", (int)file->modTime, path); if (unlink(path) < 0) { ALOGE("Couldn't unlink %s: %s\n", path, strerror(errno)); } file->dir->childCount--; if (file->dir->childCount <= 0) { delete_cache_dir(path, file->dir); } } }
/* Try to ensure free_size bytes of storage are available. * Returns 0 on success. * This is rather simple-minded because doing a full LRU would * be potentially memory-intensive, and without atime it would * also require that apps constantly modify file metadata even * when just reading from the cache, which is pretty awful. */ int free_cache(int64_t free_size) { cache_t* cache; int64_t avail; DIR *d; struct dirent *de; char tmpdir[PATH_MAX]; char *dirpos; avail = data_disk_free(); if (avail < 0) return -1; ALOGI("free_cache(%" PRId64 ") avail %" PRId64 "\n", free_size, avail); if (avail >= free_size) return 0; cache = start_cache_collection(); // Collect cache files for primary user. if (create_persona_path(tmpdir, 0) == 0) { //ALOGI("adding cache files from %s\n", tmpdir); add_cache_files(cache, tmpdir, "cache"); } // Search for other users and add any cache files from them. snprintf(tmpdir, sizeof(tmpdir), "%s%s", android_data_dir.path, SECONDARY_USER_PREFIX); dirpos = tmpdir + strlen(tmpdir); d = opendir(tmpdir); if (d != NULL) { while ((de = readdir(d))) { if (de->d_type == DT_DIR) { const char *name = de->d_name; /* always skip "." and ".." */ if (name[0] == '.') { if (name[1] == 0) continue; if ((name[1] == '.') && (name[2] == 0)) continue; } if ((strlen(name)+(dirpos-tmpdir)) < (sizeof(tmpdir)-1)) { strcpy(dirpos, name); //ALOGI("adding cache files from %s\n", tmpdir); add_cache_files(cache, tmpdir, "cache"); } else { ALOGW("Path exceeds limit: %s%s", tmpdir, name); } } } closedir(d); } // Collect cache files on external storage for all users (if it is mounted as part // of the internal storage). strcpy(tmpdir, android_media_dir.path); dirpos = tmpdir + strlen(tmpdir); d = opendir(tmpdir); if (d != NULL) { while ((de = readdir(d))) { if (de->d_type == DT_DIR) { const char *name = de->d_name; /* skip any dir that doesn't start with a number, so not a user */ if (name[0] < '0' || name[0] > '9') { continue; } if ((strlen(name)+(dirpos-tmpdir)) < (sizeof(tmpdir)-1)) { strcpy(dirpos, name); if (lookup_media_dir(tmpdir, "Android") == 0 && lookup_media_dir(tmpdir, "data") == 0) { //ALOGI("adding cache files from %s\n", tmpdir); add_cache_files(cache, tmpdir, "cache"); } } else { ALOGW("Path exceeds limit: %s%s", tmpdir, name); } } } closedir(d); } clear_cache_files(cache, free_size); finish_cache_collection(cache); return data_disk_free() >= free_size ? 0 : -1; }