Beispiel #1
0
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;
}