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