Home | History | Annotate | Download | only in installd
      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 <fts.h>
     22 #include <stdlib.h>
     23 #include <sys/stat.h>
     24 #include <sys/wait.h>
     25 #include <sys/xattr.h>
     26 #include <sys/statvfs.h>
     27 
     28 #include <android-base/logging.h>
     29 #include <android-base/stringprintf.h>
     30 #include <cutils/fs.h>
     31 #include <cutils/properties.h>
     32 #include <log/log.h>
     33 #include <private/android_filesystem_config.h>
     34 
     35 #include "globals.h"  // extern variables.
     36 
     37 #ifndef LOG_TAG
     38 #define LOG_TAG "installd"
     39 #endif
     40 
     41 #define DEBUG_XATTRS 0
     42 
     43 using android::base::StringPrintf;
     44 
     45 namespace android {
     46 namespace installd {
     47 
     48 /**
     49  * Check that given string is valid filename, and that it attempts no
     50  * parent or child directory traversal.
     51  */
     52 bool is_valid_filename(const std::string& name) {
     53     if (name.empty() || (name == ".") || (name == "..")
     54             || (name.find('/') != std::string::npos)) {
     55         return false;
     56     } else {
     57         return true;
     58     }
     59 }
     60 
     61 static void check_package_name(const char* package_name) {
     62     CHECK(is_valid_filename(package_name));
     63     CHECK(is_valid_package_name(package_name));
     64 }
     65 
     66 /**
     67  * Create the path name where package app contents should be stored for
     68  * the given volume UUID and package name.  An empty UUID is assumed to
     69  * be internal storage.
     70  */
     71 std::string create_data_app_package_path(const char* volume_uuid,
     72         const char* package_name) {
     73     check_package_name(package_name);
     74     return StringPrintf("%s/%s",
     75             create_data_app_path(volume_uuid).c_str(), package_name);
     76 }
     77 
     78 /**
     79  * Create the path name where package data should be stored for the given
     80  * volume UUID, package name, and user ID. An empty UUID is assumed to be
     81  * internal storage.
     82  */
     83 std::string create_data_user_ce_package_path(const char* volume_uuid,
     84         userid_t user, const char* package_name) {
     85     check_package_name(package_name);
     86     return StringPrintf("%s/%s",
     87             create_data_user_ce_path(volume_uuid, user).c_str(), package_name);
     88 }
     89 
     90 std::string create_data_user_ce_package_path(const char* volume_uuid, userid_t user,
     91         const char* package_name, ino_t ce_data_inode) {
     92     // For testing purposes, rely on the inode when defined; this could be
     93     // optimized to use access() in the future.
     94     auto fallback = create_data_user_ce_package_path(volume_uuid, user, package_name);
     95     if (ce_data_inode != 0) {
     96         auto user_path = create_data_user_ce_path(volume_uuid, user);
     97         DIR* dir = opendir(user_path.c_str());
     98         if (dir == nullptr) {
     99             PLOG(ERROR) << "Failed to opendir " << user_path;
    100             return fallback;
    101         }
    102 
    103         struct dirent* ent;
    104         while ((ent = readdir(dir))) {
    105             if (ent->d_ino == ce_data_inode) {
    106                 auto resolved = StringPrintf("%s/%s", user_path.c_str(), ent->d_name);
    107 #if DEBUG_XATTRS
    108                 if (resolved != fallback) {
    109                     LOG(DEBUG) << "Resolved path " << resolved << " for inode " << ce_data_inode
    110                             << " instead of " << fallback;
    111                 }
    112 #endif
    113                 closedir(dir);
    114                 return resolved;
    115             }
    116         }
    117         LOG(WARNING) << "Failed to resolve inode " << ce_data_inode << "; using " << fallback;
    118         closedir(dir);
    119         return fallback;
    120     } else {
    121         return fallback;
    122     }
    123 }
    124 
    125 std::string create_data_user_de_package_path(const char* volume_uuid,
    126         userid_t user, const char* package_name) {
    127     check_package_name(package_name);
    128     return StringPrintf("%s/%s",
    129             create_data_user_de_path(volume_uuid, user).c_str(), package_name);
    130 }
    131 
    132 int create_pkg_path(char path[PKG_PATH_MAX], const char *pkgname,
    133         const char *postfix, userid_t userid) {
    134     if (!is_valid_package_name(pkgname)) {
    135         path[0] = '\0';
    136         return -1;
    137     }
    138 
    139     std::string _tmp(create_data_user_ce_package_path(nullptr, userid, pkgname) + postfix);
    140     const char* tmp = _tmp.c_str();
    141     if (strlen(tmp) >= PKG_PATH_MAX) {
    142         path[0] = '\0';
    143         return -1;
    144     } else {
    145         strcpy(path, tmp);
    146         return 0;
    147     }
    148 }
    149 
    150 std::string create_data_path(const char* volume_uuid) {
    151     if (volume_uuid == nullptr) {
    152         return "/data";
    153     } else if (!strcmp(volume_uuid, "TEST")) {
    154         CHECK(property_get_bool("ro.debuggable", false));
    155         return "/data/local/tmp";
    156     } else {
    157         CHECK(is_valid_filename(volume_uuid));
    158         return StringPrintf("/mnt/expand/%s", volume_uuid);
    159     }
    160 }
    161 
    162 /**
    163  * Create the path name for app data.
    164  */
    165 std::string create_data_app_path(const char* volume_uuid) {
    166     return StringPrintf("%s/app", create_data_path(volume_uuid).c_str());
    167 }
    168 
    169 /**
    170  * Create the path name for user data for a certain userid.
    171  * Keep same implementation as vold to minimize path walking overhead
    172  */
    173 std::string create_data_user_ce_path(const char* volume_uuid, userid_t userid) {
    174     std::string data(create_data_path(volume_uuid));
    175     if (volume_uuid == nullptr && userid == 0) {
    176         std::string legacy = StringPrintf("%s/data", data.c_str());
    177         struct stat sb;
    178         if (lstat(legacy.c_str(), &sb) == 0 && S_ISDIR(sb.st_mode)) {
    179             /* /data/data is dir, return /data/data for legacy system */
    180             return legacy;
    181         }
    182     }
    183     return StringPrintf("%s/user/%u", data.c_str(), userid);
    184 }
    185 
    186 /**
    187  * Create the path name for device encrypted user data for a certain userid.
    188  */
    189 std::string create_data_user_de_path(const char* volume_uuid, userid_t userid) {
    190     std::string data(create_data_path(volume_uuid));
    191     return StringPrintf("%s/user_de/%u", data.c_str(), userid);
    192 }
    193 
    194 /**
    195  * Create the path name for media for a certain userid.
    196  */
    197 std::string create_data_media_path(const char* volume_uuid, userid_t userid) {
    198     return StringPrintf("%s/media/%u", create_data_path(volume_uuid).c_str(), userid);
    199 }
    200 
    201 std::string create_data_media_obb_path(const char* volume_uuid, const char* package_name) {
    202     return StringPrintf("%s/media/obb/%s", create_data_path(volume_uuid).c_str(), package_name);
    203 }
    204 
    205 std::string create_data_media_package_path(const char* volume_uuid, userid_t userid,
    206         const char* data_type, const char* package_name) {
    207     return StringPrintf("%s/Android/%s/%s", create_data_media_path(volume_uuid, userid).c_str(),
    208             data_type, package_name);
    209 }
    210 
    211 std::string create_data_misc_legacy_path(userid_t userid) {
    212     return StringPrintf("%s/misc/user/%u", create_data_path(nullptr).c_str(), userid);
    213 }
    214 
    215 std::string create_primary_cur_profile_dir_path(userid_t userid) {
    216     return StringPrintf("%s/cur/%u", android_profiles_dir.path, userid);
    217 }
    218 
    219 std::string create_primary_current_profile_package_dir_path(userid_t user,
    220         const std::string& package_name) {
    221     check_package_name(package_name.c_str());
    222     return StringPrintf("%s/%s",
    223             create_primary_cur_profile_dir_path(user).c_str(), package_name.c_str());
    224 }
    225 
    226 std::string create_primary_ref_profile_dir_path() {
    227     return StringPrintf("%s/ref", android_profiles_dir.path);
    228 }
    229 
    230 std::string create_primary_reference_profile_package_dir_path(const std::string& package_name) {
    231     check_package_name(package_name.c_str());
    232     return StringPrintf("%s/ref/%s", android_profiles_dir.path, package_name.c_str());
    233 }
    234 
    235 std::string create_data_dalvik_cache_path() {
    236     return "/data/dalvik-cache";
    237 }
    238 
    239 // Keep profile paths in sync with ActivityThread and LoadedApk.
    240 const std::string PROFILE_EXT = ".prof";
    241 const std::string CURRENT_PROFILE_EXT = ".cur";
    242 const std::string PRIMARY_PROFILE_NAME = "primary" + PROFILE_EXT;
    243 
    244 // Gets the parent directory and the file name for the given secondary dex path.
    245 // Returns true on success, false on failure (if the dex_path does not have the expected
    246 // structure).
    247 static bool get_secondary_dex_location(const std::string& dex_path,
    248         std::string* out_dir_name, std::string* out_file_name) {
    249    size_t dirIndex = dex_path.rfind('/');
    250    if (dirIndex == std::string::npos) {
    251         return false;
    252    }
    253    if (dirIndex == dex_path.size() - 1) {
    254         return false;
    255    }
    256    *out_dir_name = dex_path.substr(0, dirIndex);
    257    *out_file_name = dex_path.substr(dirIndex + 1);
    258 
    259    return true;
    260 }
    261 
    262 std::string create_current_profile_path(userid_t user, const std::string& location,
    263         bool is_secondary_dex) {
    264     if (is_secondary_dex) {
    265         // Secondary dex current profiles are stored next to the dex files under the oat folder.
    266         std::string dex_dir;
    267         std::string dex_name;
    268         CHECK(get_secondary_dex_location(location, &dex_dir, &dex_name))
    269                 << "Unexpected dir structure for secondary dex " << location;
    270         return StringPrintf("%s/oat/%s%s%s",
    271                 dex_dir.c_str(), dex_name.c_str(), CURRENT_PROFILE_EXT.c_str(),
    272                 PROFILE_EXT.c_str());
    273     } else {
    274         // Profiles for primary apks are under /data/misc/profiles/cur.
    275         std::string profile_dir = create_primary_current_profile_package_dir_path(user, location);
    276         return StringPrintf("%s/%s", profile_dir.c_str(), PRIMARY_PROFILE_NAME.c_str());
    277     }
    278 }
    279 
    280 std::string create_reference_profile_path(const std::string& location, bool is_secondary_dex) {
    281     if (is_secondary_dex) {
    282         // Secondary dex reference profiles are stored next to the dex files under the oat folder.
    283         std::string dex_dir;
    284         std::string dex_name;
    285         CHECK(get_secondary_dex_location(location, &dex_dir, &dex_name))
    286                 << "Unexpected dir structure for secondary dex " << location;
    287         return StringPrintf("%s/oat/%s%s",
    288                 dex_dir.c_str(), dex_name.c_str(), PROFILE_EXT.c_str());
    289     } else {
    290         // Reference profiles for primary apks are stored in /data/misc/profile/ref.
    291         std::string profile_dir = create_primary_reference_profile_package_dir_path(location);
    292         return StringPrintf("%s/%s", profile_dir.c_str(), PRIMARY_PROFILE_NAME.c_str());
    293     }
    294 }
    295 
    296 std::vector<userid_t> get_known_users(const char* volume_uuid) {
    297     std::vector<userid_t> users;
    298 
    299     // We always have an owner
    300     users.push_back(0);
    301 
    302     std::string path(create_data_path(volume_uuid) + "/" + SECONDARY_USER_PREFIX);
    303     DIR* dir = opendir(path.c_str());
    304     if (dir == NULL) {
    305         // Unable to discover other users, but at least return owner
    306         PLOG(ERROR) << "Failed to opendir " << path;
    307         return users;
    308     }
    309 
    310     struct dirent* ent;
    311     while ((ent = readdir(dir))) {
    312         if (ent->d_type != DT_DIR) {
    313             continue;
    314         }
    315 
    316         char* end;
    317         userid_t user = strtol(ent->d_name, &end, 10);
    318         if (*end == '\0' && user != 0) {
    319             LOG(DEBUG) << "Found valid user " << user;
    320             users.push_back(user);
    321         }
    322     }
    323     closedir(dir);
    324 
    325     return users;
    326 }
    327 
    328 int calculate_tree_size(const std::string& path, int64_t* size,
    329         int32_t include_gid, int32_t exclude_gid, bool exclude_apps) {
    330     FTS *fts;
    331     FTSENT *p;
    332     int64_t matchedSize = 0;
    333     char *argv[] = { (char*) path.c_str(), nullptr };
    334     if (!(fts = fts_open(argv, FTS_PHYSICAL | FTS_NOCHDIR | FTS_XDEV, NULL))) {
    335         if (errno != ENOENT) {
    336             PLOG(ERROR) << "Failed to fts_open " << path;
    337         }
    338         return -1;
    339     }
    340     while ((p = fts_read(fts)) != NULL) {
    341         switch (p->fts_info) {
    342         case FTS_D:
    343         case FTS_DEFAULT:
    344         case FTS_F:
    345         case FTS_SL:
    346         case FTS_SLNONE:
    347             int32_t uid = p->fts_statp->st_uid;
    348             int32_t gid = p->fts_statp->st_gid;
    349             int32_t user_uid = multiuser_get_app_id(uid);
    350             int32_t user_gid = multiuser_get_app_id(gid);
    351             if (exclude_apps && ((user_uid >= AID_APP_START && user_uid <= AID_APP_END)
    352                     || (user_gid >= AID_CACHE_GID_START && user_gid <= AID_CACHE_GID_END)
    353                     || (user_gid >= AID_SHARED_GID_START && user_gid <= AID_SHARED_GID_END))) {
    354                 // Don't traverse inside or measure
    355                 fts_set(fts, p, FTS_SKIP);
    356                 break;
    357             }
    358             if (include_gid != -1 && gid != include_gid) {
    359                 break;
    360             }
    361             if (exclude_gid != -1 && gid == exclude_gid) {
    362                 break;
    363             }
    364             matchedSize += (p->fts_statp->st_blocks * 512);
    365             break;
    366         }
    367     }
    368     fts_close(fts);
    369 #if MEASURE_DEBUG
    370     if ((include_gid == -1) && (exclude_gid == -1)) {
    371         LOG(DEBUG) << "Measured " << path << " size " << matchedSize;
    372     } else {
    373         LOG(DEBUG) << "Measured " << path << " size " << matchedSize << "; include " << include_gid
    374                 << " exclude " << exclude_gid;
    375     }
    376 #endif
    377     *size += matchedSize;
    378     return 0;
    379 }
    380 
    381 int create_move_path(char path[PKG_PATH_MAX],
    382     const char* pkgname,
    383     const char* leaf,
    384     userid_t userid ATTRIBUTE_UNUSED)
    385 {
    386     if ((android_data_dir.len + strlen(PRIMARY_USER_PREFIX) + strlen(pkgname) + strlen(leaf) + 1)
    387             >= PKG_PATH_MAX) {
    388         return -1;
    389     }
    390 
    391     sprintf(path, "%s%s%s/%s", android_data_dir.path, PRIMARY_USER_PREFIX, pkgname, leaf);
    392     return 0;
    393 }
    394 
    395 /**
    396  * Checks whether the package name is valid. Returns -1 on error and
    397  * 0 on success.
    398  */
    399 bool is_valid_package_name(const std::string& packageName) {
    400     // This logic is borrowed from PackageParser.java
    401     bool hasSep = false;
    402     bool front = true;
    403 
    404     auto it = packageName.begin();
    405     for (; it != packageName.end() && *it != '-'; it++) {
    406         char c = *it;
    407         if ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')) {
    408             front = false;
    409             continue;
    410         }
    411         if (!front) {
    412             if ((c >= '0' && c <= '9') || c == '_') {
    413                 continue;
    414             }
    415         }
    416         if (c == '.') {
    417             hasSep = true;
    418             front = true;
    419             continue;
    420         }
    421         LOG(WARNING) << "Bad package character " << c << " in " << packageName;
    422         return false;
    423     }
    424 
    425     if (front) {
    426         LOG(WARNING) << "Missing separator in " << packageName;
    427         return false;
    428     }
    429 
    430     for (; it != packageName.end(); it++) {
    431         char c = *it;
    432         if ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')) continue;
    433         if ((c >= '0' && c <= '9') || c == '_' || c == '-' || c == '=') continue;
    434         LOG(WARNING) << "Bad suffix character " << c << " in " << packageName;
    435         return false;
    436     }
    437 
    438     return true;
    439 }
    440 
    441 static int _delete_dir_contents(DIR *d,
    442                                 int (*exclusion_predicate)(const char *name, const int is_dir))
    443 {
    444     int result = 0;
    445     struct dirent *de;
    446     int dfd;
    447 
    448     dfd = dirfd(d);
    449 
    450     if (dfd < 0) return -1;
    451 
    452     while ((de = readdir(d))) {
    453         const char *name = de->d_name;
    454 
    455             /* check using the exclusion predicate, if provided */
    456         if (exclusion_predicate && exclusion_predicate(name, (de->d_type == DT_DIR))) {
    457             continue;
    458         }
    459 
    460         if (de->d_type == DT_DIR) {
    461             int subfd;
    462             DIR *subdir;
    463 
    464                 /* always skip "." and ".." */
    465             if (name[0] == '.') {
    466                 if (name[1] == 0) continue;
    467                 if ((name[1] == '.') && (name[2] == 0)) continue;
    468             }
    469 
    470             subfd = openat(dfd, name, O_RDONLY | O_DIRECTORY | O_NOFOLLOW | O_CLOEXEC);
    471             if (subfd < 0) {
    472                 ALOGE("Couldn't openat %s: %s\n", name, strerror(errno));
    473                 result = -1;
    474                 continue;
    475             }
    476             subdir = fdopendir(subfd);
    477             if (subdir == NULL) {
    478                 ALOGE("Couldn't fdopendir %s: %s\n", name, strerror(errno));
    479                 close(subfd);
    480                 result = -1;
    481                 continue;
    482             }
    483             if (_delete_dir_contents(subdir, exclusion_predicate)) {
    484                 result = -1;
    485             }
    486             closedir(subdir);
    487             if (unlinkat(dfd, name, AT_REMOVEDIR) < 0) {
    488                 ALOGE("Couldn't unlinkat %s: %s\n", name, strerror(errno));
    489                 result = -1;
    490             }
    491         } else {
    492             if (unlinkat(dfd, name, 0) < 0) {
    493                 ALOGE("Couldn't unlinkat %s: %s\n", name, strerror(errno));
    494                 result = -1;
    495             }
    496         }
    497     }
    498 
    499     return result;
    500 }
    501 
    502 int delete_dir_contents(const std::string& pathname, bool ignore_if_missing) {
    503     return delete_dir_contents(pathname.c_str(), 0, NULL, ignore_if_missing);
    504 }
    505 
    506 int delete_dir_contents_and_dir(const std::string& pathname, bool ignore_if_missing) {
    507     return delete_dir_contents(pathname.c_str(), 1, NULL, ignore_if_missing);
    508 }
    509 
    510 int delete_dir_contents(const char *pathname,
    511                         int also_delete_dir,
    512                         int (*exclusion_predicate)(const char*, const int),
    513                         bool ignore_if_missing)
    514 {
    515     int res = 0;
    516     DIR *d;
    517 
    518     d = opendir(pathname);
    519     if (d == NULL) {
    520         if (ignore_if_missing && (errno == ENOENT)) {
    521             return 0;
    522         }
    523         ALOGE("Couldn't opendir %s: %s\n", pathname, strerror(errno));
    524         return -errno;
    525     }
    526     res = _delete_dir_contents(d, exclusion_predicate);
    527     closedir(d);
    528     if (also_delete_dir) {
    529         if (rmdir(pathname)) {
    530             ALOGE("Couldn't rmdir %s: %s\n", pathname, strerror(errno));
    531             res = -1;
    532         }
    533     }
    534     return res;
    535 }
    536 
    537 int delete_dir_contents_fd(int dfd, const char *name)
    538 {
    539     int fd, res;
    540     DIR *d;
    541 
    542     fd = openat(dfd, name, O_RDONLY | O_DIRECTORY | O_NOFOLLOW | O_CLOEXEC);
    543     if (fd < 0) {
    544         ALOGE("Couldn't openat %s: %s\n", name, strerror(errno));
    545         return -1;
    546     }
    547     d = fdopendir(fd);
    548     if (d == NULL) {
    549         ALOGE("Couldn't fdopendir %s: %s\n", name, strerror(errno));
    550         close(fd);
    551         return -1;
    552     }
    553     res = _delete_dir_contents(d, 0);
    554     closedir(d);
    555     return res;
    556 }
    557 
    558 static int _copy_owner_permissions(int srcfd, int dstfd)
    559 {
    560     struct stat st;
    561     if (fstat(srcfd, &st) != 0) {
    562         return -1;
    563     }
    564     if (fchmod(dstfd, st.st_mode) != 0) {
    565         return -1;
    566     }
    567     return 0;
    568 }
    569 
    570 static int _copy_dir_files(int sdfd, int ddfd, uid_t owner, gid_t group)
    571 {
    572     int result = 0;
    573     if (_copy_owner_permissions(sdfd, ddfd) != 0) {
    574         ALOGE("_copy_dir_files failed to copy dir permissions\n");
    575     }
    576     if (fchown(ddfd, owner, group) != 0) {
    577         ALOGE("_copy_dir_files failed to change dir owner\n");
    578     }
    579 
    580     DIR *ds = fdopendir(sdfd);
    581     if (ds == NULL) {
    582         ALOGE("Couldn't fdopendir: %s\n", strerror(errno));
    583         return -1;
    584     }
    585     struct dirent *de;
    586     while ((de = readdir(ds))) {
    587         if (de->d_type != DT_REG) {
    588             continue;
    589         }
    590 
    591         const char *name = de->d_name;
    592         int fsfd = openat(sdfd, name, O_RDONLY | O_NOFOLLOW | O_CLOEXEC);
    593         int fdfd = openat(ddfd, name, O_WRONLY | O_NOFOLLOW | O_CLOEXEC | O_CREAT, 0600);
    594         if (fsfd == -1 || fdfd == -1) {
    595             ALOGW("Couldn't copy %s: %s\n", name, strerror(errno));
    596         } else {
    597             if (_copy_owner_permissions(fsfd, fdfd) != 0) {
    598                 ALOGE("Failed to change file permissions\n");
    599             }
    600             if (fchown(fdfd, owner, group) != 0) {
    601                 ALOGE("Failed to change file owner\n");
    602             }
    603 
    604             char buf[8192];
    605             ssize_t size;
    606             while ((size = read(fsfd, buf, sizeof(buf))) > 0) {
    607                 write(fdfd, buf, size);
    608             }
    609             if (size < 0) {
    610                 ALOGW("Couldn't copy %s: %s\n", name, strerror(errno));
    611                 result = -1;
    612             }
    613         }
    614         close(fdfd);
    615         close(fsfd);
    616     }
    617 
    618     return result;
    619 }
    620 
    621 int copy_dir_files(const char *srcname,
    622                    const char *dstname,
    623                    uid_t owner,
    624                    uid_t group)
    625 {
    626     int res = 0;
    627     DIR *ds = NULL;
    628     DIR *dd = NULL;
    629 
    630     ds = opendir(srcname);
    631     if (ds == NULL) {
    632         ALOGE("Couldn't opendir %s: %s\n", srcname, strerror(errno));
    633         return -errno;
    634     }
    635 
    636     mkdir(dstname, 0600);
    637     dd = opendir(dstname);
    638     if (dd == NULL) {
    639         ALOGE("Couldn't opendir %s: %s\n", dstname, strerror(errno));
    640         closedir(ds);
    641         return -errno;
    642     }
    643 
    644     int sdfd = dirfd(ds);
    645     int ddfd = dirfd(dd);
    646     if (sdfd != -1 && ddfd != -1) {
    647         res = _copy_dir_files(sdfd, ddfd, owner, group);
    648     } else {
    649         res = -errno;
    650     }
    651     closedir(dd);
    652     closedir(ds);
    653     return res;
    654 }
    655 
    656 int64_t data_disk_free(const std::string& data_path) {
    657     struct statvfs sfs;
    658     if (statvfs(data_path.c_str(), &sfs) == 0) {
    659         return static_cast<int64_t>(sfs.f_bavail) * sfs.f_frsize;
    660     } else {
    661         PLOG(ERROR) << "Couldn't statvfs " << data_path;
    662         return -1;
    663     }
    664 }
    665 
    666 int get_path_inode(const std::string& path, ino_t *inode) {
    667     struct stat buf;
    668     memset(&buf, 0, sizeof(buf));
    669     if (stat(path.c_str(), &buf) != 0) {
    670         PLOG(WARNING) << "Failed to stat " << path;
    671         return -1;
    672     } else {
    673         *inode = buf.st_ino;
    674         return 0;
    675     }
    676 }
    677 
    678 /**
    679  * Write the inode of a specific child file into the given xattr on the
    680  * parent directory. This allows you to find the child later, even if its
    681  * name is encrypted.
    682  */
    683 int write_path_inode(const std::string& parent, const char* name, const char* inode_xattr) {
    684     ino_t inode = 0;
    685     uint64_t inode_raw = 0;
    686     auto path = StringPrintf("%s/%s", parent.c_str(), name);
    687 
    688     if (get_path_inode(path, &inode) != 0) {
    689         // Path probably doesn't exist yet; ignore
    690         return 0;
    691     }
    692 
    693     // Check to see if already set correctly
    694     if (getxattr(parent.c_str(), inode_xattr, &inode_raw, sizeof(inode_raw)) == sizeof(inode_raw)) {
    695         if (inode_raw == inode) {
    696             // Already set correctly; skip writing
    697             return 0;
    698         } else {
    699             PLOG(WARNING) << "Mismatched inode value; found " << inode
    700                     << " on disk but marked value was " << inode_raw << "; overwriting";
    701         }
    702     }
    703 
    704     inode_raw = inode;
    705     if (setxattr(parent.c_str(), inode_xattr, &inode_raw, sizeof(inode_raw), 0) != 0 && errno != EOPNOTSUPP) {
    706         PLOG(ERROR) << "Failed to write xattr " << inode_xattr << " at " << parent;
    707         return -1;
    708     } else {
    709         return 0;
    710     }
    711 }
    712 
    713 /**
    714  * Read the inode of a specific child file from the given xattr on the
    715  * parent directory. Returns a currently valid path for that child, which
    716  * might have an encrypted name.
    717  */
    718 std::string read_path_inode(const std::string& parent, const char* name, const char* inode_xattr) {
    719     ino_t inode = 0;
    720     uint64_t inode_raw = 0;
    721     auto fallback = StringPrintf("%s/%s", parent.c_str(), name);
    722 
    723     // Lookup the inode value written earlier
    724     if (getxattr(parent.c_str(), inode_xattr, &inode_raw, sizeof(inode_raw)) == sizeof(inode_raw)) {
    725         inode = inode_raw;
    726     }
    727 
    728     // For testing purposes, rely on the inode when defined; this could be
    729     // optimized to use access() in the future.
    730     if (inode != 0) {
    731         DIR* dir = opendir(parent.c_str());
    732         if (dir == nullptr) {
    733             PLOG(ERROR) << "Failed to opendir " << parent;
    734             return fallback;
    735         }
    736 
    737         struct dirent* ent;
    738         while ((ent = readdir(dir))) {
    739             if (ent->d_ino == inode) {
    740                 auto resolved = StringPrintf("%s/%s", parent.c_str(), ent->d_name);
    741 #if DEBUG_XATTRS
    742                 if (resolved != fallback) {
    743                     LOG(DEBUG) << "Resolved path " << resolved << " for inode " << inode
    744                             << " instead of " << fallback;
    745                 }
    746 #endif
    747                 closedir(dir);
    748                 return resolved;
    749             }
    750         }
    751         LOG(WARNING) << "Failed to resolve inode " << inode << "; using " << fallback;
    752         closedir(dir);
    753         return fallback;
    754     } else {
    755         return fallback;
    756     }
    757 }
    758 
    759 /**
    760  * Validate that the path is valid in the context of the provided directory.
    761  * The path is allowed to have at most one subdirectory and no indirections
    762  * to top level directories (i.e. have "..").
    763  */
    764 static int validate_path(const dir_rec_t* dir, const char* path, int maxSubdirs) {
    765     size_t dir_len = dir->len;
    766     const char* subdir = strchr(path + dir_len, '/');
    767 
    768     // Only allow the path to have at most one subdirectory.
    769     if (subdir != NULL) {
    770         ++subdir;
    771         if ((--maxSubdirs == 0) && strchr(subdir, '/') != NULL) {
    772             ALOGE("invalid apk path '%s' (subdir?)\n", path);
    773             return -1;
    774         }
    775     }
    776 
    777     // Directories can't have a period directly after the directory markers to prevent "..".
    778     if ((path[dir_len] == '.') || ((subdir != NULL) && (*subdir == '.'))) {
    779         ALOGE("invalid apk path '%s' (trickery)\n", path);
    780         return -1;
    781     }
    782 
    783     return 0;
    784 }
    785 
    786 /**
    787  * Checks whether a path points to a system app (.apk file). Returns 0
    788  * if it is a system app or -1 if it is not.
    789  */
    790 int validate_system_app_path(const char* path) {
    791     size_t i;
    792 
    793     for (i = 0; i < android_system_dirs.count; i++) {
    794         const size_t dir_len = android_system_dirs.dirs[i].len;
    795         if (!strncmp(path, android_system_dirs.dirs[i].path, dir_len)) {
    796             return validate_path(android_system_dirs.dirs + i, path, 1);
    797         }
    798     }
    799 
    800     return -1;
    801 }
    802 
    803 bool validate_secondary_dex_path(const std::string& pkgname, const std::string& dex_path,
    804         const char* volume_uuid, int uid, int storage_flag, bool validate_package_path) {
    805     CHECK(storage_flag == FLAG_STORAGE_CE || storage_flag == FLAG_STORAGE_DE);
    806 
    807     // Empty paths are not allowed.
    808     if (dex_path.empty()) { return false; }
    809     // First character should always be '/'. No relative paths.
    810     if (dex_path[0] != '/') { return false; }
    811     // The last character should not be '/'.
    812     if (dex_path[dex_path.size() - 1] == '/') { return false; }
    813     // There should be no '.' after the directory marker.
    814     if (dex_path.find("/.") != std::string::npos) { return false; }
    815     // The path should be at most PKG_PATH_MAX long.
    816     if (dex_path.size() > PKG_PATH_MAX) { return false; }
    817 
    818     if (validate_package_path) {
    819         // If we are asked to validate the package path check that
    820         // the dex_path is under the app data directory.
    821         std::string app_private_dir = storage_flag == FLAG_STORAGE_CE
    822             ? create_data_user_ce_package_path(
    823                     volume_uuid, multiuser_get_user_id(uid), pkgname.c_str())
    824             : create_data_user_de_package_path(
    825                     volume_uuid, multiuser_get_user_id(uid), pkgname.c_str());
    826 
    827         if (strncmp(dex_path.c_str(), app_private_dir.c_str(), app_private_dir.size()) != 0) {
    828             return false;
    829         }
    830     }
    831 
    832     // If we got here we have a valid path.
    833     return true;
    834 }
    835 
    836 /**
    837  * Get the contents of a environment variable that contains a path. Caller
    838  * owns the string that is inserted into the directory record. Returns
    839  * 0 on success and -1 on error.
    840  */
    841 int get_path_from_env(dir_rec_t* rec, const char* var) {
    842     const char* path = getenv(var);
    843     int ret = get_path_from_string(rec, path);
    844     if (ret < 0) {
    845         ALOGW("Problem finding value for environment variable %s\n", var);
    846     }
    847     return ret;
    848 }
    849 
    850 /**
    851  * Puts the string into the record as a directory. Appends '/' to the end
    852  * of all paths. Caller owns the string that is inserted into the directory
    853  * record. A null value will result in an error.
    854  *
    855  * Returns 0 on success and -1 on error.
    856  */
    857 int get_path_from_string(dir_rec_t* rec, const char* path) {
    858     if (path == NULL) {
    859         return -1;
    860     } else {
    861         const size_t path_len = strlen(path);
    862         if (path_len <= 0) {
    863             return -1;
    864         }
    865 
    866         // Make sure path is absolute.
    867         if (path[0] != '/') {
    868             return -1;
    869         }
    870 
    871         if (path[path_len - 1] == '/') {
    872             // Path ends with a forward slash. Make our own copy.
    873 
    874             rec->path = strdup(path);
    875             if (rec->path == NULL) {
    876                 return -1;
    877             }
    878 
    879             rec->len = path_len;
    880         } else {
    881             // Path does not end with a slash. Generate a new string.
    882             char *dst;
    883 
    884             // Add space for slash and terminating null.
    885             size_t dst_size = path_len + 2;
    886 
    887             rec->path = (char*) malloc(dst_size);
    888             if (rec->path == NULL) {
    889                 return -1;
    890             }
    891 
    892             dst = rec->path;
    893 
    894             if (append_and_increment(&dst, path, &dst_size) < 0
    895                     || append_and_increment(&dst, "/", &dst_size)) {
    896                 ALOGE("Error canonicalizing path");
    897                 return -1;
    898             }
    899 
    900             rec->len = dst - rec->path;
    901         }
    902     }
    903     return 0;
    904 }
    905 
    906 int copy_and_append(dir_rec_t* dst, const dir_rec_t* src, const char* suffix) {
    907     dst->len = src->len + strlen(suffix);
    908     const size_t dstSize = dst->len + 1;
    909     dst->path = (char*) malloc(dstSize);
    910 
    911     if (dst->path == NULL
    912             || snprintf(dst->path, dstSize, "%s%s", src->path, suffix)
    913                     != (ssize_t) dst->len) {
    914         ALOGE("Could not allocate memory to hold appended path; aborting\n");
    915         return -1;
    916     }
    917 
    918     return 0;
    919 }
    920 
    921 /**
    922  * Check whether path points to a valid path for an APK file. The path must
    923  * begin with a whitelisted prefix path and must be no deeper than |maxSubdirs| within
    924  * that path. Returns -1 when an invalid path is encountered and 0 when a valid path
    925  * is encountered.
    926  */
    927 static int validate_apk_path_internal(const char *path, int maxSubdirs) {
    928     const dir_rec_t* dir = NULL;
    929     if (!strncmp(path, android_app_dir.path, android_app_dir.len)) {
    930         dir = &android_app_dir;
    931     } else if (!strncmp(path, android_app_private_dir.path, android_app_private_dir.len)) {
    932         dir = &android_app_private_dir;
    933     } else if (!strncmp(path, android_app_ephemeral_dir.path, android_app_ephemeral_dir.len)) {
    934         dir = &android_app_ephemeral_dir;
    935     } else if (!strncmp(path, android_asec_dir.path, android_asec_dir.len)) {
    936         dir = &android_asec_dir;
    937     } else if (!strncmp(path, android_mnt_expand_dir.path, android_mnt_expand_dir.len)) {
    938         dir = &android_mnt_expand_dir;
    939         if (maxSubdirs < 2) {
    940             maxSubdirs = 2;
    941         }
    942     } else {
    943         return -1;
    944     }
    945 
    946     return validate_path(dir, path, maxSubdirs);
    947 }
    948 
    949 int validate_apk_path(const char* path) {
    950     return validate_apk_path_internal(path, 1 /* maxSubdirs */);
    951 }
    952 
    953 int validate_apk_path_subdirs(const char* path) {
    954     return validate_apk_path_internal(path, 3 /* maxSubdirs */);
    955 }
    956 
    957 int append_and_increment(char** dst, const char* src, size_t* dst_size) {
    958     ssize_t ret = strlcpy(*dst, src, *dst_size);
    959     if (ret < 0 || (size_t) ret >= *dst_size) {
    960         return -1;
    961     }
    962     *dst += ret;
    963     *dst_size -= ret;
    964     return 0;
    965 }
    966 
    967 char *build_string2(const char *s1, const char *s2) {
    968     if (s1 == NULL || s2 == NULL) return NULL;
    969 
    970     int len_s1 = strlen(s1);
    971     int len_s2 = strlen(s2);
    972     int len = len_s1 + len_s2 + 1;
    973     char *result = (char *) malloc(len);
    974     if (result == NULL) return NULL;
    975 
    976     strcpy(result, s1);
    977     strcpy(result + len_s1, s2);
    978 
    979     return result;
    980 }
    981 
    982 char *build_string3(const char *s1, const char *s2, const char *s3) {
    983     if (s1 == NULL || s2 == NULL || s3 == NULL) return NULL;
    984 
    985     int len_s1 = strlen(s1);
    986     int len_s2 = strlen(s2);
    987     int len_s3 = strlen(s3);
    988     int len = len_s1 + len_s2 + len_s3 + 1;
    989     char *result = (char *) malloc(len);
    990     if (result == NULL) return NULL;
    991 
    992     strcpy(result, s1);
    993     strcpy(result + len_s1, s2);
    994     strcpy(result + len_s1 + len_s2, s3);
    995 
    996     return result;
    997 }
    998 
    999 int ensure_config_user_dirs(userid_t userid) {
   1000     // writable by system, readable by any app within the same user
   1001     const int uid = multiuser_get_uid(userid, AID_SYSTEM);
   1002     const int gid = multiuser_get_uid(userid, AID_EVERYBODY);
   1003 
   1004     // Ensure /data/misc/user/<userid> exists
   1005     auto path = create_data_misc_legacy_path(userid);
   1006     return fs_prepare_dir(path.c_str(), 0750, uid, gid);
   1007 }
   1008 
   1009 int wait_child(pid_t pid)
   1010 {
   1011     int status;
   1012     pid_t got_pid;
   1013 
   1014     while (1) {
   1015         got_pid = waitpid(pid, &status, 0);
   1016         if (got_pid == -1 && errno == EINTR) {
   1017             printf("waitpid interrupted, retrying\n");
   1018         } else {
   1019             break;
   1020         }
   1021     }
   1022     if (got_pid != pid) {
   1023         ALOGW("waitpid failed: wanted %d, got %d: %s\n",
   1024             (int) pid, (int) got_pid, strerror(errno));
   1025         return 1;
   1026     }
   1027 
   1028     if (WIFEXITED(status) && WEXITSTATUS(status) == 0) {
   1029         return 0;
   1030     } else {
   1031         return status;      /* always nonzero */
   1032     }
   1033 }
   1034 
   1035 /**
   1036  * Prepare an app cache directory, which offers to fix-up the GID and
   1037  * directory mode flags during a platform upgrade.
   1038  * The app cache directory path will be 'parent'/'name'.
   1039  */
   1040 int prepare_app_cache_dir(const std::string& parent, const char* name, mode_t target_mode,
   1041         uid_t uid, gid_t gid) {
   1042     auto path = StringPrintf("%s/%s", parent.c_str(), name);
   1043     struct stat st;
   1044     if (stat(path.c_str(), &st) != 0) {
   1045         if (errno == ENOENT) {
   1046             // This is fine, just create it
   1047             if (fs_prepare_dir_strict(path.c_str(), target_mode, uid, gid) != 0) {
   1048                 PLOG(ERROR) << "Failed to prepare " << path;
   1049                 return -1;
   1050             } else {
   1051                 return 0;
   1052             }
   1053         } else {
   1054             PLOG(ERROR) << "Failed to stat " << path;
   1055             return -1;
   1056         }
   1057     }
   1058 
   1059     mode_t actual_mode = st.st_mode & (S_IRWXU | S_IRWXG | S_IRWXO | S_ISGID);
   1060     if (st.st_uid != uid) {
   1061         // Mismatched UID is real trouble; we can't recover
   1062         LOG(ERROR) << "Mismatched UID at " << path << ": found " << st.st_uid
   1063                 << " but expected " << uid;
   1064         return -1;
   1065     } else if (st.st_gid == gid && actual_mode == target_mode) {
   1066         // Everything looks good!
   1067         return 0;
   1068     } else {
   1069         // Mismatched GID/mode is recoverable; fall through to update
   1070         LOG(DEBUG) << "Mismatched cache GID/mode at " << path << ": found " << st.st_gid
   1071                 << " but expected " << gid;
   1072     }
   1073 
   1074     // Directory is owned correctly, but GID or mode mismatch means it's
   1075     // probably a platform upgrade so we need to fix them
   1076     FTS *fts;
   1077     FTSENT *p;
   1078     char *argv[] = { (char*) path.c_str(), nullptr };
   1079     if (!(fts = fts_open(argv, FTS_PHYSICAL | FTS_NOCHDIR | FTS_XDEV, NULL))) {
   1080         PLOG(ERROR) << "Failed to fts_open " << path;
   1081         return -1;
   1082     }
   1083     while ((p = fts_read(fts)) != NULL) {
   1084         switch (p->fts_info) {
   1085         case FTS_DP:
   1086             if (chmod(p->fts_path, target_mode) != 0) {
   1087                 PLOG(WARNING) << "Failed to chmod " << p->fts_path;
   1088             }
   1089             // Intentional fall through to also set GID
   1090         case FTS_F:
   1091             if (chown(p->fts_path, -1, gid) != 0) {
   1092                 PLOG(WARNING) << "Failed to chown " << p->fts_path;
   1093             }
   1094             break;
   1095         case FTS_SL:
   1096         case FTS_SLNONE:
   1097             if (lchown(p->fts_path, -1, gid) != 0) {
   1098                 PLOG(WARNING) << "Failed to chown " << p->fts_path;
   1099             }
   1100             break;
   1101         }
   1102     }
   1103     fts_close(fts);
   1104     return 0;
   1105 }
   1106 
   1107 }  // namespace installd
   1108 }  // namespace android
   1109