utils.cpp revision e02657d627a85628ec6f0f398fb85283b8d91bfa
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
1171int ensure_config_user_dirs(userid_t userid) {
1172    char config_user_path[PATH_MAX];
1173
1174    // writable by system, readable by any app within the same user
1175    const int uid = multiuser_get_uid(userid, AID_SYSTEM);
1176    const int gid = multiuser_get_uid(userid, AID_EVERYBODY);
1177
1178    // Ensure /data/misc/user/<userid> exists
1179    create_user_config_path(config_user_path, userid);
1180    if (fs_prepare_dir(config_user_path, 0750, uid, gid) == -1) {
1181        return -1;
1182    }
1183
1184   return 0;
1185}
1186
1187int wait_child(pid_t pid)
1188{
1189    int status;
1190    pid_t got_pid;
1191
1192    while (1) {
1193        got_pid = waitpid(pid, &status, 0);
1194        if (got_pid == -1 && errno == EINTR) {
1195            printf("waitpid interrupted, retrying\n");
1196        } else {
1197            break;
1198        }
1199    }
1200    if (got_pid != pid) {
1201        ALOGW("waitpid failed: wanted %d, got %d: %s\n",
1202            (int) pid, (int) got_pid, strerror(errno));
1203        return 1;
1204    }
1205
1206    if (WIFEXITED(status) && WEXITSTATUS(status) == 0) {
1207        return 0;
1208    } else {
1209        return status;      /* always nonzero */
1210    }
1211}
1212
1213}  // namespace installd
1214}  // namespace android
1215