194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood/*
294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood** Copyright 2008, The Android Open Source Project
394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood**
494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood** Licensed under the Apache License, Version 2.0 (the "License");
594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood** you may not use this file except in compliance with the License.
694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood** You may obtain a copy of the License at
794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood**
894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood**     http://www.apache.org/licenses/LICENSE-2.0
994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood**
1094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood** Unless required by applicable law or agreed to in writing, software
1194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood** distributed under the License is distributed on an "AS IS" BASIS,
1294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood** See the License for the specific language governing permissions and
1494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood** limitations under the License.
1594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood*/
1694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
17d747129e1e8876f5a50f47156ec50b6969a638e4Nick Kralevich#include <sys/capability.h>
1894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood#include <linux/prctl.h>
1994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
2094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood#include "installd.h"
2194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
2294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
2394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood#define BUFFER_MAX    1024  /* input buffer for commands */
2494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood#define TOKEN_MAX     8     /* max number of arguments in buffer */
2594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood#define REPLY_MAX     256   /* largest reply allowed */
2694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
2794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwoodstatic int do_ping(char **arg, char reply[REPLY_MAX])
2894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood{
2994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    return 0;
3094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood}
3194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
3294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwoodstatic int do_install(char **arg, char reply[REPLY_MAX])
3394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood{
344d3fd4e9988c0eb284dd5104c4dea757f723c716Robert Craig    return install(arg[0], atoi(arg[1]), atoi(arg[2]), arg[3]); /* pkgname, uid, gid, seinfo */
3594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood}
3694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
3794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwoodstatic int do_dexopt(char **arg, char reply[REPLY_MAX])
3894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood{
3994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        /* apk_path, uid, is_public */
4094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    return dexopt(arg[0], atoi(arg[1]), atoi(arg[2]));
4194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood}
4294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
4394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwoodstatic int do_move_dex(char **arg, char reply[REPLY_MAX])
4494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood{
4594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    return move_dex(arg[0], arg[1]); /* src, dst */
4694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood}
4794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
4894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwoodstatic int do_rm_dex(char **arg, char reply[REPLY_MAX])
4994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood{
5094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    return rm_dex(arg[0]); /* pkgname */
5194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood}
5294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
5394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwoodstatic int do_remove(char **arg, char reply[REPLY_MAX])
5494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood{
5594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    return uninstall(arg[0], atoi(arg[1])); /* pkgname, userid */
5694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood}
5794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
5894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwoodstatic int do_rename(char **arg, char reply[REPLY_MAX])
5994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood{
6094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    return renamepkg(arg[0], arg[1]); /* oldpkgname, newpkgname */
6194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood}
6294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
6394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwoodstatic int do_fixuid(char **arg, char reply[REPLY_MAX])
6494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood{
6594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    return fix_uid(arg[0], atoi(arg[1]), atoi(arg[2])); /* pkgname, uid, gid */
6694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood}
6794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
6894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwoodstatic int do_free_cache(char **arg, char reply[REPLY_MAX]) /* TODO int:free_size */
6994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood{
7094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    return free_cache((int64_t)atoll(arg[0])); /* free_size */
7194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood}
7294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
7394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwoodstatic int do_rm_cache(char **arg, char reply[REPLY_MAX])
7494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood{
7594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    return delete_cache(arg[0], atoi(arg[1])); /* pkgname, userid */
7694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood}
7794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
7894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwoodstatic int do_get_size(char **arg, char reply[REPLY_MAX])
7994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood{
8094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    int64_t codesize = 0;
8194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    int64_t datasize = 0;
8294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    int64_t cachesize = 0;
8394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    int64_t asecsize = 0;
8494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    int res = 0;
8594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
86abe4fe5b46157ecd2a52d28abf938c816c3ce878Jeff Sharkey        /* pkgdir, userid, apkpath */
878b41780d73930b37b6254cc1dac5607c843839c0Dianne Hackborn    res = get_size(arg[0], atoi(arg[1]), arg[2], arg[3], arg[4], arg[5],
8894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood            &codesize, &datasize, &cachesize, &asecsize);
8994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
9094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    /*
9194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood     * Each int64_t can take up 22 characters printed out. Make sure it
9294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood     * doesn't go over REPLY_MAX in the future.
9394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood     */
9494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    snprintf(reply, REPLY_MAX, "%" PRId64 " %" PRId64 " %" PRId64 " %" PRId64,
9594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood            codesize, datasize, cachesize, asecsize);
9694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    return res;
9794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood}
9894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
9994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwoodstatic int do_rm_user_data(char **arg, char reply[REPLY_MAX])
10094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood{
10194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    return delete_user_data(arg[0], atoi(arg[1])); /* pkgname, userid */
10294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood}
10394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
10494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwoodstatic int do_mk_user_data(char **arg, char reply[REPLY_MAX])
10594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood{
106a2d838a542c34d2887a0ec1fafa5f47566d595e9Nick Kralevich    return make_user_data(arg[0], atoi(arg[1]), atoi(arg[2])); /* pkgname, uid, userid */
10794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood}
10894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
10994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwoodstatic int do_rm_user(char **arg, char reply[REPLY_MAX])
11094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood{
111abe4fe5b46157ecd2a52d28abf938c816c3ce878Jeff Sharkey    return delete_user(atoi(arg[0])); /* userid */
11294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood}
11394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
11494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwoodstatic int do_movefiles(char **arg, char reply[REPLY_MAX])
11594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood{
11694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    return movefiles();
11794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood}
11894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
11994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwoodstatic int do_linklib(char **arg, char reply[REPLY_MAX])
12094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood{
12194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    return linklib(arg[0], arg[1], atoi(arg[2]));
12294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood}
12394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
12494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwoodstruct cmdinfo {
12594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    const char *name;
12694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    unsigned numargs;
12794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    int (*func)(char **arg, char reply[REPLY_MAX]);
12894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood};
12994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
13094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwoodstruct cmdinfo cmds[] = {
13194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    { "ping",                 0, do_ping },
1324d3fd4e9988c0eb284dd5104c4dea757f723c716Robert Craig    { "install",              4, do_install },
13394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    { "dexopt",               3, do_dexopt },
13494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    { "movedex",              2, do_move_dex },
13594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    { "rmdex",                1, do_rm_dex },
13694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    { "remove",               2, do_remove },
13794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    { "rename",               2, do_rename },
13894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    { "fixuid",               3, do_fixuid },
13994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    { "freecache",            1, do_free_cache },
14094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    { "rmcache",              2, do_rm_cache },
1418b41780d73930b37b6254cc1dac5607c843839c0Dianne Hackborn    { "getsize",              6, do_get_size },
14294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    { "rmuserdata",           2, do_rm_user_data },
14394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    { "movefiles",            0, do_movefiles },
14494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    { "linklib",              3, do_linklib },
145a2d838a542c34d2887a0ec1fafa5f47566d595e9Nick Kralevich    { "mkuserdata",           3, do_mk_user_data },
14694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    { "rmuser",               1, do_rm_user },
14794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood};
14894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
14994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwoodstatic int readx(int s, void *_buf, int count)
15094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood{
15194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    char *buf = _buf;
15294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    int n = 0, r;
15394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    if (count < 0) return -1;
15494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    while (n < count) {
15594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        r = read(s, buf + n, count - n);
15694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        if (r < 0) {
15794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood            if (errno == EINTR) continue;
15894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood            ALOGE("read error: %s\n", strerror(errno));
15994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood            return -1;
16094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        }
16194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        if (r == 0) {
16294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood            ALOGE("eof\n");
16394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood            return -1; /* EOF */
16494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        }
16594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        n += r;
16694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    }
16794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    return 0;
16894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood}
16994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
17094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwoodstatic int writex(int s, const void *_buf, int count)
17194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood{
17294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    const char *buf = _buf;
17394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    int n = 0, r;
17494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    if (count < 0) return -1;
17594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    while (n < count) {
17694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        r = write(s, buf + n, count - n);
17794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        if (r < 0) {
17894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood            if (errno == EINTR) continue;
17994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood            ALOGE("write error: %s\n", strerror(errno));
18094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood            return -1;
18194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        }
18294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        n += r;
18394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    }
18494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    return 0;
18594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood}
18694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
18794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
18894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood/* Tokenize the command buffer, locate a matching command,
18994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood * ensure that the required number of arguments are provided,
19094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood * call the function(), return the result.
19194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood */
19294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwoodstatic int execute(int s, char cmd[BUFFER_MAX])
19394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood{
19494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    char reply[REPLY_MAX];
19594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    char *arg[TOKEN_MAX+1];
19694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    unsigned i;
19794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    unsigned n = 0;
19894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    unsigned short count;
19994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    int ret = -1;
20094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
2011705fc44fb85c4232637f9f7189c3bdca98a63d5Brian Carlstrom    // ALOGI("execute('%s')\n", cmd);
20294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
20394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        /* default reply is "" */
20494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    reply[0] = 0;
20594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
20694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        /* n is number of args (not counting arg[0]) */
20794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    arg[0] = cmd;
20894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    while (*cmd) {
20994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        if (isspace(*cmd)) {
21094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood            *cmd++ = 0;
21194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood            n++;
21294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood            arg[n] = cmd;
21394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood            if (n == TOKEN_MAX) {
21494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood                ALOGE("too many arguments\n");
21594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood                goto done;
21694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood            }
21794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        }
21894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        cmd++;
21994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    }
22094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
22194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    for (i = 0; i < sizeof(cmds) / sizeof(cmds[0]); i++) {
22294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        if (!strcmp(cmds[i].name,arg[0])) {
22394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood            if (n != cmds[i].numargs) {
22494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood                ALOGE("%s requires %d arguments (%d given)\n",
22594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood                     cmds[i].name, cmds[i].numargs, n);
22694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood            } else {
22794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood                ret = cmds[i].func(arg + 1, reply);
22894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood            }
22994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood            goto done;
23094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        }
23194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    }
23294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    ALOGE("unsupported command '%s'\n", arg[0]);
23394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
23494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwooddone:
23594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    if (reply[0]) {
23694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        n = snprintf(cmd, BUFFER_MAX, "%d %s", ret, reply);
23794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    } else {
23894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        n = snprintf(cmd, BUFFER_MAX, "%d", ret);
23994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    }
24094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    if (n > BUFFER_MAX) n = BUFFER_MAX;
24194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    count = n;
24294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
2431705fc44fb85c4232637f9f7189c3bdca98a63d5Brian Carlstrom    // ALOGI("reply: '%s'\n", cmd);
24494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    if (writex(s, &count, sizeof(count))) return -1;
24594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    if (writex(s, cmd, count)) return -1;
24694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    return 0;
24794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood}
24894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
24994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood/**
25094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood * Initialize all the global variables that are used elsewhere. Returns 0 upon
25194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood * success and -1 on error.
25294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood */
25394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwoodvoid free_globals() {
25494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    size_t i;
25594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
25694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    for (i = 0; i < android_system_dirs.count; i++) {
25794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        if (android_system_dirs.dirs[i].path != NULL) {
25894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood            free(android_system_dirs.dirs[i].path);
25994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        }
26094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    }
26194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
26294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    free(android_system_dirs.dirs);
26394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood}
26494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
26594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwoodint initialize_globals() {
26694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    // Get the android data directory.
26794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    if (get_path_from_env(&android_data_dir, "ANDROID_DATA") < 0) {
26894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        return -1;
26994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    }
27094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
27194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    // Get the android app directory.
27294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    if (copy_and_append(&android_app_dir, &android_data_dir, APP_SUBDIR) < 0) {
27394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        return -1;
27494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    }
27594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
27694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    // Get the android protected app directory.
27794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    if (copy_and_append(&android_app_private_dir, &android_data_dir, PRIVATE_APP_SUBDIR) < 0) {
27894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        return -1;
27994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    }
28094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
28194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    // Get the android app native library directory.
28294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    if (copy_and_append(&android_app_lib_dir, &android_data_dir, APP_LIB_SUBDIR) < 0) {
28394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        return -1;
28494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    }
28594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
28694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    // Get the sd-card ASEC mount point.
28794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    if (get_path_from_env(&android_asec_dir, "ASEC_MOUNTPOINT") < 0) {
28894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        return -1;
28994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    }
29094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
29194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    // Get the android media directory.
29294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    if (copy_and_append(&android_media_dir, &android_data_dir, MEDIA_SUBDIR) < 0) {
29394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        return -1;
29494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    }
29594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
29694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    // Take note of the system and vendor directories.
29794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    android_system_dirs.count = 2;
29894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
29994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    android_system_dirs.dirs = calloc(android_system_dirs.count, sizeof(dir_rec_t));
30094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    if (android_system_dirs.dirs == NULL) {
30194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        ALOGE("Couldn't allocate array for dirs; aborting\n");
30294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        return -1;
30394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    }
30494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
30594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    // system
30694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    if (get_path_from_env(&android_system_dirs.dirs[0], "ANDROID_ROOT") < 0) {
30794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        free_globals();
30894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        return -1;
30994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    }
31094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
31194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    // append "app/" to dirs[0]
31294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    char *system_app_path = build_string2(android_system_dirs.dirs[0].path, APP_SUBDIR);
31394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    android_system_dirs.dirs[0].path = system_app_path;
31494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    android_system_dirs.dirs[0].len = strlen(system_app_path);
31594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
31694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    // vendor
31794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    // TODO replace this with an environment variable (doesn't exist yet)
31894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    android_system_dirs.dirs[1].path = "/vendor/app/";
31994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    android_system_dirs.dirs[1].len = strlen(android_system_dirs.dirs[1].path);
32094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
32194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    return 0;
32294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood}
32394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
32494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwoodint initialize_directories() {
32594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    int res = -1;
32694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
32794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    // Read current filesystem layout version to handle upgrade paths
32894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    char version_path[PATH_MAX];
32994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    snprintf(version_path, PATH_MAX, "%s.layout_version", android_data_dir.path);
33094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
33194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    int oldVersion;
33294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    if (fs_read_atomic_int(version_path, &oldVersion) == -1) {
33394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        oldVersion = 0;
33494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    }
33594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    int version = oldVersion;
33694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
33794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    // /data/user
33894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    char *user_data_dir = build_string2(android_data_dir.path, SECONDARY_USER_PREFIX);
33994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    // /data/data
34094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    char *legacy_data_dir = build_string2(android_data_dir.path, PRIMARY_USER_PREFIX);
34194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    // /data/user/0
34294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    char *primary_data_dir = build_string3(android_data_dir.path, SECONDARY_USER_PREFIX, "0");
34394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    if (!user_data_dir || !legacy_data_dir || !primary_data_dir) {
34494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        goto fail;
34594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    }
34694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
34794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    // Make the /data/user directory if necessary
34894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    if (access(user_data_dir, R_OK) < 0) {
34994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        if (mkdir(user_data_dir, 0711) < 0) {
35094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood            goto fail;
35194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        }
35294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        if (chown(user_data_dir, AID_SYSTEM, AID_SYSTEM) < 0) {
35394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood            goto fail;
35494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        }
35594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        if (chmod(user_data_dir, 0711) < 0) {
35694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood            goto fail;
35794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        }
35894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    }
35994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    // Make the /data/user/0 symlink to /data/data if necessary
36094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    if (access(primary_data_dir, R_OK) < 0) {
36194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        if (symlink(legacy_data_dir, primary_data_dir)) {
36294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood            goto fail;
36394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        }
36494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    }
36594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
36694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    if (version == 0) {
36794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        // Introducing multi-user, so migrate /data/media contents into /data/media/0
36894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        ALOGD("Upgrading /data/media for multi-user");
36994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
37094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        // Ensure /data/media
37194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        if (fs_prepare_dir(android_media_dir.path, 0770, AID_MEDIA_RW, AID_MEDIA_RW) == -1) {
37294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood            goto fail;
37394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        }
37494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
37594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        // /data/media.tmp
37694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        char media_tmp_dir[PATH_MAX];
37794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        snprintf(media_tmp_dir, PATH_MAX, "%smedia.tmp", android_data_dir.path);
37894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
37994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        // Only copy when upgrade not already in progress
38094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        if (access(media_tmp_dir, F_OK) == -1) {
38194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood            if (rename(android_media_dir.path, media_tmp_dir) == -1) {
38294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood                ALOGE("Failed to move legacy media path: %s", strerror(errno));
38394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood                goto fail;
38494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood            }
38594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        }
38694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
38794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        // Create /data/media again
38894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        if (fs_prepare_dir(android_media_dir.path, 0770, AID_MEDIA_RW, AID_MEDIA_RW) == -1) {
38994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood            goto fail;
39094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        }
39194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
39294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        // /data/media/0
39394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        char owner_media_dir[PATH_MAX];
39494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        snprintf(owner_media_dir, PATH_MAX, "%s0", android_media_dir.path);
39594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
39694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        // Move any owner data into place
39794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        if (access(media_tmp_dir, F_OK) == 0) {
39894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood            if (rename(media_tmp_dir, owner_media_dir) == -1) {
39994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood                ALOGE("Failed to move owner media path: %s", strerror(errno));
40094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood                goto fail;
40194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood            }
40294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        }
40394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
40494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        // Ensure media directories for any existing users
40594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        DIR *dir;
40694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        struct dirent *dirent;
40794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        char user_media_dir[PATH_MAX];
40894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
40994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        dir = opendir(user_data_dir);
41094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        if (dir != NULL) {
41194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood            while ((dirent = readdir(dir))) {
41294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood                if (dirent->d_type == DT_DIR) {
41394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood                    const char *name = dirent->d_name;
41494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
41594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood                    // skip "." and ".."
41694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood                    if (name[0] == '.') {
41794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood                        if (name[1] == 0) continue;
41894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood                        if ((name[1] == '.') && (name[2] == 0)) continue;
41994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood                    }
42094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
42194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood                    // /data/media/<user_id>
42294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood                    snprintf(user_media_dir, PATH_MAX, "%s%s", android_media_dir.path, name);
42394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood                    if (fs_prepare_dir(user_media_dir, 0770, AID_MEDIA_RW, AID_MEDIA_RW) == -1) {
42494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood                        goto fail;
42594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood                    }
42694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood                }
42794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood            }
42894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood            closedir(dir);
42994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        }
43094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
43194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        version = 1;
43294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    }
43394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
43494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    // /data/media/obb
43594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    char media_obb_dir[PATH_MAX];
43694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    snprintf(media_obb_dir, PATH_MAX, "%sobb", android_media_dir.path);
43794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
43894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    if (version == 1) {
43994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        // Introducing /data/media/obb for sharing OBB across users; migrate
44094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        // any existing OBB files from owner.
44194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        ALOGD("Upgrading to shared /data/media/obb");
44294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
44394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        // /data/media/0/Android/obb
44494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        char owner_obb_path[PATH_MAX];
44594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        snprintf(owner_obb_path, PATH_MAX, "%s0/Android/obb", android_media_dir.path);
44694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
44794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        // Only move if target doesn't already exist
44894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        if (access(media_obb_dir, F_OK) != 0 && access(owner_obb_path, F_OK) == 0) {
44994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood            if (rename(owner_obb_path, media_obb_dir) == -1) {
45094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood                ALOGE("Failed to move OBB from owner: %s", strerror(errno));
45194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood                goto fail;
45294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood            }
45394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        }
45494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
45594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        version = 2;
45694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    }
45794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
45894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    if (ensure_media_user_dirs(0) == -1) {
45994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        ALOGE("Failed to setup media for user 0");
46094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        goto fail;
46194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    }
46294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    if (fs_prepare_dir(media_obb_dir, 0770, AID_MEDIA_RW, AID_MEDIA_RW) == -1) {
46394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        goto fail;
46494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    }
46594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
46694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    // Persist layout version if changed
46794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    if (version != oldVersion) {
46894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        if (fs_write_atomic_int(version_path, version) == -1) {
46994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood            ALOGE("Failed to save version to %s: %s", version_path, strerror(errno));
47094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood            goto fail;
47194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        }
47294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    }
47394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
47494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    // Success!
47594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    res = 0;
47694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
47794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwoodfail:
47894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    free(user_data_dir);
47994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    free(legacy_data_dir);
48094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    free(primary_data_dir);
48194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    return res;
48294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood}
48394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
48494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwoodstatic void drop_privileges() {
48594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    if (prctl(PR_SET_KEEPCAPS, 1) < 0) {
48694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        ALOGE("prctl(PR_SET_KEEPCAPS) failed: %s\n", strerror(errno));
48794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        exit(1);
48894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    }
48994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
49094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    if (setgid(AID_INSTALL) < 0) {
49194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        ALOGE("setgid() can't drop privileges; exiting.\n");
49294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        exit(1);
49394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    }
49494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
49594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    if (setuid(AID_INSTALL) < 0) {
49694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        ALOGE("setuid() can't drop privileges; exiting.\n");
49794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        exit(1);
49894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    }
49994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
50094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    struct __user_cap_header_struct capheader;
50194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    struct __user_cap_data_struct capdata[2];
50294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    memset(&capheader, 0, sizeof(capheader));
50394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    memset(&capdata, 0, sizeof(capdata));
50494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    capheader.version = _LINUX_CAPABILITY_VERSION_3;
50594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    capheader.pid = 0;
50694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
50794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    capdata[CAP_TO_INDEX(CAP_DAC_OVERRIDE)].permitted |= CAP_TO_MASK(CAP_DAC_OVERRIDE);
50894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    capdata[CAP_TO_INDEX(CAP_CHOWN)].permitted        |= CAP_TO_MASK(CAP_CHOWN);
50994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    capdata[CAP_TO_INDEX(CAP_SETUID)].permitted       |= CAP_TO_MASK(CAP_SETUID);
51094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    capdata[CAP_TO_INDEX(CAP_SETGID)].permitted       |= CAP_TO_MASK(CAP_SETGID);
51194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
51294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    capdata[0].effective = capdata[0].permitted;
51394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    capdata[1].effective = capdata[1].permitted;
51494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    capdata[0].inheritable = 0;
51594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    capdata[1].inheritable = 0;
51694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
51794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    if (capset(&capheader, &capdata[0]) < 0) {
51894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        ALOGE("capset failed: %s\n", strerror(errno));
51994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        exit(1);
52094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    }
52194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood}
52294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
52394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwoodint main(const int argc, const char *argv[]) {
52494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    char buf[BUFFER_MAX];
52594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    struct sockaddr addr;
52694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    socklen_t alen;
52794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    int lsocket, s, count;
52894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
52994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    ALOGI("installd firing up\n");
53094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
53194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    if (initialize_globals() < 0) {
53294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        ALOGE("Could not initialize globals; exiting.\n");
53394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        exit(1);
53494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    }
53594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
53694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    if (initialize_directories() < 0) {
53794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        ALOGE("Could not create directories; exiting.\n");
53894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        exit(1);
53994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    }
54094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
54194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    drop_privileges();
54294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
54394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    lsocket = android_get_control_socket(SOCKET_PATH);
54494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    if (lsocket < 0) {
54594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        ALOGE("Failed to get socket from environment: %s\n", strerror(errno));
54694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        exit(1);
54794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    }
54894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    if (listen(lsocket, 5)) {
54994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        ALOGE("Listen on socket failed: %s\n", strerror(errno));
55094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        exit(1);
55194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    }
55294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    fcntl(lsocket, F_SETFD, FD_CLOEXEC);
55394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
55494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    for (;;) {
55594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        alen = sizeof(addr);
55694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        s = accept(lsocket, &addr, &alen);
55794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        if (s < 0) {
55894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood            ALOGE("Accept failed: %s\n", strerror(errno));
55994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood            continue;
56094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        }
56194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        fcntl(s, F_SETFD, FD_CLOEXEC);
56294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
56394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        ALOGI("new connection\n");
56494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        for (;;) {
56594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood            unsigned short count;
56694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood            if (readx(s, &count, sizeof(count))) {
56794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood                ALOGE("failed to read size\n");
56894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood                break;
56994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood            }
57094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood            if ((count < 1) || (count >= BUFFER_MAX)) {
57194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood                ALOGE("invalid size %d\n", count);
57294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood                break;
57394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood            }
57494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood            if (readx(s, buf, count)) {
57594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood                ALOGE("failed to read command\n");
57694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood                break;
57794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood            }
57894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood            buf[count] = 0;
57994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood            if (execute(s, buf)) break;
58094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        }
58194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        ALOGI("closing connection\n");
58294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood        close(s);
58394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    }
58494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood
58594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood    return 0;
58694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood}
587