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
17812b19a425b8304ac9e5408cc8ceb9f363c72559Nick Kralevich#include <linux/capability.h>
18812b19a425b8304ac9e5408cc8ceb9f363c72559Nick Kralevich#include <linux/prctl.h>
19812b19a425b8304ac9e5408cc8ceb9f363c72559Nick Kralevich
209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include "installd.h"
219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#define BUFFER_MAX    1024  /* input buffer for commands */
249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#define TOKEN_MAX     8     /* max number of arguments in buffer */
259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#define REPLY_MAX     256   /* largest reply allowed */
269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic int do_ping(char **arg, char reply[REPLY_MAX])
289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return 0;
309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic int do_install(char **arg, char reply[REPLY_MAX])
339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
3435ab3ad61fcc349380d7e7f2fcf9a0dfbf76ae11Kenny Root    return install(arg[0], atoi(arg[1]), atoi(arg[2])); /* pkgname, uid, gid */
359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic int do_dexopt(char **arg, char reply[REPLY_MAX])
389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        /* apk_path, uid, is_public */
409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return dexopt(arg[0], atoi(arg[1]), atoi(arg[2]));
419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic int do_move_dex(char **arg, char reply[REPLY_MAX])
449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return move_dex(arg[0], arg[1]); /* src, dst */
469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic int do_rm_dex(char **arg, char reply[REPLY_MAX])
499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return rm_dex(arg[0]); /* pkgname */
519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic int do_remove(char **arg, char reply[REPLY_MAX])
549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
550b285499db739ba50f2f839d633e763c70e67f96Amith Yamasani    return uninstall(arg[0], atoi(arg[1])); /* pkgname, userid */
569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
58b858dfda5012a1040927ed62c3bb856c3294d882Dianne Hackbornstatic int do_rename(char **arg, char reply[REPLY_MAX])
59b858dfda5012a1040927ed62c3bb856c3294d882Dianne Hackborn{
6035ab3ad61fcc349380d7e7f2fcf9a0dfbf76ae11Kenny Root    return renamepkg(arg[0], arg[1]); /* oldpkgname, newpkgname */
61b858dfda5012a1040927ed62c3bb856c3294d882Dianne Hackborn}
62b858dfda5012a1040927ed62c3bb856c3294d882Dianne Hackborn
63d0c5f515c05d05c9d24971695337daf9d6ce409cDianne Hackbornstatic int do_fixuid(char **arg, char reply[REPLY_MAX])
64d0c5f515c05d05c9d24971695337daf9d6ce409cDianne Hackborn{
65d0c5f515c05d05c9d24971695337daf9d6ce409cDianne Hackborn    return fix_uid(arg[0], atoi(arg[1]), atoi(arg[2])); /* pkgname, uid, gid */
66d0c5f515c05d05c9d24971695337daf9d6ce409cDianne Hackborn}
67d0c5f515c05d05c9d24971695337daf9d6ce409cDianne Hackborn
689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic int do_free_cache(char **arg, char reply[REPLY_MAX]) /* TODO int:free_size */
699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
703e319a9962434e1fae86b2180ad210170f02c152Kenny Root    return free_cache((int64_t)atoll(arg[0])); /* free_size */
719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic int do_rm_cache(char **arg, char reply[REPLY_MAX])
749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
7554289b8b4a110cc1ae106d79785cc762a2aebd6eAmith Yamasani    return delete_cache(arg[0], atoi(arg[1])); /* pkgname, userid */
769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic int do_get_size(char **arg, char reply[REPLY_MAX])
799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
803e319a9962434e1fae86b2180ad210170f02c152Kenny Root    int64_t codesize = 0;
813e319a9962434e1fae86b2180ad210170f02c152Kenny Root    int64_t datasize = 0;
823e319a9962434e1fae86b2180ad210170f02c152Kenny Root    int64_t cachesize = 0;
83292f8bc9d1b790ab975a87a842c7fabc908b97e0Dianne Hackborn    int64_t asecsize = 0;
849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    int res = 0;
859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
860c3804950236fe170ebf6cc7a5f1e3e305b8f315Dianne Hackborn        /* pkgdir, persona, apkpath */
870c3804950236fe170ebf6cc7a5f1e3e305b8f315Dianne Hackborn    res = get_size(arg[0], atoi(arg[1]), arg[2], arg[3], arg[4],
880c3804950236fe170ebf6cc7a5f1e3e305b8f315Dianne Hackborn            &codesize, &datasize, &cachesize, &asecsize);
899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
903e319a9962434e1fae86b2180ad210170f02c152Kenny Root    /*
913e319a9962434e1fae86b2180ad210170f02c152Kenny Root     * Each int64_t can take up 22 characters printed out. Make sure it
923e319a9962434e1fae86b2180ad210170f02c152Kenny Root     * doesn't go over REPLY_MAX in the future.
933e319a9962434e1fae86b2180ad210170f02c152Kenny Root     */
94292f8bc9d1b790ab975a87a842c7fabc908b97e0Dianne Hackborn    snprintf(reply, REPLY_MAX, "%" PRId64 " %" PRId64 " %" PRId64 " %" PRId64,
95292f8bc9d1b790ab975a87a842c7fabc908b97e0Dianne Hackborn            codesize, datasize, cachesize, asecsize);
969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return res;
979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic int do_rm_user_data(char **arg, char reply[REPLY_MAX])
1009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
1010b285499db739ba50f2f839d633e763c70e67f96Amith Yamasani    return delete_user_data(arg[0], atoi(arg[1])); /* pkgname, userid */
1020b285499db739ba50f2f839d633e763c70e67f96Amith Yamasani}
1030b285499db739ba50f2f839d633e763c70e67f96Amith Yamasani
1040b285499db739ba50f2f839d633e763c70e67f96Amith Yamasanistatic int do_mk_user_data(char **arg, char reply[REPLY_MAX])
1050b285499db739ba50f2f839d633e763c70e67f96Amith Yamasani{
1060b285499db739ba50f2f839d633e763c70e67f96Amith Yamasani    return make_user_data(arg[0], atoi(arg[1]), atoi(arg[2])); /* pkgname, uid, userid */
1070b285499db739ba50f2f839d633e763c70e67f96Amith Yamasani}
1080b285499db739ba50f2f839d633e763c70e67f96Amith Yamasani
1090b285499db739ba50f2f839d633e763c70e67f96Amith Yamasanistatic int do_rm_user(char **arg, char reply[REPLY_MAX])
1100b285499db739ba50f2f839d633e763c70e67f96Amith Yamasani{
1110b285499db739ba50f2f839d633e763c70e67f96Amith Yamasani    return delete_persona(atoi(arg[0])); /* userid */
1129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
1139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
114742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasanistatic int do_clone_user_data(char **arg, char reply[REPLY_MAX])
115742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani{
116742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani    return clone_persona_data(atoi(arg[0]), atoi(arg[1]), atoi(arg[2]));
117742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani}
118742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani
119b858dfda5012a1040927ed62c3bb856c3294d882Dianne Hackbornstatic int do_movefiles(char **arg, char reply[REPLY_MAX])
120b858dfda5012a1040927ed62c3bb856c3294d882Dianne Hackborn{
121b858dfda5012a1040927ed62c3bb856c3294d882Dianne Hackborn    return movefiles();
122b858dfda5012a1040927ed62c3bb856c3294d882Dianne Hackborn}
123b858dfda5012a1040927ed62c3bb856c3294d882Dianne Hackborn
1246a6b007c77e5cab7ee435506a4f65824f52028b6Kenny Rootstatic int do_linklib(char **arg, char reply[REPLY_MAX])
1256a6b007c77e5cab7ee435506a4f65824f52028b6Kenny Root{
126a3e90798b7ad3ed62e5b31842c699b2f98bd457bKenny Root    return linklib(arg[0], arg[1], atoi(arg[2]));
1276a6b007c77e5cab7ee435506a4f65824f52028b6Kenny Root}
1286a6b007c77e5cab7ee435506a4f65824f52028b6Kenny Root
1299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstruct cmdinfo {
1309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    const char *name;
1319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    unsigned numargs;
1329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    int (*func)(char **arg, char reply[REPLY_MAX]);
1339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project};
1349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstruct cmdinfo cmds[] = {
1369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    { "ping",                 0, do_ping },
13735ab3ad61fcc349380d7e7f2fcf9a0dfbf76ae11Kenny Root    { "install",              3, do_install },
1389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    { "dexopt",               3, do_dexopt },
1399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    { "movedex",              2, do_move_dex },
1409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    { "rmdex",                1, do_rm_dex },
1410b285499db739ba50f2f839d633e763c70e67f96Amith Yamasani    { "remove",               2, do_remove },
14235ab3ad61fcc349380d7e7f2fcf9a0dfbf76ae11Kenny Root    { "rename",               2, do_rename },
143d0c5f515c05d05c9d24971695337daf9d6ce409cDianne Hackborn    { "fixuid",               3, do_fixuid },
1449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    { "freecache",            1, do_free_cache },
14554289b8b4a110cc1ae106d79785cc762a2aebd6eAmith Yamasani    { "rmcache",              2, do_rm_cache },
1460c3804950236fe170ebf6cc7a5f1e3e305b8f315Dianne Hackborn    { "getsize",              5, do_get_size },
1470b285499db739ba50f2f839d633e763c70e67f96Amith Yamasani    { "rmuserdata",           2, do_rm_user_data },
148b858dfda5012a1040927ed62c3bb856c3294d882Dianne Hackborn    { "movefiles",            0, do_movefiles },
149a3e90798b7ad3ed62e5b31842c699b2f98bd457bKenny Root    { "linklib",              3, do_linklib },
1500b285499db739ba50f2f839d633e763c70e67f96Amith Yamasani    { "mkuserdata",           3, do_mk_user_data },
1510b285499db739ba50f2f839d633e763c70e67f96Amith Yamasani    { "rmuser",               1, do_rm_user },
152742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani    { "cloneuserdata",        3, do_clone_user_data },
1539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project};
1549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic int readx(int s, void *_buf, int count)
1569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
1579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    char *buf = _buf;
1589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    int n = 0, r;
1599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (count < 0) return -1;
1609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    while (n < count) {
1619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        r = read(s, buf + n, count - n);
1629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (r < 0) {
1639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (errno == EINTR) continue;
1643762c311729fe9f3af085c14c5c1fb471d994c03Steve Block            ALOGE("read error: %s\n", strerror(errno));
1659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return -1;
1669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (r == 0) {
1683762c311729fe9f3af085c14c5c1fb471d994c03Steve Block            ALOGE("eof\n");
1699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return -1; /* EOF */
1709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        n += r;
1729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return 0;
1749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
1759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic int writex(int s, const void *_buf, int count)
1779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
1789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    const char *buf = _buf;
1799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    int n = 0, r;
1809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (count < 0) return -1;
1819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    while (n < count) {
1829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        r = write(s, buf + n, count - n);
1839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (r < 0) {
1849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (errno == EINTR) continue;
1853762c311729fe9f3af085c14c5c1fb471d994c03Steve Block            ALOGE("write error: %s\n", strerror(errno));
1869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return -1;
1879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        n += r;
1899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return 0;
1919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
1929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/* Tokenize the command buffer, locate a matching command,
1959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * ensure that the required number of arguments are provided,
1969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * call the function(), return the result.
1979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
1989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic int execute(int s, char cmd[BUFFER_MAX])
1999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
2009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    char reply[REPLY_MAX];
2019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    char *arg[TOKEN_MAX+1];
2029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    unsigned i;
2039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    unsigned n = 0;
2049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    unsigned short count;
2059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    int ret = -1;
2069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2076215d3ff4b5dfa52a5d8b9a42e343051f31066a5Steve Block//    ALOGI("execute('%s')\n", cmd);
2089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        /* default reply is "" */
2109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    reply[0] = 0;
2119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        /* n is number of args (not counting arg[0]) */
2139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    arg[0] = cmd;
2149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    while (*cmd) {
2159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (isspace(*cmd)) {
2169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            *cmd++ = 0;
2179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            n++;
2189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            arg[n] = cmd;
2199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (n == TOKEN_MAX) {
2203762c311729fe9f3af085c14c5c1fb471d994c03Steve Block                ALOGE("too many arguments\n");
2219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                goto done;
2229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
2239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        cmd++;
2259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    for (i = 0; i < sizeof(cmds) / sizeof(cmds[0]); i++) {
2289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (!strcmp(cmds[i].name,arg[0])) {
2299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (n != cmds[i].numargs) {
2303762c311729fe9f3af085c14c5c1fb471d994c03Steve Block                ALOGE("%s requires %d arguments (%d given)\n",
2319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                     cmds[i].name, cmds[i].numargs, n);
2329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else {
2339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                ret = cmds[i].func(arg + 1, reply);
2349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
2359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            goto done;
2369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2383762c311729fe9f3af085c14c5c1fb471d994c03Steve Block    ALOGE("unsupported command '%s'\n", arg[0]);
2399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectdone:
2419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (reply[0]) {
2429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        n = snprintf(cmd, BUFFER_MAX, "%d %s", ret, reply);
2439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    } else {
2449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        n = snprintf(cmd, BUFFER_MAX, "%d", ret);
2459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (n > BUFFER_MAX) n = BUFFER_MAX;
2479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    count = n;
2489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2496215d3ff4b5dfa52a5d8b9a42e343051f31066a5Steve Block//    ALOGI("reply: '%s'\n", cmd);
2509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (writex(s, &count, sizeof(count))) return -1;
2519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (writex(s, cmd, count)) return -1;
2529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return 0;
2539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
2549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
25586c9584559439504fc57ece2ccd9b6cbd568430cKenny Root/**
25686c9584559439504fc57ece2ccd9b6cbd568430cKenny Root * Initialize all the global variables that are used elsewhere. Returns 0 upon
25786c9584559439504fc57ece2ccd9b6cbd568430cKenny Root * success and -1 on error.
25886c9584559439504fc57ece2ccd9b6cbd568430cKenny Root */
25986c9584559439504fc57ece2ccd9b6cbd568430cKenny Rootvoid free_globals() {
26086c9584559439504fc57ece2ccd9b6cbd568430cKenny Root    size_t i;
26186c9584559439504fc57ece2ccd9b6cbd568430cKenny Root
26286c9584559439504fc57ece2ccd9b6cbd568430cKenny Root    for (i = 0; i < android_system_dirs.count; i++) {
26386c9584559439504fc57ece2ccd9b6cbd568430cKenny Root        if (android_system_dirs.dirs[i].path != NULL) {
26486c9584559439504fc57ece2ccd9b6cbd568430cKenny Root            free(android_system_dirs.dirs[i].path);
26586c9584559439504fc57ece2ccd9b6cbd568430cKenny Root        }
26686c9584559439504fc57ece2ccd9b6cbd568430cKenny Root    }
26786c9584559439504fc57ece2ccd9b6cbd568430cKenny Root
26886c9584559439504fc57ece2ccd9b6cbd568430cKenny Root    free(android_system_dirs.dirs);
26986c9584559439504fc57ece2ccd9b6cbd568430cKenny Root}
27086c9584559439504fc57ece2ccd9b6cbd568430cKenny Root
27186c9584559439504fc57ece2ccd9b6cbd568430cKenny Rootint initialize_globals() {
27286c9584559439504fc57ece2ccd9b6cbd568430cKenny Root    // Get the android data directory.
27386c9584559439504fc57ece2ccd9b6cbd568430cKenny Root    if (get_path_from_env(&android_data_dir, "ANDROID_DATA") < 0) {
27486c9584559439504fc57ece2ccd9b6cbd568430cKenny Root        return -1;
27586c9584559439504fc57ece2ccd9b6cbd568430cKenny Root    }
27686c9584559439504fc57ece2ccd9b6cbd568430cKenny Root
27786c9584559439504fc57ece2ccd9b6cbd568430cKenny Root    // Get the android app directory.
27886c9584559439504fc57ece2ccd9b6cbd568430cKenny Root    if (copy_and_append(&android_app_dir, &android_data_dir, APP_SUBDIR) < 0) {
27986c9584559439504fc57ece2ccd9b6cbd568430cKenny Root        return -1;
28086c9584559439504fc57ece2ccd9b6cbd568430cKenny Root    }
28186c9584559439504fc57ece2ccd9b6cbd568430cKenny Root
28286c9584559439504fc57ece2ccd9b6cbd568430cKenny Root    // Get the android protected app directory.
28386c9584559439504fc57ece2ccd9b6cbd568430cKenny Root    if (copy_and_append(&android_app_private_dir, &android_data_dir, PRIVATE_APP_SUBDIR) < 0) {
28486c9584559439504fc57ece2ccd9b6cbd568430cKenny Root        return -1;
28586c9584559439504fc57ece2ccd9b6cbd568430cKenny Root    }
28686c9584559439504fc57ece2ccd9b6cbd568430cKenny Root
2879bbd70a96397bd5f1445ad6c21977fccfb350dfaKenny Root    // Get the android app native library directory.
2889bbd70a96397bd5f1445ad6c21977fccfb350dfaKenny Root    if (copy_and_append(&android_app_lib_dir, &android_data_dir, APP_LIB_SUBDIR) < 0) {
2899bbd70a96397bd5f1445ad6c21977fccfb350dfaKenny Root        return -1;
2909bbd70a96397bd5f1445ad6c21977fccfb350dfaKenny Root    }
2919bbd70a96397bd5f1445ad6c21977fccfb350dfaKenny Root
29286c9584559439504fc57ece2ccd9b6cbd568430cKenny Root    // Get the sd-card ASEC mount point.
29386c9584559439504fc57ece2ccd9b6cbd568430cKenny Root    if (get_path_from_env(&android_asec_dir, "ASEC_MOUNTPOINT") < 0) {
29486c9584559439504fc57ece2ccd9b6cbd568430cKenny Root        return -1;
29586c9584559439504fc57ece2ccd9b6cbd568430cKenny Root    }
29686c9584559439504fc57ece2ccd9b6cbd568430cKenny Root
297197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn    // Get the android media directory.
298197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn    if (copy_and_append(&android_media_dir, &android_data_dir, MEDIA_SUBDIR) < 0) {
299197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn        return -1;
300197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn    }
301197a0c82a1fbf337ec0a85d36b6b89c3d6e8a0acDianne Hackborn
30286c9584559439504fc57ece2ccd9b6cbd568430cKenny Root    // Take note of the system and vendor directories.
30386c9584559439504fc57ece2ccd9b6cbd568430cKenny Root    android_system_dirs.count = 2;
30486c9584559439504fc57ece2ccd9b6cbd568430cKenny Root
30586c9584559439504fc57ece2ccd9b6cbd568430cKenny Root    android_system_dirs.dirs = calloc(android_system_dirs.count, sizeof(dir_rec_t));
30686c9584559439504fc57ece2ccd9b6cbd568430cKenny Root    if (android_system_dirs.dirs == NULL) {
3073762c311729fe9f3af085c14c5c1fb471d994c03Steve Block        ALOGE("Couldn't allocate array for dirs; aborting\n");
30886c9584559439504fc57ece2ccd9b6cbd568430cKenny Root        return -1;
30986c9584559439504fc57ece2ccd9b6cbd568430cKenny Root    }
31086c9584559439504fc57ece2ccd9b6cbd568430cKenny Root
31186c9584559439504fc57ece2ccd9b6cbd568430cKenny Root    // system
31286c9584559439504fc57ece2ccd9b6cbd568430cKenny Root    if (get_path_from_env(&android_system_dirs.dirs[0], "ANDROID_ROOT") < 0) {
31386c9584559439504fc57ece2ccd9b6cbd568430cKenny Root        free_globals();
31486c9584559439504fc57ece2ccd9b6cbd568430cKenny Root        return -1;
31586c9584559439504fc57ece2ccd9b6cbd568430cKenny Root    }
31686c9584559439504fc57ece2ccd9b6cbd568430cKenny Root
3170b285499db739ba50f2f839d633e763c70e67f96Amith Yamasani    // append "app/" to dirs[0]
3180b285499db739ba50f2f839d633e763c70e67f96Amith Yamasani    char *system_app_path = build_string2(android_system_dirs.dirs[0].path, APP_SUBDIR);
3190b285499db739ba50f2f839d633e763c70e67f96Amith Yamasani    android_system_dirs.dirs[0].path = system_app_path;
3200b285499db739ba50f2f839d633e763c70e67f96Amith Yamasani    android_system_dirs.dirs[0].len = strlen(system_app_path);
3210b285499db739ba50f2f839d633e763c70e67f96Amith Yamasani
32286c9584559439504fc57ece2ccd9b6cbd568430cKenny Root    // vendor
32386c9584559439504fc57ece2ccd9b6cbd568430cKenny Root    // TODO replace this with an environment variable (doesn't exist yet)
3240b285499db739ba50f2f839d633e763c70e67f96Amith Yamasani    android_system_dirs.dirs[1].path = "/vendor/app/";
32586c9584559439504fc57ece2ccd9b6cbd568430cKenny Root    android_system_dirs.dirs[1].len = strlen(android_system_dirs.dirs[1].path);
32686c9584559439504fc57ece2ccd9b6cbd568430cKenny Root
32786c9584559439504fc57ece2ccd9b6cbd568430cKenny Root    return 0;
32886c9584559439504fc57ece2ccd9b6cbd568430cKenny Root}
32986c9584559439504fc57ece2ccd9b6cbd568430cKenny Root
3300b285499db739ba50f2f839d633e763c70e67f96Amith Yamasaniint initialize_directories() {
3315b1ada2562c17921adf6a62ea62bcb445160983cJeff Sharkey    int res = -1;
3325b1ada2562c17921adf6a62ea62bcb445160983cJeff Sharkey
3335b1ada2562c17921adf6a62ea62bcb445160983cJeff Sharkey    // Read current filesystem layout version to handle upgrade paths
3345b1ada2562c17921adf6a62ea62bcb445160983cJeff Sharkey    char version_path[PATH_MAX];
3358ea0dc6a89b011d4f478c0c8192570d69cf7ce79Jeff Sharkey    snprintf(version_path, PATH_MAX, "%s.layout_version", android_data_dir.path);
3368ea0dc6a89b011d4f478c0c8192570d69cf7ce79Jeff Sharkey
3378ea0dc6a89b011d4f478c0c8192570d69cf7ce79Jeff Sharkey    int oldVersion;
3388ea0dc6a89b011d4f478c0c8192570d69cf7ce79Jeff Sharkey    if (fs_read_atomic_int(version_path, &oldVersion) == -1) {
3398ea0dc6a89b011d4f478c0c8192570d69cf7ce79Jeff Sharkey        oldVersion = 0;
3405b1ada2562c17921adf6a62ea62bcb445160983cJeff Sharkey    }
3418ea0dc6a89b011d4f478c0c8192570d69cf7ce79Jeff Sharkey    int version = oldVersion;
3425b1ada2562c17921adf6a62ea62bcb445160983cJeff Sharkey
3430b285499db739ba50f2f839d633e763c70e67f96Amith Yamasani    // /data/user
3440b285499db739ba50f2f839d633e763c70e67f96Amith Yamasani    char *user_data_dir = build_string2(android_data_dir.path, SECONDARY_USER_PREFIX);
3450b285499db739ba50f2f839d633e763c70e67f96Amith Yamasani    // /data/data
3460b285499db739ba50f2f839d633e763c70e67f96Amith Yamasani    char *legacy_data_dir = build_string2(android_data_dir.path, PRIMARY_USER_PREFIX);
3470b285499db739ba50f2f839d633e763c70e67f96Amith Yamasani    // /data/user/0
3485b1ada2562c17921adf6a62ea62bcb445160983cJeff Sharkey    char *primary_data_dir = build_string3(android_data_dir.path, SECONDARY_USER_PREFIX, "0");
3495b1ada2562c17921adf6a62ea62bcb445160983cJeff Sharkey    if (!user_data_dir || !legacy_data_dir || !primary_data_dir) {
3505b1ada2562c17921adf6a62ea62bcb445160983cJeff Sharkey        goto fail;
3515b1ada2562c17921adf6a62ea62bcb445160983cJeff Sharkey    }
3525b1ada2562c17921adf6a62ea62bcb445160983cJeff Sharkey
3535b1ada2562c17921adf6a62ea62bcb445160983cJeff Sharkey    // Make the /data/user directory if necessary
3545b1ada2562c17921adf6a62ea62bcb445160983cJeff Sharkey    if (access(user_data_dir, R_OK) < 0) {
3555b1ada2562c17921adf6a62ea62bcb445160983cJeff Sharkey        if (mkdir(user_data_dir, 0711) < 0) {
3565b1ada2562c17921adf6a62ea62bcb445160983cJeff Sharkey            goto fail;
3575b1ada2562c17921adf6a62ea62bcb445160983cJeff Sharkey        }
3585b1ada2562c17921adf6a62ea62bcb445160983cJeff Sharkey        if (chown(user_data_dir, AID_SYSTEM, AID_SYSTEM) < 0) {
3595b1ada2562c17921adf6a62ea62bcb445160983cJeff Sharkey            goto fail;
3605b1ada2562c17921adf6a62ea62bcb445160983cJeff Sharkey        }
3615b1ada2562c17921adf6a62ea62bcb445160983cJeff Sharkey        if (chmod(user_data_dir, 0711) < 0) {
3625b1ada2562c17921adf6a62ea62bcb445160983cJeff Sharkey            goto fail;
3635b1ada2562c17921adf6a62ea62bcb445160983cJeff Sharkey        }
3645b1ada2562c17921adf6a62ea62bcb445160983cJeff Sharkey    }
3655b1ada2562c17921adf6a62ea62bcb445160983cJeff Sharkey    // Make the /data/user/0 symlink to /data/data if necessary
3665b1ada2562c17921adf6a62ea62bcb445160983cJeff Sharkey    if (access(primary_data_dir, R_OK) < 0) {
3675b1ada2562c17921adf6a62ea62bcb445160983cJeff Sharkey        if (symlink(legacy_data_dir, primary_data_dir)) {
3685b1ada2562c17921adf6a62ea62bcb445160983cJeff Sharkey            goto fail;
3695b1ada2562c17921adf6a62ea62bcb445160983cJeff Sharkey        }
3705b1ada2562c17921adf6a62ea62bcb445160983cJeff Sharkey    }
3715b1ada2562c17921adf6a62ea62bcb445160983cJeff Sharkey
3725b1ada2562c17921adf6a62ea62bcb445160983cJeff Sharkey    if (version == 0) {
3735b1ada2562c17921adf6a62ea62bcb445160983cJeff Sharkey        // Introducing multi-user, so migrate /data/media contents into /data/media/0
3748ea0dc6a89b011d4f478c0c8192570d69cf7ce79Jeff Sharkey        ALOGD("Upgrading /data/media for multi-user");
3755b1ada2562c17921adf6a62ea62bcb445160983cJeff Sharkey
376dc9b0128c52cc797847240e81ebc6de75229a3abJeff Sharkey        // Ensure /data/media
3778ea0dc6a89b011d4f478c0c8192570d69cf7ce79Jeff Sharkey        if (fs_prepare_dir(android_media_dir.path, 0770, AID_MEDIA_RW, AID_MEDIA_RW) == -1) {
378dc9b0128c52cc797847240e81ebc6de75229a3abJeff Sharkey            goto fail;
379dc9b0128c52cc797847240e81ebc6de75229a3abJeff Sharkey        }
380dc9b0128c52cc797847240e81ebc6de75229a3abJeff Sharkey
3815b1ada2562c17921adf6a62ea62bcb445160983cJeff Sharkey        // /data/media.tmp
3825b1ada2562c17921adf6a62ea62bcb445160983cJeff Sharkey        char media_tmp_dir[PATH_MAX];
3835b1ada2562c17921adf6a62ea62bcb445160983cJeff Sharkey        snprintf(media_tmp_dir, PATH_MAX, "%smedia.tmp", android_data_dir.path);
3845b1ada2562c17921adf6a62ea62bcb445160983cJeff Sharkey
3855b1ada2562c17921adf6a62ea62bcb445160983cJeff Sharkey        // Only copy when upgrade not already in progress
3865b1ada2562c17921adf6a62ea62bcb445160983cJeff Sharkey        if (access(media_tmp_dir, F_OK) == -1) {
3875b1ada2562c17921adf6a62ea62bcb445160983cJeff Sharkey            if (rename(android_media_dir.path, media_tmp_dir) == -1) {
3885b1ada2562c17921adf6a62ea62bcb445160983cJeff Sharkey                ALOGE("Failed to move legacy media path: %s", strerror(errno));
3895b1ada2562c17921adf6a62ea62bcb445160983cJeff Sharkey                goto fail;
3907ac3ed1d7679e9cb90b44c6ab1629318b17c0690Nick Kralevich            }
3910b285499db739ba50f2f839d633e763c70e67f96Amith Yamasani        }
3925b1ada2562c17921adf6a62ea62bcb445160983cJeff Sharkey
3935b1ada2562c17921adf6a62ea62bcb445160983cJeff Sharkey        // Create /data/media again
3948ea0dc6a89b011d4f478c0c8192570d69cf7ce79Jeff Sharkey        if (fs_prepare_dir(android_media_dir.path, 0770, AID_MEDIA_RW, AID_MEDIA_RW) == -1) {
3955b1ada2562c17921adf6a62ea62bcb445160983cJeff Sharkey            goto fail;
3965b1ada2562c17921adf6a62ea62bcb445160983cJeff Sharkey        }
3975b1ada2562c17921adf6a62ea62bcb445160983cJeff Sharkey
3988ea0dc6a89b011d4f478c0c8192570d69cf7ce79Jeff Sharkey        // /data/media/0
3998ea0dc6a89b011d4f478c0c8192570d69cf7ce79Jeff Sharkey        char owner_media_dir[PATH_MAX];
4008ea0dc6a89b011d4f478c0c8192570d69cf7ce79Jeff Sharkey        snprintf(owner_media_dir, PATH_MAX, "%s0", android_media_dir.path);
4018ea0dc6a89b011d4f478c0c8192570d69cf7ce79Jeff Sharkey
4025b1ada2562c17921adf6a62ea62bcb445160983cJeff Sharkey        // Move any owner data into place
4035b1ada2562c17921adf6a62ea62bcb445160983cJeff Sharkey        if (access(media_tmp_dir, F_OK) == 0) {
4045b1ada2562c17921adf6a62ea62bcb445160983cJeff Sharkey            if (rename(media_tmp_dir, owner_media_dir) == -1) {
4055b1ada2562c17921adf6a62ea62bcb445160983cJeff Sharkey                ALOGE("Failed to move owner media path: %s", strerror(errno));
4065b1ada2562c17921adf6a62ea62bcb445160983cJeff Sharkey                goto fail;
4075b1ada2562c17921adf6a62ea62bcb445160983cJeff Sharkey            }
4080b285499db739ba50f2f839d633e763c70e67f96Amith Yamasani        }
40991bbb8a1e9f8b4324fd086fa9b26a4e9fe57569bJeff Sharkey
41091bbb8a1e9f8b4324fd086fa9b26a4e9fe57569bJeff Sharkey        // Ensure media directories for any existing users
41191bbb8a1e9f8b4324fd086fa9b26a4e9fe57569bJeff Sharkey        DIR *dir;
41291bbb8a1e9f8b4324fd086fa9b26a4e9fe57569bJeff Sharkey        struct dirent *dirent;
41391bbb8a1e9f8b4324fd086fa9b26a4e9fe57569bJeff Sharkey        char user_media_dir[PATH_MAX];
41491bbb8a1e9f8b4324fd086fa9b26a4e9fe57569bJeff Sharkey
41591bbb8a1e9f8b4324fd086fa9b26a4e9fe57569bJeff Sharkey        dir = opendir(user_data_dir);
41691bbb8a1e9f8b4324fd086fa9b26a4e9fe57569bJeff Sharkey        if (dir != NULL) {
41791bbb8a1e9f8b4324fd086fa9b26a4e9fe57569bJeff Sharkey            while ((dirent = readdir(dir))) {
41891bbb8a1e9f8b4324fd086fa9b26a4e9fe57569bJeff Sharkey                if (dirent->d_type == DT_DIR) {
41991bbb8a1e9f8b4324fd086fa9b26a4e9fe57569bJeff Sharkey                    const char *name = dirent->d_name;
42091bbb8a1e9f8b4324fd086fa9b26a4e9fe57569bJeff Sharkey
42191bbb8a1e9f8b4324fd086fa9b26a4e9fe57569bJeff Sharkey                    // skip "." and ".."
42291bbb8a1e9f8b4324fd086fa9b26a4e9fe57569bJeff Sharkey                    if (name[0] == '.') {
42391bbb8a1e9f8b4324fd086fa9b26a4e9fe57569bJeff Sharkey                        if (name[1] == 0) continue;
42491bbb8a1e9f8b4324fd086fa9b26a4e9fe57569bJeff Sharkey                        if ((name[1] == '.') && (name[2] == 0)) continue;
42591bbb8a1e9f8b4324fd086fa9b26a4e9fe57569bJeff Sharkey                    }
42691bbb8a1e9f8b4324fd086fa9b26a4e9fe57569bJeff Sharkey
42791bbb8a1e9f8b4324fd086fa9b26a4e9fe57569bJeff Sharkey                    // /data/media/<user_id>
42891bbb8a1e9f8b4324fd086fa9b26a4e9fe57569bJeff Sharkey                    snprintf(user_media_dir, PATH_MAX, "%s%s", android_media_dir.path, name);
4298ea0dc6a89b011d4f478c0c8192570d69cf7ce79Jeff Sharkey                    if (fs_prepare_dir(user_media_dir, 0770, AID_MEDIA_RW, AID_MEDIA_RW) == -1) {
43091bbb8a1e9f8b4324fd086fa9b26a4e9fe57569bJeff Sharkey                        goto fail;
43191bbb8a1e9f8b4324fd086fa9b26a4e9fe57569bJeff Sharkey                    }
43291bbb8a1e9f8b4324fd086fa9b26a4e9fe57569bJeff Sharkey                }
43391bbb8a1e9f8b4324fd086fa9b26a4e9fe57569bJeff Sharkey            }
43491bbb8a1e9f8b4324fd086fa9b26a4e9fe57569bJeff Sharkey            closedir(dir);
43591bbb8a1e9f8b4324fd086fa9b26a4e9fe57569bJeff Sharkey        }
43691bbb8a1e9f8b4324fd086fa9b26a4e9fe57569bJeff Sharkey
4375b1ada2562c17921adf6a62ea62bcb445160983cJeff Sharkey        version = 1;
4380b285499db739ba50f2f839d633e763c70e67f96Amith Yamasani    }
4395b1ada2562c17921adf6a62ea62bcb445160983cJeff Sharkey
4408ea0dc6a89b011d4f478c0c8192570d69cf7ce79Jeff Sharkey    // /data/media/obb
4418ea0dc6a89b011d4f478c0c8192570d69cf7ce79Jeff Sharkey    char media_obb_dir[PATH_MAX];
4428ea0dc6a89b011d4f478c0c8192570d69cf7ce79Jeff Sharkey    snprintf(media_obb_dir, PATH_MAX, "%sobb", android_media_dir.path);
4438ea0dc6a89b011d4f478c0c8192570d69cf7ce79Jeff Sharkey
4448ea0dc6a89b011d4f478c0c8192570d69cf7ce79Jeff Sharkey    if (version == 1) {
4458ea0dc6a89b011d4f478c0c8192570d69cf7ce79Jeff Sharkey        // Introducing /data/media/obb for sharing OBB across users; migrate
4468ea0dc6a89b011d4f478c0c8192570d69cf7ce79Jeff Sharkey        // any existing OBB files from owner.
4478ea0dc6a89b011d4f478c0c8192570d69cf7ce79Jeff Sharkey        ALOGD("Upgrading to shared /data/media/obb");
4488ea0dc6a89b011d4f478c0c8192570d69cf7ce79Jeff Sharkey
4498ea0dc6a89b011d4f478c0c8192570d69cf7ce79Jeff Sharkey        // /data/media/0/Android/obb
4508ea0dc6a89b011d4f478c0c8192570d69cf7ce79Jeff Sharkey        char owner_obb_path[PATH_MAX];
4518ea0dc6a89b011d4f478c0c8192570d69cf7ce79Jeff Sharkey        snprintf(owner_obb_path, PATH_MAX, "%s0/Android/obb", android_media_dir.path);
4528ea0dc6a89b011d4f478c0c8192570d69cf7ce79Jeff Sharkey
4538ea0dc6a89b011d4f478c0c8192570d69cf7ce79Jeff Sharkey        // Only move if target doesn't already exist
4548ea0dc6a89b011d4f478c0c8192570d69cf7ce79Jeff Sharkey        if (access(media_obb_dir, F_OK) != 0 && access(owner_obb_path, F_OK) == 0) {
4558ea0dc6a89b011d4f478c0c8192570d69cf7ce79Jeff Sharkey            if (rename(owner_obb_path, media_obb_dir) == -1) {
4568ea0dc6a89b011d4f478c0c8192570d69cf7ce79Jeff Sharkey                ALOGE("Failed to move OBB from owner: %s", strerror(errno));
4578ea0dc6a89b011d4f478c0c8192570d69cf7ce79Jeff Sharkey                goto fail;
4588ea0dc6a89b011d4f478c0c8192570d69cf7ce79Jeff Sharkey            }
4598ea0dc6a89b011d4f478c0c8192570d69cf7ce79Jeff Sharkey        }
4608ea0dc6a89b011d4f478c0c8192570d69cf7ce79Jeff Sharkey
4618ea0dc6a89b011d4f478c0c8192570d69cf7ce79Jeff Sharkey        version = 2;
4625b1ada2562c17921adf6a62ea62bcb445160983cJeff Sharkey    }
4635b1ada2562c17921adf6a62ea62bcb445160983cJeff Sharkey
4648ea0dc6a89b011d4f478c0c8192570d69cf7ce79Jeff Sharkey    if (ensure_media_user_dirs(0) == -1) {
4658ea0dc6a89b011d4f478c0c8192570d69cf7ce79Jeff Sharkey        ALOGE("Failed to setup media for user 0");
4668ea0dc6a89b011d4f478c0c8192570d69cf7ce79Jeff Sharkey        goto fail;
4678ea0dc6a89b011d4f478c0c8192570d69cf7ce79Jeff Sharkey    }
4688ea0dc6a89b011d4f478c0c8192570d69cf7ce79Jeff Sharkey    if (fs_prepare_dir(media_obb_dir, 0770, AID_MEDIA_RW, AID_MEDIA_RW) == -1) {
4695b1ada2562c17921adf6a62ea62bcb445160983cJeff Sharkey        goto fail;
4705b1ada2562c17921adf6a62ea62bcb445160983cJeff Sharkey    }
4715b1ada2562c17921adf6a62ea62bcb445160983cJeff Sharkey
4728ea0dc6a89b011d4f478c0c8192570d69cf7ce79Jeff Sharkey    // Persist layout version if changed
4738ea0dc6a89b011d4f478c0c8192570d69cf7ce79Jeff Sharkey    if (version != oldVersion) {
4748ea0dc6a89b011d4f478c0c8192570d69cf7ce79Jeff Sharkey        if (fs_write_atomic_int(version_path, version) == -1) {
4758ea0dc6a89b011d4f478c0c8192570d69cf7ce79Jeff Sharkey            ALOGE("Failed to save version to %s: %s", version_path, strerror(errno));
4768ea0dc6a89b011d4f478c0c8192570d69cf7ce79Jeff Sharkey            goto fail;
4778ea0dc6a89b011d4f478c0c8192570d69cf7ce79Jeff Sharkey        }
4788ea0dc6a89b011d4f478c0c8192570d69cf7ce79Jeff Sharkey    }
4798ea0dc6a89b011d4f478c0c8192570d69cf7ce79Jeff Sharkey
4805b1ada2562c17921adf6a62ea62bcb445160983cJeff Sharkey    // Success!
4815b1ada2562c17921adf6a62ea62bcb445160983cJeff Sharkey    res = 0;
4825b1ada2562c17921adf6a62ea62bcb445160983cJeff Sharkey
4835b1ada2562c17921adf6a62ea62bcb445160983cJeff Sharkeyfail:
4845b1ada2562c17921adf6a62ea62bcb445160983cJeff Sharkey    free(user_data_dir);
4855b1ada2562c17921adf6a62ea62bcb445160983cJeff Sharkey    free(legacy_data_dir);
4865b1ada2562c17921adf6a62ea62bcb445160983cJeff Sharkey    free(primary_data_dir);
4875b1ada2562c17921adf6a62ea62bcb445160983cJeff Sharkey    return res;
4880b285499db739ba50f2f839d633e763c70e67f96Amith Yamasani}
4890b285499db739ba50f2f839d633e763c70e67f96Amith Yamasani
490812b19a425b8304ac9e5408cc8ceb9f363c72559Nick Kralevichstatic void drop_privileges() {
491812b19a425b8304ac9e5408cc8ceb9f363c72559Nick Kralevich    if (prctl(PR_SET_KEEPCAPS, 1) < 0) {
492812b19a425b8304ac9e5408cc8ceb9f363c72559Nick Kralevich        ALOGE("prctl(PR_SET_KEEPCAPS) failed: %s\n", strerror(errno));
493812b19a425b8304ac9e5408cc8ceb9f363c72559Nick Kralevich        exit(1);
494812b19a425b8304ac9e5408cc8ceb9f363c72559Nick Kralevich    }
495812b19a425b8304ac9e5408cc8ceb9f363c72559Nick Kralevich
496812b19a425b8304ac9e5408cc8ceb9f363c72559Nick Kralevich    if (setgid(AID_INSTALL) < 0) {
497812b19a425b8304ac9e5408cc8ceb9f363c72559Nick Kralevich        ALOGE("setgid() can't drop privileges; exiting.\n");
498812b19a425b8304ac9e5408cc8ceb9f363c72559Nick Kralevich        exit(1);
499812b19a425b8304ac9e5408cc8ceb9f363c72559Nick Kralevich    }
500812b19a425b8304ac9e5408cc8ceb9f363c72559Nick Kralevich
501812b19a425b8304ac9e5408cc8ceb9f363c72559Nick Kralevich    if (setuid(AID_INSTALL) < 0) {
502812b19a425b8304ac9e5408cc8ceb9f363c72559Nick Kralevich        ALOGE("setuid() can't drop privileges; exiting.\n");
503812b19a425b8304ac9e5408cc8ceb9f363c72559Nick Kralevich        exit(1);
504812b19a425b8304ac9e5408cc8ceb9f363c72559Nick Kralevich    }
505812b19a425b8304ac9e5408cc8ceb9f363c72559Nick Kralevich
506812b19a425b8304ac9e5408cc8ceb9f363c72559Nick Kralevich    struct __user_cap_header_struct capheader;
507812b19a425b8304ac9e5408cc8ceb9f363c72559Nick Kralevich    struct __user_cap_data_struct capdata[2];
508812b19a425b8304ac9e5408cc8ceb9f363c72559Nick Kralevich    memset(&capheader, 0, sizeof(capheader));
509812b19a425b8304ac9e5408cc8ceb9f363c72559Nick Kralevich    memset(&capdata, 0, sizeof(capdata));
510812b19a425b8304ac9e5408cc8ceb9f363c72559Nick Kralevich    capheader.version = _LINUX_CAPABILITY_VERSION_3;
511812b19a425b8304ac9e5408cc8ceb9f363c72559Nick Kralevich    capheader.pid = 0;
512812b19a425b8304ac9e5408cc8ceb9f363c72559Nick Kralevich
513812b19a425b8304ac9e5408cc8ceb9f363c72559Nick Kralevich    capdata[CAP_TO_INDEX(CAP_DAC_OVERRIDE)].permitted |= CAP_TO_MASK(CAP_DAC_OVERRIDE);
514812b19a425b8304ac9e5408cc8ceb9f363c72559Nick Kralevich    capdata[CAP_TO_INDEX(CAP_CHOWN)].permitted        |= CAP_TO_MASK(CAP_CHOWN);
515812b19a425b8304ac9e5408cc8ceb9f363c72559Nick Kralevich    capdata[CAP_TO_INDEX(CAP_SETUID)].permitted       |= CAP_TO_MASK(CAP_SETUID);
516812b19a425b8304ac9e5408cc8ceb9f363c72559Nick Kralevich    capdata[CAP_TO_INDEX(CAP_SETGID)].permitted       |= CAP_TO_MASK(CAP_SETGID);
517812b19a425b8304ac9e5408cc8ceb9f363c72559Nick Kralevich
518812b19a425b8304ac9e5408cc8ceb9f363c72559Nick Kralevich    capdata[0].effective = capdata[0].permitted;
519812b19a425b8304ac9e5408cc8ceb9f363c72559Nick Kralevich    capdata[1].effective = capdata[1].permitted;
520812b19a425b8304ac9e5408cc8ceb9f363c72559Nick Kralevich    capdata[0].inheritable = 0;
521812b19a425b8304ac9e5408cc8ceb9f363c72559Nick Kralevich    capdata[1].inheritable = 0;
522812b19a425b8304ac9e5408cc8ceb9f363c72559Nick Kralevich
523812b19a425b8304ac9e5408cc8ceb9f363c72559Nick Kralevich    if (capset(&capheader, &capdata[0]) < 0) {
524812b19a425b8304ac9e5408cc8ceb9f363c72559Nick Kralevich        ALOGE("capset failed: %s\n", strerror(errno));
525812b19a425b8304ac9e5408cc8ceb9f363c72559Nick Kralevich        exit(1);
526812b19a425b8304ac9e5408cc8ceb9f363c72559Nick Kralevich    }
527812b19a425b8304ac9e5408cc8ceb9f363c72559Nick Kralevich}
528812b19a425b8304ac9e5408cc8ceb9f363c72559Nick Kralevich
52986c9584559439504fc57ece2ccd9b6cbd568430cKenny Rootint main(const int argc, const char *argv[]) {
5309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    char buf[BUFFER_MAX];
5319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    struct sockaddr addr;
5329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    socklen_t alen;
5339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    int lsocket, s, count;
5349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
535812b19a425b8304ac9e5408cc8ceb9f363c72559Nick Kralevich    ALOGI("installd firing up\n");
536812b19a425b8304ac9e5408cc8ceb9f363c72559Nick Kralevich
53786c9584559439504fc57ece2ccd9b6cbd568430cKenny Root    if (initialize_globals() < 0) {
5383762c311729fe9f3af085c14c5c1fb471d994c03Steve Block        ALOGE("Could not initialize globals; exiting.\n");
53986c9584559439504fc57ece2ccd9b6cbd568430cKenny Root        exit(1);
54086c9584559439504fc57ece2ccd9b6cbd568430cKenny Root    }
54186c9584559439504fc57ece2ccd9b6cbd568430cKenny Root
5420b285499db739ba50f2f839d633e763c70e67f96Amith Yamasani    if (initialize_directories() < 0) {
5433762c311729fe9f3af085c14c5c1fb471d994c03Steve Block        ALOGE("Could not create directories; exiting.\n");
5440b285499db739ba50f2f839d633e763c70e67f96Amith Yamasani        exit(1);
5450b285499db739ba50f2f839d633e763c70e67f96Amith Yamasani    }
5460b285499db739ba50f2f839d633e763c70e67f96Amith Yamasani
547812b19a425b8304ac9e5408cc8ceb9f363c72559Nick Kralevich    drop_privileges();
548812b19a425b8304ac9e5408cc8ceb9f363c72559Nick Kralevich
5499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    lsocket = android_get_control_socket(SOCKET_PATH);
5509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (lsocket < 0) {
5513762c311729fe9f3af085c14c5c1fb471d994c03Steve Block        ALOGE("Failed to get socket from environment: %s\n", strerror(errno));
5529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        exit(1);
5539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
5549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (listen(lsocket, 5)) {
5553762c311729fe9f3af085c14c5c1fb471d994c03Steve Block        ALOGE("Listen on socket failed: %s\n", strerror(errno));
5569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        exit(1);
5579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
5589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    fcntl(lsocket, F_SETFD, FD_CLOEXEC);
5599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    for (;;) {
5619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        alen = sizeof(addr);
5629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        s = accept(lsocket, &addr, &alen);
5639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (s < 0) {
5643762c311729fe9f3af085c14c5c1fb471d994c03Steve Block            ALOGE("Accept failed: %s\n", strerror(errno));
5659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            continue;
5669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
5679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        fcntl(s, F_SETFD, FD_CLOEXEC);
5689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5696215d3ff4b5dfa52a5d8b9a42e343051f31066a5Steve Block        ALOGI("new connection\n");
5709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        for (;;) {
5719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            unsigned short count;
5729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (readx(s, &count, sizeof(count))) {
5733762c311729fe9f3af085c14c5c1fb471d994c03Steve Block                ALOGE("failed to read size\n");
5749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                break;
5759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
5769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if ((count < 1) || (count >= BUFFER_MAX)) {
5773762c311729fe9f3af085c14c5c1fb471d994c03Steve Block                ALOGE("invalid size %d\n", count);
5789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                break;
5799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
5809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (readx(s, buf, count)) {
5813762c311729fe9f3af085c14c5c1fb471d994c03Steve Block                ALOGE("failed to read command\n");
5829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                break;
5839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
5849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            buf[count] = 0;
5859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (execute(s, buf)) break;
5869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
5876215d3ff4b5dfa52a5d8b9a42e343051f31066a5Steve Block        ALOGI("closing connection\n");
5889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        close(s);
5899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
5909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return 0;
5929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
593