Home | History | Annotate | Download | only in installd
      1 /*
      2 ** Copyright 2008, The Android Open Source Project
      3 **
      4 ** Licensed under the Apache License, Version 2.0 (the "License");
      5 ** you may not use this file except in compliance with the License.
      6 ** You may obtain a copy of the License at
      7 **
      8 **     http://www.apache.org/licenses/LICENSE-2.0
      9 **
     10 ** Unless required by applicable law or agreed to in writing, software
     11 ** distributed under the License is distributed on an "AS IS" BASIS,
     12 ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13 ** See the License for the specific language governing permissions and
     14 ** limitations under the License.
     15 */
     16 
     17 #include "installd.h"
     18 
     19 
     20 #define BUFFER_MAX    1024  /* input buffer for commands */
     21 #define TOKEN_MAX     8     /* max number of arguments in buffer */
     22 #define REPLY_MAX     256   /* largest reply allowed */
     23 
     24 
     25 static int do_ping(char **arg, char reply[REPLY_MAX])
     26 {
     27     return 0;
     28 }
     29 
     30 static int do_install(char **arg, char reply[REPLY_MAX])
     31 {
     32     return install(arg[0], atoi(arg[1]), atoi(arg[2]), atoi(arg[3])); /* pkgname, uid, gid */
     33 }
     34 
     35 static int do_dexopt(char **arg, char reply[REPLY_MAX])
     36 {
     37         /* apk_path, uid, is_public */
     38     return dexopt(arg[0], atoi(arg[1]), atoi(arg[2]));
     39 }
     40 
     41 static int do_move_dex(char **arg, char reply[REPLY_MAX])
     42 {
     43     return move_dex(arg[0], arg[1]); /* src, dst */
     44 }
     45 
     46 static int do_rm_dex(char **arg, char reply[REPLY_MAX])
     47 {
     48     return rm_dex(arg[0]); /* pkgname */
     49 }
     50 
     51 static int do_remove(char **arg, char reply[REPLY_MAX])
     52 {
     53     return uninstall(arg[0], atoi(arg[1])); /* pkgname */
     54 }
     55 
     56 static int do_rename(char **arg, char reply[REPLY_MAX])
     57 {
     58     return renamepkg(arg[0], arg[1], atoi(arg[2])); /* oldpkgname, newpkgname */
     59 }
     60 
     61 static int do_free_cache(char **arg, char reply[REPLY_MAX]) /* TODO int:free_size */
     62 {
     63     return free_cache((int64_t)atoll(arg[0])); /* free_size */
     64 }
     65 
     66 static int do_rm_cache(char **arg, char reply[REPLY_MAX])
     67 {
     68     return delete_cache(arg[0], atoi(arg[1])); /* pkgname */
     69 }
     70 
     71 static int do_protect(char **arg, char reply[REPLY_MAX])
     72 {
     73     return protect(arg[0], atoi(arg[1])); /* pkgname, gid */
     74 }
     75 
     76 static int do_get_size(char **arg, char reply[REPLY_MAX])
     77 {
     78     int64_t codesize = 0;
     79     int64_t datasize = 0;
     80     int64_t cachesize = 0;
     81     int res = 0;
     82 
     83         /* pkgdir, apkpath */
     84     res = get_size(arg[0], arg[1], arg[2], &codesize, &datasize, &cachesize, atoi(arg[3]));
     85 
     86     /*
     87      * Each int64_t can take up 22 characters printed out. Make sure it
     88      * doesn't go over REPLY_MAX in the future.
     89      */
     90     snprintf(reply, REPLY_MAX, "%" PRId64 " %" PRId64 " %" PRId64, codesize, datasize, cachesize);
     91     return res;
     92 }
     93 
     94 static int do_rm_user_data(char **arg, char reply[REPLY_MAX])
     95 {
     96     return delete_user_data(arg[0], atoi(arg[1])); /* pkgname */
     97 }
     98 
     99 static int do_movefiles(char **arg, char reply[REPLY_MAX])
    100 {
    101     return movefiles();
    102 }
    103 
    104 static int do_linklib(char **arg, char reply[REPLY_MAX])
    105 {
    106     return linklib(arg[0], arg[1]);
    107 }
    108 
    109 static int do_unlinklib(char **arg, char reply[REPLY_MAX])
    110 {
    111     return unlinklib(arg[0]);
    112 }
    113 
    114 struct cmdinfo {
    115     const char *name;
    116     unsigned numargs;
    117     int (*func)(char **arg, char reply[REPLY_MAX]);
    118 };
    119 
    120 struct cmdinfo cmds[] = {
    121     { "ping",                 0, do_ping },
    122     { "install",              4, do_install },
    123     { "dexopt",               3, do_dexopt },
    124     { "movedex",              2, do_move_dex },
    125     { "rmdex",                1, do_rm_dex },
    126     { "remove",               2, do_remove },
    127     { "rename",               3, do_rename },
    128     { "freecache",            1, do_free_cache },
    129     { "rmcache",              2, do_rm_cache },
    130     { "protect",              2, do_protect },
    131     { "getsize",              4, do_get_size },
    132     { "rmuserdata",           2, do_rm_user_data },
    133     { "movefiles",            0, do_movefiles },
    134     { "linklib",              2, do_linklib },
    135     { "unlinklib",            1, do_unlinklib },
    136 };
    137 
    138 static int readx(int s, void *_buf, int count)
    139 {
    140     char *buf = _buf;
    141     int n = 0, r;
    142     if (count < 0) return -1;
    143     while (n < count) {
    144         r = read(s, buf + n, count - n);
    145         if (r < 0) {
    146             if (errno == EINTR) continue;
    147             LOGE("read error: %s\n", strerror(errno));
    148             return -1;
    149         }
    150         if (r == 0) {
    151             LOGE("eof\n");
    152             return -1; /* EOF */
    153         }
    154         n += r;
    155     }
    156     return 0;
    157 }
    158 
    159 static int writex(int s, const void *_buf, int count)
    160 {
    161     const char *buf = _buf;
    162     int n = 0, r;
    163     if (count < 0) return -1;
    164     while (n < count) {
    165         r = write(s, buf + n, count - n);
    166         if (r < 0) {
    167             if (errno == EINTR) continue;
    168             LOGE("write error: %s\n", strerror(errno));
    169             return -1;
    170         }
    171         n += r;
    172     }
    173     return 0;
    174 }
    175 
    176 
    177 /* Tokenize the command buffer, locate a matching command,
    178  * ensure that the required number of arguments are provided,
    179  * call the function(), return the result.
    180  */
    181 static int execute(int s, char cmd[BUFFER_MAX])
    182 {
    183     char reply[REPLY_MAX];
    184     char *arg[TOKEN_MAX+1];
    185     unsigned i;
    186     unsigned n = 0;
    187     unsigned short count;
    188     int ret = -1;
    189 
    190 //    LOGI("execute('%s')\n", cmd);
    191 
    192         /* default reply is "" */
    193     reply[0] = 0;
    194 
    195         /* n is number of args (not counting arg[0]) */
    196     arg[0] = cmd;
    197     while (*cmd) {
    198         if (isspace(*cmd)) {
    199             *cmd++ = 0;
    200             n++;
    201             arg[n] = cmd;
    202             if (n == TOKEN_MAX) {
    203                 LOGE("too many arguments\n");
    204                 goto done;
    205             }
    206         }
    207         cmd++;
    208     }
    209 
    210     for (i = 0; i < sizeof(cmds) / sizeof(cmds[0]); i++) {
    211         if (!strcmp(cmds[i].name,arg[0])) {
    212             if (n != cmds[i].numargs) {
    213                 LOGE("%s requires %d arguments (%d given)\n",
    214                      cmds[i].name, cmds[i].numargs, n);
    215             } else {
    216                 ret = cmds[i].func(arg + 1, reply);
    217             }
    218             goto done;
    219         }
    220     }
    221     LOGE("unsupported command '%s'\n", arg[0]);
    222 
    223 done:
    224     if (reply[0]) {
    225         n = snprintf(cmd, BUFFER_MAX, "%d %s", ret, reply);
    226     } else {
    227         n = snprintf(cmd, BUFFER_MAX, "%d", ret);
    228     }
    229     if (n > BUFFER_MAX) n = BUFFER_MAX;
    230     count = n;
    231 
    232 //    LOGI("reply: '%s'\n", cmd);
    233     if (writex(s, &count, sizeof(count))) return -1;
    234     if (writex(s, cmd, count)) return -1;
    235     return 0;
    236 }
    237 
    238 int main(const int argc, const char *argv[]) {
    239     char buf[BUFFER_MAX];
    240     struct sockaddr addr;
    241     socklen_t alen;
    242     int lsocket, s, count;
    243 
    244     lsocket = android_get_control_socket(SOCKET_PATH);
    245     if (lsocket < 0) {
    246         LOGE("Failed to get socket from environment: %s\n", strerror(errno));
    247         exit(1);
    248     }
    249     if (listen(lsocket, 5)) {
    250         LOGE("Listen on socket failed: %s\n", strerror(errno));
    251         exit(1);
    252     }
    253     fcntl(lsocket, F_SETFD, FD_CLOEXEC);
    254 
    255     for (;;) {
    256         alen = sizeof(addr);
    257         s = accept(lsocket, &addr, &alen);
    258         if (s < 0) {
    259             LOGE("Accept failed: %s\n", strerror(errno));
    260             continue;
    261         }
    262         fcntl(s, F_SETFD, FD_CLOEXEC);
    263 
    264         LOGI("new connection\n");
    265         for (;;) {
    266             unsigned short count;
    267             if (readx(s, &count, sizeof(count))) {
    268                 LOGE("failed to read size\n");
    269                 break;
    270             }
    271             if ((count < 1) || (count >= BUFFER_MAX)) {
    272                 LOGE("invalid size %d\n", count);
    273                 break;
    274             }
    275             if (readx(s, buf, count)) {
    276                 LOGE("failed to read command\n");
    277                 break;
    278             }
    279             buf[count] = 0;
    280             if (execute(s, buf)) break;
    281         }
    282         LOGI("closing connection\n");
    283         close(s);
    284     }
    285 
    286     return 0;
    287 }
    288