utils.cpp revision 1d992f9f7886f98e46f98430d6c1d061cc31fdb3
1/* 2** Copyright 2008, The Android Open Source Project 3** 4** Licensed under the Apache License, Version 2.0 (the "License"); 5** you may not use this file except in compliance with the License. 6** You may obtain a copy of the License at 7** 8** http://www.apache.org/licenses/LICENSE-2.0 9** 10** Unless required by applicable law or agreed to in writing, software 11** distributed under the License is distributed on an "AS IS" BASIS, 12** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13** See the License for the specific language governing permissions and 14** limitations under the License. 15*/ 16 17#include "utils.h" 18 19#include <errno.h> 20#include <fcntl.h> 21#include <stdlib.h> 22#include <sys/stat.h> 23#include <sys/wait.h> 24 25#if defined(__APPLE__) 26#include <sys/mount.h> 27#else 28#include <sys/statfs.h> 29#endif 30 31#include <android-base/logging.h> 32#include <android-base/stringprintf.h> 33#include <cutils/fs.h> 34#include <cutils/log.h> 35#include <private/android_filesystem_config.h> 36 37#include "globals.h" // extern variables. 38 39#ifndef LOG_TAG 40#define LOG_TAG "installd" 41#endif 42#define CACHE_NOISY(x) //x 43 44using android::base::StringPrintf; 45 46namespace android { 47namespace installd { 48 49/** 50 * Check that given string is valid filename, and that it attempts no 51 * parent or child directory traversal. 52 */ 53static bool is_valid_filename(const std::string& name) { 54 if (name.empty() || (name == ".") || (name == "..") 55 || (name.find('/') != std::string::npos)) { 56 return false; 57 } else { 58 return true; 59 } 60} 61 62static void check_package_name(const char* package_name) { 63 CHECK(is_valid_filename(package_name)); 64 CHECK(is_valid_package_name(package_name) == 0); 65} 66 67/** 68 * Create the path name where package app contents should be stored for 69 * the given volume UUID and package name. An empty UUID is assumed to 70 * be internal storage. 71 */ 72std::string create_data_app_package_path(const char* volume_uuid, 73 const char* package_name) { 74 check_package_name(package_name); 75 return StringPrintf("%s/%s", 76 create_data_app_path(volume_uuid).c_str(), package_name); 77} 78 79/** 80 * Create the path name where package data should be stored for the given 81 * volume UUID, package name, and user ID. An empty UUID is assumed to be 82 * internal storage. 83 */ 84std::string create_data_user_ce_package_path(const char* volume_uuid, 85 userid_t user, const char* package_name) { 86 check_package_name(package_name); 87 return StringPrintf("%s/%s", 88 create_data_user_ce_path(volume_uuid, user).c_str(), package_name); 89} 90 91std::string create_data_user_ce_package_path(const char* volume_uuid, userid_t user, 92 const char* package_name, ino_t ce_data_inode) { 93 // For testing purposes, rely on the inode when defined; this could be 94 // optimized to use access() in the future. 95 auto fallback = create_data_user_ce_package_path(volume_uuid, user, package_name); 96 if (ce_data_inode != 0) { 97 auto user_path = create_data_user_ce_path(volume_uuid, user); 98 DIR* dir = opendir(user_path.c_str()); 99 if (dir == nullptr) { 100 PLOG(ERROR) << "Failed to opendir " << user_path; 101 return fallback; 102 } 103 104 struct dirent* ent; 105 while ((ent = readdir(dir))) { 106 if (ent->d_ino == ce_data_inode) { 107 auto resolved = StringPrintf("%s/%s", user_path.c_str(), ent->d_name); 108 if (resolved != fallback) { 109 LOG(DEBUG) << "Resolved path " << resolved << " for inode " << ce_data_inode 110 << " instead of " << fallback; 111 } 112 closedir(dir); 113 return resolved; 114 } 115 } 116 LOG(WARNING) << "Failed to resolve inode " << ce_data_inode << "; using " << fallback; 117 closedir(dir); 118 return fallback; 119 } else { 120 return fallback; 121 } 122} 123 124std::string create_data_user_de_package_path(const char* volume_uuid, 125 userid_t user, const char* package_name) { 126 check_package_name(package_name); 127 return StringPrintf("%s/%s", 128 create_data_user_de_path(volume_uuid, user).c_str(), package_name); 129} 130 131int create_pkg_path(char path[PKG_PATH_MAX], const char *pkgname, 132 const char *postfix, userid_t userid) { 133 if (is_valid_package_name(pkgname) != 0) { 134 path[0] = '\0'; 135 return -1; 136 } 137 138 std::string _tmp(create_data_user_ce_package_path(nullptr, userid, pkgname) + postfix); 139 const char* tmp = _tmp.c_str(); 140 if (strlen(tmp) >= PKG_PATH_MAX) { 141 path[0] = '\0'; 142 return -1; 143 } else { 144 strcpy(path, tmp); 145 return 0; 146 } 147} 148 149std::string create_data_path(const char* volume_uuid) { 150 if (volume_uuid == nullptr) { 151 return "/data"; 152 } else { 153 CHECK(is_valid_filename(volume_uuid)); 154 return StringPrintf("/mnt/expand/%s", volume_uuid); 155 } 156} 157 158/** 159 * Create the path name for app data. 160 */ 161std::string create_data_app_path(const char* volume_uuid) { 162 return StringPrintf("%s/app", create_data_path(volume_uuid).c_str()); 163} 164 165/** 166 * Create the path name for user data for a certain userid. 167 */ 168std::string create_data_user_ce_path(const char* volume_uuid, userid_t userid) { 169 std::string data(create_data_path(volume_uuid)); 170 if (volume_uuid == nullptr) { 171 if (userid == 0) { 172 return StringPrintf("%s/data", data.c_str()); 173 } else { 174 return StringPrintf("%s/user/%u", data.c_str(), userid); 175 } 176 } else { 177 return StringPrintf("%s/user/%u", data.c_str(), userid); 178 } 179} 180 181/** 182 * Create the path name for device encrypted user data for a certain userid. 183 */ 184std::string create_data_user_de_path(const char* volume_uuid, userid_t userid) { 185 std::string data(create_data_path(volume_uuid)); 186 return StringPrintf("%s/user_de/%u", data.c_str(), userid); 187} 188 189/** 190 * Create the path name for media for a certain userid. 191 */ 192std::string create_data_media_path(const char* volume_uuid, userid_t userid) { 193 return StringPrintf("%s/media/%u", create_data_path(volume_uuid).c_str(), userid); 194} 195 196std::string create_data_user_profiles_path(userid_t userid) { 197 return StringPrintf("%s/cur/%u", android_profiles_dir.path, userid); 198} 199 200std::string create_data_user_profile_package_path(userid_t user, const char* package_name) { 201 check_package_name(package_name); 202 return StringPrintf("%s/%s",create_data_user_profiles_path(user).c_str(), package_name); 203} 204 205std::string create_data_ref_profile_package_path(const char* package_name) { 206 check_package_name(package_name); 207 return StringPrintf("%s/ref/%s", android_profiles_dir.path, package_name); 208} 209 210std::vector<userid_t> get_known_users(const char* volume_uuid) { 211 std::vector<userid_t> users; 212 213 // We always have an owner 214 users.push_back(0); 215 216 std::string path(create_data_path(volume_uuid) + "/" + SECONDARY_USER_PREFIX); 217 DIR* dir = opendir(path.c_str()); 218 if (dir == NULL) { 219 // Unable to discover other users, but at least return owner 220 PLOG(ERROR) << "Failed to opendir " << path; 221 return users; 222 } 223 224 struct dirent* ent; 225 while ((ent = readdir(dir))) { 226 if (ent->d_type != DT_DIR) { 227 continue; 228 } 229 230 char* end; 231 userid_t user = strtol(ent->d_name, &end, 10); 232 if (*end == '\0' && user != 0) { 233 LOG(DEBUG) << "Found valid user " << user; 234 users.push_back(user); 235 } 236 } 237 closedir(dir); 238 239 return users; 240} 241 242/** 243 * Create the path name for config for a certain userid. 244 * Returns 0 on success, and -1 on failure. 245 */ 246int create_user_config_path(char path[PATH_MAX], userid_t userid) { 247 if (snprintf(path, PATH_MAX, "%s%d", "/data/misc/user/", userid) > PATH_MAX) { 248 return -1; 249 } 250 return 0; 251} 252 253int create_move_path(char path[PKG_PATH_MAX], 254 const char* pkgname, 255 const char* leaf, 256 userid_t userid ATTRIBUTE_UNUSED) 257{ 258 if ((android_data_dir.len + strlen(PRIMARY_USER_PREFIX) + strlen(pkgname) + strlen(leaf) + 1) 259 >= PKG_PATH_MAX) { 260 return -1; 261 } 262 263 sprintf(path, "%s%s%s/%s", android_data_dir.path, PRIMARY_USER_PREFIX, pkgname, leaf); 264 return 0; 265} 266 267/** 268 * Checks whether the package name is valid. Returns -1 on error and 269 * 0 on success. 270 */ 271int is_valid_package_name(const char* pkgname) { 272 const char *x = pkgname; 273 int alpha = -1; 274 275 if (strlen(pkgname) > PKG_NAME_MAX) { 276 return -1; 277 } 278 279 while (*x) { 280 if (isalnum(*x) || (*x == '_')) { 281 /* alphanumeric or underscore are fine */ 282 } else if (*x == '.') { 283 if ((x == pkgname) || (x[1] == '.') || (x[1] == 0)) { 284 /* periods must not be first, last, or doubled */ 285 ALOGE("invalid package name '%s'\n", pkgname); 286 return -1; 287 } 288 } else if (*x == '-') { 289 /* Suffix -X is fine to let versioning of packages. 290 But whatever follows should be alphanumeric.*/ 291 alpha = 1; 292 } else { 293 /* anything not A-Z, a-z, 0-9, _, or . is invalid */ 294 ALOGE("invalid package name '%s'\n", pkgname); 295 return -1; 296 } 297 298 x++; 299 } 300 301 if (alpha == 1) { 302 // Skip current character 303 x++; 304 while (*x) { 305 if (!isalnum(*x)) { 306 ALOGE("invalid package name '%s' should include only numbers after -\n", pkgname); 307 return -1; 308 } 309 x++; 310 } 311 } 312 313 return 0; 314} 315 316static int _delete_dir_contents(DIR *d, 317 int (*exclusion_predicate)(const char *name, const int is_dir)) 318{ 319 int result = 0; 320 struct dirent *de; 321 int dfd; 322 323 dfd = dirfd(d); 324 325 if (dfd < 0) return -1; 326 327 while ((de = readdir(d))) { 328 const char *name = de->d_name; 329 330 /* check using the exclusion predicate, if provided */ 331 if (exclusion_predicate && exclusion_predicate(name, (de->d_type == DT_DIR))) { 332 continue; 333 } 334 335 if (de->d_type == DT_DIR) { 336 int subfd; 337 DIR *subdir; 338 339 /* always skip "." and ".." */ 340 if (name[0] == '.') { 341 if (name[1] == 0) continue; 342 if ((name[1] == '.') && (name[2] == 0)) continue; 343 } 344 345 subfd = openat(dfd, name, O_RDONLY | O_DIRECTORY | O_NOFOLLOW | O_CLOEXEC); 346 if (subfd < 0) { 347 ALOGE("Couldn't openat %s: %s\n", name, strerror(errno)); 348 result = -1; 349 continue; 350 } 351 subdir = fdopendir(subfd); 352 if (subdir == NULL) { 353 ALOGE("Couldn't fdopendir %s: %s\n", name, strerror(errno)); 354 close(subfd); 355 result = -1; 356 continue; 357 } 358 if (_delete_dir_contents(subdir, exclusion_predicate)) { 359 result = -1; 360 } 361 closedir(subdir); 362 if (unlinkat(dfd, name, AT_REMOVEDIR) < 0) { 363 ALOGE("Couldn't unlinkat %s: %s\n", name, strerror(errno)); 364 result = -1; 365 } 366 } else { 367 if (unlinkat(dfd, name, 0) < 0) { 368 ALOGE("Couldn't unlinkat %s: %s\n", name, strerror(errno)); 369 result = -1; 370 } 371 } 372 } 373 374 return result; 375} 376 377int delete_dir_contents(const std::string& pathname, bool ignore_if_missing) { 378 return delete_dir_contents(pathname.c_str(), 0, NULL, ignore_if_missing); 379} 380 381int delete_dir_contents_and_dir(const std::string& pathname, bool ignore_if_missing) { 382 return delete_dir_contents(pathname.c_str(), 1, NULL, ignore_if_missing); 383} 384 385int delete_dir_contents(const char *pathname, 386 int also_delete_dir, 387 int (*exclusion_predicate)(const char*, const int), 388 bool ignore_if_missing) 389{ 390 int res = 0; 391 DIR *d; 392 393 d = opendir(pathname); 394 if (d == NULL) { 395 if (ignore_if_missing && (errno == ENOENT)) { 396 return 0; 397 } 398 ALOGE("Couldn't opendir %s: %s\n", pathname, strerror(errno)); 399 return -errno; 400 } 401 res = _delete_dir_contents(d, exclusion_predicate); 402 closedir(d); 403 if (also_delete_dir) { 404 if (rmdir(pathname)) { 405 ALOGE("Couldn't rmdir %s: %s\n", pathname, strerror(errno)); 406 res = -1; 407 } 408 } 409 return res; 410} 411 412int delete_dir_contents_fd(int dfd, const char *name) 413{ 414 int fd, res; 415 DIR *d; 416 417 fd = openat(dfd, name, O_RDONLY | O_DIRECTORY | O_NOFOLLOW | O_CLOEXEC); 418 if (fd < 0) { 419 ALOGE("Couldn't openat %s: %s\n", name, strerror(errno)); 420 return -1; 421 } 422 d = fdopendir(fd); 423 if (d == NULL) { 424 ALOGE("Couldn't fdopendir %s: %s\n", name, strerror(errno)); 425 close(fd); 426 return -1; 427 } 428 res = _delete_dir_contents(d, 0); 429 closedir(d); 430 return res; 431} 432 433static int _copy_owner_permissions(int srcfd, int dstfd) 434{ 435 struct stat st; 436 if (fstat(srcfd, &st) != 0) { 437 return -1; 438 } 439 if (fchmod(dstfd, st.st_mode) != 0) { 440 return -1; 441 } 442 return 0; 443} 444 445static int _copy_dir_files(int sdfd, int ddfd, uid_t owner, gid_t group) 446{ 447 int result = 0; 448 if (_copy_owner_permissions(sdfd, ddfd) != 0) { 449 ALOGE("_copy_dir_files failed to copy dir permissions\n"); 450 } 451 if (fchown(ddfd, owner, group) != 0) { 452 ALOGE("_copy_dir_files failed to change dir owner\n"); 453 } 454 455 DIR *ds = fdopendir(sdfd); 456 if (ds == NULL) { 457 ALOGE("Couldn't fdopendir: %s\n", strerror(errno)); 458 return -1; 459 } 460 struct dirent *de; 461 while ((de = readdir(ds))) { 462 if (de->d_type != DT_REG) { 463 continue; 464 } 465 466 const char *name = de->d_name; 467 int fsfd = openat(sdfd, name, O_RDONLY | O_NOFOLLOW | O_CLOEXEC); 468 int fdfd = openat(ddfd, name, O_WRONLY | O_NOFOLLOW | O_CLOEXEC | O_CREAT, 0600); 469 if (fsfd == -1 || fdfd == -1) { 470 ALOGW("Couldn't copy %s: %s\n", name, strerror(errno)); 471 } else { 472 if (_copy_owner_permissions(fsfd, fdfd) != 0) { 473 ALOGE("Failed to change file permissions\n"); 474 } 475 if (fchown(fdfd, owner, group) != 0) { 476 ALOGE("Failed to change file owner\n"); 477 } 478 479 char buf[8192]; 480 ssize_t size; 481 while ((size = read(fsfd, buf, sizeof(buf))) > 0) { 482 write(fdfd, buf, size); 483 } 484 if (size < 0) { 485 ALOGW("Couldn't copy %s: %s\n", name, strerror(errno)); 486 result = -1; 487 } 488 } 489 close(fdfd); 490 close(fsfd); 491 } 492 493 return result; 494} 495 496int copy_dir_files(const char *srcname, 497 const char *dstname, 498 uid_t owner, 499 uid_t group) 500{ 501 int res = 0; 502 DIR *ds = NULL; 503 DIR *dd = NULL; 504 505 ds = opendir(srcname); 506 if (ds == NULL) { 507 ALOGE("Couldn't opendir %s: %s\n", srcname, strerror(errno)); 508 return -errno; 509 } 510 511 mkdir(dstname, 0600); 512 dd = opendir(dstname); 513 if (dd == NULL) { 514 ALOGE("Couldn't opendir %s: %s\n", dstname, strerror(errno)); 515 closedir(ds); 516 return -errno; 517 } 518 519 int sdfd = dirfd(ds); 520 int ddfd = dirfd(dd); 521 if (sdfd != -1 && ddfd != -1) { 522 res = _copy_dir_files(sdfd, ddfd, owner, group); 523 } else { 524 res = -errno; 525 } 526 closedir(dd); 527 closedir(ds); 528 return res; 529} 530 531int lookup_media_dir(char basepath[PATH_MAX], const char *dir) 532{ 533 DIR *d; 534 struct dirent *de; 535 struct stat s; 536 char* dirpos = basepath + strlen(basepath); 537 538 if ((*(dirpos-1)) != '/') { 539 *dirpos = '/'; 540 dirpos++; 541 } 542 543 CACHE_NOISY(ALOGI("Looking up %s in %s\n", dir, basepath)); 544 // Verify the path won't extend beyond our buffer, to avoid 545 // repeated checking later. 546 if ((dirpos-basepath+strlen(dir)) >= (PATH_MAX-1)) { 547 ALOGW("Path exceeds limit: %s%s", basepath, dir); 548 return -1; 549 } 550 551 // First, can we find this directory with the case that is given? 552 strcpy(dirpos, dir); 553 if (stat(basepath, &s) >= 0) { 554 CACHE_NOISY(ALOGI("Found direct: %s\n", basepath)); 555 return 0; 556 } 557 558 // Not found with that case... search through all entries to find 559 // one that matches regardless of case. 560 *dirpos = 0; 561 562 d = opendir(basepath); 563 if (d == NULL) { 564 return -1; 565 } 566 567 while ((de = readdir(d))) { 568 if (strcasecmp(de->d_name, dir) == 0) { 569 strcpy(dirpos, de->d_name); 570 closedir(d); 571 CACHE_NOISY(ALOGI("Found search: %s\n", basepath)); 572 return 0; 573 } 574 } 575 576 ALOGW("Couldn't find %s in %s", dir, basepath); 577 closedir(d); 578 return -1; 579} 580 581int64_t data_disk_free(const std::string& data_path) 582{ 583 struct statfs sfs; 584 if (statfs(data_path.c_str(), &sfs) == 0) { 585 return sfs.f_bavail * sfs.f_bsize; 586 } else { 587 PLOG(ERROR) << "Couldn't statfs " << data_path; 588 return -1; 589 } 590} 591 592cache_t* start_cache_collection() 593{ 594 cache_t* cache = (cache_t*)calloc(1, sizeof(cache_t)); 595 return cache; 596} 597 598#define CACHE_BLOCK_SIZE (512*1024) 599 600static void* _cache_malloc(cache_t* cache, size_t len) 601{ 602 len = (len+3)&~3; 603 if (len > (CACHE_BLOCK_SIZE/2)) { 604 // It doesn't make sense to try to put this allocation into one 605 // of our blocks, because it is so big. Instead, make a new dedicated 606 // block for it. 607 int8_t* res = (int8_t*)malloc(len+sizeof(void*)); 608 if (res == NULL) { 609 return NULL; 610 } 611 CACHE_NOISY(ALOGI("Allocated large cache mem block: %p size %d", res, len)); 612 // Link it into our list of blocks, not disrupting the current one. 613 if (cache->memBlocks == NULL) { 614 *(void**)res = NULL; 615 cache->memBlocks = res; 616 } else { 617 *(void**)res = *(void**)cache->memBlocks; 618 *(void**)cache->memBlocks = res; 619 } 620 return res + sizeof(void*); 621 } 622 int8_t* res = cache->curMemBlockAvail; 623 int8_t* nextPos = res + len; 624 if (cache->memBlocks == NULL || nextPos > cache->curMemBlockEnd) { 625 int8_t* newBlock = (int8_t*) malloc(CACHE_BLOCK_SIZE); 626 if (newBlock == NULL) { 627 return NULL; 628 } 629 CACHE_NOISY(ALOGI("Allocated new cache mem block: %p", newBlock)); 630 *(void**)newBlock = cache->memBlocks; 631 cache->memBlocks = newBlock; 632 res = cache->curMemBlockAvail = newBlock + sizeof(void*); 633 cache->curMemBlockEnd = newBlock + CACHE_BLOCK_SIZE; 634 nextPos = res + len; 635 } 636 CACHE_NOISY(ALOGI("cache_malloc: ret %p size %d, block=%p, nextPos=%p", 637 res, len, cache->memBlocks, nextPos)); 638 cache->curMemBlockAvail = nextPos; 639 return res; 640} 641 642static void* _cache_realloc(cache_t* cache, void* cur, size_t origLen, size_t len) 643{ 644 // This isn't really a realloc, but it is good enough for our purposes here. 645 void* alloc = _cache_malloc(cache, len); 646 if (alloc != NULL && cur != NULL) { 647 memcpy(alloc, cur, origLen < len ? origLen : len); 648 } 649 return alloc; 650} 651 652static void _inc_num_cache_collected(cache_t* cache) 653{ 654 cache->numCollected++; 655 if ((cache->numCollected%20000) == 0) { 656 ALOGI("Collected cache so far: %zd directories, %zd files", 657 cache->numDirs, cache->numFiles); 658 } 659} 660 661static cache_dir_t* _add_cache_dir_t(cache_t* cache, cache_dir_t* parent, const char *name) 662{ 663 size_t nameLen = strlen(name); 664 cache_dir_t* dir = (cache_dir_t*)_cache_malloc(cache, sizeof(cache_dir_t)+nameLen+1); 665 if (dir != NULL) { 666 dir->parent = parent; 667 dir->childCount = 0; 668 dir->hiddenCount = 0; 669 dir->deleted = 0; 670 strcpy(dir->name, name); 671 if (cache->numDirs >= cache->availDirs) { 672 size_t newAvail = cache->availDirs < 1000 ? 1000 : cache->availDirs*2; 673 cache_dir_t** newDirs = (cache_dir_t**)_cache_realloc(cache, cache->dirs, 674 cache->availDirs*sizeof(cache_dir_t*), newAvail*sizeof(cache_dir_t*)); 675 if (newDirs == NULL) { 676 ALOGE("Failure growing cache dirs array for %s\n", name); 677 return NULL; 678 } 679 cache->availDirs = newAvail; 680 cache->dirs = newDirs; 681 } 682 cache->dirs[cache->numDirs] = dir; 683 cache->numDirs++; 684 if (parent != NULL) { 685 parent->childCount++; 686 } 687 _inc_num_cache_collected(cache); 688 } else { 689 ALOGE("Failure allocating cache_dir_t for %s\n", name); 690 } 691 return dir; 692} 693 694static cache_file_t* _add_cache_file_t(cache_t* cache, cache_dir_t* dir, time_t modTime, 695 const char *name) 696{ 697 size_t nameLen = strlen(name); 698 cache_file_t* file = (cache_file_t*)_cache_malloc(cache, sizeof(cache_file_t)+nameLen+1); 699 if (file != NULL) { 700 file->dir = dir; 701 file->modTime = modTime; 702 strcpy(file->name, name); 703 if (cache->numFiles >= cache->availFiles) { 704 size_t newAvail = cache->availFiles < 1000 ? 1000 : cache->availFiles*2; 705 cache_file_t** newFiles = (cache_file_t**)_cache_realloc(cache, cache->files, 706 cache->availFiles*sizeof(cache_file_t*), newAvail*sizeof(cache_file_t*)); 707 if (newFiles == NULL) { 708 ALOGE("Failure growing cache file array for %s\n", name); 709 return NULL; 710 } 711 cache->availFiles = newAvail; 712 cache->files = newFiles; 713 } 714 CACHE_NOISY(ALOGI("Setting file %p at position %d in array %p", file, 715 cache->numFiles, cache->files)); 716 cache->files[cache->numFiles] = file; 717 cache->numFiles++; 718 dir->childCount++; 719 _inc_num_cache_collected(cache); 720 } else { 721 ALOGE("Failure allocating cache_file_t for %s\n", name); 722 } 723 return file; 724} 725 726static int _add_cache_files(cache_t *cache, cache_dir_t *parentDir, const char *dirName, 727 DIR* dir, char *pathBase, char *pathPos, size_t pathAvailLen) 728{ 729 struct dirent *de; 730 cache_dir_t* cacheDir = NULL; 731 int dfd; 732 733 CACHE_NOISY(ALOGI("_add_cache_files: parent=%p dirName=%s dir=%p pathBase=%s", 734 parentDir, dirName, dir, pathBase)); 735 736 dfd = dirfd(dir); 737 738 if (dfd < 0) return 0; 739 740 // Sub-directories always get added to the data structure, so if they 741 // are empty we will know about them to delete them later. 742 cacheDir = _add_cache_dir_t(cache, parentDir, dirName); 743 744 while ((de = readdir(dir))) { 745 const char *name = de->d_name; 746 747 if (de->d_type == DT_DIR) { 748 int subfd; 749 DIR *subdir; 750 751 /* always skip "." and ".." */ 752 if (name[0] == '.') { 753 if (name[1] == 0) continue; 754 if ((name[1] == '.') && (name[2] == 0)) continue; 755 } 756 757 subfd = openat(dfd, name, O_RDONLY | O_DIRECTORY | O_NOFOLLOW | O_CLOEXEC); 758 if (subfd < 0) { 759 ALOGE("Couldn't openat %s: %s\n", name, strerror(errno)); 760 continue; 761 } 762 subdir = fdopendir(subfd); 763 if (subdir == NULL) { 764 ALOGE("Couldn't fdopendir %s: %s\n", name, strerror(errno)); 765 close(subfd); 766 continue; 767 } 768 if (cacheDir == NULL) { 769 cacheDir = _add_cache_dir_t(cache, parentDir, dirName); 770 } 771 if (cacheDir != NULL) { 772 // Update pathBase for the new path... this may change dirName 773 // if that is also pointing to the path, but we are done with it 774 // now. 775 size_t finallen = snprintf(pathPos, pathAvailLen, "/%s", name); 776 CACHE_NOISY(ALOGI("Collecting dir %s\n", pathBase)); 777 if (finallen < pathAvailLen) { 778 _add_cache_files(cache, cacheDir, name, subdir, pathBase, 779 pathPos+finallen, pathAvailLen-finallen); 780 } else { 781 // Whoops, the final path is too long! We'll just delete 782 // this directory. 783 ALOGW("Cache dir %s truncated in path %s; deleting dir\n", 784 name, pathBase); 785 _delete_dir_contents(subdir, NULL); 786 if (unlinkat(dfd, name, AT_REMOVEDIR) < 0) { 787 ALOGE("Couldn't unlinkat %s: %s\n", name, strerror(errno)); 788 } 789 } 790 } 791 closedir(subdir); 792 } else if (de->d_type == DT_REG) { 793 // Skip files that start with '.'; they will be deleted if 794 // their entire directory is deleted. This allows for metadata 795 // like ".nomedia" to remain in the directory until the entire 796 // directory is deleted. 797 if (cacheDir == NULL) { 798 cacheDir = _add_cache_dir_t(cache, parentDir, dirName); 799 } 800 if (name[0] == '.') { 801 cacheDir->hiddenCount++; 802 continue; 803 } 804 if (cacheDir != NULL) { 805 // Build final full path for file... this may change dirName 806 // if that is also pointing to the path, but we are done with it 807 // now. 808 size_t finallen = snprintf(pathPos, pathAvailLen, "/%s", name); 809 CACHE_NOISY(ALOGI("Collecting file %s\n", pathBase)); 810 if (finallen < pathAvailLen) { 811 struct stat s; 812 if (stat(pathBase, &s) >= 0) { 813 _add_cache_file_t(cache, cacheDir, s.st_mtime, name); 814 } else { 815 ALOGW("Unable to stat cache file %s; deleting\n", pathBase); 816 if (unlink(pathBase) < 0) { 817 ALOGE("Couldn't unlink %s: %s\n", pathBase, strerror(errno)); 818 } 819 } 820 } else { 821 // Whoops, the final path is too long! We'll just delete 822 // this file. 823 ALOGW("Cache file %s truncated in path %s; deleting\n", 824 name, pathBase); 825 if (unlinkat(dfd, name, 0) < 0) { 826 *pathPos = 0; 827 ALOGE("Couldn't unlinkat %s in %s: %s\n", name, pathBase, 828 strerror(errno)); 829 } 830 } 831 } 832 } else { 833 cacheDir->hiddenCount++; 834 } 835 } 836 return 0; 837} 838 839void add_cache_files(cache_t* cache, const char *basepath, const char *cachedir) 840{ 841 DIR *d; 842 struct dirent *de; 843 char dirname[PATH_MAX]; 844 845 CACHE_NOISY(ALOGI("add_cache_files: base=%s cachedir=%s\n", basepath, cachedir)); 846 847 d = opendir(basepath); 848 if (d == NULL) { 849 return; 850 } 851 852 while ((de = readdir(d))) { 853 if (de->d_type == DT_DIR) { 854 DIR* subdir; 855 const char *name = de->d_name; 856 char* pathpos; 857 858 /* always skip "." and ".." */ 859 if (name[0] == '.') { 860 if (name[1] == 0) continue; 861 if ((name[1] == '.') && (name[2] == 0)) continue; 862 } 863 864 strcpy(dirname, basepath); 865 pathpos = dirname + strlen(dirname); 866 if ((*(pathpos-1)) != '/') { 867 *pathpos = '/'; 868 pathpos++; 869 *pathpos = 0; 870 } 871 if (cachedir != NULL) { 872 snprintf(pathpos, sizeof(dirname)-(pathpos-dirname), "%s/%s", name, cachedir); 873 } else { 874 snprintf(pathpos, sizeof(dirname)-(pathpos-dirname), "%s", name); 875 } 876 CACHE_NOISY(ALOGI("Adding cache files from dir: %s\n", dirname)); 877 subdir = opendir(dirname); 878 if (subdir != NULL) { 879 size_t dirnameLen = strlen(dirname); 880 _add_cache_files(cache, NULL, dirname, subdir, dirname, dirname+dirnameLen, 881 PATH_MAX - dirnameLen); 882 closedir(subdir); 883 } 884 } 885 } 886 887 closedir(d); 888} 889 890static char *create_dir_path(char path[PATH_MAX], cache_dir_t* dir) 891{ 892 char *pos = path; 893 if (dir->parent != NULL) { 894 pos = create_dir_path(path, dir->parent); 895 } 896 // Note that we don't need to worry about going beyond the buffer, 897 // since when we were constructing the cache entries our maximum 898 // buffer size for full paths was PATH_MAX. 899 strcpy(pos, dir->name); 900 pos += strlen(pos); 901 *pos = '/'; 902 pos++; 903 *pos = 0; 904 return pos; 905} 906 907static void delete_cache_dir(char path[PATH_MAX], cache_dir_t* dir) 908{ 909 if (dir->parent != NULL) { 910 create_dir_path(path, dir); 911 ALOGI("DEL DIR %s\n", path); 912 if (dir->hiddenCount <= 0) { 913 if (rmdir(path)) { 914 ALOGE("Couldn't rmdir %s: %s\n", path, strerror(errno)); 915 return; 916 } 917 } else { 918 // The directory contains hidden files so we need to delete 919 // them along with the directory itself. 920 if (delete_dir_contents(path, 1, NULL)) { 921 return; 922 } 923 } 924 dir->parent->childCount--; 925 dir->deleted = 1; 926 if (dir->parent->childCount <= 0) { 927 delete_cache_dir(path, dir->parent); 928 } 929 } else if (dir->hiddenCount > 0) { 930 // This is a root directory, but it has hidden files. Get rid of 931 // all of those files, but not the directory itself. 932 create_dir_path(path, dir); 933 ALOGI("DEL CONTENTS %s\n", path); 934 delete_dir_contents(path, 0, NULL); 935 } 936} 937 938static int cache_modtime_sort(const void *lhsP, const void *rhsP) 939{ 940 const cache_file_t *lhs = *(const cache_file_t**)lhsP; 941 const cache_file_t *rhs = *(const cache_file_t**)rhsP; 942 return lhs->modTime < rhs->modTime ? -1 : (lhs->modTime > rhs->modTime ? 1 : 0); 943} 944 945void clear_cache_files(const std::string& data_path, cache_t* cache, int64_t free_size) 946{ 947 size_t i; 948 int skip = 0; 949 char path[PATH_MAX]; 950 951 ALOGI("Collected cache files: %zd directories, %zd files", 952 cache->numDirs, cache->numFiles); 953 954 CACHE_NOISY(ALOGI("Sorting files...")); 955 qsort(cache->files, cache->numFiles, sizeof(cache_file_t*), 956 cache_modtime_sort); 957 958 CACHE_NOISY(ALOGI("Cleaning empty directories...")); 959 for (i=cache->numDirs; i>0; i--) { 960 cache_dir_t* dir = cache->dirs[i-1]; 961 if (dir->childCount <= 0 && !dir->deleted) { 962 delete_cache_dir(path, dir); 963 } 964 } 965 966 CACHE_NOISY(ALOGI("Trimming files...")); 967 for (i=0; i<cache->numFiles; i++) { 968 skip++; 969 if (skip > 10) { 970 if (data_disk_free(data_path) > free_size) { 971 return; 972 } 973 skip = 0; 974 } 975 cache_file_t* file = cache->files[i]; 976 strcpy(create_dir_path(path, file->dir), file->name); 977 ALOGI("DEL (mod %d) %s\n", (int)file->modTime, path); 978 if (unlink(path) < 0) { 979 ALOGE("Couldn't unlink %s: %s\n", path, strerror(errno)); 980 } 981 file->dir->childCount--; 982 if (file->dir->childCount <= 0) { 983 delete_cache_dir(path, file->dir); 984 } 985 } 986} 987 988void finish_cache_collection(cache_t* cache) 989{ 990 CACHE_NOISY(size_t i;) 991 992 CACHE_NOISY(ALOGI("clear_cache_files: %d dirs, %d files\n", cache->numDirs, cache->numFiles)); 993 CACHE_NOISY( 994 for (i=0; i<cache->numDirs; i++) { 995 cache_dir_t* dir = cache->dirs[i]; 996 ALOGI("dir #%d: %p %s parent=%p\n", i, dir, dir->name, dir->parent); 997 }) 998 CACHE_NOISY( 999 for (i=0; i<cache->numFiles; i++) { 1000 cache_file_t* file = cache->files[i]; 1001 ALOGI("file #%d: %p %s time=%d dir=%p\n", i, file, file->name, 1002 (int)file->modTime, file->dir); 1003 }) 1004 void* block = cache->memBlocks; 1005 while (block != NULL) { 1006 void* nextBlock = *(void**)block; 1007 CACHE_NOISY(ALOGI("Freeing cache mem block: %p", block)); 1008 free(block); 1009 block = nextBlock; 1010 } 1011 free(cache); 1012} 1013 1014/** 1015 * Validate that the path is valid in the context of the provided directory. 1016 * The path is allowed to have at most one subdirectory and no indirections 1017 * to top level directories (i.e. have ".."). 1018 */ 1019static int validate_path(const dir_rec_t* dir, const char* path, int maxSubdirs) { 1020 size_t dir_len = dir->len; 1021 const char* subdir = strchr(path + dir_len, '/'); 1022 1023 // Only allow the path to have at most one subdirectory. 1024 if (subdir != NULL) { 1025 ++subdir; 1026 if ((--maxSubdirs == 0) && strchr(subdir, '/') != NULL) { 1027 ALOGE("invalid apk path '%s' (subdir?)\n", path); 1028 return -1; 1029 } 1030 } 1031 1032 // Directories can't have a period directly after the directory markers to prevent "..". 1033 if ((path[dir_len] == '.') || ((subdir != NULL) && (*subdir == '.'))) { 1034 ALOGE("invalid apk path '%s' (trickery)\n", path); 1035 return -1; 1036 } 1037 1038 return 0; 1039} 1040 1041/** 1042 * Checks whether a path points to a system app (.apk file). Returns 0 1043 * if it is a system app or -1 if it is not. 1044 */ 1045int validate_system_app_path(const char* path) { 1046 size_t i; 1047 1048 for (i = 0; i < android_system_dirs.count; i++) { 1049 const size_t dir_len = android_system_dirs.dirs[i].len; 1050 if (!strncmp(path, android_system_dirs.dirs[i].path, dir_len)) { 1051 return validate_path(android_system_dirs.dirs + i, path, 1); 1052 } 1053 } 1054 1055 return -1; 1056} 1057 1058/** 1059 * Get the contents of a environment variable that contains a path. Caller 1060 * owns the string that is inserted into the directory record. Returns 1061 * 0 on success and -1 on error. 1062 */ 1063int get_path_from_env(dir_rec_t* rec, const char* var) { 1064 const char* path = getenv(var); 1065 int ret = get_path_from_string(rec, path); 1066 if (ret < 0) { 1067 ALOGW("Problem finding value for environment variable %s\n", var); 1068 } 1069 return ret; 1070} 1071 1072/** 1073 * Puts the string into the record as a directory. Appends '/' to the end 1074 * of all paths. Caller owns the string that is inserted into the directory 1075 * record. A null value will result in an error. 1076 * 1077 * Returns 0 on success and -1 on error. 1078 */ 1079int get_path_from_string(dir_rec_t* rec, const char* path) { 1080 if (path == NULL) { 1081 return -1; 1082 } else { 1083 const size_t path_len = strlen(path); 1084 if (path_len <= 0) { 1085 return -1; 1086 } 1087 1088 // Make sure path is absolute. 1089 if (path[0] != '/') { 1090 return -1; 1091 } 1092 1093 if (path[path_len - 1] == '/') { 1094 // Path ends with a forward slash. Make our own copy. 1095 1096 rec->path = strdup(path); 1097 if (rec->path == NULL) { 1098 return -1; 1099 } 1100 1101 rec->len = path_len; 1102 } else { 1103 // Path does not end with a slash. Generate a new string. 1104 char *dst; 1105 1106 // Add space for slash and terminating null. 1107 size_t dst_size = path_len + 2; 1108 1109 rec->path = (char*) malloc(dst_size); 1110 if (rec->path == NULL) { 1111 return -1; 1112 } 1113 1114 dst = rec->path; 1115 1116 if (append_and_increment(&dst, path, &dst_size) < 0 1117 || append_and_increment(&dst, "/", &dst_size)) { 1118 ALOGE("Error canonicalizing path"); 1119 return -1; 1120 } 1121 1122 rec->len = dst - rec->path; 1123 } 1124 } 1125 return 0; 1126} 1127 1128int copy_and_append(dir_rec_t* dst, const dir_rec_t* src, const char* suffix) { 1129 dst->len = src->len + strlen(suffix); 1130 const size_t dstSize = dst->len + 1; 1131 dst->path = (char*) malloc(dstSize); 1132 1133 if (dst->path == NULL 1134 || snprintf(dst->path, dstSize, "%s%s", src->path, suffix) 1135 != (ssize_t) dst->len) { 1136 ALOGE("Could not allocate memory to hold appended path; aborting\n"); 1137 return -1; 1138 } 1139 1140 return 0; 1141} 1142 1143/** 1144 * Check whether path points to a valid path for an APK file. The path must 1145 * begin with a whitelisted prefix path and must be no deeper than |maxSubdirs| within 1146 * that path. Returns -1 when an invalid path is encountered and 0 when a valid path 1147 * is encountered. 1148 */ 1149static int validate_apk_path_internal(const char *path, int maxSubdirs) { 1150 const dir_rec_t* dir = NULL; 1151 if (!strncmp(path, android_app_dir.path, android_app_dir.len)) { 1152 dir = &android_app_dir; 1153 } else if (!strncmp(path, android_app_private_dir.path, android_app_private_dir.len)) { 1154 dir = &android_app_private_dir; 1155 } else if (!strncmp(path, android_app_ephemeral_dir.path, android_app_ephemeral_dir.len)) { 1156 dir = &android_app_ephemeral_dir; 1157 } else if (!strncmp(path, android_asec_dir.path, android_asec_dir.len)) { 1158 dir = &android_asec_dir; 1159 } else if (!strncmp(path, android_mnt_expand_dir.path, android_mnt_expand_dir.len)) { 1160 dir = &android_mnt_expand_dir; 1161 if (maxSubdirs < 2) { 1162 maxSubdirs = 2; 1163 } 1164 } else { 1165 return -1; 1166 } 1167 1168 return validate_path(dir, path, maxSubdirs); 1169} 1170 1171int validate_apk_path(const char* path) { 1172 return validate_apk_path_internal(path, 1 /* maxSubdirs */); 1173} 1174 1175int validate_apk_path_subdirs(const char* path) { 1176 return validate_apk_path_internal(path, 3 /* maxSubdirs */); 1177} 1178 1179int append_and_increment(char** dst, const char* src, size_t* dst_size) { 1180 ssize_t ret = strlcpy(*dst, src, *dst_size); 1181 if (ret < 0 || (size_t) ret >= *dst_size) { 1182 return -1; 1183 } 1184 *dst += ret; 1185 *dst_size -= ret; 1186 return 0; 1187} 1188 1189char *build_string2(const char *s1, const char *s2) { 1190 if (s1 == NULL || s2 == NULL) return NULL; 1191 1192 int len_s1 = strlen(s1); 1193 int len_s2 = strlen(s2); 1194 int len = len_s1 + len_s2 + 1; 1195 char *result = (char *) malloc(len); 1196 if (result == NULL) return NULL; 1197 1198 strcpy(result, s1); 1199 strcpy(result + len_s1, s2); 1200 1201 return result; 1202} 1203 1204char *build_string3(const char *s1, const char *s2, const char *s3) { 1205 if (s1 == NULL || s2 == NULL || s3 == NULL) return NULL; 1206 1207 int len_s1 = strlen(s1); 1208 int len_s2 = strlen(s2); 1209 int len_s3 = strlen(s3); 1210 int len = len_s1 + len_s2 + len_s3 + 1; 1211 char *result = (char *) malloc(len); 1212 if (result == NULL) return NULL; 1213 1214 strcpy(result, s1); 1215 strcpy(result + len_s1, s2); 1216 strcpy(result + len_s1 + len_s2, s3); 1217 1218 return result; 1219} 1220 1221int ensure_config_user_dirs(userid_t userid) { 1222 char config_user_path[PATH_MAX]; 1223 1224 // writable by system, readable by any app within the same user 1225 const int uid = multiuser_get_uid(userid, AID_SYSTEM); 1226 const int gid = multiuser_get_uid(userid, AID_EVERYBODY); 1227 1228 // Ensure /data/misc/user/<userid> exists 1229 create_user_config_path(config_user_path, userid); 1230 if (fs_prepare_dir(config_user_path, 0750, uid, gid) == -1) { 1231 return -1; 1232 } 1233 1234 return 0; 1235} 1236 1237int wait_child(pid_t pid) 1238{ 1239 int status; 1240 pid_t got_pid; 1241 1242 while (1) { 1243 got_pid = waitpid(pid, &status, 0); 1244 if (got_pid == -1 && errno == EINTR) { 1245 printf("waitpid interrupted, retrying\n"); 1246 } else { 1247 break; 1248 } 1249 } 1250 if (got_pid != pid) { 1251 ALOGW("waitpid failed: wanted %d, got %d: %s\n", 1252 (int) pid, (int) got_pid, strerror(errno)); 1253 return 1; 1254 } 1255 1256 if (WIFEXITED(status) && WEXITSTATUS(status) == 0) { 1257 return 0; 1258 } else { 1259 return status; /* always nonzero */ 1260 } 1261} 1262 1263} // namespace installd 1264} // namespace android 1265