InstalldNativeService.cpp revision e4ec9eb7b4c452493589983970ba5ccc501728d1
194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood/* 294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood** Copyright 2008, The Android Open Source Project 394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood** 4d93707342a61e66bc3eb2145628158452f577f42Dave Allison** Licensed under the Apache License, Version 2.0 (the "License"); 5d93707342a61e66bc3eb2145628158452f577f42Dave Allison** you may not use this file except in compliance with the License. 6d93707342a61e66bc3eb2145628158452f577f42Dave Allison** You may obtain a copy of the License at 794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood** 8d93707342a61e66bc3eb2145628158452f577f42Dave Allison** http://www.apache.org/licenses/LICENSE-2.0 994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood** 10d93707342a61e66bc3eb2145628158452f577f42Dave Allison** Unless required by applicable law or agreed to in writing, software 11d93707342a61e66bc3eb2145628158452f577f42Dave Allison** distributed under the License is distributed on an "AS IS" BASIS, 12d93707342a61e66bc3eb2145628158452f577f42Dave Allison** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13d93707342a61e66bc3eb2145628158452f577f42Dave Allison** See the License for the specific language governing permissions and 1494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood** limitations under the License. 1594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood*/ 1694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood 1741ea424413c0381ef2aa15fc5bd5d4b88abd23c4Jeff Sharkey#include "installd.h" 1841ea424413c0381ef2aa15fc5bd5d4b88abd23c4Jeff Sharkey 19e4ec9eb7b4c452493589983970ba5ccc501728d1Elliott Hughes#include <android-base/stringprintf.h> 20e4ec9eb7b4c452493589983970ba5ccc501728d1Elliott Hughes#include <android-base/logging.h> 210378aaf257aee92539d30543914a50c4481c6a18Brian Carlstrom#include <cutils/sched_policy.h> 2294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood#include <diskusage/dirsize.h> 23e36372423000a906bafae68844ebc6c42d09335aJeff Sharkey#include <logwrap/logwrap.h> 249e87a8014055606b514b1c72b21915e17db7d513Igor Murashkin#include <system/thread_defs.h> 25e36372423000a906bafae68844ebc6c42d09335aJeff Sharkey#include <selinux/android.h> 26e36372423000a906bafae68844ebc6c42d09335aJeff Sharkey 27e36372423000a906bafae68844ebc6c42d09335aJeff Sharkey#include <inttypes.h> 28e36372423000a906bafae68844ebc6c42d09335aJeff Sharkey#include <sys/capability.h> 29e36372423000a906bafae68844ebc6c42d09335aJeff Sharkey#include <sys/file.h> 30e36372423000a906bafae68844ebc6c42d09335aJeff Sharkey#include <unistd.h> 3141ea424413c0381ef2aa15fc5bd5d4b88abd23c4Jeff Sharkey 3241ea424413c0381ef2aa15fc5bd5d4b88abd23c4Jeff Sharkeyusing android::base::StringPrintf; 3394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood 3494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood/* Directory records that are used in execution of commands. */ 3594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwooddir_rec_t android_data_dir; 3694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwooddir_rec_t android_asec_dir; 3794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwooddir_rec_t android_app_dir; 3894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwooddir_rec_t android_app_private_dir; 3994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwooddir_rec_t android_app_lib_dir; 4094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwooddir_rec_t android_media_dir; 41e23a13299a4f6f2488935b4786cdbb46f46e3d3cJeff Sharkeydir_rec_t android_mnt_expand_dir; 4294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwooddir_rec_array_t android_system_dirs; 4394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood 44e36372423000a906bafae68844ebc6c42d09335aJeff Sharkeystatic const char* kCpPath = "/system/bin/cp"; 45e36372423000a906bafae68844ebc6c42d09335aJeff Sharkey 46c03de09173f98506e73e7cf7df21fe11795d4b24Jeff Sharkeyint install(const char *uuid, const char *pkgname, uid_t uid, gid_t gid, const char *seinfo) 4794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood{ 4894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood if ((uid < AID_SYSTEM) || (gid < AID_SYSTEM)) { 4994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood ALOGE("invalid uid/gid: %d %d\n", uid, gid); 5094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood return -1; 5194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood } 5294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood 53d792118c493806eeb24a8203f508e6e18fe93bd7Jeff Sharkey std::string _pkgdir(create_data_user_package_path(uuid, 0, pkgname)); 54c03de09173f98506e73e7cf7df21fe11795d4b24Jeff Sharkey const char* pkgdir = _pkgdir.c_str(); 5594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood 56a2d838a542c34d2887a0ec1fafa5f47566d595e9Nick Kralevich if (mkdir(pkgdir, 0751) < 0) { 5794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood ALOGE("cannot create dir '%s': %s\n", pkgdir, strerror(errno)); 5894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood return -1; 5994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood } 60a2d838a542c34d2887a0ec1fafa5f47566d595e9Nick Kralevich if (chmod(pkgdir, 0751) < 0) { 6194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood ALOGE("cannot chmod dir '%s': %s\n", pkgdir, strerror(errno)); 6294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood unlink(pkgdir); 6394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood return -1; 6494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood } 6594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood 6626288202e7bdf2e897a11bf31a15685d7c20945fStephen Smalley if (selinux_android_setfilecon(pkgdir, pkgname, seinfo, uid) < 0) { 6794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood ALOGE("cannot setfilecon dir '%s': %s\n", pkgdir, strerror(errno)); 6894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood unlink(pkgdir); 6994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood return -errno; 7094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood } 7194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood 7294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood if (chown(pkgdir, uid, gid) < 0) { 7394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood ALOGE("cannot chown dir '%s': %s\n", pkgdir, strerror(errno)); 7494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood unlink(pkgdir); 7594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood return -1; 7694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood } 7794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood 7894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood return 0; 7994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood} 8094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood 81c03de09173f98506e73e7cf7df21fe11795d4b24Jeff Sharkeyint uninstall(const char *uuid, const char *pkgname, userid_t userid) 8294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood{ 83d792118c493806eeb24a8203f508e6e18fe93bd7Jeff Sharkey std::string _pkgdir(create_data_user_package_path(uuid, userid, pkgname)); 84c03de09173f98506e73e7cf7df21fe11795d4b24Jeff Sharkey const char* pkgdir = _pkgdir.c_str(); 8594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood 8694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood /* delete contents AND directory, no exceptions */ 8794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood return delete_dir_contents(pkgdir, 1, NULL); 8894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood} 8994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood 9094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwoodint renamepkg(const char *oldpkgname, const char *newpkgname) 9194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood{ 9294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood char oldpkgdir[PKG_PATH_MAX]; 9394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood char newpkgdir[PKG_PATH_MAX]; 9494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood 9594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood if (create_pkg_path(oldpkgdir, oldpkgname, PKG_DIR_POSTFIX, 0)) 9694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood return -1; 9794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood if (create_pkg_path(newpkgdir, newpkgname, PKG_DIR_POSTFIX, 0)) 9894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood return -1; 9994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood 10094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood if (rename(oldpkgdir, newpkgdir) < 0) { 10194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood ALOGE("cannot rename dir '%s' to '%s': %s\n", oldpkgdir, newpkgdir, strerror(errno)); 10294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood return -errno; 10394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood } 10494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood return 0; 10594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood} 10694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood 107c03de09173f98506e73e7cf7df21fe11795d4b24Jeff Sharkeyint fix_uid(const char *uuid, const char *pkgname, uid_t uid, gid_t gid) 10894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood{ 10994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood struct stat s; 11094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood 11194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood if ((uid < AID_SYSTEM) || (gid < AID_SYSTEM)) { 11294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood ALOGE("invalid uid/gid: %d %d\n", uid, gid); 11394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood return -1; 11494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood } 11594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood 116d792118c493806eeb24a8203f508e6e18fe93bd7Jeff Sharkey std::string _pkgdir(create_data_user_package_path(uuid, 0, pkgname)); 117c03de09173f98506e73e7cf7df21fe11795d4b24Jeff Sharkey const char* pkgdir = _pkgdir.c_str(); 11894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood 11994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood if (stat(pkgdir, &s) < 0) return -1; 12094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood 12194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood if (s.st_uid != 0 || s.st_gid != 0) { 12292dc3fc52cf097bd105460cf377779bdcf146d62Mark Salyzyn ALOGE("fixing uid of non-root pkg: %s %" PRIu32 " %" PRIu32 "\n", pkgdir, s.st_uid, s.st_gid); 12394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood return -1; 12494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood } 12594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood 12694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood if (chmod(pkgdir, 0751) < 0) { 12794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood ALOGE("cannot chmod dir '%s': %s\n", pkgdir, strerror(errno)); 12894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood unlink(pkgdir); 12994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood return -errno; 13094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood } 13194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood if (chown(pkgdir, uid, gid) < 0) { 13294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood ALOGE("cannot chown dir '%s': %s\n", pkgdir, strerror(errno)); 13394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood unlink(pkgdir); 13494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood return -errno; 13594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood } 13694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood 13794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood return 0; 13894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood} 13994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood 140c03de09173f98506e73e7cf7df21fe11795d4b24Jeff Sharkeyint delete_user_data(const char *uuid, const char *pkgname, userid_t userid) 14194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood{ 142d792118c493806eeb24a8203f508e6e18fe93bd7Jeff Sharkey std::string _pkgdir(create_data_user_package_path(uuid, userid, pkgname)); 143c03de09173f98506e73e7cf7df21fe11795d4b24Jeff Sharkey const char* pkgdir = _pkgdir.c_str(); 14494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood 1453316fe472fd68377eba9983c43dfce4281209103Jeff Sharkey return delete_dir_contents(pkgdir, 0, NULL); 14694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood} 14794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood 148c03de09173f98506e73e7cf7df21fe11795d4b24Jeff Sharkeyint make_user_data(const char *uuid, const char *pkgname, uid_t uid, userid_t userid, const char* seinfo) 14994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood{ 150d792118c493806eeb24a8203f508e6e18fe93bd7Jeff Sharkey std::string _pkgdir(create_data_user_package_path(uuid, userid, pkgname)); 151c03de09173f98506e73e7cf7df21fe11795d4b24Jeff Sharkey const char* pkgdir = _pkgdir.c_str(); 15294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood 153a2d838a542c34d2887a0ec1fafa5f47566d595e9Nick Kralevich if (mkdir(pkgdir, 0751) < 0) { 15494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood ALOGE("cannot create dir '%s': %s\n", pkgdir, strerror(errno)); 15594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood return -errno; 15694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood } 157a2d838a542c34d2887a0ec1fafa5f47566d595e9Nick Kralevich if (chmod(pkgdir, 0751) < 0) { 15894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood ALOGE("cannot chmod dir '%s': %s\n", pkgdir, strerror(errno)); 15994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood unlink(pkgdir); 16094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood return -errno; 16194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood } 16294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood 16326288202e7bdf2e897a11bf31a15685d7c20945fStephen Smalley if (selinux_android_setfilecon(pkgdir, pkgname, seinfo, uid) < 0) { 16494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood ALOGE("cannot setfilecon dir '%s': %s\n", pkgdir, strerror(errno)); 16594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood unlink(pkgdir); 16694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood return -errno; 16794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood } 16894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood 16994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood if (chown(pkgdir, uid, uid) < 0) { 17094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood ALOGE("cannot chown dir '%s': %s\n", pkgdir, strerror(errno)); 17194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood unlink(pkgdir); 17294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood return -errno; 17394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood } 17494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood 17594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood return 0; 17694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood} 17794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood 17831f08986f83fa6f2dcf55523b2cf706460aeed7cJeff Sharkeyint copy_complete_app(const char *from_uuid, const char *to_uuid, 179d792118c493806eeb24a8203f508e6e18fe93bd7Jeff Sharkey const char *package_name, const char *data_app_name, appid_t appid, 180d792118c493806eeb24a8203f508e6e18fe93bd7Jeff Sharkey const char* seinfo) { 181e36372423000a906bafae68844ebc6c42d09335aJeff Sharkey std::vector<userid_t> users = get_known_users(from_uuid); 182e36372423000a906bafae68844ebc6c42d09335aJeff Sharkey 183d792118c493806eeb24a8203f508e6e18fe93bd7Jeff Sharkey // Copy app 184d792118c493806eeb24a8203f508e6e18fe93bd7Jeff Sharkey { 185d792118c493806eeb24a8203f508e6e18fe93bd7Jeff Sharkey std::string from(create_data_app_package_path(from_uuid, data_app_name)); 186d792118c493806eeb24a8203f508e6e18fe93bd7Jeff Sharkey std::string to(create_data_app_package_path(to_uuid, data_app_name)); 187d792118c493806eeb24a8203f508e6e18fe93bd7Jeff Sharkey std::string to_parent(create_data_app_path(to_uuid)); 188d792118c493806eeb24a8203f508e6e18fe93bd7Jeff Sharkey 189d792118c493806eeb24a8203f508e6e18fe93bd7Jeff Sharkey char *argv[] = { 190d792118c493806eeb24a8203f508e6e18fe93bd7Jeff Sharkey (char*) kCpPath, 191d792118c493806eeb24a8203f508e6e18fe93bd7Jeff Sharkey (char*) "-F", /* delete any existing destination file first (--remove-destination) */ 192d792118c493806eeb24a8203f508e6e18fe93bd7Jeff Sharkey (char*) "-p", /* preserve timestamps, ownership, and permissions */ 193d792118c493806eeb24a8203f508e6e18fe93bd7Jeff Sharkey (char*) "-R", /* recurse into subdirectories (DEST must be a directory) */ 194d792118c493806eeb24a8203f508e6e18fe93bd7Jeff Sharkey (char*) "-P", /* Do not follow symlinks [default] */ 195d792118c493806eeb24a8203f508e6e18fe93bd7Jeff Sharkey (char*) "-d", /* don't dereference symlinks */ 196d792118c493806eeb24a8203f508e6e18fe93bd7Jeff Sharkey (char*) from.c_str(), 197d792118c493806eeb24a8203f508e6e18fe93bd7Jeff Sharkey (char*) to_parent.c_str() 198d792118c493806eeb24a8203f508e6e18fe93bd7Jeff Sharkey }; 199d792118c493806eeb24a8203f508e6e18fe93bd7Jeff Sharkey 200d792118c493806eeb24a8203f508e6e18fe93bd7Jeff Sharkey LOG(DEBUG) << "Copying " << from << " to " << to; 201d792118c493806eeb24a8203f508e6e18fe93bd7Jeff Sharkey int rc = android_fork_execvp(ARRAY_SIZE(argv), argv, NULL, false, true); 202d792118c493806eeb24a8203f508e6e18fe93bd7Jeff Sharkey 203d792118c493806eeb24a8203f508e6e18fe93bd7Jeff Sharkey if (rc != 0) { 204d792118c493806eeb24a8203f508e6e18fe93bd7Jeff Sharkey LOG(ERROR) << "Failed copying " << from << " to " << to 205d792118c493806eeb24a8203f508e6e18fe93bd7Jeff Sharkey << ": status " << rc; 206d792118c493806eeb24a8203f508e6e18fe93bd7Jeff Sharkey goto fail; 207d792118c493806eeb24a8203f508e6e18fe93bd7Jeff Sharkey } 208d792118c493806eeb24a8203f508e6e18fe93bd7Jeff Sharkey 209d792118c493806eeb24a8203f508e6e18fe93bd7Jeff Sharkey if (selinux_android_restorecon(to.c_str(), SELINUX_ANDROID_RESTORECON_RECURSE) != 0) { 210d792118c493806eeb24a8203f508e6e18fe93bd7Jeff Sharkey LOG(ERROR) << "Failed to restorecon " << to; 211d792118c493806eeb24a8203f508e6e18fe93bd7Jeff Sharkey goto fail; 212d792118c493806eeb24a8203f508e6e18fe93bd7Jeff Sharkey } 213d792118c493806eeb24a8203f508e6e18fe93bd7Jeff Sharkey } 214d792118c493806eeb24a8203f508e6e18fe93bd7Jeff Sharkey 215d792118c493806eeb24a8203f508e6e18fe93bd7Jeff Sharkey // Copy private data for all known users 216e36372423000a906bafae68844ebc6c42d09335aJeff Sharkey for (auto user : users) { 217d792118c493806eeb24a8203f508e6e18fe93bd7Jeff Sharkey std::string from(create_data_user_package_path(from_uuid, user, package_name)); 218d792118c493806eeb24a8203f508e6e18fe93bd7Jeff Sharkey std::string to(create_data_user_package_path(to_uuid, user, package_name)); 219d792118c493806eeb24a8203f508e6e18fe93bd7Jeff Sharkey std::string to_parent(create_data_user_path(to_uuid, user)); 220e36372423000a906bafae68844ebc6c42d09335aJeff Sharkey 221e36372423000a906bafae68844ebc6c42d09335aJeff Sharkey // Data source may not exist for all users; that's okay 222e36372423000a906bafae68844ebc6c42d09335aJeff Sharkey if (access(from.c_str(), F_OK) != 0) { 223e36372423000a906bafae68844ebc6c42d09335aJeff Sharkey LOG(INFO) << "Missing source " << from; 224e36372423000a906bafae68844ebc6c42d09335aJeff Sharkey continue; 225e36372423000a906bafae68844ebc6c42d09335aJeff Sharkey } 226e36372423000a906bafae68844ebc6c42d09335aJeff Sharkey 227e36372423000a906bafae68844ebc6c42d09335aJeff Sharkey std::string user_path(create_data_user_path(to_uuid, user)); 228e36372423000a906bafae68844ebc6c42d09335aJeff Sharkey if (fs_prepare_dir(user_path.c_str(), 0771, AID_SYSTEM, AID_SYSTEM) != 0) { 229e36372423000a906bafae68844ebc6c42d09335aJeff Sharkey LOG(ERROR) << "Failed to prepare user target " << user_path; 230e36372423000a906bafae68844ebc6c42d09335aJeff Sharkey goto fail; 231e36372423000a906bafae68844ebc6c42d09335aJeff Sharkey } 232e36372423000a906bafae68844ebc6c42d09335aJeff Sharkey 233e36372423000a906bafae68844ebc6c42d09335aJeff Sharkey uid_t uid = multiuser_get_uid(user, appid); 234e36372423000a906bafae68844ebc6c42d09335aJeff Sharkey if (make_user_data(to_uuid, package_name, uid, user, seinfo) != 0) { 235e36372423000a906bafae68844ebc6c42d09335aJeff Sharkey LOG(ERROR) << "Failed to create package target " << to; 236e36372423000a906bafae68844ebc6c42d09335aJeff Sharkey goto fail; 237e36372423000a906bafae68844ebc6c42d09335aJeff Sharkey } 238e36372423000a906bafae68844ebc6c42d09335aJeff Sharkey 239e36372423000a906bafae68844ebc6c42d09335aJeff Sharkey char *argv[] = { 240e36372423000a906bafae68844ebc6c42d09335aJeff Sharkey (char*) kCpPath, 241e36372423000a906bafae68844ebc6c42d09335aJeff Sharkey (char*) "-F", /* delete any existing destination file first (--remove-destination) */ 242e36372423000a906bafae68844ebc6c42d09335aJeff Sharkey (char*) "-p", /* preserve timestamps, ownership, and permissions */ 243e36372423000a906bafae68844ebc6c42d09335aJeff Sharkey (char*) "-R", /* recurse into subdirectories (DEST must be a directory) */ 244e36372423000a906bafae68844ebc6c42d09335aJeff Sharkey (char*) "-P", /* Do not follow symlinks [default] */ 245e36372423000a906bafae68844ebc6c42d09335aJeff Sharkey (char*) "-d", /* don't dereference symlinks */ 246e36372423000a906bafae68844ebc6c42d09335aJeff Sharkey (char*) from.c_str(), 247d792118c493806eeb24a8203f508e6e18fe93bd7Jeff Sharkey (char*) to_parent.c_str() 248e36372423000a906bafae68844ebc6c42d09335aJeff Sharkey }; 249e36372423000a906bafae68844ebc6c42d09335aJeff Sharkey 250e36372423000a906bafae68844ebc6c42d09335aJeff Sharkey LOG(DEBUG) << "Copying " << from << " to " << to; 251e36372423000a906bafae68844ebc6c42d09335aJeff Sharkey int rc = android_fork_execvp(ARRAY_SIZE(argv), argv, NULL, false, true); 252e36372423000a906bafae68844ebc6c42d09335aJeff Sharkey 253e36372423000a906bafae68844ebc6c42d09335aJeff Sharkey if (rc != 0) { 254e36372423000a906bafae68844ebc6c42d09335aJeff Sharkey LOG(ERROR) << "Failed copying " << from << " to " << to 255e36372423000a906bafae68844ebc6c42d09335aJeff Sharkey << ": status " << rc; 256e36372423000a906bafae68844ebc6c42d09335aJeff Sharkey goto fail; 257e36372423000a906bafae68844ebc6c42d09335aJeff Sharkey } 258a2307aefd06f1310660ef1d35ce01bcfc72c9633Jeff Sharkey } 259e36372423000a906bafae68844ebc6c42d09335aJeff Sharkey 260a2307aefd06f1310660ef1d35ce01bcfc72c9633Jeff Sharkey if (restorecon_data(to_uuid, package_name, seinfo, multiuser_get_uid(0, appid)) != 0) { 261a2307aefd06f1310660ef1d35ce01bcfc72c9633Jeff Sharkey LOG(ERROR) << "Failed to restorecon"; 262a2307aefd06f1310660ef1d35ce01bcfc72c9633Jeff Sharkey goto fail; 263e36372423000a906bafae68844ebc6c42d09335aJeff Sharkey } 264e36372423000a906bafae68844ebc6c42d09335aJeff Sharkey 26531f08986f83fa6f2dcf55523b2cf706460aeed7cJeff Sharkey // We let the framework scan the new location and persist that before 26631f08986f83fa6f2dcf55523b2cf706460aeed7cJeff Sharkey // deleting the data in the old location; this ordering ensures that 26731f08986f83fa6f2dcf55523b2cf706460aeed7cJeff Sharkey // we can recover from things like battery pulls. 268e36372423000a906bafae68844ebc6c42d09335aJeff Sharkey return 0; 269e36372423000a906bafae68844ebc6c42d09335aJeff Sharkey 270e36372423000a906bafae68844ebc6c42d09335aJeff Sharkeyfail: 271e36372423000a906bafae68844ebc6c42d09335aJeff Sharkey // Nuke everything we might have already copied 272d792118c493806eeb24a8203f508e6e18fe93bd7Jeff Sharkey { 273d792118c493806eeb24a8203f508e6e18fe93bd7Jeff Sharkey std::string to(create_data_app_package_path(to_uuid, data_app_name)); 274d792118c493806eeb24a8203f508e6e18fe93bd7Jeff Sharkey if (delete_dir_contents(to.c_str(), 1, NULL) != 0) { 275d792118c493806eeb24a8203f508e6e18fe93bd7Jeff Sharkey LOG(WARNING) << "Failed to rollback " << to; 276d792118c493806eeb24a8203f508e6e18fe93bd7Jeff Sharkey } 277d792118c493806eeb24a8203f508e6e18fe93bd7Jeff Sharkey } 278e36372423000a906bafae68844ebc6c42d09335aJeff Sharkey for (auto user : users) { 279d792118c493806eeb24a8203f508e6e18fe93bd7Jeff Sharkey std::string to(create_data_user_package_path(to_uuid, user, package_name)); 280e36372423000a906bafae68844ebc6c42d09335aJeff Sharkey if (delete_dir_contents(to.c_str(), 1, NULL) != 0) { 281e36372423000a906bafae68844ebc6c42d09335aJeff Sharkey LOG(WARNING) << "Failed to rollback " << to; 282e36372423000a906bafae68844ebc6c42d09335aJeff Sharkey } 283e36372423000a906bafae68844ebc6c42d09335aJeff Sharkey } 284e36372423000a906bafae68844ebc6c42d09335aJeff Sharkey return -1; 285e36372423000a906bafae68844ebc6c42d09335aJeff Sharkey} 286e36372423000a906bafae68844ebc6c42d09335aJeff Sharkey 2877c8bec01790087748ec7afa69a31789828b751f9Robin Leeint make_user_config(userid_t userid) 28894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood{ 289095c763dd9aa26a206d10ab7c1d7e1c569298fb3Robin Lee if (ensure_config_user_dirs(userid) == -1) { 29094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood return -1; 29194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood } 292095c763dd9aa26a206d10ab7c1d7e1c569298fb3Robin Lee 293095c763dd9aa26a206d10ab7c1d7e1c569298fb3Robin Lee return 0; 294095c763dd9aa26a206d10ab7c1d7e1c569298fb3Robin Lee} 295095c763dd9aa26a206d10ab7c1d7e1c569298fb3Robin Lee 29641ea424413c0381ef2aa15fc5bd5d4b88abd23c4Jeff Sharkeyint delete_user(const char *uuid, userid_t userid) 297095c763dd9aa26a206d10ab7c1d7e1c569298fb3Robin Lee{ 298095c763dd9aa26a206d10ab7c1d7e1c569298fb3Robin Lee int status = 0; 299095c763dd9aa26a206d10ab7c1d7e1c569298fb3Robin Lee 30041ea424413c0381ef2aa15fc5bd5d4b88abd23c4Jeff Sharkey std::string data_path(create_data_user_path(uuid, userid)); 30141ea424413c0381ef2aa15fc5bd5d4b88abd23c4Jeff Sharkey if (delete_dir_contents(data_path.c_str(), 1, NULL) != 0) { 302095c763dd9aa26a206d10ab7c1d7e1c569298fb3Robin Lee status = -1; 30394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood } 30494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood 30541ea424413c0381ef2aa15fc5bd5d4b88abd23c4Jeff Sharkey std::string media_path(create_data_media_path(uuid, userid)); 30641ea424413c0381ef2aa15fc5bd5d4b88abd23c4Jeff Sharkey if (delete_dir_contents(media_path.c_str(), 1, NULL) != 0) { 307095c763dd9aa26a206d10ab7c1d7e1c569298fb3Robin Lee status = -1; 30894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood } 309095c763dd9aa26a206d10ab7c1d7e1c569298fb3Robin Lee 31041ea424413c0381ef2aa15fc5bd5d4b88abd23c4Jeff Sharkey // Config paths only exist on internal storage 31141ea424413c0381ef2aa15fc5bd5d4b88abd23c4Jeff Sharkey if (uuid == nullptr) { 31241ea424413c0381ef2aa15fc5bd5d4b88abd23c4Jeff Sharkey char config_path[PATH_MAX]; 31341ea424413c0381ef2aa15fc5bd5d4b88abd23c4Jeff Sharkey if ((create_user_config_path(config_path, userid) != 0) 31441ea424413c0381ef2aa15fc5bd5d4b88abd23c4Jeff Sharkey || (delete_dir_contents(config_path, 1, NULL) != 0)) { 31541ea424413c0381ef2aa15fc5bd5d4b88abd23c4Jeff Sharkey status = -1; 31641ea424413c0381ef2aa15fc5bd5d4b88abd23c4Jeff Sharkey } 31794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood } 31894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood 319095c763dd9aa26a206d10ab7c1d7e1c569298fb3Robin Lee return status; 32094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood} 32194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood 322c03de09173f98506e73e7cf7df21fe11795d4b24Jeff Sharkeyint delete_cache(const char *uuid, const char *pkgname, userid_t userid) 32394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood{ 324c03de09173f98506e73e7cf7df21fe11795d4b24Jeff Sharkey std::string _cachedir( 325d792118c493806eeb24a8203f508e6e18fe93bd7Jeff Sharkey create_data_user_package_path(uuid, userid, pkgname) + CACHE_DIR_POSTFIX); 326c03de09173f98506e73e7cf7df21fe11795d4b24Jeff Sharkey const char* cachedir = _cachedir.c_str(); 32794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood 328c796b681e52fbb792da9a5b4f30e935cc927c1d7Jeff Sharkey /* delete contents, not the directory, no exceptions */ 3293aee2c5c749dc2589f001b26fae1ec958ec89524Narayan Kamath return delete_dir_contents(cachedir, 0, NULL); 33094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood} 33194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood 332c03de09173f98506e73e7cf7df21fe11795d4b24Jeff Sharkeyint delete_code_cache(const char *uuid, const char *pkgname, userid_t userid) 333c796b681e52fbb792da9a5b4f30e935cc927c1d7Jeff Sharkey{ 334c03de09173f98506e73e7cf7df21fe11795d4b24Jeff Sharkey std::string _codecachedir( 335a2ccb9e43db52a18d088c1d440676335cb4b9e68Daichi Hirono create_data_user_package_path(uuid, userid, pkgname) + CODE_CACHE_DIR_POSTFIX); 336c03de09173f98506e73e7cf7df21fe11795d4b24Jeff Sharkey const char* codecachedir = _codecachedir.c_str(); 337c796b681e52fbb792da9a5b4f30e935cc927c1d7Jeff Sharkey 338c03de09173f98506e73e7cf7df21fe11795d4b24Jeff Sharkey struct stat s; 339c796b681e52fbb792da9a5b4f30e935cc927c1d7Jeff Sharkey 340770180a4dd86f8bda6af2e6db4676e99a5bb1548Jeff Sharkey /* it's okay if code cache is missing */ 341770180a4dd86f8bda6af2e6db4676e99a5bb1548Jeff Sharkey if (lstat(codecachedir, &s) == -1 && errno == ENOENT) { 342770180a4dd86f8bda6af2e6db4676e99a5bb1548Jeff Sharkey return 0; 343770180a4dd86f8bda6af2e6db4676e99a5bb1548Jeff Sharkey } 344770180a4dd86f8bda6af2e6db4676e99a5bb1548Jeff Sharkey 345c796b681e52fbb792da9a5b4f30e935cc927c1d7Jeff Sharkey /* delete contents, not the directory, no exceptions */ 346c796b681e52fbb792da9a5b4f30e935cc927c1d7Jeff Sharkey return delete_dir_contents(codecachedir, 0, NULL); 347c796b681e52fbb792da9a5b4f30e935cc927c1d7Jeff Sharkey} 348c796b681e52fbb792da9a5b4f30e935cc927c1d7Jeff Sharkey 34994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood/* Try to ensure free_size bytes of storage are available. 35094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood * Returns 0 on success. 35194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood * This is rather simple-minded because doing a full LRU would 35294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood * be potentially memory-intensive, and without atime it would 35394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood * also require that apps constantly modify file metadata even 35494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood * when just reading from the cache, which is pretty awful. 35594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood */ 35641ea424413c0381ef2aa15fc5bd5d4b88abd23c4Jeff Sharkeyint free_cache(const char *uuid, int64_t free_size) 35794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood{ 35894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood cache_t* cache; 35994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood int64_t avail; 36094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood DIR *d; 36194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood struct dirent *de; 36294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood char tmpdir[PATH_MAX]; 36394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood char *dirpos; 36494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood 36541ea424413c0381ef2aa15fc5bd5d4b88abd23c4Jeff Sharkey std::string data_path(create_data_path(uuid)); 36641ea424413c0381ef2aa15fc5bd5d4b88abd23c4Jeff Sharkey 36741ea424413c0381ef2aa15fc5bd5d4b88abd23c4Jeff Sharkey avail = data_disk_free(data_path); 36894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood if (avail < 0) return -1; 36994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood 37094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood ALOGI("free_cache(%" PRId64 ") avail %" PRId64 "\n", free_size, avail); 37194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood if (avail >= free_size) return 0; 37294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood 37394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood cache = start_cache_collection(); 37494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood 37541ea424413c0381ef2aa15fc5bd5d4b88abd23c4Jeff Sharkey // Special case for owner on internal storage 37641ea424413c0381ef2aa15fc5bd5d4b88abd23c4Jeff Sharkey if (uuid == nullptr) { 37741ea424413c0381ef2aa15fc5bd5d4b88abd23c4Jeff Sharkey std::string _tmpdir(create_data_user_path(nullptr, 0)); 37841ea424413c0381ef2aa15fc5bd5d4b88abd23c4Jeff Sharkey add_cache_files(cache, _tmpdir.c_str(), "cache"); 37994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood } 38094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood 38194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood // Search for other users and add any cache files from them. 38241ea424413c0381ef2aa15fc5bd5d4b88abd23c4Jeff Sharkey std::string _tmpdir(create_data_path(uuid) + "/" + SECONDARY_USER_PREFIX); 38341ea424413c0381ef2aa15fc5bd5d4b88abd23c4Jeff Sharkey strcpy(tmpdir, _tmpdir.c_str()); 38441ea424413c0381ef2aa15fc5bd5d4b88abd23c4Jeff Sharkey 38594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood dirpos = tmpdir + strlen(tmpdir); 38694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood d = opendir(tmpdir); 38794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood if (d != NULL) { 38894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood while ((de = readdir(d))) { 38994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood if (de->d_type == DT_DIR) { 39094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood const char *name = de->d_name; 39194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood /* always skip "." and ".." */ 39294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood if (name[0] == '.') { 39394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood if (name[1] == 0) continue; 39494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood if ((name[1] == '.') && (name[2] == 0)) continue; 39594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood } 39694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood if ((strlen(name)+(dirpos-tmpdir)) < (sizeof(tmpdir)-1)) { 39794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood strcpy(dirpos, name); 39894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood //ALOGI("adding cache files from %s\n", tmpdir); 39994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood add_cache_files(cache, tmpdir, "cache"); 40094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood } else { 40194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood ALOGW("Path exceeds limit: %s%s", tmpdir, name); 40294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood } 40394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood } 40494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood } 40594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood closedir(d); 40694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood } 40794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood 40894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood // Collect cache files on external storage for all users (if it is mounted as part 40994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood // of the internal storage). 41094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood strcpy(tmpdir, android_media_dir.path); 41194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood dirpos = tmpdir + strlen(tmpdir); 41294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood d = opendir(tmpdir); 41394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood if (d != NULL) { 41494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood while ((de = readdir(d))) { 41594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood if (de->d_type == DT_DIR) { 41694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood const char *name = de->d_name; 41794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood /* skip any dir that doesn't start with a number, so not a user */ 41894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood if (name[0] < '0' || name[0] > '9') { 41994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood continue; 42094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood } 42194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood if ((strlen(name)+(dirpos-tmpdir)) < (sizeof(tmpdir)-1)) { 42294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood strcpy(dirpos, name); 42394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood if (lookup_media_dir(tmpdir, "Android") == 0 42494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood && lookup_media_dir(tmpdir, "data") == 0) { 42594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood //ALOGI("adding cache files from %s\n", tmpdir); 42694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood add_cache_files(cache, tmpdir, "cache"); 42794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood } 42894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood } else { 42994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood ALOGW("Path exceeds limit: %s%s", tmpdir, name); 43094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood } 43194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood } 43294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood } 43394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood closedir(d); 43494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood } 43594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood 43641ea424413c0381ef2aa15fc5bd5d4b88abd23c4Jeff Sharkey clear_cache_files(data_path, cache, free_size); 43794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood finish_cache_collection(cache); 43894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood 43941ea424413c0381ef2aa15fc5bd5d4b88abd23c4Jeff Sharkey return data_disk_free(data_path) >= free_size ? 0 : -1; 44094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood} 44194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood 4421b4003207750ea8fe8c7b03eb32d80f1df83979eNarayan Kamathint move_dex(const char *src, const char *dst, const char *instruction_set) 44394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood{ 44494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood char src_dex[PKG_PATH_MAX]; 44594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood char dst_dex[PKG_PATH_MAX]; 44694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood 447770180a4dd86f8bda6af2e6db4676e99a5bb1548Jeff Sharkey if (validate_apk_path(src)) { 448770180a4dd86f8bda6af2e6db4676e99a5bb1548Jeff Sharkey ALOGE("invalid apk path '%s' (bad prefix)\n", src); 449770180a4dd86f8bda6af2e6db4676e99a5bb1548Jeff Sharkey return -1; 450770180a4dd86f8bda6af2e6db4676e99a5bb1548Jeff Sharkey } 451770180a4dd86f8bda6af2e6db4676e99a5bb1548Jeff Sharkey if (validate_apk_path(dst)) { 452770180a4dd86f8bda6af2e6db4676e99a5bb1548Jeff Sharkey ALOGE("invalid apk path '%s' (bad prefix)\n", dst); 453770180a4dd86f8bda6af2e6db4676e99a5bb1548Jeff Sharkey return -1; 454770180a4dd86f8bda6af2e6db4676e99a5bb1548Jeff Sharkey } 45594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood 4561b4003207750ea8fe8c7b03eb32d80f1df83979eNarayan Kamath if (create_cache_path(src_dex, src, instruction_set)) return -1; 4571b4003207750ea8fe8c7b03eb32d80f1df83979eNarayan Kamath if (create_cache_path(dst_dex, dst, instruction_set)) return -1; 45894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood 45994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood ALOGV("move %s -> %s\n", src_dex, dst_dex); 46094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood if (rename(src_dex, dst_dex) < 0) { 46194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood ALOGE("Couldn't move %s: %s\n", src_dex, strerror(errno)); 46294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood return -1; 46394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood } else { 46494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood return 0; 46594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood } 46694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood} 46794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood 4681b4003207750ea8fe8c7b03eb32d80f1df83979eNarayan Kamathint rm_dex(const char *path, const char *instruction_set) 46994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood{ 47094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood char dex_path[PKG_PATH_MAX]; 47194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood 472770180a4dd86f8bda6af2e6db4676e99a5bb1548Jeff Sharkey if (validate_apk_path(path) && validate_system_app_path(path)) { 473770180a4dd86f8bda6af2e6db4676e99a5bb1548Jeff Sharkey ALOGE("invalid apk path '%s' (bad prefix)\n", path); 474770180a4dd86f8bda6af2e6db4676e99a5bb1548Jeff Sharkey return -1; 475770180a4dd86f8bda6af2e6db4676e99a5bb1548Jeff Sharkey } 476770180a4dd86f8bda6af2e6db4676e99a5bb1548Jeff Sharkey 4771b4003207750ea8fe8c7b03eb32d80f1df83979eNarayan Kamath if (create_cache_path(dex_path, path, instruction_set)) return -1; 47894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood 47994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood ALOGV("unlink %s\n", dex_path); 48094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood if (unlink(dex_path) < 0) { 481770180a4dd86f8bda6af2e6db4676e99a5bb1548Jeff Sharkey if (errno != ENOENT) { 482770180a4dd86f8bda6af2e6db4676e99a5bb1548Jeff Sharkey ALOGE("Couldn't unlink %s: %s\n", dex_path, strerror(errno)); 483770180a4dd86f8bda6af2e6db4676e99a5bb1548Jeff Sharkey } 48494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood return -1; 48594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood } else { 48694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood return 0; 48794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood } 48894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood} 48994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood 490d792118c493806eeb24a8203f508e6e18fe93bd7Jeff Sharkeyint get_size(const char *uuid, const char *pkgname, int userid, const char *apkpath, 4918b41780d73930b37b6254cc1dac5607c843839c0Dianne Hackborn const char *libdirpath, const char *fwdlock_apkpath, const char *asecpath, 4921b4003207750ea8fe8c7b03eb32d80f1df83979eNarayan Kamath const char *instruction_set, int64_t *_codesize, int64_t *_datasize, 4931b4003207750ea8fe8c7b03eb32d80f1df83979eNarayan Kamath int64_t *_cachesize, int64_t* _asecsize) 49494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood{ 49594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood DIR *d; 49694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood int dfd; 49794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood struct dirent *de; 49894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood struct stat s; 49994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood char path[PKG_PATH_MAX]; 50094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood 50194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood int64_t codesize = 0; 50294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood int64_t datasize = 0; 50394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood int64_t cachesize = 0; 50494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood int64_t asecsize = 0; 50594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood 506d792118c493806eeb24a8203f508e6e18fe93bd7Jeff Sharkey /* count the source apk as code -- but only if it's not 507d792118c493806eeb24a8203f508e6e18fe93bd7Jeff Sharkey * on the /system partition and its not on the sdcard. */ 50894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood if (validate_system_app_path(apkpath) && 50994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood strncmp(apkpath, android_asec_dir.path, android_asec_dir.len) != 0) { 51094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood if (stat(apkpath, &s) == 0) { 51194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood codesize += stat_size(&s); 512d792118c493806eeb24a8203f508e6e18fe93bd7Jeff Sharkey if (S_ISDIR(s.st_mode)) { 513d792118c493806eeb24a8203f508e6e18fe93bd7Jeff Sharkey d = opendir(apkpath); 514d792118c493806eeb24a8203f508e6e18fe93bd7Jeff Sharkey if (d != NULL) { 515d792118c493806eeb24a8203f508e6e18fe93bd7Jeff Sharkey dfd = dirfd(d); 516d792118c493806eeb24a8203f508e6e18fe93bd7Jeff Sharkey codesize += calculate_dir_size(dfd); 517d792118c493806eeb24a8203f508e6e18fe93bd7Jeff Sharkey closedir(d); 518d792118c493806eeb24a8203f508e6e18fe93bd7Jeff Sharkey } 519d792118c493806eeb24a8203f508e6e18fe93bd7Jeff Sharkey } 52094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood } 52194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood } 522d792118c493806eeb24a8203f508e6e18fe93bd7Jeff Sharkey 523d792118c493806eeb24a8203f508e6e18fe93bd7Jeff Sharkey /* count the forward locked apk as code if it is given */ 52494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood if (fwdlock_apkpath != NULL && fwdlock_apkpath[0] != '!') { 52594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood if (stat(fwdlock_apkpath, &s) == 0) { 52694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood codesize += stat_size(&s); 52794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood } 52894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood } 529d792118c493806eeb24a8203f508e6e18fe93bd7Jeff Sharkey 530d792118c493806eeb24a8203f508e6e18fe93bd7Jeff Sharkey /* count the cached dexfile as code */ 5311b4003207750ea8fe8c7b03eb32d80f1df83979eNarayan Kamath if (!create_cache_path(path, apkpath, instruction_set)) { 53294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood if (stat(path, &s) == 0) { 53394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood codesize += stat_size(&s); 53494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood } 53594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood } 53694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood 537d792118c493806eeb24a8203f508e6e18fe93bd7Jeff Sharkey /* add in size of any libraries */ 5388b41780d73930b37b6254cc1dac5607c843839c0Dianne Hackborn if (libdirpath != NULL && libdirpath[0] != '!') { 5398b41780d73930b37b6254cc1dac5607c843839c0Dianne Hackborn d = opendir(libdirpath); 54094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood if (d != NULL) { 54194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood dfd = dirfd(d); 54294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood codesize += calculate_dir_size(dfd); 54394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood closedir(d); 54494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood } 54594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood } 54694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood 547d792118c493806eeb24a8203f508e6e18fe93bd7Jeff Sharkey /* compute asec size if it is given */ 54894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood if (asecpath != NULL && asecpath[0] != '!') { 54994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood if (stat(asecpath, &s) == 0) { 55094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood asecsize += stat_size(&s); 55194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood } 55294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood } 55394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood 554d792118c493806eeb24a8203f508e6e18fe93bd7Jeff Sharkey std::vector<userid_t> users; 555d792118c493806eeb24a8203f508e6e18fe93bd7Jeff Sharkey if (userid == -1) { 556d792118c493806eeb24a8203f508e6e18fe93bd7Jeff Sharkey users = get_known_users(uuid); 557d792118c493806eeb24a8203f508e6e18fe93bd7Jeff Sharkey } else { 558d792118c493806eeb24a8203f508e6e18fe93bd7Jeff Sharkey users.push_back(userid); 55994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood } 56094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood 561d792118c493806eeb24a8203f508e6e18fe93bd7Jeff Sharkey for (auto user : users) { 562d792118c493806eeb24a8203f508e6e18fe93bd7Jeff Sharkey std::string _pkgdir(create_data_user_package_path(uuid, user, pkgname)); 563d792118c493806eeb24a8203f508e6e18fe93bd7Jeff Sharkey const char* pkgdir = _pkgdir.c_str(); 56494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood 565d792118c493806eeb24a8203f508e6e18fe93bd7Jeff Sharkey d = opendir(pkgdir); 566d792118c493806eeb24a8203f508e6e18fe93bd7Jeff Sharkey if (d == NULL) { 567d792118c493806eeb24a8203f508e6e18fe93bd7Jeff Sharkey PLOG(WARNING) << "Failed to open " << pkgdir; 568d792118c493806eeb24a8203f508e6e18fe93bd7Jeff Sharkey continue; 569d792118c493806eeb24a8203f508e6e18fe93bd7Jeff Sharkey } 570d792118c493806eeb24a8203f508e6e18fe93bd7Jeff Sharkey dfd = dirfd(d); 571d792118c493806eeb24a8203f508e6e18fe93bd7Jeff Sharkey 572d792118c493806eeb24a8203f508e6e18fe93bd7Jeff Sharkey /* most stuff in the pkgdir is data, except for the "cache" 573d792118c493806eeb24a8203f508e6e18fe93bd7Jeff Sharkey * directory and below, which is cache, and the "lib" directory 574d792118c493806eeb24a8203f508e6e18fe93bd7Jeff Sharkey * and below, which is code... 575d792118c493806eeb24a8203f508e6e18fe93bd7Jeff Sharkey */ 576d792118c493806eeb24a8203f508e6e18fe93bd7Jeff Sharkey while ((de = readdir(d))) { 577d792118c493806eeb24a8203f508e6e18fe93bd7Jeff Sharkey const char *name = de->d_name; 578d792118c493806eeb24a8203f508e6e18fe93bd7Jeff Sharkey 579d792118c493806eeb24a8203f508e6e18fe93bd7Jeff Sharkey if (de->d_type == DT_DIR) { 580d792118c493806eeb24a8203f508e6e18fe93bd7Jeff Sharkey int subfd; 581d792118c493806eeb24a8203f508e6e18fe93bd7Jeff Sharkey int64_t statsize = 0; 582d792118c493806eeb24a8203f508e6e18fe93bd7Jeff Sharkey int64_t dirsize = 0; 583d792118c493806eeb24a8203f508e6e18fe93bd7Jeff Sharkey /* always skip "." and ".." */ 584d792118c493806eeb24a8203f508e6e18fe93bd7Jeff Sharkey if (name[0] == '.') { 585d792118c493806eeb24a8203f508e6e18fe93bd7Jeff Sharkey if (name[1] == 0) continue; 586d792118c493806eeb24a8203f508e6e18fe93bd7Jeff Sharkey if ((name[1] == '.') && (name[2] == 0)) continue; 587d792118c493806eeb24a8203f508e6e18fe93bd7Jeff Sharkey } 588d792118c493806eeb24a8203f508e6e18fe93bd7Jeff Sharkey if (fstatat(dfd, name, &s, AT_SYMLINK_NOFOLLOW) == 0) { 589d792118c493806eeb24a8203f508e6e18fe93bd7Jeff Sharkey statsize = stat_size(&s); 590d792118c493806eeb24a8203f508e6e18fe93bd7Jeff Sharkey } 591d792118c493806eeb24a8203f508e6e18fe93bd7Jeff Sharkey subfd = openat(dfd, name, O_RDONLY | O_DIRECTORY); 592d792118c493806eeb24a8203f508e6e18fe93bd7Jeff Sharkey if (subfd >= 0) { 593d792118c493806eeb24a8203f508e6e18fe93bd7Jeff Sharkey dirsize = calculate_dir_size(subfd); 594d792118c493806eeb24a8203f508e6e18fe93bd7Jeff Sharkey } 595d792118c493806eeb24a8203f508e6e18fe93bd7Jeff Sharkey if(!strcmp(name,"lib")) { 596d792118c493806eeb24a8203f508e6e18fe93bd7Jeff Sharkey codesize += dirsize + statsize; 597d792118c493806eeb24a8203f508e6e18fe93bd7Jeff Sharkey } else if(!strcmp(name,"cache")) { 598d792118c493806eeb24a8203f508e6e18fe93bd7Jeff Sharkey cachesize += dirsize + statsize; 599d792118c493806eeb24a8203f508e6e18fe93bd7Jeff Sharkey } else { 600d792118c493806eeb24a8203f508e6e18fe93bd7Jeff Sharkey datasize += dirsize + statsize; 601d792118c493806eeb24a8203f508e6e18fe93bd7Jeff Sharkey } 602d792118c493806eeb24a8203f508e6e18fe93bd7Jeff Sharkey } else if (de->d_type == DT_LNK && !strcmp(name,"lib")) { 603d792118c493806eeb24a8203f508e6e18fe93bd7Jeff Sharkey // This is the symbolic link to the application's library 604d792118c493806eeb24a8203f508e6e18fe93bd7Jeff Sharkey // code. We'll count this as code instead of data, since 605d792118c493806eeb24a8203f508e6e18fe93bd7Jeff Sharkey // it is not something that the app creates. 606d792118c493806eeb24a8203f508e6e18fe93bd7Jeff Sharkey if (fstatat(dfd, name, &s, AT_SYMLINK_NOFOLLOW) == 0) { 607d792118c493806eeb24a8203f508e6e18fe93bd7Jeff Sharkey codesize += stat_size(&s); 608d792118c493806eeb24a8203f508e6e18fe93bd7Jeff Sharkey } 60994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood } else { 610d792118c493806eeb24a8203f508e6e18fe93bd7Jeff Sharkey if (fstatat(dfd, name, &s, AT_SYMLINK_NOFOLLOW) == 0) { 611d792118c493806eeb24a8203f508e6e18fe93bd7Jeff Sharkey datasize += stat_size(&s); 612d792118c493806eeb24a8203f508e6e18fe93bd7Jeff Sharkey } 61394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood } 61494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood } 615d792118c493806eeb24a8203f508e6e18fe93bd7Jeff Sharkey closedir(d); 61694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood } 61794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood *_codesize = codesize; 61894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood *_datasize = datasize; 61994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood *_cachesize = cachesize; 62094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood *_asecsize = asecsize; 62194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood return 0; 62294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood} 62394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood 6241b4003207750ea8fe8c7b03eb32d80f1df83979eNarayan Kamathint create_cache_path(char path[PKG_PATH_MAX], const char *src, const char *instruction_set) 62594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood{ 62694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood char *tmp; 62794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood int srclen; 62894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood int dstlen; 62994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood 63094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood srclen = strlen(src); 63194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood 63294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood /* demand that we are an absolute path */ 63394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood if ((src == 0) || (src[0] != '/') || strstr(src,"..")) { 63494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood return -1; 63594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood } 63694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood 63794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood if (srclen > PKG_PATH_MAX) { // XXX: PKG_NAME_MAX? 63894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood return -1; 63994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood } 64094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood 641d93707342a61e66bc3eb2145628158452f577f42Dave Allison dstlen = srclen + strlen(DALVIK_CACHE_PREFIX) + 6421b4003207750ea8fe8c7b03eb32d80f1df83979eNarayan Kamath strlen(instruction_set) + 6431b4003207750ea8fe8c7b03eb32d80f1df83979eNarayan Kamath strlen(DALVIK_CACHE_POSTFIX) + 2; 644d93707342a61e66bc3eb2145628158452f577f42Dave Allison 64594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood if (dstlen > PKG_PATH_MAX) { 64694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood return -1; 64794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood } 64894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood 6491b4003207750ea8fe8c7b03eb32d80f1df83979eNarayan Kamath sprintf(path,"%s%s/%s%s", 65094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood DALVIK_CACHE_PREFIX, 6511b4003207750ea8fe8c7b03eb32d80f1df83979eNarayan Kamath instruction_set, 65294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood src + 1, /* skip the leading / */ 65394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood DALVIK_CACHE_POSTFIX); 654d93707342a61e66bc3eb2145628158452f577f42Dave Allison 6551b4003207750ea8fe8c7b03eb32d80f1df83979eNarayan Kamath for(tmp = path + strlen(DALVIK_CACHE_PREFIX) + strlen(instruction_set) + 1; *tmp; tmp++) { 65694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood if (*tmp == '/') { 65794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood *tmp = '@'; 65894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood } 65994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood } 66094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood 66194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood return 0; 66294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood} 66394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood 664b0d8d00b2916aef7b01ad42f6d441f5b46b7731aYevgeny Roubanstatic int split_count(const char *str) 665b0d8d00b2916aef7b01ad42f6d441f5b46b7731aYevgeny Rouban{ 666b0d8d00b2916aef7b01ad42f6d441f5b46b7731aYevgeny Rouban char *ctx; 667b0d8d00b2916aef7b01ad42f6d441f5b46b7731aYevgeny Rouban int count = 0; 668b0d8d00b2916aef7b01ad42f6d441f5b46b7731aYevgeny Rouban char buf[PROPERTY_VALUE_MAX]; 669b0d8d00b2916aef7b01ad42f6d441f5b46b7731aYevgeny Rouban 670b0d8d00b2916aef7b01ad42f6d441f5b46b7731aYevgeny Rouban strncpy(buf, str, sizeof(buf)); 671b0d8d00b2916aef7b01ad42f6d441f5b46b7731aYevgeny Rouban char *pBuf = buf; 672b0d8d00b2916aef7b01ad42f6d441f5b46b7731aYevgeny Rouban 673b0d8d00b2916aef7b01ad42f6d441f5b46b7731aYevgeny Rouban while(strtok_r(pBuf, " ", &ctx) != NULL) { 674b0d8d00b2916aef7b01ad42f6d441f5b46b7731aYevgeny Rouban count++; 675b0d8d00b2916aef7b01ad42f6d441f5b46b7731aYevgeny Rouban pBuf = NULL; 676b0d8d00b2916aef7b01ad42f6d441f5b46b7731aYevgeny Rouban } 677b0d8d00b2916aef7b01ad42f6d441f5b46b7731aYevgeny Rouban 678b0d8d00b2916aef7b01ad42f6d441f5b46b7731aYevgeny Rouban return count; 679b0d8d00b2916aef7b01ad42f6d441f5b46b7731aYevgeny Rouban} 680b0d8d00b2916aef7b01ad42f6d441f5b46b7731aYevgeny Rouban 68114e084d39ac44e9d4d0a0143bf1f111011343d34neo.chaestatic int split(char *buf, const char **argv) 682b0d8d00b2916aef7b01ad42f6d441f5b46b7731aYevgeny Rouban{ 683b0d8d00b2916aef7b01ad42f6d441f5b46b7731aYevgeny Rouban char *ctx; 684b0d8d00b2916aef7b01ad42f6d441f5b46b7731aYevgeny Rouban int count = 0; 685b0d8d00b2916aef7b01ad42f6d441f5b46b7731aYevgeny Rouban char *tok; 686b0d8d00b2916aef7b01ad42f6d441f5b46b7731aYevgeny Rouban char *pBuf = buf; 687b0d8d00b2916aef7b01ad42f6d441f5b46b7731aYevgeny Rouban 688b0d8d00b2916aef7b01ad42f6d441f5b46b7731aYevgeny Rouban while((tok = strtok_r(pBuf, " ", &ctx)) != NULL) { 689b0d8d00b2916aef7b01ad42f6d441f5b46b7731aYevgeny Rouban argv[count++] = tok; 690b0d8d00b2916aef7b01ad42f6d441f5b46b7731aYevgeny Rouban pBuf = NULL; 691b0d8d00b2916aef7b01ad42f6d441f5b46b7731aYevgeny Rouban } 692b0d8d00b2916aef7b01ad42f6d441f5b46b7731aYevgeny Rouban 693b0d8d00b2916aef7b01ad42f6d441f5b46b7731aYevgeny Rouban return count; 694b0d8d00b2916aef7b01ad42f6d441f5b46b7731aYevgeny Rouban} 695b0d8d00b2916aef7b01ad42f6d441f5b46b7731aYevgeny Rouban 6967365a10689df23334d245b211ce272502ad20669Alex Lightstatic void run_patchoat(int input_fd, int oat_fd, const char* input_file_name, 69799d9fb15b4a1eb534261ae81b2cf25aec4447bd0Chih-Hung Hsieh const char* output_file_name, const char *pkgname __unused, const char *instruction_set) 6987365a10689df23334d245b211ce272502ad20669Alex Light{ 6997365a10689df23334d245b211ce272502ad20669Alex Light static const int MAX_INT_LEN = 12; // '-'+10dig+'\0' -OR- 0x+8dig 7008fc7315a67fdbf9b56cc6fa061f0773be2223a81Calin Juravle static const unsigned int MAX_INSTRUCTION_SET_LEN = 7; 7017365a10689df23334d245b211ce272502ad20669Alex Light 7027365a10689df23334d245b211ce272502ad20669Alex Light static const char* PATCHOAT_BIN = "/system/bin/patchoat"; 7037365a10689df23334d245b211ce272502ad20669Alex Light if (strlen(instruction_set) >= MAX_INSTRUCTION_SET_LEN) { 7047365a10689df23334d245b211ce272502ad20669Alex Light ALOGE("Instruction set %s longer than max length of %d", 7057365a10689df23334d245b211ce272502ad20669Alex Light instruction_set, MAX_INSTRUCTION_SET_LEN); 7067365a10689df23334d245b211ce272502ad20669Alex Light return; 7077365a10689df23334d245b211ce272502ad20669Alex Light } 7087365a10689df23334d245b211ce272502ad20669Alex Light 7097365a10689df23334d245b211ce272502ad20669Alex Light /* input_file_name/input_fd should be the .odex/.oat file that is precompiled. I think*/ 7107365a10689df23334d245b211ce272502ad20669Alex Light char instruction_set_arg[strlen("--instruction-set=") + MAX_INSTRUCTION_SET_LEN]; 7117365a10689df23334d245b211ce272502ad20669Alex Light char output_oat_fd_arg[strlen("--output-oat-fd=") + MAX_INT_LEN]; 7127365a10689df23334d245b211ce272502ad20669Alex Light char input_oat_fd_arg[strlen("--input-oat-fd=") + MAX_INT_LEN]; 7137365a10689df23334d245b211ce272502ad20669Alex Light const char* patched_image_location_arg = "--patched-image-location=/system/framework/boot.art"; 7147365a10689df23334d245b211ce272502ad20669Alex Light // The caller has already gotten all the locks we need. 7157365a10689df23334d245b211ce272502ad20669Alex Light const char* no_lock_arg = "--no-lock-output"; 7167365a10689df23334d245b211ce272502ad20669Alex Light sprintf(instruction_set_arg, "--instruction-set=%s", instruction_set); 7177365a10689df23334d245b211ce272502ad20669Alex Light sprintf(output_oat_fd_arg, "--output-oat-fd=%d", oat_fd); 7187365a10689df23334d245b211ce272502ad20669Alex Light sprintf(input_oat_fd_arg, "--input-oat-fd=%d", input_fd); 719a7915d437c3971943f82dfc2370fe7a5df522801Alex Light ALOGV("Running %s isa=%s in-fd=%d (%s) out-fd=%d (%s)\n", 7207365a10689df23334d245b211ce272502ad20669Alex Light PATCHOAT_BIN, instruction_set, input_fd, input_file_name, oat_fd, output_file_name); 7217365a10689df23334d245b211ce272502ad20669Alex Light 7227365a10689df23334d245b211ce272502ad20669Alex Light /* patchoat, patched-image-location, no-lock, isa, input-fd, output-fd */ 7237365a10689df23334d245b211ce272502ad20669Alex Light char* argv[7]; 7247365a10689df23334d245b211ce272502ad20669Alex Light argv[0] = (char*) PATCHOAT_BIN; 7257365a10689df23334d245b211ce272502ad20669Alex Light argv[1] = (char*) patched_image_location_arg; 7267365a10689df23334d245b211ce272502ad20669Alex Light argv[2] = (char*) no_lock_arg; 7277365a10689df23334d245b211ce272502ad20669Alex Light argv[3] = instruction_set_arg; 7287365a10689df23334d245b211ce272502ad20669Alex Light argv[4] = output_oat_fd_arg; 7297365a10689df23334d245b211ce272502ad20669Alex Light argv[5] = input_oat_fd_arg; 7307365a10689df23334d245b211ce272502ad20669Alex Light argv[6] = NULL; 7317365a10689df23334d245b211ce272502ad20669Alex Light 7327365a10689df23334d245b211ce272502ad20669Alex Light execv(PATCHOAT_BIN, (char* const *)argv); 7337365a10689df23334d245b211ce272502ad20669Alex Light ALOGE("execv(%s) failed: %s\n", PATCHOAT_BIN, strerror(errno)); 7347365a10689df23334d245b211ce272502ad20669Alex Light} 7357365a10689df23334d245b211ce272502ad20669Alex Light 7363822b8b79cf533ee8573794176838406c32a1c20Andreas Gampestatic bool check_boolean_property(const char* property_name, bool default_value = false) { 7373822b8b79cf533ee8573794176838406c32a1c20Andreas Gampe char tmp_property_value[PROPERTY_VALUE_MAX]; 7383822b8b79cf533ee8573794176838406c32a1c20Andreas Gampe bool have_property = property_get(property_name, tmp_property_value, nullptr) > 0; 7393822b8b79cf533ee8573794176838406c32a1c20Andreas Gampe if (!have_property) { 7403822b8b79cf533ee8573794176838406c32a1c20Andreas Gampe return default_value; 7413822b8b79cf533ee8573794176838406c32a1c20Andreas Gampe } 7423822b8b79cf533ee8573794176838406c32a1c20Andreas Gampe return strcmp(tmp_property_value, "true") == 0; 7433822b8b79cf533ee8573794176838406c32a1c20Andreas Gampe} 7443822b8b79cf533ee8573794176838406c32a1c20Andreas Gampe 7451705fc44fb85c4232637f9f7189c3bdca98a63d5Brian Carlstromstatic void run_dex2oat(int zip_fd, int oat_fd, const char* input_file_name, 746df9dadd5e5c287110d837c38aaec12bcf5e5d151Calin Juravle const char* output_file_name, int swap_fd, const char *instruction_set, 74712434f8cce66a753ef49c07b503f9625e01366c8Todd Kennedy bool vm_safe_mode, bool debuggable, bool post_bootcomplete, bool use_jit) 7481705fc44fb85c4232637f9f7189c3bdca98a63d5Brian Carlstrom{ 7498fc7315a67fdbf9b56cc6fa061f0773be2223a81Calin Juravle static const unsigned int MAX_INSTRUCTION_SET_LEN = 7; 7508fc7315a67fdbf9b56cc6fa061f0773be2223a81Calin Juravle 7518fc7315a67fdbf9b56cc6fa061f0773be2223a81Calin Juravle if (strlen(instruction_set) >= MAX_INSTRUCTION_SET_LEN) { 7528fc7315a67fdbf9b56cc6fa061f0773be2223a81Calin Juravle ALOGE("Instruction set %s longer than max length of %d", 7538fc7315a67fdbf9b56cc6fa061f0773be2223a81Calin Juravle instruction_set, MAX_INSTRUCTION_SET_LEN); 7548fc7315a67fdbf9b56cc6fa061f0773be2223a81Calin Juravle return; 7558fc7315a67fdbf9b56cc6fa061f0773be2223a81Calin Juravle } 7568fc7315a67fdbf9b56cc6fa061f0773be2223a81Calin Juravle 757e46a75a0f6007967cd0d161959af844772cdc330Brian Carlstrom char dex2oat_Xms_flag[PROPERTY_VALUE_MAX]; 758e46a75a0f6007967cd0d161959af844772cdc330Brian Carlstrom bool have_dex2oat_Xms_flag = property_get("dalvik.vm.dex2oat-Xms", dex2oat_Xms_flag, NULL) > 0; 759e46a75a0f6007967cd0d161959af844772cdc330Brian Carlstrom 760e46a75a0f6007967cd0d161959af844772cdc330Brian Carlstrom char dex2oat_Xmx_flag[PROPERTY_VALUE_MAX]; 761e46a75a0f6007967cd0d161959af844772cdc330Brian Carlstrom bool have_dex2oat_Xmx_flag = property_get("dalvik.vm.dex2oat-Xmx", dex2oat_Xmx_flag, NULL) > 0; 762e46a75a0f6007967cd0d161959af844772cdc330Brian Carlstrom 763cf51ba1360ee13459830a0502b0d454d0145544fBrian Carlstrom char dex2oat_compiler_filter_flag[PROPERTY_VALUE_MAX]; 764cf51ba1360ee13459830a0502b0d454d0145544fBrian Carlstrom bool have_dex2oat_compiler_filter_flag = property_get("dalvik.vm.dex2oat-filter", 765cf51ba1360ee13459830a0502b0d454d0145544fBrian Carlstrom dex2oat_compiler_filter_flag, NULL) > 0; 766cf51ba1360ee13459830a0502b0d454d0145544fBrian Carlstrom 7678d7af8b2418cc5e7e59746f0cb359a75ed0bdfd1Andreas Gampe char dex2oat_threads_buf[PROPERTY_VALUE_MAX]; 768919461cbeef3e9f35388fc099a5fcdae1cb79cc6Andreas Gampe bool have_dex2oat_threads_flag = property_get(post_bootcomplete 769919461cbeef3e9f35388fc099a5fcdae1cb79cc6Andreas Gampe ? "dalvik.vm.dex2oat-threads" 770919461cbeef3e9f35388fc099a5fcdae1cb79cc6Andreas Gampe : "dalvik.vm.boot-dex2oat-threads", 771919461cbeef3e9f35388fc099a5fcdae1cb79cc6Andreas Gampe dex2oat_threads_buf, 772919461cbeef3e9f35388fc099a5fcdae1cb79cc6Andreas Gampe NULL) > 0; 7738d7af8b2418cc5e7e59746f0cb359a75ed0bdfd1Andreas Gampe char dex2oat_threads_arg[PROPERTY_VALUE_MAX + 2]; 7748d7af8b2418cc5e7e59746f0cb359a75ed0bdfd1Andreas Gampe if (have_dex2oat_threads_flag) { 7758d7af8b2418cc5e7e59746f0cb359a75ed0bdfd1Andreas Gampe sprintf(dex2oat_threads_arg, "-j%s", dex2oat_threads_buf); 7768d7af8b2418cc5e7e59746f0cb359a75ed0bdfd1Andreas Gampe } 7778d7af8b2418cc5e7e59746f0cb359a75ed0bdfd1Andreas Gampe 7788fc7315a67fdbf9b56cc6fa061f0773be2223a81Calin Juravle char dex2oat_isa_features_key[PROPERTY_KEY_MAX]; 7798fc7315a67fdbf9b56cc6fa061f0773be2223a81Calin Juravle sprintf(dex2oat_isa_features_key, "dalvik.vm.isa.%s.features", instruction_set); 7808fc7315a67fdbf9b56cc6fa061f0773be2223a81Calin Juravle char dex2oat_isa_features[PROPERTY_VALUE_MAX]; 7818fc7315a67fdbf9b56cc6fa061f0773be2223a81Calin Juravle bool have_dex2oat_isa_features = property_get(dex2oat_isa_features_key, 7828fc7315a67fdbf9b56cc6fa061f0773be2223a81Calin Juravle dex2oat_isa_features, NULL) > 0; 7838fc7315a67fdbf9b56cc6fa061f0773be2223a81Calin Juravle 78416a95b267ac6aac75453f65f1bc382ce65c0741eIan Rogers char dex2oat_isa_variant_key[PROPERTY_KEY_MAX]; 78516a95b267ac6aac75453f65f1bc382ce65c0741eIan Rogers sprintf(dex2oat_isa_variant_key, "dalvik.vm.isa.%s.variant", instruction_set); 78616a95b267ac6aac75453f65f1bc382ce65c0741eIan Rogers char dex2oat_isa_variant[PROPERTY_VALUE_MAX]; 78716a95b267ac6aac75453f65f1bc382ce65c0741eIan Rogers bool have_dex2oat_isa_variant = property_get(dex2oat_isa_variant_key, 78816a95b267ac6aac75453f65f1bc382ce65c0741eIan Rogers dex2oat_isa_variant, NULL) > 0; 78916a95b267ac6aac75453f65f1bc382ce65c0741eIan Rogers 79014e084d39ac44e9d4d0a0143bf1f111011343d34neo.chae const char *dex2oat_norelocation = "-Xnorelocate"; 79114e084d39ac44e9d4d0a0143bf1f111011343d34neo.chae bool have_dex2oat_relocation_skip_flag = false; 79214e084d39ac44e9d4d0a0143bf1f111011343d34neo.chae 7930ae8e39ebcc26836ba55a5ee4481825a0f473a9eBrian Carlstrom char dex2oat_flags[PROPERTY_VALUE_MAX]; 794b0d8d00b2916aef7b01ad42f6d441f5b46b7731aYevgeny Rouban int dex2oat_flags_count = property_get("dalvik.vm.dex2oat-flags", 795b0d8d00b2916aef7b01ad42f6d441f5b46b7731aYevgeny Rouban dex2oat_flags, NULL) <= 0 ? 0 : split_count(dex2oat_flags); 7960ae8e39ebcc26836ba55a5ee4481825a0f473a9eBrian Carlstrom ALOGV("dalvik.vm.dex2oat-flags=%s\n", dex2oat_flags); 7970ae8e39ebcc26836ba55a5ee4481825a0f473a9eBrian Carlstrom 798538998f204d1e542e235de9e7ce18ef4dc68c9ccBrian Carlstrom // If we booting without the real /data, don't spend time compiling. 799538998f204d1e542e235de9e7ce18ef4dc68c9ccBrian Carlstrom char vold_decrypt[PROPERTY_VALUE_MAX]; 800538998f204d1e542e235de9e7ce18ef4dc68c9ccBrian Carlstrom bool have_vold_decrypt = property_get("vold.decrypt", vold_decrypt, "") > 0; 801538998f204d1e542e235de9e7ce18ef4dc68c9ccBrian Carlstrom bool skip_compilation = (have_vold_decrypt && 802538998f204d1e542e235de9e7ce18ef4dc68c9ccBrian Carlstrom (strcmp(vold_decrypt, "trigger_restart_min_framework") == 0 || 803538998f204d1e542e235de9e7ce18ef4dc68c9ccBrian Carlstrom (strcmp(vold_decrypt, "1") == 0))); 804538998f204d1e542e235de9e7ce18ef4dc68c9ccBrian Carlstrom 805528c8ddc60df7b3d291b389117e4db878a20ad48David Srbecky bool generate_debug_info = check_boolean_property("debug.generate-debug-info"); 806d4a7b459f4f383988440c0512513b321ce03fc22Mathieu Chartier 8071705fc44fb85c4232637f9f7189c3bdca98a63d5Brian Carlstrom static const char* DEX2OAT_BIN = "/system/bin/dex2oat"; 80853e0776d967324e2908e3be56b80cddb2c9d9e03Brian Carlstrom 80953e0776d967324e2908e3be56b80cddb2c9d9e03Brian Carlstrom static const char* RUNTIME_ARG = "--runtime-arg"; 81053e0776d967324e2908e3be56b80cddb2c9d9e03Brian Carlstrom 8111705fc44fb85c4232637f9f7189c3bdca98a63d5Brian Carlstrom static const int MAX_INT_LEN = 12; // '-'+10dig+'\0' -OR- 0x+8dig 8121b4003207750ea8fe8c7b03eb32d80f1df83979eNarayan Kamath 8131705fc44fb85c4232637f9f7189c3bdca98a63d5Brian Carlstrom char zip_fd_arg[strlen("--zip-fd=") + MAX_INT_LEN]; 8141705fc44fb85c4232637f9f7189c3bdca98a63d5Brian Carlstrom char zip_location_arg[strlen("--zip-location=") + PKG_PATH_MAX]; 8151705fc44fb85c4232637f9f7189c3bdca98a63d5Brian Carlstrom char oat_fd_arg[strlen("--oat-fd=") + MAX_INT_LEN]; 8167195fcc2185c35b45a8f28c79fde4999b38850e8Brian Carlstrom char oat_location_arg[strlen("--oat-location=") + PKG_PATH_MAX]; 8171b4003207750ea8fe8c7b03eb32d80f1df83979eNarayan Kamath char instruction_set_arg[strlen("--instruction-set=") + MAX_INSTRUCTION_SET_LEN]; 81816a95b267ac6aac75453f65f1bc382ce65c0741eIan Rogers char instruction_set_variant_arg[strlen("--instruction-set-variant=") + PROPERTY_VALUE_MAX]; 8198fc7315a67fdbf9b56cc6fa061f0773be2223a81Calin Juravle char instruction_set_features_arg[strlen("--instruction-set-features=") + PROPERTY_VALUE_MAX]; 820e46a75a0f6007967cd0d161959af844772cdc330Brian Carlstrom char dex2oat_Xms_arg[strlen("-Xms") + PROPERTY_VALUE_MAX]; 821e46a75a0f6007967cd0d161959af844772cdc330Brian Carlstrom char dex2oat_Xmx_arg[strlen("-Xmx") + PROPERTY_VALUE_MAX]; 822cf51ba1360ee13459830a0502b0d454d0145544fBrian Carlstrom char dex2oat_compiler_filter_arg[strlen("--compiler-filter=") + PROPERTY_VALUE_MAX]; 823e1c01353c4dc6058a384eea9853238d2a87040dbAndreas Gampe bool have_dex2oat_swap_fd = false; 824e1c01353c4dc6058a384eea9853238d2a87040dbAndreas Gampe char dex2oat_swap_fd[strlen("--swap-fd=") + MAX_INT_LEN]; 8251705fc44fb85c4232637f9f7189c3bdca98a63d5Brian Carlstrom 8261705fc44fb85c4232637f9f7189c3bdca98a63d5Brian Carlstrom sprintf(zip_fd_arg, "--zip-fd=%d", zip_fd); 8271705fc44fb85c4232637f9f7189c3bdca98a63d5Brian Carlstrom sprintf(zip_location_arg, "--zip-location=%s", input_file_name); 8281705fc44fb85c4232637f9f7189c3bdca98a63d5Brian Carlstrom sprintf(oat_fd_arg, "--oat-fd=%d", oat_fd); 8291705fc44fb85c4232637f9f7189c3bdca98a63d5Brian Carlstrom sprintf(oat_location_arg, "--oat-location=%s", output_file_name); 8301b4003207750ea8fe8c7b03eb32d80f1df83979eNarayan Kamath sprintf(instruction_set_arg, "--instruction-set=%s", instruction_set); 83116a95b267ac6aac75453f65f1bc382ce65c0741eIan Rogers sprintf(instruction_set_variant_arg, "--instruction-set-variant=%s", dex2oat_isa_variant); 8328fc7315a67fdbf9b56cc6fa061f0773be2223a81Calin Juravle sprintf(instruction_set_features_arg, "--instruction-set-features=%s", dex2oat_isa_features); 833e1c01353c4dc6058a384eea9853238d2a87040dbAndreas Gampe if (swap_fd >= 0) { 834e1c01353c4dc6058a384eea9853238d2a87040dbAndreas Gampe have_dex2oat_swap_fd = true; 835e1c01353c4dc6058a384eea9853238d2a87040dbAndreas Gampe sprintf(dex2oat_swap_fd, "--swap-fd=%d", swap_fd); 836e1c01353c4dc6058a384eea9853238d2a87040dbAndreas Gampe } 83757c69c39640a7d6a08b3afb56361d76f7ecf1250Calin Juravle 83812434f8cce66a753ef49c07b503f9625e01366c8Todd Kennedy // use the JIT if either it's specified as a dexopt flag or if the property is set 83912434f8cce66a753ef49c07b503f9625e01366c8Todd Kennedy use_jit = use_jit || check_boolean_property("debug.usejit"); 840e46a75a0f6007967cd0d161959af844772cdc330Brian Carlstrom if (have_dex2oat_Xms_flag) { 841e46a75a0f6007967cd0d161959af844772cdc330Brian Carlstrom sprintf(dex2oat_Xms_arg, "-Xms%s", dex2oat_Xms_flag); 842e46a75a0f6007967cd0d161959af844772cdc330Brian Carlstrom } 843e46a75a0f6007967cd0d161959af844772cdc330Brian Carlstrom if (have_dex2oat_Xmx_flag) { 844e46a75a0f6007967cd0d161959af844772cdc330Brian Carlstrom sprintf(dex2oat_Xmx_arg, "-Xmx%s", dex2oat_Xmx_flag); 845e46a75a0f6007967cd0d161959af844772cdc330Brian Carlstrom } 846538998f204d1e542e235de9e7ce18ef4dc68c9ccBrian Carlstrom if (skip_compilation) { 847e18987efb5e39ca1bed15527b7b82bde55c99669Brian Carlstrom strcpy(dex2oat_compiler_filter_arg, "--compiler-filter=verify-none"); 848538998f204d1e542e235de9e7ce18ef4dc68c9ccBrian Carlstrom have_dex2oat_compiler_filter_flag = true; 84914e084d39ac44e9d4d0a0143bf1f111011343d34neo.chae have_dex2oat_relocation_skip_flag = true; 850b1efac103523efccbe671e76cc0eaaeab810415bCalin Juravle } else if (vm_safe_mode) { 851b1efac103523efccbe671e76cc0eaaeab810415bCalin Juravle strcpy(dex2oat_compiler_filter_arg, "--compiler-filter=interpret-only"); 85297477d203eaf0c3235bbe2415356f20a0431cadaCalin Juravle have_dex2oat_compiler_filter_flag = true; 853d4a7b459f4f383988440c0512513b321ce03fc22Mathieu Chartier } else if (use_jit) { 854d4a7b459f4f383988440c0512513b321ce03fc22Mathieu Chartier strcpy(dex2oat_compiler_filter_arg, "--compiler-filter=verify-at-runtime"); 855d4a7b459f4f383988440c0512513b321ce03fc22Mathieu Chartier have_dex2oat_compiler_filter_flag = true; 856538998f204d1e542e235de9e7ce18ef4dc68c9ccBrian Carlstrom } else if (have_dex2oat_compiler_filter_flag) { 857cf51ba1360ee13459830a0502b0d454d0145544fBrian Carlstrom sprintf(dex2oat_compiler_filter_arg, "--compiler-filter=%s", dex2oat_compiler_filter_flag); 858cf51ba1360ee13459830a0502b0d454d0145544fBrian Carlstrom } 859e46a75a0f6007967cd0d161959af844772cdc330Brian Carlstrom 860598c25e23f7c97470e09a2316513ddf2efdfb670Andreas Gampe // Check whether all apps should be compiled debuggable. 861598c25e23f7c97470e09a2316513ddf2efdfb670Andreas Gampe if (!debuggable) { 862df9dadd5e5c287110d837c38aaec12bcf5e5d151Calin Juravle char prop_buf[PROPERTY_VALUE_MAX]; 863598c25e23f7c97470e09a2316513ddf2efdfb670Andreas Gampe debuggable = 864598c25e23f7c97470e09a2316513ddf2efdfb670Andreas Gampe (property_get("dalvik.vm.always_debuggable", prop_buf, "0") > 0) && 865598c25e23f7c97470e09a2316513ddf2efdfb670Andreas Gampe (prop_buf[0] == '1'); 866598c25e23f7c97470e09a2316513ddf2efdfb670Andreas Gampe } 867598c25e23f7c97470e09a2316513ddf2efdfb670Andreas Gampe 8681705fc44fb85c4232637f9f7189c3bdca98a63d5Brian Carlstrom ALOGV("Running %s in=%s out=%s\n", DEX2OAT_BIN, input_file_name, output_file_name); 8694fdff4616699708e58d875273c3c1a85ba4c63bdCalin Juravle 87014e084d39ac44e9d4d0a0143bf1f111011343d34neo.chae const char* argv[7 // program name, mandatory arguments and the final NULL 87114e084d39ac44e9d4d0a0143bf1f111011343d34neo.chae + (have_dex2oat_isa_variant ? 1 : 0) 87214e084d39ac44e9d4d0a0143bf1f111011343d34neo.chae + (have_dex2oat_isa_features ? 1 : 0) 87314e084d39ac44e9d4d0a0143bf1f111011343d34neo.chae + (have_dex2oat_Xms_flag ? 2 : 0) 87414e084d39ac44e9d4d0a0143bf1f111011343d34neo.chae + (have_dex2oat_Xmx_flag ? 2 : 0) 87514e084d39ac44e9d4d0a0143bf1f111011343d34neo.chae + (have_dex2oat_compiler_filter_flag ? 1 : 0) 8768d7af8b2418cc5e7e59746f0cb359a75ed0bdfd1Andreas Gampe + (have_dex2oat_threads_flag ? 1 : 0) 87714e084d39ac44e9d4d0a0143bf1f111011343d34neo.chae + (have_dex2oat_swap_fd ? 1 : 0) 87814e084d39ac44e9d4d0a0143bf1f111011343d34neo.chae + (have_dex2oat_relocation_skip_flag ? 2 : 0) 879528c8ddc60df7b3d291b389117e4db878a20ad48David Srbecky + (generate_debug_info ? 1 : 0) 880598c25e23f7c97470e09a2316513ddf2efdfb670Andreas Gampe + (debuggable ? 1 : 0) 88114e084d39ac44e9d4d0a0143bf1f111011343d34neo.chae + dex2oat_flags_count]; 8824fdff4616699708e58d875273c3c1a85ba4c63bdCalin Juravle int i = 0; 88314e084d39ac44e9d4d0a0143bf1f111011343d34neo.chae argv[i++] = DEX2OAT_BIN; 8844fdff4616699708e58d875273c3c1a85ba4c63bdCalin Juravle argv[i++] = zip_fd_arg; 8854fdff4616699708e58d875273c3c1a85ba4c63bdCalin Juravle argv[i++] = zip_location_arg; 8864fdff4616699708e58d875273c3c1a85ba4c63bdCalin Juravle argv[i++] = oat_fd_arg; 8874fdff4616699708e58d875273c3c1a85ba4c63bdCalin Juravle argv[i++] = oat_location_arg; 8884fdff4616699708e58d875273c3c1a85ba4c63bdCalin Juravle argv[i++] = instruction_set_arg; 88916a95b267ac6aac75453f65f1bc382ce65c0741eIan Rogers if (have_dex2oat_isa_variant) { 89016a95b267ac6aac75453f65f1bc382ce65c0741eIan Rogers argv[i++] = instruction_set_variant_arg; 89116a95b267ac6aac75453f65f1bc382ce65c0741eIan Rogers } 8928fc7315a67fdbf9b56cc6fa061f0773be2223a81Calin Juravle if (have_dex2oat_isa_features) { 8938fc7315a67fdbf9b56cc6fa061f0773be2223a81Calin Juravle argv[i++] = instruction_set_features_arg; 8948fc7315a67fdbf9b56cc6fa061f0773be2223a81Calin Juravle } 895e46a75a0f6007967cd0d161959af844772cdc330Brian Carlstrom if (have_dex2oat_Xms_flag) { 89614e084d39ac44e9d4d0a0143bf1f111011343d34neo.chae argv[i++] = RUNTIME_ARG; 897e46a75a0f6007967cd0d161959af844772cdc330Brian Carlstrom argv[i++] = dex2oat_Xms_arg; 898e46a75a0f6007967cd0d161959af844772cdc330Brian Carlstrom } 899e46a75a0f6007967cd0d161959af844772cdc330Brian Carlstrom if (have_dex2oat_Xmx_flag) { 90014e084d39ac44e9d4d0a0143bf1f111011343d34neo.chae argv[i++] = RUNTIME_ARG; 901e46a75a0f6007967cd0d161959af844772cdc330Brian Carlstrom argv[i++] = dex2oat_Xmx_arg; 902e46a75a0f6007967cd0d161959af844772cdc330Brian Carlstrom } 903cf51ba1360ee13459830a0502b0d454d0145544fBrian Carlstrom if (have_dex2oat_compiler_filter_flag) { 904cf51ba1360ee13459830a0502b0d454d0145544fBrian Carlstrom argv[i++] = dex2oat_compiler_filter_arg; 905cf51ba1360ee13459830a0502b0d454d0145544fBrian Carlstrom } 9068d7af8b2418cc5e7e59746f0cb359a75ed0bdfd1Andreas Gampe if (have_dex2oat_threads_flag) { 9078d7af8b2418cc5e7e59746f0cb359a75ed0bdfd1Andreas Gampe argv[i++] = dex2oat_threads_arg; 9088d7af8b2418cc5e7e59746f0cb359a75ed0bdfd1Andreas Gampe } 909e1c01353c4dc6058a384eea9853238d2a87040dbAndreas Gampe if (have_dex2oat_swap_fd) { 910e1c01353c4dc6058a384eea9853238d2a87040dbAndreas Gampe argv[i++] = dex2oat_swap_fd; 911e1c01353c4dc6058a384eea9853238d2a87040dbAndreas Gampe } 912528c8ddc60df7b3d291b389117e4db878a20ad48David Srbecky if (generate_debug_info) { 913528c8ddc60df7b3d291b389117e4db878a20ad48David Srbecky argv[i++] = "--generate-debug-info"; 9143822b8b79cf533ee8573794176838406c32a1c20Andreas Gampe } 915598c25e23f7c97470e09a2316513ddf2efdfb670Andreas Gampe if (debuggable) { 916598c25e23f7c97470e09a2316513ddf2efdfb670Andreas Gampe argv[i++] = "--debuggable"; 917598c25e23f7c97470e09a2316513ddf2efdfb670Andreas Gampe } 918b0d8d00b2916aef7b01ad42f6d441f5b46b7731aYevgeny Rouban if (dex2oat_flags_count) { 919b0d8d00b2916aef7b01ad42f6d441f5b46b7731aYevgeny Rouban i += split(dex2oat_flags, argv + i); 9204fdff4616699708e58d875273c3c1a85ba4c63bdCalin Juravle } 92114e084d39ac44e9d4d0a0143bf1f111011343d34neo.chae if (have_dex2oat_relocation_skip_flag) { 92214e084d39ac44e9d4d0a0143bf1f111011343d34neo.chae argv[i++] = RUNTIME_ARG; 92314e084d39ac44e9d4d0a0143bf1f111011343d34neo.chae argv[i++] = dex2oat_norelocation; 92414e084d39ac44e9d4d0a0143bf1f111011343d34neo.chae } 925e46a75a0f6007967cd0d161959af844772cdc330Brian Carlstrom // Do not add after dex2oat_flags, they should override others for debugging. 9264fdff4616699708e58d875273c3c1a85ba4c63bdCalin Juravle argv[i] = NULL; 9274fdff4616699708e58d875273c3c1a85ba4c63bdCalin Juravle 92814e084d39ac44e9d4d0a0143bf1f111011343d34neo.chae execv(DEX2OAT_BIN, (char * const *)argv); 929b0d8d00b2916aef7b01ad42f6d441f5b46b7731aYevgeny Rouban ALOGE("execv(%s) failed: %s\n", DEX2OAT_BIN, strerror(errno)); 9301705fc44fb85c4232637f9f7189c3bdca98a63d5Brian Carlstrom} 9311705fc44fb85c4232637f9f7189c3bdca98a63d5Brian Carlstrom 93263568b1430d741f40ca008391c854ef1cc880138MÃ¥rten Kongstadstatic int wait_child(pid_t pid) 93394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood{ 93494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood int status; 93594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood pid_t got_pid; 93694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood 93794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood while (1) { 93894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood got_pid = waitpid(pid, &status, 0); 93994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood if (got_pid == -1 && errno == EINTR) { 94094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood printf("waitpid interrupted, retrying\n"); 94194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood } else { 94294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood break; 94394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood } 94494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood } 94594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood if (got_pid != pid) { 94694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood ALOGW("waitpid failed: wanted %d, got %d: %s\n", 94794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood (int) pid, (int) got_pid, strerror(errno)); 94894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood return 1; 94994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood } 95094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood 95194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood if (WIFEXITED(status) && WEXITSTATUS(status) == 0) { 95294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood return 0; 95394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood } else { 95494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood return status; /* always nonzero */ 95594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood } 95694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood} 95794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood 958e1c01353c4dc6058a384eea9853238d2a87040dbAndreas Gampe/* 959c968c0175e967e39e72f557b5e014b9575ba4727Andreas Gampe * Whether dexopt should use a swap file when compiling an APK. 960c968c0175e967e39e72f557b5e014b9575ba4727Andreas Gampe * 961c968c0175e967e39e72f557b5e014b9575ba4727Andreas Gampe * If kAlwaysProvideSwapFile, do this on all devices (dex2oat will make a more informed decision 962c968c0175e967e39e72f557b5e014b9575ba4727Andreas Gampe * itself, anyways). 963c968c0175e967e39e72f557b5e014b9575ba4727Andreas Gampe * 964c968c0175e967e39e72f557b5e014b9575ba4727Andreas Gampe * Otherwise, read "dalvik.vm.dex2oat-swap". If the property exists, return whether it is "true". 965c968c0175e967e39e72f557b5e014b9575ba4727Andreas Gampe * 966c968c0175e967e39e72f557b5e014b9575ba4727Andreas Gampe * Otherwise, return true if this is a low-mem device. 967c968c0175e967e39e72f557b5e014b9575ba4727Andreas Gampe * 968c968c0175e967e39e72f557b5e014b9575ba4727Andreas Gampe * Otherwise, return default value. 969e1c01353c4dc6058a384eea9853238d2a87040dbAndreas Gampe */ 970c968c0175e967e39e72f557b5e014b9575ba4727Andreas Gampestatic bool kAlwaysProvideSwapFile = false; 971c968c0175e967e39e72f557b5e014b9575ba4727Andreas Gampestatic bool kDefaultProvideSwapFile = true; 972e1c01353c4dc6058a384eea9853238d2a87040dbAndreas Gampe 973e1c01353c4dc6058a384eea9853238d2a87040dbAndreas Gampestatic bool ShouldUseSwapFileForDexopt() { 974e1c01353c4dc6058a384eea9853238d2a87040dbAndreas Gampe if (kAlwaysProvideSwapFile) { 975e1c01353c4dc6058a384eea9853238d2a87040dbAndreas Gampe return true; 976e1c01353c4dc6058a384eea9853238d2a87040dbAndreas Gampe } 977e1c01353c4dc6058a384eea9853238d2a87040dbAndreas Gampe 978c968c0175e967e39e72f557b5e014b9575ba4727Andreas Gampe // Check the "override" property. If it exists, return value == "true". 979c968c0175e967e39e72f557b5e014b9575ba4727Andreas Gampe char dex2oat_prop_buf[PROPERTY_VALUE_MAX]; 980c968c0175e967e39e72f557b5e014b9575ba4727Andreas Gampe if (property_get("dalvik.vm.dex2oat-swap", dex2oat_prop_buf, "") > 0) { 981c968c0175e967e39e72f557b5e014b9575ba4727Andreas Gampe if (strcmp(dex2oat_prop_buf, "true") == 0) { 982c968c0175e967e39e72f557b5e014b9575ba4727Andreas Gampe return true; 983c968c0175e967e39e72f557b5e014b9575ba4727Andreas Gampe } else { 984c968c0175e967e39e72f557b5e014b9575ba4727Andreas Gampe return false; 985c968c0175e967e39e72f557b5e014b9575ba4727Andreas Gampe } 986c968c0175e967e39e72f557b5e014b9575ba4727Andreas Gampe } 987c968c0175e967e39e72f557b5e014b9575ba4727Andreas Gampe 988c968c0175e967e39e72f557b5e014b9575ba4727Andreas Gampe // Shortcut for default value. This is an implementation optimization for the process sketched 989c968c0175e967e39e72f557b5e014b9575ba4727Andreas Gampe // above. If the default value is true, we can avoid to check whether this is a low-mem device, 990c968c0175e967e39e72f557b5e014b9575ba4727Andreas Gampe // as low-mem is never returning false. The compiler will optimize this away if it can. 991c968c0175e967e39e72f557b5e014b9575ba4727Andreas Gampe if (kDefaultProvideSwapFile) { 992c968c0175e967e39e72f557b5e014b9575ba4727Andreas Gampe return true; 993c968c0175e967e39e72f557b5e014b9575ba4727Andreas Gampe } 994c968c0175e967e39e72f557b5e014b9575ba4727Andreas Gampe 995c968c0175e967e39e72f557b5e014b9575ba4727Andreas Gampe bool is_low_mem = check_boolean_property("ro.config.low_ram"); 996c968c0175e967e39e72f557b5e014b9575ba4727Andreas Gampe if (is_low_mem) { 997c968c0175e967e39e72f557b5e014b9575ba4727Andreas Gampe return true; 998c968c0175e967e39e72f557b5e014b9575ba4727Andreas Gampe } 999c968c0175e967e39e72f557b5e014b9575ba4727Andreas Gampe 1000c968c0175e967e39e72f557b5e014b9575ba4727Andreas Gampe // Default value must be false here. 1001c968c0175e967e39e72f557b5e014b9575ba4727Andreas Gampe return kDefaultProvideSwapFile; 1002e1c01353c4dc6058a384eea9853238d2a87040dbAndreas Gampe} 1003e1c01353c4dc6058a384eea9853238d2a87040dbAndreas Gampe 1004009b8771323ce69658c1ac0254c3259186107fb6Richard Uhler/* 1005009b8771323ce69658c1ac0254c3259186107fb6Richard Uhler * Computes the odex file for the given apk_path and instruction_set. 1006009b8771323ce69658c1ac0254c3259186107fb6Richard Uhler * /system/framework/whatever.jar -> /system/framework/oat/<isa>/whatever.odex 1007009b8771323ce69658c1ac0254c3259186107fb6Richard Uhler * 1008009b8771323ce69658c1ac0254c3259186107fb6Richard Uhler * Returns false if it failed to determine the odex file path. 1009009b8771323ce69658c1ac0254c3259186107fb6Richard Uhler */ 1010009b8771323ce69658c1ac0254c3259186107fb6Richard Uhlerstatic bool calculate_odex_file_path(char path[PKG_PATH_MAX], 1011009b8771323ce69658c1ac0254c3259186107fb6Richard Uhler const char *apk_path, 1012009b8771323ce69658c1ac0254c3259186107fb6Richard Uhler const char *instruction_set) 1013009b8771323ce69658c1ac0254c3259186107fb6Richard Uhler{ 1014009b8771323ce69658c1ac0254c3259186107fb6Richard Uhler if (strlen(apk_path) + strlen("oat/") + strlen(instruction_set) 1015009b8771323ce69658c1ac0254c3259186107fb6Richard Uhler + strlen("/") + strlen("odex") + 1 > PKG_PATH_MAX) { 1016009b8771323ce69658c1ac0254c3259186107fb6Richard Uhler ALOGE("apk_path '%s' may be too long to form odex file path.\n", apk_path); 1017009b8771323ce69658c1ac0254c3259186107fb6Richard Uhler return false; 1018009b8771323ce69658c1ac0254c3259186107fb6Richard Uhler } 1019009b8771323ce69658c1ac0254c3259186107fb6Richard Uhler 1020009b8771323ce69658c1ac0254c3259186107fb6Richard Uhler strcpy(path, apk_path); 1021009b8771323ce69658c1ac0254c3259186107fb6Richard Uhler char *end = strrchr(path, '/'); 1022009b8771323ce69658c1ac0254c3259186107fb6Richard Uhler if (end == NULL) { 1023009b8771323ce69658c1ac0254c3259186107fb6Richard Uhler ALOGE("apk_path '%s' has no '/'s in it?!\n", apk_path); 1024009b8771323ce69658c1ac0254c3259186107fb6Richard Uhler return false; 1025009b8771323ce69658c1ac0254c3259186107fb6Richard Uhler } 1026009b8771323ce69658c1ac0254c3259186107fb6Richard Uhler const char *apk_end = apk_path + (end - path); // strrchr(apk_path, '/'); 1027009b8771323ce69658c1ac0254c3259186107fb6Richard Uhler 1028009b8771323ce69658c1ac0254c3259186107fb6Richard Uhler strcpy(end + 1, "oat/"); // path = /system/framework/oat/\0 1029009b8771323ce69658c1ac0254c3259186107fb6Richard Uhler strcat(path, instruction_set); // path = /system/framework/oat/<isa>\0 1030009b8771323ce69658c1ac0254c3259186107fb6Richard Uhler strcat(path, apk_end); // path = /system/framework/oat/<isa>/whatever.jar\0 1031009b8771323ce69658c1ac0254c3259186107fb6Richard Uhler end = strrchr(path, '.'); 1032009b8771323ce69658c1ac0254c3259186107fb6Richard Uhler if (end == NULL) { 1033009b8771323ce69658c1ac0254c3259186107fb6Richard Uhler ALOGE("apk_path '%s' has no extension.\n", apk_path); 1034009b8771323ce69658c1ac0254c3259186107fb6Richard Uhler return false; 1035009b8771323ce69658c1ac0254c3259186107fb6Richard Uhler } 1036009b8771323ce69658c1ac0254c3259186107fb6Richard Uhler strcpy(end + 1, "odex"); 1037009b8771323ce69658c1ac0254c3259186107fb6Richard Uhler return true; 1038009b8771323ce69658c1ac0254c3259186107fb6Richard Uhler} 1039009b8771323ce69658c1ac0254c3259186107fb6Richard Uhler 104094dd3d3c5be4de57278ee668218a3464585795c0Andreas Gampestatic void SetDex2OatAndPatchOatScheduling(bool set_to_bg) { 104194dd3d3c5be4de57278ee668218a3464585795c0Andreas Gampe if (set_to_bg) { 104294dd3d3c5be4de57278ee668218a3464585795c0Andreas Gampe if (set_sched_policy(0, SP_BACKGROUND) < 0) { 104394dd3d3c5be4de57278ee668218a3464585795c0Andreas Gampe ALOGE("set_sched_policy failed: %s\n", strerror(errno)); 104494dd3d3c5be4de57278ee668218a3464585795c0Andreas Gampe exit(70); 104594dd3d3c5be4de57278ee668218a3464585795c0Andreas Gampe } 104694dd3d3c5be4de57278ee668218a3464585795c0Andreas Gampe if (setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_BACKGROUND) < 0) { 104794dd3d3c5be4de57278ee668218a3464585795c0Andreas Gampe ALOGE("setpriority failed: %s\n", strerror(errno)); 104894dd3d3c5be4de57278ee668218a3464585795c0Andreas Gampe exit(71); 104994dd3d3c5be4de57278ee668218a3464585795c0Andreas Gampe } 105094dd3d3c5be4de57278ee668218a3464585795c0Andreas Gampe } 105194dd3d3c5be4de57278ee668218a3464585795c0Andreas Gampe} 105294dd3d3c5be4de57278ee668218a3464585795c0Andreas Gampe 105376e767ca14bcbb4bc809cd1279ece82a3aabe8a4Todd Kennedyint dexopt(const char *apk_path, uid_t uid, const char *pkgname, const char *instruction_set, 105476e767ca14bcbb4bc809cd1279ece82a3aabe8a4Todd Kennedy int dexopt_needed, const char* oat_dir, int dexopt_flags) 105594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood{ 105694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood struct utimbuf ut; 105726ff93c1a783d02c177a47f0a80249070fe43682Fyodor Kupolov struct stat input_stat; 10581705fc44fb85c4232637f9f7189c3bdca98a63d5Brian Carlstrom char out_path[PKG_PATH_MAX]; 1059e1c01353c4dc6058a384eea9853238d2a87040dbAndreas Gampe char swap_file_name[PKG_PATH_MAX]; 10607365a10689df23334d245b211ce272502ad20669Alex Light const char *input_file; 10617365a10689df23334d245b211ce272502ad20669Alex Light char in_odex_path[PKG_PATH_MAX]; 1062e1c01353c4dc6058a384eea9853238d2a87040dbAndreas Gampe int res, input_fd=-1, out_fd=-1, swap_fd=-1; 106376e767ca14bcbb4bc809cd1279ece82a3aabe8a4Todd Kennedy bool is_public = (dexopt_flags & DEXOPT_PUBLIC) != 0; 106476e767ca14bcbb4bc809cd1279ece82a3aabe8a4Todd Kennedy bool vm_safe_mode = (dexopt_flags & DEXOPT_SAFEMODE) != 0; 106576e767ca14bcbb4bc809cd1279ece82a3aabe8a4Todd Kennedy bool debuggable = (dexopt_flags & DEXOPT_DEBUGGABLE) != 0; 106676e767ca14bcbb4bc809cd1279ece82a3aabe8a4Todd Kennedy bool boot_complete = (dexopt_flags & DEXOPT_BOOTCOMPLETE) != 0; 106712434f8cce66a753ef49c07b503f9625e01366c8Todd Kennedy bool use_jit = (dexopt_flags & DEXOPT_USEJIT) != 0; 106876e767ca14bcbb4bc809cd1279ece82a3aabe8a4Todd Kennedy 1069e296e00df65461629a20cd03b5b041a59935d00fTodd Kennedy if ((dexopt_flags & ~DEXOPT_MASK) != 0) { 107076e767ca14bcbb4bc809cd1279ece82a3aabe8a4Todd Kennedy LOG_FATAL("dexopt flags contains unknown fields\n"); 107176e767ca14bcbb4bc809cd1279ece82a3aabe8a4Todd Kennedy } 107294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood 1073e1c01353c4dc6058a384eea9853238d2a87040dbAndreas Gampe // Early best-effort check whether we can fit the the path into our buffers. 1074e1c01353c4dc6058a384eea9853238d2a87040dbAndreas Gampe // Note: the cache path will require an additional 5 bytes for ".swap", but we'll try to run 1075e1c01353c4dc6058a384eea9853238d2a87040dbAndreas Gampe // without a swap file, if necessary. 107694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood if (strlen(apk_path) >= (PKG_PATH_MAX - 8)) { 107788ce4ff7a95ea2008fa28f12b880ee526e331440Fyodor Kupolov ALOGE("apk_path too long '%s'\n", apk_path); 107894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood return -1; 107994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood } 108094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood 108188ce4ff7a95ea2008fa28f12b880ee526e331440Fyodor Kupolov if (oat_dir != NULL && oat_dir[0] != '!') { 108288ce4ff7a95ea2008fa28f12b880ee526e331440Fyodor Kupolov if (validate_apk_path(oat_dir)) { 108388ce4ff7a95ea2008fa28f12b880ee526e331440Fyodor Kupolov ALOGE("invalid oat_dir '%s'\n", oat_dir); 108488ce4ff7a95ea2008fa28f12b880ee526e331440Fyodor Kupolov return -1; 108588ce4ff7a95ea2008fa28f12b880ee526e331440Fyodor Kupolov } 108688ce4ff7a95ea2008fa28f12b880ee526e331440Fyodor Kupolov if (calculate_oat_file_path(out_path, oat_dir, apk_path, instruction_set)) { 108788ce4ff7a95ea2008fa28f12b880ee526e331440Fyodor Kupolov return -1; 108888ce4ff7a95ea2008fa28f12b880ee526e331440Fyodor Kupolov } 108988ce4ff7a95ea2008fa28f12b880ee526e331440Fyodor Kupolov } else { 109088ce4ff7a95ea2008fa28f12b880ee526e331440Fyodor Kupolov if (create_cache_path(out_path, apk_path, instruction_set)) { 109188ce4ff7a95ea2008fa28f12b880ee526e331440Fyodor Kupolov return -1; 10920e8ae16f084e3d4772ea6dd33a9b72925d7b40d5Chih-Wei Huang } 109394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood } 109494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood 1095c92fb6247d4c4fbc34c0a5deb26ccf538ca9ec81Richard Uhler switch (dexopt_needed) { 1096c92fb6247d4c4fbc34c0a5deb26ccf538ca9ec81Richard Uhler case DEXOPT_DEX2OAT_NEEDED: 1097c92fb6247d4c4fbc34c0a5deb26ccf538ca9ec81Richard Uhler input_file = apk_path; 1098c92fb6247d4c4fbc34c0a5deb26ccf538ca9ec81Richard Uhler break; 1099c92fb6247d4c4fbc34c0a5deb26ccf538ca9ec81Richard Uhler 1100c92fb6247d4c4fbc34c0a5deb26ccf538ca9ec81Richard Uhler case DEXOPT_PATCHOAT_NEEDED: 1101c92fb6247d4c4fbc34c0a5deb26ccf538ca9ec81Richard Uhler if (!calculate_odex_file_path(in_odex_path, apk_path, instruction_set)) { 1102c92fb6247d4c4fbc34c0a5deb26ccf538ca9ec81Richard Uhler return -1; 1103c92fb6247d4c4fbc34c0a5deb26ccf538ca9ec81Richard Uhler } 1104c92fb6247d4c4fbc34c0a5deb26ccf538ca9ec81Richard Uhler input_file = in_odex_path; 1105c92fb6247d4c4fbc34c0a5deb26ccf538ca9ec81Richard Uhler break; 1106c92fb6247d4c4fbc34c0a5deb26ccf538ca9ec81Richard Uhler 1107c92fb6247d4c4fbc34c0a5deb26ccf538ca9ec81Richard Uhler case DEXOPT_SELF_PATCHOAT_NEEDED: 1108c92fb6247d4c4fbc34c0a5deb26ccf538ca9ec81Richard Uhler input_file = out_path; 1109c92fb6247d4c4fbc34c0a5deb26ccf538ca9ec81Richard Uhler break; 1110c92fb6247d4c4fbc34c0a5deb26ccf538ca9ec81Richard Uhler 1111c92fb6247d4c4fbc34c0a5deb26ccf538ca9ec81Richard Uhler default: 1112c92fb6247d4c4fbc34c0a5deb26ccf538ca9ec81Richard Uhler ALOGE("Invalid dexopt needed: %d\n", dexopt_needed); 1113c92fb6247d4c4fbc34c0a5deb26ccf538ca9ec81Richard Uhler exit(72); 11147365a10689df23334d245b211ce272502ad20669Alex Light } 11157365a10689df23334d245b211ce272502ad20669Alex Light 11167365a10689df23334d245b211ce272502ad20669Alex Light memset(&input_stat, 0, sizeof(input_stat)); 11177365a10689df23334d245b211ce272502ad20669Alex Light stat(input_file, &input_stat); 111894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood 11197365a10689df23334d245b211ce272502ad20669Alex Light input_fd = open(input_file, O_RDONLY, 0); 11207365a10689df23334d245b211ce272502ad20669Alex Light if (input_fd < 0) { 11217365a10689df23334d245b211ce272502ad20669Alex Light ALOGE("installd cannot open '%s' for input during dexopt\n", input_file); 112294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood return -1; 112394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood } 112494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood 11251705fc44fb85c4232637f9f7189c3bdca98a63d5Brian Carlstrom unlink(out_path); 11261705fc44fb85c4232637f9f7189c3bdca98a63d5Brian Carlstrom out_fd = open(out_path, O_RDWR | O_CREAT | O_EXCL, 0644); 11271705fc44fb85c4232637f9f7189c3bdca98a63d5Brian Carlstrom if (out_fd < 0) { 11281705fc44fb85c4232637f9f7189c3bdca98a63d5Brian Carlstrom ALOGE("installd cannot open '%s' for output during dexopt\n", out_path); 112994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood goto fail; 113094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood } 11311705fc44fb85c4232637f9f7189c3bdca98a63d5Brian Carlstrom if (fchmod(out_fd, 113294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood S_IRUSR|S_IWUSR|S_IRGRP | 113394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood (is_public ? S_IROTH : 0)) < 0) { 11341705fc44fb85c4232637f9f7189c3bdca98a63d5Brian Carlstrom ALOGE("installd cannot chmod '%s' during dexopt\n", out_path); 113594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood goto fail; 113694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood } 11371705fc44fb85c4232637f9f7189c3bdca98a63d5Brian Carlstrom if (fchown(out_fd, AID_SYSTEM, uid) < 0) { 11381705fc44fb85c4232637f9f7189c3bdca98a63d5Brian Carlstrom ALOGE("installd cannot chown '%s' during dexopt\n", out_path); 113994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood goto fail; 114094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood } 114194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood 1142e1c01353c4dc6058a384eea9853238d2a87040dbAndreas Gampe // Create a swap file if necessary. 1143c92fb6247d4c4fbc34c0a5deb26ccf538ca9ec81Richard Uhler if (ShouldUseSwapFileForDexopt()) { 1144e1c01353c4dc6058a384eea9853238d2a87040dbAndreas Gampe // Make sure there really is enough space. 1145e1c01353c4dc6058a384eea9853238d2a87040dbAndreas Gampe size_t out_len = strlen(out_path); 1146e1c01353c4dc6058a384eea9853238d2a87040dbAndreas Gampe if (out_len + strlen(".swap") + 1 <= PKG_PATH_MAX) { 1147e1c01353c4dc6058a384eea9853238d2a87040dbAndreas Gampe strcpy(swap_file_name, out_path); 1148e1c01353c4dc6058a384eea9853238d2a87040dbAndreas Gampe strcpy(swap_file_name + strlen(out_path), ".swap"); 1149e1c01353c4dc6058a384eea9853238d2a87040dbAndreas Gampe unlink(swap_file_name); 1150e1c01353c4dc6058a384eea9853238d2a87040dbAndreas Gampe swap_fd = open(swap_file_name, O_RDWR | O_CREAT | O_EXCL, 0600); 1151e1c01353c4dc6058a384eea9853238d2a87040dbAndreas Gampe if (swap_fd < 0) { 1152e1c01353c4dc6058a384eea9853238d2a87040dbAndreas Gampe // Could not create swap file. Optimistically go on and hope that we can compile 1153e1c01353c4dc6058a384eea9853238d2a87040dbAndreas Gampe // without it. 1154e1c01353c4dc6058a384eea9853238d2a87040dbAndreas Gampe ALOGE("installd could not create '%s' for swap during dexopt\n", swap_file_name); 1155e1c01353c4dc6058a384eea9853238d2a87040dbAndreas Gampe } else { 1156e1c01353c4dc6058a384eea9853238d2a87040dbAndreas Gampe // Immediately unlink. We don't really want to hit flash. 1157e1c01353c4dc6058a384eea9853238d2a87040dbAndreas Gampe unlink(swap_file_name); 1158e1c01353c4dc6058a384eea9853238d2a87040dbAndreas Gampe } 1159e1c01353c4dc6058a384eea9853238d2a87040dbAndreas Gampe } else { 1160e1c01353c4dc6058a384eea9853238d2a87040dbAndreas Gampe // Swap file path is too long. Try to run without. 1161e1c01353c4dc6058a384eea9853238d2a87040dbAndreas Gampe ALOGE("installd could not create swap file for path %s during dexopt\n", out_path); 1162e1c01353c4dc6058a384eea9853238d2a87040dbAndreas Gampe } 1163e1c01353c4dc6058a384eea9853238d2a87040dbAndreas Gampe } 1164d93707342a61e66bc3eb2145628158452f577f42Dave Allison 11657365a10689df23334d245b211ce272502ad20669Alex Light ALOGV("DexInv: --- BEGIN '%s' ---\n", input_file); 116694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood 116794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood pid_t pid; 116894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood pid = fork(); 116994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood if (pid == 0) { 117094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood /* child -- drop privileges before continuing */ 117194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood if (setgid(uid) != 0) { 11721705fc44fb85c4232637f9f7189c3bdca98a63d5Brian Carlstrom ALOGE("setgid(%d) failed in installd during dexopt\n", uid); 117394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood exit(64); 117494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood } 117594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood if (setuid(uid) != 0) { 11761705fc44fb85c4232637f9f7189c3bdca98a63d5Brian Carlstrom ALOGE("setuid(%d) failed in installd during dexopt\n", uid); 117794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood exit(65); 117894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood } 117994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood // drop capabilities 118094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood struct __user_cap_header_struct capheader; 118194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood struct __user_cap_data_struct capdata[2]; 118294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood memset(&capheader, 0, sizeof(capheader)); 118394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood memset(&capdata, 0, sizeof(capdata)); 118494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood capheader.version = _LINUX_CAPABILITY_VERSION_3; 118594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood if (capset(&capheader, &capdata[0]) < 0) { 118694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood ALOGE("capset failed: %s\n", strerror(errno)); 118794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood exit(66); 118894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood } 118913f141910ba383404145924df64ad6626fe5b42fAndreas Gampe SetDex2OatAndPatchOatScheduling(boot_complete); 11901705fc44fb85c4232637f9f7189c3bdca98a63d5Brian Carlstrom if (flock(out_fd, LOCK_EX | LOCK_NB) != 0) { 11911705fc44fb85c4232637f9f7189c3bdca98a63d5Brian Carlstrom ALOGE("flock(%s) failed: %s\n", out_path, strerror(errno)); 119294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood exit(67); 119394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood } 119494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood 1195c92fb6247d4c4fbc34c0a5deb26ccf538ca9ec81Richard Uhler if (dexopt_needed == DEXOPT_PATCHOAT_NEEDED 1196c92fb6247d4c4fbc34c0a5deb26ccf538ca9ec81Richard Uhler || dexopt_needed == DEXOPT_SELF_PATCHOAT_NEEDED) { 1197bd872e49561282682793ab526616d609f7fbb274Andreas Gampe run_patchoat(input_fd, out_fd, input_file, out_path, pkgname, instruction_set); 1198c92fb6247d4c4fbc34c0a5deb26ccf538ca9ec81Richard Uhler } else if (dexopt_needed == DEXOPT_DEX2OAT_NEEDED) { 119988ce4ff7a95ea2008fa28f12b880ee526e331440Fyodor Kupolov const char *input_file_name = strrchr(input_file, '/'); 120088ce4ff7a95ea2008fa28f12b880ee526e331440Fyodor Kupolov if (input_file_name == NULL) { 120188ce4ff7a95ea2008fa28f12b880ee526e331440Fyodor Kupolov input_file_name = input_file; 120288ce4ff7a95ea2008fa28f12b880ee526e331440Fyodor Kupolov } else { 120388ce4ff7a95ea2008fa28f12b880ee526e331440Fyodor Kupolov input_file_name++; 120488ce4ff7a95ea2008fa28f12b880ee526e331440Fyodor Kupolov } 1205df9dadd5e5c287110d837c38aaec12bcf5e5d151Calin Juravle run_dex2oat(input_fd, out_fd, input_file_name, out_path, swap_fd, 120612434f8cce66a753ef49c07b503f9625e01366c8Todd Kennedy instruction_set, vm_safe_mode, debuggable, boot_complete, use_jit); 1207c92fb6247d4c4fbc34c0a5deb26ccf538ca9ec81Richard Uhler } else { 1208c92fb6247d4c4fbc34c0a5deb26ccf538ca9ec81Richard Uhler ALOGE("Invalid dexopt needed: %d\n", dexopt_needed); 1209c92fb6247d4c4fbc34c0a5deb26ccf538ca9ec81Richard Uhler exit(73); 12101705fc44fb85c4232637f9f7189c3bdca98a63d5Brian Carlstrom } 121194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood exit(68); /* only get here on exec failure */ 121294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood } else { 121363568b1430d741f40ca008391c854ef1cc880138MÃ¥rten Kongstad res = wait_child(pid); 121463568b1430d741f40ca008391c854ef1cc880138MÃ¥rten Kongstad if (res == 0) { 12157365a10689df23334d245b211ce272502ad20669Alex Light ALOGV("DexInv: --- END '%s' (success) ---\n", input_file); 121663568b1430d741f40ca008391c854ef1cc880138MÃ¥rten Kongstad } else { 12177365a10689df23334d245b211ce272502ad20669Alex Light ALOGE("DexInv: --- END '%s' --- status=0x%04x, process failed\n", input_file, res); 121894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood goto fail; 121994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood } 122094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood } 122194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood 12227365a10689df23334d245b211ce272502ad20669Alex Light ut.actime = input_stat.st_atime; 12237365a10689df23334d245b211ce272502ad20669Alex Light ut.modtime = input_stat.st_mtime; 12241705fc44fb85c4232637f9f7189c3bdca98a63d5Brian Carlstrom utime(out_path, &ut); 12251705fc44fb85c4232637f9f7189c3bdca98a63d5Brian Carlstrom 12261705fc44fb85c4232637f9f7189c3bdca98a63d5Brian Carlstrom close(out_fd); 12277365a10689df23334d245b211ce272502ad20669Alex Light close(input_fd); 1228e1c01353c4dc6058a384eea9853238d2a87040dbAndreas Gampe if (swap_fd != -1) { 1229e1c01353c4dc6058a384eea9853238d2a87040dbAndreas Gampe close(swap_fd); 1230e1c01353c4dc6058a384eea9853238d2a87040dbAndreas Gampe } 123194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood return 0; 123294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood 123394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwoodfail: 12341705fc44fb85c4232637f9f7189c3bdca98a63d5Brian Carlstrom if (out_fd >= 0) { 12351705fc44fb85c4232637f9f7189c3bdca98a63d5Brian Carlstrom close(out_fd); 12361705fc44fb85c4232637f9f7189c3bdca98a63d5Brian Carlstrom unlink(out_path); 123794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood } 12387365a10689df23334d245b211ce272502ad20669Alex Light if (input_fd >= 0) { 12397365a10689df23334d245b211ce272502ad20669Alex Light close(input_fd); 124094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood } 124194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood return -1; 124294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood} 124394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood 1244091ea779d4e575856c04d51d82f45cc8a6155b5eNarayan Kamathint mark_boot_complete(const char* instruction_set) 1245091ea779d4e575856c04d51d82f45cc8a6155b5eNarayan Kamath{ 1246091ea779d4e575856c04d51d82f45cc8a6155b5eNarayan Kamath char boot_marker_path[PKG_PATH_MAX]; 1247091ea779d4e575856c04d51d82f45cc8a6155b5eNarayan Kamath sprintf(boot_marker_path,"%s%s/.booting", DALVIK_CACHE_PREFIX, instruction_set); 1248091ea779d4e575856c04d51d82f45cc8a6155b5eNarayan Kamath 1249091ea779d4e575856c04d51d82f45cc8a6155b5eNarayan Kamath ALOGV("mark_boot_complete : %s", boot_marker_path); 1250091ea779d4e575856c04d51d82f45cc8a6155b5eNarayan Kamath if (unlink(boot_marker_path) != 0) { 1251091ea779d4e575856c04d51d82f45cc8a6155b5eNarayan Kamath ALOGE("Unable to unlink boot marker at %s, error=%s", boot_marker_path, 1252091ea779d4e575856c04d51d82f45cc8a6155b5eNarayan Kamath strerror(errno)); 1253091ea779d4e575856c04d51d82f45cc8a6155b5eNarayan Kamath return -1; 1254091ea779d4e575856c04d51d82f45cc8a6155b5eNarayan Kamath } 1255091ea779d4e575856c04d51d82f45cc8a6155b5eNarayan Kamath 1256091ea779d4e575856c04d51d82f45cc8a6155b5eNarayan Kamath return 0; 1257091ea779d4e575856c04d51d82f45cc8a6155b5eNarayan Kamath} 1258091ea779d4e575856c04d51d82f45cc8a6155b5eNarayan Kamath 125994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwoodvoid mkinnerdirs(char* path, int basepos, mode_t mode, int uid, int gid, 126094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood struct stat* statbuf) 126194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood{ 126294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood while (path[basepos] != 0) { 126394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood if (path[basepos] == '/') { 126494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood path[basepos] = 0; 126594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood if (lstat(path, statbuf) < 0) { 126694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood ALOGV("Making directory: %s\n", path); 126794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood if (mkdir(path, mode) == 0) { 126894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood chown(path, uid, gid); 126994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood } else { 127094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood ALOGW("Unable to make directory %s: %s\n", path, strerror(errno)); 127194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood } 127294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood } 127394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood path[basepos] = '/'; 127494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood basepos++; 127594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood } 127694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood basepos++; 127794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood } 127894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood} 127994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood 128094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwoodint movefileordir(char* srcpath, char* dstpath, int dstbasepos, 128194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood int dstuid, int dstgid, struct stat* statbuf) 128294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood{ 128394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood DIR *d; 128494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood struct dirent *de; 128594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood int res; 128694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood 128794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood int srcend = strlen(srcpath); 128894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood int dstend = strlen(dstpath); 1289d93707342a61e66bc3eb2145628158452f577f42Dave Allison 129094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood if (lstat(srcpath, statbuf) < 0) { 129194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood ALOGW("Unable to stat %s: %s\n", srcpath, strerror(errno)); 129294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood return 1; 129394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood } 1294d93707342a61e66bc3eb2145628158452f577f42Dave Allison 129594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood if ((statbuf->st_mode&S_IFDIR) == 0) { 129694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood mkinnerdirs(dstpath, dstbasepos, S_IRWXU|S_IRWXG|S_IXOTH, 129794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood dstuid, dstgid, statbuf); 129894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood ALOGV("Renaming %s to %s (uid %d)\n", srcpath, dstpath, dstuid); 129994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood if (rename(srcpath, dstpath) >= 0) { 130094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood if (chown(dstpath, dstuid, dstgid) < 0) { 130194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood ALOGE("cannot chown %s: %s\n", dstpath, strerror(errno)); 130294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood unlink(dstpath); 130394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood return 1; 130494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood } 130594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood } else { 130694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood ALOGW("Unable to rename %s to %s: %s\n", 130794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood srcpath, dstpath, strerror(errno)); 130894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood return 1; 130994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood } 131094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood return 0; 131194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood } 131294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood 131394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood d = opendir(srcpath); 131494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood if (d == NULL) { 131594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood ALOGW("Unable to opendir %s: %s\n", srcpath, strerror(errno)); 131694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood return 1; 131794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood } 131894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood 131994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood res = 0; 1320d93707342a61e66bc3eb2145628158452f577f42Dave Allison 132194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood while ((de = readdir(d))) { 132294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood const char *name = de->d_name; 132394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood /* always skip "." and ".." */ 132494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood if (name[0] == '.') { 132594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood if (name[1] == 0) continue; 132694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood if ((name[1] == '.') && (name[2] == 0)) continue; 132794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood } 1328d93707342a61e66bc3eb2145628158452f577f42Dave Allison 132994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood if ((srcend+strlen(name)) >= (PKG_PATH_MAX-2)) { 133094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood ALOGW("Source path too long; skipping: %s/%s\n", srcpath, name); 133194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood continue; 133294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood } 1333d93707342a61e66bc3eb2145628158452f577f42Dave Allison 133494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood if ((dstend+strlen(name)) >= (PKG_PATH_MAX-2)) { 133594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood ALOGW("Destination path too long; skipping: %s/%s\n", dstpath, name); 133694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood continue; 133794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood } 1338d93707342a61e66bc3eb2145628158452f577f42Dave Allison 133994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood srcpath[srcend] = dstpath[dstend] = '/'; 134094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood strcpy(srcpath+srcend+1, name); 134194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood strcpy(dstpath+dstend+1, name); 1342d93707342a61e66bc3eb2145628158452f577f42Dave Allison 134394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood if (movefileordir(srcpath, dstpath, dstbasepos, dstuid, dstgid, statbuf) != 0) { 134494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood res = 1; 134594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood } 1346d93707342a61e66bc3eb2145628158452f577f42Dave Allison 134794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood // Note: we will be leaving empty directories behind in srcpath, 134894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood // but that is okay, the package manager will be erasing all of the 134994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood // data associated with .apks that disappear. 1350d93707342a61e66bc3eb2145628158452f577f42Dave Allison 135194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood srcpath[srcend] = dstpath[dstend] = 0; 135294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood } 1353d93707342a61e66bc3eb2145628158452f577f42Dave Allison 135494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood closedir(d); 135594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood return res; 135694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood} 135794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood 135894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwoodint movefiles() 135994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood{ 136094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood DIR *d; 136194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood int dfd, subfd; 136294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood struct dirent *de; 136394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood struct stat s; 136494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood char buf[PKG_PATH_MAX+1]; 136594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood int bufp, bufe, bufi, readlen; 136694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood 136794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood char srcpkg[PKG_NAME_MAX]; 136894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood char dstpkg[PKG_NAME_MAX]; 136994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood char srcpath[PKG_PATH_MAX]; 137094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood char dstpath[PKG_PATH_MAX]; 137194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood int dstuid=-1, dstgid=-1; 137294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood int hasspace; 137394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood 137494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood d = opendir(UPDATE_COMMANDS_DIR_PREFIX); 137594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood if (d == NULL) { 137694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood goto done; 137794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood } 137894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood dfd = dirfd(d); 137994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood 138094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood /* Iterate through all files in the directory, executing the 138194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood * file movements requested there-in. 138294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood */ 138394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood while ((de = readdir(d))) { 138494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood const char *name = de->d_name; 138594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood 138694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood if (de->d_type == DT_DIR) { 138794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood continue; 138894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood } else { 138994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood subfd = openat(dfd, name, O_RDONLY); 139094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood if (subfd < 0) { 139194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood ALOGW("Unable to open update commands at %s%s\n", 139294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood UPDATE_COMMANDS_DIR_PREFIX, name); 139394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood continue; 139494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood } 1395d93707342a61e66bc3eb2145628158452f577f42Dave Allison 139694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood bufp = 0; 139794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood bufe = 0; 139894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood buf[PKG_PATH_MAX] = 0; 139994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood srcpkg[0] = dstpkg[0] = 0; 140094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood while (1) { 140194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood bufi = bufp; 140294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood while (bufi < bufe && buf[bufi] != '\n') { 140394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood bufi++; 140494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood } 140594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood if (bufi < bufe) { 140694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood buf[bufi] = 0; 140794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood ALOGV("Processing line: %s\n", buf+bufp); 140894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood hasspace = 0; 140994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood while (bufp < bufi && isspace(buf[bufp])) { 141094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood hasspace = 1; 141194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood bufp++; 141294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood } 141394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood if (buf[bufp] == '#' || bufp == bufi) { 141494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood // skip comments and empty lines. 141594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood } else if (hasspace) { 141694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood if (dstpkg[0] == 0) { 141794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood ALOGW("Path before package line in %s%s: %s\n", 141894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood UPDATE_COMMANDS_DIR_PREFIX, name, buf+bufp); 141994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood } else if (srcpkg[0] == 0) { 142094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood // Skip -- source package no longer exists. 142194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood } else { 142294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood ALOGV("Move file: %s (from %s to %s)\n", buf+bufp, srcpkg, dstpkg); 142394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood if (!create_move_path(srcpath, srcpkg, buf+bufp, 0) && 142494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood !create_move_path(dstpath, dstpkg, buf+bufp, 0)) { 142594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood movefileordir(srcpath, dstpath, 142694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood strlen(dstpath)-strlen(buf+bufp), 142794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood dstuid, dstgid, &s); 142894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood } 142994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood } 143094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood } else { 143194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood char* div = strchr(buf+bufp, ':'); 143294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood if (div == NULL) { 143394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood ALOGW("Bad package spec in %s%s; no ':' sep: %s\n", 143494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood UPDATE_COMMANDS_DIR_PREFIX, name, buf+bufp); 143594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood } else { 143694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood *div = 0; 143794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood div++; 143894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood if (strlen(buf+bufp) < PKG_NAME_MAX) { 143994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood strcpy(dstpkg, buf+bufp); 144094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood } else { 144194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood srcpkg[0] = dstpkg[0] = 0; 144294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood ALOGW("Package name too long in %s%s: %s\n", 144394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood UPDATE_COMMANDS_DIR_PREFIX, name, buf+bufp); 144494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood } 144594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood if (strlen(div) < PKG_NAME_MAX) { 144694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood strcpy(srcpkg, div); 144794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood } else { 144894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood srcpkg[0] = dstpkg[0] = 0; 144994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood ALOGW("Package name too long in %s%s: %s\n", 145094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood UPDATE_COMMANDS_DIR_PREFIX, name, div); 145194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood } 145294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood if (srcpkg[0] != 0) { 145394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood if (!create_pkg_path(srcpath, srcpkg, PKG_DIR_POSTFIX, 0)) { 145494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood if (lstat(srcpath, &s) < 0) { 145594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood // Package no longer exists -- skip. 145694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood srcpkg[0] = 0; 145794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood } 145894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood } else { 145994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood srcpkg[0] = 0; 146094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood ALOGW("Can't create path %s in %s%s\n", 146194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood div, UPDATE_COMMANDS_DIR_PREFIX, name); 146294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood } 146394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood if (srcpkg[0] != 0) { 146494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood if (!create_pkg_path(dstpath, dstpkg, PKG_DIR_POSTFIX, 0)) { 146594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood if (lstat(dstpath, &s) == 0) { 146694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood dstuid = s.st_uid; 146794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood dstgid = s.st_gid; 146894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood } else { 146994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood // Destination package doesn't 147094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood // exist... due to original-package, 147194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood // this is normal, so don't be 147294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood // noisy about it. 147394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood srcpkg[0] = 0; 147494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood } 147594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood } else { 147694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood srcpkg[0] = 0; 147794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood ALOGW("Can't create path %s in %s%s\n", 147894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood div, UPDATE_COMMANDS_DIR_PREFIX, name); 147994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood } 148094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood } 148194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood ALOGV("Transfering from %s to %s: uid=%d\n", 148294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood srcpkg, dstpkg, dstuid); 148394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood } 148494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood } 148594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood } 148694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood bufp = bufi+1; 148794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood } else { 148894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood if (bufp == 0) { 148994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood if (bufp < bufe) { 149094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood ALOGW("Line too long in %s%s, skipping: %s\n", 149194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood UPDATE_COMMANDS_DIR_PREFIX, name, buf); 149294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood } 149394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood } else if (bufp < bufe) { 149494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood memcpy(buf, buf+bufp, bufe-bufp); 149594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood bufe -= bufp; 149694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood bufp = 0; 149794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood } 149894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood readlen = read(subfd, buf+bufe, PKG_PATH_MAX-bufe); 149994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood if (readlen < 0) { 150094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood ALOGW("Failure reading update commands in %s%s: %s\n", 150194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood UPDATE_COMMANDS_DIR_PREFIX, name, strerror(errno)); 150294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood break; 150394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood } else if (readlen == 0) { 150494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood break; 150594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood } 150694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood bufe += readlen; 150794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood buf[bufe] = 0; 150894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood ALOGV("Read buf: %s\n", buf); 150994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood } 151094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood } 151194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood close(subfd); 151294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood } 151394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood } 151494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood closedir(d); 151594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwooddone: 151694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood return 0; 151794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood} 151894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood 1519c03de09173f98506e73e7cf7df21fe11795d4b24Jeff Sharkeyint linklib(const char* uuid, const char* pkgname, const char* asecLibDir, int userId) 152094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood{ 152194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood struct stat s, libStat; 152294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood int rc = 0; 152394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood 1524d792118c493806eeb24a8203f508e6e18fe93bd7Jeff Sharkey std::string _pkgdir(create_data_user_package_path(uuid, userId, pkgname)); 1525c03de09173f98506e73e7cf7df21fe11795d4b24Jeff Sharkey std::string _libsymlink(_pkgdir + PKG_LIB_POSTFIX); 1526c03de09173f98506e73e7cf7df21fe11795d4b24Jeff Sharkey 1527c03de09173f98506e73e7cf7df21fe11795d4b24Jeff Sharkey const char* pkgdir = _pkgdir.c_str(); 1528c03de09173f98506e73e7cf7df21fe11795d4b24Jeff Sharkey const char* libsymlink = _libsymlink.c_str(); 152994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood 153094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood if (stat(pkgdir, &s) < 0) return -1; 153194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood 153294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood if (chown(pkgdir, AID_INSTALL, AID_INSTALL) < 0) { 153394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood ALOGE("failed to chown '%s': %s\n", pkgdir, strerror(errno)); 153494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood return -1; 153594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood } 153694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood 153794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood if (chmod(pkgdir, 0700) < 0) { 153894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood ALOGE("linklib() 1: failed to chmod '%s': %s\n", pkgdir, strerror(errno)); 153994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood rc = -1; 154094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood goto out; 154194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood } 154294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood 154394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood if (lstat(libsymlink, &libStat) < 0) { 154494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood if (errno != ENOENT) { 154594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood ALOGE("couldn't stat lib dir: %s\n", strerror(errno)); 154694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood rc = -1; 154794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood goto out; 154894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood } 154994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood } else { 155094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood if (S_ISDIR(libStat.st_mode)) { 15513aee2c5c749dc2589f001b26fae1ec958ec89524Narayan Kamath if (delete_dir_contents(libsymlink, 1, NULL) < 0) { 155294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood rc = -1; 155394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood goto out; 155494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood } 155594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood } else if (S_ISLNK(libStat.st_mode)) { 155694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood if (unlink(libsymlink) < 0) { 155794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood ALOGE("couldn't unlink lib dir: %s\n", strerror(errno)); 155894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood rc = -1; 155994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood goto out; 156094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood } 156194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood } 156294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood } 156394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood 156494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood if (symlink(asecLibDir, libsymlink) < 0) { 156594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood ALOGE("couldn't symlink directory '%s' -> '%s': %s\n", libsymlink, asecLibDir, 156694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood strerror(errno)); 156794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood rc = -errno; 156894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood goto out; 156994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood } 157094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood 157194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwoodout: 157294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood if (chmod(pkgdir, s.st_mode) < 0) { 157394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood ALOGE("linklib() 2: failed to chmod '%s': %s\n", pkgdir, strerror(errno)); 157494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood rc = -errno; 157594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood } 157694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood 157794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood if (chown(pkgdir, s.st_uid, s.st_gid) < 0) { 157894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood ALOGE("failed to chown '%s' : %s\n", pkgdir, strerror(errno)); 157994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood return -errno; 158094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood } 158194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood 158294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood return rc; 158394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood} 158463568b1430d741f40ca008391c854ef1cc880138MÃ¥rten Kongstad 158563568b1430d741f40ca008391c854ef1cc880138MÃ¥rten Kongstadstatic void run_idmap(const char *target_apk, const char *overlay_apk, int idmap_fd) 158663568b1430d741f40ca008391c854ef1cc880138MÃ¥rten Kongstad{ 158763568b1430d741f40ca008391c854ef1cc880138MÃ¥rten Kongstad static const char *IDMAP_BIN = "/system/bin/idmap"; 158863568b1430d741f40ca008391c854ef1cc880138MÃ¥rten Kongstad static const size_t MAX_INT_LEN = 32; 158963568b1430d741f40ca008391c854ef1cc880138MÃ¥rten Kongstad char idmap_str[MAX_INT_LEN]; 159063568b1430d741f40ca008391c854ef1cc880138MÃ¥rten Kongstad 159163568b1430d741f40ca008391c854ef1cc880138MÃ¥rten Kongstad snprintf(idmap_str, sizeof(idmap_str), "%d", idmap_fd); 159263568b1430d741f40ca008391c854ef1cc880138MÃ¥rten Kongstad 159363568b1430d741f40ca008391c854ef1cc880138MÃ¥rten Kongstad execl(IDMAP_BIN, IDMAP_BIN, "--fd", target_apk, overlay_apk, idmap_str, (char*)NULL); 159463568b1430d741f40ca008391c854ef1cc880138MÃ¥rten Kongstad ALOGE("execl(%s) failed: %s\n", IDMAP_BIN, strerror(errno)); 159563568b1430d741f40ca008391c854ef1cc880138MÃ¥rten Kongstad} 159663568b1430d741f40ca008391c854ef1cc880138MÃ¥rten Kongstad 159763568b1430d741f40ca008391c854ef1cc880138MÃ¥rten Kongstad// Transform string /a/b/c.apk to (prefix)/a@b@c.apk@(suffix) 159863568b1430d741f40ca008391c854ef1cc880138MÃ¥rten Kongstad// eg /a/b/c.apk to /data/resource-cache/a@b@c.apk@idmap 159963568b1430d741f40ca008391c854ef1cc880138MÃ¥rten Kongstadstatic int flatten_path(const char *prefix, const char *suffix, 160063568b1430d741f40ca008391c854ef1cc880138MÃ¥rten Kongstad const char *overlay_path, char *idmap_path, size_t N) 160163568b1430d741f40ca008391c854ef1cc880138MÃ¥rten Kongstad{ 160263568b1430d741f40ca008391c854ef1cc880138MÃ¥rten Kongstad if (overlay_path == NULL || idmap_path == NULL) { 160363568b1430d741f40ca008391c854ef1cc880138MÃ¥rten Kongstad return -1; 160463568b1430d741f40ca008391c854ef1cc880138MÃ¥rten Kongstad } 160563568b1430d741f40ca008391c854ef1cc880138MÃ¥rten Kongstad const size_t len_overlay_path = strlen(overlay_path); 160663568b1430d741f40ca008391c854ef1cc880138MÃ¥rten Kongstad // will access overlay_path + 1 further below; requires absolute path 160763568b1430d741f40ca008391c854ef1cc880138MÃ¥rten Kongstad if (len_overlay_path < 2 || *overlay_path != '/') { 160863568b1430d741f40ca008391c854ef1cc880138MÃ¥rten Kongstad return -1; 160963568b1430d741f40ca008391c854ef1cc880138MÃ¥rten Kongstad } 161063568b1430d741f40ca008391c854ef1cc880138MÃ¥rten Kongstad const size_t len_idmap_root = strlen(prefix); 161163568b1430d741f40ca008391c854ef1cc880138MÃ¥rten Kongstad const size_t len_suffix = strlen(suffix); 161263568b1430d741f40ca008391c854ef1cc880138MÃ¥rten Kongstad if (SIZE_MAX - len_idmap_root < len_overlay_path || 161363568b1430d741f40ca008391c854ef1cc880138MÃ¥rten Kongstad SIZE_MAX - (len_idmap_root + len_overlay_path) < len_suffix) { 161463568b1430d741f40ca008391c854ef1cc880138MÃ¥rten Kongstad // additions below would cause overflow 161563568b1430d741f40ca008391c854ef1cc880138MÃ¥rten Kongstad return -1; 161663568b1430d741f40ca008391c854ef1cc880138MÃ¥rten Kongstad } 161763568b1430d741f40ca008391c854ef1cc880138MÃ¥rten Kongstad if (N < len_idmap_root + len_overlay_path + len_suffix) { 161863568b1430d741f40ca008391c854ef1cc880138MÃ¥rten Kongstad return -1; 161963568b1430d741f40ca008391c854ef1cc880138MÃ¥rten Kongstad } 162063568b1430d741f40ca008391c854ef1cc880138MÃ¥rten Kongstad memset(idmap_path, 0, N); 162163568b1430d741f40ca008391c854ef1cc880138MÃ¥rten Kongstad snprintf(idmap_path, N, "%s%s%s", prefix, overlay_path + 1, suffix); 162263568b1430d741f40ca008391c854ef1cc880138MÃ¥rten Kongstad char *ch = idmap_path + len_idmap_root; 162363568b1430d741f40ca008391c854ef1cc880138MÃ¥rten Kongstad while (*ch != '\0') { 162463568b1430d741f40ca008391c854ef1cc880138MÃ¥rten Kongstad if (*ch == '/') { 162563568b1430d741f40ca008391c854ef1cc880138MÃ¥rten Kongstad *ch = '@'; 162663568b1430d741f40ca008391c854ef1cc880138MÃ¥rten Kongstad } 162763568b1430d741f40ca008391c854ef1cc880138MÃ¥rten Kongstad ++ch; 162863568b1430d741f40ca008391c854ef1cc880138MÃ¥rten Kongstad } 162963568b1430d741f40ca008391c854ef1cc880138MÃ¥rten Kongstad return 0; 163063568b1430d741f40ca008391c854ef1cc880138MÃ¥rten Kongstad} 163163568b1430d741f40ca008391c854ef1cc880138MÃ¥rten Kongstad 163263568b1430d741f40ca008391c854ef1cc880138MÃ¥rten Kongstadint idmap(const char *target_apk, const char *overlay_apk, uid_t uid) 163363568b1430d741f40ca008391c854ef1cc880138MÃ¥rten Kongstad{ 163463568b1430d741f40ca008391c854ef1cc880138MÃ¥rten Kongstad ALOGV("idmap target_apk=%s overlay_apk=%s uid=%d\n", target_apk, overlay_apk, uid); 163563568b1430d741f40ca008391c854ef1cc880138MÃ¥rten Kongstad 163663568b1430d741f40ca008391c854ef1cc880138MÃ¥rten Kongstad int idmap_fd = -1; 163763568b1430d741f40ca008391c854ef1cc880138MÃ¥rten Kongstad char idmap_path[PATH_MAX]; 163863568b1430d741f40ca008391c854ef1cc880138MÃ¥rten Kongstad 163963568b1430d741f40ca008391c854ef1cc880138MÃ¥rten Kongstad if (flatten_path(IDMAP_PREFIX, IDMAP_SUFFIX, overlay_apk, 164063568b1430d741f40ca008391c854ef1cc880138MÃ¥rten Kongstad idmap_path, sizeof(idmap_path)) == -1) { 164163568b1430d741f40ca008391c854ef1cc880138MÃ¥rten Kongstad ALOGE("idmap cannot generate idmap path for overlay %s\n", overlay_apk); 164263568b1430d741f40ca008391c854ef1cc880138MÃ¥rten Kongstad goto fail; 164363568b1430d741f40ca008391c854ef1cc880138MÃ¥rten Kongstad } 164463568b1430d741f40ca008391c854ef1cc880138MÃ¥rten Kongstad 164563568b1430d741f40ca008391c854ef1cc880138MÃ¥rten Kongstad unlink(idmap_path); 164663568b1430d741f40ca008391c854ef1cc880138MÃ¥rten Kongstad idmap_fd = open(idmap_path, O_RDWR | O_CREAT | O_EXCL, 0644); 164763568b1430d741f40ca008391c854ef1cc880138MÃ¥rten Kongstad if (idmap_fd < 0) { 164863568b1430d741f40ca008391c854ef1cc880138MÃ¥rten Kongstad ALOGE("idmap cannot open '%s' for output: %s\n", idmap_path, strerror(errno)); 164963568b1430d741f40ca008391c854ef1cc880138MÃ¥rten Kongstad goto fail; 165063568b1430d741f40ca008391c854ef1cc880138MÃ¥rten Kongstad } 165163568b1430d741f40ca008391c854ef1cc880138MÃ¥rten Kongstad if (fchown(idmap_fd, AID_SYSTEM, uid) < 0) { 165263568b1430d741f40ca008391c854ef1cc880138MÃ¥rten Kongstad ALOGE("idmap cannot chown '%s'\n", idmap_path); 165363568b1430d741f40ca008391c854ef1cc880138MÃ¥rten Kongstad goto fail; 165463568b1430d741f40ca008391c854ef1cc880138MÃ¥rten Kongstad } 165563568b1430d741f40ca008391c854ef1cc880138MÃ¥rten Kongstad if (fchmod(idmap_fd, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH) < 0) { 165663568b1430d741f40ca008391c854ef1cc880138MÃ¥rten Kongstad ALOGE("idmap cannot chmod '%s'\n", idmap_path); 165763568b1430d741f40ca008391c854ef1cc880138MÃ¥rten Kongstad goto fail; 165863568b1430d741f40ca008391c854ef1cc880138MÃ¥rten Kongstad } 165963568b1430d741f40ca008391c854ef1cc880138MÃ¥rten Kongstad 166063568b1430d741f40ca008391c854ef1cc880138MÃ¥rten Kongstad pid_t pid; 166163568b1430d741f40ca008391c854ef1cc880138MÃ¥rten Kongstad pid = fork(); 166263568b1430d741f40ca008391c854ef1cc880138MÃ¥rten Kongstad if (pid == 0) { 166363568b1430d741f40ca008391c854ef1cc880138MÃ¥rten Kongstad /* child -- drop privileges before continuing */ 166463568b1430d741f40ca008391c854ef1cc880138MÃ¥rten Kongstad if (setgid(uid) != 0) { 166563568b1430d741f40ca008391c854ef1cc880138MÃ¥rten Kongstad ALOGE("setgid(%d) failed during idmap\n", uid); 166663568b1430d741f40ca008391c854ef1cc880138MÃ¥rten Kongstad exit(1); 166763568b1430d741f40ca008391c854ef1cc880138MÃ¥rten Kongstad } 166863568b1430d741f40ca008391c854ef1cc880138MÃ¥rten Kongstad if (setuid(uid) != 0) { 166963568b1430d741f40ca008391c854ef1cc880138MÃ¥rten Kongstad ALOGE("setuid(%d) failed during idmap\n", uid); 167063568b1430d741f40ca008391c854ef1cc880138MÃ¥rten Kongstad exit(1); 167163568b1430d741f40ca008391c854ef1cc880138MÃ¥rten Kongstad } 167263568b1430d741f40ca008391c854ef1cc880138MÃ¥rten Kongstad if (flock(idmap_fd, LOCK_EX | LOCK_NB) != 0) { 167363568b1430d741f40ca008391c854ef1cc880138MÃ¥rten Kongstad ALOGE("flock(%s) failed during idmap: %s\n", idmap_path, strerror(errno)); 167463568b1430d741f40ca008391c854ef1cc880138MÃ¥rten Kongstad exit(1); 167563568b1430d741f40ca008391c854ef1cc880138MÃ¥rten Kongstad } 167663568b1430d741f40ca008391c854ef1cc880138MÃ¥rten Kongstad 167763568b1430d741f40ca008391c854ef1cc880138MÃ¥rten Kongstad run_idmap(target_apk, overlay_apk, idmap_fd); 167863568b1430d741f40ca008391c854ef1cc880138MÃ¥rten Kongstad exit(1); /* only if exec call to idmap failed */ 167963568b1430d741f40ca008391c854ef1cc880138MÃ¥rten Kongstad } else { 168063568b1430d741f40ca008391c854ef1cc880138MÃ¥rten Kongstad int status = wait_child(pid); 168163568b1430d741f40ca008391c854ef1cc880138MÃ¥rten Kongstad if (status != 0) { 168263568b1430d741f40ca008391c854ef1cc880138MÃ¥rten Kongstad ALOGE("idmap failed, status=0x%04x\n", status); 168363568b1430d741f40ca008391c854ef1cc880138MÃ¥rten Kongstad goto fail; 168463568b1430d741f40ca008391c854ef1cc880138MÃ¥rten Kongstad } 168563568b1430d741f40ca008391c854ef1cc880138MÃ¥rten Kongstad } 168663568b1430d741f40ca008391c854ef1cc880138MÃ¥rten Kongstad 168763568b1430d741f40ca008391c854ef1cc880138MÃ¥rten Kongstad close(idmap_fd); 168863568b1430d741f40ca008391c854ef1cc880138MÃ¥rten Kongstad return 0; 168963568b1430d741f40ca008391c854ef1cc880138MÃ¥rten Kongstadfail: 169063568b1430d741f40ca008391c854ef1cc880138MÃ¥rten Kongstad if (idmap_fd >= 0) { 169163568b1430d741f40ca008391c854ef1cc880138MÃ¥rten Kongstad close(idmap_fd); 169263568b1430d741f40ca008391c854ef1cc880138MÃ¥rten Kongstad unlink(idmap_path); 169363568b1430d741f40ca008391c854ef1cc880138MÃ¥rten Kongstad } 169463568b1430d741f40ca008391c854ef1cc880138MÃ¥rten Kongstad return -1; 169563568b1430d741f40ca008391c854ef1cc880138MÃ¥rten Kongstad} 1696e9887e46cea4a095e4219927eadbe4c57bb1a5eeRobert Craig 16976fe28a06012250da85f808a0869f87e06e0bcce9Jeff Sharkeyint restorecon_data(const char* uuid, const char* pkgName, 16980ad7a11003ad76381452c3751368b8e3f42b1f6aAndreas Gampe const char* seinfo, uid_t uid) 1699e9887e46cea4a095e4219927eadbe4c57bb1a5eeRobert Craig{ 1700da30dc7336f03ca629fe173db1425fdce989119cRobert Craig struct dirent *entry; 1701da30dc7336f03ca629fe173db1425fdce989119cRobert Craig DIR *d; 1702da30dc7336f03ca629fe173db1425fdce989119cRobert Craig struct stat s; 1703da30dc7336f03ca629fe173db1425fdce989119cRobert Craig int ret = 0; 1704e9887e46cea4a095e4219927eadbe4c57bb1a5eeRobert Craig 1705da30dc7336f03ca629fe173db1425fdce989119cRobert Craig // SELINUX_ANDROID_RESTORECON_DATADATA flag is set by libselinux. Not needed here. 1706da30dc7336f03ca629fe173db1425fdce989119cRobert Craig unsigned int flags = SELINUX_ANDROID_RESTORECON_RECURSE; 1707e9887e46cea4a095e4219927eadbe4c57bb1a5eeRobert Craig 1708da30dc7336f03ca629fe173db1425fdce989119cRobert Craig if (!pkgName || !seinfo) { 1709da30dc7336f03ca629fe173db1425fdce989119cRobert Craig ALOGE("Package name or seinfo tag is null when trying to restorecon."); 1710da30dc7336f03ca629fe173db1425fdce989119cRobert Craig return -1; 1711da30dc7336f03ca629fe173db1425fdce989119cRobert Craig } 1712e9887e46cea4a095e4219927eadbe4c57bb1a5eeRobert Craig 171341ea424413c0381ef2aa15fc5bd5d4b88abd23c4Jeff Sharkey // Special case for owner on internal storage 171441ea424413c0381ef2aa15fc5bd5d4b88abd23c4Jeff Sharkey if (uuid == nullptr) { 1715d792118c493806eeb24a8203f508e6e18fe93bd7Jeff Sharkey std::string path(create_data_user_package_path(nullptr, 0, pkgName)); 1716e9887e46cea4a095e4219927eadbe4c57bb1a5eeRobert Craig 171741ea424413c0381ef2aa15fc5bd5d4b88abd23c4Jeff Sharkey if (selinux_android_restorecon_pkgdir(path.c_str(), seinfo, uid, flags) < 0) { 171841ea424413c0381ef2aa15fc5bd5d4b88abd23c4Jeff Sharkey PLOG(ERROR) << "restorecon failed for " << path; 171941ea424413c0381ef2aa15fc5bd5d4b88abd23c4Jeff Sharkey ret |= -1; 172041ea424413c0381ef2aa15fc5bd5d4b88abd23c4Jeff Sharkey } 1721e9887e46cea4a095e4219927eadbe4c57bb1a5eeRobert Craig } 1722e9887e46cea4a095e4219927eadbe4c57bb1a5eeRobert Craig 1723da30dc7336f03ca629fe173db1425fdce989119cRobert Craig // Relabel package directory for all secondary users. 172441ea424413c0381ef2aa15fc5bd5d4b88abd23c4Jeff Sharkey std::string userdir(create_data_path(uuid) + "/" + SECONDARY_USER_PREFIX); 172541ea424413c0381ef2aa15fc5bd5d4b88abd23c4Jeff Sharkey d = opendir(userdir.c_str()); 1726da30dc7336f03ca629fe173db1425fdce989119cRobert Craig if (d == NULL) { 1727da30dc7336f03ca629fe173db1425fdce989119cRobert Craig return -1; 1728da30dc7336f03ca629fe173db1425fdce989119cRobert Craig } 1729da30dc7336f03ca629fe173db1425fdce989119cRobert Craig 1730da30dc7336f03ca629fe173db1425fdce989119cRobert Craig while ((entry = readdir(d))) { 1731da30dc7336f03ca629fe173db1425fdce989119cRobert Craig if (entry->d_type != DT_DIR) { 1732da30dc7336f03ca629fe173db1425fdce989119cRobert Craig continue; 1733da30dc7336f03ca629fe173db1425fdce989119cRobert Craig } 1734da30dc7336f03ca629fe173db1425fdce989119cRobert Craig 1735da30dc7336f03ca629fe173db1425fdce989119cRobert Craig const char *user = entry->d_name; 1736da30dc7336f03ca629fe173db1425fdce989119cRobert Craig // Ignore "." and ".." 1737da30dc7336f03ca629fe173db1425fdce989119cRobert Craig if (!strcmp(user, ".") || !strcmp(user, "..")) { 1738da30dc7336f03ca629fe173db1425fdce989119cRobert Craig continue; 1739da30dc7336f03ca629fe173db1425fdce989119cRobert Craig } 1740da30dc7336f03ca629fe173db1425fdce989119cRobert Craig 1741da30dc7336f03ca629fe173db1425fdce989119cRobert Craig // user directories start with a number 1742da30dc7336f03ca629fe173db1425fdce989119cRobert Craig if (user[0] < '0' || user[0] > '9') { 1743da30dc7336f03ca629fe173db1425fdce989119cRobert Craig ALOGE("Expecting numbered directory during restorecon. Instead got '%s'.", user); 1744da30dc7336f03ca629fe173db1425fdce989119cRobert Craig continue; 1745da30dc7336f03ca629fe173db1425fdce989119cRobert Craig } 1746da30dc7336f03ca629fe173db1425fdce989119cRobert Craig 1747e36372423000a906bafae68844ebc6c42d09335aJeff Sharkey std::string pkgdir(StringPrintf("%s%s/%s", userdir.c_str(), user, pkgName)); 174841ea424413c0381ef2aa15fc5bd5d4b88abd23c4Jeff Sharkey if (stat(pkgdir.c_str(), &s) < 0) { 1749da30dc7336f03ca629fe173db1425fdce989119cRobert Craig continue; 1750da30dc7336f03ca629fe173db1425fdce989119cRobert Craig } 1751da30dc7336f03ca629fe173db1425fdce989119cRobert Craig 175241ea424413c0381ef2aa15fc5bd5d4b88abd23c4Jeff Sharkey if (selinux_android_restorecon_pkgdir(pkgdir.c_str(), seinfo, s.st_uid, flags) < 0) { 175341ea424413c0381ef2aa15fc5bd5d4b88abd23c4Jeff Sharkey PLOG(ERROR) << "restorecon failed for " << pkgdir; 1754da30dc7336f03ca629fe173db1425fdce989119cRobert Craig ret |= -1; 1755da30dc7336f03ca629fe173db1425fdce989119cRobert Craig } 1756da30dc7336f03ca629fe173db1425fdce989119cRobert Craig } 1757da30dc7336f03ca629fe173db1425fdce989119cRobert Craig 1758da30dc7336f03ca629fe173db1425fdce989119cRobert Craig closedir(d); 1759e9887e46cea4a095e4219927eadbe4c57bb1a5eeRobert Craig return ret; 1760e9887e46cea4a095e4219927eadbe4c57bb1a5eeRobert Craig} 17613aee2c5c749dc2589f001b26fae1ec958ec89524Narayan Kamath 176288ce4ff7a95ea2008fa28f12b880ee526e331440Fyodor Kupolovint create_oat_dir(const char* oat_dir, const char* instruction_set) 176388ce4ff7a95ea2008fa28f12b880ee526e331440Fyodor Kupolov{ 176488ce4ff7a95ea2008fa28f12b880ee526e331440Fyodor Kupolov char oat_instr_dir[PKG_PATH_MAX]; 176588ce4ff7a95ea2008fa28f12b880ee526e331440Fyodor Kupolov 176688ce4ff7a95ea2008fa28f12b880ee526e331440Fyodor Kupolov if (validate_apk_path(oat_dir)) { 176788ce4ff7a95ea2008fa28f12b880ee526e331440Fyodor Kupolov ALOGE("invalid apk path '%s' (bad prefix)\n", oat_dir); 176888ce4ff7a95ea2008fa28f12b880ee526e331440Fyodor Kupolov return -1; 176988ce4ff7a95ea2008fa28f12b880ee526e331440Fyodor Kupolov } 17708eed7e6a9bb527af7380ec13b390c6e2955eba6aFyodor Kupolov if (fs_prepare_dir(oat_dir, S_IRWXU | S_IRWXG | S_IXOTH, AID_SYSTEM, AID_INSTALL)) { 177188ce4ff7a95ea2008fa28f12b880ee526e331440Fyodor Kupolov return -1; 177288ce4ff7a95ea2008fa28f12b880ee526e331440Fyodor Kupolov } 177388ce4ff7a95ea2008fa28f12b880ee526e331440Fyodor Kupolov if (selinux_android_restorecon(oat_dir, 0)) { 177488ce4ff7a95ea2008fa28f12b880ee526e331440Fyodor Kupolov ALOGE("cannot restorecon dir '%s': %s\n", oat_dir, strerror(errno)); 177588ce4ff7a95ea2008fa28f12b880ee526e331440Fyodor Kupolov return -1; 177688ce4ff7a95ea2008fa28f12b880ee526e331440Fyodor Kupolov } 177788ce4ff7a95ea2008fa28f12b880ee526e331440Fyodor Kupolov snprintf(oat_instr_dir, PKG_PATH_MAX, "%s/%s", oat_dir, instruction_set); 17788eed7e6a9bb527af7380ec13b390c6e2955eba6aFyodor Kupolov if (fs_prepare_dir(oat_instr_dir, S_IRWXU | S_IRWXG | S_IXOTH, AID_SYSTEM, AID_INSTALL)) { 177988ce4ff7a95ea2008fa28f12b880ee526e331440Fyodor Kupolov return -1; 178088ce4ff7a95ea2008fa28f12b880ee526e331440Fyodor Kupolov } 178188ce4ff7a95ea2008fa28f12b880ee526e331440Fyodor Kupolov return 0; 178288ce4ff7a95ea2008fa28f12b880ee526e331440Fyodor Kupolov} 178388ce4ff7a95ea2008fa28f12b880ee526e331440Fyodor Kupolov 178488ce4ff7a95ea2008fa28f12b880ee526e331440Fyodor Kupolovint rm_package_dir(const char* apk_path) 178588ce4ff7a95ea2008fa28f12b880ee526e331440Fyodor Kupolov{ 178688ce4ff7a95ea2008fa28f12b880ee526e331440Fyodor Kupolov if (validate_apk_path(apk_path)) { 178788ce4ff7a95ea2008fa28f12b880ee526e331440Fyodor Kupolov ALOGE("invalid apk path '%s' (bad prefix)\n", apk_path); 178888ce4ff7a95ea2008fa28f12b880ee526e331440Fyodor Kupolov return -1; 178988ce4ff7a95ea2008fa28f12b880ee526e331440Fyodor Kupolov } 179088ce4ff7a95ea2008fa28f12b880ee526e331440Fyodor Kupolov return delete_dir_contents(apk_path, 1 /* also_delete_dir */ , NULL /* exclusion_predicate */); 179188ce4ff7a95ea2008fa28f12b880ee526e331440Fyodor Kupolov} 179288ce4ff7a95ea2008fa28f12b880ee526e331440Fyodor Kupolov 1793d845c96128a40ca5802c0840ae190fa0af7d4735Narayan Kamathint link_file(const char* relative_path, const char* from_base, const char* to_base) { 1794d845c96128a40ca5802c0840ae190fa0af7d4735Narayan Kamath char from_path[PKG_PATH_MAX]; 1795d845c96128a40ca5802c0840ae190fa0af7d4735Narayan Kamath char to_path[PKG_PATH_MAX]; 1796d845c96128a40ca5802c0840ae190fa0af7d4735Narayan Kamath snprintf(from_path, PKG_PATH_MAX, "%s/%s", from_base, relative_path); 1797d845c96128a40ca5802c0840ae190fa0af7d4735Narayan Kamath snprintf(to_path, PKG_PATH_MAX, "%s/%s", to_base, relative_path); 1798d845c96128a40ca5802c0840ae190fa0af7d4735Narayan Kamath 1799d845c96128a40ca5802c0840ae190fa0af7d4735Narayan Kamath if (validate_apk_path_subdirs(from_path)) { 1800d845c96128a40ca5802c0840ae190fa0af7d4735Narayan Kamath ALOGE("invalid app data sub-path '%s' (bad prefix)\n", from_path); 1801d845c96128a40ca5802c0840ae190fa0af7d4735Narayan Kamath return -1; 1802d845c96128a40ca5802c0840ae190fa0af7d4735Narayan Kamath } 1803d845c96128a40ca5802c0840ae190fa0af7d4735Narayan Kamath 1804d845c96128a40ca5802c0840ae190fa0af7d4735Narayan Kamath if (validate_apk_path_subdirs(to_path)) { 1805d845c96128a40ca5802c0840ae190fa0af7d4735Narayan Kamath ALOGE("invalid app data sub-path '%s' (bad prefix)\n", to_path); 1806d845c96128a40ca5802c0840ae190fa0af7d4735Narayan Kamath return -1; 1807d845c96128a40ca5802c0840ae190fa0af7d4735Narayan Kamath } 1808d845c96128a40ca5802c0840ae190fa0af7d4735Narayan Kamath 1809d845c96128a40ca5802c0840ae190fa0af7d4735Narayan Kamath const int ret = link(from_path, to_path); 1810d845c96128a40ca5802c0840ae190fa0af7d4735Narayan Kamath if (ret < 0) { 1811d845c96128a40ca5802c0840ae190fa0af7d4735Narayan Kamath ALOGE("link(%s, %s) failed : %s", from_path, to_path, strerror(errno)); 1812d845c96128a40ca5802c0840ae190fa0af7d4735Narayan Kamath return -1; 1813d845c96128a40ca5802c0840ae190fa0af7d4735Narayan Kamath } 1814d845c96128a40ca5802c0840ae190fa0af7d4735Narayan Kamath 1815d845c96128a40ca5802c0840ae190fa0af7d4735Narayan Kamath return 0; 1816d845c96128a40ca5802c0840ae190fa0af7d4735Narayan Kamath} 1817d845c96128a40ca5802c0840ae190fa0af7d4735Narayan Kamath 181888ce4ff7a95ea2008fa28f12b880ee526e331440Fyodor Kupolovint calculate_oat_file_path(char path[PKG_PATH_MAX], const char *oat_dir, const char *apk_path, 181988ce4ff7a95ea2008fa28f12b880ee526e331440Fyodor Kupolov const char *instruction_set) { 182088ce4ff7a95ea2008fa28f12b880ee526e331440Fyodor Kupolov char *file_name_start; 182188ce4ff7a95ea2008fa28f12b880ee526e331440Fyodor Kupolov char *file_name_end; 182288ce4ff7a95ea2008fa28f12b880ee526e331440Fyodor Kupolov 182388ce4ff7a95ea2008fa28f12b880ee526e331440Fyodor Kupolov file_name_start = strrchr(apk_path, '/'); 182488ce4ff7a95ea2008fa28f12b880ee526e331440Fyodor Kupolov if (file_name_start == NULL) { 182588ce4ff7a95ea2008fa28f12b880ee526e331440Fyodor Kupolov ALOGE("apk_path '%s' has no '/'s in it\n", apk_path); 182688ce4ff7a95ea2008fa28f12b880ee526e331440Fyodor Kupolov return -1; 182788ce4ff7a95ea2008fa28f12b880ee526e331440Fyodor Kupolov } 182888ce4ff7a95ea2008fa28f12b880ee526e331440Fyodor Kupolov file_name_end = strrchr(apk_path, '.'); 182988ce4ff7a95ea2008fa28f12b880ee526e331440Fyodor Kupolov if (file_name_end < file_name_start) { 183088ce4ff7a95ea2008fa28f12b880ee526e331440Fyodor Kupolov ALOGE("apk_path '%s' has no extension\n", apk_path); 183188ce4ff7a95ea2008fa28f12b880ee526e331440Fyodor Kupolov return -1; 183288ce4ff7a95ea2008fa28f12b880ee526e331440Fyodor Kupolov } 183388ce4ff7a95ea2008fa28f12b880ee526e331440Fyodor Kupolov 183488ce4ff7a95ea2008fa28f12b880ee526e331440Fyodor Kupolov // Calculate file_name 183588ce4ff7a95ea2008fa28f12b880ee526e331440Fyodor Kupolov int file_name_len = file_name_end - file_name_start - 1; 183688ce4ff7a95ea2008fa28f12b880ee526e331440Fyodor Kupolov char file_name[file_name_len + 1]; 183788ce4ff7a95ea2008fa28f12b880ee526e331440Fyodor Kupolov memcpy(file_name, file_name_start + 1, file_name_len); 183888ce4ff7a95ea2008fa28f12b880ee526e331440Fyodor Kupolov file_name[file_name_len] = '\0'; 183988ce4ff7a95ea2008fa28f12b880ee526e331440Fyodor Kupolov 184088ce4ff7a95ea2008fa28f12b880ee526e331440Fyodor Kupolov // <apk_parent_dir>/oat/<isa>/<file_name>.odex 184188ce4ff7a95ea2008fa28f12b880ee526e331440Fyodor Kupolov snprintf(path, PKG_PATH_MAX, "%s/%s/%s.odex", oat_dir, instruction_set, file_name); 184288ce4ff7a95ea2008fa28f12b880ee526e331440Fyodor Kupolov return 0; 184388ce4ff7a95ea2008fa28f12b880ee526e331440Fyodor Kupolov} 1844