InstalldNativeService.cpp revision 0378aaf257aee92539d30543914a50c4481c6a18
1c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main/* 2c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main** Copyright 2008, The Android Open Source Project 3c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main** 4c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main** Licensed under the Apache License, Version 2.0 (the "License"); 5c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main** you may not use this file except in compliance with the License. 6c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main** You may obtain a copy of the License at 7c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main** 8c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main** http://www.apache.org/licenses/LICENSE-2.0 9c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main** 10c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main** Unless required by applicable law or agreed to in writing, software 11c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main** distributed under the License is distributed on an "AS IS" BASIS, 12c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main** See the License for the specific language governing permissions and 14c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main** limitations under the License. 15c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main*/ 16c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main 17c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main#include <inttypes.h> 18c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main#include <sys/capability.h> 19c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main#include "installd.h" 20c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main#include <cutils/sched_policy.h> 21c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main#include <diskusage/dirsize.h> 22c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main#include <selinux/android.h> 23c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main 24c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main/* Directory records that are used in execution of commands. */ 25257cecb5e24c9af71ba4d621887e88e46b0ac411Stephen Hinesdir_rec_t android_data_dir; 26c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Maindir_rec_t android_asec_dir; 27dd12e72228ea20b7fdea4dbf32c88291aef6d552Miao Wangdir_rec_t android_app_dir; 28470b3b5b70ec71042d30004747c625ca76c4007aMiao Wangdir_rec_t android_app_private_dir; 29470b3b5b70ec71042d30004747c625ca76c4007aMiao Wangdir_rec_t android_app_lib_dir; 30470b3b5b70ec71042d30004747c625ca76c4007aMiao Wangdir_rec_t android_media_dir; 31c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Maindir_rec_array_t android_system_dirs; 32c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main 33c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Mainint install(const char *pkgname, uid_t uid, gid_t gid, const char *seinfo) 34257cecb5e24c9af71ba4d621887e88e46b0ac411Stephen Hines{ 35c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main char pkgdir[PKG_PATH_MAX]; 368352bdceb7f0030593db04a06ba8caebf81eaeeaMiao Wang char libsymlink[PKG_PATH_MAX]; 378352bdceb7f0030593db04a06ba8caebf81eaeeaMiao Wang char applibdir[PKG_PATH_MAX]; 388352bdceb7f0030593db04a06ba8caebf81eaeeaMiao Wang struct stat libStat; 398352bdceb7f0030593db04a06ba8caebf81eaeeaMiao Wang 408352bdceb7f0030593db04a06ba8caebf81eaeeaMiao Wang if ((uid < AID_SYSTEM) || (gid < AID_SYSTEM)) { 418352bdceb7f0030593db04a06ba8caebf81eaeeaMiao Wang ALOGE("invalid uid/gid: %d %d\n", uid, gid); 428352bdceb7f0030593db04a06ba8caebf81eaeeaMiao Wang return -1; 438352bdceb7f0030593db04a06ba8caebf81eaeeaMiao Wang } 448352bdceb7f0030593db04a06ba8caebf81eaeeaMiao Wang 458352bdceb7f0030593db04a06ba8caebf81eaeeaMiao Wang if (create_pkg_path(pkgdir, pkgname, PKG_DIR_POSTFIX, 0)) { 468352bdceb7f0030593db04a06ba8caebf81eaeeaMiao Wang ALOGE("cannot create package path\n"); 478352bdceb7f0030593db04a06ba8caebf81eaeeaMiao Wang return -1; 488352bdceb7f0030593db04a06ba8caebf81eaeeaMiao Wang } 498352bdceb7f0030593db04a06ba8caebf81eaeeaMiao Wang 508352bdceb7f0030593db04a06ba8caebf81eaeeaMiao Wang if (create_pkg_path(libsymlink, pkgname, PKG_LIB_POSTFIX, 0)) { 518352bdceb7f0030593db04a06ba8caebf81eaeeaMiao Wang ALOGE("cannot create package lib symlink origin path\n"); 528352bdceb7f0030593db04a06ba8caebf81eaeeaMiao Wang return -1; 538352bdceb7f0030593db04a06ba8caebf81eaeeaMiao Wang } 548352bdceb7f0030593db04a06ba8caebf81eaeeaMiao Wang 558352bdceb7f0030593db04a06ba8caebf81eaeeaMiao Wang if (create_pkg_path_in_dir(applibdir, &android_app_lib_dir, pkgname, PKG_DIR_POSTFIX)) { 568352bdceb7f0030593db04a06ba8caebf81eaeeaMiao Wang ALOGE("cannot create package lib symlink dest path\n"); 578352bdceb7f0030593db04a06ba8caebf81eaeeaMiao Wang return -1; 588352bdceb7f0030593db04a06ba8caebf81eaeeaMiao Wang } 598352bdceb7f0030593db04a06ba8caebf81eaeeaMiao Wang 608352bdceb7f0030593db04a06ba8caebf81eaeeaMiao Wang if (mkdir(pkgdir, 0751) < 0) { 618352bdceb7f0030593db04a06ba8caebf81eaeeaMiao Wang ALOGE("cannot create dir '%s': %s\n", pkgdir, strerror(errno)); 628352bdceb7f0030593db04a06ba8caebf81eaeeaMiao Wang return -1; 638352bdceb7f0030593db04a06ba8caebf81eaeeaMiao Wang } 648352bdceb7f0030593db04a06ba8caebf81eaeeaMiao Wang if (chmod(pkgdir, 0751) < 0) { 658352bdceb7f0030593db04a06ba8caebf81eaeeaMiao Wang ALOGE("cannot chmod dir '%s': %s\n", pkgdir, strerror(errno)); 668352bdceb7f0030593db04a06ba8caebf81eaeeaMiao Wang unlink(pkgdir); 678352bdceb7f0030593db04a06ba8caebf81eaeeaMiao Wang return -1; 688352bdceb7f0030593db04a06ba8caebf81eaeeaMiao Wang } 698352bdceb7f0030593db04a06ba8caebf81eaeeaMiao Wang 708352bdceb7f0030593db04a06ba8caebf81eaeeaMiao Wang if (lstat(libsymlink, &libStat) < 0) { 718352bdceb7f0030593db04a06ba8caebf81eaeeaMiao Wang if (errno != ENOENT) { 728352bdceb7f0030593db04a06ba8caebf81eaeeaMiao Wang ALOGE("couldn't stat lib dir: %s\n", strerror(errno)); 738352bdceb7f0030593db04a06ba8caebf81eaeeaMiao Wang return -1; 748352bdceb7f0030593db04a06ba8caebf81eaeeaMiao Wang } 758352bdceb7f0030593db04a06ba8caebf81eaeeaMiao Wang } else { 768352bdceb7f0030593db04a06ba8caebf81eaeeaMiao Wang if (S_ISDIR(libStat.st_mode)) { 778352bdceb7f0030593db04a06ba8caebf81eaeeaMiao Wang if (delete_dir_contents(libsymlink, 1, NULL) < 0) { 788352bdceb7f0030593db04a06ba8caebf81eaeeaMiao Wang ALOGE("couldn't delete lib directory during install for: %s", libsymlink); 798352bdceb7f0030593db04a06ba8caebf81eaeeaMiao Wang return -1; 808352bdceb7f0030593db04a06ba8caebf81eaeeaMiao Wang } 818352bdceb7f0030593db04a06ba8caebf81eaeeaMiao Wang } else if (S_ISLNK(libStat.st_mode)) { 828352bdceb7f0030593db04a06ba8caebf81eaeeaMiao Wang if (unlink(libsymlink) < 0) { 838352bdceb7f0030593db04a06ba8caebf81eaeeaMiao Wang ALOGE("couldn't unlink lib directory during install for: %s", libsymlink); 848352bdceb7f0030593db04a06ba8caebf81eaeeaMiao Wang return -1; 858352bdceb7f0030593db04a06ba8caebf81eaeeaMiao Wang } 868352bdceb7f0030593db04a06ba8caebf81eaeeaMiao Wang } 878352bdceb7f0030593db04a06ba8caebf81eaeeaMiao Wang } 888352bdceb7f0030593db04a06ba8caebf81eaeeaMiao Wang 898352bdceb7f0030593db04a06ba8caebf81eaeeaMiao Wang if (selinux_android_setfilecon(pkgdir, pkgname, seinfo, uid) < 0) { 908352bdceb7f0030593db04a06ba8caebf81eaeeaMiao Wang ALOGE("cannot setfilecon dir '%s': %s\n", pkgdir, strerror(errno)); 918352bdceb7f0030593db04a06ba8caebf81eaeeaMiao Wang unlink(libsymlink); 928352bdceb7f0030593db04a06ba8caebf81eaeeaMiao Wang unlink(pkgdir); 938352bdceb7f0030593db04a06ba8caebf81eaeeaMiao Wang return -errno; 948352bdceb7f0030593db04a06ba8caebf81eaeeaMiao Wang } 958352bdceb7f0030593db04a06ba8caebf81eaeeaMiao Wang 968352bdceb7f0030593db04a06ba8caebf81eaeeaMiao Wang if (symlink(applibdir, libsymlink) < 0) { 978352bdceb7f0030593db04a06ba8caebf81eaeeaMiao Wang ALOGE("couldn't symlink directory '%s' -> '%s': %s\n", libsymlink, applibdir, 988352bdceb7f0030593db04a06ba8caebf81eaeeaMiao Wang strerror(errno)); 998352bdceb7f0030593db04a06ba8caebf81eaeeaMiao Wang unlink(pkgdir); 1008352bdceb7f0030593db04a06ba8caebf81eaeeaMiao Wang return -1; 101c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main } 102c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main 103c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main if (chown(pkgdir, uid, gid) < 0) { 104c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main ALOGE("cannot chown dir '%s': %s\n", pkgdir, strerror(errno)); 105c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main unlink(libsymlink); 106c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main unlink(pkgdir); 107c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main return -1; 108c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main } 109c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main 110c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main return 0; 111c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main} 112c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main 113c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Mainint uninstall(const char *pkgname, userid_t userid) 114c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main{ 115c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main char pkgdir[PKG_PATH_MAX]; 116c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main 117c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main if (create_pkg_path(pkgdir, pkgname, PKG_DIR_POSTFIX, userid)) 118c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main return -1; 119c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main 120c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main remove_profile_file(pkgname); 121c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main 122c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main /* delete contents AND directory, no exceptions */ 123c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main return delete_dir_contents(pkgdir, 1, NULL); 124c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main} 125c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main 126c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Mainint renamepkg(const char *oldpkgname, const char *newpkgname) 127c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main{ 128c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main char oldpkgdir[PKG_PATH_MAX]; 129c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main char newpkgdir[PKG_PATH_MAX]; 130c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main 131c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main if (create_pkg_path(oldpkgdir, oldpkgname, PKG_DIR_POSTFIX, 0)) 132c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main return -1; 133c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main if (create_pkg_path(newpkgdir, newpkgname, PKG_DIR_POSTFIX, 0)) 134c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main return -1; 135c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main 136c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main if (rename(oldpkgdir, newpkgdir) < 0) { 137c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main ALOGE("cannot rename dir '%s' to '%s': %s\n", oldpkgdir, newpkgdir, strerror(errno)); 138c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main return -errno; 139c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main } 140c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main return 0; 141c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main} 142c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main 143c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Mainint fix_uid(const char *pkgname, uid_t uid, gid_t gid) 144c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main{ 145c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main char pkgdir[PKG_PATH_MAX]; 146c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main struct stat s; 147c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main int rc = 0; 148c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main 149c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main if ((uid < AID_SYSTEM) || (gid < AID_SYSTEM)) { 150c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main ALOGE("invalid uid/gid: %d %d\n", uid, gid); 151c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main return -1; 152c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main } 153c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main 154c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main if (create_pkg_path(pkgdir, pkgname, PKG_DIR_POSTFIX, 0)) { 155c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main ALOGE("cannot create package path\n"); 156470b3b5b70ec71042d30004747c625ca76c4007aMiao Wang return -1; 157470b3b5b70ec71042d30004747c625ca76c4007aMiao Wang } 158470b3b5b70ec71042d30004747c625ca76c4007aMiao Wang 159470b3b5b70ec71042d30004747c625ca76c4007aMiao Wang if (stat(pkgdir, &s) < 0) return -1; 160470b3b5b70ec71042d30004747c625ca76c4007aMiao Wang 161470b3b5b70ec71042d30004747c625ca76c4007aMiao Wang if (s.st_uid != 0 || s.st_gid != 0) { 162470b3b5b70ec71042d30004747c625ca76c4007aMiao Wang ALOGE("fixing uid of non-root pkg: %s %" PRIu32 " %" PRIu32 "\n", pkgdir, s.st_uid, s.st_gid); 163470b3b5b70ec71042d30004747c625ca76c4007aMiao Wang return -1; 164470b3b5b70ec71042d30004747c625ca76c4007aMiao Wang } 165470b3b5b70ec71042d30004747c625ca76c4007aMiao Wang 166470b3b5b70ec71042d30004747c625ca76c4007aMiao Wang if (chmod(pkgdir, 0751) < 0) { 167470b3b5b70ec71042d30004747c625ca76c4007aMiao Wang ALOGE("cannot chmod dir '%s': %s\n", pkgdir, strerror(errno)); 168470b3b5b70ec71042d30004747c625ca76c4007aMiao Wang unlink(pkgdir); 169470b3b5b70ec71042d30004747c625ca76c4007aMiao Wang return -errno; 170470b3b5b70ec71042d30004747c625ca76c4007aMiao Wang } 171470b3b5b70ec71042d30004747c625ca76c4007aMiao Wang if (chown(pkgdir, uid, gid) < 0) { 17214ff9bdadc9f41b943611201bd8cc942dddc8ee3Miao Wang ALOGE("cannot chown dir '%s': %s\n", pkgdir, strerror(errno)); 173470b3b5b70ec71042d30004747c625ca76c4007aMiao Wang unlink(pkgdir); 174470b3b5b70ec71042d30004747c625ca76c4007aMiao Wang return -errno; 175470b3b5b70ec71042d30004747c625ca76c4007aMiao Wang } 176470b3b5b70ec71042d30004747c625ca76c4007aMiao Wang 177470b3b5b70ec71042d30004747c625ca76c4007aMiao Wang return 0; 178470b3b5b70ec71042d30004747c625ca76c4007aMiao Wang} 179470b3b5b70ec71042d30004747c625ca76c4007aMiao Wang 180dd12e72228ea20b7fdea4dbf32c88291aef6d552Miao Wangstatic int lib_dir_matcher(const char* file_name, const int is_dir) { 181dd12e72228ea20b7fdea4dbf32c88291aef6d552Miao Wang return is_dir && !strcmp(file_name, "lib"); 182dd12e72228ea20b7fdea4dbf32c88291aef6d552Miao Wang} 183dd12e72228ea20b7fdea4dbf32c88291aef6d552Miao Wang 184dd12e72228ea20b7fdea4dbf32c88291aef6d552Miao Wangint delete_user_data(const char *pkgname, userid_t userid) 185dd12e72228ea20b7fdea4dbf32c88291aef6d552Miao Wang{ 186dd12e72228ea20b7fdea4dbf32c88291aef6d552Miao Wang char pkgdir[PKG_PATH_MAX]; 187dd12e72228ea20b7fdea4dbf32c88291aef6d552Miao Wang 188dd12e72228ea20b7fdea4dbf32c88291aef6d552Miao Wang if (create_pkg_path(pkgdir, pkgname, PKG_DIR_POSTFIX, userid)) 189dd12e72228ea20b7fdea4dbf32c88291aef6d552Miao Wang return -1; 190dd12e72228ea20b7fdea4dbf32c88291aef6d552Miao Wang 191dd12e72228ea20b7fdea4dbf32c88291aef6d552Miao Wang /* delete contents, excluding "lib", but not the directory itself */ 192dd12e72228ea20b7fdea4dbf32c88291aef6d552Miao Wang return delete_dir_contents(pkgdir, 0, &lib_dir_matcher); 193dd12e72228ea20b7fdea4dbf32c88291aef6d552Miao Wang} 194ecccf940f72679f7602c52b0b4bcb245acdad55bMiao Wang 195c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Mainint make_user_data(const char *pkgname, uid_t uid, userid_t userid, const char* seinfo) 196c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main{ 197c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main char pkgdir[PKG_PATH_MAX]; 198bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang char applibdir[PKG_PATH_MAX]; 199c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main char libsymlink[PKG_PATH_MAX]; 200bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang struct stat libStat; 201bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang 202c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main // Create the data dir for the package 203c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main if (create_pkg_path(pkgdir, pkgname, PKG_DIR_POSTFIX, userid)) { 204936fbd696aac243a514f74b6fee6efd5959527a4Yang Ni return -1; 205936fbd696aac243a514f74b6fee6efd5959527a4Yang Ni } 206936fbd696aac243a514f74b6fee6efd5959527a4Yang Ni if (create_pkg_path(libsymlink, pkgname, PKG_LIB_POSTFIX, userid)) { 207936fbd696aac243a514f74b6fee6efd5959527a4Yang Ni ALOGE("cannot create package lib symlink origin path\n"); 208936fbd696aac243a514f74b6fee6efd5959527a4Yang Ni return -1; 209936fbd696aac243a514f74b6fee6efd5959527a4Yang Ni } 210936fbd696aac243a514f74b6fee6efd5959527a4Yang Ni if (create_pkg_path_in_dir(applibdir, &android_app_lib_dir, pkgname, PKG_DIR_POSTFIX)) { 211936fbd696aac243a514f74b6fee6efd5959527a4Yang Ni ALOGE("cannot create package lib symlink dest path\n"); 212936fbd696aac243a514f74b6fee6efd5959527a4Yang Ni return -1; 213936fbd696aac243a514f74b6fee6efd5959527a4Yang Ni } 214936fbd696aac243a514f74b6fee6efd5959527a4Yang Ni 215936fbd696aac243a514f74b6fee6efd5959527a4Yang Ni if (mkdir(pkgdir, 0751) < 0) { 216936fbd696aac243a514f74b6fee6efd5959527a4Yang Ni ALOGE("cannot create dir '%s': %s\n", pkgdir, strerror(errno)); 217936fbd696aac243a514f74b6fee6efd5959527a4Yang Ni return -errno; 218936fbd696aac243a514f74b6fee6efd5959527a4Yang Ni } 219936fbd696aac243a514f74b6fee6efd5959527a4Yang Ni if (chmod(pkgdir, 0751) < 0) { 220936fbd696aac243a514f74b6fee6efd5959527a4Yang Ni ALOGE("cannot chmod dir '%s': %s\n", pkgdir, strerror(errno)); 221936fbd696aac243a514f74b6fee6efd5959527a4Yang Ni unlink(pkgdir); 222936fbd696aac243a514f74b6fee6efd5959527a4Yang Ni return -errno; 223936fbd696aac243a514f74b6fee6efd5959527a4Yang Ni } 224936fbd696aac243a514f74b6fee6efd5959527a4Yang Ni 225936fbd696aac243a514f74b6fee6efd5959527a4Yang Ni if (lstat(libsymlink, &libStat) < 0) { 226936fbd696aac243a514f74b6fee6efd5959527a4Yang Ni if (errno != ENOENT) { 227936fbd696aac243a514f74b6fee6efd5959527a4Yang Ni ALOGE("couldn't stat lib dir for non-primary: %s\n", strerror(errno)); 228936fbd696aac243a514f74b6fee6efd5959527a4Yang Ni unlink(pkgdir); 229936fbd696aac243a514f74b6fee6efd5959527a4Yang Ni return -1; 230936fbd696aac243a514f74b6fee6efd5959527a4Yang Ni } 231936fbd696aac243a514f74b6fee6efd5959527a4Yang Ni } else { 232936fbd696aac243a514f74b6fee6efd5959527a4Yang Ni if (S_ISDIR(libStat.st_mode)) { 233936fbd696aac243a514f74b6fee6efd5959527a4Yang Ni if (delete_dir_contents(libsymlink, 1, NULL) < 0) { 234936fbd696aac243a514f74b6fee6efd5959527a4Yang Ni ALOGE("couldn't delete lib directory during install for non-primary: %s", 235936fbd696aac243a514f74b6fee6efd5959527a4Yang Ni libsymlink); 236936fbd696aac243a514f74b6fee6efd5959527a4Yang Ni unlink(pkgdir); 237936fbd696aac243a514f74b6fee6efd5959527a4Yang Ni return -1; 238936fbd696aac243a514f74b6fee6efd5959527a4Yang Ni } 239936fbd696aac243a514f74b6fee6efd5959527a4Yang Ni } else if (S_ISLNK(libStat.st_mode)) { 240936fbd696aac243a514f74b6fee6efd5959527a4Yang Ni if (unlink(libsymlink) < 0) { 241936fbd696aac243a514f74b6fee6efd5959527a4Yang Ni ALOGE("couldn't unlink lib directory during install for non-primary: %s", 242936fbd696aac243a514f74b6fee6efd5959527a4Yang Ni libsymlink); 243936fbd696aac243a514f74b6fee6efd5959527a4Yang Ni unlink(pkgdir); 244936fbd696aac243a514f74b6fee6efd5959527a4Yang Ni return -1; 245936fbd696aac243a514f74b6fee6efd5959527a4Yang Ni } 246936fbd696aac243a514f74b6fee6efd5959527a4Yang Ni } 247936fbd696aac243a514f74b6fee6efd5959527a4Yang Ni } 248936fbd696aac243a514f74b6fee6efd5959527a4Yang Ni 249936fbd696aac243a514f74b6fee6efd5959527a4Yang Ni if (selinux_android_setfilecon(pkgdir, pkgname, seinfo, uid) < 0) { 250936fbd696aac243a514f74b6fee6efd5959527a4Yang Ni ALOGE("cannot setfilecon dir '%s': %s\n", pkgdir, strerror(errno)); 251936fbd696aac243a514f74b6fee6efd5959527a4Yang Ni unlink(libsymlink); 252936fbd696aac243a514f74b6fee6efd5959527a4Yang Ni unlink(pkgdir); 253936fbd696aac243a514f74b6fee6efd5959527a4Yang Ni return -errno; 254936fbd696aac243a514f74b6fee6efd5959527a4Yang Ni } 255936fbd696aac243a514f74b6fee6efd5959527a4Yang Ni 256936fbd696aac243a514f74b6fee6efd5959527a4Yang Ni if (symlink(applibdir, libsymlink) < 0) { 257936fbd696aac243a514f74b6fee6efd5959527a4Yang Ni ALOGE("couldn't symlink directory for non-primary '%s' -> '%s': %s\n", libsymlink, 258936fbd696aac243a514f74b6fee6efd5959527a4Yang Ni applibdir, strerror(errno)); 259936fbd696aac243a514f74b6fee6efd5959527a4Yang Ni unlink(pkgdir); 260936fbd696aac243a514f74b6fee6efd5959527a4Yang Ni return -1; 261936fbd696aac243a514f74b6fee6efd5959527a4Yang Ni } 262936fbd696aac243a514f74b6fee6efd5959527a4Yang Ni 263936fbd696aac243a514f74b6fee6efd5959527a4Yang Ni if (chown(pkgdir, uid, uid) < 0) { 264936fbd696aac243a514f74b6fee6efd5959527a4Yang Ni ALOGE("cannot chown dir '%s': %s\n", pkgdir, strerror(errno)); 265936fbd696aac243a514f74b6fee6efd5959527a4Yang Ni unlink(libsymlink); 266936fbd696aac243a514f74b6fee6efd5959527a4Yang Ni unlink(pkgdir); 267936fbd696aac243a514f74b6fee6efd5959527a4Yang Ni return -errno; 268936fbd696aac243a514f74b6fee6efd5959527a4Yang Ni } 269936fbd696aac243a514f74b6fee6efd5959527a4Yang Ni 270936fbd696aac243a514f74b6fee6efd5959527a4Yang Ni return 0; 271936fbd696aac243a514f74b6fee6efd5959527a4Yang Ni} 272936fbd696aac243a514f74b6fee6efd5959527a4Yang Ni 273936fbd696aac243a514f74b6fee6efd5959527a4Yang Niint make_user_config(userid_t userid) 274936fbd696aac243a514f74b6fee6efd5959527a4Yang Ni{ 275936fbd696aac243a514f74b6fee6efd5959527a4Yang Ni if (ensure_config_user_dirs(userid) == -1) { 276936fbd696aac243a514f74b6fee6efd5959527a4Yang Ni return -1; 277936fbd696aac243a514f74b6fee6efd5959527a4Yang Ni } 278936fbd696aac243a514f74b6fee6efd5959527a4Yang Ni 279936fbd696aac243a514f74b6fee6efd5959527a4Yang Ni return 0; 280936fbd696aac243a514f74b6fee6efd5959527a4Yang Ni} 281936fbd696aac243a514f74b6fee6efd5959527a4Yang Ni 282936fbd696aac243a514f74b6fee6efd5959527a4Yang Niint delete_user(userid_t userid) 283936fbd696aac243a514f74b6fee6efd5959527a4Yang Ni{ 284c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main int status = 0; 285bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang 286c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main char data_path[PKG_PATH_MAX]; 287bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang if ((create_user_path(data_path, userid) != 0) 288bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang || (delete_dir_contents(data_path, 1, NULL) != 0)) { 289c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main status = -1; 290c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main } 291c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main 292bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang char media_path[PATH_MAX]; 293c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main if ((create_user_media_path(media_path, userid) != 0) 294c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main || (delete_dir_contents(media_path, 1, NULL) != 0)) { 295c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main status = -1; 296bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang } 297c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main 298c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main char config_path[PATH_MAX]; 299c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main if ((create_user_config_path(config_path, userid) != 0) 300bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang || (delete_dir_contents(config_path, 1, NULL) != 0)) { 301c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main status = -1; 302c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main } 303470b3b5b70ec71042d30004747c625ca76c4007aMiao Wang 304c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main return status; 305c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main} 306c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main 307bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wangint delete_cache(const char *pkgname, userid_t userid) 308c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main{ 309c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main char cachedir[PKG_PATH_MAX]; 310470b3b5b70ec71042d30004747c625ca76c4007aMiao Wang 311c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main if (create_pkg_path(cachedir, pkgname, CACHE_DIR_POSTFIX, userid)) 312c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main return -1; 313bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang 314ecccf940f72679f7602c52b0b4bcb245acdad55bMiao Wang /* delete contents, not the directory, no exceptions */ 315ecccf940f72679f7602c52b0b4bcb245acdad55bMiao Wang return delete_dir_contents(cachedir, 0, NULL); 316c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main} 317c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main 318ecccf940f72679f7602c52b0b4bcb245acdad55bMiao Wang/* Try to ensure free_size bytes of storage are available. 319ecccf940f72679f7602c52b0b4bcb245acdad55bMiao Wang * Returns 0 on success. 320ecccf940f72679f7602c52b0b4bcb245acdad55bMiao Wang * This is rather simple-minded because doing a full LRU would 321ecccf940f72679f7602c52b0b4bcb245acdad55bMiao Wang * be potentially memory-intensive, and without atime it would 322ecccf940f72679f7602c52b0b4bcb245acdad55bMiao Wang * also require that apps constantly modify file metadata even 323ecccf940f72679f7602c52b0b4bcb245acdad55bMiao Wang * when just reading from the cache, which is pretty awful. 324ecccf940f72679f7602c52b0b4bcb245acdad55bMiao Wang */ 325ecccf940f72679f7602c52b0b4bcb245acdad55bMiao Wangint free_cache(int64_t free_size) 326ecccf940f72679f7602c52b0b4bcb245acdad55bMiao Wang{ 327ecccf940f72679f7602c52b0b4bcb245acdad55bMiao Wang cache_t* cache; 328ecccf940f72679f7602c52b0b4bcb245acdad55bMiao Wang int64_t avail; 329ecccf940f72679f7602c52b0b4bcb245acdad55bMiao Wang DIR *d; 330ecccf940f72679f7602c52b0b4bcb245acdad55bMiao Wang struct dirent *de; 331c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main char tmpdir[PATH_MAX]; 332c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main char *dirpos; 333c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main 334c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main avail = data_disk_free(); 335bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang if (avail < 0) return -1; 336c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main 337bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang ALOGI("free_cache(%" PRId64 ") avail %" PRId64 "\n", free_size, avail); 338bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang if (avail >= free_size) return 0; 339c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main 340c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main cache = start_cache_collection(); 341c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main 342c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main // Collect cache files for primary user. 343c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main if (create_user_path(tmpdir, 0) == 0) { 344bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang //ALOGI("adding cache files from %s\n", tmpdir); 345c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main add_cache_files(cache, tmpdir, "cache"); 346bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang } 347bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang 348c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main // Search for other users and add any cache files from them. 349c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main snprintf(tmpdir, sizeof(tmpdir), "%s%s", android_data_dir.path, 350c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main SECONDARY_USER_PREFIX); 351bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang dirpos = tmpdir + strlen(tmpdir); 352c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main d = opendir(tmpdir); 353c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main if (d != NULL) { 354470b3b5b70ec71042d30004747c625ca76c4007aMiao Wang while ((de = readdir(d))) { 355c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main if (de->d_type == DT_DIR) { 356c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main const char *name = de->d_name; 357c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main /* always skip "." and ".." */ 358c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main if (name[0] == '.') { 359bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang if (name[1] == 0) continue; 360c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main if ((name[1] == '.') && (name[2] == 0)) continue; 361bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang } 362c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main if ((strlen(name)+(dirpos-tmpdir)) < (sizeof(tmpdir)-1)) { 363c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main strcpy(dirpos, name); 364c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main //ALOGI("adding cache files from %s\n", tmpdir); 365c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main add_cache_files(cache, tmpdir, "cache"); 366bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang } else { 367c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main ALOGW("Path exceeds limit: %s%s", tmpdir, name); 368c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main } 369c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main } 370c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main } 371184d51999d546d11dd18d2f5f848871f8459a230Tim Murray closedir(d); 372184d51999d546d11dd18d2f5f848871f8459a230Tim Murray } 373c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main 374c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main // Collect cache files on external storage for all users (if it is mounted as part 375c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main // of the internal storage). 376c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main strcpy(tmpdir, android_media_dir.path); 377c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main dirpos = tmpdir + strlen(tmpdir); 378bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang d = opendir(tmpdir); 379c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main if (d != NULL) { 380c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main while ((de = readdir(d))) { 381bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang if (de->d_type == DT_DIR) { 382c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main const char *name = de->d_name; 383c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main /* skip any dir that doesn't start with a number, so not a user */ 384c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main if (name[0] < '0' || name[0] > '9') { 385bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang continue; 386c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main } 387c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main if ((strlen(name)+(dirpos-tmpdir)) < (sizeof(tmpdir)-1)) { 388c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main strcpy(dirpos, name); 389c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main if (lookup_media_dir(tmpdir, "Android") == 0 390184d51999d546d11dd18d2f5f848871f8459a230Tim Murray && lookup_media_dir(tmpdir, "data") == 0) { 391184d51999d546d11dd18d2f5f848871f8459a230Tim Murray //ALOGI("adding cache files from %s\n", tmpdir); 392c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main add_cache_files(cache, tmpdir, "cache"); 393c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main } 394bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang } else { 395c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main ALOGW("Path exceeds limit: %s%s", tmpdir, name); 396c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main } 397c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main } 398bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang } 399c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main closedir(d); 400bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang } 401c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main 402c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main clear_cache_files(cache, free_size); 403c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main finish_cache_collection(cache); 404bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang 405c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main return data_disk_free() >= free_size ? 0 : -1; 406c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main} 407c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main 408c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Mainint move_dex(const char *src, const char *dst, const char *instruction_set) 409bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang{ 410c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main char src_dex[PKG_PATH_MAX]; 411c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main char dst_dex[PKG_PATH_MAX]; 412bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang 413c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main if (validate_apk_path(src)) return -1; 414bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang if (validate_apk_path(dst)) return -1; 415bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang 416c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main if (create_cache_path(src_dex, src, instruction_set)) return -1; 417c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main if (create_cache_path(dst_dex, dst, instruction_set)) return -1; 418bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang 419c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main ALOGV("move %s -> %s\n", src_dex, dst_dex); 420bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang if (rename(src_dex, dst_dex) < 0) { 421bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang ALOGE("Couldn't move %s: %s\n", src_dex, strerror(errno)); 422c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main return -1; 423c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main } else { 424c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main return 0; 425bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang } 426c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main} 427c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main 428c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Mainint rm_dex(const char *path, const char *instruction_set) 429c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main{ 430c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main char dex_path[PKG_PATH_MAX]; 431c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main 432c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main if (validate_apk_path(path)) return -1; 433bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang if (create_cache_path(dex_path, path, instruction_set)) return -1; 434bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang 435c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main ALOGV("unlink %s\n", dex_path); 436c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main if (unlink(dex_path) < 0) { 437c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main ALOGE("Couldn't unlink %s: %s\n", dex_path, strerror(errno)); 438c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main return -1; 439c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main } else { 440c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main return 0; 441c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main } 442bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang} 443086010500c28e2bca57ea583d3f38da9a2f2f414Yang Ni 444086010500c28e2bca57ea583d3f38da9a2f2f414Yang Niint get_size(const char *pkgname, userid_t userid, const char *apkpath, 445c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main const char *libdirpath, const char *fwdlock_apkpath, const char *asecpath, 446bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang const char *instruction_set, int64_t *_codesize, int64_t *_datasize, 447bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang int64_t *_cachesize, int64_t* _asecsize) 448086010500c28e2bca57ea583d3f38da9a2f2f414Yang Ni{ 449086010500c28e2bca57ea583d3f38da9a2f2f414Yang Ni DIR *d; 450086010500c28e2bca57ea583d3f38da9a2f2f414Yang Ni int dfd; 451bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang struct dirent *de; 452c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main struct stat s; 453c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main char path[PKG_PATH_MAX]; 454bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang 455bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang int64_t codesize = 0; 456bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang int64_t datasize = 0; 457c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main int64_t cachesize = 0; 458c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main int64_t asecsize = 0; 459bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang 460bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang /* count the source apk as code -- but only if it's not 461bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang * on the /system partition and its not on the sdcard. 462bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang */ 463c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main if (validate_system_app_path(apkpath) && 464bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang strncmp(apkpath, android_asec_dir.path, android_asec_dir.len) != 0) { 465bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang if (stat(apkpath, &s) == 0) { 466bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang codesize += stat_size(&s); 467bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang } 468bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang } 469bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang /* count the forward locked apk as code if it is given 470bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang */ 471c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main if (fwdlock_apkpath != NULL && fwdlock_apkpath[0] != '!') { 472c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main if (stat(fwdlock_apkpath, &s) == 0) { 473c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main codesize += stat_size(&s); 474c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main } 475c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main } 476c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main /* count the cached dexfile as code */ 477bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang if (!create_cache_path(path, apkpath, instruction_set)) { 478c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main if (stat(path, &s) == 0) { 479c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main codesize += stat_size(&s); 480c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main } 481c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main } 482bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang 483bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang /* add in size of any libraries */ 484bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang if (libdirpath != NULL && libdirpath[0] != '!') { 485bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang d = opendir(libdirpath); 486bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang if (d != NULL) { 487c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main dfd = dirfd(d); 488c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main codesize += calculate_dir_size(dfd); 489c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main closedir(d); 490c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main } 491bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang } 492c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main 493bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang /* compute asec size if it is given 494bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang */ 495c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main if (asecpath != NULL && asecpath[0] != '!') { 496c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main if (stat(asecpath, &s) == 0) { 497c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main asecsize += stat_size(&s); 498bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang } 499bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang } 500c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main 501bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang if (create_pkg_path(path, pkgname, PKG_DIR_POSTFIX, userid)) { 502c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main goto done; 503c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main } 504c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main 505bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang d = opendir(path); 506bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang if (d == NULL) { 507c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main goto done; 508bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang } 509bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang dfd = dirfd(d); 510bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang 511c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main /* most stuff in the pkgdir is data, except for the "cache" 512bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang * directory and below, which is cache, and the "lib" directory 513bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang * and below, which is code... 514c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main */ 515c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main while ((de = readdir(d))) { 516c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main const char *name = de->d_name; 517c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main 518c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main if (de->d_type == DT_DIR) { 519c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main int subfd; 520c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main int64_t statsize = 0; 521c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main int64_t dirsize = 0; 522c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main /* always skip "." and ".." */ 523bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang if (name[0] == '.') { 524bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang if (name[1] == 0) continue; 525c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main if ((name[1] == '.') && (name[2] == 0)) continue; 526c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main } 527c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main if (fstatat(dfd, name, &s, AT_SYMLINK_NOFOLLOW) == 0) { 528bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang statsize = stat_size(&s); 529c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main } 530bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang subfd = openat(dfd, name, O_RDONLY | O_DIRECTORY); 531bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang if (subfd >= 0) { 532c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main dirsize = calculate_dir_size(subfd); 533c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main } 534c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main if(!strcmp(name,"lib")) { 535c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main codesize += dirsize + statsize; 536bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang } else if(!strcmp(name,"cache")) { 537bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang cachesize += dirsize + statsize; 538bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang } else { 539c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main datasize += dirsize + statsize; 540bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang } 541bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang } else if (de->d_type == DT_LNK && !strcmp(name,"lib")) { 542bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang // This is the symbolic link to the application's library 543bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang // code. We'll count this as code instead of data, since 544bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang // it is not something that the app creates. 545c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main if (fstatat(dfd, name, &s, AT_SYMLINK_NOFOLLOW) == 0) { 546c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main codesize += stat_size(&s); 547c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main } 548bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang } else { 549c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main if (fstatat(dfd, name, &s, AT_SYMLINK_NOFOLLOW) == 0) { 550bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang datasize += stat_size(&s); 551bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang } 552c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main } 553c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main } 554c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main closedir(d); 555bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wangdone: 556dd12e72228ea20b7fdea4dbf32c88291aef6d552Miao Wang *_codesize = codesize; 557bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang *_datasize = datasize; 558dd12e72228ea20b7fdea4dbf32c88291aef6d552Miao Wang *_cachesize = cachesize; 559dd12e72228ea20b7fdea4dbf32c88291aef6d552Miao Wang *_asecsize = asecsize; 560dd12e72228ea20b7fdea4dbf32c88291aef6d552Miao Wang return 0; 561bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang} 562dd12e72228ea20b7fdea4dbf32c88291aef6d552Miao Wang 563bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wangint create_cache_path(char path[PKG_PATH_MAX], const char *src, const char *instruction_set) 564dd12e72228ea20b7fdea4dbf32c88291aef6d552Miao Wang{ 565dd12e72228ea20b7fdea4dbf32c88291aef6d552Miao Wang char *tmp; 566dd12e72228ea20b7fdea4dbf32c88291aef6d552Miao Wang int srclen; 567bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang int dstlen; 568c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main 569bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang srclen = strlen(src); 570bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang 571c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main /* demand that we are an absolute path */ 572c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main if ((src == 0) || (src[0] != '/') || strstr(src,"..")) { 573c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main return -1; 574c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main } 575c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main 576c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main if (srclen > PKG_PATH_MAX) { // XXX: PKG_NAME_MAX? 577c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main return -1; 578c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main } 579c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main 580c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main dstlen = srclen + strlen(DALVIK_CACHE_PREFIX) + 581c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main strlen(instruction_set) + 582c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main strlen(DALVIK_CACHE_POSTFIX) + 2; 583c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main 584c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main if (dstlen > PKG_PATH_MAX) { 585c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main return -1; 586bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang } 587bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang 588bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang sprintf(path,"%s%s/%s%s", 589c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main DALVIK_CACHE_PREFIX, 590bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang instruction_set, 591257cecb5e24c9af71ba4d621887e88e46b0ac411Stephen Hines src + 1, /* skip the leading / */ 592257cecb5e24c9af71ba4d621887e88e46b0ac411Stephen Hines DALVIK_CACHE_POSTFIX); 593c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main 594257cecb5e24c9af71ba4d621887e88e46b0ac411Stephen Hines for(tmp = path + strlen(DALVIK_CACHE_PREFIX) + strlen(instruction_set) + 1; *tmp; tmp++) { 595bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang if (*tmp == '/') { 596bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang *tmp = '@'; 597bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang } 598bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang } 599bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang 600bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang return 0; 601257cecb5e24c9af71ba4d621887e88e46b0ac411Stephen Hines} 602257cecb5e24c9af71ba4d621887e88e46b0ac411Stephen Hines 603c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Mainstatic void run_dexopt(int zip_fd, int odex_fd, const char* input_file_name, 604c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main const char* output_file_name) 605c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main{ 606bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang /* platform-specific flags affecting optimization and verification */ 607bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang char dexopt_flags[PROPERTY_VALUE_MAX]; 608bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang property_get("dalvik.vm.dexopt-flags", dexopt_flags, ""); 609c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main ALOGV("dalvik.vm.dexopt-flags=%s\n", dexopt_flags); 610bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang 611257cecb5e24c9af71ba4d621887e88e46b0ac411Stephen Hines static const char* DEX_OPT_BIN = "/system/bin/dexopt"; 612257cecb5e24c9af71ba4d621887e88e46b0ac411Stephen Hines static const int MAX_INT_LEN = 12; // '-'+10dig+'\0' -OR- 0x+8dig 613c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main char zip_num[MAX_INT_LEN]; 614257cecb5e24c9af71ba4d621887e88e46b0ac411Stephen Hines char odex_num[MAX_INT_LEN]; 615bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang 616bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang sprintf(zip_num, "%d", zip_fd); 617bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang sprintf(odex_num, "%d", odex_fd); 618bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang 619bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang ALOGV("Running %s in=%s out=%s\n", DEX_OPT_BIN, input_file_name, output_file_name); 620257cecb5e24c9af71ba4d621887e88e46b0ac411Stephen Hines execl(DEX_OPT_BIN, DEX_OPT_BIN, "--zip", zip_num, odex_num, input_file_name, 621257cecb5e24c9af71ba4d621887e88e46b0ac411Stephen Hines dexopt_flags, (char*) NULL); 622c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main ALOGE("execl(%s) failed: %s\n", DEX_OPT_BIN, strerror(errno)); 623c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main} 624c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main 625bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wangstatic void run_patchoat(int input_fd, int oat_fd, const char* input_file_name, 626bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang const char* output_file_name, const char *pkgname, const char *instruction_set) 627bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang{ 628c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main static const int MAX_INT_LEN = 12; // '-'+10dig+'\0' -OR- 0x+8dig 629c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main static const unsigned int MAX_INSTRUCTION_SET_LEN = 32; 630c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main 631c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main static const char* PATCHOAT_BIN = "/system/bin/patchoat"; 632bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang if (strlen(instruction_set) >= MAX_INSTRUCTION_SET_LEN) { 633c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main ALOGE("Instruction set %s longer than max length of %d", 634bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang instruction_set, MAX_INSTRUCTION_SET_LEN); 635bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang return; 636bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang } 637bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang 638bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang /* input_file_name/input_fd should be the .odex/.oat file that is precompiled. I think*/ 639bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang char instruction_set_arg[strlen("--instruction-set=") + MAX_INSTRUCTION_SET_LEN]; 640c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main char output_oat_fd_arg[strlen("--output-oat-fd=") + MAX_INT_LEN]; 641c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main char input_oat_fd_arg[strlen("--input-oat-fd=") + MAX_INT_LEN]; 642c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main const char* patched_image_location_arg = "--patched-image-location=/system/framework/boot.art"; 643c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main // The caller has already gotten all the locks we need. 644c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main const char* no_lock_arg = "--no-lock-output"; 645c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main sprintf(instruction_set_arg, "--instruction-set=%s", instruction_set); 646bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang sprintf(output_oat_fd_arg, "--output-oat-fd=%d", oat_fd); 647c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main sprintf(input_oat_fd_arg, "--input-oat-fd=%d", input_fd); 648c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main ALOGE("Running %s isa=%s in-fd=%d (%s) out-fd=%d (%s)\n", 649c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main PATCHOAT_BIN, instruction_set, input_fd, input_file_name, oat_fd, output_file_name); 650c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main 651c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main /* patchoat, patched-image-location, no-lock, isa, input-fd, output-fd */ 652c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main char* argv[7]; 653c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main argv[0] = (char*) PATCHOAT_BIN; 654c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main argv[1] = (char*) patched_image_location_arg; 655c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main argv[2] = (char*) no_lock_arg; 656bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang argv[3] = instruction_set_arg; 657bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang argv[4] = output_oat_fd_arg; 658bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang argv[5] = input_oat_fd_arg; 659c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main argv[6] = NULL; 660c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main 661c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main execv(PATCHOAT_BIN, (char* const *)argv); 662c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main ALOGE("execv(%s) failed: %s\n", PATCHOAT_BIN, strerror(errno)); 663c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main} 664bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang 665c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Mainstatic void run_dex2oat(int zip_fd, int oat_fd, const char* input_file_name, 666c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main const char* output_file_name, const char *pkgname, const char *instruction_set) 667c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main{ 668c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main char prop_buf[PROPERTY_VALUE_MAX]; 669c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main bool profiler = (property_get("dalvik.vm.profiler", prop_buf, "0") > 0) && (prop_buf[0] == '1'); 670c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main 671c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main char dex2oat_Xms_flag[PROPERTY_VALUE_MAX]; 672c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main bool have_dex2oat_Xms_flag = property_get("dalvik.vm.dex2oat-Xms", dex2oat_Xms_flag, NULL) > 0; 673c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main 674bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang char dex2oat_Xmx_flag[PROPERTY_VALUE_MAX]; 675bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang bool have_dex2oat_Xmx_flag = property_get("dalvik.vm.dex2oat-Xmx", dex2oat_Xmx_flag, NULL) > 0; 676c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main 677c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main char dex2oat_compiler_filter_flag[PROPERTY_VALUE_MAX]; 678c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main bool have_dex2oat_compiler_filter_flag = property_get("dalvik.vm.dex2oat-filter", 679c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main dex2oat_compiler_filter_flag, NULL) > 0; 680c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main 6818352bdceb7f0030593db04a06ba8caebf81eaeeaMiao Wang char dex2oat_flags[PROPERTY_VALUE_MAX]; 682c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main bool have_dex2oat_flags = property_get("dalvik.vm.dex2oat-flags", dex2oat_flags, NULL) > 0; 6838352bdceb7f0030593db04a06ba8caebf81eaeeaMiao Wang ALOGV("dalvik.vm.dex2oat-flags=%s\n", dex2oat_flags); 6848352bdceb7f0030593db04a06ba8caebf81eaeeaMiao Wang 685c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main // If we booting without the real /data, don't spend time compiling. 6868352bdceb7f0030593db04a06ba8caebf81eaeeaMiao Wang char vold_decrypt[PROPERTY_VALUE_MAX]; 6878352bdceb7f0030593db04a06ba8caebf81eaeeaMiao Wang bool have_vold_decrypt = property_get("vold.decrypt", vold_decrypt, "") > 0; 6888352bdceb7f0030593db04a06ba8caebf81eaeeaMiao Wang bool skip_compilation = (have_vold_decrypt && 6898352bdceb7f0030593db04a06ba8caebf81eaeeaMiao Wang (strcmp(vold_decrypt, "trigger_restart_min_framework") == 0 || 6908352bdceb7f0030593db04a06ba8caebf81eaeeaMiao Wang (strcmp(vold_decrypt, "1") == 0))); 6918352bdceb7f0030593db04a06ba8caebf81eaeeaMiao Wang 692c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main static const char* DEX2OAT_BIN = "/system/bin/dex2oat"; 693c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main 694c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main static const char* RUNTIME_ARG = "--runtime-arg"; 695c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main 696bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang static const int MAX_INT_LEN = 12; // '-'+10dig+'\0' -OR- 0x+8dig 697bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang static const unsigned int MAX_INSTRUCTION_SET_LEN = 32; 698c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main 699c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main if (strlen(instruction_set) >= MAX_INSTRUCTION_SET_LEN) { 700bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang ALOGE("Instruction set %s longer than max length of %d", 701bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang instruction_set, MAX_INSTRUCTION_SET_LEN); 702c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main return; 703bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang } 704bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang 705c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main char zip_fd_arg[strlen("--zip-fd=") + MAX_INT_LEN]; 706c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main char zip_location_arg[strlen("--zip-location=") + PKG_PATH_MAX]; 707c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main char oat_fd_arg[strlen("--oat-fd=") + MAX_INT_LEN]; 7088352bdceb7f0030593db04a06ba8caebf81eaeeaMiao Wang char oat_location_arg[strlen("--oat-location=") + PKG_PATH_MAX]; 709c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main char instruction_set_arg[strlen("--instruction-set=") + MAX_INSTRUCTION_SET_LEN]; 7108352bdceb7f0030593db04a06ba8caebf81eaeeaMiao Wang char profile_file_arg[strlen("--profile-file=") + PKG_PATH_MAX]; 7118352bdceb7f0030593db04a06ba8caebf81eaeeaMiao Wang char top_k_profile_threshold_arg[strlen("--top-k-profile-threshold=") + PROPERTY_VALUE_MAX]; 712c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main char dex2oat_Xms_arg[strlen("-Xms") + PROPERTY_VALUE_MAX]; 7138352bdceb7f0030593db04a06ba8caebf81eaeeaMiao Wang char dex2oat_Xmx_arg[strlen("-Xmx") + PROPERTY_VALUE_MAX]; 7148352bdceb7f0030593db04a06ba8caebf81eaeeaMiao Wang char dex2oat_compiler_filter_arg[strlen("--compiler-filter=") + PROPERTY_VALUE_MAX]; 7158352bdceb7f0030593db04a06ba8caebf81eaeeaMiao Wang 7168352bdceb7f0030593db04a06ba8caebf81eaeeaMiao Wang sprintf(zip_fd_arg, "--zip-fd=%d", zip_fd); 7178352bdceb7f0030593db04a06ba8caebf81eaeeaMiao Wang sprintf(zip_location_arg, "--zip-location=%s", input_file_name); 718c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main sprintf(oat_fd_arg, "--oat-fd=%d", oat_fd); 719c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main sprintf(oat_location_arg, "--oat-location=%s", output_file_name); 720c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main sprintf(instruction_set_arg, "--instruction-set=%s", instruction_set); 721bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang 722bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang bool have_profile_file = false; 723c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main bool have_top_k_profile_threshold = false; 724c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main if (profiler && (strcmp(pkgname, "*") != 0)) { 725bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang char profile_file[PKG_PATH_MAX]; 726c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main snprintf(profile_file, sizeof(profile_file), "%s/%s", 727c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main DALVIK_CACHE_PREFIX "profiles", pkgname); 728c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main struct stat st; 729c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main if ((stat(profile_file, &st) == 0) && (st.st_size > 0)) { 730c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main sprintf(profile_file_arg, "--profile-file=%s", profile_file); 731bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang have_profile_file = true; 732c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main if (property_get("dalvik.vm.profile.top-k-thr", prop_buf, NULL) > 0) { 733c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main snprintf(top_k_profile_threshold_arg, sizeof(top_k_profile_threshold_arg), 734bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang "--top-k-profile-threshold=%s", prop_buf); 735bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang have_top_k_profile_threshold = true; 736bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang } 737bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang } 738bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang } 739bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang 740bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang if (have_dex2oat_Xms_flag) { 741bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang sprintf(dex2oat_Xms_arg, "-Xms%s", dex2oat_Xms_flag); 742c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main } 743c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main if (have_dex2oat_Xmx_flag) { 7448352bdceb7f0030593db04a06ba8caebf81eaeeaMiao Wang sprintf(dex2oat_Xmx_arg, "-Xmx%s", dex2oat_Xmx_flag); 745c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main } 7468352bdceb7f0030593db04a06ba8caebf81eaeeaMiao Wang if (skip_compilation) { 7478352bdceb7f0030593db04a06ba8caebf81eaeeaMiao Wang strcpy(dex2oat_compiler_filter_arg, "--compiler-filter=interpret-only"); 748c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main have_dex2oat_compiler_filter_flag = true; 7498352bdceb7f0030593db04a06ba8caebf81eaeeaMiao Wang } else if (have_dex2oat_compiler_filter_flag) { 7508352bdceb7f0030593db04a06ba8caebf81eaeeaMiao Wang sprintf(dex2oat_compiler_filter_arg, "--compiler-filter=%s", dex2oat_compiler_filter_flag); 7518352bdceb7f0030593db04a06ba8caebf81eaeeaMiao Wang } 7528352bdceb7f0030593db04a06ba8caebf81eaeeaMiao Wang 7538352bdceb7f0030593db04a06ba8caebf81eaeeaMiao Wang ALOGV("Running %s in=%s out=%s\n", DEX2OAT_BIN, input_file_name, output_file_name); 754c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main 755c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main char* argv[7 // program name, mandatory arguments and the final NULL 756c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main + (have_profile_file ? 1 : 0) 757bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang + (have_top_k_profile_threshold ? 1 : 0) 758bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang + (have_dex2oat_Xms_flag ? 2 : 0) 759c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main + (have_dex2oat_Xmx_flag ? 2 : 0) 760c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main + (have_dex2oat_compiler_filter_flag ? 1 : 0) 761bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang + (have_dex2oat_flags ? 1 : 0)]; 762c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main int i = 0; 763c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main argv[i++] = (char*)DEX2OAT_BIN; 764c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main argv[i++] = zip_fd_arg; 765c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main argv[i++] = zip_location_arg; 766c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main argv[i++] = oat_fd_arg; 767bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang argv[i++] = oat_location_arg; 768c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main argv[i++] = instruction_set_arg; 769c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main if (have_profile_file) { 770bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang argv[i++] = profile_file_arg; 771bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang } 772bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang if (have_top_k_profile_threshold) { 773bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang argv[i++] = top_k_profile_threshold_arg; 774bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang } 775bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang if (have_dex2oat_Xms_flag) { 776bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang argv[i++] = (char*)RUNTIME_ARG; 777bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang argv[i++] = dex2oat_Xms_arg; 7788352bdceb7f0030593db04a06ba8caebf81eaeeaMiao Wang } 779bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang if (have_dex2oat_Xmx_flag) { 7808352bdceb7f0030593db04a06ba8caebf81eaeeaMiao Wang argv[i++] = (char*)RUNTIME_ARG; 781bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang argv[i++] = dex2oat_Xmx_arg; 7828352bdceb7f0030593db04a06ba8caebf81eaeeaMiao Wang } 7838352bdceb7f0030593db04a06ba8caebf81eaeeaMiao Wang if (have_dex2oat_compiler_filter_flag) { 7848352bdceb7f0030593db04a06ba8caebf81eaeeaMiao Wang argv[i++] = dex2oat_compiler_filter_arg; 785c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main } 786c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main if (have_dex2oat_flags) { 7878352bdceb7f0030593db04a06ba8caebf81eaeeaMiao Wang argv[i++] = dex2oat_flags; 788c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main } 7898352bdceb7f0030593db04a06ba8caebf81eaeeaMiao Wang // Do not add after dex2oat_flags, they should override others for debugging. 7908352bdceb7f0030593db04a06ba8caebf81eaeeaMiao Wang argv[i] = NULL; 791c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main 7928352bdceb7f0030593db04a06ba8caebf81eaeeaMiao Wang execv(DEX2OAT_BIN, (char* const *)argv); 7938352bdceb7f0030593db04a06ba8caebf81eaeeaMiao Wang ALOGE("execl(%s) failed: %s\n", DEX2OAT_BIN, strerror(errno)); 7948352bdceb7f0030593db04a06ba8caebf81eaeeaMiao Wang} 7958352bdceb7f0030593db04a06ba8caebf81eaeeaMiao Wang 796c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Mainstatic int wait_child(pid_t pid) 797c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main{ 7988352bdceb7f0030593db04a06ba8caebf81eaeeaMiao Wang int status; 799c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main pid_t got_pid; 8008352bdceb7f0030593db04a06ba8caebf81eaeeaMiao Wang 8018352bdceb7f0030593db04a06ba8caebf81eaeeaMiao Wang while (1) { 802c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main got_pid = waitpid(pid, &status, 0); 8038352bdceb7f0030593db04a06ba8caebf81eaeeaMiao Wang if (got_pid == -1 && errno == EINTR) { 8048352bdceb7f0030593db04a06ba8caebf81eaeeaMiao Wang printf("waitpid interrupted, retrying\n"); 8058352bdceb7f0030593db04a06ba8caebf81eaeeaMiao Wang } else { 8068352bdceb7f0030593db04a06ba8caebf81eaeeaMiao Wang break; 8078352bdceb7f0030593db04a06ba8caebf81eaeeaMiao Wang } 8088352bdceb7f0030593db04a06ba8caebf81eaeeaMiao Wang } 809c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main if (got_pid != pid) { 810c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main ALOGW("waitpid failed: wanted %d, got %d: %s\n", 811bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang (int) pid, (int) got_pid, strerror(errno)); 812bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang return 1; 813c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main } 814bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang 815bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang if (WIFEXITED(status) && WEXITSTATUS(status) == 0) { 816c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main return 0; 817c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main } else { 818c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main return status; /* always nonzero */ 819bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang } 820c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main} 821bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang 822bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wangint dexopt(const char *apk_path, uid_t uid, int is_public, 823bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang const char *pkgname, const char *instruction_set, 824c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main int is_patchoat) 825c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main{ 826c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main struct utimbuf ut; 827c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main struct stat input_stat, dex_stat; 828c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main char out_path[PKG_PATH_MAX]; 829bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang char persist_sys_dalvik_vm_lib[PROPERTY_VALUE_MAX]; 830c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main char *end; 831bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang const char *input_file; 832bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang char in_odex_path[PKG_PATH_MAX]; 833bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang int res, input_fd=-1, out_fd=-1; 834c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main 835c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main if (strlen(apk_path) >= (PKG_PATH_MAX - 8)) { 836c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main return -1; 837bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang } 838c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main 839bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang /* The command to run depend on the value of persist.sys.dalvik.vm.lib */ 840bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang property_get("persist.sys.dalvik.vm.lib.2", persist_sys_dalvik_vm_lib, "libart.so"); 841bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang 842c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main if (is_patchoat && strncmp(persist_sys_dalvik_vm_lib, "libart", 6) != 0) { 843c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main /* We may only patch if we are libart */ 844c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main ALOGE("Patching is only supported in libart\n"); 845bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang return -1; 846c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main } 847bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang 848bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang /* Before anything else: is there a .odex file? If so, we have 849bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang * precompiled the apk and there is nothing to do here. 850c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main * 851c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main * We skip this if we are doing a patchoat. 852c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main */ 853bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang strcpy(out_path, apk_path); 854c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main end = strrchr(out_path, '.'); 855bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang if (end != NULL && !is_patchoat) { 856bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang strcpy(end, ".odex"); 857bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang if (stat(out_path, &dex_stat) == 0) { 858c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main return 0; 859c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main } 860c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main } 861bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang 862c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main if (create_cache_path(out_path, apk_path, instruction_set)) { 863bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang return -1; 864bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang } 865bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang 866c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main if (is_patchoat) { 867c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main /* /system/framework/whatever.jar -> /system/framework/<isa>/whatever.odex */ 868c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main strcpy(in_odex_path, apk_path); 869bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang end = strrchr(in_odex_path, '/'); 870c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main if (end == NULL) { 871bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang ALOGE("apk_path '%s' has no '/'s in it?!\n", apk_path); 872bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang return -1; 873bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang } 874c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main const char *apk_end = apk_path + (end - in_odex_path); // strrchr(apk_path, '/'); 875c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main strcpy(end + 1, instruction_set); // in_odex_path now is /system/framework/<isa>\0 876c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main strcat(in_odex_path, apk_end); 877bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang end = strrchr(in_odex_path, '.'); 878c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main if (end == NULL) { 879bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang return -1; 880c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main } 881c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main strcpy(end + 1, "odex"); 882bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang input_file = in_odex_path; 883c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main } else { 884c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main input_file = apk_path; 885c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main } 886c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main 887bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang memset(&input_stat, 0, sizeof(input_stat)); 888bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang stat(input_file, &input_stat); 889c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main 890bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang input_fd = open(input_file, O_RDONLY, 0); 891c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main if (input_fd < 0) { 892c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main ALOGE("installd cannot open '%s' for input during dexopt\n", input_file); 893c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main return -1; 894c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main } 895bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang 8961bb70c5cd78ab10ee54376f76d78b61c8352baddStephen Hines unlink(out_path); 897c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main out_fd = open(out_path, O_RDWR | O_CREAT | O_EXCL, 0644); 898c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main if (out_fd < 0) { 899c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main ALOGE("installd cannot open '%s' for output during dexopt\n", out_path); 900c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main goto fail; 901c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main } 902c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main if (fchmod(out_fd, 903bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang S_IRUSR|S_IWUSR|S_IRGRP | 904c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main (is_public ? S_IROTH : 0)) < 0) { 905bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang ALOGE("installd cannot chmod '%s' during dexopt\n", out_path); 906bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang goto fail; 907c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main } 908c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main if (fchown(out_fd, AID_SYSTEM, uid) < 0) { 909c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main ALOGE("installd cannot chown '%s' during dexopt\n", out_path); 910c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main goto fail; 911c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main } 912bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang 913c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main // Create profile file if there is a package name present. 914c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main if (strcmp(pkgname, "*") != 0) { 915c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main create_profile_file(pkgname, uid); 916c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main } 917c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main 918c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main 919c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main ALOGV("DexInv: --- BEGIN '%s' ---\n", input_file); 920bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang 921c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main pid_t pid; 922bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang pid = fork(); 923bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang if (pid == 0) { 924c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main /* child -- drop privileges before continuing */ 925c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main if (setgid(uid) != 0) { 926c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main ALOGE("setgid(%d) failed in installd during dexopt\n", uid); 927bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang exit(64); 928c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main } 929bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang if (setuid(uid) != 0) { 930c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main ALOGE("setuid(%d) failed in installd during dexopt\n", uid); 931c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main exit(65); 932bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang } 933c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main // drop capabilities 934c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main struct __user_cap_header_struct capheader; 935c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main struct __user_cap_data_struct capdata[2]; 936c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main memset(&capheader, 0, sizeof(capheader)); 937bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang memset(&capdata, 0, sizeof(capdata)); 938bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang capheader.version = _LINUX_CAPABILITY_VERSION_3; 939c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main if (capset(&capheader, &capdata[0]) < 0) { 940bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang ALOGE("capset failed: %s\n", strerror(errno)); 941bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang exit(66); 942bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang } 943bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang if (set_sched_policy(0, SP_BACKGROUND) < 0) { 944c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main ALOGE("set_sched_policy failed: %s\n", strerror(errno)); 945c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main exit(70); 946bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang } 947bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang if (flock(out_fd, LOCK_EX | LOCK_NB) != 0) { 948c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main ALOGE("flock(%s) failed: %s\n", out_path, strerror(errno)); 949bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang exit(67); 950c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main } 951c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main 952bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang if (strncmp(persist_sys_dalvik_vm_lib, "libdvm", 6) == 0) { 953bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang run_dexopt(input_fd, out_fd, input_file, out_path); 954bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang } else if (strncmp(persist_sys_dalvik_vm_lib, "libart", 6) == 0) { 955c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main if (is_patchoat) { 956c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main run_patchoat(input_fd, out_fd, input_file, out_path, pkgname, instruction_set); 957c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main } else { 958c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main run_dex2oat(input_fd, out_fd, input_file, out_path, pkgname, instruction_set); 959bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang } 960bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang } else { 961c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main exit(69); /* Unexpected persist.sys.dalvik.vm.lib value */ 962c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main } 963c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main exit(68); /* only get here on exec failure */ 964bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang } else { 965c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main res = wait_child(pid); 966c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main if (res == 0) { 967c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main ALOGV("DexInv: --- END '%s' (success) ---\n", input_file); 968c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main } else { 969c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main ALOGE("DexInv: --- END '%s' --- status=0x%04x, process failed\n", input_file, res); 970c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main goto fail; 971c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main } 972c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main } 973c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main 974c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main ut.actime = input_stat.st_atime; 975bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang ut.modtime = input_stat.st_mtime; 976bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang utime(out_path, &ut); 977bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang 978c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main close(out_fd); 979c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main close(input_fd); 980c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main return 0; 981bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang 982bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wangfail: 983c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main if (out_fd >= 0) { 984c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main close(out_fd); 985c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main unlink(out_path); 986bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang } 987c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main if (input_fd >= 0) { 988c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main close(input_fd); 989c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main } 990c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main return -1; 991c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main} 992c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main 993c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Mainvoid mkinnerdirs(char* path, int basepos, mode_t mode, int uid, int gid, 994c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main struct stat* statbuf) 995c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main{ 996c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main while (path[basepos] != 0) { 997c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main if (path[basepos] == '/') { 998c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main path[basepos] = 0; 999bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang if (lstat(path, statbuf) < 0) { 1000bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang ALOGV("Making directory: %s\n", path); 1001bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang if (mkdir(path, mode) == 0) { 1002c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main chown(path, uid, gid); 1003c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main } else { 1004c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main ALOGW("Unable to make directory %s: %s\n", path, strerror(errno)); 1005c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main } 1006c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main } 1007bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang path[basepos] = '/'; 1008bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang basepos++; 1009c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main } 1010c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main basepos++; 1011c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main } 1012bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang} 1013c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main 1014c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Mainint movefileordir(char* srcpath, char* dstpath, int dstbasepos, 1015c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main int dstuid, int dstgid, struct stat* statbuf) 1016bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang{ 1017c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main DIR *d; 1018c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main struct dirent *de; 1019c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main int res; 1020c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main 1021c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main int srcend = strlen(srcpath); 1022c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main int dstend = strlen(dstpath); 1023c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main 1024c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main if (lstat(srcpath, statbuf) < 0) { 1025c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main ALOGW("Unable to stat %s: %s\n", srcpath, strerror(errno)); 1026c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main return 1; 1027c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main } 1028c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main 1029c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main if ((statbuf->st_mode&S_IFDIR) == 0) { 1030c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main mkinnerdirs(dstpath, dstbasepos, S_IRWXU|S_IRWXG|S_IXOTH, 1031c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main dstuid, dstgid, statbuf); 1032c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main ALOGV("Renaming %s to %s (uid %d)\n", srcpath, dstpath, dstuid); 1033c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main if (rename(srcpath, dstpath) >= 0) { 1034c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main if (chown(dstpath, dstuid, dstgid) < 0) { 1035c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main ALOGE("cannot chown %s: %s\n", dstpath, strerror(errno)); 1036c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main unlink(dstpath); 1037c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main return 1; 1038c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main } 1039c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main } else { 1040c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main ALOGW("Unable to rename %s to %s: %s\n", 1041c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main srcpath, dstpath, strerror(errno)); 1042bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang return 1; 1043bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang } 1044bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang return 0; 1045bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang } 1046c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main 1047c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main d = opendir(srcpath); 1048c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main if (d == NULL) { 1049c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main ALOGW("Unable to opendir %s: %s\n", srcpath, strerror(errno)); 1050c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main return 1; 1051c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main } 1052c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main 1053bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang res = 0; 1054c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main 1055c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main while ((de = readdir(d))) { 1056bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang const char *name = de->d_name; 1057bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang /* always skip "." and ".." */ 1058c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main if (name[0] == '.') { 1059bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang if (name[1] == 0) continue; 1060bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang if ((name[1] == '.') && (name[2] == 0)) continue; 1061c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main } 1062c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main 1063bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang if ((srcend+strlen(name)) >= (PKG_PATH_MAX-2)) { 1064bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang ALOGW("Source path too long; skipping: %s/%s\n", srcpath, name); 1065c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main continue; 1066bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang } 1067bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang 1068bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang if ((dstend+strlen(name)) >= (PKG_PATH_MAX-2)) { 1069bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang ALOGW("Destination path too long; skipping: %s/%s\n", dstpath, name); 1070c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main continue; 1071c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main } 1072bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang 1073086010500c28e2bca57ea583d3f38da9a2f2f414Yang Ni srcpath[srcend] = dstpath[dstend] = '/'; 1074086010500c28e2bca57ea583d3f38da9a2f2f414Yang Ni strcpy(srcpath+srcend+1, name); 1075086010500c28e2bca57ea583d3f38da9a2f2f414Yang Ni strcpy(dstpath+dstend+1, name); 1076086010500c28e2bca57ea583d3f38da9a2f2f414Yang Ni 1077086010500c28e2bca57ea583d3f38da9a2f2f414Yang Ni if (movefileordir(srcpath, dstpath, dstbasepos, dstuid, dstgid, statbuf) != 0) { 1078086010500c28e2bca57ea583d3f38da9a2f2f414Yang Ni res = 1; 1079086010500c28e2bca57ea583d3f38da9a2f2f414Yang Ni } 1080086010500c28e2bca57ea583d3f38da9a2f2f414Yang Ni 1081bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang // Note: we will be leaving empty directories behind in srcpath, 1082c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main // but that is okay, the package manager will be erasing all of the 1083bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang // data associated with .apks that disappear. 1084bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang 1085c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main srcpath[srcend] = dstpath[dstend] = 0; 1086c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main } 1087bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang 1088bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang closedir(d); 1089bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang return res; 1090bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang} 1091bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang 1092bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wangint movefiles() 1093bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang{ 1094bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang DIR *d; 1095bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang int dfd, subfd; 1096bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang struct dirent *de; 1097bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang struct stat s; 1098bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang char buf[PKG_PATH_MAX+1]; 1099bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang int bufp, bufe, bufi, readlen; 1100bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang 1101bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang char srcpkg[PKG_NAME_MAX]; 1102bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang char dstpkg[PKG_NAME_MAX]; 1103bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang char srcpath[PKG_PATH_MAX]; 1104bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang char dstpath[PKG_PATH_MAX]; 1105bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang int dstuid=-1, dstgid=-1; 1106bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang int hasspace; 1107bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang 1108bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang d = opendir(UPDATE_COMMANDS_DIR_PREFIX); 1109bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang if (d == NULL) { 1110bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang goto done; 1111bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang } 1112bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang dfd = dirfd(d); 1113bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang 1114bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang /* Iterate through all files in the directory, executing the 1115bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang * file movements requested there-in. 1116bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang */ 1117bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang while ((de = readdir(d))) { 1118bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang const char *name = de->d_name; 1119bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang 1120bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang if (de->d_type == DT_DIR) { 1121bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang continue; 1122bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang } else { 1123bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang subfd = openat(dfd, name, O_RDONLY); 1124bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang if (subfd < 0) { 1125bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang ALOGW("Unable to open update commands at %s%s\n", 1126bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang UPDATE_COMMANDS_DIR_PREFIX, name); 1127bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang continue; 1128bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang } 1129bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang 1130bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang bufp = 0; 1131bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang bufe = 0; 1132bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang buf[PKG_PATH_MAX] = 0; 1133bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang srcpkg[0] = dstpkg[0] = 0; 1134bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang while (1) { 1135bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang bufi = bufp; 1136bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang while (bufi < bufe && buf[bufi] != '\n') { 1137bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang bufi++; 1138bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang } 1139bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang if (bufi < bufe) { 1140bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang buf[bufi] = 0; 1141bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang ALOGV("Processing line: %s\n", buf+bufp); 1142bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang hasspace = 0; 1143bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang while (bufp < bufi && isspace(buf[bufp])) { 1144bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang hasspace = 1; 1145c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main bufp++; 1146c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main } 1147c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main if (buf[bufp] == '#' || bufp == bufi) { 1148c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main // skip comments and empty lines. 1149bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang } else if (hasspace) { 1150c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main if (dstpkg[0] == 0) { 1151bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang ALOGW("Path before package line in %s%s: %s\n", 1152bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang UPDATE_COMMANDS_DIR_PREFIX, name, buf+bufp); 1153bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang } else if (srcpkg[0] == 0) { 1154bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang // Skip -- source package no longer exists. 1155c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main } else { 1156c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main ALOGV("Move file: %s (from %s to %s)\n", buf+bufp, srcpkg, dstpkg); 1157c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main if (!create_move_path(srcpath, srcpkg, buf+bufp, 0) && 1158bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang !create_move_path(dstpath, dstpkg, buf+bufp, 0)) { 1159c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main movefileordir(srcpath, dstpath, 1160bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang strlen(dstpath)-strlen(buf+bufp), 1161bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang dstuid, dstgid, &s); 1162bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang } 1163bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang } 1164c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main } else { 1165c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main char* div = strchr(buf+bufp, ':'); 1166c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main if (div == NULL) { 1167bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang ALOGW("Bad package spec in %s%s; no ':' sep: %s\n", 1168c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main UPDATE_COMMANDS_DIR_PREFIX, name, buf+bufp); 1169bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang } else { 1170bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang *div = 0; 1171c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main div++; 1172c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main if (strlen(buf+bufp) < PKG_NAME_MAX) { 1173c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main strcpy(dstpkg, buf+bufp); 1174c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main } else { 1175bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang srcpkg[0] = dstpkg[0] = 0; 1176bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang ALOGW("Package name too long in %s%s: %s\n", 1177c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main UPDATE_COMMANDS_DIR_PREFIX, name, buf+bufp); 1178c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main } 1179bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang if (strlen(div) < PKG_NAME_MAX) { 1180bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang strcpy(srcpkg, div); 1181bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang } else { 1182bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang srcpkg[0] = dstpkg[0] = 0; 1183bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang ALOGW("Package name too long in %s%s: %s\n", 1184bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang UPDATE_COMMANDS_DIR_PREFIX, name, div); 1185bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang } 1186bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang if (srcpkg[0] != 0) { 1187bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang if (!create_pkg_path(srcpath, srcpkg, PKG_DIR_POSTFIX, 0)) { 1188bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang if (lstat(srcpath, &s) < 0) { 1189bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang // Package no longer exists -- skip. 1190bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang srcpkg[0] = 0; 1191bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang } 1192c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main } else { 1193c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main srcpkg[0] = 0; 1194c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main ALOGW("Can't create path %s in %s%s\n", 1195c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main div, UPDATE_COMMANDS_DIR_PREFIX, name); 1196c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main } 1197bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang if (srcpkg[0] != 0) { 1198c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main if (!create_pkg_path(dstpath, dstpkg, PKG_DIR_POSTFIX, 0)) { 1199c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main if (lstat(dstpath, &s) == 0) { 1200c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main dstuid = s.st_uid; 1201bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang dstgid = s.st_gid; 1202dd12e72228ea20b7fdea4dbf32c88291aef6d552Miao Wang } else { 1203bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang // Destination package doesn't 1204bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang // exist... due to original-package, 1205bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang // this is normal, so don't be 1206bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang // noisy about it. 1207bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang srcpkg[0] = 0; 1208bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang } 1209bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang } else { 1210bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang srcpkg[0] = 0; 1211c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main ALOGW("Can't create path %s in %s%s\n", 1212c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main div, UPDATE_COMMANDS_DIR_PREFIX, name); 1213c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main } 1214ecccf940f72679f7602c52b0b4bcb245acdad55bMiao Wang } 1215bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang ALOGV("Transfering from %s to %s: uid=%d\n", 1216bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang srcpkg, dstpkg, dstuid); 1217bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang } 1218bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang } 1219bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang } 1220a6620f0f767012a1d0c2c8f71529c919bba74a41Miao Wang bufp = bufi+1; 1221a6620f0f767012a1d0c2c8f71529c919bba74a41Miao Wang } else { 1222a6620f0f767012a1d0c2c8f71529c919bba74a41Miao Wang if (bufp == 0) { 1223bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang if (bufp < bufe) { 1224bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang ALOGW("Line too long in %s%s, skipping: %s\n", 1225bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang UPDATE_COMMANDS_DIR_PREFIX, name, buf); 1226bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang } 1227bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang } else if (bufp < bufe) { 1228bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang memcpy(buf, buf+bufp, bufe-bufp); 1229bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang bufe -= bufp; 1230bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang bufp = 0; 1231bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang } 1232bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang readlen = read(subfd, buf+bufe, PKG_PATH_MAX-bufe); 1233bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang if (readlen < 0) { 1234bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang ALOGW("Failure reading update commands in %s%s: %s\n", 1235bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang UPDATE_COMMANDS_DIR_PREFIX, name, strerror(errno)); 1236bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang break; 1237bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang } else if (readlen == 0) { 1238bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang break; 1239bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang } 1240bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang bufe += readlen; 1241bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang buf[bufe] = 0; 12428352bdceb7f0030593db04a06ba8caebf81eaeeaMiao Wang ALOGV("Read buf: %s\n", buf); 1243bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang } 12448352bdceb7f0030593db04a06ba8caebf81eaeeaMiao Wang } 1245bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang close(subfd); 12468352bdceb7f0030593db04a06ba8caebf81eaeeaMiao Wang } 1247bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang } 12488352bdceb7f0030593db04a06ba8caebf81eaeeaMiao Wang closedir(d); 12498352bdceb7f0030593db04a06ba8caebf81eaeeaMiao Wangdone: 12508352bdceb7f0030593db04a06ba8caebf81eaeeaMiao Wang return 0; 1251bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang} 1252bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang 1253bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wangint linklib(const char* pkgname, const char* asecLibDir, int userId) 1254bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang{ 1255bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang char pkgdir[PKG_PATH_MAX]; 1256bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang char libsymlink[PKG_PATH_MAX]; 1257bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang struct stat s, libStat; 1258bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang int rc = 0; 1259bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang 1260bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang if (create_pkg_path(pkgdir, pkgname, PKG_DIR_POSTFIX, userId)) { 1261bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang ALOGE("cannot create package path\n"); 1262bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang return -1; 1263bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang } 1264bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang if (create_pkg_path(libsymlink, pkgname, PKG_LIB_POSTFIX, userId)) { 1265bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang ALOGE("cannot create package lib symlink origin path\n"); 1266bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang return -1; 1267bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang } 1268bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang 1269bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang if (stat(pkgdir, &s) < 0) return -1; 1270bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang 1271bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang if (chown(pkgdir, AID_INSTALL, AID_INSTALL) < 0) { 1272bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang ALOGE("failed to chown '%s': %s\n", pkgdir, strerror(errno)); 1273bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang return -1; 1274086010500c28e2bca57ea583d3f38da9a2f2f414Yang Ni } 1275bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang 1276bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang if (chmod(pkgdir, 0700) < 0) { 1277a6620f0f767012a1d0c2c8f71529c919bba74a41Miao Wang ALOGE("linklib() 1: failed to chmod '%s': %s\n", pkgdir, strerror(errno)); 1278bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang rc = -1; 1279bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang goto out; 1280bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang } 1281bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang 1282bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang if (lstat(libsymlink, &libStat) < 0) { 1283c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main if (errno != ENOENT) { 1284bec39b6de685a7dddb1925c7e9f83fae20388de3Miao Wang ALOGE("couldn't stat lib dir: %s\n", strerror(errno)); 1285c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main rc = -1; 1286c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main goto out; 1287c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main } 1288c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main } else { 1289c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main if (S_ISDIR(libStat.st_mode)) { 1290c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main if (delete_dir_contents(libsymlink, 1, NULL) < 0) { 1291c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main rc = -1; 1292257cecb5e24c9af71ba4d621887e88e46b0ac411Stephen Hines goto out; 1293c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main } 1294c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main } else if (S_ISLNK(libStat.st_mode)) { 1295c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main if (unlink(libsymlink) < 0) { 1296184d51999d546d11dd18d2f5f848871f8459a230Tim Murray ALOGE("couldn't unlink lib dir: %s\n", strerror(errno)); 1297184d51999d546d11dd18d2f5f848871f8459a230Tim Murray rc = -1; 1298257cecb5e24c9af71ba4d621887e88e46b0ac411Stephen Hines goto out; 1299257cecb5e24c9af71ba4d621887e88e46b0ac411Stephen Hines } 1300257cecb5e24c9af71ba4d621887e88e46b0ac411Stephen Hines } 1301184d51999d546d11dd18d2f5f848871f8459a230Tim Murray } 1302257cecb5e24c9af71ba4d621887e88e46b0ac411Stephen Hines 1303257cecb5e24c9af71ba4d621887e88e46b0ac411Stephen Hines if (symlink(asecLibDir, libsymlink) < 0) { 1304257cecb5e24c9af71ba4d621887e88e46b0ac411Stephen Hines ALOGE("couldn't symlink directory '%s' -> '%s': %s\n", libsymlink, asecLibDir, 1305257cecb5e24c9af71ba4d621887e88e46b0ac411Stephen Hines strerror(errno)); 1306257cecb5e24c9af71ba4d621887e88e46b0ac411Stephen Hines rc = -errno; 1307c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main goto out; 1308c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main } 1309c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main 1310257cecb5e24c9af71ba4d621887e88e46b0ac411Stephen Hinesout: 1311184d51999d546d11dd18d2f5f848871f8459a230Tim Murray if (chmod(pkgdir, s.st_mode) < 0) { 1312184d51999d546d11dd18d2f5f848871f8459a230Tim Murray ALOGE("linklib() 2: failed to chmod '%s': %s\n", pkgdir, strerror(errno)); 1313c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main rc = -errno; 1314c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main } 1315c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main 1316c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main if (chown(pkgdir, s.st_uid, s.st_gid) < 0) { 1317c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main ALOGE("failed to chown '%s' : %s\n", pkgdir, strerror(errno)); 1318c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main return -errno; 1319c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main } 1320c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main 1321c89ad4606ae29e103b85bdfc40c57e36c8877dbaScott Main return rc; 1322} 1323 1324static void run_idmap(const char *target_apk, const char *overlay_apk, int idmap_fd) 1325{ 1326 static const char *IDMAP_BIN = "/system/bin/idmap"; 1327 static const size_t MAX_INT_LEN = 32; 1328 char idmap_str[MAX_INT_LEN]; 1329 1330 snprintf(idmap_str, sizeof(idmap_str), "%d", idmap_fd); 1331 1332 execl(IDMAP_BIN, IDMAP_BIN, "--fd", target_apk, overlay_apk, idmap_str, (char*)NULL); 1333 ALOGE("execl(%s) failed: %s\n", IDMAP_BIN, strerror(errno)); 1334} 1335 1336// Transform string /a/b/c.apk to (prefix)/a@b@c.apk@(suffix) 1337// eg /a/b/c.apk to /data/resource-cache/a@b@c.apk@idmap 1338static int flatten_path(const char *prefix, const char *suffix, 1339 const char *overlay_path, char *idmap_path, size_t N) 1340{ 1341 if (overlay_path == NULL || idmap_path == NULL) { 1342 return -1; 1343 } 1344 const size_t len_overlay_path = strlen(overlay_path); 1345 // will access overlay_path + 1 further below; requires absolute path 1346 if (len_overlay_path < 2 || *overlay_path != '/') { 1347 return -1; 1348 } 1349 const size_t len_idmap_root = strlen(prefix); 1350 const size_t len_suffix = strlen(suffix); 1351 if (SIZE_MAX - len_idmap_root < len_overlay_path || 1352 SIZE_MAX - (len_idmap_root + len_overlay_path) < len_suffix) { 1353 // additions below would cause overflow 1354 return -1; 1355 } 1356 if (N < len_idmap_root + len_overlay_path + len_suffix) { 1357 return -1; 1358 } 1359 memset(idmap_path, 0, N); 1360 snprintf(idmap_path, N, "%s%s%s", prefix, overlay_path + 1, suffix); 1361 char *ch = idmap_path + len_idmap_root; 1362 while (*ch != '\0') { 1363 if (*ch == '/') { 1364 *ch = '@'; 1365 } 1366 ++ch; 1367 } 1368 return 0; 1369} 1370 1371int idmap(const char *target_apk, const char *overlay_apk, uid_t uid) 1372{ 1373 ALOGV("idmap target_apk=%s overlay_apk=%s uid=%d\n", target_apk, overlay_apk, uid); 1374 1375 int idmap_fd = -1; 1376 char idmap_path[PATH_MAX]; 1377 1378 if (flatten_path(IDMAP_PREFIX, IDMAP_SUFFIX, overlay_apk, 1379 idmap_path, sizeof(idmap_path)) == -1) { 1380 ALOGE("idmap cannot generate idmap path for overlay %s\n", overlay_apk); 1381 goto fail; 1382 } 1383 1384 unlink(idmap_path); 1385 idmap_fd = open(idmap_path, O_RDWR | O_CREAT | O_EXCL, 0644); 1386 if (idmap_fd < 0) { 1387 ALOGE("idmap cannot open '%s' for output: %s\n", idmap_path, strerror(errno)); 1388 goto fail; 1389 } 1390 if (fchown(idmap_fd, AID_SYSTEM, uid) < 0) { 1391 ALOGE("idmap cannot chown '%s'\n", idmap_path); 1392 goto fail; 1393 } 1394 if (fchmod(idmap_fd, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH) < 0) { 1395 ALOGE("idmap cannot chmod '%s'\n", idmap_path); 1396 goto fail; 1397 } 1398 1399 pid_t pid; 1400 pid = fork(); 1401 if (pid == 0) { 1402 /* child -- drop privileges before continuing */ 1403 if (setgid(uid) != 0) { 1404 ALOGE("setgid(%d) failed during idmap\n", uid); 1405 exit(1); 1406 } 1407 if (setuid(uid) != 0) { 1408 ALOGE("setuid(%d) failed during idmap\n", uid); 1409 exit(1); 1410 } 1411 if (flock(idmap_fd, LOCK_EX | LOCK_NB) != 0) { 1412 ALOGE("flock(%s) failed during idmap: %s\n", idmap_path, strerror(errno)); 1413 exit(1); 1414 } 1415 1416 run_idmap(target_apk, overlay_apk, idmap_fd); 1417 exit(1); /* only if exec call to idmap failed */ 1418 } else { 1419 int status = wait_child(pid); 1420 if (status != 0) { 1421 ALOGE("idmap failed, status=0x%04x\n", status); 1422 goto fail; 1423 } 1424 } 1425 1426 close(idmap_fd); 1427 return 0; 1428fail: 1429 if (idmap_fd >= 0) { 1430 close(idmap_fd); 1431 unlink(idmap_path); 1432 } 1433 return -1; 1434} 1435 1436int restorecon_data(const char* pkgName, const char* seinfo, uid_t uid) 1437{ 1438 struct dirent *entry; 1439 DIR *d; 1440 struct stat s; 1441 char *userdir; 1442 char *primarydir; 1443 char *pkgdir; 1444 int ret = 0; 1445 1446 // SELINUX_ANDROID_RESTORECON_DATADATA flag is set by libselinux. Not needed here. 1447 unsigned int flags = SELINUX_ANDROID_RESTORECON_RECURSE; 1448 1449 if (!pkgName || !seinfo) { 1450 ALOGE("Package name or seinfo tag is null when trying to restorecon."); 1451 return -1; 1452 } 1453 1454 if (asprintf(&primarydir, "%s%s%s", android_data_dir.path, PRIMARY_USER_PREFIX, pkgName) < 0) { 1455 return -1; 1456 } 1457 1458 // Relabel for primary user. 1459 if (selinux_android_restorecon_pkgdir(primarydir, seinfo, uid, flags) < 0) { 1460 ALOGE("restorecon failed for %s: %s\n", primarydir, strerror(errno)); 1461 ret |= -1; 1462 } 1463 1464 if (asprintf(&userdir, "%s%s", android_data_dir.path, SECONDARY_USER_PREFIX) < 0) { 1465 free(primarydir); 1466 return -1; 1467 } 1468 1469 // Relabel package directory for all secondary users. 1470 d = opendir(userdir); 1471 if (d == NULL) { 1472 free(primarydir); 1473 free(userdir); 1474 return -1; 1475 } 1476 1477 while ((entry = readdir(d))) { 1478 if (entry->d_type != DT_DIR) { 1479 continue; 1480 } 1481 1482 const char *user = entry->d_name; 1483 // Ignore "." and ".." 1484 if (!strcmp(user, ".") || !strcmp(user, "..")) { 1485 continue; 1486 } 1487 1488 // user directories start with a number 1489 if (user[0] < '0' || user[0] > '9') { 1490 ALOGE("Expecting numbered directory during restorecon. Instead got '%s'.", user); 1491 continue; 1492 } 1493 1494 if (asprintf(&pkgdir, "%s%s/%s", userdir, user, pkgName) < 0) { 1495 continue; 1496 } 1497 1498 if (stat(pkgdir, &s) < 0) { 1499 free(pkgdir); 1500 continue; 1501 } 1502 1503 if (selinux_android_restorecon_pkgdir(pkgdir, seinfo, uid, flags) < 0) { 1504 ALOGE("restorecon failed for %s: %s\n", pkgdir, strerror(errno)); 1505 ret |= -1; 1506 } 1507 free(pkgdir); 1508 } 1509 1510 closedir(d); 1511 free(primarydir); 1512 free(userdir); 1513 return ret; 1514} 1515 1516static int prune_dex_exclusion_predicate(const char *file_name, const int is_dir) 1517{ 1518 // Exclude all directories. The top level command will be 1519 // given a list of ISA specific directories that are assumed 1520 // to be flat. 1521 if (is_dir) { 1522 return 1; 1523 } 1524 1525 1526 // Don't exclude regular files that start with the list 1527 // of prefixes. 1528 static const char data_app_prefix[] = "data@app@"; 1529 static const char data_priv_app_prefix[] = "data@priv-app@"; 1530 if (!strncmp(file_name, data_app_prefix, sizeof(data_app_prefix) - 1) || 1531 !strncmp(file_name, data_priv_app_prefix, sizeof(data_priv_app_prefix) - 1)) { 1532 return 0; 1533 } 1534 1535 // Exclude all regular files that don't start with the prefix "data@app@" or 1536 // "data@priv-app@". 1537 return 1; 1538} 1539 1540int prune_dex_cache(const char* subdir) { 1541 // "." is handled as a special case, and refers to 1542 // DALVIK_CACHE_PREFIX (usually /data/dalvik-cache). 1543 const bool is_dalvik_cache_root = !strcmp(subdir, "."); 1544 1545 // Don't allow the path to contain "." or ".." except for the 1546 // special case above. This is much stricter than we need to be, 1547 // but there's no good reason to support them. 1548 if (strchr(subdir, '.' ) != NULL && !is_dalvik_cache_root) { 1549 return -1; 1550 } 1551 1552 if (!is_dalvik_cache_root) { 1553 char full_path[PKG_PATH_MAX]; 1554 snprintf(full_path, sizeof(full_path), "%s%s", DALVIK_CACHE_PREFIX, subdir); 1555 return delete_dir_contents(full_path, 0, &prune_dex_exclusion_predicate); 1556 } 1557 1558 1559 // When subdir == ".", clean the contents of the top level 1560 // dalvik-cache directory. 1561 return delete_dir_contents(DALVIK_CACHE_PREFIX, 0, &prune_dex_exclusion_predicate); 1562} 1563