blob: 70a1206b11ecbad1cafaa8da22aa45d79101e5e1 [file] [log] [blame]
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001/*
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
19int install(const char *pkgname, uid_t uid, gid_t gid)
20{
21 char pkgdir[PKG_PATH_MAX];
22 char libdir[PKG_PATH_MAX];
23
24 if ((uid < AID_SYSTEM) || (gid < AID_SYSTEM)) {
25 LOGE("invalid uid/gid: %d %d\n", uid, gid);
26 return -1;
27
28 }
29 if (create_pkg_path(pkgdir, PKG_DIR_PREFIX, pkgname, PKG_DIR_POSTFIX))
30 return -1;
31 if (create_pkg_path(libdir, PKG_LIB_PREFIX, pkgname, PKG_LIB_POSTFIX))
32 return -1;
33
34 if (mkdir(pkgdir, 0755) < 0) {
35 LOGE("cannot create dir '%s': %s\n", pkgdir, strerror(errno));
36 return -errno;
37 }
38 if (chown(pkgdir, uid, gid) < 0) {
39 LOGE("cannot chown dir '%s': %s\n", pkgdir, strerror(errno));
40 unlink(pkgdir);
41 return -errno;
42 }
43 if (mkdir(libdir, 0755) < 0) {
44 LOGE("cannot create dir '%s': %s\n", libdir, strerror(errno));
45 unlink(pkgdir);
46 return -errno;
47 }
48 if (chown(libdir, AID_SYSTEM, AID_SYSTEM) < 0) {
49 LOGE("cannot chown dir '%s': %s\n", libdir, strerror(errno));
50 unlink(libdir);
51 unlink(pkgdir);
52 return -errno;
53 }
54 return 0;
55}
56
57int uninstall(const char *pkgname)
58{
59 char pkgdir[PKG_PATH_MAX];
60
61 if (create_pkg_path(pkgdir, PKG_DIR_PREFIX, pkgname, PKG_DIR_POSTFIX))
62 return -1;
63
64 /* delete contents AND directory, no exceptions */
65 return delete_dir_contents(pkgdir, 1, 0);
66}
67
68int delete_user_data(const char *pkgname)
69{
70 char pkgdir[PKG_PATH_MAX];
71
72 if (create_pkg_path(pkgdir, PKG_DIR_PREFIX, pkgname, PKG_DIR_POSTFIX))
73 return -1;
74
75 /* delete contents, excluding "lib", but not the directory itself */
76 return delete_dir_contents(pkgdir, 0, "lib");
77}
78
79int delete_cache(const char *pkgname)
80{
81 char cachedir[PKG_PATH_MAX];
82
83 if (create_pkg_path(cachedir, CACHE_DIR_PREFIX, pkgname, CACHE_DIR_POSTFIX))
84 return -1;
85
86 /* delete contents, not the directory, no exceptions */
87 return delete_dir_contents(cachedir, 0, 0);
88}
89
90
91static int disk_free(void)
92{
93 struct statfs sfs;
94 if (statfs(PKG_DIR_PREFIX, &sfs) == 0) {
95 return sfs.f_bavail * sfs.f_bsize;
96 } else {
97 return -1;
98 }
99}
100
101
102/* Try to ensure free_size bytes of storage are available.
103 * Returns 0 on success.
104 * This is rather simple-minded because doing a full LRU would
105 * be potentially memory-intensive, and without atime it would
106 * also require that apps constantly modify file metadata even
107 * when just reading from the cache, which is pretty awful.
108 */
109int free_cache(int free_size)
110{
111 const char *name;
112 int dfd, subfd;
113 DIR *d;
114 struct dirent *de;
115 int avail;
116
117 avail = disk_free();
118 if (avail < 0) return -1;
119
120 LOGI("free_cache(%d) avail %d\n", free_size, avail);
121 if (avail >= free_size) return 0;
122
123 d = opendir(PKG_DIR_PREFIX);
124 if (d == NULL) {
125 LOGE("cannot open %s\n", PKG_DIR_PREFIX);
126 return -1;
127 }
128 dfd = dirfd(d);
129
130 while ((de = readdir(d))) {
131 if (de->d_type != DT_DIR) continue;
132 name = de->d_name;
133
134 /* always skip "." and ".." */
135 if (name[0] == '.') {
136 if (name[1] == 0) continue;
137 if ((name[1] == '.') && (name[2] == 0)) continue;
138 }
139
140 subfd = openat(dfd, name, O_RDONLY | O_DIRECTORY);
141 if (subfd < 0) continue;
142
143 delete_dir_contents_fd(subfd, "cache");
144 close(subfd);
145
146 avail = disk_free();
147 if (avail >= free_size) {
148 closedir(d);
149 return 0;
150 }
151 }
152 closedir(d);
153 return -1;
154}
155
156
157/* used by move_dex, rm_dex, etc to ensure that the provided paths
158 * don't point anywhere other than at the APK_DIR_PREFIX
159 */
160static int is_valid_apk_path(const char *path)
161{
162 int len = strlen(APK_DIR_PREFIX);
163 if (strncmp(path, APK_DIR_PREFIX, len)) {
164 len = strlen(PROTECTED_DIR_PREFIX);
165 if (strncmp(path, PROTECTED_DIR_PREFIX, len)) {
166 LOGE("invalid apk path '%s' (bad prefix)\n", path);
167 return 0;
168 }
169 }
170 if (strchr(path + len, '/')) {
171 LOGE("invalid apk path '%s' (subdir?)\n", path);
172 return 0;
173 }
174 if (path[len] == '.') {
175 LOGE("invalid apk path '%s' (trickery)\n", path);
176 return 0;
177 }
178 return 1;
179}
180
181int move_dex(const char *src, const char *dst)
182{
183 char src_dex[PKG_PATH_MAX];
184 char dst_dex[PKG_PATH_MAX];
185
186 if (!is_valid_apk_path(src)) return -1;
187 if (!is_valid_apk_path(dst)) return -1;
188
189 if (create_cache_path(src_dex, src)) return -1;
190 if (create_cache_path(dst_dex, dst)) return -1;
191
192 LOGI("move %s -> %s\n", src_dex, dst_dex);
193 if (rename(src_dex, dst_dex) < 0) {
194 return -1;
195 } else {
196 return 0;
197 }
198}
199
200int rm_dex(const char *path)
201{
202 char dex_path[PKG_PATH_MAX];
203
204 if (!is_valid_apk_path(path)) return -1;
205 if (create_cache_path(dex_path, path)) return -1;
206
207 LOGI("unlink %s\n", dex_path);
208 if (unlink(dex_path) < 0) {
209 return -1;
210 } else {
211 return 0;
212 }
213}
214
215int protect(char *pkgname, gid_t gid)
216{
217 struct stat s;
218 char pkgpath[PKG_PATH_MAX];
219
220 if (gid < AID_SYSTEM) return -1;
221
222 if (create_pkg_path(pkgpath, PROTECTED_DIR_PREFIX, pkgname, ".apk"))
223 return -1;
224
225 if (stat(pkgpath, &s) < 0) return -1;
226
227 if (chown(pkgpath, s.st_uid, gid) < 0) {
228 LOGE("failed to chgrp '%s': %s\n", pkgpath, strerror(errno));
229 return -1;
230 }
231
232 if (chmod(pkgpath, S_IRUSR|S_IWUSR|S_IRGRP) < 0) {
233 LOGE("failed to chmod '%s': %s\n", pkgpath, strerror(errno));
234 return -1;
235 }
236
237 return 0;
238}
239
240static int stat_size(struct stat *s)
241{
242 int blksize = s->st_blksize;
243 int size = s->st_size;
244
245 if (blksize) {
246 /* round up to filesystem block size */
247 size = (size + blksize - 1) & (~(blksize - 1));
248 }
249
250 return size;
251}
252
253static int calculate_dir_size(int dfd)
254{
255 int size = 0;
256 struct stat s;
257 DIR *d;
258 struct dirent *de;
259
260 d = fdopendir(dfd);
261 if (d == NULL) {
262 close(dfd);
263 return 0;
264 }
265
266 while ((de = readdir(d))) {
267 const char *name = de->d_name;
268 if (de->d_type == DT_DIR) {
269 int subfd;
270 /* always skip "." and ".." */
271 if (name[0] == '.') {
272 if (name[1] == 0) continue;
273 if ((name[1] == '.') && (name[2] == 0)) continue;
274 }
275 subfd = openat(dfd, name, O_RDONLY | O_DIRECTORY);
276 if (subfd >= 0) {
277 size += calculate_dir_size(subfd);
278 }
279 } else {
280 if (fstatat(dfd, name, &s, AT_SYMLINK_NOFOLLOW) == 0) {
281 size += stat_size(&s);
282 }
283 }
284 }
285 closedir(d);
286 return size;
287}
288
289int get_size(const char *pkgname, const char *apkpath,
290 const char *fwdlock_apkpath,
291 int *_codesize, int *_datasize, int *_cachesize)
292{
293 DIR *d;
294 int dfd;
295 struct dirent *de;
296 struct stat s;
297 char path[PKG_PATH_MAX];
298
299 int codesize = 0;
300 int datasize = 0;
301 int cachesize = 0;
302
303 /* count the source apk as code -- but only if it's not
304 * on the /system partition
305 */
306 if (strncmp(apkpath, "/system", 7) != 0) {
307 if (stat(apkpath, &s) == 0) {
308 codesize += stat_size(&s);
309 }
310 }
311 /* count the forward locked apk as code if it is given
312 */
313 if (fwdlock_apkpath != NULL && fwdlock_apkpath[0] != '!') {
314 if (stat(fwdlock_apkpath, &s) == 0) {
315 codesize += stat_size(&s);
316 }
317 }
318
319
320 /* count the cached dexfile as code */
321 if (!create_cache_path(path, apkpath)) {
322 if (stat(path, &s) == 0) {
323 codesize += stat_size(&s);
324 }
325 }
326
327 if (create_pkg_path(path, PKG_DIR_PREFIX, pkgname, PKG_DIR_POSTFIX)) {
328 goto done;
329 }
330
331 d = opendir(path);
332 if (d == NULL) {
333 goto done;
334 }
335 dfd = dirfd(d);
336
337 /* most stuff in the pkgdir is data, except for the "cache"
338 * directory and below, which is cache, and the "lib" directory
339 * and below, which is code...
340 */
341 while ((de = readdir(d))) {
342 const char *name = de->d_name;
343
344 if (de->d_type == DT_DIR) {
345 int subfd;
346 /* always skip "." and ".." */
347 if (name[0] == '.') {
348 if (name[1] == 0) continue;
349 if ((name[1] == '.') && (name[2] == 0)) continue;
350 }
351 subfd = openat(dfd, name, O_RDONLY | O_DIRECTORY);
352 if (subfd >= 0) {
353 int size = calculate_dir_size(subfd);
354 if (!strcmp(name,"lib")) {
355 codesize += size;
356 } else if(!strcmp(name,"cache")) {
357 cachesize += size;
358 } else {
359 datasize += size;
360 }
361 }
362 } else {
363 if (fstatat(dfd, name, &s, AT_SYMLINK_NOFOLLOW) == 0) {
364 datasize += stat_size(&s);
365 }
366 }
367 }
368 closedir(d);
369done:
370 *_codesize = codesize;
371 *_datasize = datasize;
372 *_cachesize = cachesize;
373 return 0;
374}
375
376
377/* a simpler version of dexOptGenerateCacheFileName() */
378int create_cache_path(char path[PKG_PATH_MAX], const char *src)
379{
380 char *tmp;
381 int srclen;
382 int dstlen;
383
384 srclen = strlen(src);
385
386 /* demand that we are an absolute path */
387 if ((src == 0) || (src[0] != '/') || strstr(src,"..")) {
388 return -1;
389 }
390
391 if (srclen > PKG_PATH_MAX) { // XXX: PKG_NAME_MAX?
392 return -1;
393 }
394
395 dstlen = srclen + strlen(DALVIK_CACHE_PREFIX) +
396 strlen(DALVIK_CACHE_POSTFIX) + 1;
397
398 if (dstlen > PKG_PATH_MAX) {
399 return -1;
400 }
401
402 sprintf(path,"%s%s%s",
403 DALVIK_CACHE_PREFIX,
404 src + 1, /* skip the leading / */
405 DALVIK_CACHE_POSTFIX);
406
407 for(tmp = path + strlen(DALVIK_CACHE_PREFIX); *tmp; tmp++) {
408 if (*tmp == '/') {
409 *tmp = '@';
410 }
411 }
412
413 return 0;
414}
415
416static void run_dexopt(int zip_fd, int odex_fd, const char* input_file_name,
417 const char* dexopt_flags)
418{
419 static const char* DEX_OPT_BIN = "/system/bin/dexopt";
420 static const int MAX_INT_LEN = 12; // '-'+10dig+'\0' -OR- 0x+8dig
421 char zip_num[MAX_INT_LEN];
422 char odex_num[MAX_INT_LEN];
423
424 sprintf(zip_num, "%d", zip_fd);
425 sprintf(odex_num, "%d", odex_fd);
426
427 execl(DEX_OPT_BIN, DEX_OPT_BIN, "--zip", zip_num, odex_num, input_file_name,
428 dexopt_flags, (char*) NULL);
429 LOGE("execl(%s) failed: %s\n", DEX_OPT_BIN, strerror(errno));
430}
431
432static int wait_dexopt(pid_t pid, const char* apk_path)
433{
434 int status;
435 pid_t got_pid;
436
437 /*
438 * Wait for the optimization process to finish.
439 */
440 while (1) {
441 got_pid = waitpid(pid, &status, 0);
442 if (got_pid == -1 && errno == EINTR) {
443 printf("waitpid interrupted, retrying\n");
444 } else {
445 break;
446 }
447 }
448 if (got_pid != pid) {
449 LOGW("waitpid failed: wanted %d, got %d: %s\n",
450 (int) pid, (int) got_pid, strerror(errno));
451 return 1;
452 }
453
454 if (WIFEXITED(status) && WEXITSTATUS(status) == 0) {
455 LOGD("DexInv: --- END '%s' (success) ---\n", apk_path);
456 return 0;
457 } else {
458 LOGW("DexInv: --- END '%s' --- status=0x%04x, process failed\n",
459 apk_path, status);
460 return status; /* always nonzero */
461 }
462}
463
464int dexopt(const char *apk_path, uid_t uid, int is_public)
465{
466 struct utimbuf ut;
467 struct stat apk_stat, dex_stat;
468 char dex_path[PKG_PATH_MAX];
469 char dexopt_flags[PROPERTY_VALUE_MAX];
470 char *end;
471 int res, zip_fd=-1, odex_fd=-1;
472
473 /* Before anything else: is there a .odex file? If so, we have
474 * pre-optimized the apk and there is nothing to do here.
475 */
476 if (strlen(apk_path) >= (PKG_PATH_MAX - 8)) {
477 return -1;
478 }
479
480 /* platform-specific flags affecting optimization and verification */
481 property_get("dalvik.vm.dexopt-flags", dexopt_flags, "");
482
483 strcpy(dex_path, apk_path);
484 end = strrchr(dex_path, '.');
485 if (end != NULL) {
486 strcpy(end, ".odex");
487 if (stat(dex_path, &dex_stat) == 0) {
488 return 0;
489 }
490 }
491
492 if (create_cache_path(dex_path, apk_path)) {
493 return -1;
494 }
495
496 memset(&apk_stat, 0, sizeof(apk_stat));
497 stat(apk_path, &apk_stat);
498
499 zip_fd = open(apk_path, O_RDONLY, 0);
500 if (zip_fd < 0) {
501 LOGE("dexopt cannot open '%s' for input\n", apk_path);
502 return -1;
503 }
504
505 unlink(dex_path);
506 odex_fd = open(dex_path, O_RDWR | O_CREAT | O_EXCL, 0644);
507 if (odex_fd < 0) {
508 LOGE("dexopt cannot open '%s' for output\n", dex_path);
509 goto fail;
510 }
511 if (fchown(odex_fd, AID_SYSTEM, uid) < 0) {
512 LOGE("dexopt cannot chown '%s'\n", dex_path);
513 goto fail;
514 }
515 if (fchmod(odex_fd,
516 S_IRUSR|S_IWUSR|S_IRGRP |
517 (is_public ? S_IROTH : 0)) < 0) {
518 LOGE("dexopt cannot chmod '%s'\n", dex_path);
519 goto fail;
520 }
521
522 LOGD("DexInv: --- BEGIN '%s' ---\n", apk_path);
523
524 pid_t pid;
525 pid = fork();
526 if (pid == 0) {
527 /* child -- drop privileges before continuing */
528 if (setgid(uid) != 0) {
529 LOGE("setgid(%d) failed during dexopt\n", uid);
530 exit(64);
531 }
532 if (setuid(uid) != 0) {
533 LOGE("setuid(%d) during dexopt\n", uid);
534 exit(65);
535 }
536 if (flock(odex_fd, LOCK_EX | LOCK_NB) != 0) {
537 LOGE("flock(%s) failed: %s\n", dex_path, strerror(errno));
538 exit(66);
539 }
540
541 run_dexopt(zip_fd, odex_fd, apk_path, dexopt_flags);
542 exit(67); /* only get here on exec failure */
543 } else {
544 res = wait_dexopt(pid, apk_path);
545 if (res != 0) {
546 LOGE("dexopt failed on '%s' res = %d\n", dex_path, res);
547 goto fail;
548 }
549 }
550
551 ut.actime = apk_stat.st_atime;
552 ut.modtime = apk_stat.st_mtime;
553 utime(dex_path, &ut);
554
555 close(odex_fd);
556 close(zip_fd);
557 return 0;
558
559fail:
560 if (odex_fd >= 0) {
561 close(odex_fd);
562 unlink(dex_path);
563 }
564 if (zip_fd >= 0) {
565 close(zip_fd);
566 }
567 return -1;
568}