19066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/*
29066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project** Copyright 2008, The Android Open Source Project
39066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project**
49066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project** Licensed under the Apache License, Version 2.0 (the "License");
59066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project** you may not use this file except in compliance with the License.
69066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project** You may obtain a copy of the License at
79066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project**
89066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project**     http://www.apache.org/licenses/LICENSE-2.0
99066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project**
109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project** Unless required by applicable law or agreed to in writing, software
119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project** distributed under the License is distributed on an "AS IS" BASIS,
129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project** See the License for the specific language governing permissions and
149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project** limitations under the License.
159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project*/
169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include "installd.h"
189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#define BUFFER_MAX    1024  /* input buffer for commands */
219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#define TOKEN_MAX     8     /* max number of arguments in buffer */
229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#define REPLY_MAX     256   /* largest reply allowed */
239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic int do_ping(char **arg, char reply[REPLY_MAX])
259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return 0;
279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic int do_install(char **arg, char reply[REPLY_MAX])
309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
3135ab3ad61fcc349380d7e7f2fcf9a0dfbf76ae11Kenny Root    return install(arg[0], atoi(arg[1]), atoi(arg[2])); /* pkgname, uid, gid */
329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic int do_dexopt(char **arg, char reply[REPLY_MAX])
359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        /* apk_path, uid, is_public */
379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return dexopt(arg[0], atoi(arg[1]), atoi(arg[2]));
389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic int do_move_dex(char **arg, char reply[REPLY_MAX])
419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return move_dex(arg[0], arg[1]); /* src, dst */
439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic int do_rm_dex(char **arg, char reply[REPLY_MAX])
469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return rm_dex(arg[0]); /* pkgname */
489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic int do_remove(char **arg, char reply[REPLY_MAX])
519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
520b285499db739ba50f2f839d633e763c70e67f96Amith Yamasani    return uninstall(arg[0], atoi(arg[1])); /* pkgname, userid */
539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
55b858dfda5012a1040927ed62c3bb856c3294d882Dianne Hackbornstatic int do_rename(char **arg, char reply[REPLY_MAX])
56b858dfda5012a1040927ed62c3bb856c3294d882Dianne Hackborn{
5735ab3ad61fcc349380d7e7f2fcf9a0dfbf76ae11Kenny Root    return renamepkg(arg[0], arg[1]); /* oldpkgname, newpkgname */
58b858dfda5012a1040927ed62c3bb856c3294d882Dianne Hackborn}
59b858dfda5012a1040927ed62c3bb856c3294d882Dianne Hackborn
609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic int do_free_cache(char **arg, char reply[REPLY_MAX]) /* TODO int:free_size */
619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
623e319a9962434e1fae86b2180ad210170f02c152Kenny Root    return free_cache((int64_t)atoll(arg[0])); /* free_size */
639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic int do_rm_cache(char **arg, char reply[REPLY_MAX])
669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
6735ab3ad61fcc349380d7e7f2fcf9a0dfbf76ae11Kenny Root    return delete_cache(arg[0]); /* pkgname */
689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic int do_protect(char **arg, char reply[REPLY_MAX])
719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return protect(arg[0], atoi(arg[1])); /* pkgname, gid */
739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic int do_get_size(char **arg, char reply[REPLY_MAX])
769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
773e319a9962434e1fae86b2180ad210170f02c152Kenny Root    int64_t codesize = 0;
783e319a9962434e1fae86b2180ad210170f02c152Kenny Root    int64_t datasize = 0;
793e319a9962434e1fae86b2180ad210170f02c152Kenny Root    int64_t cachesize = 0;
80292f8bc9d1b790ab975a87a842c7fabc908b97e0Dianne Hackborn    int64_t asecsize = 0;
819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    int res = 0;
829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        /* pkgdir, apkpath */
84292f8bc9d1b790ab975a87a842c7fabc908b97e0Dianne Hackborn    res = get_size(arg[0], arg[1], arg[2], arg[3], &codesize, &datasize, &cachesize, &asecsize);
859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
863e319a9962434e1fae86b2180ad210170f02c152Kenny Root    /*
873e319a9962434e1fae86b2180ad210170f02c152Kenny Root     * Each int64_t can take up 22 characters printed out. Make sure it
883e319a9962434e1fae86b2180ad210170f02c152Kenny Root     * doesn't go over REPLY_MAX in the future.
893e319a9962434e1fae86b2180ad210170f02c152Kenny Root     */
90292f8bc9d1b790ab975a87a842c7fabc908b97e0Dianne Hackborn    snprintf(reply, REPLY_MAX, "%" PRId64 " %" PRId64 " %" PRId64 " %" PRId64,
91292f8bc9d1b790ab975a87a842c7fabc908b97e0Dianne Hackborn            codesize, datasize, cachesize, asecsize);
929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return res;
939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic int do_rm_user_data(char **arg, char reply[REPLY_MAX])
969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
970b285499db739ba50f2f839d633e763c70e67f96Amith Yamasani    return delete_user_data(arg[0], atoi(arg[1])); /* pkgname, userid */
980b285499db739ba50f2f839d633e763c70e67f96Amith Yamasani}
990b285499db739ba50f2f839d633e763c70e67f96Amith Yamasani
1000b285499db739ba50f2f839d633e763c70e67f96Amith Yamasanistatic int do_mk_user_data(char **arg, char reply[REPLY_MAX])
1010b285499db739ba50f2f839d633e763c70e67f96Amith Yamasani{
1020b285499db739ba50f2f839d633e763c70e67f96Amith Yamasani    return make_user_data(arg[0], atoi(arg[1]), atoi(arg[2])); /* pkgname, uid, userid */
1030b285499db739ba50f2f839d633e763c70e67f96Amith Yamasani}
1040b285499db739ba50f2f839d633e763c70e67f96Amith Yamasani
1050b285499db739ba50f2f839d633e763c70e67f96Amith Yamasanistatic int do_rm_user(char **arg, char reply[REPLY_MAX])
1060b285499db739ba50f2f839d633e763c70e67f96Amith Yamasani{
1070b285499db739ba50f2f839d633e763c70e67f96Amith Yamasani    return delete_persona(atoi(arg[0])); /* userid */
1089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
1099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
110b858dfda5012a1040927ed62c3bb856c3294d882Dianne Hackbornstatic int do_movefiles(char **arg, char reply[REPLY_MAX])
111b858dfda5012a1040927ed62c3bb856c3294d882Dianne Hackborn{
112b858dfda5012a1040927ed62c3bb856c3294d882Dianne Hackborn    return movefiles();
113b858dfda5012a1040927ed62c3bb856c3294d882Dianne Hackborn}
114b858dfda5012a1040927ed62c3bb856c3294d882Dianne Hackborn
1156a6b007c77e5cab7ee435506a4f65824f52028b6Kenny Rootstatic int do_linklib(char **arg, char reply[REPLY_MAX])
1166a6b007c77e5cab7ee435506a4f65824f52028b6Kenny Root{
1176a6b007c77e5cab7ee435506a4f65824f52028b6Kenny Root    return linklib(arg[0], arg[1]);
1186a6b007c77e5cab7ee435506a4f65824f52028b6Kenny Root}
1196a6b007c77e5cab7ee435506a4f65824f52028b6Kenny Root
1206a6b007c77e5cab7ee435506a4f65824f52028b6Kenny Rootstatic int do_unlinklib(char **arg, char reply[REPLY_MAX])
1216a6b007c77e5cab7ee435506a4f65824f52028b6Kenny Root{
1226a6b007c77e5cab7ee435506a4f65824f52028b6Kenny Root    return unlinklib(arg[0]);
1236a6b007c77e5cab7ee435506a4f65824f52028b6Kenny Root}
1246a6b007c77e5cab7ee435506a4f65824f52028b6Kenny Root
1259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstruct cmdinfo {
1269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    const char *name;
1279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    unsigned numargs;
1289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    int (*func)(char **arg, char reply[REPLY_MAX]);
1299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project};
1309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstruct cmdinfo cmds[] = {
1329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    { "ping",                 0, do_ping },
13335ab3ad61fcc349380d7e7f2fcf9a0dfbf76ae11Kenny Root    { "install",              3, do_install },
1349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    { "dexopt",               3, do_dexopt },
1359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    { "movedex",              2, do_move_dex },
1369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    { "rmdex",                1, do_rm_dex },
1370b285499db739ba50f2f839d633e763c70e67f96Amith Yamasani    { "remove",               2, do_remove },
13835ab3ad61fcc349380d7e7f2fcf9a0dfbf76ae11Kenny Root    { "rename",               2, do_rename },
1399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    { "freecache",            1, do_free_cache },
14035ab3ad61fcc349380d7e7f2fcf9a0dfbf76ae11Kenny Root    { "rmcache",              1, do_rm_cache },
1419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    { "protect",              2, do_protect },
142292f8bc9d1b790ab975a87a842c7fabc908b97e0Dianne Hackborn    { "getsize",              4, do_get_size },
1430b285499db739ba50f2f839d633e763c70e67f96Amith Yamasani    { "rmuserdata",           2, do_rm_user_data },
144b858dfda5012a1040927ed62c3bb856c3294d882Dianne Hackborn    { "movefiles",            0, do_movefiles },
1456a6b007c77e5cab7ee435506a4f65824f52028b6Kenny Root    { "linklib",              2, do_linklib },
1466a6b007c77e5cab7ee435506a4f65824f52028b6Kenny Root    { "unlinklib",            1, do_unlinklib },
1470b285499db739ba50f2f839d633e763c70e67f96Amith Yamasani    { "mkuserdata",           3, do_mk_user_data },
1480b285499db739ba50f2f839d633e763c70e67f96Amith Yamasani    { "rmuser",               1, do_rm_user },
1499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project};
1509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic int readx(int s, void *_buf, int count)
1529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
1539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    char *buf = _buf;
1549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    int n = 0, r;
1559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (count < 0) return -1;
1569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    while (n < count) {
1579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        r = read(s, buf + n, count - n);
1589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (r < 0) {
1599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (errno == EINTR) continue;
1609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            LOGE("read error: %s\n", strerror(errno));
1619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return -1;
1629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (r == 0) {
1649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            LOGE("eof\n");
1659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return -1; /* EOF */
1669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        n += r;
1689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return 0;
1709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
1719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic int writex(int s, const void *_buf, int count)
1739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
1749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    const char *buf = _buf;
1759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    int n = 0, r;
1769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (count < 0) return -1;
1779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    while (n < count) {
1789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        r = write(s, buf + n, count - n);
1799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (r < 0) {
1809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (errno == EINTR) continue;
1819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            LOGE("write error: %s\n", strerror(errno));
1829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return -1;
1839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        n += r;
1859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return 0;
1879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
1889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/* Tokenize the command buffer, locate a matching command,
1919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * ensure that the required number of arguments are provided,
1929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * call the function(), return the result.
1939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
1949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic int execute(int s, char cmd[BUFFER_MAX])
1959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
1969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    char reply[REPLY_MAX];
1979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    char *arg[TOKEN_MAX+1];
1989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    unsigned i;
1999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    unsigned n = 0;
2009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    unsigned short count;
2019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    int ret = -1;
2029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project//    LOGI("execute('%s')\n", cmd);
2049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        /* default reply is "" */
2069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    reply[0] = 0;
2079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        /* n is number of args (not counting arg[0]) */
2099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    arg[0] = cmd;
2109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    while (*cmd) {
2119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (isspace(*cmd)) {
2129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            *cmd++ = 0;
2139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            n++;
2149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            arg[n] = cmd;
2159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (n == TOKEN_MAX) {
2169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                LOGE("too many arguments\n");
2179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                goto done;
2189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
2199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        cmd++;
2219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    for (i = 0; i < sizeof(cmds) / sizeof(cmds[0]); i++) {
2249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (!strcmp(cmds[i].name,arg[0])) {
2259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (n != cmds[i].numargs) {
2269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                LOGE("%s requires %d arguments (%d given)\n",
2279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                     cmds[i].name, cmds[i].numargs, n);
2289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else {
2299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                ret = cmds[i].func(arg + 1, reply);
2309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
2319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            goto done;
2329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    LOGE("unsupported command '%s'\n", arg[0]);
2359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectdone:
2379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (reply[0]) {
2389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        n = snprintf(cmd, BUFFER_MAX, "%d %s", ret, reply);
2399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    } else {
2409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        n = snprintf(cmd, BUFFER_MAX, "%d", ret);
2419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (n > BUFFER_MAX) n = BUFFER_MAX;
2439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    count = n;
2449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project//    LOGI("reply: '%s'\n", cmd);
2469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (writex(s, &count, sizeof(count))) return -1;
2479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (writex(s, cmd, count)) return -1;
2489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return 0;
2499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
2509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
25186c9584559439504fc57ece2ccd9b6cbd568430cKenny Root/**
25286c9584559439504fc57ece2ccd9b6cbd568430cKenny Root * Initialize all the global variables that are used elsewhere. Returns 0 upon
25386c9584559439504fc57ece2ccd9b6cbd568430cKenny Root * success and -1 on error.
25486c9584559439504fc57ece2ccd9b6cbd568430cKenny Root */
25586c9584559439504fc57ece2ccd9b6cbd568430cKenny Rootvoid free_globals() {
25686c9584559439504fc57ece2ccd9b6cbd568430cKenny Root    size_t i;
25786c9584559439504fc57ece2ccd9b6cbd568430cKenny Root
25886c9584559439504fc57ece2ccd9b6cbd568430cKenny Root    for (i = 0; i < android_system_dirs.count; i++) {
25986c9584559439504fc57ece2ccd9b6cbd568430cKenny Root        if (android_system_dirs.dirs[i].path != NULL) {
26086c9584559439504fc57ece2ccd9b6cbd568430cKenny Root            free(android_system_dirs.dirs[i].path);
26186c9584559439504fc57ece2ccd9b6cbd568430cKenny Root        }
26286c9584559439504fc57ece2ccd9b6cbd568430cKenny Root    }
26386c9584559439504fc57ece2ccd9b6cbd568430cKenny Root
26486c9584559439504fc57ece2ccd9b6cbd568430cKenny Root    free(android_system_dirs.dirs);
26586c9584559439504fc57ece2ccd9b6cbd568430cKenny Root}
26686c9584559439504fc57ece2ccd9b6cbd568430cKenny Root
26786c9584559439504fc57ece2ccd9b6cbd568430cKenny Rootint initialize_globals() {
26886c9584559439504fc57ece2ccd9b6cbd568430cKenny Root    // Get the android data directory.
26986c9584559439504fc57ece2ccd9b6cbd568430cKenny Root    if (get_path_from_env(&android_data_dir, "ANDROID_DATA") < 0) {
27086c9584559439504fc57ece2ccd9b6cbd568430cKenny Root        return -1;
27186c9584559439504fc57ece2ccd9b6cbd568430cKenny Root    }
27286c9584559439504fc57ece2ccd9b6cbd568430cKenny Root
27386c9584559439504fc57ece2ccd9b6cbd568430cKenny Root    // Get the android app directory.
27486c9584559439504fc57ece2ccd9b6cbd568430cKenny Root    if (copy_and_append(&android_app_dir, &android_data_dir, APP_SUBDIR) < 0) {
27586c9584559439504fc57ece2ccd9b6cbd568430cKenny Root        return -1;
27686c9584559439504fc57ece2ccd9b6cbd568430cKenny Root    }
27786c9584559439504fc57ece2ccd9b6cbd568430cKenny Root
27886c9584559439504fc57ece2ccd9b6cbd568430cKenny Root    // Get the android protected app directory.
27986c9584559439504fc57ece2ccd9b6cbd568430cKenny Root    if (copy_and_append(&android_app_private_dir, &android_data_dir, PRIVATE_APP_SUBDIR) < 0) {
28086c9584559439504fc57ece2ccd9b6cbd568430cKenny Root        return -1;
28186c9584559439504fc57ece2ccd9b6cbd568430cKenny Root    }
28286c9584559439504fc57ece2ccd9b6cbd568430cKenny Root
28386c9584559439504fc57ece2ccd9b6cbd568430cKenny Root    // Get the sd-card ASEC mount point.
28486c9584559439504fc57ece2ccd9b6cbd568430cKenny Root    if (get_path_from_env(&android_asec_dir, "ASEC_MOUNTPOINT") < 0) {
28586c9584559439504fc57ece2ccd9b6cbd568430cKenny Root        return -1;
28686c9584559439504fc57ece2ccd9b6cbd568430cKenny Root    }
28786c9584559439504fc57ece2ccd9b6cbd568430cKenny Root
28886c9584559439504fc57ece2ccd9b6cbd568430cKenny Root    // Take note of the system and vendor directories.
28986c9584559439504fc57ece2ccd9b6cbd568430cKenny Root    android_system_dirs.count = 2;
29086c9584559439504fc57ece2ccd9b6cbd568430cKenny Root
29186c9584559439504fc57ece2ccd9b6cbd568430cKenny Root    android_system_dirs.dirs = calloc(android_system_dirs.count, sizeof(dir_rec_t));
29286c9584559439504fc57ece2ccd9b6cbd568430cKenny Root    if (android_system_dirs.dirs == NULL) {
29386c9584559439504fc57ece2ccd9b6cbd568430cKenny Root        LOGE("Couldn't allocate array for dirs; aborting\n");
29486c9584559439504fc57ece2ccd9b6cbd568430cKenny Root        return -1;
29586c9584559439504fc57ece2ccd9b6cbd568430cKenny Root    }
29686c9584559439504fc57ece2ccd9b6cbd568430cKenny Root
29786c9584559439504fc57ece2ccd9b6cbd568430cKenny Root    // system
29886c9584559439504fc57ece2ccd9b6cbd568430cKenny Root    if (get_path_from_env(&android_system_dirs.dirs[0], "ANDROID_ROOT") < 0) {
29986c9584559439504fc57ece2ccd9b6cbd568430cKenny Root        free_globals();
30086c9584559439504fc57ece2ccd9b6cbd568430cKenny Root        return -1;
30186c9584559439504fc57ece2ccd9b6cbd568430cKenny Root    }
30286c9584559439504fc57ece2ccd9b6cbd568430cKenny Root
3030b285499db739ba50f2f839d633e763c70e67f96Amith Yamasani    // append "app/" to dirs[0]
3040b285499db739ba50f2f839d633e763c70e67f96Amith Yamasani    char *system_app_path = build_string2(android_system_dirs.dirs[0].path, APP_SUBDIR);
3050b285499db739ba50f2f839d633e763c70e67f96Amith Yamasani    android_system_dirs.dirs[0].path = system_app_path;
3060b285499db739ba50f2f839d633e763c70e67f96Amith Yamasani    android_system_dirs.dirs[0].len = strlen(system_app_path);
3070b285499db739ba50f2f839d633e763c70e67f96Amith Yamasani
30886c9584559439504fc57ece2ccd9b6cbd568430cKenny Root    // vendor
30986c9584559439504fc57ece2ccd9b6cbd568430cKenny Root    // TODO replace this with an environment variable (doesn't exist yet)
3100b285499db739ba50f2f839d633e763c70e67f96Amith Yamasani    android_system_dirs.dirs[1].path = "/vendor/app/";
31186c9584559439504fc57ece2ccd9b6cbd568430cKenny Root    android_system_dirs.dirs[1].len = strlen(android_system_dirs.dirs[1].path);
31286c9584559439504fc57ece2ccd9b6cbd568430cKenny Root
31386c9584559439504fc57ece2ccd9b6cbd568430cKenny Root    return 0;
31486c9584559439504fc57ece2ccd9b6cbd568430cKenny Root}
31586c9584559439504fc57ece2ccd9b6cbd568430cKenny Root
3160b285499db739ba50f2f839d633e763c70e67f96Amith Yamasaniint initialize_directories() {
3170b285499db739ba50f2f839d633e763c70e67f96Amith Yamasani    // /data/user
3180b285499db739ba50f2f839d633e763c70e67f96Amith Yamasani    char *user_data_dir = build_string2(android_data_dir.path, SECONDARY_USER_PREFIX);
3190b285499db739ba50f2f839d633e763c70e67f96Amith Yamasani    // /data/data
3200b285499db739ba50f2f839d633e763c70e67f96Amith Yamasani    char *legacy_data_dir = build_string2(android_data_dir.path, PRIMARY_USER_PREFIX);
3210b285499db739ba50f2f839d633e763c70e67f96Amith Yamasani    // /data/user/0
3220b285499db739ba50f2f839d633e763c70e67f96Amith Yamasani    char *primary_data_dir = build_string3(android_data_dir.path, SECONDARY_USER_PREFIX,
3230b285499db739ba50f2f839d633e763c70e67f96Amith Yamasani            "0");
3240b285499db739ba50f2f839d633e763c70e67f96Amith Yamasani    int ret = -1;
3250b285499db739ba50f2f839d633e763c70e67f96Amith Yamasani    if (user_data_dir != NULL && primary_data_dir != NULL && legacy_data_dir != NULL) {
3260b285499db739ba50f2f839d633e763c70e67f96Amith Yamasani        ret = 0;
3270b285499db739ba50f2f839d633e763c70e67f96Amith Yamasani        // Make the /data/user directory if necessary
3280b285499db739ba50f2f839d633e763c70e67f96Amith Yamasani        if (access(user_data_dir, R_OK) < 0) {
3290b285499db739ba50f2f839d633e763c70e67f96Amith Yamasani            if (mkdir(user_data_dir, 0755) < 0) {
3300b285499db739ba50f2f839d633e763c70e67f96Amith Yamasani                return -1;
3310b285499db739ba50f2f839d633e763c70e67f96Amith Yamasani            }
3320b285499db739ba50f2f839d633e763c70e67f96Amith Yamasani            if (chown(user_data_dir, AID_SYSTEM, AID_SYSTEM) < 0) {
3330b285499db739ba50f2f839d633e763c70e67f96Amith Yamasani                return -1;
3340b285499db739ba50f2f839d633e763c70e67f96Amith Yamasani            }
3350b285499db739ba50f2f839d633e763c70e67f96Amith Yamasani        }
3360b285499db739ba50f2f839d633e763c70e67f96Amith Yamasani        // Make the /data/user/0 symlink to /data/data if necessary
3370b285499db739ba50f2f839d633e763c70e67f96Amith Yamasani        if (access(primary_data_dir, R_OK) < 0) {
3380b285499db739ba50f2f839d633e763c70e67f96Amith Yamasani              ret = symlink(legacy_data_dir, primary_data_dir);
3390b285499db739ba50f2f839d633e763c70e67f96Amith Yamasani        }
3400b285499db739ba50f2f839d633e763c70e67f96Amith Yamasani        free(user_data_dir);
3410b285499db739ba50f2f839d633e763c70e67f96Amith Yamasani        free(legacy_data_dir);
3420b285499db739ba50f2f839d633e763c70e67f96Amith Yamasani        free(primary_data_dir);
3430b285499db739ba50f2f839d633e763c70e67f96Amith Yamasani    }
3440b285499db739ba50f2f839d633e763c70e67f96Amith Yamasani    return ret;
3450b285499db739ba50f2f839d633e763c70e67f96Amith Yamasani}
3460b285499db739ba50f2f839d633e763c70e67f96Amith Yamasani
34786c9584559439504fc57ece2ccd9b6cbd568430cKenny Rootint main(const int argc, const char *argv[]) {
3489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    char buf[BUFFER_MAX];
3499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    struct sockaddr addr;
3509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    socklen_t alen;
3519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    int lsocket, s, count;
3529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
35386c9584559439504fc57ece2ccd9b6cbd568430cKenny Root    if (initialize_globals() < 0) {
35486c9584559439504fc57ece2ccd9b6cbd568430cKenny Root        LOGE("Could not initialize globals; exiting.\n");
35586c9584559439504fc57ece2ccd9b6cbd568430cKenny Root        exit(1);
35686c9584559439504fc57ece2ccd9b6cbd568430cKenny Root    }
35786c9584559439504fc57ece2ccd9b6cbd568430cKenny Root
3580b285499db739ba50f2f839d633e763c70e67f96Amith Yamasani    if (initialize_directories() < 0) {
3590b285499db739ba50f2f839d633e763c70e67f96Amith Yamasani        LOGE("Could not create directories; exiting.\n");
3600b285499db739ba50f2f839d633e763c70e67f96Amith Yamasani        exit(1);
3610b285499db739ba50f2f839d633e763c70e67f96Amith Yamasani    }
3620b285499db739ba50f2f839d633e763c70e67f96Amith Yamasani
3639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    lsocket = android_get_control_socket(SOCKET_PATH);
3649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (lsocket < 0) {
3659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        LOGE("Failed to get socket from environment: %s\n", strerror(errno));
3669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        exit(1);
3679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (listen(lsocket, 5)) {
3699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        LOGE("Listen on socket failed: %s\n", strerror(errno));
3709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        exit(1);
3719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    fcntl(lsocket, F_SETFD, FD_CLOEXEC);
3739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    for (;;) {
3759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        alen = sizeof(addr);
3769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        s = accept(lsocket, &addr, &alen);
3779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (s < 0) {
3789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            LOGE("Accept failed: %s\n", strerror(errno));
3799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            continue;
3809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
3819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        fcntl(s, F_SETFD, FD_CLOEXEC);
3829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        LOGI("new connection\n");
3849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        for (;;) {
3859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            unsigned short count;
3869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (readx(s, &count, sizeof(count))) {
3879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                LOGE("failed to read size\n");
3889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                break;
3899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
3909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if ((count < 1) || (count >= BUFFER_MAX)) {
3919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                LOGE("invalid size %d\n", count);
3929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                break;
3939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
3949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (readx(s, buf, count)) {
3959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                LOGE("failed to read command\n");
3969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                break;
3979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
3989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            buf[count] = 0;
3999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (execute(s, buf)) break;
4009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
4019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        LOGI("closing connection\n");
4029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        close(s);
4039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return 0;
4069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
407