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