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