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