installd.c revision 9066cfe9886ac131c34d59ed0e2d287b0e3c0087
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 25static int do_ping(char **arg, char reply[REPLY_MAX]) 26{ 27 return 0; 28} 29 30static int do_install(char **arg, char reply[REPLY_MAX]) 31{ 32 return install(arg[0], atoi(arg[1]), atoi(arg[2])); /* pkgname, uid, gid */ 33} 34 35static 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 41static int do_move_dex(char **arg, char reply[REPLY_MAX]) 42{ 43 return move_dex(arg[0], arg[1]); /* src, dst */ 44} 45 46static int do_rm_dex(char **arg, char reply[REPLY_MAX]) 47{ 48 return rm_dex(arg[0]); /* pkgname */ 49} 50 51static int do_remove(char **arg, char reply[REPLY_MAX]) 52{ 53 return uninstall(arg[0]); /* pkgname */ 54} 55 56static int do_free_cache(char **arg, char reply[REPLY_MAX]) /* TODO int:free_size */ 57{ 58 return free_cache(atoi(arg[0])); /* free_size */ 59} 60 61static int do_rm_cache(char **arg, char reply[REPLY_MAX]) 62{ 63 return delete_cache(arg[0]); /* pkgname */ 64} 65 66static int do_protect(char **arg, char reply[REPLY_MAX]) 67{ 68 return protect(arg[0], atoi(arg[1])); /* pkgname, gid */ 69} 70 71static int do_get_size(char **arg, char reply[REPLY_MAX]) 72{ 73 int codesize = 0; 74 int datasize = 0; 75 int cachesize = 0; 76 int res = 0; 77 78 /* pkgdir, apkpath */ 79 res = get_size(arg[0], arg[1], arg[2], &codesize, &datasize, &cachesize); 80 81 sprintf(reply,"%d %d %d", codesize, datasize, cachesize); 82 return res; 83} 84 85static int do_rm_user_data(char **arg, char reply[REPLY_MAX]) 86{ 87 return delete_user_data(arg[0]); /* pkgname */ 88} 89 90struct cmdinfo { 91 const char *name; 92 unsigned numargs; 93 int (*func)(char **arg, char reply[REPLY_MAX]); 94}; 95 96struct cmdinfo cmds[] = { 97 { "ping", 0, do_ping }, 98 { "install", 3, do_install }, 99 { "dexopt", 3, do_dexopt }, 100 { "movedex", 2, do_move_dex }, 101 { "rmdex", 1, do_rm_dex }, 102 { "remove", 1, do_remove }, 103 { "freecache", 1, do_free_cache }, 104 { "rmcache", 1, do_rm_cache }, 105 { "protect", 2, do_protect }, 106 { "getsize", 3, do_get_size }, 107 { "rmuserdata", 1, do_rm_user_data }, 108}; 109 110static int readx(int s, void *_buf, int count) 111{ 112 char *buf = _buf; 113 int n = 0, r; 114 if (count < 0) return -1; 115 while (n < count) { 116 r = read(s, buf + n, count - n); 117 if (r < 0) { 118 if (errno == EINTR) continue; 119 LOGE("read error: %s\n", strerror(errno)); 120 return -1; 121 } 122 if (r == 0) { 123 LOGE("eof\n"); 124 return -1; /* EOF */ 125 } 126 n += r; 127 } 128 return 0; 129} 130 131static int writex(int s, const void *_buf, int count) 132{ 133 const char *buf = _buf; 134 int n = 0, r; 135 if (count < 0) return -1; 136 while (n < count) { 137 r = write(s, buf + n, count - n); 138 if (r < 0) { 139 if (errno == EINTR) continue; 140 LOGE("write error: %s\n", strerror(errno)); 141 return -1; 142 } 143 n += r; 144 } 145 return 0; 146} 147 148 149/* Tokenize the command buffer, locate a matching command, 150 * ensure that the required number of arguments are provided, 151 * call the function(), return the result. 152 */ 153static int execute(int s, char cmd[BUFFER_MAX]) 154{ 155 char reply[REPLY_MAX]; 156 char *arg[TOKEN_MAX+1]; 157 unsigned i; 158 unsigned n = 0; 159 unsigned short count; 160 int ret = -1; 161 162// LOGI("execute('%s')\n", cmd); 163 164 /* default reply is "" */ 165 reply[0] = 0; 166 167 /* n is number of args (not counting arg[0]) */ 168 arg[0] = cmd; 169 while (*cmd) { 170 if (isspace(*cmd)) { 171 *cmd++ = 0; 172 n++; 173 arg[n] = cmd; 174 if (n == TOKEN_MAX) { 175 LOGE("too many arguments\n"); 176 goto done; 177 } 178 } 179 cmd++; 180 } 181 182 for (i = 0; i < sizeof(cmds) / sizeof(cmds[0]); i++) { 183 if (!strcmp(cmds[i].name,arg[0])) { 184 if (n != cmds[i].numargs) { 185 LOGE("%s requires %d arguments (%d given)\n", 186 cmds[i].name, cmds[i].numargs, n); 187 } else { 188 ret = cmds[i].func(arg + 1, reply); 189 } 190 goto done; 191 } 192 } 193 LOGE("unsupported command '%s'\n", arg[0]); 194 195done: 196 if (reply[0]) { 197 n = snprintf(cmd, BUFFER_MAX, "%d %s", ret, reply); 198 } else { 199 n = snprintf(cmd, BUFFER_MAX, "%d", ret); 200 } 201 if (n > BUFFER_MAX) n = BUFFER_MAX; 202 count = n; 203 204// LOGI("reply: '%s'\n", cmd); 205 if (writex(s, &count, sizeof(count))) return -1; 206 if (writex(s, cmd, count)) return -1; 207 return 0; 208} 209 210int main(const int argc, const char *argv[]) { 211 char buf[BUFFER_MAX]; 212 struct sockaddr addr; 213 socklen_t alen; 214 int lsocket, s, count; 215 216 lsocket = android_get_control_socket(SOCKET_PATH); 217 if (lsocket < 0) { 218 LOGE("Failed to get socket from environment: %s\n", strerror(errno)); 219 exit(1); 220 } 221 if (listen(lsocket, 5)) { 222 LOGE("Listen on socket failed: %s\n", strerror(errno)); 223 exit(1); 224 } 225 fcntl(lsocket, F_SETFD, FD_CLOEXEC); 226 227 for (;;) { 228 alen = sizeof(addr); 229 s = accept(lsocket, &addr, &alen); 230 if (s < 0) { 231 LOGE("Accept failed: %s\n", strerror(errno)); 232 continue; 233 } 234 fcntl(s, F_SETFD, FD_CLOEXEC); 235 236 LOGI("new connection\n"); 237 for (;;) { 238 unsigned short count; 239 if (readx(s, &count, sizeof(count))) { 240 LOGE("failed to read size\n"); 241 break; 242 } 243 if ((count < 1) || (count >= BUFFER_MAX)) { 244 LOGE("invalid size %d\n", count); 245 break; 246 } 247 if (readx(s, buf, count)) { 248 LOGE("failed to read command\n"); 249 break; 250 } 251 buf[count] = 0; 252 if (execute(s, buf)) break; 253 } 254 LOGI("closing connection\n"); 255 close(s); 256 } 257 258 return 0; 259} 260