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
19e36372423000a906bafae68844ebc6c42d09335aJeff Sharkey#include <base/stringprintf.h>
20e36372423000a906bafae68844ebc6c42d09335aJeff Sharkey#include <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
86d93707342a61e66bc3eb2145628158452f577f42Dave Allison    remove_profile_file(pkgname);
87d93707342a61e66bc3eb2145628158452f577f42Dave Allison
8894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    /* delete contents AND directory, no exceptions */
8994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    return delete_dir_contents(pkgdir, 1, NULL);
9094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood}
9194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
9294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwoodint renamepkg(const char *oldpkgname, const char *newpkgname)
9394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood{
9494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    char oldpkgdir[PKG_PATH_MAX];
9594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    char newpkgdir[PKG_PATH_MAX];
9694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
9794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    if (create_pkg_path(oldpkgdir, oldpkgname, PKG_DIR_POSTFIX, 0))
9894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        return -1;
9994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    if (create_pkg_path(newpkgdir, newpkgname, PKG_DIR_POSTFIX, 0))
10094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        return -1;
10194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
10294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    if (rename(oldpkgdir, newpkgdir) < 0) {
10394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        ALOGE("cannot rename dir '%s' to '%s': %s\n", oldpkgdir, newpkgdir, strerror(errno));
10494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        return -errno;
10594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    }
10694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    return 0;
10794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood}
10894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
109c03de09173f98506e73e7cf7df21fe11795d4b24Jeff Sharkeyint fix_uid(const char *uuid, const char *pkgname, uid_t uid, gid_t gid)
11094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood{
11194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    struct stat s;
11294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
11394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    if ((uid < AID_SYSTEM) || (gid < AID_SYSTEM)) {
11494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        ALOGE("invalid uid/gid: %d %d\n", uid, gid);
11594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        return -1;
11694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    }
11794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
118d792118c493806eeb24a8203f508e6e18fe93bd7Jeff Sharkey    std::string _pkgdir(create_data_user_package_path(uuid, 0, pkgname));
119c03de09173f98506e73e7cf7df21fe11795d4b24Jeff Sharkey    const char* pkgdir = _pkgdir.c_str();
12094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
12194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    if (stat(pkgdir, &s) < 0) return -1;
12294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
12394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    if (s.st_uid != 0 || s.st_gid != 0) {
12492dc3fc52cf097bd105460cf377779bdcf146d62Mark Salyzyn        ALOGE("fixing uid of non-root pkg: %s %" PRIu32 " %" PRIu32 "\n", pkgdir, s.st_uid, s.st_gid);
12594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        return -1;
12694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    }
12794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
12894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    if (chmod(pkgdir, 0751) < 0) {
12994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        ALOGE("cannot chmod dir '%s': %s\n", pkgdir, strerror(errno));
13094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        unlink(pkgdir);
13194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        return -errno;
13294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    }
13394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    if (chown(pkgdir, uid, gid) < 0) {
13494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        ALOGE("cannot chown dir '%s': %s\n", pkgdir, strerror(errno));
13594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        unlink(pkgdir);
13694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        return -errno;
13794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    }
13894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
13994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    return 0;
14094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood}
14194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
142c03de09173f98506e73e7cf7df21fe11795d4b24Jeff Sharkeyint delete_user_data(const char *uuid, const char *pkgname, userid_t userid)
14394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood{
144d792118c493806eeb24a8203f508e6e18fe93bd7Jeff Sharkey    std::string _pkgdir(create_data_user_package_path(uuid, userid, pkgname));
145c03de09173f98506e73e7cf7df21fe11795d4b24Jeff Sharkey    const char* pkgdir = _pkgdir.c_str();
14694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
1473316fe472fd68377eba9983c43dfce4281209103Jeff Sharkey    return delete_dir_contents(pkgdir, 0, NULL);
14894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood}
14994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
150c03de09173f98506e73e7cf7df21fe11795d4b24Jeff Sharkeyint make_user_data(const char *uuid, const char *pkgname, uid_t uid, userid_t userid, const char* seinfo)
15194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood{
152d792118c493806eeb24a8203f508e6e18fe93bd7Jeff Sharkey    std::string _pkgdir(create_data_user_package_path(uuid, userid, pkgname));
153c03de09173f98506e73e7cf7df21fe11795d4b24Jeff Sharkey    const char* pkgdir = _pkgdir.c_str();
15494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
155a2d838a542c34d2887a0ec1fafa5f47566d595e9Nick Kralevich    if (mkdir(pkgdir, 0751) < 0) {
15694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        ALOGE("cannot create dir '%s': %s\n", pkgdir, strerror(errno));
15794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        return -errno;
15894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    }
159a2d838a542c34d2887a0ec1fafa5f47566d595e9Nick Kralevich    if (chmod(pkgdir, 0751) < 0) {
16094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        ALOGE("cannot chmod dir '%s': %s\n", pkgdir, strerror(errno));
16194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        unlink(pkgdir);
16294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        return -errno;
16394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    }
16494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
16526288202e7bdf2e897a11bf31a15685d7c20945fStephen Smalley    if (selinux_android_setfilecon(pkgdir, pkgname, seinfo, uid) < 0) {
16694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        ALOGE("cannot setfilecon dir '%s': %s\n", pkgdir, strerror(errno));
16794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        unlink(pkgdir);
16894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        return -errno;
16994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    }
17094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
17194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    if (chown(pkgdir, uid, uid) < 0) {
17294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        ALOGE("cannot chown dir '%s': %s\n", pkgdir, strerror(errno));
17394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        unlink(pkgdir);
17494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        return -errno;
17594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    }
17694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
17794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    return 0;
17894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood}
17994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
18031f08986f83fa6f2dcf55523b2cf706460aeed7cJeff Sharkeyint copy_complete_app(const char *from_uuid, const char *to_uuid,
181d792118c493806eeb24a8203f508e6e18fe93bd7Jeff Sharkey        const char *package_name, const char *data_app_name, appid_t appid,
182d792118c493806eeb24a8203f508e6e18fe93bd7Jeff Sharkey        const char* seinfo) {
183e36372423000a906bafae68844ebc6c42d09335aJeff Sharkey    std::vector<userid_t> users = get_known_users(from_uuid);
184e36372423000a906bafae68844ebc6c42d09335aJeff Sharkey
185d792118c493806eeb24a8203f508e6e18fe93bd7Jeff Sharkey    // Copy app
186d792118c493806eeb24a8203f508e6e18fe93bd7Jeff Sharkey    {
187d792118c493806eeb24a8203f508e6e18fe93bd7Jeff Sharkey        std::string from(create_data_app_package_path(from_uuid, data_app_name));
188d792118c493806eeb24a8203f508e6e18fe93bd7Jeff Sharkey        std::string to(create_data_app_package_path(to_uuid, data_app_name));
189d792118c493806eeb24a8203f508e6e18fe93bd7Jeff Sharkey        std::string to_parent(create_data_app_path(to_uuid));
190d792118c493806eeb24a8203f508e6e18fe93bd7Jeff Sharkey
191d792118c493806eeb24a8203f508e6e18fe93bd7Jeff Sharkey        char *argv[] = {
192d792118c493806eeb24a8203f508e6e18fe93bd7Jeff Sharkey            (char*) kCpPath,
193d792118c493806eeb24a8203f508e6e18fe93bd7Jeff Sharkey            (char*) "-F", /* delete any existing destination file first (--remove-destination) */
194d792118c493806eeb24a8203f508e6e18fe93bd7Jeff Sharkey            (char*) "-p", /* preserve timestamps, ownership, and permissions */
195d792118c493806eeb24a8203f508e6e18fe93bd7Jeff Sharkey            (char*) "-R", /* recurse into subdirectories (DEST must be a directory) */
196d792118c493806eeb24a8203f508e6e18fe93bd7Jeff Sharkey            (char*) "-P", /* Do not follow symlinks [default] */
197d792118c493806eeb24a8203f508e6e18fe93bd7Jeff Sharkey            (char*) "-d", /* don't dereference symlinks */
198d792118c493806eeb24a8203f508e6e18fe93bd7Jeff Sharkey            (char*) from.c_str(),
199d792118c493806eeb24a8203f508e6e18fe93bd7Jeff Sharkey            (char*) to_parent.c_str()
200d792118c493806eeb24a8203f508e6e18fe93bd7Jeff Sharkey        };
201d792118c493806eeb24a8203f508e6e18fe93bd7Jeff Sharkey
202d792118c493806eeb24a8203f508e6e18fe93bd7Jeff Sharkey        LOG(DEBUG) << "Copying " << from << " to " << to;
203d792118c493806eeb24a8203f508e6e18fe93bd7Jeff Sharkey        int rc = android_fork_execvp(ARRAY_SIZE(argv), argv, NULL, false, true);
204d792118c493806eeb24a8203f508e6e18fe93bd7Jeff Sharkey
205d792118c493806eeb24a8203f508e6e18fe93bd7Jeff Sharkey        if (rc != 0) {
206d792118c493806eeb24a8203f508e6e18fe93bd7Jeff Sharkey            LOG(ERROR) << "Failed copying " << from << " to " << to
207d792118c493806eeb24a8203f508e6e18fe93bd7Jeff Sharkey                    << ": status " << rc;
208d792118c493806eeb24a8203f508e6e18fe93bd7Jeff Sharkey            goto fail;
209d792118c493806eeb24a8203f508e6e18fe93bd7Jeff Sharkey        }
210d792118c493806eeb24a8203f508e6e18fe93bd7Jeff Sharkey
211d792118c493806eeb24a8203f508e6e18fe93bd7Jeff Sharkey        if (selinux_android_restorecon(to.c_str(), SELINUX_ANDROID_RESTORECON_RECURSE) != 0) {
212d792118c493806eeb24a8203f508e6e18fe93bd7Jeff Sharkey            LOG(ERROR) << "Failed to restorecon " << to;
213d792118c493806eeb24a8203f508e6e18fe93bd7Jeff Sharkey            goto fail;
214d792118c493806eeb24a8203f508e6e18fe93bd7Jeff Sharkey        }
215d792118c493806eeb24a8203f508e6e18fe93bd7Jeff Sharkey    }
216d792118c493806eeb24a8203f508e6e18fe93bd7Jeff Sharkey
217d792118c493806eeb24a8203f508e6e18fe93bd7Jeff Sharkey    // Copy private data for all known users
218e36372423000a906bafae68844ebc6c42d09335aJeff Sharkey    for (auto user : users) {
219d792118c493806eeb24a8203f508e6e18fe93bd7Jeff Sharkey        std::string from(create_data_user_package_path(from_uuid, user, package_name));
220d792118c493806eeb24a8203f508e6e18fe93bd7Jeff Sharkey        std::string to(create_data_user_package_path(to_uuid, user, package_name));
221d792118c493806eeb24a8203f508e6e18fe93bd7Jeff Sharkey        std::string to_parent(create_data_user_path(to_uuid, user));
222e36372423000a906bafae68844ebc6c42d09335aJeff Sharkey
223e36372423000a906bafae68844ebc6c42d09335aJeff Sharkey        // Data source may not exist for all users; that's okay
224e36372423000a906bafae68844ebc6c42d09335aJeff Sharkey        if (access(from.c_str(), F_OK) != 0) {
225e36372423000a906bafae68844ebc6c42d09335aJeff Sharkey            LOG(INFO) << "Missing source " << from;
226e36372423000a906bafae68844ebc6c42d09335aJeff Sharkey            continue;
227e36372423000a906bafae68844ebc6c42d09335aJeff Sharkey        }
228e36372423000a906bafae68844ebc6c42d09335aJeff Sharkey
229e36372423000a906bafae68844ebc6c42d09335aJeff Sharkey        std::string user_path(create_data_user_path(to_uuid, user));
230e36372423000a906bafae68844ebc6c42d09335aJeff Sharkey        if (fs_prepare_dir(user_path.c_str(), 0771, AID_SYSTEM, AID_SYSTEM) != 0) {
231e36372423000a906bafae68844ebc6c42d09335aJeff Sharkey            LOG(ERROR) << "Failed to prepare user target " << user_path;
232e36372423000a906bafae68844ebc6c42d09335aJeff Sharkey            goto fail;
233e36372423000a906bafae68844ebc6c42d09335aJeff Sharkey        }
234e36372423000a906bafae68844ebc6c42d09335aJeff Sharkey
235e36372423000a906bafae68844ebc6c42d09335aJeff Sharkey        uid_t uid = multiuser_get_uid(user, appid);
236e36372423000a906bafae68844ebc6c42d09335aJeff Sharkey        if (make_user_data(to_uuid, package_name, uid, user, seinfo) != 0) {
237e36372423000a906bafae68844ebc6c42d09335aJeff Sharkey            LOG(ERROR) << "Failed to create package target " << to;
238e36372423000a906bafae68844ebc6c42d09335aJeff Sharkey            goto fail;
239e36372423000a906bafae68844ebc6c42d09335aJeff Sharkey        }
240e36372423000a906bafae68844ebc6c42d09335aJeff Sharkey
241e36372423000a906bafae68844ebc6c42d09335aJeff Sharkey        char *argv[] = {
242e36372423000a906bafae68844ebc6c42d09335aJeff Sharkey            (char*) kCpPath,
243e36372423000a906bafae68844ebc6c42d09335aJeff Sharkey            (char*) "-F", /* delete any existing destination file first (--remove-destination) */
244e36372423000a906bafae68844ebc6c42d09335aJeff Sharkey            (char*) "-p", /* preserve timestamps, ownership, and permissions */
245e36372423000a906bafae68844ebc6c42d09335aJeff Sharkey            (char*) "-R", /* recurse into subdirectories (DEST must be a directory) */
246e36372423000a906bafae68844ebc6c42d09335aJeff Sharkey            (char*) "-P", /* Do not follow symlinks [default] */
247e36372423000a906bafae68844ebc6c42d09335aJeff Sharkey            (char*) "-d", /* don't dereference symlinks */
248e36372423000a906bafae68844ebc6c42d09335aJeff Sharkey            (char*) from.c_str(),
249d792118c493806eeb24a8203f508e6e18fe93bd7Jeff Sharkey            (char*) to_parent.c_str()
250e36372423000a906bafae68844ebc6c42d09335aJeff Sharkey        };
251e36372423000a906bafae68844ebc6c42d09335aJeff Sharkey
252e36372423000a906bafae68844ebc6c42d09335aJeff Sharkey        LOG(DEBUG) << "Copying " << from << " to " << to;
253e36372423000a906bafae68844ebc6c42d09335aJeff Sharkey        int rc = android_fork_execvp(ARRAY_SIZE(argv), argv, NULL, false, true);
254e36372423000a906bafae68844ebc6c42d09335aJeff Sharkey
255e36372423000a906bafae68844ebc6c42d09335aJeff Sharkey        if (rc != 0) {
256e36372423000a906bafae68844ebc6c42d09335aJeff Sharkey            LOG(ERROR) << "Failed copying " << from << " to " << to
257e36372423000a906bafae68844ebc6c42d09335aJeff Sharkey                    << ": status " << rc;
258e36372423000a906bafae68844ebc6c42d09335aJeff Sharkey            goto fail;
259e36372423000a906bafae68844ebc6c42d09335aJeff Sharkey        }
260a2307aefd06f1310660ef1d35ce01bcfc72c9633Jeff Sharkey    }
261e36372423000a906bafae68844ebc6c42d09335aJeff Sharkey
262a2307aefd06f1310660ef1d35ce01bcfc72c9633Jeff Sharkey    if (restorecon_data(to_uuid, package_name, seinfo, multiuser_get_uid(0, appid)) != 0) {
263a2307aefd06f1310660ef1d35ce01bcfc72c9633Jeff Sharkey        LOG(ERROR) << "Failed to restorecon";
264a2307aefd06f1310660ef1d35ce01bcfc72c9633Jeff Sharkey        goto fail;
265e36372423000a906bafae68844ebc6c42d09335aJeff Sharkey    }
266e36372423000a906bafae68844ebc6c42d09335aJeff Sharkey
26731f08986f83fa6f2dcf55523b2cf706460aeed7cJeff Sharkey    // We let the framework scan the new location and persist that before
26831f08986f83fa6f2dcf55523b2cf706460aeed7cJeff Sharkey    // deleting the data in the old location; this ordering ensures that
26931f08986f83fa6f2dcf55523b2cf706460aeed7cJeff Sharkey    // we can recover from things like battery pulls.
270e36372423000a906bafae68844ebc6c42d09335aJeff Sharkey    return 0;
271e36372423000a906bafae68844ebc6c42d09335aJeff Sharkey
272e36372423000a906bafae68844ebc6c42d09335aJeff Sharkeyfail:
273e36372423000a906bafae68844ebc6c42d09335aJeff Sharkey    // Nuke everything we might have already copied
274d792118c493806eeb24a8203f508e6e18fe93bd7Jeff Sharkey    {
275d792118c493806eeb24a8203f508e6e18fe93bd7Jeff Sharkey        std::string to(create_data_app_package_path(to_uuid, data_app_name));
276d792118c493806eeb24a8203f508e6e18fe93bd7Jeff Sharkey        if (delete_dir_contents(to.c_str(), 1, NULL) != 0) {
277d792118c493806eeb24a8203f508e6e18fe93bd7Jeff Sharkey            LOG(WARNING) << "Failed to rollback " << to;
278d792118c493806eeb24a8203f508e6e18fe93bd7Jeff Sharkey        }
279d792118c493806eeb24a8203f508e6e18fe93bd7Jeff Sharkey    }
280e36372423000a906bafae68844ebc6c42d09335aJeff Sharkey    for (auto user : users) {
281d792118c493806eeb24a8203f508e6e18fe93bd7Jeff Sharkey        std::string to(create_data_user_package_path(to_uuid, user, package_name));
282e36372423000a906bafae68844ebc6c42d09335aJeff Sharkey        if (delete_dir_contents(to.c_str(), 1, NULL) != 0) {
283e36372423000a906bafae68844ebc6c42d09335aJeff Sharkey            LOG(WARNING) << "Failed to rollback " << to;
284e36372423000a906bafae68844ebc6c42d09335aJeff Sharkey        }
285e36372423000a906bafae68844ebc6c42d09335aJeff Sharkey    }
286e36372423000a906bafae68844ebc6c42d09335aJeff Sharkey    return -1;
287e36372423000a906bafae68844ebc6c42d09335aJeff Sharkey}
288e36372423000a906bafae68844ebc6c42d09335aJeff Sharkey
2897c8bec01790087748ec7afa69a31789828b751f9Robin Leeint make_user_config(userid_t userid)
29094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood{
291095c763dd9aa26a206d10ab7c1d7e1c569298fb3Robin Lee    if (ensure_config_user_dirs(userid) == -1) {
29294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        return -1;
29394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    }
294095c763dd9aa26a206d10ab7c1d7e1c569298fb3Robin Lee
295095c763dd9aa26a206d10ab7c1d7e1c569298fb3Robin Lee    return 0;
296095c763dd9aa26a206d10ab7c1d7e1c569298fb3Robin Lee}
297095c763dd9aa26a206d10ab7c1d7e1c569298fb3Robin Lee
29841ea424413c0381ef2aa15fc5bd5d4b88abd23c4Jeff Sharkeyint delete_user(const char *uuid, userid_t userid)
299095c763dd9aa26a206d10ab7c1d7e1c569298fb3Robin Lee{
300095c763dd9aa26a206d10ab7c1d7e1c569298fb3Robin Lee    int status = 0;
301095c763dd9aa26a206d10ab7c1d7e1c569298fb3Robin Lee
30241ea424413c0381ef2aa15fc5bd5d4b88abd23c4Jeff Sharkey    std::string data_path(create_data_user_path(uuid, userid));
30341ea424413c0381ef2aa15fc5bd5d4b88abd23c4Jeff Sharkey    if (delete_dir_contents(data_path.c_str(), 1, NULL) != 0) {
304095c763dd9aa26a206d10ab7c1d7e1c569298fb3Robin Lee        status = -1;
30594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    }
30694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
30741ea424413c0381ef2aa15fc5bd5d4b88abd23c4Jeff Sharkey    std::string media_path(create_data_media_path(uuid, userid));
30841ea424413c0381ef2aa15fc5bd5d4b88abd23c4Jeff Sharkey    if (delete_dir_contents(media_path.c_str(), 1, NULL) != 0) {
309095c763dd9aa26a206d10ab7c1d7e1c569298fb3Robin Lee        status = -1;
31094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    }
311095c763dd9aa26a206d10ab7c1d7e1c569298fb3Robin Lee
31241ea424413c0381ef2aa15fc5bd5d4b88abd23c4Jeff Sharkey    // Config paths only exist on internal storage
31341ea424413c0381ef2aa15fc5bd5d4b88abd23c4Jeff Sharkey    if (uuid == nullptr) {
31441ea424413c0381ef2aa15fc5bd5d4b88abd23c4Jeff Sharkey        char config_path[PATH_MAX];
31541ea424413c0381ef2aa15fc5bd5d4b88abd23c4Jeff Sharkey        if ((create_user_config_path(config_path, userid) != 0)
31641ea424413c0381ef2aa15fc5bd5d4b88abd23c4Jeff Sharkey                || (delete_dir_contents(config_path, 1, NULL) != 0)) {
31741ea424413c0381ef2aa15fc5bd5d4b88abd23c4Jeff Sharkey            status = -1;
31841ea424413c0381ef2aa15fc5bd5d4b88abd23c4Jeff Sharkey        }
31994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    }
32094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
321095c763dd9aa26a206d10ab7c1d7e1c569298fb3Robin Lee    return status;
32294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood}
32394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
324c03de09173f98506e73e7cf7df21fe11795d4b24Jeff Sharkeyint delete_cache(const char *uuid, const char *pkgname, userid_t userid)
32594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood{
326c03de09173f98506e73e7cf7df21fe11795d4b24Jeff Sharkey    std::string _cachedir(
327d792118c493806eeb24a8203f508e6e18fe93bd7Jeff Sharkey            create_data_user_package_path(uuid, userid, pkgname) + CACHE_DIR_POSTFIX);
328c03de09173f98506e73e7cf7df21fe11795d4b24Jeff Sharkey    const char* cachedir = _cachedir.c_str();
32994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
330c796b681e52fbb792da9a5b4f30e935cc927c1d7Jeff Sharkey    /* delete contents, not the directory, no exceptions */
3313aee2c5c749dc2589f001b26fae1ec958ec89524Narayan Kamath    return delete_dir_contents(cachedir, 0, NULL);
33294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood}
33394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
334c03de09173f98506e73e7cf7df21fe11795d4b24Jeff Sharkeyint delete_code_cache(const char *uuid, const char *pkgname, userid_t userid)
335c796b681e52fbb792da9a5b4f30e935cc927c1d7Jeff Sharkey{
336c03de09173f98506e73e7cf7df21fe11795d4b24Jeff Sharkey    std::string _codecachedir(
337a2ccb9e43db52a18d088c1d440676335cb4b9e68Daichi Hirono            create_data_user_package_path(uuid, userid, pkgname) + CODE_CACHE_DIR_POSTFIX);
338c03de09173f98506e73e7cf7df21fe11795d4b24Jeff Sharkey    const char* codecachedir = _codecachedir.c_str();
339c796b681e52fbb792da9a5b4f30e935cc927c1d7Jeff Sharkey
340c03de09173f98506e73e7cf7df21fe11795d4b24Jeff Sharkey    struct stat s;
341c796b681e52fbb792da9a5b4f30e935cc927c1d7Jeff Sharkey
342770180a4dd86f8bda6af2e6db4676e99a5bb1548Jeff Sharkey    /* it's okay if code cache is missing */
343770180a4dd86f8bda6af2e6db4676e99a5bb1548Jeff Sharkey    if (lstat(codecachedir, &s) == -1 && errno == ENOENT) {
344770180a4dd86f8bda6af2e6db4676e99a5bb1548Jeff Sharkey        return 0;
345770180a4dd86f8bda6af2e6db4676e99a5bb1548Jeff Sharkey    }
346770180a4dd86f8bda6af2e6db4676e99a5bb1548Jeff Sharkey
347c796b681e52fbb792da9a5b4f30e935cc927c1d7Jeff Sharkey    /* delete contents, not the directory, no exceptions */
348c796b681e52fbb792da9a5b4f30e935cc927c1d7Jeff Sharkey    return delete_dir_contents(codecachedir, 0, NULL);
349c796b681e52fbb792da9a5b4f30e935cc927c1d7Jeff Sharkey}
350c796b681e52fbb792da9a5b4f30e935cc927c1d7Jeff Sharkey
35194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood/* Try to ensure free_size bytes of storage are available.
35294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood * Returns 0 on success.
35394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood * This is rather simple-minded because doing a full LRU would
35494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood * be potentially memory-intensive, and without atime it would
35594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood * also require that apps constantly modify file metadata even
35694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood * when just reading from the cache, which is pretty awful.
35794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood */
35841ea424413c0381ef2aa15fc5bd5d4b88abd23c4Jeff Sharkeyint free_cache(const char *uuid, int64_t free_size)
35994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood{
36094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    cache_t* cache;
36194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    int64_t avail;
36294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    DIR *d;
36394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    struct dirent *de;
36494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    char tmpdir[PATH_MAX];
36594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    char *dirpos;
36694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
36741ea424413c0381ef2aa15fc5bd5d4b88abd23c4Jeff Sharkey    std::string data_path(create_data_path(uuid));
36841ea424413c0381ef2aa15fc5bd5d4b88abd23c4Jeff Sharkey
36941ea424413c0381ef2aa15fc5bd5d4b88abd23c4Jeff Sharkey    avail = data_disk_free(data_path);
37094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    if (avail < 0) return -1;
37194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
37294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    ALOGI("free_cache(%" PRId64 ") avail %" PRId64 "\n", free_size, avail);
37394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    if (avail >= free_size) return 0;
37494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
37594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    cache = start_cache_collection();
37694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
37741ea424413c0381ef2aa15fc5bd5d4b88abd23c4Jeff Sharkey    // Special case for owner on internal storage
37841ea424413c0381ef2aa15fc5bd5d4b88abd23c4Jeff Sharkey    if (uuid == nullptr) {
37941ea424413c0381ef2aa15fc5bd5d4b88abd23c4Jeff Sharkey        std::string _tmpdir(create_data_user_path(nullptr, 0));
38041ea424413c0381ef2aa15fc5bd5d4b88abd23c4Jeff Sharkey        add_cache_files(cache, _tmpdir.c_str(), "cache");
38194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    }
38294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
38394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    // Search for other users and add any cache files from them.
38441ea424413c0381ef2aa15fc5bd5d4b88abd23c4Jeff Sharkey    std::string _tmpdir(create_data_path(uuid) + "/" + SECONDARY_USER_PREFIX);
38541ea424413c0381ef2aa15fc5bd5d4b88abd23c4Jeff Sharkey    strcpy(tmpdir, _tmpdir.c_str());
38641ea424413c0381ef2aa15fc5bd5d4b88abd23c4Jeff Sharkey
38794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    dirpos = tmpdir + strlen(tmpdir);
38894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    d = opendir(tmpdir);
38994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    if (d != NULL) {
39094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        while ((de = readdir(d))) {
39194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood            if (de->d_type == DT_DIR) {
39294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood                const char *name = de->d_name;
39394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood                    /* always skip "." and ".." */
39494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood                if (name[0] == '.') {
39594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood                    if (name[1] == 0) continue;
39694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood                    if ((name[1] == '.') && (name[2] == 0)) continue;
39794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood                }
39894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood                if ((strlen(name)+(dirpos-tmpdir)) < (sizeof(tmpdir)-1)) {
39994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood                    strcpy(dirpos, name);
40094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood                    //ALOGI("adding cache files from %s\n", tmpdir);
40194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood                    add_cache_files(cache, tmpdir, "cache");
40294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood                } else {
40394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood                    ALOGW("Path exceeds limit: %s%s", tmpdir, name);
40494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood                }
40594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood            }
40694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        }
40794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        closedir(d);
40894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    }
40994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
41094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    // Collect cache files on external storage for all users (if it is mounted as part
41194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    // of the internal storage).
41294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    strcpy(tmpdir, android_media_dir.path);
41394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    dirpos = tmpdir + strlen(tmpdir);
41494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    d = opendir(tmpdir);
41594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    if (d != NULL) {
41694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        while ((de = readdir(d))) {
41794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood            if (de->d_type == DT_DIR) {
41894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood                const char *name = de->d_name;
41994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood                    /* skip any dir that doesn't start with a number, so not a user */
42094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood                if (name[0] < '0' || name[0] > '9') {
42194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood                    continue;
42294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood                }
42394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood                if ((strlen(name)+(dirpos-tmpdir)) < (sizeof(tmpdir)-1)) {
42494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood                    strcpy(dirpos, name);
42594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood                    if (lookup_media_dir(tmpdir, "Android") == 0
42694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood                            && lookup_media_dir(tmpdir, "data") == 0) {
42794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood                        //ALOGI("adding cache files from %s\n", tmpdir);
42894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood                        add_cache_files(cache, tmpdir, "cache");
42994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood                    }
43094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood                } else {
43194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood                    ALOGW("Path exceeds limit: %s%s", tmpdir, name);
43294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood                }
43394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood            }
43494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        }
43594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        closedir(d);
43694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    }
43794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
43841ea424413c0381ef2aa15fc5bd5d4b88abd23c4Jeff Sharkey    clear_cache_files(data_path, cache, free_size);
43994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    finish_cache_collection(cache);
44094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
44141ea424413c0381ef2aa15fc5bd5d4b88abd23c4Jeff Sharkey    return data_disk_free(data_path) >= free_size ? 0 : -1;
44294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood}
44394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
4441b4003207750ea8fe8c7b03eb32d80f1df83979eNarayan Kamathint move_dex(const char *src, const char *dst, const char *instruction_set)
44594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood{
44694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    char src_dex[PKG_PATH_MAX];
44794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    char dst_dex[PKG_PATH_MAX];
44894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
449770180a4dd86f8bda6af2e6db4676e99a5bb1548Jeff Sharkey    if (validate_apk_path(src)) {
450770180a4dd86f8bda6af2e6db4676e99a5bb1548Jeff Sharkey        ALOGE("invalid apk path '%s' (bad prefix)\n", src);
451770180a4dd86f8bda6af2e6db4676e99a5bb1548Jeff Sharkey        return -1;
452770180a4dd86f8bda6af2e6db4676e99a5bb1548Jeff Sharkey    }
453770180a4dd86f8bda6af2e6db4676e99a5bb1548Jeff Sharkey    if (validate_apk_path(dst)) {
454770180a4dd86f8bda6af2e6db4676e99a5bb1548Jeff Sharkey        ALOGE("invalid apk path '%s' (bad prefix)\n", dst);
455770180a4dd86f8bda6af2e6db4676e99a5bb1548Jeff Sharkey        return -1;
456770180a4dd86f8bda6af2e6db4676e99a5bb1548Jeff Sharkey    }
45794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
4581b4003207750ea8fe8c7b03eb32d80f1df83979eNarayan Kamath    if (create_cache_path(src_dex, src, instruction_set)) return -1;
4591b4003207750ea8fe8c7b03eb32d80f1df83979eNarayan Kamath    if (create_cache_path(dst_dex, dst, instruction_set)) return -1;
46094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
46194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    ALOGV("move %s -> %s\n", src_dex, dst_dex);
46294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    if (rename(src_dex, dst_dex) < 0) {
46394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        ALOGE("Couldn't move %s: %s\n", src_dex, strerror(errno));
46494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        return -1;
46594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    } else {
46694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        return 0;
46794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    }
46894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood}
46994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
4701b4003207750ea8fe8c7b03eb32d80f1df83979eNarayan Kamathint rm_dex(const char *path, const char *instruction_set)
47194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood{
47294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    char dex_path[PKG_PATH_MAX];
47394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
474770180a4dd86f8bda6af2e6db4676e99a5bb1548Jeff Sharkey    if (validate_apk_path(path) && validate_system_app_path(path)) {
475770180a4dd86f8bda6af2e6db4676e99a5bb1548Jeff Sharkey        ALOGE("invalid apk path '%s' (bad prefix)\n", path);
476770180a4dd86f8bda6af2e6db4676e99a5bb1548Jeff Sharkey        return -1;
477770180a4dd86f8bda6af2e6db4676e99a5bb1548Jeff Sharkey    }
478770180a4dd86f8bda6af2e6db4676e99a5bb1548Jeff Sharkey
4791b4003207750ea8fe8c7b03eb32d80f1df83979eNarayan Kamath    if (create_cache_path(dex_path, path, instruction_set)) return -1;
48094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
48194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    ALOGV("unlink %s\n", dex_path);
48294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    if (unlink(dex_path) < 0) {
483770180a4dd86f8bda6af2e6db4676e99a5bb1548Jeff Sharkey        if (errno != ENOENT) {
484770180a4dd86f8bda6af2e6db4676e99a5bb1548Jeff Sharkey            ALOGE("Couldn't unlink %s: %s\n", dex_path, strerror(errno));
485770180a4dd86f8bda6af2e6db4676e99a5bb1548Jeff Sharkey        }
48694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        return -1;
48794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    } else {
48894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        return 0;
48994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    }
49094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood}
49194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
492d792118c493806eeb24a8203f508e6e18fe93bd7Jeff Sharkeyint get_size(const char *uuid, const char *pkgname, int userid, const char *apkpath,
4938b41780d73930b37b6254cc1dac5607c843839c0Dianne Hackborn             const char *libdirpath, const char *fwdlock_apkpath, const char *asecpath,
4941b4003207750ea8fe8c7b03eb32d80f1df83979eNarayan Kamath             const char *instruction_set, int64_t *_codesize, int64_t *_datasize,
4951b4003207750ea8fe8c7b03eb32d80f1df83979eNarayan Kamath             int64_t *_cachesize, int64_t* _asecsize)
49694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood{
49794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    DIR *d;
49894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    int dfd;
49994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    struct dirent *de;
50094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    struct stat s;
50194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    char path[PKG_PATH_MAX];
50294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
50394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    int64_t codesize = 0;
50494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    int64_t datasize = 0;
50594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    int64_t cachesize = 0;
50694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    int64_t asecsize = 0;
50794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
508d792118c493806eeb24a8203f508e6e18fe93bd7Jeff Sharkey    /* count the source apk as code -- but only if it's not
509d792118c493806eeb24a8203f508e6e18fe93bd7Jeff Sharkey     * on the /system partition and its not on the sdcard. */
51094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    if (validate_system_app_path(apkpath) &&
51194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood            strncmp(apkpath, android_asec_dir.path, android_asec_dir.len) != 0) {
51294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        if (stat(apkpath, &s) == 0) {
51394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood            codesize += stat_size(&s);
514d792118c493806eeb24a8203f508e6e18fe93bd7Jeff Sharkey            if (S_ISDIR(s.st_mode)) {
515d792118c493806eeb24a8203f508e6e18fe93bd7Jeff Sharkey                d = opendir(apkpath);
516d792118c493806eeb24a8203f508e6e18fe93bd7Jeff Sharkey                if (d != NULL) {
517d792118c493806eeb24a8203f508e6e18fe93bd7Jeff Sharkey                    dfd = dirfd(d);
518d792118c493806eeb24a8203f508e6e18fe93bd7Jeff Sharkey                    codesize += calculate_dir_size(dfd);
519d792118c493806eeb24a8203f508e6e18fe93bd7Jeff Sharkey                    closedir(d);
520d792118c493806eeb24a8203f508e6e18fe93bd7Jeff Sharkey                }
521d792118c493806eeb24a8203f508e6e18fe93bd7Jeff Sharkey            }
52294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        }
52394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    }
524d792118c493806eeb24a8203f508e6e18fe93bd7Jeff Sharkey
525d792118c493806eeb24a8203f508e6e18fe93bd7Jeff Sharkey    /* count the forward locked apk as code if it is given */
52694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    if (fwdlock_apkpath != NULL && fwdlock_apkpath[0] != '!') {
52794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        if (stat(fwdlock_apkpath, &s) == 0) {
52894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood            codesize += stat_size(&s);
52994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        }
53094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    }
531d792118c493806eeb24a8203f508e6e18fe93bd7Jeff Sharkey
532d792118c493806eeb24a8203f508e6e18fe93bd7Jeff Sharkey    /* count the cached dexfile as code */
5331b4003207750ea8fe8c7b03eb32d80f1df83979eNarayan Kamath    if (!create_cache_path(path, apkpath, instruction_set)) {
53494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        if (stat(path, &s) == 0) {
53594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood            codesize += stat_size(&s);
53694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        }
53794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    }
53894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
539d792118c493806eeb24a8203f508e6e18fe93bd7Jeff Sharkey    /* add in size of any libraries */
5408b41780d73930b37b6254cc1dac5607c843839c0Dianne Hackborn    if (libdirpath != NULL && libdirpath[0] != '!') {
5418b41780d73930b37b6254cc1dac5607c843839c0Dianne Hackborn        d = opendir(libdirpath);
54294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        if (d != NULL) {
54394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood            dfd = dirfd(d);
54494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood            codesize += calculate_dir_size(dfd);
54594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood            closedir(d);
54694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        }
54794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    }
54894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
549d792118c493806eeb24a8203f508e6e18fe93bd7Jeff Sharkey    /* compute asec size if it is given */
55094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    if (asecpath != NULL && asecpath[0] != '!') {
55194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        if (stat(asecpath, &s) == 0) {
55294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood            asecsize += stat_size(&s);
55394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        }
55494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    }
55594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
556d792118c493806eeb24a8203f508e6e18fe93bd7Jeff Sharkey    std::vector<userid_t> users;
557d792118c493806eeb24a8203f508e6e18fe93bd7Jeff Sharkey    if (userid == -1) {
558d792118c493806eeb24a8203f508e6e18fe93bd7Jeff Sharkey        users = get_known_users(uuid);
559d792118c493806eeb24a8203f508e6e18fe93bd7Jeff Sharkey    } else {
560d792118c493806eeb24a8203f508e6e18fe93bd7Jeff Sharkey        users.push_back(userid);
56194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    }
56294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
563d792118c493806eeb24a8203f508e6e18fe93bd7Jeff Sharkey    for (auto user : users) {
564d792118c493806eeb24a8203f508e6e18fe93bd7Jeff Sharkey        std::string _pkgdir(create_data_user_package_path(uuid, user, pkgname));
565d792118c493806eeb24a8203f508e6e18fe93bd7Jeff Sharkey        const char* pkgdir = _pkgdir.c_str();
56694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
567d792118c493806eeb24a8203f508e6e18fe93bd7Jeff Sharkey        d = opendir(pkgdir);
568d792118c493806eeb24a8203f508e6e18fe93bd7Jeff Sharkey        if (d == NULL) {
569d792118c493806eeb24a8203f508e6e18fe93bd7Jeff Sharkey            PLOG(WARNING) << "Failed to open " << pkgdir;
570d792118c493806eeb24a8203f508e6e18fe93bd7Jeff Sharkey            continue;
571d792118c493806eeb24a8203f508e6e18fe93bd7Jeff Sharkey        }
572d792118c493806eeb24a8203f508e6e18fe93bd7Jeff Sharkey        dfd = dirfd(d);
573d792118c493806eeb24a8203f508e6e18fe93bd7Jeff Sharkey
574d792118c493806eeb24a8203f508e6e18fe93bd7Jeff Sharkey        /* most stuff in the pkgdir is data, except for the "cache"
575d792118c493806eeb24a8203f508e6e18fe93bd7Jeff Sharkey         * directory and below, which is cache, and the "lib" directory
576d792118c493806eeb24a8203f508e6e18fe93bd7Jeff Sharkey         * and below, which is code...
577d792118c493806eeb24a8203f508e6e18fe93bd7Jeff Sharkey         */
578d792118c493806eeb24a8203f508e6e18fe93bd7Jeff Sharkey        while ((de = readdir(d))) {
579d792118c493806eeb24a8203f508e6e18fe93bd7Jeff Sharkey            const char *name = de->d_name;
580d792118c493806eeb24a8203f508e6e18fe93bd7Jeff Sharkey
581d792118c493806eeb24a8203f508e6e18fe93bd7Jeff Sharkey            if (de->d_type == DT_DIR) {
582d792118c493806eeb24a8203f508e6e18fe93bd7Jeff Sharkey                int subfd;
583d792118c493806eeb24a8203f508e6e18fe93bd7Jeff Sharkey                int64_t statsize = 0;
584d792118c493806eeb24a8203f508e6e18fe93bd7Jeff Sharkey                int64_t dirsize = 0;
585d792118c493806eeb24a8203f508e6e18fe93bd7Jeff Sharkey                    /* always skip "." and ".." */
586d792118c493806eeb24a8203f508e6e18fe93bd7Jeff Sharkey                if (name[0] == '.') {
587d792118c493806eeb24a8203f508e6e18fe93bd7Jeff Sharkey                    if (name[1] == 0) continue;
588d792118c493806eeb24a8203f508e6e18fe93bd7Jeff Sharkey                    if ((name[1] == '.') && (name[2] == 0)) continue;
589d792118c493806eeb24a8203f508e6e18fe93bd7Jeff Sharkey                }
590d792118c493806eeb24a8203f508e6e18fe93bd7Jeff Sharkey                if (fstatat(dfd, name, &s, AT_SYMLINK_NOFOLLOW) == 0) {
591d792118c493806eeb24a8203f508e6e18fe93bd7Jeff Sharkey                    statsize = stat_size(&s);
592d792118c493806eeb24a8203f508e6e18fe93bd7Jeff Sharkey                }
593d792118c493806eeb24a8203f508e6e18fe93bd7Jeff Sharkey                subfd = openat(dfd, name, O_RDONLY | O_DIRECTORY);
594d792118c493806eeb24a8203f508e6e18fe93bd7Jeff Sharkey                if (subfd >= 0) {
595d792118c493806eeb24a8203f508e6e18fe93bd7Jeff Sharkey                    dirsize = calculate_dir_size(subfd);
596d792118c493806eeb24a8203f508e6e18fe93bd7Jeff Sharkey                }
597d792118c493806eeb24a8203f508e6e18fe93bd7Jeff Sharkey                if(!strcmp(name,"lib")) {
598d792118c493806eeb24a8203f508e6e18fe93bd7Jeff Sharkey                    codesize += dirsize + statsize;
599d792118c493806eeb24a8203f508e6e18fe93bd7Jeff Sharkey                } else if(!strcmp(name,"cache")) {
600d792118c493806eeb24a8203f508e6e18fe93bd7Jeff Sharkey                    cachesize += dirsize + statsize;
601d792118c493806eeb24a8203f508e6e18fe93bd7Jeff Sharkey                } else {
602d792118c493806eeb24a8203f508e6e18fe93bd7Jeff Sharkey                    datasize += dirsize + statsize;
603d792118c493806eeb24a8203f508e6e18fe93bd7Jeff Sharkey                }
604d792118c493806eeb24a8203f508e6e18fe93bd7Jeff Sharkey            } else if (de->d_type == DT_LNK && !strcmp(name,"lib")) {
605d792118c493806eeb24a8203f508e6e18fe93bd7Jeff Sharkey                // This is the symbolic link to the application's library
606d792118c493806eeb24a8203f508e6e18fe93bd7Jeff Sharkey                // code.  We'll count this as code instead of data, since
607d792118c493806eeb24a8203f508e6e18fe93bd7Jeff Sharkey                // it is not something that the app creates.
608d792118c493806eeb24a8203f508e6e18fe93bd7Jeff Sharkey                if (fstatat(dfd, name, &s, AT_SYMLINK_NOFOLLOW) == 0) {
609d792118c493806eeb24a8203f508e6e18fe93bd7Jeff Sharkey                    codesize += stat_size(&s);
610d792118c493806eeb24a8203f508e6e18fe93bd7Jeff Sharkey                }
61194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood            } else {
612d792118c493806eeb24a8203f508e6e18fe93bd7Jeff Sharkey                if (fstatat(dfd, name, &s, AT_SYMLINK_NOFOLLOW) == 0) {
613d792118c493806eeb24a8203f508e6e18fe93bd7Jeff Sharkey                    datasize += stat_size(&s);
614d792118c493806eeb24a8203f508e6e18fe93bd7Jeff Sharkey                }
61594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood            }
61694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        }
617d792118c493806eeb24a8203f508e6e18fe93bd7Jeff Sharkey        closedir(d);
61894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    }
61994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    *_codesize = codesize;
62094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    *_datasize = datasize;
62194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    *_cachesize = cachesize;
62294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    *_asecsize = asecsize;
62394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    return 0;
62494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood}
62594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
6261b4003207750ea8fe8c7b03eb32d80f1df83979eNarayan Kamathint create_cache_path(char path[PKG_PATH_MAX], const char *src, const char *instruction_set)
62794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood{
62894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    char *tmp;
62994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    int srclen;
63094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    int dstlen;
63194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
63294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    srclen = strlen(src);
63394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
63494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        /* demand that we are an absolute path */
63594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    if ((src == 0) || (src[0] != '/') || strstr(src,"..")) {
63694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        return -1;
63794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    }
63894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
63994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    if (srclen > PKG_PATH_MAX) {        // XXX: PKG_NAME_MAX?
64094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        return -1;
64194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    }
64294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
643d93707342a61e66bc3eb2145628158452f577f42Dave Allison    dstlen = srclen + strlen(DALVIK_CACHE_PREFIX) +
6441b4003207750ea8fe8c7b03eb32d80f1df83979eNarayan Kamath        strlen(instruction_set) +
6451b4003207750ea8fe8c7b03eb32d80f1df83979eNarayan Kamath        strlen(DALVIK_CACHE_POSTFIX) + 2;
646d93707342a61e66bc3eb2145628158452f577f42Dave Allison
64794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    if (dstlen > PKG_PATH_MAX) {
64894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        return -1;
64994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    }
65094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
6511b4003207750ea8fe8c7b03eb32d80f1df83979eNarayan Kamath    sprintf(path,"%s%s/%s%s",
65294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood            DALVIK_CACHE_PREFIX,
6531b4003207750ea8fe8c7b03eb32d80f1df83979eNarayan Kamath            instruction_set,
65494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood            src + 1, /* skip the leading / */
65594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood            DALVIK_CACHE_POSTFIX);
656d93707342a61e66bc3eb2145628158452f577f42Dave Allison
6571b4003207750ea8fe8c7b03eb32d80f1df83979eNarayan Kamath    for(tmp = path + strlen(DALVIK_CACHE_PREFIX) + strlen(instruction_set) + 1; *tmp; tmp++) {
65894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        if (*tmp == '/') {
65994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood            *tmp = '@';
66094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        }
66194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    }
66294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
66394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    return 0;
66494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood}
66594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
666b0d8d00b2916aef7b01ad42f6d441f5b46b7731aYevgeny Roubanstatic int split_count(const char *str)
667b0d8d00b2916aef7b01ad42f6d441f5b46b7731aYevgeny Rouban{
668b0d8d00b2916aef7b01ad42f6d441f5b46b7731aYevgeny Rouban  char *ctx;
669b0d8d00b2916aef7b01ad42f6d441f5b46b7731aYevgeny Rouban  int count = 0;
670b0d8d00b2916aef7b01ad42f6d441f5b46b7731aYevgeny Rouban  char buf[PROPERTY_VALUE_MAX];
671b0d8d00b2916aef7b01ad42f6d441f5b46b7731aYevgeny Rouban
672b0d8d00b2916aef7b01ad42f6d441f5b46b7731aYevgeny Rouban  strncpy(buf, str, sizeof(buf));
673b0d8d00b2916aef7b01ad42f6d441f5b46b7731aYevgeny Rouban  char *pBuf = buf;
674b0d8d00b2916aef7b01ad42f6d441f5b46b7731aYevgeny Rouban
675b0d8d00b2916aef7b01ad42f6d441f5b46b7731aYevgeny Rouban  while(strtok_r(pBuf, " ", &ctx) != NULL) {
676b0d8d00b2916aef7b01ad42f6d441f5b46b7731aYevgeny Rouban    count++;
677b0d8d00b2916aef7b01ad42f6d441f5b46b7731aYevgeny Rouban    pBuf = NULL;
678b0d8d00b2916aef7b01ad42f6d441f5b46b7731aYevgeny Rouban  }
679b0d8d00b2916aef7b01ad42f6d441f5b46b7731aYevgeny Rouban
680b0d8d00b2916aef7b01ad42f6d441f5b46b7731aYevgeny Rouban  return count;
681b0d8d00b2916aef7b01ad42f6d441f5b46b7731aYevgeny Rouban}
682b0d8d00b2916aef7b01ad42f6d441f5b46b7731aYevgeny Rouban
68314e084d39ac44e9d4d0a0143bf1f111011343d34neo.chaestatic int split(char *buf, const char **argv)
684b0d8d00b2916aef7b01ad42f6d441f5b46b7731aYevgeny Rouban{
685b0d8d00b2916aef7b01ad42f6d441f5b46b7731aYevgeny Rouban  char *ctx;
686b0d8d00b2916aef7b01ad42f6d441f5b46b7731aYevgeny Rouban  int count = 0;
687b0d8d00b2916aef7b01ad42f6d441f5b46b7731aYevgeny Rouban  char *tok;
688b0d8d00b2916aef7b01ad42f6d441f5b46b7731aYevgeny Rouban  char *pBuf = buf;
689b0d8d00b2916aef7b01ad42f6d441f5b46b7731aYevgeny Rouban
690b0d8d00b2916aef7b01ad42f6d441f5b46b7731aYevgeny Rouban  while((tok = strtok_r(pBuf, " ", &ctx)) != NULL) {
691b0d8d00b2916aef7b01ad42f6d441f5b46b7731aYevgeny Rouban    argv[count++] = tok;
692b0d8d00b2916aef7b01ad42f6d441f5b46b7731aYevgeny Rouban    pBuf = NULL;
693b0d8d00b2916aef7b01ad42f6d441f5b46b7731aYevgeny Rouban  }
694b0d8d00b2916aef7b01ad42f6d441f5b46b7731aYevgeny Rouban
695b0d8d00b2916aef7b01ad42f6d441f5b46b7731aYevgeny Rouban  return count;
696b0d8d00b2916aef7b01ad42f6d441f5b46b7731aYevgeny Rouban}
697b0d8d00b2916aef7b01ad42f6d441f5b46b7731aYevgeny Rouban
6987365a10689df23334d245b211ce272502ad20669Alex Lightstatic void run_patchoat(int input_fd, int oat_fd, const char* input_file_name,
69999d9fb15b4a1eb534261ae81b2cf25aec4447bd0Chih-Hung Hsieh    const char* output_file_name, const char *pkgname __unused, const char *instruction_set)
7007365a10689df23334d245b211ce272502ad20669Alex Light{
7017365a10689df23334d245b211ce272502ad20669Alex Light    static const int MAX_INT_LEN = 12;      // '-'+10dig+'\0' -OR- 0x+8dig
7028fc7315a67fdbf9b56cc6fa061f0773be2223a81Calin Juravle    static const unsigned int MAX_INSTRUCTION_SET_LEN = 7;
7037365a10689df23334d245b211ce272502ad20669Alex Light
7047365a10689df23334d245b211ce272502ad20669Alex Light    static const char* PATCHOAT_BIN = "/system/bin/patchoat";
7057365a10689df23334d245b211ce272502ad20669Alex Light    if (strlen(instruction_set) >= MAX_INSTRUCTION_SET_LEN) {
7067365a10689df23334d245b211ce272502ad20669Alex Light        ALOGE("Instruction set %s longer than max length of %d",
7077365a10689df23334d245b211ce272502ad20669Alex Light              instruction_set, MAX_INSTRUCTION_SET_LEN);
7087365a10689df23334d245b211ce272502ad20669Alex Light        return;
7097365a10689df23334d245b211ce272502ad20669Alex Light    }
7107365a10689df23334d245b211ce272502ad20669Alex Light
7117365a10689df23334d245b211ce272502ad20669Alex Light    /* input_file_name/input_fd should be the .odex/.oat file that is precompiled. I think*/
7127365a10689df23334d245b211ce272502ad20669Alex Light    char instruction_set_arg[strlen("--instruction-set=") + MAX_INSTRUCTION_SET_LEN];
7137365a10689df23334d245b211ce272502ad20669Alex Light    char output_oat_fd_arg[strlen("--output-oat-fd=") + MAX_INT_LEN];
7147365a10689df23334d245b211ce272502ad20669Alex Light    char input_oat_fd_arg[strlen("--input-oat-fd=") + MAX_INT_LEN];
7157365a10689df23334d245b211ce272502ad20669Alex Light    const char* patched_image_location_arg = "--patched-image-location=/system/framework/boot.art";
7167365a10689df23334d245b211ce272502ad20669Alex Light    // The caller has already gotten all the locks we need.
7177365a10689df23334d245b211ce272502ad20669Alex Light    const char* no_lock_arg = "--no-lock-output";
7187365a10689df23334d245b211ce272502ad20669Alex Light    sprintf(instruction_set_arg, "--instruction-set=%s", instruction_set);
7197365a10689df23334d245b211ce272502ad20669Alex Light    sprintf(output_oat_fd_arg, "--output-oat-fd=%d", oat_fd);
7207365a10689df23334d245b211ce272502ad20669Alex Light    sprintf(input_oat_fd_arg, "--input-oat-fd=%d", input_fd);
721a7915d437c3971943f82dfc2370fe7a5df522801Alex Light    ALOGV("Running %s isa=%s in-fd=%d (%s) out-fd=%d (%s)\n",
7227365a10689df23334d245b211ce272502ad20669Alex Light          PATCHOAT_BIN, instruction_set, input_fd, input_file_name, oat_fd, output_file_name);
7237365a10689df23334d245b211ce272502ad20669Alex Light
7247365a10689df23334d245b211ce272502ad20669Alex Light    /* patchoat, patched-image-location, no-lock, isa, input-fd, output-fd */
7257365a10689df23334d245b211ce272502ad20669Alex Light    char* argv[7];
7267365a10689df23334d245b211ce272502ad20669Alex Light    argv[0] = (char*) PATCHOAT_BIN;
7277365a10689df23334d245b211ce272502ad20669Alex Light    argv[1] = (char*) patched_image_location_arg;
7287365a10689df23334d245b211ce272502ad20669Alex Light    argv[2] = (char*) no_lock_arg;
7297365a10689df23334d245b211ce272502ad20669Alex Light    argv[3] = instruction_set_arg;
7307365a10689df23334d245b211ce272502ad20669Alex Light    argv[4] = output_oat_fd_arg;
7317365a10689df23334d245b211ce272502ad20669Alex Light    argv[5] = input_oat_fd_arg;
7327365a10689df23334d245b211ce272502ad20669Alex Light    argv[6] = NULL;
7337365a10689df23334d245b211ce272502ad20669Alex Light
7347365a10689df23334d245b211ce272502ad20669Alex Light    execv(PATCHOAT_BIN, (char* const *)argv);
7357365a10689df23334d245b211ce272502ad20669Alex Light    ALOGE("execv(%s) failed: %s\n", PATCHOAT_BIN, strerror(errno));
7367365a10689df23334d245b211ce272502ad20669Alex Light}
7377365a10689df23334d245b211ce272502ad20669Alex Light
7383822b8b79cf533ee8573794176838406c32a1c20Andreas Gampestatic bool check_boolean_property(const char* property_name, bool default_value = false) {
7393822b8b79cf533ee8573794176838406c32a1c20Andreas Gampe    char tmp_property_value[PROPERTY_VALUE_MAX];
7403822b8b79cf533ee8573794176838406c32a1c20Andreas Gampe    bool have_property = property_get(property_name, tmp_property_value, nullptr) > 0;
7413822b8b79cf533ee8573794176838406c32a1c20Andreas Gampe    if (!have_property) {
7423822b8b79cf533ee8573794176838406c32a1c20Andreas Gampe        return default_value;
7433822b8b79cf533ee8573794176838406c32a1c20Andreas Gampe    }
7443822b8b79cf533ee8573794176838406c32a1c20Andreas Gampe    return strcmp(tmp_property_value, "true") == 0;
7453822b8b79cf533ee8573794176838406c32a1c20Andreas Gampe}
7463822b8b79cf533ee8573794176838406c32a1c20Andreas Gampe
7471705fc44fb85c4232637f9f7189c3bdca98a63d5Brian Carlstromstatic void run_dex2oat(int zip_fd, int oat_fd, const char* input_file_name,
748e1c01353c4dc6058a384eea9853238d2a87040dbAndreas Gampe    const char* output_file_name, int swap_fd, const char *pkgname, const char *instruction_set,
74921948005f0294a64a42932b21a33ae75295dc3d9Andreas Gampe    bool vm_safe_mode, bool debuggable, bool post_bootcomplete)
7501705fc44fb85c4232637f9f7189c3bdca98a63d5Brian Carlstrom{
7518fc7315a67fdbf9b56cc6fa061f0773be2223a81Calin Juravle    static const unsigned int MAX_INSTRUCTION_SET_LEN = 7;
7528fc7315a67fdbf9b56cc6fa061f0773be2223a81Calin Juravle
7538fc7315a67fdbf9b56cc6fa061f0773be2223a81Calin Juravle    if (strlen(instruction_set) >= MAX_INSTRUCTION_SET_LEN) {
7548fc7315a67fdbf9b56cc6fa061f0773be2223a81Calin Juravle        ALOGE("Instruction set %s longer than max length of %d",
7558fc7315a67fdbf9b56cc6fa061f0773be2223a81Calin Juravle              instruction_set, MAX_INSTRUCTION_SET_LEN);
7568fc7315a67fdbf9b56cc6fa061f0773be2223a81Calin Juravle        return;
7578fc7315a67fdbf9b56cc6fa061f0773be2223a81Calin Juravle    }
7588fc7315a67fdbf9b56cc6fa061f0773be2223a81Calin Juravle
759e46a75a0f6007967cd0d161959af844772cdc330Brian Carlstrom    char prop_buf[PROPERTY_VALUE_MAX];
760e46a75a0f6007967cd0d161959af844772cdc330Brian Carlstrom    bool profiler = (property_get("dalvik.vm.profiler", prop_buf, "0") > 0) && (prop_buf[0] == '1');
761e46a75a0f6007967cd0d161959af844772cdc330Brian Carlstrom
762e46a75a0f6007967cd0d161959af844772cdc330Brian Carlstrom    char dex2oat_Xms_flag[PROPERTY_VALUE_MAX];
763e46a75a0f6007967cd0d161959af844772cdc330Brian Carlstrom    bool have_dex2oat_Xms_flag = property_get("dalvik.vm.dex2oat-Xms", dex2oat_Xms_flag, NULL) > 0;
764e46a75a0f6007967cd0d161959af844772cdc330Brian Carlstrom
765e46a75a0f6007967cd0d161959af844772cdc330Brian Carlstrom    char dex2oat_Xmx_flag[PROPERTY_VALUE_MAX];
766e46a75a0f6007967cd0d161959af844772cdc330Brian Carlstrom    bool have_dex2oat_Xmx_flag = property_get("dalvik.vm.dex2oat-Xmx", dex2oat_Xmx_flag, NULL) > 0;
767e46a75a0f6007967cd0d161959af844772cdc330Brian Carlstrom
768cf51ba1360ee13459830a0502b0d454d0145544fBrian Carlstrom    char dex2oat_compiler_filter_flag[PROPERTY_VALUE_MAX];
769cf51ba1360ee13459830a0502b0d454d0145544fBrian Carlstrom    bool have_dex2oat_compiler_filter_flag = property_get("dalvik.vm.dex2oat-filter",
770cf51ba1360ee13459830a0502b0d454d0145544fBrian Carlstrom                                                          dex2oat_compiler_filter_flag, NULL) > 0;
771cf51ba1360ee13459830a0502b0d454d0145544fBrian Carlstrom
7728d7af8b2418cc5e7e59746f0cb359a75ed0bdfd1Andreas Gampe    char dex2oat_threads_buf[PROPERTY_VALUE_MAX];
77321948005f0294a64a42932b21a33ae75295dc3d9Andreas Gampe    bool have_dex2oat_threads_flag = false;
77421948005f0294a64a42932b21a33ae75295dc3d9Andreas Gampe    if (!post_bootcomplete) {
77521948005f0294a64a42932b21a33ae75295dc3d9Andreas Gampe        have_dex2oat_threads_flag = property_get("dalvik.vm.boot-dex2oat-threads",
77621948005f0294a64a42932b21a33ae75295dc3d9Andreas Gampe                                                 dex2oat_threads_buf,
77721948005f0294a64a42932b21a33ae75295dc3d9Andreas Gampe                                                 NULL) > 0;
77821948005f0294a64a42932b21a33ae75295dc3d9Andreas Gampe        // If there's no boot property, fall back to the image property.
77921948005f0294a64a42932b21a33ae75295dc3d9Andreas Gampe        if (!have_dex2oat_threads_flag) {
78021948005f0294a64a42932b21a33ae75295dc3d9Andreas Gampe            have_dex2oat_threads_flag = property_get("dalvik.vm.image-dex2oat-threads",
78121948005f0294a64a42932b21a33ae75295dc3d9Andreas Gampe                                                     dex2oat_threads_buf,
78221948005f0294a64a42932b21a33ae75295dc3d9Andreas Gampe                                                     NULL) > 0;
78321948005f0294a64a42932b21a33ae75295dc3d9Andreas Gampe        }
78421948005f0294a64a42932b21a33ae75295dc3d9Andreas Gampe        // If there's neither, fall back to the default property.
78521948005f0294a64a42932b21a33ae75295dc3d9Andreas Gampe    }
78621948005f0294a64a42932b21a33ae75295dc3d9Andreas Gampe    if (!have_dex2oat_threads_flag) {
78721948005f0294a64a42932b21a33ae75295dc3d9Andreas Gampe        have_dex2oat_threads_flag = property_get("dalvik.vm.dex2oat-threads",
78821948005f0294a64a42932b21a33ae75295dc3d9Andreas Gampe                                                 dex2oat_threads_buf,
78921948005f0294a64a42932b21a33ae75295dc3d9Andreas Gampe                                                 NULL) > 0;
79021948005f0294a64a42932b21a33ae75295dc3d9Andreas Gampe    }
7918d7af8b2418cc5e7e59746f0cb359a75ed0bdfd1Andreas Gampe    char dex2oat_threads_arg[PROPERTY_VALUE_MAX + 2];
7928d7af8b2418cc5e7e59746f0cb359a75ed0bdfd1Andreas Gampe    if (have_dex2oat_threads_flag) {
7938d7af8b2418cc5e7e59746f0cb359a75ed0bdfd1Andreas Gampe        sprintf(dex2oat_threads_arg, "-j%s", dex2oat_threads_buf);
7948d7af8b2418cc5e7e59746f0cb359a75ed0bdfd1Andreas Gampe    }
7958d7af8b2418cc5e7e59746f0cb359a75ed0bdfd1Andreas Gampe
7968fc7315a67fdbf9b56cc6fa061f0773be2223a81Calin Juravle    char dex2oat_isa_features_key[PROPERTY_KEY_MAX];
7978fc7315a67fdbf9b56cc6fa061f0773be2223a81Calin Juravle    sprintf(dex2oat_isa_features_key, "dalvik.vm.isa.%s.features", instruction_set);
7988fc7315a67fdbf9b56cc6fa061f0773be2223a81Calin Juravle    char dex2oat_isa_features[PROPERTY_VALUE_MAX];
7998fc7315a67fdbf9b56cc6fa061f0773be2223a81Calin Juravle    bool have_dex2oat_isa_features = property_get(dex2oat_isa_features_key,
8008fc7315a67fdbf9b56cc6fa061f0773be2223a81Calin Juravle                                                  dex2oat_isa_features, NULL) > 0;
8018fc7315a67fdbf9b56cc6fa061f0773be2223a81Calin Juravle
80216a95b267ac6aac75453f65f1bc382ce65c0741eIan Rogers    char dex2oat_isa_variant_key[PROPERTY_KEY_MAX];
80316a95b267ac6aac75453f65f1bc382ce65c0741eIan Rogers    sprintf(dex2oat_isa_variant_key, "dalvik.vm.isa.%s.variant", instruction_set);
80416a95b267ac6aac75453f65f1bc382ce65c0741eIan Rogers    char dex2oat_isa_variant[PROPERTY_VALUE_MAX];
80516a95b267ac6aac75453f65f1bc382ce65c0741eIan Rogers    bool have_dex2oat_isa_variant = property_get(dex2oat_isa_variant_key,
80616a95b267ac6aac75453f65f1bc382ce65c0741eIan Rogers                                                 dex2oat_isa_variant, NULL) > 0;
80716a95b267ac6aac75453f65f1bc382ce65c0741eIan Rogers
80814e084d39ac44e9d4d0a0143bf1f111011343d34neo.chae    const char *dex2oat_norelocation = "-Xnorelocate";
80914e084d39ac44e9d4d0a0143bf1f111011343d34neo.chae    bool have_dex2oat_relocation_skip_flag = false;
81014e084d39ac44e9d4d0a0143bf1f111011343d34neo.chae
8110ae8e39ebcc26836ba55a5ee4481825a0f473a9eBrian Carlstrom    char dex2oat_flags[PROPERTY_VALUE_MAX];
812b0d8d00b2916aef7b01ad42f6d441f5b46b7731aYevgeny Rouban    int dex2oat_flags_count = property_get("dalvik.vm.dex2oat-flags",
813b0d8d00b2916aef7b01ad42f6d441f5b46b7731aYevgeny Rouban                                 dex2oat_flags, NULL) <= 0 ? 0 : split_count(dex2oat_flags);
8140ae8e39ebcc26836ba55a5ee4481825a0f473a9eBrian Carlstrom    ALOGV("dalvik.vm.dex2oat-flags=%s\n", dex2oat_flags);
8150ae8e39ebcc26836ba55a5ee4481825a0f473a9eBrian Carlstrom
816538998f204d1e542e235de9e7ce18ef4dc68c9ccBrian Carlstrom    // If we booting without the real /data, don't spend time compiling.
817538998f204d1e542e235de9e7ce18ef4dc68c9ccBrian Carlstrom    char vold_decrypt[PROPERTY_VALUE_MAX];
818538998f204d1e542e235de9e7ce18ef4dc68c9ccBrian Carlstrom    bool have_vold_decrypt = property_get("vold.decrypt", vold_decrypt, "") > 0;
819538998f204d1e542e235de9e7ce18ef4dc68c9ccBrian Carlstrom    bool skip_compilation = (have_vold_decrypt &&
820538998f204d1e542e235de9e7ce18ef4dc68c9ccBrian Carlstrom                             (strcmp(vold_decrypt, "trigger_restart_min_framework") == 0 ||
821538998f204d1e542e235de9e7ce18ef4dc68c9ccBrian Carlstrom                             (strcmp(vold_decrypt, "1") == 0)));
822538998f204d1e542e235de9e7ce18ef4dc68c9ccBrian Carlstrom
8233822b8b79cf533ee8573794176838406c32a1c20Andreas Gampe    bool use_jit = check_boolean_property("debug.usejit");
824528c8ddc60df7b3d291b389117e4db878a20ad48David Srbecky    bool generate_debug_info = check_boolean_property("debug.generate-debug-info");
825d4a7b459f4f383988440c0512513b321ce03fc22Mathieu Chartier
8261705fc44fb85c4232637f9f7189c3bdca98a63d5Brian Carlstrom    static const char* DEX2OAT_BIN = "/system/bin/dex2oat";
82753e0776d967324e2908e3be56b80cddb2c9d9e03Brian Carlstrom
82853e0776d967324e2908e3be56b80cddb2c9d9e03Brian Carlstrom    static const char* RUNTIME_ARG = "--runtime-arg";
82953e0776d967324e2908e3be56b80cddb2c9d9e03Brian Carlstrom
8301705fc44fb85c4232637f9f7189c3bdca98a63d5Brian Carlstrom    static const int MAX_INT_LEN = 12;      // '-'+10dig+'\0' -OR- 0x+8dig
8311b4003207750ea8fe8c7b03eb32d80f1df83979eNarayan Kamath
8321705fc44fb85c4232637f9f7189c3bdca98a63d5Brian Carlstrom    char zip_fd_arg[strlen("--zip-fd=") + MAX_INT_LEN];
8331705fc44fb85c4232637f9f7189c3bdca98a63d5Brian Carlstrom    char zip_location_arg[strlen("--zip-location=") + PKG_PATH_MAX];
8341705fc44fb85c4232637f9f7189c3bdca98a63d5Brian Carlstrom    char oat_fd_arg[strlen("--oat-fd=") + MAX_INT_LEN];
8357195fcc2185c35b45a8f28c79fde4999b38850e8Brian Carlstrom    char oat_location_arg[strlen("--oat-location=") + PKG_PATH_MAX];
8361b4003207750ea8fe8c7b03eb32d80f1df83979eNarayan Kamath    char instruction_set_arg[strlen("--instruction-set=") + MAX_INSTRUCTION_SET_LEN];
83716a95b267ac6aac75453f65f1bc382ce65c0741eIan Rogers    char instruction_set_variant_arg[strlen("--instruction-set-variant=") + PROPERTY_VALUE_MAX];
8388fc7315a67fdbf9b56cc6fa061f0773be2223a81Calin Juravle    char instruction_set_features_arg[strlen("--instruction-set-features=") + PROPERTY_VALUE_MAX];
8394fdff4616699708e58d875273c3c1a85ba4c63bdCalin Juravle    char profile_file_arg[strlen("--profile-file=") + PKG_PATH_MAX];
8404fdff4616699708e58d875273c3c1a85ba4c63bdCalin Juravle    char top_k_profile_threshold_arg[strlen("--top-k-profile-threshold=") + PROPERTY_VALUE_MAX];
841e46a75a0f6007967cd0d161959af844772cdc330Brian Carlstrom    char dex2oat_Xms_arg[strlen("-Xms") + PROPERTY_VALUE_MAX];
842e46a75a0f6007967cd0d161959af844772cdc330Brian Carlstrom    char dex2oat_Xmx_arg[strlen("-Xmx") + PROPERTY_VALUE_MAX];
843cf51ba1360ee13459830a0502b0d454d0145544fBrian Carlstrom    char dex2oat_compiler_filter_arg[strlen("--compiler-filter=") + PROPERTY_VALUE_MAX];
844e1c01353c4dc6058a384eea9853238d2a87040dbAndreas Gampe    bool have_dex2oat_swap_fd = false;
845e1c01353c4dc6058a384eea9853238d2a87040dbAndreas Gampe    char dex2oat_swap_fd[strlen("--swap-fd=") + MAX_INT_LEN];
8461705fc44fb85c4232637f9f7189c3bdca98a63d5Brian Carlstrom
8471705fc44fb85c4232637f9f7189c3bdca98a63d5Brian Carlstrom    sprintf(zip_fd_arg, "--zip-fd=%d", zip_fd);
8481705fc44fb85c4232637f9f7189c3bdca98a63d5Brian Carlstrom    sprintf(zip_location_arg, "--zip-location=%s", input_file_name);
8491705fc44fb85c4232637f9f7189c3bdca98a63d5Brian Carlstrom    sprintf(oat_fd_arg, "--oat-fd=%d", oat_fd);
8501705fc44fb85c4232637f9f7189c3bdca98a63d5Brian Carlstrom    sprintf(oat_location_arg, "--oat-location=%s", output_file_name);
8511b4003207750ea8fe8c7b03eb32d80f1df83979eNarayan Kamath    sprintf(instruction_set_arg, "--instruction-set=%s", instruction_set);
85216a95b267ac6aac75453f65f1bc382ce65c0741eIan Rogers    sprintf(instruction_set_variant_arg, "--instruction-set-variant=%s", dex2oat_isa_variant);
8538fc7315a67fdbf9b56cc6fa061f0773be2223a81Calin Juravle    sprintf(instruction_set_features_arg, "--instruction-set-features=%s", dex2oat_isa_features);
854e1c01353c4dc6058a384eea9853238d2a87040dbAndreas Gampe    if (swap_fd >= 0) {
855e1c01353c4dc6058a384eea9853238d2a87040dbAndreas Gampe        have_dex2oat_swap_fd = true;
856e1c01353c4dc6058a384eea9853238d2a87040dbAndreas Gampe        sprintf(dex2oat_swap_fd, "--swap-fd=%d", swap_fd);
857e1c01353c4dc6058a384eea9853238d2a87040dbAndreas Gampe    }
85857c69c39640a7d6a08b3afb56361d76f7ecf1250Calin Juravle
8594fdff4616699708e58d875273c3c1a85ba4c63bdCalin Juravle    bool have_profile_file = false;
8604fdff4616699708e58d875273c3c1a85ba4c63bdCalin Juravle    bool have_top_k_profile_threshold = false;
86157c69c39640a7d6a08b3afb56361d76f7ecf1250Calin Juravle    if (profiler && (strcmp(pkgname, "*") != 0)) {
86257c69c39640a7d6a08b3afb56361d76f7ecf1250Calin Juravle        char profile_file[PKG_PATH_MAX];
86357c69c39640a7d6a08b3afb56361d76f7ecf1250Calin Juravle        snprintf(profile_file, sizeof(profile_file), "%s/%s",
864d93707342a61e66bc3eb2145628158452f577f42Dave Allison                 DALVIK_CACHE_PREFIX "profiles", pkgname);
86557c69c39640a7d6a08b3afb56361d76f7ecf1250Calin Juravle        struct stat st;
8664fdff4616699708e58d875273c3c1a85ba4c63bdCalin Juravle        if ((stat(profile_file, &st) == 0) && (st.st_size > 0)) {
86757c69c39640a7d6a08b3afb56361d76f7ecf1250Calin Juravle            sprintf(profile_file_arg, "--profile-file=%s", profile_file);
8684fdff4616699708e58d875273c3c1a85ba4c63bdCalin Juravle            have_profile_file = true;
8694fdff4616699708e58d875273c3c1a85ba4c63bdCalin Juravle            if (property_get("dalvik.vm.profile.top-k-thr", prop_buf, NULL) > 0) {
8704fdff4616699708e58d875273c3c1a85ba4c63bdCalin Juravle                snprintf(top_k_profile_threshold_arg, sizeof(top_k_profile_threshold_arg),
8714fdff4616699708e58d875273c3c1a85ba4c63bdCalin Juravle                         "--top-k-profile-threshold=%s", prop_buf);
8724fdff4616699708e58d875273c3c1a85ba4c63bdCalin Juravle                have_top_k_profile_threshold = true;
8734fdff4616699708e58d875273c3c1a85ba4c63bdCalin Juravle            }
87457c69c39640a7d6a08b3afb56361d76f7ecf1250Calin Juravle        }
875d93707342a61e66bc3eb2145628158452f577f42Dave Allison    }
8761705fc44fb85c4232637f9f7189c3bdca98a63d5Brian Carlstrom
877e46a75a0f6007967cd0d161959af844772cdc330Brian Carlstrom    if (have_dex2oat_Xms_flag) {
878e46a75a0f6007967cd0d161959af844772cdc330Brian Carlstrom        sprintf(dex2oat_Xms_arg, "-Xms%s", dex2oat_Xms_flag);
879e46a75a0f6007967cd0d161959af844772cdc330Brian Carlstrom    }
880e46a75a0f6007967cd0d161959af844772cdc330Brian Carlstrom    if (have_dex2oat_Xmx_flag) {
881e46a75a0f6007967cd0d161959af844772cdc330Brian Carlstrom        sprintf(dex2oat_Xmx_arg, "-Xmx%s", dex2oat_Xmx_flag);
882e46a75a0f6007967cd0d161959af844772cdc330Brian Carlstrom    }
883538998f204d1e542e235de9e7ce18ef4dc68c9ccBrian Carlstrom    if (skip_compilation) {
884e18987efb5e39ca1bed15527b7b82bde55c99669Brian Carlstrom        strcpy(dex2oat_compiler_filter_arg, "--compiler-filter=verify-none");
885538998f204d1e542e235de9e7ce18ef4dc68c9ccBrian Carlstrom        have_dex2oat_compiler_filter_flag = true;
88614e084d39ac44e9d4d0a0143bf1f111011343d34neo.chae        have_dex2oat_relocation_skip_flag = true;
887b1efac103523efccbe671e76cc0eaaeab810415bCalin Juravle    } else if (vm_safe_mode) {
888b1efac103523efccbe671e76cc0eaaeab810415bCalin Juravle        strcpy(dex2oat_compiler_filter_arg, "--compiler-filter=interpret-only");
88997477d203eaf0c3235bbe2415356f20a0431cadaCalin Juravle        have_dex2oat_compiler_filter_flag = true;
890d4a7b459f4f383988440c0512513b321ce03fc22Mathieu Chartier    } else if (use_jit) {
891d4a7b459f4f383988440c0512513b321ce03fc22Mathieu Chartier        strcpy(dex2oat_compiler_filter_arg, "--compiler-filter=verify-at-runtime");
892d4a7b459f4f383988440c0512513b321ce03fc22Mathieu Chartier        have_dex2oat_compiler_filter_flag = true;
893538998f204d1e542e235de9e7ce18ef4dc68c9ccBrian Carlstrom    } else if (have_dex2oat_compiler_filter_flag) {
894cf51ba1360ee13459830a0502b0d454d0145544fBrian Carlstrom        sprintf(dex2oat_compiler_filter_arg, "--compiler-filter=%s", dex2oat_compiler_filter_flag);
895cf51ba1360ee13459830a0502b0d454d0145544fBrian Carlstrom    }
896e46a75a0f6007967cd0d161959af844772cdc330Brian Carlstrom
897598c25e23f7c97470e09a2316513ddf2efdfb670Andreas Gampe    // Check whether all apps should be compiled debuggable.
898598c25e23f7c97470e09a2316513ddf2efdfb670Andreas Gampe    if (!debuggable) {
899598c25e23f7c97470e09a2316513ddf2efdfb670Andreas Gampe        debuggable =
900598c25e23f7c97470e09a2316513ddf2efdfb670Andreas Gampe                (property_get("dalvik.vm.always_debuggable", prop_buf, "0") > 0) &&
901598c25e23f7c97470e09a2316513ddf2efdfb670Andreas Gampe                (prop_buf[0] == '1');
902598c25e23f7c97470e09a2316513ddf2efdfb670Andreas Gampe    }
903598c25e23f7c97470e09a2316513ddf2efdfb670Andreas Gampe
9041705fc44fb85c4232637f9f7189c3bdca98a63d5Brian Carlstrom    ALOGV("Running %s in=%s out=%s\n", DEX2OAT_BIN, input_file_name, output_file_name);
9054fdff4616699708e58d875273c3c1a85ba4c63bdCalin Juravle
90614e084d39ac44e9d4d0a0143bf1f111011343d34neo.chae    const char* argv[7  // program name, mandatory arguments and the final NULL
90714e084d39ac44e9d4d0a0143bf1f111011343d34neo.chae                     + (have_dex2oat_isa_variant ? 1 : 0)
90814e084d39ac44e9d4d0a0143bf1f111011343d34neo.chae                     + (have_dex2oat_isa_features ? 1 : 0)
90914e084d39ac44e9d4d0a0143bf1f111011343d34neo.chae                     + (have_profile_file ? 1 : 0)
91014e084d39ac44e9d4d0a0143bf1f111011343d34neo.chae                     + (have_top_k_profile_threshold ? 1 : 0)
91114e084d39ac44e9d4d0a0143bf1f111011343d34neo.chae                     + (have_dex2oat_Xms_flag ? 2 : 0)
91214e084d39ac44e9d4d0a0143bf1f111011343d34neo.chae                     + (have_dex2oat_Xmx_flag ? 2 : 0)
91314e084d39ac44e9d4d0a0143bf1f111011343d34neo.chae                     + (have_dex2oat_compiler_filter_flag ? 1 : 0)
9148d7af8b2418cc5e7e59746f0cb359a75ed0bdfd1Andreas Gampe                     + (have_dex2oat_threads_flag ? 1 : 0)
91514e084d39ac44e9d4d0a0143bf1f111011343d34neo.chae                     + (have_dex2oat_swap_fd ? 1 : 0)
91614e084d39ac44e9d4d0a0143bf1f111011343d34neo.chae                     + (have_dex2oat_relocation_skip_flag ? 2 : 0)
917528c8ddc60df7b3d291b389117e4db878a20ad48David Srbecky                     + (generate_debug_info ? 1 : 0)
918598c25e23f7c97470e09a2316513ddf2efdfb670Andreas Gampe                     + (debuggable ? 1 : 0)
91914e084d39ac44e9d4d0a0143bf1f111011343d34neo.chae                     + dex2oat_flags_count];
9204fdff4616699708e58d875273c3c1a85ba4c63bdCalin Juravle    int i = 0;
92114e084d39ac44e9d4d0a0143bf1f111011343d34neo.chae    argv[i++] = DEX2OAT_BIN;
9224fdff4616699708e58d875273c3c1a85ba4c63bdCalin Juravle    argv[i++] = zip_fd_arg;
9234fdff4616699708e58d875273c3c1a85ba4c63bdCalin Juravle    argv[i++] = zip_location_arg;
9244fdff4616699708e58d875273c3c1a85ba4c63bdCalin Juravle    argv[i++] = oat_fd_arg;
9254fdff4616699708e58d875273c3c1a85ba4c63bdCalin Juravle    argv[i++] = oat_location_arg;
9264fdff4616699708e58d875273c3c1a85ba4c63bdCalin Juravle    argv[i++] = instruction_set_arg;
92716a95b267ac6aac75453f65f1bc382ce65c0741eIan Rogers    if (have_dex2oat_isa_variant) {
92816a95b267ac6aac75453f65f1bc382ce65c0741eIan Rogers        argv[i++] = instruction_set_variant_arg;
92916a95b267ac6aac75453f65f1bc382ce65c0741eIan Rogers    }
9308fc7315a67fdbf9b56cc6fa061f0773be2223a81Calin Juravle    if (have_dex2oat_isa_features) {
9318fc7315a67fdbf9b56cc6fa061f0773be2223a81Calin Juravle        argv[i++] = instruction_set_features_arg;
9328fc7315a67fdbf9b56cc6fa061f0773be2223a81Calin Juravle    }
9334fdff4616699708e58d875273c3c1a85ba4c63bdCalin Juravle    if (have_profile_file) {
9344fdff4616699708e58d875273c3c1a85ba4c63bdCalin Juravle        argv[i++] = profile_file_arg;
9354fdff4616699708e58d875273c3c1a85ba4c63bdCalin Juravle    }
9364fdff4616699708e58d875273c3c1a85ba4c63bdCalin Juravle    if (have_top_k_profile_threshold) {
9374fdff4616699708e58d875273c3c1a85ba4c63bdCalin Juravle        argv[i++] = top_k_profile_threshold_arg;
9384fdff4616699708e58d875273c3c1a85ba4c63bdCalin Juravle    }
939e46a75a0f6007967cd0d161959af844772cdc330Brian Carlstrom    if (have_dex2oat_Xms_flag) {
94014e084d39ac44e9d4d0a0143bf1f111011343d34neo.chae        argv[i++] = RUNTIME_ARG;
941e46a75a0f6007967cd0d161959af844772cdc330Brian Carlstrom        argv[i++] = dex2oat_Xms_arg;
942e46a75a0f6007967cd0d161959af844772cdc330Brian Carlstrom    }
943e46a75a0f6007967cd0d161959af844772cdc330Brian Carlstrom    if (have_dex2oat_Xmx_flag) {
94414e084d39ac44e9d4d0a0143bf1f111011343d34neo.chae        argv[i++] = RUNTIME_ARG;
945e46a75a0f6007967cd0d161959af844772cdc330Brian Carlstrom        argv[i++] = dex2oat_Xmx_arg;
946e46a75a0f6007967cd0d161959af844772cdc330Brian Carlstrom    }
947cf51ba1360ee13459830a0502b0d454d0145544fBrian Carlstrom    if (have_dex2oat_compiler_filter_flag) {
948cf51ba1360ee13459830a0502b0d454d0145544fBrian Carlstrom        argv[i++] = dex2oat_compiler_filter_arg;
949cf51ba1360ee13459830a0502b0d454d0145544fBrian Carlstrom    }
9508d7af8b2418cc5e7e59746f0cb359a75ed0bdfd1Andreas Gampe    if (have_dex2oat_threads_flag) {
9518d7af8b2418cc5e7e59746f0cb359a75ed0bdfd1Andreas Gampe        argv[i++] = dex2oat_threads_arg;
9528d7af8b2418cc5e7e59746f0cb359a75ed0bdfd1Andreas Gampe    }
953e1c01353c4dc6058a384eea9853238d2a87040dbAndreas Gampe    if (have_dex2oat_swap_fd) {
954e1c01353c4dc6058a384eea9853238d2a87040dbAndreas Gampe        argv[i++] = dex2oat_swap_fd;
955e1c01353c4dc6058a384eea9853238d2a87040dbAndreas Gampe    }
956528c8ddc60df7b3d291b389117e4db878a20ad48David Srbecky    if (generate_debug_info) {
957528c8ddc60df7b3d291b389117e4db878a20ad48David Srbecky        argv[i++] = "--generate-debug-info";
9583822b8b79cf533ee8573794176838406c32a1c20Andreas Gampe    }
959598c25e23f7c97470e09a2316513ddf2efdfb670Andreas Gampe    if (debuggable) {
960598c25e23f7c97470e09a2316513ddf2efdfb670Andreas Gampe        argv[i++] = "--debuggable";
961598c25e23f7c97470e09a2316513ddf2efdfb670Andreas Gampe    }
962b0d8d00b2916aef7b01ad42f6d441f5b46b7731aYevgeny Rouban    if (dex2oat_flags_count) {
963b0d8d00b2916aef7b01ad42f6d441f5b46b7731aYevgeny Rouban        i += split(dex2oat_flags, argv + i);
9644fdff4616699708e58d875273c3c1a85ba4c63bdCalin Juravle    }
96514e084d39ac44e9d4d0a0143bf1f111011343d34neo.chae    if (have_dex2oat_relocation_skip_flag) {
96614e084d39ac44e9d4d0a0143bf1f111011343d34neo.chae        argv[i++] = RUNTIME_ARG;
96714e084d39ac44e9d4d0a0143bf1f111011343d34neo.chae        argv[i++] = dex2oat_norelocation;
96814e084d39ac44e9d4d0a0143bf1f111011343d34neo.chae    }
969e46a75a0f6007967cd0d161959af844772cdc330Brian Carlstrom    // Do not add after dex2oat_flags, they should override others for debugging.
9704fdff4616699708e58d875273c3c1a85ba4c63bdCalin Juravle    argv[i] = NULL;
9714fdff4616699708e58d875273c3c1a85ba4c63bdCalin Juravle
97214e084d39ac44e9d4d0a0143bf1f111011343d34neo.chae    execv(DEX2OAT_BIN, (char * const *)argv);
973b0d8d00b2916aef7b01ad42f6d441f5b46b7731aYevgeny Rouban    ALOGE("execv(%s) failed: %s\n", DEX2OAT_BIN, strerror(errno));
9741705fc44fb85c4232637f9f7189c3bdca98a63d5Brian Carlstrom}
9751705fc44fb85c4232637f9f7189c3bdca98a63d5Brian Carlstrom
97663568b1430d741f40ca008391c854ef1cc880138MÃ¥rten Kongstadstatic int wait_child(pid_t pid)
97794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood{
97894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    int status;
97994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    pid_t got_pid;
98094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
98194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    while (1) {
98294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        got_pid = waitpid(pid, &status, 0);
98394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        if (got_pid == -1 && errno == EINTR) {
98494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood            printf("waitpid interrupted, retrying\n");
98594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        } else {
98694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood            break;
98794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        }
98894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    }
98994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    if (got_pid != pid) {
99094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        ALOGW("waitpid failed: wanted %d, got %d: %s\n",
99194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood            (int) pid, (int) got_pid, strerror(errno));
99294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        return 1;
99394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    }
99494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
99594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    if (WIFEXITED(status) && WEXITSTATUS(status) == 0) {
99694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        return 0;
99794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    } else {
99894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        return status;      /* always nonzero */
99994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    }
100094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood}
100194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
1002e1c01353c4dc6058a384eea9853238d2a87040dbAndreas Gampe/*
1003c968c0175e967e39e72f557b5e014b9575ba4727Andreas Gampe * Whether dexopt should use a swap file when compiling an APK.
1004c968c0175e967e39e72f557b5e014b9575ba4727Andreas Gampe *
1005c968c0175e967e39e72f557b5e014b9575ba4727Andreas Gampe * If kAlwaysProvideSwapFile, do this on all devices (dex2oat will make a more informed decision
1006c968c0175e967e39e72f557b5e014b9575ba4727Andreas Gampe * itself, anyways).
1007c968c0175e967e39e72f557b5e014b9575ba4727Andreas Gampe *
1008c968c0175e967e39e72f557b5e014b9575ba4727Andreas Gampe * Otherwise, read "dalvik.vm.dex2oat-swap". If the property exists, return whether it is "true".
1009c968c0175e967e39e72f557b5e014b9575ba4727Andreas Gampe *
1010c968c0175e967e39e72f557b5e014b9575ba4727Andreas Gampe * Otherwise, return true if this is a low-mem device.
1011c968c0175e967e39e72f557b5e014b9575ba4727Andreas Gampe *
1012c968c0175e967e39e72f557b5e014b9575ba4727Andreas Gampe * Otherwise, return default value.
1013e1c01353c4dc6058a384eea9853238d2a87040dbAndreas Gampe */
1014c968c0175e967e39e72f557b5e014b9575ba4727Andreas Gampestatic bool kAlwaysProvideSwapFile = false;
1015c968c0175e967e39e72f557b5e014b9575ba4727Andreas Gampestatic bool kDefaultProvideSwapFile = true;
1016e1c01353c4dc6058a384eea9853238d2a87040dbAndreas Gampe
1017e1c01353c4dc6058a384eea9853238d2a87040dbAndreas Gampestatic bool ShouldUseSwapFileForDexopt() {
1018e1c01353c4dc6058a384eea9853238d2a87040dbAndreas Gampe    if (kAlwaysProvideSwapFile) {
1019e1c01353c4dc6058a384eea9853238d2a87040dbAndreas Gampe        return true;
1020e1c01353c4dc6058a384eea9853238d2a87040dbAndreas Gampe    }
1021e1c01353c4dc6058a384eea9853238d2a87040dbAndreas Gampe
1022c968c0175e967e39e72f557b5e014b9575ba4727Andreas Gampe    // Check the "override" property. If it exists, return value == "true".
1023c968c0175e967e39e72f557b5e014b9575ba4727Andreas Gampe    char dex2oat_prop_buf[PROPERTY_VALUE_MAX];
1024c968c0175e967e39e72f557b5e014b9575ba4727Andreas Gampe    if (property_get("dalvik.vm.dex2oat-swap", dex2oat_prop_buf, "") > 0) {
1025c968c0175e967e39e72f557b5e014b9575ba4727Andreas Gampe        if (strcmp(dex2oat_prop_buf, "true") == 0) {
1026c968c0175e967e39e72f557b5e014b9575ba4727Andreas Gampe            return true;
1027c968c0175e967e39e72f557b5e014b9575ba4727Andreas Gampe        } else {
1028c968c0175e967e39e72f557b5e014b9575ba4727Andreas Gampe            return false;
1029c968c0175e967e39e72f557b5e014b9575ba4727Andreas Gampe        }
1030c968c0175e967e39e72f557b5e014b9575ba4727Andreas Gampe    }
1031c968c0175e967e39e72f557b5e014b9575ba4727Andreas Gampe
1032c968c0175e967e39e72f557b5e014b9575ba4727Andreas Gampe    // Shortcut for default value. This is an implementation optimization for the process sketched
1033c968c0175e967e39e72f557b5e014b9575ba4727Andreas Gampe    // above. If the default value is true, we can avoid to check whether this is a low-mem device,
1034c968c0175e967e39e72f557b5e014b9575ba4727Andreas Gampe    // as low-mem is never returning false. The compiler will optimize this away if it can.
1035c968c0175e967e39e72f557b5e014b9575ba4727Andreas Gampe    if (kDefaultProvideSwapFile) {
1036c968c0175e967e39e72f557b5e014b9575ba4727Andreas Gampe        return true;
1037c968c0175e967e39e72f557b5e014b9575ba4727Andreas Gampe    }
1038c968c0175e967e39e72f557b5e014b9575ba4727Andreas Gampe
1039c968c0175e967e39e72f557b5e014b9575ba4727Andreas Gampe    bool is_low_mem = check_boolean_property("ro.config.low_ram");
1040c968c0175e967e39e72f557b5e014b9575ba4727Andreas Gampe    if (is_low_mem) {
1041c968c0175e967e39e72f557b5e014b9575ba4727Andreas Gampe        return true;
1042c968c0175e967e39e72f557b5e014b9575ba4727Andreas Gampe    }
1043c968c0175e967e39e72f557b5e014b9575ba4727Andreas Gampe
1044c968c0175e967e39e72f557b5e014b9575ba4727Andreas Gampe    // Default value must be false here.
1045c968c0175e967e39e72f557b5e014b9575ba4727Andreas Gampe    return kDefaultProvideSwapFile;
1046e1c01353c4dc6058a384eea9853238d2a87040dbAndreas Gampe}
1047e1c01353c4dc6058a384eea9853238d2a87040dbAndreas Gampe
1048009b8771323ce69658c1ac0254c3259186107fb6Richard Uhler/*
1049009b8771323ce69658c1ac0254c3259186107fb6Richard Uhler * Computes the odex file for the given apk_path and instruction_set.
1050009b8771323ce69658c1ac0254c3259186107fb6Richard Uhler * /system/framework/whatever.jar -> /system/framework/oat/<isa>/whatever.odex
1051009b8771323ce69658c1ac0254c3259186107fb6Richard Uhler *
1052009b8771323ce69658c1ac0254c3259186107fb6Richard Uhler * Returns false if it failed to determine the odex file path.
1053009b8771323ce69658c1ac0254c3259186107fb6Richard Uhler */
1054009b8771323ce69658c1ac0254c3259186107fb6Richard Uhlerstatic bool calculate_odex_file_path(char path[PKG_PATH_MAX],
1055009b8771323ce69658c1ac0254c3259186107fb6Richard Uhler                                     const char *apk_path,
1056009b8771323ce69658c1ac0254c3259186107fb6Richard Uhler                                     const char *instruction_set)
1057009b8771323ce69658c1ac0254c3259186107fb6Richard Uhler{
1058009b8771323ce69658c1ac0254c3259186107fb6Richard Uhler    if (strlen(apk_path) + strlen("oat/") + strlen(instruction_set)
1059009b8771323ce69658c1ac0254c3259186107fb6Richard Uhler        + strlen("/") + strlen("odex") + 1 > PKG_PATH_MAX) {
1060009b8771323ce69658c1ac0254c3259186107fb6Richard Uhler      ALOGE("apk_path '%s' may be too long to form odex file path.\n", apk_path);
1061009b8771323ce69658c1ac0254c3259186107fb6Richard Uhler      return false;
1062009b8771323ce69658c1ac0254c3259186107fb6Richard Uhler    }
1063009b8771323ce69658c1ac0254c3259186107fb6Richard Uhler
1064009b8771323ce69658c1ac0254c3259186107fb6Richard Uhler    strcpy(path, apk_path);
1065009b8771323ce69658c1ac0254c3259186107fb6Richard Uhler    char *end = strrchr(path, '/');
1066009b8771323ce69658c1ac0254c3259186107fb6Richard Uhler    if (end == NULL) {
1067009b8771323ce69658c1ac0254c3259186107fb6Richard Uhler      ALOGE("apk_path '%s' has no '/'s in it?!\n", apk_path);
1068009b8771323ce69658c1ac0254c3259186107fb6Richard Uhler      return false;
1069009b8771323ce69658c1ac0254c3259186107fb6Richard Uhler    }
1070009b8771323ce69658c1ac0254c3259186107fb6Richard Uhler    const char *apk_end = apk_path + (end - path); // strrchr(apk_path, '/');
1071009b8771323ce69658c1ac0254c3259186107fb6Richard Uhler
1072009b8771323ce69658c1ac0254c3259186107fb6Richard Uhler    strcpy(end + 1, "oat/");       // path = /system/framework/oat/\0
1073009b8771323ce69658c1ac0254c3259186107fb6Richard Uhler    strcat(path, instruction_set); // path = /system/framework/oat/<isa>\0
1074009b8771323ce69658c1ac0254c3259186107fb6Richard Uhler    strcat(path, apk_end);         // path = /system/framework/oat/<isa>/whatever.jar\0
1075009b8771323ce69658c1ac0254c3259186107fb6Richard Uhler    end = strrchr(path, '.');
1076009b8771323ce69658c1ac0254c3259186107fb6Richard Uhler    if (end == NULL) {
1077009b8771323ce69658c1ac0254c3259186107fb6Richard Uhler      ALOGE("apk_path '%s' has no extension.\n", apk_path);
1078009b8771323ce69658c1ac0254c3259186107fb6Richard Uhler      return false;
1079009b8771323ce69658c1ac0254c3259186107fb6Richard Uhler    }
1080009b8771323ce69658c1ac0254c3259186107fb6Richard Uhler    strcpy(end + 1, "odex");
1081009b8771323ce69658c1ac0254c3259186107fb6Richard Uhler    return true;
1082009b8771323ce69658c1ac0254c3259186107fb6Richard Uhler}
1083009b8771323ce69658c1ac0254c3259186107fb6Richard Uhler
108421948005f0294a64a42932b21a33ae75295dc3d9Andreas Gampestatic void SetDex2OatAndPatchOatScheduling(bool set_to_bg) {
108521948005f0294a64a42932b21a33ae75295dc3d9Andreas Gampe    if (set_to_bg) {
108621948005f0294a64a42932b21a33ae75295dc3d9Andreas Gampe        if (set_sched_policy(0, SP_BACKGROUND) < 0) {
108721948005f0294a64a42932b21a33ae75295dc3d9Andreas Gampe            ALOGE("set_sched_policy failed: %s\n", strerror(errno));
108821948005f0294a64a42932b21a33ae75295dc3d9Andreas Gampe            exit(70);
108921948005f0294a64a42932b21a33ae75295dc3d9Andreas Gampe        }
109021948005f0294a64a42932b21a33ae75295dc3d9Andreas Gampe        if (setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_BACKGROUND) < 0) {
109121948005f0294a64a42932b21a33ae75295dc3d9Andreas Gampe            ALOGE("setpriority failed: %s\n", strerror(errno));
109221948005f0294a64a42932b21a33ae75295dc3d9Andreas Gampe            exit(71);
109321948005f0294a64a42932b21a33ae75295dc3d9Andreas Gampe        }
109421948005f0294a64a42932b21a33ae75295dc3d9Andreas Gampe    }
109521948005f0294a64a42932b21a33ae75295dc3d9Andreas Gampe}
109621948005f0294a64a42932b21a33ae75295dc3d9Andreas Gampe
1097b1efac103523efccbe671e76cc0eaaeab810415bCalin Juravleint dexopt(const char *apk_path, uid_t uid, bool is_public,
1098c92fb6247d4c4fbc34c0a5deb26ccf538ca9ec81Richard Uhler           const char *pkgname, const char *instruction_set, int dexopt_needed,
109972ebebed876a62e719b098e43d9d516361bde029Andreas Gampe           bool vm_safe_mode, bool debuggable, const char* oat_dir, bool boot_complete)
110094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood{
110194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    struct utimbuf ut;
110226ff93c1a783d02c177a47f0a80249070fe43682Fyodor Kupolov    struct stat input_stat;
11031705fc44fb85c4232637f9f7189c3bdca98a63d5Brian Carlstrom    char out_path[PKG_PATH_MAX];
1104e1c01353c4dc6058a384eea9853238d2a87040dbAndreas Gampe    char swap_file_name[PKG_PATH_MAX];
11057365a10689df23334d245b211ce272502ad20669Alex Light    const char *input_file;
11067365a10689df23334d245b211ce272502ad20669Alex Light    char in_odex_path[PKG_PATH_MAX];
1107e1c01353c4dc6058a384eea9853238d2a87040dbAndreas Gampe    int res, input_fd=-1, out_fd=-1, swap_fd=-1;
110894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
1109e1c01353c4dc6058a384eea9853238d2a87040dbAndreas Gampe    // Early best-effort check whether we can fit the the path into our buffers.
1110e1c01353c4dc6058a384eea9853238d2a87040dbAndreas Gampe    // Note: the cache path will require an additional 5 bytes for ".swap", but we'll try to run
1111e1c01353c4dc6058a384eea9853238d2a87040dbAndreas Gampe    // without a swap file, if necessary.
111294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    if (strlen(apk_path) >= (PKG_PATH_MAX - 8)) {
111388ce4ff7a95ea2008fa28f12b880ee526e331440Fyodor Kupolov        ALOGE("apk_path too long '%s'\n", apk_path);
111494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        return -1;
111594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    }
111694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
111788ce4ff7a95ea2008fa28f12b880ee526e331440Fyodor Kupolov    if (oat_dir != NULL && oat_dir[0] != '!') {
111888ce4ff7a95ea2008fa28f12b880ee526e331440Fyodor Kupolov        if (validate_apk_path(oat_dir)) {
111988ce4ff7a95ea2008fa28f12b880ee526e331440Fyodor Kupolov            ALOGE("invalid oat_dir '%s'\n", oat_dir);
112088ce4ff7a95ea2008fa28f12b880ee526e331440Fyodor Kupolov            return -1;
112188ce4ff7a95ea2008fa28f12b880ee526e331440Fyodor Kupolov        }
112288ce4ff7a95ea2008fa28f12b880ee526e331440Fyodor Kupolov        if (calculate_oat_file_path(out_path, oat_dir, apk_path, instruction_set)) {
112388ce4ff7a95ea2008fa28f12b880ee526e331440Fyodor Kupolov            return -1;
112488ce4ff7a95ea2008fa28f12b880ee526e331440Fyodor Kupolov        }
112588ce4ff7a95ea2008fa28f12b880ee526e331440Fyodor Kupolov    } else {
112688ce4ff7a95ea2008fa28f12b880ee526e331440Fyodor Kupolov        if (create_cache_path(out_path, apk_path, instruction_set)) {
112788ce4ff7a95ea2008fa28f12b880ee526e331440Fyodor Kupolov            return -1;
11280e8ae16f084e3d4772ea6dd33a9b72925d7b40d5Chih-Wei Huang        }
112994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    }
113094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
1131c92fb6247d4c4fbc34c0a5deb26ccf538ca9ec81Richard Uhler    switch (dexopt_needed) {
1132c92fb6247d4c4fbc34c0a5deb26ccf538ca9ec81Richard Uhler        case DEXOPT_DEX2OAT_NEEDED:
1133c92fb6247d4c4fbc34c0a5deb26ccf538ca9ec81Richard Uhler            input_file = apk_path;
1134c92fb6247d4c4fbc34c0a5deb26ccf538ca9ec81Richard Uhler            break;
1135c92fb6247d4c4fbc34c0a5deb26ccf538ca9ec81Richard Uhler
1136c92fb6247d4c4fbc34c0a5deb26ccf538ca9ec81Richard Uhler        case DEXOPT_PATCHOAT_NEEDED:
1137c92fb6247d4c4fbc34c0a5deb26ccf538ca9ec81Richard Uhler            if (!calculate_odex_file_path(in_odex_path, apk_path, instruction_set)) {
1138c92fb6247d4c4fbc34c0a5deb26ccf538ca9ec81Richard Uhler                return -1;
1139c92fb6247d4c4fbc34c0a5deb26ccf538ca9ec81Richard Uhler            }
1140c92fb6247d4c4fbc34c0a5deb26ccf538ca9ec81Richard Uhler            input_file = in_odex_path;
1141c92fb6247d4c4fbc34c0a5deb26ccf538ca9ec81Richard Uhler            break;
1142c92fb6247d4c4fbc34c0a5deb26ccf538ca9ec81Richard Uhler
1143c92fb6247d4c4fbc34c0a5deb26ccf538ca9ec81Richard Uhler        case DEXOPT_SELF_PATCHOAT_NEEDED:
1144c92fb6247d4c4fbc34c0a5deb26ccf538ca9ec81Richard Uhler            input_file = out_path;
1145c92fb6247d4c4fbc34c0a5deb26ccf538ca9ec81Richard Uhler            break;
1146c92fb6247d4c4fbc34c0a5deb26ccf538ca9ec81Richard Uhler
1147c92fb6247d4c4fbc34c0a5deb26ccf538ca9ec81Richard Uhler        default:
1148c92fb6247d4c4fbc34c0a5deb26ccf538ca9ec81Richard Uhler            ALOGE("Invalid dexopt needed: %d\n", dexopt_needed);
1149c92fb6247d4c4fbc34c0a5deb26ccf538ca9ec81Richard Uhler            exit(72);
11507365a10689df23334d245b211ce272502ad20669Alex Light    }
11517365a10689df23334d245b211ce272502ad20669Alex Light
11527365a10689df23334d245b211ce272502ad20669Alex Light    memset(&input_stat, 0, sizeof(input_stat));
11537365a10689df23334d245b211ce272502ad20669Alex Light    stat(input_file, &input_stat);
115494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
11557365a10689df23334d245b211ce272502ad20669Alex Light    input_fd = open(input_file, O_RDONLY, 0);
11567365a10689df23334d245b211ce272502ad20669Alex Light    if (input_fd < 0) {
11577365a10689df23334d245b211ce272502ad20669Alex Light        ALOGE("installd cannot open '%s' for input during dexopt\n", input_file);
115894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        return -1;
115994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    }
116094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
11611705fc44fb85c4232637f9f7189c3bdca98a63d5Brian Carlstrom    unlink(out_path);
11621705fc44fb85c4232637f9f7189c3bdca98a63d5Brian Carlstrom    out_fd = open(out_path, O_RDWR | O_CREAT | O_EXCL, 0644);
11631705fc44fb85c4232637f9f7189c3bdca98a63d5Brian Carlstrom    if (out_fd < 0) {
11641705fc44fb85c4232637f9f7189c3bdca98a63d5Brian Carlstrom        ALOGE("installd cannot open '%s' for output during dexopt\n", out_path);
116594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        goto fail;
116694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    }
11671705fc44fb85c4232637f9f7189c3bdca98a63d5Brian Carlstrom    if (fchmod(out_fd,
116894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood               S_IRUSR|S_IWUSR|S_IRGRP |
116994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood               (is_public ? S_IROTH : 0)) < 0) {
11701705fc44fb85c4232637f9f7189c3bdca98a63d5Brian Carlstrom        ALOGE("installd cannot chmod '%s' during dexopt\n", out_path);
117194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        goto fail;
117294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    }
11731705fc44fb85c4232637f9f7189c3bdca98a63d5Brian Carlstrom    if (fchown(out_fd, AID_SYSTEM, uid) < 0) {
11741705fc44fb85c4232637f9f7189c3bdca98a63d5Brian Carlstrom        ALOGE("installd cannot chown '%s' during dexopt\n", out_path);
117594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        goto fail;
117694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    }
117794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
1178d93707342a61e66bc3eb2145628158452f577f42Dave Allison    // Create profile file if there is a package name present.
1179d93707342a61e66bc3eb2145628158452f577f42Dave Allison    if (strcmp(pkgname, "*") != 0) {
1180d93707342a61e66bc3eb2145628158452f577f42Dave Allison        create_profile_file(pkgname, uid);
1181d93707342a61e66bc3eb2145628158452f577f42Dave Allison    }
1182d93707342a61e66bc3eb2145628158452f577f42Dave Allison
1183e1c01353c4dc6058a384eea9853238d2a87040dbAndreas Gampe    // Create a swap file if necessary.
1184c92fb6247d4c4fbc34c0a5deb26ccf538ca9ec81Richard Uhler    if (ShouldUseSwapFileForDexopt()) {
1185e1c01353c4dc6058a384eea9853238d2a87040dbAndreas Gampe        // Make sure there really is enough space.
1186e1c01353c4dc6058a384eea9853238d2a87040dbAndreas Gampe        size_t out_len = strlen(out_path);
1187e1c01353c4dc6058a384eea9853238d2a87040dbAndreas Gampe        if (out_len + strlen(".swap") + 1 <= PKG_PATH_MAX) {
1188e1c01353c4dc6058a384eea9853238d2a87040dbAndreas Gampe            strcpy(swap_file_name, out_path);
1189e1c01353c4dc6058a384eea9853238d2a87040dbAndreas Gampe            strcpy(swap_file_name + strlen(out_path), ".swap");
1190e1c01353c4dc6058a384eea9853238d2a87040dbAndreas Gampe            unlink(swap_file_name);
1191e1c01353c4dc6058a384eea9853238d2a87040dbAndreas Gampe            swap_fd = open(swap_file_name, O_RDWR | O_CREAT | O_EXCL, 0600);
1192e1c01353c4dc6058a384eea9853238d2a87040dbAndreas Gampe            if (swap_fd < 0) {
1193e1c01353c4dc6058a384eea9853238d2a87040dbAndreas Gampe                // Could not create swap file. Optimistically go on and hope that we can compile
1194e1c01353c4dc6058a384eea9853238d2a87040dbAndreas Gampe                // without it.
1195e1c01353c4dc6058a384eea9853238d2a87040dbAndreas Gampe                ALOGE("installd could not create '%s' for swap during dexopt\n", swap_file_name);
1196e1c01353c4dc6058a384eea9853238d2a87040dbAndreas Gampe            } else {
1197e1c01353c4dc6058a384eea9853238d2a87040dbAndreas Gampe                // Immediately unlink. We don't really want to hit flash.
1198e1c01353c4dc6058a384eea9853238d2a87040dbAndreas Gampe                unlink(swap_file_name);
1199e1c01353c4dc6058a384eea9853238d2a87040dbAndreas Gampe            }
1200e1c01353c4dc6058a384eea9853238d2a87040dbAndreas Gampe        } else {
1201e1c01353c4dc6058a384eea9853238d2a87040dbAndreas Gampe            // Swap file path is too long. Try to run without.
1202e1c01353c4dc6058a384eea9853238d2a87040dbAndreas Gampe            ALOGE("installd could not create swap file for path %s during dexopt\n", out_path);
1203e1c01353c4dc6058a384eea9853238d2a87040dbAndreas Gampe        }
1204e1c01353c4dc6058a384eea9853238d2a87040dbAndreas Gampe    }
1205d93707342a61e66bc3eb2145628158452f577f42Dave Allison
12067365a10689df23334d245b211ce272502ad20669Alex Light    ALOGV("DexInv: --- BEGIN '%s' ---\n", input_file);
120794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
120894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    pid_t pid;
120994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    pid = fork();
121094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    if (pid == 0) {
121194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        /* child -- drop privileges before continuing */
121294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        if (setgid(uid) != 0) {
12131705fc44fb85c4232637f9f7189c3bdca98a63d5Brian Carlstrom            ALOGE("setgid(%d) failed in installd during dexopt\n", uid);
121494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood            exit(64);
121594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        }
121694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        if (setuid(uid) != 0) {
12171705fc44fb85c4232637f9f7189c3bdca98a63d5Brian Carlstrom            ALOGE("setuid(%d) failed in installd during dexopt\n", uid);
121894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood            exit(65);
121994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        }
122094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        // drop capabilities
122194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        struct __user_cap_header_struct capheader;
122294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        struct __user_cap_data_struct capdata[2];
122394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        memset(&capheader, 0, sizeof(capheader));
122494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        memset(&capdata, 0, sizeof(capdata));
122594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        capheader.version = _LINUX_CAPABILITY_VERSION_3;
122694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        if (capset(&capheader, &capdata[0]) < 0) {
122794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood            ALOGE("capset failed: %s\n", strerror(errno));
122894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood            exit(66);
122994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        }
123072ebebed876a62e719b098e43d9d516361bde029Andreas Gampe        SetDex2OatAndPatchOatScheduling(boot_complete);
12311705fc44fb85c4232637f9f7189c3bdca98a63d5Brian Carlstrom        if (flock(out_fd, LOCK_EX | LOCK_NB) != 0) {
12321705fc44fb85c4232637f9f7189c3bdca98a63d5Brian Carlstrom            ALOGE("flock(%s) failed: %s\n", out_path, strerror(errno));
123394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood            exit(67);
123494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        }
123594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
1236c92fb6247d4c4fbc34c0a5deb26ccf538ca9ec81Richard Uhler        if (dexopt_needed == DEXOPT_PATCHOAT_NEEDED
1237c92fb6247d4c4fbc34c0a5deb26ccf538ca9ec81Richard Uhler            || dexopt_needed == DEXOPT_SELF_PATCHOAT_NEEDED) {
1238bd872e49561282682793ab526616d609f7fbb274Andreas Gampe            run_patchoat(input_fd, out_fd, input_file, out_path, pkgname, instruction_set);
1239c92fb6247d4c4fbc34c0a5deb26ccf538ca9ec81Richard Uhler        } else if (dexopt_needed == DEXOPT_DEX2OAT_NEEDED) {
124088ce4ff7a95ea2008fa28f12b880ee526e331440Fyodor Kupolov            const char *input_file_name = strrchr(input_file, '/');
124188ce4ff7a95ea2008fa28f12b880ee526e331440Fyodor Kupolov            if (input_file_name == NULL) {
124288ce4ff7a95ea2008fa28f12b880ee526e331440Fyodor Kupolov                input_file_name = input_file;
124388ce4ff7a95ea2008fa28f12b880ee526e331440Fyodor Kupolov            } else {
124488ce4ff7a95ea2008fa28f12b880ee526e331440Fyodor Kupolov                input_file_name++;
124588ce4ff7a95ea2008fa28f12b880ee526e331440Fyodor Kupolov            }
124688ce4ff7a95ea2008fa28f12b880ee526e331440Fyodor Kupolov            run_dex2oat(input_fd, out_fd, input_file_name, out_path, swap_fd, pkgname,
124772ebebed876a62e719b098e43d9d516361bde029Andreas Gampe                        instruction_set, vm_safe_mode, debuggable, boot_complete);
1248c92fb6247d4c4fbc34c0a5deb26ccf538ca9ec81Richard Uhler        } else {
1249c92fb6247d4c4fbc34c0a5deb26ccf538ca9ec81Richard Uhler            ALOGE("Invalid dexopt needed: %d\n", dexopt_needed);
1250c92fb6247d4c4fbc34c0a5deb26ccf538ca9ec81Richard Uhler            exit(73);
12511705fc44fb85c4232637f9f7189c3bdca98a63d5Brian Carlstrom        }
125294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        exit(68);   /* only get here on exec failure */
125394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    } else {
125463568b1430d741f40ca008391c854ef1cc880138MÃ¥rten Kongstad        res = wait_child(pid);
125563568b1430d741f40ca008391c854ef1cc880138MÃ¥rten Kongstad        if (res == 0) {
12567365a10689df23334d245b211ce272502ad20669Alex Light            ALOGV("DexInv: --- END '%s' (success) ---\n", input_file);
125763568b1430d741f40ca008391c854ef1cc880138MÃ¥rten Kongstad        } else {
12587365a10689df23334d245b211ce272502ad20669Alex Light            ALOGE("DexInv: --- END '%s' --- status=0x%04x, process failed\n", input_file, res);
125994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood            goto fail;
126094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        }
126194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    }
126294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
12637365a10689df23334d245b211ce272502ad20669Alex Light    ut.actime = input_stat.st_atime;
12647365a10689df23334d245b211ce272502ad20669Alex Light    ut.modtime = input_stat.st_mtime;
12651705fc44fb85c4232637f9f7189c3bdca98a63d5Brian Carlstrom    utime(out_path, &ut);
12661705fc44fb85c4232637f9f7189c3bdca98a63d5Brian Carlstrom
12671705fc44fb85c4232637f9f7189c3bdca98a63d5Brian Carlstrom    close(out_fd);
12687365a10689df23334d245b211ce272502ad20669Alex Light    close(input_fd);
1269e1c01353c4dc6058a384eea9853238d2a87040dbAndreas Gampe    if (swap_fd != -1) {
1270e1c01353c4dc6058a384eea9853238d2a87040dbAndreas Gampe        close(swap_fd);
1271e1c01353c4dc6058a384eea9853238d2a87040dbAndreas Gampe    }
127294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    return 0;
127394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
127494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwoodfail:
12751705fc44fb85c4232637f9f7189c3bdca98a63d5Brian Carlstrom    if (out_fd >= 0) {
12761705fc44fb85c4232637f9f7189c3bdca98a63d5Brian Carlstrom        close(out_fd);
12771705fc44fb85c4232637f9f7189c3bdca98a63d5Brian Carlstrom        unlink(out_path);
127894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    }
12797365a10689df23334d245b211ce272502ad20669Alex Light    if (input_fd >= 0) {
12807365a10689df23334d245b211ce272502ad20669Alex Light        close(input_fd);
128194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    }
128294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    return -1;
128394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood}
128494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
1285091ea779d4e575856c04d51d82f45cc8a6155b5eNarayan Kamathint mark_boot_complete(const char* instruction_set)
1286091ea779d4e575856c04d51d82f45cc8a6155b5eNarayan Kamath{
1287091ea779d4e575856c04d51d82f45cc8a6155b5eNarayan Kamath  char boot_marker_path[PKG_PATH_MAX];
1288091ea779d4e575856c04d51d82f45cc8a6155b5eNarayan Kamath  sprintf(boot_marker_path,"%s%s/.booting", DALVIK_CACHE_PREFIX, instruction_set);
1289091ea779d4e575856c04d51d82f45cc8a6155b5eNarayan Kamath
1290091ea779d4e575856c04d51d82f45cc8a6155b5eNarayan Kamath  ALOGV("mark_boot_complete : %s", boot_marker_path);
1291091ea779d4e575856c04d51d82f45cc8a6155b5eNarayan Kamath  if (unlink(boot_marker_path) != 0) {
1292091ea779d4e575856c04d51d82f45cc8a6155b5eNarayan Kamath      ALOGE("Unable to unlink boot marker at %s, error=%s", boot_marker_path,
1293091ea779d4e575856c04d51d82f45cc8a6155b5eNarayan Kamath            strerror(errno));
1294091ea779d4e575856c04d51d82f45cc8a6155b5eNarayan Kamath      return -1;
1295091ea779d4e575856c04d51d82f45cc8a6155b5eNarayan Kamath  }
1296091ea779d4e575856c04d51d82f45cc8a6155b5eNarayan Kamath
1297091ea779d4e575856c04d51d82f45cc8a6155b5eNarayan Kamath  return 0;
1298091ea779d4e575856c04d51d82f45cc8a6155b5eNarayan Kamath}
1299091ea779d4e575856c04d51d82f45cc8a6155b5eNarayan Kamath
130094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwoodvoid mkinnerdirs(char* path, int basepos, mode_t mode, int uid, int gid,
130194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        struct stat* statbuf)
130294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood{
130394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    while (path[basepos] != 0) {
130494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        if (path[basepos] == '/') {
130594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood            path[basepos] = 0;
130694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood            if (lstat(path, statbuf) < 0) {
130794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood                ALOGV("Making directory: %s\n", path);
130894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood                if (mkdir(path, mode) == 0) {
130994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood                    chown(path, uid, gid);
131094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood                } else {
131194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood                    ALOGW("Unable to make directory %s: %s\n", path, strerror(errno));
131294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood                }
131394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood            }
131494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood            path[basepos] = '/';
131594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood            basepos++;
131694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        }
131794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        basepos++;
131894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    }
131994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood}
132094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
132194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwoodint movefileordir(char* srcpath, char* dstpath, int dstbasepos,
132294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        int dstuid, int dstgid, struct stat* statbuf)
132394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood{
132494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    DIR *d;
132594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    struct dirent *de;
132694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    int res;
132794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
132894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    int srcend = strlen(srcpath);
132994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    int dstend = strlen(dstpath);
1330d93707342a61e66bc3eb2145628158452f577f42Dave Allison
133194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    if (lstat(srcpath, statbuf) < 0) {
133294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        ALOGW("Unable to stat %s: %s\n", srcpath, strerror(errno));
133394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        return 1;
133494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    }
1335d93707342a61e66bc3eb2145628158452f577f42Dave Allison
133694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    if ((statbuf->st_mode&S_IFDIR) == 0) {
133794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        mkinnerdirs(dstpath, dstbasepos, S_IRWXU|S_IRWXG|S_IXOTH,
133894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood                dstuid, dstgid, statbuf);
133994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        ALOGV("Renaming %s to %s (uid %d)\n", srcpath, dstpath, dstuid);
134094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        if (rename(srcpath, dstpath) >= 0) {
134194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood            if (chown(dstpath, dstuid, dstgid) < 0) {
134294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood                ALOGE("cannot chown %s: %s\n", dstpath, strerror(errno));
134394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood                unlink(dstpath);
134494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood                return 1;
134594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood            }
134694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        } else {
134794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood            ALOGW("Unable to rename %s to %s: %s\n",
134894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood                srcpath, dstpath, strerror(errno));
134994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood            return 1;
135094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        }
135194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        return 0;
135294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    }
135394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
135494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    d = opendir(srcpath);
135594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    if (d == NULL) {
135694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        ALOGW("Unable to opendir %s: %s\n", srcpath, strerror(errno));
135794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        return 1;
135894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    }
135994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
136094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    res = 0;
1361d93707342a61e66bc3eb2145628158452f577f42Dave Allison
136294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    while ((de = readdir(d))) {
136394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        const char *name = de->d_name;
136494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood            /* always skip "." and ".." */
136594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        if (name[0] == '.') {
136694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood            if (name[1] == 0) continue;
136794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood            if ((name[1] == '.') && (name[2] == 0)) continue;
136894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        }
1369d93707342a61e66bc3eb2145628158452f577f42Dave Allison
137094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        if ((srcend+strlen(name)) >= (PKG_PATH_MAX-2)) {
137194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood            ALOGW("Source path too long; skipping: %s/%s\n", srcpath, name);
137294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood            continue;
137394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        }
1374d93707342a61e66bc3eb2145628158452f577f42Dave Allison
137594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        if ((dstend+strlen(name)) >= (PKG_PATH_MAX-2)) {
137694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood            ALOGW("Destination path too long; skipping: %s/%s\n", dstpath, name);
137794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood            continue;
137894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        }
1379d93707342a61e66bc3eb2145628158452f577f42Dave Allison
138094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        srcpath[srcend] = dstpath[dstend] = '/';
138194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        strcpy(srcpath+srcend+1, name);
138294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        strcpy(dstpath+dstend+1, name);
1383d93707342a61e66bc3eb2145628158452f577f42Dave Allison
138494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        if (movefileordir(srcpath, dstpath, dstbasepos, dstuid, dstgid, statbuf) != 0) {
138594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood            res = 1;
138694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        }
1387d93707342a61e66bc3eb2145628158452f577f42Dave Allison
138894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        // Note: we will be leaving empty directories behind in srcpath,
138994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        // but that is okay, the package manager will be erasing all of the
139094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        // data associated with .apks that disappear.
1391d93707342a61e66bc3eb2145628158452f577f42Dave Allison
139294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        srcpath[srcend] = dstpath[dstend] = 0;
139394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    }
1394d93707342a61e66bc3eb2145628158452f577f42Dave Allison
139594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    closedir(d);
139694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    return res;
139794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood}
139894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
139994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwoodint movefiles()
140094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood{
140194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    DIR *d;
140294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    int dfd, subfd;
140394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    struct dirent *de;
140494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    struct stat s;
140594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    char buf[PKG_PATH_MAX+1];
140694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    int bufp, bufe, bufi, readlen;
140794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
140894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    char srcpkg[PKG_NAME_MAX];
140994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    char dstpkg[PKG_NAME_MAX];
141094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    char srcpath[PKG_PATH_MAX];
141194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    char dstpath[PKG_PATH_MAX];
141294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    int dstuid=-1, dstgid=-1;
141394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    int hasspace;
141494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
141594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    d = opendir(UPDATE_COMMANDS_DIR_PREFIX);
141694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    if (d == NULL) {
141794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        goto done;
141894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    }
141994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    dfd = dirfd(d);
142094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
142194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        /* Iterate through all files in the directory, executing the
142294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood         * file movements requested there-in.
142394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood         */
142494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    while ((de = readdir(d))) {
142594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        const char *name = de->d_name;
142694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
142794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        if (de->d_type == DT_DIR) {
142894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood            continue;
142994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        } else {
143094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood            subfd = openat(dfd, name, O_RDONLY);
143194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood            if (subfd < 0) {
143294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood                ALOGW("Unable to open update commands at %s%s\n",
143394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood                        UPDATE_COMMANDS_DIR_PREFIX, name);
143494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood                continue;
143594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood            }
1436d93707342a61e66bc3eb2145628158452f577f42Dave Allison
143794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood            bufp = 0;
143894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood            bufe = 0;
143994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood            buf[PKG_PATH_MAX] = 0;
144094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood            srcpkg[0] = dstpkg[0] = 0;
144194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood            while (1) {
144294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood                bufi = bufp;
144394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood                while (bufi < bufe && buf[bufi] != '\n') {
144494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood                    bufi++;
144594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood                }
144694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood                if (bufi < bufe) {
144794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood                    buf[bufi] = 0;
144894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood                    ALOGV("Processing line: %s\n", buf+bufp);
144994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood                    hasspace = 0;
145094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood                    while (bufp < bufi && isspace(buf[bufp])) {
145194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood                        hasspace = 1;
145294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood                        bufp++;
145394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood                    }
145494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood                    if (buf[bufp] == '#' || bufp == bufi) {
145594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood                        // skip comments and empty lines.
145694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood                    } else if (hasspace) {
145794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood                        if (dstpkg[0] == 0) {
145894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood                            ALOGW("Path before package line in %s%s: %s\n",
145994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood                                    UPDATE_COMMANDS_DIR_PREFIX, name, buf+bufp);
146094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood                        } else if (srcpkg[0] == 0) {
146194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood                            // Skip -- source package no longer exists.
146294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood                        } else {
146394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood                            ALOGV("Move file: %s (from %s to %s)\n", buf+bufp, srcpkg, dstpkg);
146494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood                            if (!create_move_path(srcpath, srcpkg, buf+bufp, 0) &&
146594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood                                    !create_move_path(dstpath, dstpkg, buf+bufp, 0)) {
146694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood                                movefileordir(srcpath, dstpath,
146794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood                                        strlen(dstpath)-strlen(buf+bufp),
146894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood                                        dstuid, dstgid, &s);
146994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood                            }
147094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood                        }
147194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood                    } else {
147294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood                        char* div = strchr(buf+bufp, ':');
147394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood                        if (div == NULL) {
147494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood                            ALOGW("Bad package spec in %s%s; no ':' sep: %s\n",
147594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood                                    UPDATE_COMMANDS_DIR_PREFIX, name, buf+bufp);
147694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood                        } else {
147794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood                            *div = 0;
147894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood                            div++;
147994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood                            if (strlen(buf+bufp) < PKG_NAME_MAX) {
148094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood                                strcpy(dstpkg, buf+bufp);
148194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood                            } else {
148294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood                                srcpkg[0] = dstpkg[0] = 0;
148394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood                                ALOGW("Package name too long in %s%s: %s\n",
148494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood                                        UPDATE_COMMANDS_DIR_PREFIX, name, buf+bufp);
148594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood                            }
148694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood                            if (strlen(div) < PKG_NAME_MAX) {
148794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood                                strcpy(srcpkg, div);
148894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood                            } else {
148994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood                                srcpkg[0] = dstpkg[0] = 0;
149094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood                                ALOGW("Package name too long in %s%s: %s\n",
149194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood                                        UPDATE_COMMANDS_DIR_PREFIX, name, div);
149294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood                            }
149394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood                            if (srcpkg[0] != 0) {
149494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood                                if (!create_pkg_path(srcpath, srcpkg, PKG_DIR_POSTFIX, 0)) {
149594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood                                    if (lstat(srcpath, &s) < 0) {
149694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood                                        // Package no longer exists -- skip.
149794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood                                        srcpkg[0] = 0;
149894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood                                    }
149994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood                                } else {
150094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood                                    srcpkg[0] = 0;
150194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood                                    ALOGW("Can't create path %s in %s%s\n",
150294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood                                            div, UPDATE_COMMANDS_DIR_PREFIX, name);
150394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood                                }
150494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood                                if (srcpkg[0] != 0) {
150594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood                                    if (!create_pkg_path(dstpath, dstpkg, PKG_DIR_POSTFIX, 0)) {
150694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood                                        if (lstat(dstpath, &s) == 0) {
150794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood                                            dstuid = s.st_uid;
150894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood                                            dstgid = s.st_gid;
150994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood                                        } else {
151094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood                                            // Destination package doesn't
151194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood                                            // exist...  due to original-package,
151294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood                                            // this is normal, so don't be
151394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood                                            // noisy about it.
151494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood                                            srcpkg[0] = 0;
151594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood                                        }
151694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood                                    } else {
151794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood                                        srcpkg[0] = 0;
151894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood                                        ALOGW("Can't create path %s in %s%s\n",
151994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood                                                div, UPDATE_COMMANDS_DIR_PREFIX, name);
152094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood                                    }
152194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood                                }
152294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood                                ALOGV("Transfering from %s to %s: uid=%d\n",
152394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood                                    srcpkg, dstpkg, dstuid);
152494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood                            }
152594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood                        }
152694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood                    }
152794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood                    bufp = bufi+1;
152894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood                } else {
152994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood                    if (bufp == 0) {
153094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood                        if (bufp < bufe) {
153194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood                            ALOGW("Line too long in %s%s, skipping: %s\n",
153294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood                                    UPDATE_COMMANDS_DIR_PREFIX, name, buf);
153394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood                        }
153494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood                    } else if (bufp < bufe) {
153594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood                        memcpy(buf, buf+bufp, bufe-bufp);
153694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood                        bufe -= bufp;
153794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood                        bufp = 0;
153894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood                    }
153994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood                    readlen = read(subfd, buf+bufe, PKG_PATH_MAX-bufe);
154094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood                    if (readlen < 0) {
154194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood                        ALOGW("Failure reading update commands in %s%s: %s\n",
154294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood                                UPDATE_COMMANDS_DIR_PREFIX, name, strerror(errno));
154394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood                        break;
154494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood                    } else if (readlen == 0) {
154594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood                        break;
154694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood                    }
154794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood                    bufe += readlen;
154894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood                    buf[bufe] = 0;
154994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood                    ALOGV("Read buf: %s\n", buf);
155094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood                }
155194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood            }
155294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood            close(subfd);
155394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        }
155494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    }
155594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    closedir(d);
155694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwooddone:
155794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    return 0;
155894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood}
155994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
1560c03de09173f98506e73e7cf7df21fe11795d4b24Jeff Sharkeyint linklib(const char* uuid, const char* pkgname, const char* asecLibDir, int userId)
156194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood{
156294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    struct stat s, libStat;
156394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    int rc = 0;
156494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
1565d792118c493806eeb24a8203f508e6e18fe93bd7Jeff Sharkey    std::string _pkgdir(create_data_user_package_path(uuid, userId, pkgname));
1566c03de09173f98506e73e7cf7df21fe11795d4b24Jeff Sharkey    std::string _libsymlink(_pkgdir + PKG_LIB_POSTFIX);
1567c03de09173f98506e73e7cf7df21fe11795d4b24Jeff Sharkey
1568c03de09173f98506e73e7cf7df21fe11795d4b24Jeff Sharkey    const char* pkgdir = _pkgdir.c_str();
1569c03de09173f98506e73e7cf7df21fe11795d4b24Jeff Sharkey    const char* libsymlink = _libsymlink.c_str();
157094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
157194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    if (stat(pkgdir, &s) < 0) return -1;
157294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
157394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    if (chown(pkgdir, AID_INSTALL, AID_INSTALL) < 0) {
157494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        ALOGE("failed to chown '%s': %s\n", pkgdir, strerror(errno));
157594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        return -1;
157694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    }
157794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
157894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    if (chmod(pkgdir, 0700) < 0) {
157994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        ALOGE("linklib() 1: failed to chmod '%s': %s\n", pkgdir, strerror(errno));
158094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        rc = -1;
158194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        goto out;
158294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    }
158394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
158494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    if (lstat(libsymlink, &libStat) < 0) {
158594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        if (errno != ENOENT) {
158694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood            ALOGE("couldn't stat lib dir: %s\n", strerror(errno));
158794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood            rc = -1;
158894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood            goto out;
158994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        }
159094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    } else {
159194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        if (S_ISDIR(libStat.st_mode)) {
15923aee2c5c749dc2589f001b26fae1ec958ec89524Narayan Kamath            if (delete_dir_contents(libsymlink, 1, NULL) < 0) {
159394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood                rc = -1;
159494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood                goto out;
159594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood            }
159694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        } else if (S_ISLNK(libStat.st_mode)) {
159794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood            if (unlink(libsymlink) < 0) {
159894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood                ALOGE("couldn't unlink lib dir: %s\n", strerror(errno));
159994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood                rc = -1;
160094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood                goto out;
160194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood            }
160294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        }
160394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    }
160494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
160594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    if (symlink(asecLibDir, libsymlink) < 0) {
160694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        ALOGE("couldn't symlink directory '%s' -> '%s': %s\n", libsymlink, asecLibDir,
160794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood                strerror(errno));
160894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        rc = -errno;
160994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        goto out;
161094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    }
161194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
161294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwoodout:
161394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    if (chmod(pkgdir, s.st_mode) < 0) {
161494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        ALOGE("linklib() 2: failed to chmod '%s': %s\n", pkgdir, strerror(errno));
161594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        rc = -errno;
161694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    }
161794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
161894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    if (chown(pkgdir, s.st_uid, s.st_gid) < 0) {
161994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        ALOGE("failed to chown '%s' : %s\n", pkgdir, strerror(errno));
162094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        return -errno;
162194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    }
162294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
162394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    return rc;
162494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood}
162563568b1430d741f40ca008391c854ef1cc880138MÃ¥rten Kongstad
162663568b1430d741f40ca008391c854ef1cc880138MÃ¥rten Kongstadstatic void run_idmap(const char *target_apk, const char *overlay_apk, int idmap_fd)
162763568b1430d741f40ca008391c854ef1cc880138MÃ¥rten Kongstad{
162863568b1430d741f40ca008391c854ef1cc880138MÃ¥rten Kongstad    static const char *IDMAP_BIN = "/system/bin/idmap";
162963568b1430d741f40ca008391c854ef1cc880138MÃ¥rten Kongstad    static const size_t MAX_INT_LEN = 32;
163063568b1430d741f40ca008391c854ef1cc880138MÃ¥rten Kongstad    char idmap_str[MAX_INT_LEN];
163163568b1430d741f40ca008391c854ef1cc880138MÃ¥rten Kongstad
163263568b1430d741f40ca008391c854ef1cc880138MÃ¥rten Kongstad    snprintf(idmap_str, sizeof(idmap_str), "%d", idmap_fd);
163363568b1430d741f40ca008391c854ef1cc880138MÃ¥rten Kongstad
163463568b1430d741f40ca008391c854ef1cc880138MÃ¥rten Kongstad    execl(IDMAP_BIN, IDMAP_BIN, "--fd", target_apk, overlay_apk, idmap_str, (char*)NULL);
163563568b1430d741f40ca008391c854ef1cc880138MÃ¥rten Kongstad    ALOGE("execl(%s) failed: %s\n", IDMAP_BIN, strerror(errno));
163663568b1430d741f40ca008391c854ef1cc880138MÃ¥rten Kongstad}
163763568b1430d741f40ca008391c854ef1cc880138MÃ¥rten Kongstad
163863568b1430d741f40ca008391c854ef1cc880138MÃ¥rten Kongstad// Transform string /a/b/c.apk to (prefix)/a@b@c.apk@(suffix)
163963568b1430d741f40ca008391c854ef1cc880138MÃ¥rten Kongstad// eg /a/b/c.apk to /data/resource-cache/a@b@c.apk@idmap
164063568b1430d741f40ca008391c854ef1cc880138MÃ¥rten Kongstadstatic int flatten_path(const char *prefix, const char *suffix,
164163568b1430d741f40ca008391c854ef1cc880138MÃ¥rten Kongstad        const char *overlay_path, char *idmap_path, size_t N)
164263568b1430d741f40ca008391c854ef1cc880138MÃ¥rten Kongstad{
164363568b1430d741f40ca008391c854ef1cc880138MÃ¥rten Kongstad    if (overlay_path == NULL || idmap_path == NULL) {
164463568b1430d741f40ca008391c854ef1cc880138MÃ¥rten Kongstad        return -1;
164563568b1430d741f40ca008391c854ef1cc880138MÃ¥rten Kongstad    }
164663568b1430d741f40ca008391c854ef1cc880138MÃ¥rten Kongstad    const size_t len_overlay_path = strlen(overlay_path);
164763568b1430d741f40ca008391c854ef1cc880138MÃ¥rten Kongstad    // will access overlay_path + 1 further below; requires absolute path
164863568b1430d741f40ca008391c854ef1cc880138MÃ¥rten Kongstad    if (len_overlay_path < 2 || *overlay_path != '/') {
164963568b1430d741f40ca008391c854ef1cc880138MÃ¥rten Kongstad        return -1;
165063568b1430d741f40ca008391c854ef1cc880138MÃ¥rten Kongstad    }
165163568b1430d741f40ca008391c854ef1cc880138MÃ¥rten Kongstad    const size_t len_idmap_root = strlen(prefix);
165263568b1430d741f40ca008391c854ef1cc880138MÃ¥rten Kongstad    const size_t len_suffix = strlen(suffix);
165363568b1430d741f40ca008391c854ef1cc880138MÃ¥rten Kongstad    if (SIZE_MAX - len_idmap_root < len_overlay_path ||
165463568b1430d741f40ca008391c854ef1cc880138MÃ¥rten Kongstad            SIZE_MAX - (len_idmap_root + len_overlay_path) < len_suffix) {
165563568b1430d741f40ca008391c854ef1cc880138MÃ¥rten Kongstad        // additions below would cause overflow
165663568b1430d741f40ca008391c854ef1cc880138MÃ¥rten Kongstad        return -1;
165763568b1430d741f40ca008391c854ef1cc880138MÃ¥rten Kongstad    }
165863568b1430d741f40ca008391c854ef1cc880138MÃ¥rten Kongstad    if (N < len_idmap_root + len_overlay_path + len_suffix) {
165963568b1430d741f40ca008391c854ef1cc880138MÃ¥rten Kongstad        return -1;
166063568b1430d741f40ca008391c854ef1cc880138MÃ¥rten Kongstad    }
166163568b1430d741f40ca008391c854ef1cc880138MÃ¥rten Kongstad    memset(idmap_path, 0, N);
166263568b1430d741f40ca008391c854ef1cc880138MÃ¥rten Kongstad    snprintf(idmap_path, N, "%s%s%s", prefix, overlay_path + 1, suffix);
166363568b1430d741f40ca008391c854ef1cc880138MÃ¥rten Kongstad    char *ch = idmap_path + len_idmap_root;
166463568b1430d741f40ca008391c854ef1cc880138MÃ¥rten Kongstad    while (*ch != '\0') {
166563568b1430d741f40ca008391c854ef1cc880138MÃ¥rten Kongstad        if (*ch == '/') {
166663568b1430d741f40ca008391c854ef1cc880138MÃ¥rten Kongstad            *ch = '@';
166763568b1430d741f40ca008391c854ef1cc880138MÃ¥rten Kongstad        }
166863568b1430d741f40ca008391c854ef1cc880138MÃ¥rten Kongstad        ++ch;
166963568b1430d741f40ca008391c854ef1cc880138MÃ¥rten Kongstad    }
167063568b1430d741f40ca008391c854ef1cc880138MÃ¥rten Kongstad    return 0;
167163568b1430d741f40ca008391c854ef1cc880138MÃ¥rten Kongstad}
167263568b1430d741f40ca008391c854ef1cc880138MÃ¥rten Kongstad
167363568b1430d741f40ca008391c854ef1cc880138MÃ¥rten Kongstadint idmap(const char *target_apk, const char *overlay_apk, uid_t uid)
167463568b1430d741f40ca008391c854ef1cc880138MÃ¥rten Kongstad{
167563568b1430d741f40ca008391c854ef1cc880138MÃ¥rten Kongstad    ALOGV("idmap target_apk=%s overlay_apk=%s uid=%d\n", target_apk, overlay_apk, uid);
167663568b1430d741f40ca008391c854ef1cc880138MÃ¥rten Kongstad
167763568b1430d741f40ca008391c854ef1cc880138MÃ¥rten Kongstad    int idmap_fd = -1;
167863568b1430d741f40ca008391c854ef1cc880138MÃ¥rten Kongstad    char idmap_path[PATH_MAX];
167963568b1430d741f40ca008391c854ef1cc880138MÃ¥rten Kongstad
168063568b1430d741f40ca008391c854ef1cc880138MÃ¥rten Kongstad    if (flatten_path(IDMAP_PREFIX, IDMAP_SUFFIX, overlay_apk,
168163568b1430d741f40ca008391c854ef1cc880138MÃ¥rten Kongstad                idmap_path, sizeof(idmap_path)) == -1) {
168263568b1430d741f40ca008391c854ef1cc880138MÃ¥rten Kongstad        ALOGE("idmap cannot generate idmap path for overlay %s\n", overlay_apk);
168363568b1430d741f40ca008391c854ef1cc880138MÃ¥rten Kongstad        goto fail;
168463568b1430d741f40ca008391c854ef1cc880138MÃ¥rten Kongstad    }
168563568b1430d741f40ca008391c854ef1cc880138MÃ¥rten Kongstad
168663568b1430d741f40ca008391c854ef1cc880138MÃ¥rten Kongstad    unlink(idmap_path);
168763568b1430d741f40ca008391c854ef1cc880138MÃ¥rten Kongstad    idmap_fd = open(idmap_path, O_RDWR | O_CREAT | O_EXCL, 0644);
168863568b1430d741f40ca008391c854ef1cc880138MÃ¥rten Kongstad    if (idmap_fd < 0) {
168963568b1430d741f40ca008391c854ef1cc880138MÃ¥rten Kongstad        ALOGE("idmap cannot open '%s' for output: %s\n", idmap_path, strerror(errno));
169063568b1430d741f40ca008391c854ef1cc880138MÃ¥rten Kongstad        goto fail;
169163568b1430d741f40ca008391c854ef1cc880138MÃ¥rten Kongstad    }
169263568b1430d741f40ca008391c854ef1cc880138MÃ¥rten Kongstad    if (fchown(idmap_fd, AID_SYSTEM, uid) < 0) {
169363568b1430d741f40ca008391c854ef1cc880138MÃ¥rten Kongstad        ALOGE("idmap cannot chown '%s'\n", idmap_path);
169463568b1430d741f40ca008391c854ef1cc880138MÃ¥rten Kongstad        goto fail;
169563568b1430d741f40ca008391c854ef1cc880138MÃ¥rten Kongstad    }
169663568b1430d741f40ca008391c854ef1cc880138MÃ¥rten Kongstad    if (fchmod(idmap_fd, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH) < 0) {
169763568b1430d741f40ca008391c854ef1cc880138MÃ¥rten Kongstad        ALOGE("idmap cannot chmod '%s'\n", idmap_path);
169863568b1430d741f40ca008391c854ef1cc880138MÃ¥rten Kongstad        goto fail;
169963568b1430d741f40ca008391c854ef1cc880138MÃ¥rten Kongstad    }
170063568b1430d741f40ca008391c854ef1cc880138MÃ¥rten Kongstad
170163568b1430d741f40ca008391c854ef1cc880138MÃ¥rten Kongstad    pid_t pid;
170263568b1430d741f40ca008391c854ef1cc880138MÃ¥rten Kongstad    pid = fork();
170363568b1430d741f40ca008391c854ef1cc880138MÃ¥rten Kongstad    if (pid == 0) {
170463568b1430d741f40ca008391c854ef1cc880138MÃ¥rten Kongstad        /* child -- drop privileges before continuing */
170563568b1430d741f40ca008391c854ef1cc880138MÃ¥rten Kongstad        if (setgid(uid) != 0) {
170663568b1430d741f40ca008391c854ef1cc880138MÃ¥rten Kongstad            ALOGE("setgid(%d) failed during idmap\n", uid);
170763568b1430d741f40ca008391c854ef1cc880138MÃ¥rten Kongstad            exit(1);
170863568b1430d741f40ca008391c854ef1cc880138MÃ¥rten Kongstad        }
170963568b1430d741f40ca008391c854ef1cc880138MÃ¥rten Kongstad        if (setuid(uid) != 0) {
171063568b1430d741f40ca008391c854ef1cc880138MÃ¥rten Kongstad            ALOGE("setuid(%d) failed during idmap\n", uid);
171163568b1430d741f40ca008391c854ef1cc880138MÃ¥rten Kongstad            exit(1);
171263568b1430d741f40ca008391c854ef1cc880138MÃ¥rten Kongstad        }
171363568b1430d741f40ca008391c854ef1cc880138MÃ¥rten Kongstad        if (flock(idmap_fd, LOCK_EX | LOCK_NB) != 0) {
171463568b1430d741f40ca008391c854ef1cc880138MÃ¥rten Kongstad            ALOGE("flock(%s) failed during idmap: %s\n", idmap_path, strerror(errno));
171563568b1430d741f40ca008391c854ef1cc880138MÃ¥rten Kongstad            exit(1);
171663568b1430d741f40ca008391c854ef1cc880138MÃ¥rten Kongstad        }
171763568b1430d741f40ca008391c854ef1cc880138MÃ¥rten Kongstad
171863568b1430d741f40ca008391c854ef1cc880138MÃ¥rten Kongstad        run_idmap(target_apk, overlay_apk, idmap_fd);
171963568b1430d741f40ca008391c854ef1cc880138MÃ¥rten Kongstad        exit(1); /* only if exec call to idmap failed */
172063568b1430d741f40ca008391c854ef1cc880138MÃ¥rten Kongstad    } else {
172163568b1430d741f40ca008391c854ef1cc880138MÃ¥rten Kongstad        int status = wait_child(pid);
172263568b1430d741f40ca008391c854ef1cc880138MÃ¥rten Kongstad        if (status != 0) {
172363568b1430d741f40ca008391c854ef1cc880138MÃ¥rten Kongstad            ALOGE("idmap failed, status=0x%04x\n", status);
172463568b1430d741f40ca008391c854ef1cc880138MÃ¥rten Kongstad            goto fail;
172563568b1430d741f40ca008391c854ef1cc880138MÃ¥rten Kongstad        }
172663568b1430d741f40ca008391c854ef1cc880138MÃ¥rten Kongstad    }
172763568b1430d741f40ca008391c854ef1cc880138MÃ¥rten Kongstad
172863568b1430d741f40ca008391c854ef1cc880138MÃ¥rten Kongstad    close(idmap_fd);
172963568b1430d741f40ca008391c854ef1cc880138MÃ¥rten Kongstad    return 0;
173063568b1430d741f40ca008391c854ef1cc880138MÃ¥rten Kongstadfail:
173163568b1430d741f40ca008391c854ef1cc880138MÃ¥rten Kongstad    if (idmap_fd >= 0) {
173263568b1430d741f40ca008391c854ef1cc880138MÃ¥rten Kongstad        close(idmap_fd);
173363568b1430d741f40ca008391c854ef1cc880138MÃ¥rten Kongstad        unlink(idmap_path);
173463568b1430d741f40ca008391c854ef1cc880138MÃ¥rten Kongstad    }
173563568b1430d741f40ca008391c854ef1cc880138MÃ¥rten Kongstad    return -1;
173663568b1430d741f40ca008391c854ef1cc880138MÃ¥rten Kongstad}
1737e9887e46cea4a095e4219927eadbe4c57bb1a5eeRobert Craig
17386fe28a06012250da85f808a0869f87e06e0bcce9Jeff Sharkeyint restorecon_data(const char* uuid, const char* pkgName,
17390ad7a11003ad76381452c3751368b8e3f42b1f6aAndreas Gampe                    const char* seinfo, uid_t uid)
1740e9887e46cea4a095e4219927eadbe4c57bb1a5eeRobert Craig{
1741da30dc7336f03ca629fe173db1425fdce989119cRobert Craig    struct dirent *entry;
1742da30dc7336f03ca629fe173db1425fdce989119cRobert Craig    DIR *d;
1743da30dc7336f03ca629fe173db1425fdce989119cRobert Craig    struct stat s;
1744da30dc7336f03ca629fe173db1425fdce989119cRobert Craig    int ret = 0;
1745e9887e46cea4a095e4219927eadbe4c57bb1a5eeRobert Craig
1746da30dc7336f03ca629fe173db1425fdce989119cRobert Craig    // SELINUX_ANDROID_RESTORECON_DATADATA flag is set by libselinux. Not needed here.
1747da30dc7336f03ca629fe173db1425fdce989119cRobert Craig    unsigned int flags = SELINUX_ANDROID_RESTORECON_RECURSE;
1748e9887e46cea4a095e4219927eadbe4c57bb1a5eeRobert Craig
1749da30dc7336f03ca629fe173db1425fdce989119cRobert Craig    if (!pkgName || !seinfo) {
1750da30dc7336f03ca629fe173db1425fdce989119cRobert Craig        ALOGE("Package name or seinfo tag is null when trying to restorecon.");
1751da30dc7336f03ca629fe173db1425fdce989119cRobert Craig        return -1;
1752da30dc7336f03ca629fe173db1425fdce989119cRobert Craig    }
1753e9887e46cea4a095e4219927eadbe4c57bb1a5eeRobert Craig
175441ea424413c0381ef2aa15fc5bd5d4b88abd23c4Jeff Sharkey    // Special case for owner on internal storage
175541ea424413c0381ef2aa15fc5bd5d4b88abd23c4Jeff Sharkey    if (uuid == nullptr) {
1756d792118c493806eeb24a8203f508e6e18fe93bd7Jeff Sharkey        std::string path(create_data_user_package_path(nullptr, 0, pkgName));
1757e9887e46cea4a095e4219927eadbe4c57bb1a5eeRobert Craig
175841ea424413c0381ef2aa15fc5bd5d4b88abd23c4Jeff Sharkey        if (selinux_android_restorecon_pkgdir(path.c_str(), seinfo, uid, flags) < 0) {
175941ea424413c0381ef2aa15fc5bd5d4b88abd23c4Jeff Sharkey            PLOG(ERROR) << "restorecon failed for " << path;
176041ea424413c0381ef2aa15fc5bd5d4b88abd23c4Jeff Sharkey            ret |= -1;
176141ea424413c0381ef2aa15fc5bd5d4b88abd23c4Jeff Sharkey        }
1762e9887e46cea4a095e4219927eadbe4c57bb1a5eeRobert Craig    }
1763e9887e46cea4a095e4219927eadbe4c57bb1a5eeRobert Craig
1764da30dc7336f03ca629fe173db1425fdce989119cRobert Craig    // Relabel package directory for all secondary users.
176541ea424413c0381ef2aa15fc5bd5d4b88abd23c4Jeff Sharkey    std::string userdir(create_data_path(uuid) + "/" + SECONDARY_USER_PREFIX);
176641ea424413c0381ef2aa15fc5bd5d4b88abd23c4Jeff Sharkey    d = opendir(userdir.c_str());
1767da30dc7336f03ca629fe173db1425fdce989119cRobert Craig    if (d == NULL) {
1768da30dc7336f03ca629fe173db1425fdce989119cRobert Craig        return -1;
1769da30dc7336f03ca629fe173db1425fdce989119cRobert Craig    }
1770da30dc7336f03ca629fe173db1425fdce989119cRobert Craig
1771da30dc7336f03ca629fe173db1425fdce989119cRobert Craig    while ((entry = readdir(d))) {
1772da30dc7336f03ca629fe173db1425fdce989119cRobert Craig        if (entry->d_type != DT_DIR) {
1773da30dc7336f03ca629fe173db1425fdce989119cRobert Craig            continue;
1774da30dc7336f03ca629fe173db1425fdce989119cRobert Craig        }
1775da30dc7336f03ca629fe173db1425fdce989119cRobert Craig
1776da30dc7336f03ca629fe173db1425fdce989119cRobert Craig        const char *user = entry->d_name;
1777da30dc7336f03ca629fe173db1425fdce989119cRobert Craig        // Ignore "." and ".."
1778da30dc7336f03ca629fe173db1425fdce989119cRobert Craig        if (!strcmp(user, ".") || !strcmp(user, "..")) {
1779da30dc7336f03ca629fe173db1425fdce989119cRobert Craig            continue;
1780da30dc7336f03ca629fe173db1425fdce989119cRobert Craig        }
1781da30dc7336f03ca629fe173db1425fdce989119cRobert Craig
1782da30dc7336f03ca629fe173db1425fdce989119cRobert Craig        // user directories start with a number
1783da30dc7336f03ca629fe173db1425fdce989119cRobert Craig        if (user[0] < '0' || user[0] > '9') {
1784da30dc7336f03ca629fe173db1425fdce989119cRobert Craig            ALOGE("Expecting numbered directory during restorecon. Instead got '%s'.", user);
1785da30dc7336f03ca629fe173db1425fdce989119cRobert Craig            continue;
1786da30dc7336f03ca629fe173db1425fdce989119cRobert Craig        }
1787da30dc7336f03ca629fe173db1425fdce989119cRobert Craig
1788e36372423000a906bafae68844ebc6c42d09335aJeff Sharkey        std::string pkgdir(StringPrintf("%s%s/%s", userdir.c_str(), user, pkgName));
178941ea424413c0381ef2aa15fc5bd5d4b88abd23c4Jeff Sharkey        if (stat(pkgdir.c_str(), &s) < 0) {
1790da30dc7336f03ca629fe173db1425fdce989119cRobert Craig            continue;
1791da30dc7336f03ca629fe173db1425fdce989119cRobert Craig        }
1792da30dc7336f03ca629fe173db1425fdce989119cRobert Craig
179341ea424413c0381ef2aa15fc5bd5d4b88abd23c4Jeff Sharkey        if (selinux_android_restorecon_pkgdir(pkgdir.c_str(), seinfo, s.st_uid, flags) < 0) {
179441ea424413c0381ef2aa15fc5bd5d4b88abd23c4Jeff Sharkey            PLOG(ERROR) << "restorecon failed for " << pkgdir;
1795da30dc7336f03ca629fe173db1425fdce989119cRobert Craig            ret |= -1;
1796da30dc7336f03ca629fe173db1425fdce989119cRobert Craig        }
1797da30dc7336f03ca629fe173db1425fdce989119cRobert Craig    }
1798da30dc7336f03ca629fe173db1425fdce989119cRobert Craig
1799da30dc7336f03ca629fe173db1425fdce989119cRobert Craig    closedir(d);
1800e9887e46cea4a095e4219927eadbe4c57bb1a5eeRobert Craig    return ret;
1801e9887e46cea4a095e4219927eadbe4c57bb1a5eeRobert Craig}
18023aee2c5c749dc2589f001b26fae1ec958ec89524Narayan Kamath
180388ce4ff7a95ea2008fa28f12b880ee526e331440Fyodor Kupolovint create_oat_dir(const char* oat_dir, const char* instruction_set)
180488ce4ff7a95ea2008fa28f12b880ee526e331440Fyodor Kupolov{
180588ce4ff7a95ea2008fa28f12b880ee526e331440Fyodor Kupolov    char oat_instr_dir[PKG_PATH_MAX];
180688ce4ff7a95ea2008fa28f12b880ee526e331440Fyodor Kupolov
180788ce4ff7a95ea2008fa28f12b880ee526e331440Fyodor Kupolov    if (validate_apk_path(oat_dir)) {
180888ce4ff7a95ea2008fa28f12b880ee526e331440Fyodor Kupolov        ALOGE("invalid apk path '%s' (bad prefix)\n", oat_dir);
180988ce4ff7a95ea2008fa28f12b880ee526e331440Fyodor Kupolov        return -1;
181088ce4ff7a95ea2008fa28f12b880ee526e331440Fyodor Kupolov    }
18118eed7e6a9bb527af7380ec13b390c6e2955eba6aFyodor Kupolov    if (fs_prepare_dir(oat_dir, S_IRWXU | S_IRWXG | S_IXOTH, AID_SYSTEM, AID_INSTALL)) {
181288ce4ff7a95ea2008fa28f12b880ee526e331440Fyodor Kupolov        return -1;
181388ce4ff7a95ea2008fa28f12b880ee526e331440Fyodor Kupolov    }
181488ce4ff7a95ea2008fa28f12b880ee526e331440Fyodor Kupolov    if (selinux_android_restorecon(oat_dir, 0)) {
181588ce4ff7a95ea2008fa28f12b880ee526e331440Fyodor Kupolov        ALOGE("cannot restorecon dir '%s': %s\n", oat_dir, strerror(errno));
181688ce4ff7a95ea2008fa28f12b880ee526e331440Fyodor Kupolov        return -1;
181788ce4ff7a95ea2008fa28f12b880ee526e331440Fyodor Kupolov    }
181888ce4ff7a95ea2008fa28f12b880ee526e331440Fyodor Kupolov    snprintf(oat_instr_dir, PKG_PATH_MAX, "%s/%s", oat_dir, instruction_set);
18198eed7e6a9bb527af7380ec13b390c6e2955eba6aFyodor Kupolov    if (fs_prepare_dir(oat_instr_dir, S_IRWXU | S_IRWXG | S_IXOTH, AID_SYSTEM, AID_INSTALL)) {
182088ce4ff7a95ea2008fa28f12b880ee526e331440Fyodor Kupolov        return -1;
182188ce4ff7a95ea2008fa28f12b880ee526e331440Fyodor Kupolov    }
182288ce4ff7a95ea2008fa28f12b880ee526e331440Fyodor Kupolov    return 0;
182388ce4ff7a95ea2008fa28f12b880ee526e331440Fyodor Kupolov}
182488ce4ff7a95ea2008fa28f12b880ee526e331440Fyodor Kupolov
182588ce4ff7a95ea2008fa28f12b880ee526e331440Fyodor Kupolovint rm_package_dir(const char* apk_path)
182688ce4ff7a95ea2008fa28f12b880ee526e331440Fyodor Kupolov{
182788ce4ff7a95ea2008fa28f12b880ee526e331440Fyodor Kupolov    if (validate_apk_path(apk_path)) {
182888ce4ff7a95ea2008fa28f12b880ee526e331440Fyodor Kupolov        ALOGE("invalid apk path '%s' (bad prefix)\n", apk_path);
182988ce4ff7a95ea2008fa28f12b880ee526e331440Fyodor Kupolov        return -1;
183088ce4ff7a95ea2008fa28f12b880ee526e331440Fyodor Kupolov    }
183188ce4ff7a95ea2008fa28f12b880ee526e331440Fyodor Kupolov    return delete_dir_contents(apk_path, 1 /* also_delete_dir */ , NULL /* exclusion_predicate */);
183288ce4ff7a95ea2008fa28f12b880ee526e331440Fyodor Kupolov}
183388ce4ff7a95ea2008fa28f12b880ee526e331440Fyodor Kupolov
1834d845c96128a40ca5802c0840ae190fa0af7d4735Narayan Kamathint link_file(const char* relative_path, const char* from_base, const char* to_base) {
1835d845c96128a40ca5802c0840ae190fa0af7d4735Narayan Kamath    char from_path[PKG_PATH_MAX];
1836d845c96128a40ca5802c0840ae190fa0af7d4735Narayan Kamath    char to_path[PKG_PATH_MAX];
1837d845c96128a40ca5802c0840ae190fa0af7d4735Narayan Kamath    snprintf(from_path, PKG_PATH_MAX, "%s/%s", from_base, relative_path);
1838d845c96128a40ca5802c0840ae190fa0af7d4735Narayan Kamath    snprintf(to_path, PKG_PATH_MAX, "%s/%s", to_base, relative_path);
1839d845c96128a40ca5802c0840ae190fa0af7d4735Narayan Kamath
1840d845c96128a40ca5802c0840ae190fa0af7d4735Narayan Kamath    if (validate_apk_path_subdirs(from_path)) {
1841d845c96128a40ca5802c0840ae190fa0af7d4735Narayan Kamath        ALOGE("invalid app data sub-path '%s' (bad prefix)\n", from_path);
1842d845c96128a40ca5802c0840ae190fa0af7d4735Narayan Kamath        return -1;
1843d845c96128a40ca5802c0840ae190fa0af7d4735Narayan Kamath    }
1844d845c96128a40ca5802c0840ae190fa0af7d4735Narayan Kamath
1845d845c96128a40ca5802c0840ae190fa0af7d4735Narayan Kamath    if (validate_apk_path_subdirs(to_path)) {
1846d845c96128a40ca5802c0840ae190fa0af7d4735Narayan Kamath        ALOGE("invalid app data sub-path '%s' (bad prefix)\n", to_path);
1847d845c96128a40ca5802c0840ae190fa0af7d4735Narayan Kamath        return -1;
1848d845c96128a40ca5802c0840ae190fa0af7d4735Narayan Kamath    }
1849d845c96128a40ca5802c0840ae190fa0af7d4735Narayan Kamath
1850d845c96128a40ca5802c0840ae190fa0af7d4735Narayan Kamath    const int ret = link(from_path, to_path);
1851d845c96128a40ca5802c0840ae190fa0af7d4735Narayan Kamath    if (ret < 0) {
1852d845c96128a40ca5802c0840ae190fa0af7d4735Narayan Kamath        ALOGE("link(%s, %s) failed : %s", from_path, to_path, strerror(errno));
1853d845c96128a40ca5802c0840ae190fa0af7d4735Narayan Kamath        return -1;
1854d845c96128a40ca5802c0840ae190fa0af7d4735Narayan Kamath    }
1855d845c96128a40ca5802c0840ae190fa0af7d4735Narayan Kamath
1856d845c96128a40ca5802c0840ae190fa0af7d4735Narayan Kamath    return 0;
1857d845c96128a40ca5802c0840ae190fa0af7d4735Narayan Kamath}
1858d845c96128a40ca5802c0840ae190fa0af7d4735Narayan Kamath
185988ce4ff7a95ea2008fa28f12b880ee526e331440Fyodor Kupolovint calculate_oat_file_path(char path[PKG_PATH_MAX], const char *oat_dir, const char *apk_path,
186088ce4ff7a95ea2008fa28f12b880ee526e331440Fyodor Kupolov        const char *instruction_set) {
186188ce4ff7a95ea2008fa28f12b880ee526e331440Fyodor Kupolov    char *file_name_start;
186288ce4ff7a95ea2008fa28f12b880ee526e331440Fyodor Kupolov    char *file_name_end;
186388ce4ff7a95ea2008fa28f12b880ee526e331440Fyodor Kupolov
186488ce4ff7a95ea2008fa28f12b880ee526e331440Fyodor Kupolov    file_name_start = strrchr(apk_path, '/');
186588ce4ff7a95ea2008fa28f12b880ee526e331440Fyodor Kupolov    if (file_name_start == NULL) {
186688ce4ff7a95ea2008fa28f12b880ee526e331440Fyodor Kupolov         ALOGE("apk_path '%s' has no '/'s in it\n", apk_path);
186788ce4ff7a95ea2008fa28f12b880ee526e331440Fyodor Kupolov        return -1;
186888ce4ff7a95ea2008fa28f12b880ee526e331440Fyodor Kupolov    }
186988ce4ff7a95ea2008fa28f12b880ee526e331440Fyodor Kupolov    file_name_end = strrchr(apk_path, '.');
187088ce4ff7a95ea2008fa28f12b880ee526e331440Fyodor Kupolov    if (file_name_end < file_name_start) {
187188ce4ff7a95ea2008fa28f12b880ee526e331440Fyodor Kupolov        ALOGE("apk_path '%s' has no extension\n", apk_path);
187288ce4ff7a95ea2008fa28f12b880ee526e331440Fyodor Kupolov        return -1;
187388ce4ff7a95ea2008fa28f12b880ee526e331440Fyodor Kupolov    }
187488ce4ff7a95ea2008fa28f12b880ee526e331440Fyodor Kupolov
187588ce4ff7a95ea2008fa28f12b880ee526e331440Fyodor Kupolov    // Calculate file_name
187688ce4ff7a95ea2008fa28f12b880ee526e331440Fyodor Kupolov    int file_name_len = file_name_end - file_name_start - 1;
187788ce4ff7a95ea2008fa28f12b880ee526e331440Fyodor Kupolov    char file_name[file_name_len + 1];
187888ce4ff7a95ea2008fa28f12b880ee526e331440Fyodor Kupolov    memcpy(file_name, file_name_start + 1, file_name_len);
187988ce4ff7a95ea2008fa28f12b880ee526e331440Fyodor Kupolov    file_name[file_name_len] = '\0';
188088ce4ff7a95ea2008fa28f12b880ee526e331440Fyodor Kupolov
188188ce4ff7a95ea2008fa28f12b880ee526e331440Fyodor Kupolov    // <apk_parent_dir>/oat/<isa>/<file_name>.odex
188288ce4ff7a95ea2008fa28f12b880ee526e331440Fyodor Kupolov    snprintf(path, PKG_PATH_MAX, "%s/%s/%s.odex", oat_dir, instruction_set, file_name);
188388ce4ff7a95ea2008fa28f12b880ee526e331440Fyodor Kupolov    return 0;
188488ce4ff7a95ea2008fa28f12b880ee526e331440Fyodor Kupolov}
1885