19066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/* 29066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project** Copyright 2008, The Android Open Source Project 39066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project** 49066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project** Licensed under the Apache License, Version 2.0 (the "License"); 59066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project** you may not use this file except in compliance with the License. 69066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project** You may obtain a copy of the License at 79066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project** 89066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project** http://www.apache.org/licenses/LICENSE-2.0 99066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project** 109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project** Unless required by applicable law or agreed to in writing, software 119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project** distributed under the License is distributed on an "AS IS" BASIS, 129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project** See the License for the specific language governing permissions and 149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project** limitations under the License. 159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project*/ 169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include "installd.h" 189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 19197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn#define CACHE_NOISY(x) //x 20197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn 2186c9584559439504fc57ece2ccd9b6cbd568430cKenny Rootint create_pkg_path_in_dir(char path[PKG_PATH_MAX], 2286c9584559439504fc57ece2ccd9b6cbd568430cKenny Root const dir_rec_t* dir, 2386c9584559439504fc57ece2ccd9b6cbd568430cKenny Root const char* pkgname, 2486c9584559439504fc57ece2ccd9b6cbd568430cKenny Root const char* postfix) 2586c9584559439504fc57ece2ccd9b6cbd568430cKenny Root{ 2686c9584559439504fc57ece2ccd9b6cbd568430cKenny Root const size_t postfix_len = strlen(postfix); 2786c9584559439504fc57ece2ccd9b6cbd568430cKenny Root 2886c9584559439504fc57ece2ccd9b6cbd568430cKenny Root const size_t pkgname_len = strlen(pkgname); 2986c9584559439504fc57ece2ccd9b6cbd568430cKenny Root if (pkgname_len > PKG_NAME_MAX) { 3086c9584559439504fc57ece2ccd9b6cbd568430cKenny Root return -1; 3186c9584559439504fc57ece2ccd9b6cbd568430cKenny Root } 3286c9584559439504fc57ece2ccd9b6cbd568430cKenny Root 3386c9584559439504fc57ece2ccd9b6cbd568430cKenny Root if (is_valid_package_name(pkgname) < 0) { 3486c9584559439504fc57ece2ccd9b6cbd568430cKenny Root return -1; 3586c9584559439504fc57ece2ccd9b6cbd568430cKenny Root } 3686c9584559439504fc57ece2ccd9b6cbd568430cKenny Root 3786c9584559439504fc57ece2ccd9b6cbd568430cKenny Root if ((pkgname_len + dir->len + postfix_len) >= PKG_PATH_MAX) { 3886c9584559439504fc57ece2ccd9b6cbd568430cKenny Root return -1; 3986c9584559439504fc57ece2ccd9b6cbd568430cKenny Root } 4086c9584559439504fc57ece2ccd9b6cbd568430cKenny Root 4186c9584559439504fc57ece2ccd9b6cbd568430cKenny Root char *dst = path; 4286c9584559439504fc57ece2ccd9b6cbd568430cKenny Root size_t dst_size = PKG_PATH_MAX; 4386c9584559439504fc57ece2ccd9b6cbd568430cKenny Root 4486c9584559439504fc57ece2ccd9b6cbd568430cKenny Root if (append_and_increment(&dst, dir->path, &dst_size) < 0 4586c9584559439504fc57ece2ccd9b6cbd568430cKenny Root || append_and_increment(&dst, pkgname, &dst_size) < 0 4686c9584559439504fc57ece2ccd9b6cbd568430cKenny Root || append_and_increment(&dst, postfix, &dst_size) < 0) { 473762c311729fe9f3af085c14c5c1fb471d994c03Steve Block ALOGE("Error building APK path"); 4886c9584559439504fc57ece2ccd9b6cbd568430cKenny Root return -1; 4986c9584559439504fc57ece2ccd9b6cbd568430cKenny Root } 5086c9584559439504fc57ece2ccd9b6cbd568430cKenny Root 5186c9584559439504fc57ece2ccd9b6cbd568430cKenny Root return 0; 5286c9584559439504fc57ece2ccd9b6cbd568430cKenny Root} 5386c9584559439504fc57ece2ccd9b6cbd568430cKenny Root 5486c9584559439504fc57ece2ccd9b6cbd568430cKenny Root/** 5586c9584559439504fc57ece2ccd9b6cbd568430cKenny Root * Create the package path name for a given package name with a postfix for 5686c9584559439504fc57ece2ccd9b6cbd568430cKenny Root * a certain persona. Returns 0 on success, and -1 on failure. 5786c9584559439504fc57ece2ccd9b6cbd568430cKenny Root */ 589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectint create_pkg_path(char path[PKG_PATH_MAX], 599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project const char *pkgname, 6086c9584559439504fc57ece2ccd9b6cbd568430cKenny Root const char *postfix, 6186c9584559439504fc57ece2ccd9b6cbd568430cKenny Root uid_t persona) 629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 6386c9584559439504fc57ece2ccd9b6cbd568430cKenny Root size_t uid_len; 6486c9584559439504fc57ece2ccd9b6cbd568430cKenny Root char* persona_prefix; 6586c9584559439504fc57ece2ccd9b6cbd568430cKenny Root if (persona == 0) { 6686c9584559439504fc57ece2ccd9b6cbd568430cKenny Root persona_prefix = PRIMARY_USER_PREFIX; 6786c9584559439504fc57ece2ccd9b6cbd568430cKenny Root uid_len = 0; 6886c9584559439504fc57ece2ccd9b6cbd568430cKenny Root } else { 6986c9584559439504fc57ece2ccd9b6cbd568430cKenny Root persona_prefix = SECONDARY_USER_PREFIX; 7086c9584559439504fc57ece2ccd9b6cbd568430cKenny Root uid_len = snprintf(NULL, 0, "%d", persona); 7186c9584559439504fc57ece2ccd9b6cbd568430cKenny Root } 7286c9584559439504fc57ece2ccd9b6cbd568430cKenny Root 7386c9584559439504fc57ece2ccd9b6cbd568430cKenny Root const size_t prefix_len = android_data_dir.len + strlen(persona_prefix) + uid_len + 1 /*slash*/; 7486c9584559439504fc57ece2ccd9b6cbd568430cKenny Root char prefix[prefix_len + 1]; 759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7686c9584559439504fc57ece2ccd9b6cbd568430cKenny Root char *dst = prefix; 7786c9584559439504fc57ece2ccd9b6cbd568430cKenny Root size_t dst_size = sizeof(prefix); 7886c9584559439504fc57ece2ccd9b6cbd568430cKenny Root 7986c9584559439504fc57ece2ccd9b6cbd568430cKenny Root if (append_and_increment(&dst, android_data_dir.path, &dst_size) < 0 8086c9584559439504fc57ece2ccd9b6cbd568430cKenny Root || append_and_increment(&dst, persona_prefix, &dst_size) < 0) { 813762c311729fe9f3af085c14c5c1fb471d994c03Steve Block ALOGE("Error building prefix for APK path"); 829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return -1; 839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8486c9584559439504fc57ece2ccd9b6cbd568430cKenny Root 8586c9584559439504fc57ece2ccd9b6cbd568430cKenny Root if (persona != 0) { 8686c9584559439504fc57ece2ccd9b6cbd568430cKenny Root int ret = snprintf(dst, dst_size, "%d/", persona); 8786c9584559439504fc57ece2ccd9b6cbd568430cKenny Root if (ret < 0 || (size_t) ret != uid_len + 1) { 888564c8da817a845353d213acd8636b76f567b234Steve Block ALOGW("Error appending UID to APK path"); 8986c9584559439504fc57ece2ccd9b6cbd568430cKenny Root return -1; 9086c9584559439504fc57ece2ccd9b6cbd568430cKenny Root } 919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9386c9584559439504fc57ece2ccd9b6cbd568430cKenny Root dir_rec_t dir; 9486c9584559439504fc57ece2ccd9b6cbd568430cKenny Root dir.path = prefix; 9586c9584559439504fc57ece2ccd9b6cbd568430cKenny Root dir.len = prefix_len; 9686c9584559439504fc57ece2ccd9b6cbd568430cKenny Root 9786c9584559439504fc57ece2ccd9b6cbd568430cKenny Root return create_pkg_path_in_dir(path, &dir, pkgname, postfix); 9886c9584559439504fc57ece2ccd9b6cbd568430cKenny Root} 9986c9584559439504fc57ece2ccd9b6cbd568430cKenny Root 10086c9584559439504fc57ece2ccd9b6cbd568430cKenny Root/** 1010b285499db739ba50f2f839d633e763c70e67f96Amith Yamasani * Create the path name for user data for a certain persona. 1020b285499db739ba50f2f839d633e763c70e67f96Amith Yamasani * Returns 0 on success, and -1 on failure. 1030b285499db739ba50f2f839d633e763c70e67f96Amith Yamasani */ 1040b285499db739ba50f2f839d633e763c70e67f96Amith Yamasaniint create_persona_path(char path[PKG_PATH_MAX], 1050b285499db739ba50f2f839d633e763c70e67f96Amith Yamasani uid_t persona) 1060b285499db739ba50f2f839d633e763c70e67f96Amith Yamasani{ 1070b285499db739ba50f2f839d633e763c70e67f96Amith Yamasani size_t uid_len; 1080b285499db739ba50f2f839d633e763c70e67f96Amith Yamasani char* persona_prefix; 1090b285499db739ba50f2f839d633e763c70e67f96Amith Yamasani if (persona == 0) { 1100b285499db739ba50f2f839d633e763c70e67f96Amith Yamasani persona_prefix = PRIMARY_USER_PREFIX; 1110b285499db739ba50f2f839d633e763c70e67f96Amith Yamasani uid_len = 0; 1120b285499db739ba50f2f839d633e763c70e67f96Amith Yamasani } else { 1130b285499db739ba50f2f839d633e763c70e67f96Amith Yamasani persona_prefix = SECONDARY_USER_PREFIX; 114ad757e9b36d6bc6b8e39be00612d0e60863aaafcKenny Root uid_len = snprintf(NULL, 0, "%d/", persona); 1150b285499db739ba50f2f839d633e763c70e67f96Amith Yamasani } 1160b285499db739ba50f2f839d633e763c70e67f96Amith Yamasani 1170b285499db739ba50f2f839d633e763c70e67f96Amith Yamasani char *dst = path; 1180b285499db739ba50f2f839d633e763c70e67f96Amith Yamasani size_t dst_size = PKG_PATH_MAX; 1190b285499db739ba50f2f839d633e763c70e67f96Amith Yamasani 1200b285499db739ba50f2f839d633e763c70e67f96Amith Yamasani if (append_and_increment(&dst, android_data_dir.path, &dst_size) < 0 1210b285499db739ba50f2f839d633e763c70e67f96Amith Yamasani || append_and_increment(&dst, persona_prefix, &dst_size) < 0) { 1223762c311729fe9f3af085c14c5c1fb471d994c03Steve Block ALOGE("Error building prefix for user path"); 1230b285499db739ba50f2f839d633e763c70e67f96Amith Yamasani return -1; 1240b285499db739ba50f2f839d633e763c70e67f96Amith Yamasani } 1250b285499db739ba50f2f839d633e763c70e67f96Amith Yamasani 1260b285499db739ba50f2f839d633e763c70e67f96Amith Yamasani if (persona != 0) { 1270b285499db739ba50f2f839d633e763c70e67f96Amith Yamasani if (dst_size < uid_len + 1) { 1283762c311729fe9f3af085c14c5c1fb471d994c03Steve Block ALOGE("Error building user path"); 1290b285499db739ba50f2f839d633e763c70e67f96Amith Yamasani return -1; 1300b285499db739ba50f2f839d633e763c70e67f96Amith Yamasani } 131ad757e9b36d6bc6b8e39be00612d0e60863aaafcKenny Root int ret = snprintf(dst, dst_size, "%d/", persona); 1320b285499db739ba50f2f839d633e763c70e67f96Amith Yamasani if (ret < 0 || (size_t) ret != uid_len) { 1333762c311729fe9f3af085c14c5c1fb471d994c03Steve Block ALOGE("Error appending persona id to path"); 1340b285499db739ba50f2f839d633e763c70e67f96Amith Yamasani return -1; 1350b285499db739ba50f2f839d633e763c70e67f96Amith Yamasani } 1360b285499db739ba50f2f839d633e763c70e67f96Amith Yamasani } 1370b285499db739ba50f2f839d633e763c70e67f96Amith Yamasani return 0; 1380b285499db739ba50f2f839d633e763c70e67f96Amith Yamasani} 1390b285499db739ba50f2f839d633e763c70e67f96Amith Yamasani 1405b1ada2562c17921adf6a62ea62bcb445160983cJeff Sharkey/** 1415b1ada2562c17921adf6a62ea62bcb445160983cJeff Sharkey * Create the path name for media for a certain persona. 1425b1ada2562c17921adf6a62ea62bcb445160983cJeff Sharkey * Returns 0 on success, and -1 on failure. 1435b1ada2562c17921adf6a62ea62bcb445160983cJeff Sharkey */ 1445b1ada2562c17921adf6a62ea62bcb445160983cJeff Sharkeyint create_persona_media_path(char path[PATH_MAX], userid_t userid) { 1455b1ada2562c17921adf6a62ea62bcb445160983cJeff Sharkey if (snprintf(path, PATH_MAX, "%s%d", android_media_dir.path, userid) > PATH_MAX) { 1465b1ada2562c17921adf6a62ea62bcb445160983cJeff Sharkey return -1; 1475b1ada2562c17921adf6a62ea62bcb445160983cJeff Sharkey } 1485b1ada2562c17921adf6a62ea62bcb445160983cJeff Sharkey return 0; 1495b1ada2562c17921adf6a62ea62bcb445160983cJeff Sharkey} 1505b1ada2562c17921adf6a62ea62bcb445160983cJeff Sharkey 151ad757e9b36d6bc6b8e39be00612d0e60863aaafcKenny Rootint create_move_path(char path[PKG_PATH_MAX], 152ad757e9b36d6bc6b8e39be00612d0e60863aaafcKenny Root const char* pkgname, 153ad757e9b36d6bc6b8e39be00612d0e60863aaafcKenny Root const char* leaf, 154ad757e9b36d6bc6b8e39be00612d0e60863aaafcKenny Root uid_t persona) 155ad757e9b36d6bc6b8e39be00612d0e60863aaafcKenny Root{ 156ad757e9b36d6bc6b8e39be00612d0e60863aaafcKenny Root if ((android_data_dir.len + strlen(PRIMARY_USER_PREFIX) + strlen(pkgname) + strlen(leaf) + 1) 157ad757e9b36d6bc6b8e39be00612d0e60863aaafcKenny Root >= PKG_PATH_MAX) { 158ad757e9b36d6bc6b8e39be00612d0e60863aaafcKenny Root return -1; 159ad757e9b36d6bc6b8e39be00612d0e60863aaafcKenny Root } 160ad757e9b36d6bc6b8e39be00612d0e60863aaafcKenny Root 161ad757e9b36d6bc6b8e39be00612d0e60863aaafcKenny Root sprintf(path, "%s%s%s/%s", android_data_dir.path, PRIMARY_USER_PREFIX, pkgname, leaf); 162ad757e9b36d6bc6b8e39be00612d0e60863aaafcKenny Root return 0; 163ad757e9b36d6bc6b8e39be00612d0e60863aaafcKenny Root} 164ad757e9b36d6bc6b8e39be00612d0e60863aaafcKenny Root 1650b285499db739ba50f2f839d633e763c70e67f96Amith Yamasani/** 16686c9584559439504fc57ece2ccd9b6cbd568430cKenny Root * Checks whether the package name is valid. Returns -1 on error and 16786c9584559439504fc57ece2ccd9b6cbd568430cKenny Root * 0 on success. 16886c9584559439504fc57ece2ccd9b6cbd568430cKenny Root */ 16986c9584559439504fc57ece2ccd9b6cbd568430cKenny Rootint is_valid_package_name(const char* pkgname) { 17086c9584559439504fc57ece2ccd9b6cbd568430cKenny Root const char *x = pkgname; 171c028be4f3b8c7476b46859f66c3f33d528adf181Suchi Amalapurapu int alpha = -1; 17286c9584559439504fc57ece2ccd9b6cbd568430cKenny Root 1739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project while (*x) { 1749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (isalnum(*x) || (*x == '_')) { 1759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /* alphanumeric or underscore are fine */ 1769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else if (*x == '.') { 1779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if ((x == pkgname) || (x[1] == '.') || (x[1] == 0)) { 1789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /* periods must not be first, last, or doubled */ 1793762c311729fe9f3af085c14c5c1fb471d994c03Steve Block ALOGE("invalid package name '%s'\n", pkgname); 1809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return -1; 1819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 182c028be4f3b8c7476b46859f66c3f33d528adf181Suchi Amalapurapu } else if (*x == '-') { 183c028be4f3b8c7476b46859f66c3f33d528adf181Suchi Amalapurapu /* Suffix -X is fine to let versioning of packages. 184c028be4f3b8c7476b46859f66c3f33d528adf181Suchi Amalapurapu But whatever follows should be alphanumeric.*/ 185c028be4f3b8c7476b46859f66c3f33d528adf181Suchi Amalapurapu alpha = 1; 18686c9584559439504fc57ece2ccd9b6cbd568430cKenny Root } else { 1879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /* anything not A-Z, a-z, 0-9, _, or . is invalid */ 1883762c311729fe9f3af085c14c5c1fb471d994c03Steve Block ALOGE("invalid package name '%s'\n", pkgname); 1899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return -1; 1909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 19186c9584559439504fc57ece2ccd9b6cbd568430cKenny Root 1929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project x++; 1939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 19486c9584559439504fc57ece2ccd9b6cbd568430cKenny Root 195c028be4f3b8c7476b46859f66c3f33d528adf181Suchi Amalapurapu if (alpha == 1) { 196c028be4f3b8c7476b46859f66c3f33d528adf181Suchi Amalapurapu // Skip current character 197c028be4f3b8c7476b46859f66c3f33d528adf181Suchi Amalapurapu x++; 198c028be4f3b8c7476b46859f66c3f33d528adf181Suchi Amalapurapu while (*x) { 199c028be4f3b8c7476b46859f66c3f33d528adf181Suchi Amalapurapu if (!isalnum(*x)) { 2003762c311729fe9f3af085c14c5c1fb471d994c03Steve Block ALOGE("invalid package name '%s' should include only numbers after -\n", pkgname); 201c028be4f3b8c7476b46859f66c3f33d528adf181Suchi Amalapurapu return -1; 202c028be4f3b8c7476b46859f66c3f33d528adf181Suchi Amalapurapu } 203c028be4f3b8c7476b46859f66c3f33d528adf181Suchi Amalapurapu x++; 204c028be4f3b8c7476b46859f66c3f33d528adf181Suchi Amalapurapu } 205c028be4f3b8c7476b46859f66c3f33d528adf181Suchi Amalapurapu } 2069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return 0; 2089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 2099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic int _delete_dir_contents(DIR *d, const char *ignore) 2119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 2129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int result = 0; 2139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project struct dirent *de; 2149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int dfd; 2159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project dfd = dirfd(d); 2179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (dfd < 0) return -1; 2199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project while ((de = readdir(d))) { 2219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project const char *name = de->d_name; 2229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /* skip the ignore name if provided */ 2249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (ignore && !strcmp(name, ignore)) continue; 2259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (de->d_type == DT_DIR) { 2279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int r, subfd; 2289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project DIR *subdir; 2299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /* always skip "." and ".." */ 2319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (name[0] == '.') { 2329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (name[1] == 0) continue; 2339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if ((name[1] == '.') && (name[2] == 0)) continue; 2349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project subfd = openat(dfd, name, O_RDONLY | O_DIRECTORY); 2379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (subfd < 0) { 2383762c311729fe9f3af085c14c5c1fb471d994c03Steve Block ALOGE("Couldn't openat %s: %s\n", name, strerror(errno)); 2399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project result = -1; 2409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project continue; 2419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project subdir = fdopendir(subfd); 2439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (subdir == NULL) { 2443762c311729fe9f3af085c14c5c1fb471d994c03Steve Block ALOGE("Couldn't fdopendir %s: %s\n", name, strerror(errno)); 2459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project close(subfd); 2469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project result = -1; 2479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project continue; 2489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (_delete_dir_contents(subdir, 0)) { 2509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project result = -1; 2519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project closedir(subdir); 2539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (unlinkat(dfd, name, AT_REMOVEDIR) < 0) { 2543762c311729fe9f3af085c14c5c1fb471d994c03Steve Block ALOGE("Couldn't unlinkat %s: %s\n", name, strerror(errno)); 2559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project result = -1; 2569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 2589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (unlinkat(dfd, name, 0) < 0) { 2593762c311729fe9f3af085c14c5c1fb471d994c03Steve Block ALOGE("Couldn't unlinkat %s: %s\n", name, strerror(errno)); 2609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project result = -1; 2619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return result; 2669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 2679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectint delete_dir_contents(const char *pathname, 2699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int also_delete_dir, 2709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project const char *ignore) 2719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 2729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int res = 0; 2739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project DIR *d; 2749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project d = opendir(pathname); 2769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (d == NULL) { 2773762c311729fe9f3af085c14c5c1fb471d994c03Steve Block ALOGE("Couldn't opendir %s: %s\n", pathname, strerror(errno)); 2789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return -errno; 2799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project res = _delete_dir_contents(d, ignore); 2819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project closedir(d); 2829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (also_delete_dir) { 2839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (rmdir(pathname)) { 2843762c311729fe9f3af085c14c5c1fb471d994c03Steve Block ALOGE("Couldn't rmdir %s: %s\n", pathname, strerror(errno)); 2859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project res = -1; 2869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return res; 2899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 2909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectint delete_dir_contents_fd(int dfd, const char *name) 2929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 2939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int fd, res; 2949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project DIR *d; 2959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project fd = openat(dfd, name, O_RDONLY | O_DIRECTORY); 2979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (fd < 0) { 2983762c311729fe9f3af085c14c5c1fb471d994c03Steve Block ALOGE("Couldn't openat %s: %s\n", name, strerror(errno)); 2999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return -1; 3009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project d = fdopendir(fd); 3029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (d == NULL) { 3033762c311729fe9f3af085c14c5c1fb471d994c03Steve Block ALOGE("Couldn't fdopendir %s: %s\n", name, strerror(errno)); 3049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project close(fd); 3059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return -1; 3069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project res = _delete_dir_contents(d, 0); 3089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project closedir(d); 3099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return res; 3109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 31186c9584559439504fc57ece2ccd9b6cbd568430cKenny Root 312197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackbornint lookup_media_dir(char basepath[PATH_MAX], const char *dir) 313197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn{ 314197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn DIR *d; 315197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn struct dirent *de; 316197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn struct stat s; 317197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn char* dirpos = basepath + strlen(basepath); 318197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn 319197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn if ((*(dirpos-1)) != '/') { 320197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn *dirpos = '/'; 321197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn dirpos++; 322197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn } 323197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn 324197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn CACHE_NOISY(ALOGI("Looking up %s in %s\n", dir, basepath)); 325197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn // Verify the path won't extend beyond our buffer, to avoid 326197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn // repeated checking later. 327197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn if ((dirpos-basepath+strlen(dir)) >= (PATH_MAX-1)) { 328197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn ALOGW("Path exceeds limit: %s%s", basepath, dir); 329197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn return -1; 330197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn } 331197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn 332197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn // First, can we find this directory with the case that is given? 333197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn strcpy(dirpos, dir); 334197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn if (stat(basepath, &s) >= 0) { 335197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn CACHE_NOISY(ALOGI("Found direct: %s\n", basepath)); 336197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn return 0; 337197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn } 338197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn 339197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn // Not found with that case... search through all entries to find 340197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn // one that matches regardless of case. 341197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn *dirpos = 0; 342197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn 343197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn d = opendir(basepath); 344197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn if (d == NULL) { 345197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn return -1; 346197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn } 347197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn 348197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn while ((de = readdir(d))) { 349197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn if (strcasecmp(de->d_name, dir) == 0) { 350197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn strcpy(dirpos, de->d_name); 351197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn closedir(d); 352197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn CACHE_NOISY(ALOGI("Found search: %s\n", basepath)); 353197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn return 0; 354197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn } 355197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn } 356197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn 357197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn ALOGW("Couldn't find %s in %s", dir, basepath); 358197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn closedir(d); 359197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn return -1; 360197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn} 361197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn 362197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackbornint64_t data_disk_free() 363197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn{ 364197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn struct statfs sfs; 365197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn if (statfs(android_data_dir.path, &sfs) == 0) { 366197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn return sfs.f_bavail * sfs.f_bsize; 367197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn } else { 368197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn ALOGE("Couldn't statfs %s: %s\n", android_data_dir.path, strerror(errno)); 369197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn return -1; 370197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn } 371197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn} 372197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn 373197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborncache_t* start_cache_collection() 374197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn{ 375197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn cache_t* cache = (cache_t*)calloc(1, sizeof(cache_t)); 376197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn return cache; 377197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn} 378197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn 379197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn#define CACHE_BLOCK_SIZE (512*1024) 380197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn 381197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackbornstatic void* _cache_malloc(cache_t* cache, size_t len) 382197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn{ 383197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn len = (len+3)&~3; 384197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn if (len > (CACHE_BLOCK_SIZE/2)) { 385197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn // It doesn't make sense to try to put this allocation into one 386197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn // of our blocks, because it is so big. Instead, make a new dedicated 387197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn // block for it. 388197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn int8_t* res = (int8_t*)malloc(len+sizeof(void*)); 389197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn if (res == NULL) { 390197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn return NULL; 391197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn } 392197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn CACHE_NOISY(ALOGI("Allocated large cache mem block: %p size %d", res, len)); 393197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn // Link it into our list of blocks, not disrupting the current one. 394197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn if (cache->memBlocks == NULL) { 395197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn *(void**)res = NULL; 396197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn cache->memBlocks = res; 397197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn } else { 398197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn *(void**)res = *(void**)cache->memBlocks; 399197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn *(void**)cache->memBlocks = res; 400197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn } 401197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn return res + sizeof(void*); 402197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn } 403197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn int8_t* res = cache->curMemBlockAvail; 404197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn int8_t* nextPos = res + len; 405197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn if (cache->memBlocks == NULL || nextPos > cache->curMemBlockEnd) { 406197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn int8_t* newBlock = malloc(CACHE_BLOCK_SIZE); 407197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn if (newBlock == NULL) { 408197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn return NULL; 409197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn } 410197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn CACHE_NOISY(ALOGI("Allocated new cache mem block: %p", newBlock)); 411197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn *(void**)newBlock = cache->memBlocks; 412197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn cache->memBlocks = newBlock; 413197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn res = cache->curMemBlockAvail = newBlock + sizeof(void*); 414197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn cache->curMemBlockEnd = newBlock + CACHE_BLOCK_SIZE; 415197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn nextPos = res + len; 416197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn } 417197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn CACHE_NOISY(ALOGI("cache_malloc: ret %p size %d, block=%p, nextPos=%p", 418197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn res, len, cache->memBlocks, nextPos)); 419197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn cache->curMemBlockAvail = nextPos; 420197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn return res; 421197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn} 422197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn 423197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackbornstatic void* _cache_realloc(cache_t* cache, void* cur, size_t origLen, size_t len) 424197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn{ 425197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn // This isn't really a realloc, but it is good enough for our purposes here. 426197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn void* alloc = _cache_malloc(cache, len); 427197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn if (alloc != NULL && cur != NULL) { 428197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn memcpy(alloc, cur, origLen < len ? origLen : len); 429197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn } 430197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn return alloc; 431197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn} 432197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn 433197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackbornstatic void _inc_num_cache_collected(cache_t* cache) 434197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn{ 435197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn cache->numCollected++; 436197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn if ((cache->numCollected%20000) == 0) { 437197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn ALOGI("Collected cache so far: %d directories, %d files", 438197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn cache->numDirs, cache->numFiles); 439197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn } 440197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn} 441197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn 442197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackbornstatic cache_dir_t* _add_cache_dir_t(cache_t* cache, cache_dir_t* parent, const char *name) 443197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn{ 444197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn size_t nameLen = strlen(name); 445197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn cache_dir_t* dir = (cache_dir_t*)_cache_malloc(cache, sizeof(cache_dir_t)+nameLen+1); 446197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn if (dir != NULL) { 447197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn dir->parent = parent; 448197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn dir->childCount = 0; 449197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn dir->hiddenCount = 0; 450197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn dir->deleted = 0; 451197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn strcpy(dir->name, name); 452197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn if (cache->numDirs >= cache->availDirs) { 453197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn size_t newAvail = cache->availDirs < 1000 ? 1000 : cache->availDirs*2; 454197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn cache_dir_t** newDirs = (cache_dir_t**)_cache_realloc(cache, cache->dirs, 455197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn cache->availDirs*sizeof(cache_dir_t*), newAvail*sizeof(cache_dir_t*)); 456197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn if (newDirs == NULL) { 457197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn ALOGE("Failure growing cache dirs array for %s\n", name); 458197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn return NULL; 459197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn } 460197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn cache->availDirs = newAvail; 461197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn cache->dirs = newDirs; 462197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn } 463197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn cache->dirs[cache->numDirs] = dir; 464197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn cache->numDirs++; 465197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn if (parent != NULL) { 466197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn parent->childCount++; 467197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn } 468197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn _inc_num_cache_collected(cache); 469197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn } else { 470197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn ALOGE("Failure allocating cache_dir_t for %s\n", name); 471197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn } 472197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn return dir; 473197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn} 474197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn 475197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackbornstatic cache_file_t* _add_cache_file_t(cache_t* cache, cache_dir_t* dir, time_t modTime, 476197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn const char *name) 477197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn{ 478197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn size_t nameLen = strlen(name); 479197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn cache_file_t* file = (cache_file_t*)_cache_malloc(cache, sizeof(cache_file_t)+nameLen+1); 480197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn if (file != NULL) { 481197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn file->dir = dir; 482197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn file->modTime = modTime; 483197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn strcpy(file->name, name); 484197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn if (cache->numFiles >= cache->availFiles) { 485197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn size_t newAvail = cache->availFiles < 1000 ? 1000 : cache->availFiles*2; 486197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn cache_file_t** newFiles = (cache_file_t**)_cache_realloc(cache, cache->files, 487197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn cache->availFiles*sizeof(cache_file_t*), newAvail*sizeof(cache_file_t*)); 488197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn if (newFiles == NULL) { 489197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn ALOGE("Failure growing cache file array for %s\n", name); 490197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn return NULL; 491197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn } 492197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn cache->availFiles = newAvail; 493197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn cache->files = newFiles; 494197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn } 495197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn CACHE_NOISY(ALOGI("Setting file %p at position %d in array %p", file, 496197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn cache->numFiles, cache->files)); 497197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn cache->files[cache->numFiles] = file; 498197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn cache->numFiles++; 499197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn dir->childCount++; 500197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn _inc_num_cache_collected(cache); 501197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn } else { 502197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn ALOGE("Failure allocating cache_file_t for %s\n", name); 503197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn } 504197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn return file; 505197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn} 506197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn 507197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackbornstatic int _add_cache_files(cache_t *cache, cache_dir_t *parentDir, const char *dirName, 508197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn DIR* dir, char *pathBase, char *pathPos, size_t pathAvailLen) 509197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn{ 510197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn struct dirent *de; 511197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn cache_dir_t* cacheDir = NULL; 512197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn int dfd; 513197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn 514197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn CACHE_NOISY(ALOGI("_add_cache_files: parent=%p dirName=%s dir=%p pathBase=%s", 515197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn parentDir, dirName, dir, pathBase)); 516197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn 517197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn dfd = dirfd(dir); 518197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn 519197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn if (dfd < 0) return 0; 520197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn 521197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn // Sub-directories always get added to the data structure, so if they 522197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn // are empty we will know about them to delete them later. 523197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn cacheDir = _add_cache_dir_t(cache, parentDir, dirName); 524197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn 525197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn while ((de = readdir(dir))) { 526197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn const char *name = de->d_name; 527197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn 528197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn if (de->d_type == DT_DIR) { 529197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn int subfd; 530197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn DIR *subdir; 531197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn 532197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn /* always skip "." and ".." */ 533197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn if (name[0] == '.') { 534197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn if (name[1] == 0) continue; 535197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn if ((name[1] == '.') && (name[2] == 0)) continue; 536197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn } 537197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn 538197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn subfd = openat(dfd, name, O_RDONLY | O_DIRECTORY); 539197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn if (subfd < 0) { 540197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn ALOGE("Couldn't openat %s: %s\n", name, strerror(errno)); 541197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn continue; 542197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn } 543197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn subdir = fdopendir(subfd); 544197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn if (subdir == NULL) { 545197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn ALOGE("Couldn't fdopendir %s: %s\n", name, strerror(errno)); 546197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn close(subfd); 547197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn continue; 548197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn } 549197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn if (cacheDir == NULL) { 550197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn cacheDir = _add_cache_dir_t(cache, parentDir, dirName); 551197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn } 552197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn if (cacheDir != NULL) { 553197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn // Update pathBase for the new path... this may change dirName 554197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn // if that is also pointing to the path, but we are done with it 555197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn // now. 556197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn size_t finallen = snprintf(pathPos, pathAvailLen, "/%s", name); 557197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn CACHE_NOISY(ALOGI("Collecting dir %s\n", pathBase)); 558197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn if (finallen < pathAvailLen) { 559197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn _add_cache_files(cache, cacheDir, name, subdir, pathBase, 560197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn pathPos+finallen, pathAvailLen-finallen); 561197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn } else { 562197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn // Whoops, the final path is too long! We'll just delete 563197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn // this directory. 564197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn ALOGW("Cache dir %s truncated in path %s; deleting dir\n", 565197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn name, pathBase); 566197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn _delete_dir_contents(subdir, NULL); 567197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn if (unlinkat(dfd, name, AT_REMOVEDIR) < 0) { 568197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn ALOGE("Couldn't unlinkat %s: %s\n", name, strerror(errno)); 569197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn } 570197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn } 571197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn } 572197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn closedir(subdir); 573197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn } else if (de->d_type == DT_REG) { 574197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn // Skip files that start with '.'; they will be deleted if 575197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn // their entire directory is deleted. This allows for metadata 576197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn // like ".nomedia" to remain in the directory until the entire 577197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn // directory is deleted. 578197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn if (cacheDir == NULL) { 579197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn cacheDir = _add_cache_dir_t(cache, parentDir, dirName); 580197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn } 581197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn if (name[0] == '.') { 582197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn cacheDir->hiddenCount++; 583197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn continue; 584197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn } 585197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn if (cacheDir != NULL) { 586197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn // Build final full path for file... this may change dirName 587197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn // if that is also pointing to the path, but we are done with it 588197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn // now. 589197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn size_t finallen = snprintf(pathPos, pathAvailLen, "/%s", name); 590197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn CACHE_NOISY(ALOGI("Collecting file %s\n", pathBase)); 591197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn if (finallen < pathAvailLen) { 592197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn struct stat s; 593197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn if (stat(pathBase, &s) >= 0) { 594197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn _add_cache_file_t(cache, cacheDir, s.st_mtime, name); 595197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn } else { 596197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn ALOGW("Unable to stat cache file %s; deleting\n", pathBase); 597197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn if (unlink(pathBase) < 0) { 598197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn ALOGE("Couldn't unlink %s: %s\n", pathBase, strerror(errno)); 599197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn } 600197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn } 601197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn } else { 602197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn // Whoops, the final path is too long! We'll just delete 603197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn // this file. 604197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn ALOGW("Cache file %s truncated in path %s; deleting\n", 605197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn name, pathBase); 606197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn if (unlinkat(dfd, name, 0) < 0) { 607197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn *pathPos = 0; 608197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn ALOGE("Couldn't unlinkat %s in %s: %s\n", name, pathBase, 609197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn strerror(errno)); 610197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn } 611197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn } 612197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn } 613197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn } else { 614197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn cacheDir->hiddenCount++; 615197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn } 616197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn } 617197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn return 0; 618197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn} 619197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn 620197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackbornvoid add_cache_files(cache_t* cache, const char *basepath, const char *cachedir) 621197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn{ 622197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn DIR *d; 623197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn struct dirent *de; 624197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn char dirname[PATH_MAX]; 625197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn 626197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn CACHE_NOISY(ALOGI("add_cache_files: base=%s cachedir=%s\n", basepath, cachedir)); 627197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn 628197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn d = opendir(basepath); 629197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn if (d == NULL) { 630197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn return; 631197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn } 632197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn 633197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn while ((de = readdir(d))) { 634197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn if (de->d_type == DT_DIR) { 635197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn DIR* subdir; 636197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn const char *name = de->d_name; 637197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn char* pathpos; 638197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn 639197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn /* always skip "." and ".." */ 640197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn if (name[0] == '.') { 641197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn if (name[1] == 0) continue; 642197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn if ((name[1] == '.') && (name[2] == 0)) continue; 643197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn } 644197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn 645197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn strcpy(dirname, basepath); 646197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn pathpos = dirname + strlen(dirname); 647197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn if ((*(pathpos-1)) != '/') { 648197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn *pathpos = '/'; 649197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn pathpos++; 650197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn *pathpos = 0; 651197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn } 652197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn if (cachedir != NULL) { 653197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn snprintf(pathpos, sizeof(dirname)-(pathpos-dirname), "%s/%s", name, cachedir); 654197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn } else { 655197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn snprintf(pathpos, sizeof(dirname)-(pathpos-dirname), "%s", name); 656197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn } 657197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn CACHE_NOISY(ALOGI("Adding cache files from dir: %s\n", dirname)); 658197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn subdir = opendir(dirname); 659197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn if (subdir != NULL) { 660197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn size_t dirnameLen = strlen(dirname); 661197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn _add_cache_files(cache, NULL, dirname, subdir, dirname, dirname+dirnameLen, 662197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn PATH_MAX - dirnameLen); 663197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn closedir(subdir); 664197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn } 665197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn } 666197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn } 667197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn 668197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn closedir(d); 669197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn} 670197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn 671197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackbornstatic char *create_dir_path(char path[PATH_MAX], cache_dir_t* dir) 672197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn{ 673197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn char *pos = path; 674197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn if (dir->parent != NULL) { 675197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn pos = create_dir_path(path, dir->parent); 676197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn } 677197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn // Note that we don't need to worry about going beyond the buffer, 678197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn // since when we were constructing the cache entries our maximum 679197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn // buffer size for full paths was PATH_MAX. 680197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn strcpy(pos, dir->name); 681197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn pos += strlen(pos); 682197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn *pos = '/'; 683197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn pos++; 684197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn *pos = 0; 685197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn return pos; 686197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn} 687197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn 688197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackbornstatic void delete_cache_dir(char path[PATH_MAX], cache_dir_t* dir) 689197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn{ 690197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn if (dir->parent != NULL) { 691197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn create_dir_path(path, dir); 692197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn ALOGI("DEL DIR %s\n", path); 693197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn if (dir->hiddenCount <= 0) { 694197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn if (rmdir(path)) { 695197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn ALOGE("Couldn't rmdir %s: %s\n", path, strerror(errno)); 696197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn return; 697197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn } 698197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn } else { 699197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn // The directory contains hidden files so we need to delete 700197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn // them along with the directory itself. 701197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn if (delete_dir_contents(path, 1, NULL)) { 702197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn return; 703197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn } 704197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn } 705197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn dir->parent->childCount--; 706197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn dir->deleted = 1; 707197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn if (dir->parent->childCount <= 0) { 708197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn delete_cache_dir(path, dir->parent); 709197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn } 710197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn } else if (dir->hiddenCount > 0) { 711197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn // This is a root directory, but it has hidden files. Get rid of 712197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn // all of those files, but not the directory itself. 713197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn create_dir_path(path, dir); 714197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn ALOGI("DEL CONTENTS %s\n", path); 715197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn delete_dir_contents(path, 0, NULL); 716197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn } 717197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn} 718197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn 719197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackbornstatic int cache_modtime_sort(const void *lhsP, const void *rhsP) 720197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn{ 721197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn const cache_file_t *lhs = *(const cache_file_t**)lhsP; 722197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn const cache_file_t *rhs = *(const cache_file_t**)rhsP; 723197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn return lhs->modTime < rhs->modTime ? -1 : (lhs->modTime > rhs->modTime ? 1 : 0); 724197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn} 725197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn 726197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackbornvoid clear_cache_files(cache_t* cache, int64_t free_size) 727197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn{ 728197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn size_t i; 729197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn int skip = 0; 730197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn char path[PATH_MAX]; 731197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn 732197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn ALOGI("Collected cache files: %d directories, %d files", 733197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn cache->numDirs, cache->numFiles); 734197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn 735197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn CACHE_NOISY(ALOGI("Sorting files...")); 736197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn qsort(cache->files, cache->numFiles, sizeof(cache_file_t*), 737197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn cache_modtime_sort); 738197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn 739197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn CACHE_NOISY(ALOGI("Cleaning empty directories...")); 740197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn for (i=cache->numDirs; i>0; i--) { 741197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn cache_dir_t* dir = cache->dirs[i-1]; 742197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn if (dir->childCount <= 0 && !dir->deleted) { 743197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn delete_cache_dir(path, dir); 744197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn } 745197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn } 746197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn 747197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn CACHE_NOISY(ALOGI("Trimming files...")); 748197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn for (i=0; i<cache->numFiles; i++) { 749197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn skip++; 750197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn if (skip > 10) { 751197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn if (data_disk_free() > free_size) { 752197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn return; 753197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn } 754197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn skip = 0; 755197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn } 756197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn cache_file_t* file = cache->files[i]; 757197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn strcpy(create_dir_path(path, file->dir), file->name); 758197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn ALOGI("DEL (mod %d) %s\n", (int)file->modTime, path); 759197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn if (unlink(path) < 0) { 760197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn ALOGE("Couldn't unlink %s: %s\n", path, strerror(errno)); 761197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn } 762197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn file->dir->childCount--; 763197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn if (file->dir->childCount <= 0) { 764197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn delete_cache_dir(path, file->dir); 765197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn } 766197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn } 767197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn} 768197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn 769197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackbornvoid finish_cache_collection(cache_t* cache) 770197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn{ 771197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn size_t i; 772197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn 773197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn CACHE_NOISY(ALOGI("clear_cache_files: %d dirs, %d files\n", cache->numDirs, cache->numFiles)); 774197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn CACHE_NOISY( 775197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn for (i=0; i<cache->numDirs; i++) { 776197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn cache_dir_t* dir = cache->dirs[i]; 777197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn ALOGI("dir #%d: %p %s parent=%p\n", i, dir, dir->name, dir->parent); 778197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn }) 779197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn CACHE_NOISY( 780197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn for (i=0; i<cache->numFiles; i++) { 781197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn cache_file_t* file = cache->files[i]; 782197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn ALOGI("file #%d: %p %s time=%d dir=%p\n", i, file, file->name, 783197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn (int)file->modTime, file->dir); 784197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn }) 785197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn void* block = cache->memBlocks; 786197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn while (block != NULL) { 787197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn void* nextBlock = *(void**)block; 788197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn CACHE_NOISY(ALOGI("Freeing cache mem block: %p", block)); 789197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn free(block); 790197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn block = nextBlock; 791197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn } 792197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn free(cache); 793197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn} 794197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn 79586c9584559439504fc57ece2ccd9b6cbd568430cKenny Root/** 79686c9584559439504fc57ece2ccd9b6cbd568430cKenny Root * Checks whether a path points to a system app (.apk file). Returns 0 79786c9584559439504fc57ece2ccd9b6cbd568430cKenny Root * if it is a system app or -1 if it is not. 79886c9584559439504fc57ece2ccd9b6cbd568430cKenny Root */ 79986c9584559439504fc57ece2ccd9b6cbd568430cKenny Rootint validate_system_app_path(const char* path) { 80086c9584559439504fc57ece2ccd9b6cbd568430cKenny Root size_t i; 80186c9584559439504fc57ece2ccd9b6cbd568430cKenny Root 80286c9584559439504fc57ece2ccd9b6cbd568430cKenny Root for (i = 0; i < android_system_dirs.count; i++) { 80386c9584559439504fc57ece2ccd9b6cbd568430cKenny Root const size_t dir_len = android_system_dirs.dirs[i].len; 80486c9584559439504fc57ece2ccd9b6cbd568430cKenny Root if (!strncmp(path, android_system_dirs.dirs[i].path, dir_len)) { 80586c9584559439504fc57ece2ccd9b6cbd568430cKenny Root if (path[dir_len] == '.' || strchr(path + dir_len, '/') != NULL) { 8063762c311729fe9f3af085c14c5c1fb471d994c03Steve Block ALOGE("invalid system apk path '%s' (trickery)\n", path); 80786c9584559439504fc57ece2ccd9b6cbd568430cKenny Root return -1; 80886c9584559439504fc57ece2ccd9b6cbd568430cKenny Root } 80986c9584559439504fc57ece2ccd9b6cbd568430cKenny Root return 0; 81086c9584559439504fc57ece2ccd9b6cbd568430cKenny Root } 81186c9584559439504fc57ece2ccd9b6cbd568430cKenny Root } 81286c9584559439504fc57ece2ccd9b6cbd568430cKenny Root 81386c9584559439504fc57ece2ccd9b6cbd568430cKenny Root return -1; 81486c9584559439504fc57ece2ccd9b6cbd568430cKenny Root} 81586c9584559439504fc57ece2ccd9b6cbd568430cKenny Root 81686c9584559439504fc57ece2ccd9b6cbd568430cKenny Root/** 81786c9584559439504fc57ece2ccd9b6cbd568430cKenny Root * Get the contents of a environment variable that contains a path. Caller 81886c9584559439504fc57ece2ccd9b6cbd568430cKenny Root * owns the string that is inserted into the directory record. Returns 81986c9584559439504fc57ece2ccd9b6cbd568430cKenny Root * 0 on success and -1 on error. 82086c9584559439504fc57ece2ccd9b6cbd568430cKenny Root */ 82186c9584559439504fc57ece2ccd9b6cbd568430cKenny Rootint get_path_from_env(dir_rec_t* rec, const char* var) { 82286c9584559439504fc57ece2ccd9b6cbd568430cKenny Root const char* path = getenv(var); 82386c9584559439504fc57ece2ccd9b6cbd568430cKenny Root int ret = get_path_from_string(rec, path); 82486c9584559439504fc57ece2ccd9b6cbd568430cKenny Root if (ret < 0) { 8258564c8da817a845353d213acd8636b76f567b234Steve Block ALOGW("Problem finding value for environment variable %s\n", var); 82686c9584559439504fc57ece2ccd9b6cbd568430cKenny Root } 82786c9584559439504fc57ece2ccd9b6cbd568430cKenny Root return ret; 82886c9584559439504fc57ece2ccd9b6cbd568430cKenny Root} 82986c9584559439504fc57ece2ccd9b6cbd568430cKenny Root 83086c9584559439504fc57ece2ccd9b6cbd568430cKenny Root/** 83186c9584559439504fc57ece2ccd9b6cbd568430cKenny Root * Puts the string into the record as a directory. Appends '/' to the end 83286c9584559439504fc57ece2ccd9b6cbd568430cKenny Root * of all paths. Caller owns the string that is inserted into the directory 83386c9584559439504fc57ece2ccd9b6cbd568430cKenny Root * record. A null value will result in an error. 83486c9584559439504fc57ece2ccd9b6cbd568430cKenny Root * 83586c9584559439504fc57ece2ccd9b6cbd568430cKenny Root * Returns 0 on success and -1 on error. 83686c9584559439504fc57ece2ccd9b6cbd568430cKenny Root */ 83786c9584559439504fc57ece2ccd9b6cbd568430cKenny Rootint get_path_from_string(dir_rec_t* rec, const char* path) { 83886c9584559439504fc57ece2ccd9b6cbd568430cKenny Root if (path == NULL) { 83986c9584559439504fc57ece2ccd9b6cbd568430cKenny Root return -1; 84086c9584559439504fc57ece2ccd9b6cbd568430cKenny Root } else { 84186c9584559439504fc57ece2ccd9b6cbd568430cKenny Root const size_t path_len = strlen(path); 84286c9584559439504fc57ece2ccd9b6cbd568430cKenny Root if (path_len <= 0) { 84386c9584559439504fc57ece2ccd9b6cbd568430cKenny Root return -1; 84486c9584559439504fc57ece2ccd9b6cbd568430cKenny Root } 84586c9584559439504fc57ece2ccd9b6cbd568430cKenny Root 84686c9584559439504fc57ece2ccd9b6cbd568430cKenny Root // Make sure path is absolute. 84786c9584559439504fc57ece2ccd9b6cbd568430cKenny Root if (path[0] != '/') { 84886c9584559439504fc57ece2ccd9b6cbd568430cKenny Root return -1; 84986c9584559439504fc57ece2ccd9b6cbd568430cKenny Root } 85086c9584559439504fc57ece2ccd9b6cbd568430cKenny Root 85186c9584559439504fc57ece2ccd9b6cbd568430cKenny Root if (path[path_len - 1] == '/') { 85286c9584559439504fc57ece2ccd9b6cbd568430cKenny Root // Path ends with a forward slash. Make our own copy. 85386c9584559439504fc57ece2ccd9b6cbd568430cKenny Root 85486c9584559439504fc57ece2ccd9b6cbd568430cKenny Root rec->path = strdup(path); 85586c9584559439504fc57ece2ccd9b6cbd568430cKenny Root if (rec->path == NULL) { 85686c9584559439504fc57ece2ccd9b6cbd568430cKenny Root return -1; 85786c9584559439504fc57ece2ccd9b6cbd568430cKenny Root } 85886c9584559439504fc57ece2ccd9b6cbd568430cKenny Root 85986c9584559439504fc57ece2ccd9b6cbd568430cKenny Root rec->len = path_len; 86086c9584559439504fc57ece2ccd9b6cbd568430cKenny Root } else { 86186c9584559439504fc57ece2ccd9b6cbd568430cKenny Root // Path does not end with a slash. Generate a new string. 86286c9584559439504fc57ece2ccd9b6cbd568430cKenny Root char *dst; 86386c9584559439504fc57ece2ccd9b6cbd568430cKenny Root 86486c9584559439504fc57ece2ccd9b6cbd568430cKenny Root // Add space for slash and terminating null. 86586c9584559439504fc57ece2ccd9b6cbd568430cKenny Root size_t dst_size = path_len + 2; 86686c9584559439504fc57ece2ccd9b6cbd568430cKenny Root 86786c9584559439504fc57ece2ccd9b6cbd568430cKenny Root rec->path = malloc(dst_size); 86886c9584559439504fc57ece2ccd9b6cbd568430cKenny Root if (rec->path == NULL) { 86986c9584559439504fc57ece2ccd9b6cbd568430cKenny Root return -1; 87086c9584559439504fc57ece2ccd9b6cbd568430cKenny Root } 87186c9584559439504fc57ece2ccd9b6cbd568430cKenny Root 87286c9584559439504fc57ece2ccd9b6cbd568430cKenny Root dst = rec->path; 87386c9584559439504fc57ece2ccd9b6cbd568430cKenny Root 87486c9584559439504fc57ece2ccd9b6cbd568430cKenny Root if (append_and_increment(&dst, path, &dst_size) < 0 87586c9584559439504fc57ece2ccd9b6cbd568430cKenny Root || append_and_increment(&dst, "/", &dst_size)) { 8763762c311729fe9f3af085c14c5c1fb471d994c03Steve Block ALOGE("Error canonicalizing path"); 87786c9584559439504fc57ece2ccd9b6cbd568430cKenny Root return -1; 87886c9584559439504fc57ece2ccd9b6cbd568430cKenny Root } 87986c9584559439504fc57ece2ccd9b6cbd568430cKenny Root 88086c9584559439504fc57ece2ccd9b6cbd568430cKenny Root rec->len = dst - rec->path; 88186c9584559439504fc57ece2ccd9b6cbd568430cKenny Root } 88286c9584559439504fc57ece2ccd9b6cbd568430cKenny Root } 88386c9584559439504fc57ece2ccd9b6cbd568430cKenny Root return 0; 88486c9584559439504fc57ece2ccd9b6cbd568430cKenny Root} 88586c9584559439504fc57ece2ccd9b6cbd568430cKenny Root 88686c9584559439504fc57ece2ccd9b6cbd568430cKenny Rootint copy_and_append(dir_rec_t* dst, const dir_rec_t* src, const char* suffix) { 88786c9584559439504fc57ece2ccd9b6cbd568430cKenny Root dst->len = src->len + strlen(suffix); 88886c9584559439504fc57ece2ccd9b6cbd568430cKenny Root const size_t dstSize = dst->len + 1; 88986c9584559439504fc57ece2ccd9b6cbd568430cKenny Root dst->path = (char*) malloc(dstSize); 89086c9584559439504fc57ece2ccd9b6cbd568430cKenny Root 89186c9584559439504fc57ece2ccd9b6cbd568430cKenny Root if (dst->path == NULL 89286c9584559439504fc57ece2ccd9b6cbd568430cKenny Root || snprintf(dst->path, dstSize, "%s%s", src->path, suffix) 89386c9584559439504fc57ece2ccd9b6cbd568430cKenny Root != (ssize_t) dst->len) { 8943762c311729fe9f3af085c14c5c1fb471d994c03Steve Block ALOGE("Could not allocate memory to hold appended path; aborting\n"); 89586c9584559439504fc57ece2ccd9b6cbd568430cKenny Root return -1; 89686c9584559439504fc57ece2ccd9b6cbd568430cKenny Root } 89786c9584559439504fc57ece2ccd9b6cbd568430cKenny Root 89886c9584559439504fc57ece2ccd9b6cbd568430cKenny Root return 0; 89986c9584559439504fc57ece2ccd9b6cbd568430cKenny Root} 90086c9584559439504fc57ece2ccd9b6cbd568430cKenny Root 90186c9584559439504fc57ece2ccd9b6cbd568430cKenny Root/** 90286c9584559439504fc57ece2ccd9b6cbd568430cKenny Root * Check whether path points to a valid path for an APK file. An ASEC 90386c9584559439504fc57ece2ccd9b6cbd568430cKenny Root * directory is allowed to have one level of subdirectory names. Returns -1 90486c9584559439504fc57ece2ccd9b6cbd568430cKenny Root * when an invalid path is encountered and 0 when a valid path is encountered. 90586c9584559439504fc57ece2ccd9b6cbd568430cKenny Root */ 90686c9584559439504fc57ece2ccd9b6cbd568430cKenny Rootint validate_apk_path(const char *path) 90786c9584559439504fc57ece2ccd9b6cbd568430cKenny Root{ 90886c9584559439504fc57ece2ccd9b6cbd568430cKenny Root int allowsubdir = 0; 90986c9584559439504fc57ece2ccd9b6cbd568430cKenny Root char *subdir = NULL; 91086c9584559439504fc57ece2ccd9b6cbd568430cKenny Root size_t dir_len; 91186c9584559439504fc57ece2ccd9b6cbd568430cKenny Root size_t path_len; 91286c9584559439504fc57ece2ccd9b6cbd568430cKenny Root 91386c9584559439504fc57ece2ccd9b6cbd568430cKenny Root if (!strncmp(path, android_app_dir.path, android_app_dir.len)) { 91486c9584559439504fc57ece2ccd9b6cbd568430cKenny Root dir_len = android_app_dir.len; 91586c9584559439504fc57ece2ccd9b6cbd568430cKenny Root } else if (!strncmp(path, android_app_private_dir.path, android_app_private_dir.len)) { 91686c9584559439504fc57ece2ccd9b6cbd568430cKenny Root dir_len = android_app_private_dir.len; 91786c9584559439504fc57ece2ccd9b6cbd568430cKenny Root } else if (!strncmp(path, android_asec_dir.path, android_asec_dir.len)) { 91886c9584559439504fc57ece2ccd9b6cbd568430cKenny Root dir_len = android_asec_dir.len; 91986c9584559439504fc57ece2ccd9b6cbd568430cKenny Root allowsubdir = 1; 92086c9584559439504fc57ece2ccd9b6cbd568430cKenny Root } else { 9213762c311729fe9f3af085c14c5c1fb471d994c03Steve Block ALOGE("invalid apk path '%s' (bad prefix)\n", path); 92286c9584559439504fc57ece2ccd9b6cbd568430cKenny Root return -1; 92386c9584559439504fc57ece2ccd9b6cbd568430cKenny Root } 92486c9584559439504fc57ece2ccd9b6cbd568430cKenny Root 92586c9584559439504fc57ece2ccd9b6cbd568430cKenny Root path_len = strlen(path); 92686c9584559439504fc57ece2ccd9b6cbd568430cKenny Root 92786c9584559439504fc57ece2ccd9b6cbd568430cKenny Root /* 92886c9584559439504fc57ece2ccd9b6cbd568430cKenny Root * Only allow the path to have a subdirectory if it's been marked as being allowed. 92986c9584559439504fc57ece2ccd9b6cbd568430cKenny Root */ 93086c9584559439504fc57ece2ccd9b6cbd568430cKenny Root if ((subdir = strchr(path + dir_len, '/')) != NULL) { 93186c9584559439504fc57ece2ccd9b6cbd568430cKenny Root ++subdir; 93286c9584559439504fc57ece2ccd9b6cbd568430cKenny Root if (!allowsubdir 93386c9584559439504fc57ece2ccd9b6cbd568430cKenny Root || (path_len > (size_t) (subdir - path) && (strchr(subdir, '/') != NULL))) { 9343762c311729fe9f3af085c14c5c1fb471d994c03Steve Block ALOGE("invalid apk path '%s' (subdir?)\n", path); 93586c9584559439504fc57ece2ccd9b6cbd568430cKenny Root return -1; 93686c9584559439504fc57ece2ccd9b6cbd568430cKenny Root } 93786c9584559439504fc57ece2ccd9b6cbd568430cKenny Root } 93886c9584559439504fc57ece2ccd9b6cbd568430cKenny Root 93986c9584559439504fc57ece2ccd9b6cbd568430cKenny Root /* 94086c9584559439504fc57ece2ccd9b6cbd568430cKenny Root * Directories can't have a period directly after the directory markers 94186c9584559439504fc57ece2ccd9b6cbd568430cKenny Root * to prevent ".." 94286c9584559439504fc57ece2ccd9b6cbd568430cKenny Root */ 94386c9584559439504fc57ece2ccd9b6cbd568430cKenny Root if (path[dir_len] == '.' 94486c9584559439504fc57ece2ccd9b6cbd568430cKenny Root || (subdir != NULL && ((*subdir == '.') || (strchr(subdir, '/') != NULL)))) { 9453762c311729fe9f3af085c14c5c1fb471d994c03Steve Block ALOGE("invalid apk path '%s' (trickery)\n", path); 94686c9584559439504fc57ece2ccd9b6cbd568430cKenny Root return -1; 94786c9584559439504fc57ece2ccd9b6cbd568430cKenny Root } 94886c9584559439504fc57ece2ccd9b6cbd568430cKenny Root 94986c9584559439504fc57ece2ccd9b6cbd568430cKenny Root return 0; 95086c9584559439504fc57ece2ccd9b6cbd568430cKenny Root} 95186c9584559439504fc57ece2ccd9b6cbd568430cKenny Root 95286c9584559439504fc57ece2ccd9b6cbd568430cKenny Rootint append_and_increment(char** dst, const char* src, size_t* dst_size) { 95386c9584559439504fc57ece2ccd9b6cbd568430cKenny Root ssize_t ret = strlcpy(*dst, src, *dst_size); 95486c9584559439504fc57ece2ccd9b6cbd568430cKenny Root if (ret < 0 || (size_t) ret >= *dst_size) { 95586c9584559439504fc57ece2ccd9b6cbd568430cKenny Root return -1; 95686c9584559439504fc57ece2ccd9b6cbd568430cKenny Root } 95786c9584559439504fc57ece2ccd9b6cbd568430cKenny Root *dst += ret; 95886c9584559439504fc57ece2ccd9b6cbd568430cKenny Root *dst_size -= ret; 95986c9584559439504fc57ece2ccd9b6cbd568430cKenny Root return 0; 96086c9584559439504fc57ece2ccd9b6cbd568430cKenny Root} 9610b285499db739ba50f2f839d633e763c70e67f96Amith Yamasani 9620b285499db739ba50f2f839d633e763c70e67f96Amith Yamasanichar *build_string2(char *s1, char *s2) { 9630b285499db739ba50f2f839d633e763c70e67f96Amith Yamasani if (s1 == NULL || s2 == NULL) return NULL; 9640b285499db739ba50f2f839d633e763c70e67f96Amith Yamasani 9650b285499db739ba50f2f839d633e763c70e67f96Amith Yamasani int len_s1 = strlen(s1); 9660b285499db739ba50f2f839d633e763c70e67f96Amith Yamasani int len_s2 = strlen(s2); 9670b285499db739ba50f2f839d633e763c70e67f96Amith Yamasani int len = len_s1 + len_s2 + 1; 9680b285499db739ba50f2f839d633e763c70e67f96Amith Yamasani char *result = malloc(len); 9690b285499db739ba50f2f839d633e763c70e67f96Amith Yamasani if (result == NULL) return NULL; 9700b285499db739ba50f2f839d633e763c70e67f96Amith Yamasani 9710b285499db739ba50f2f839d633e763c70e67f96Amith Yamasani strcpy(result, s1); 9720b285499db739ba50f2f839d633e763c70e67f96Amith Yamasani strcpy(result + len_s1, s2); 9730b285499db739ba50f2f839d633e763c70e67f96Amith Yamasani 9740b285499db739ba50f2f839d633e763c70e67f96Amith Yamasani return result; 9750b285499db739ba50f2f839d633e763c70e67f96Amith Yamasani} 9760b285499db739ba50f2f839d633e763c70e67f96Amith Yamasani 9770b285499db739ba50f2f839d633e763c70e67f96Amith Yamasanichar *build_string3(char *s1, char *s2, char *s3) { 9780b285499db739ba50f2f839d633e763c70e67f96Amith Yamasani if (s1 == NULL || s2 == NULL || s3 == NULL) return NULL; 9790b285499db739ba50f2f839d633e763c70e67f96Amith Yamasani 9800b285499db739ba50f2f839d633e763c70e67f96Amith Yamasani int len_s1 = strlen(s1); 9810b285499db739ba50f2f839d633e763c70e67f96Amith Yamasani int len_s2 = strlen(s2); 9820b285499db739ba50f2f839d633e763c70e67f96Amith Yamasani int len_s3 = strlen(s3); 9830b285499db739ba50f2f839d633e763c70e67f96Amith Yamasani int len = len_s1 + len_s2 + len_s3 + 1; 9840b285499db739ba50f2f839d633e763c70e67f96Amith Yamasani char *result = malloc(len); 9850b285499db739ba50f2f839d633e763c70e67f96Amith Yamasani if (result == NULL) return NULL; 9860b285499db739ba50f2f839d633e763c70e67f96Amith Yamasani 9870b285499db739ba50f2f839d633e763c70e67f96Amith Yamasani strcpy(result, s1); 9880b285499db739ba50f2f839d633e763c70e67f96Amith Yamasani strcpy(result + len_s1, s2); 9890b285499db739ba50f2f839d633e763c70e67f96Amith Yamasani strcpy(result + len_s1 + len_s2, s3); 9900b285499db739ba50f2f839d633e763c70e67f96Amith Yamasani 9910b285499db739ba50f2f839d633e763c70e67f96Amith Yamasani return result; 9920b285499db739ba50f2f839d633e763c70e67f96Amith Yamasani} 9935b1ada2562c17921adf6a62ea62bcb445160983cJeff Sharkey 9948ea0dc6a89b011d4f478c0c8192570d69cf7ce79Jeff Sharkey/* Ensure that /data/media directories are prepared for given user. */ 9958ea0dc6a89b011d4f478c0c8192570d69cf7ce79Jeff Sharkeyint ensure_media_user_dirs(userid_t userid) { 9968ea0dc6a89b011d4f478c0c8192570d69cf7ce79Jeff Sharkey char media_user_path[PATH_MAX]; 9978ea0dc6a89b011d4f478c0c8192570d69cf7ce79Jeff Sharkey char path[PATH_MAX]; 9985b1ada2562c17921adf6a62ea62bcb445160983cJeff Sharkey 9998ea0dc6a89b011d4f478c0c8192570d69cf7ce79Jeff Sharkey // Ensure /data/media/<userid> exists 10008ea0dc6a89b011d4f478c0c8192570d69cf7ce79Jeff Sharkey create_persona_media_path(media_user_path, userid); 10018ea0dc6a89b011d4f478c0c8192570d69cf7ce79Jeff Sharkey if (fs_prepare_dir(media_user_path, 0770, AID_MEDIA_RW, AID_MEDIA_RW) == -1) { 10025b1ada2562c17921adf6a62ea62bcb445160983cJeff Sharkey return -1; 10035b1ada2562c17921adf6a62ea62bcb445160983cJeff Sharkey } 10045b1ada2562c17921adf6a62ea62bcb445160983cJeff Sharkey 10055b1ada2562c17921adf6a62ea62bcb445160983cJeff Sharkey return 0; 10065b1ada2562c17921adf6a62ea62bcb445160983cJeff Sharkey} 1007