installd.c revision 86c9584559439504fc57ece2ccd9b6cbd568430c
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 24static int do_ping(char **arg, char reply[REPLY_MAX]) 25{ 26 return 0; 27} 28 29static int do_install(char **arg, char reply[REPLY_MAX]) 30{ 31 return install(arg[0], atoi(arg[1]), atoi(arg[2])); /* pkgname, uid, gid */ 32} 33 34static int do_dexopt(char **arg, char reply[REPLY_MAX]) 35{ 36 /* apk_path, uid, is_public */ 37 return dexopt(arg[0], atoi(arg[1]), atoi(arg[2])); 38} 39 40static int do_move_dex(char **arg, char reply[REPLY_MAX]) 41{ 42 return move_dex(arg[0], arg[1]); /* src, dst */ 43} 44 45static int do_rm_dex(char **arg, char reply[REPLY_MAX]) 46{ 47 return rm_dex(arg[0]); /* pkgname */ 48} 49 50static int do_remove(char **arg, char reply[REPLY_MAX]) 51{ 52 return uninstall(arg[0]); /* pkgname */ 53} 54 55static int do_rename(char **arg, char reply[REPLY_MAX]) 56{ 57 return renamepkg(arg[0], arg[1]); /* oldpkgname, newpkgname */ 58} 59 60static int do_free_cache(char **arg, char reply[REPLY_MAX]) /* TODO int:free_size */ 61{ 62 return free_cache((int64_t)atoll(arg[0])); /* free_size */ 63} 64 65static int do_rm_cache(char **arg, char reply[REPLY_MAX]) 66{ 67 return delete_cache(arg[0]); /* pkgname */ 68} 69 70static int do_protect(char **arg, char reply[REPLY_MAX]) 71{ 72 return protect(arg[0], atoi(arg[1])); /* pkgname, gid */ 73} 74 75static int do_get_size(char **arg, char reply[REPLY_MAX]) 76{ 77 int64_t codesize = 0; 78 int64_t datasize = 0; 79 int64_t cachesize = 0; 80 int res = 0; 81 82 /* pkgdir, apkpath */ 83 res = get_size(arg[0], arg[1], arg[2], &codesize, &datasize, &cachesize); 84 85 /* 86 * Each int64_t can take up 22 characters printed out. Make sure it 87 * doesn't go over REPLY_MAX in the future. 88 */ 89 snprintf(reply, REPLY_MAX, "%" PRId64 " %" PRId64 " %" PRId64, codesize, datasize, cachesize); 90 return res; 91} 92 93static int do_rm_user_data(char **arg, char reply[REPLY_MAX]) 94{ 95 return delete_user_data(arg[0]); /* pkgname */ 96} 97 98static int do_movefiles(char **arg, char reply[REPLY_MAX]) 99{ 100 return movefiles(); 101} 102 103static int do_linklib(char **arg, char reply[REPLY_MAX]) 104{ 105 return linklib(arg[0], arg[1]); 106} 107 108static int do_unlinklib(char **arg, char reply[REPLY_MAX]) 109{ 110 return unlinklib(arg[0]); 111} 112 113struct cmdinfo { 114 const char *name; 115 unsigned numargs; 116 int (*func)(char **arg, char reply[REPLY_MAX]); 117}; 118 119struct cmdinfo cmds[] = { 120 { "ping", 0, do_ping }, 121 { "install", 3, do_install }, 122 { "dexopt", 3, do_dexopt }, 123 { "movedex", 2, do_move_dex }, 124 { "rmdex", 1, do_rm_dex }, 125 { "remove", 1, do_remove }, 126 { "rename", 2, do_rename }, 127 { "freecache", 1, do_free_cache }, 128 { "rmcache", 1, do_rm_cache }, 129 { "protect", 2, do_protect }, 130 { "getsize", 3, do_get_size }, 131 { "rmuserdata", 1, do_rm_user_data }, 132 { "movefiles", 0, do_movefiles }, 133 { "linklib", 2, do_linklib }, 134 { "unlinklib", 1, do_unlinklib }, 135}; 136 137static int readx(int s, void *_buf, int count) 138{ 139 char *buf = _buf; 140 int n = 0, r; 141 if (count < 0) return -1; 142 while (n < count) { 143 r = read(s, buf + n, count - n); 144 if (r < 0) { 145 if (errno == EINTR) continue; 146 LOGE("read error: %s\n", strerror(errno)); 147 return -1; 148 } 149 if (r == 0) { 150 LOGE("eof\n"); 151 return -1; /* EOF */ 152 } 153 n += r; 154 } 155 return 0; 156} 157 158static int writex(int s, const void *_buf, int count) 159{ 160 const char *buf = _buf; 161 int n = 0, r; 162 if (count < 0) return -1; 163 while (n < count) { 164 r = write(s, buf + n, count - n); 165 if (r < 0) { 166 if (errno == EINTR) continue; 167 LOGE("write error: %s\n", strerror(errno)); 168 return -1; 169 } 170 n += r; 171 } 172 return 0; 173} 174 175 176/* Tokenize the command buffer, locate a matching command, 177 * ensure that the required number of arguments are provided, 178 * call the function(), return the result. 179 */ 180static int execute(int s, char cmd[BUFFER_MAX]) 181{ 182 char reply[REPLY_MAX]; 183 char *arg[TOKEN_MAX+1]; 184 unsigned i; 185 unsigned n = 0; 186 unsigned short count; 187 int ret = -1; 188 189// LOGI("execute('%s')\n", cmd); 190 191 /* default reply is "" */ 192 reply[0] = 0; 193 194 /* n is number of args (not counting arg[0]) */ 195 arg[0] = cmd; 196 while (*cmd) { 197 if (isspace(*cmd)) { 198 *cmd++ = 0; 199 n++; 200 arg[n] = cmd; 201 if (n == TOKEN_MAX) { 202 LOGE("too many arguments\n"); 203 goto done; 204 } 205 } 206 cmd++; 207 } 208 209 for (i = 0; i < sizeof(cmds) / sizeof(cmds[0]); i++) { 210 if (!strcmp(cmds[i].name,arg[0])) { 211 if (n != cmds[i].numargs) { 212 LOGE("%s requires %d arguments (%d given)\n", 213 cmds[i].name, cmds[i].numargs, n); 214 } else { 215 ret = cmds[i].func(arg + 1, reply); 216 } 217 goto done; 218 } 219 } 220 LOGE("unsupported command '%s'\n", arg[0]); 221 222done: 223 if (reply[0]) { 224 n = snprintf(cmd, BUFFER_MAX, "%d %s", ret, reply); 225 } else { 226 n = snprintf(cmd, BUFFER_MAX, "%d", ret); 227 } 228 if (n > BUFFER_MAX) n = BUFFER_MAX; 229 count = n; 230 231// LOGI("reply: '%s'\n", cmd); 232 if (writex(s, &count, sizeof(count))) return -1; 233 if (writex(s, cmd, count)) return -1; 234 return 0; 235} 236 237/** 238 * Initialize all the global variables that are used elsewhere. Returns 0 upon 239 * success and -1 on error. 240 */ 241void free_globals() { 242 size_t i; 243 244 for (i = 0; i < android_system_dirs.count; i++) { 245 if (android_system_dirs.dirs[i].path != NULL) { 246 free(android_system_dirs.dirs[i].path); 247 } 248 } 249 250 free(android_system_dirs.dirs); 251} 252 253int initialize_globals() { 254 // Get the android data directory. 255 if (get_path_from_env(&android_data_dir, "ANDROID_DATA") < 0) { 256 return -1; 257 } 258 259 // Get the android app directory. 260 if (copy_and_append(&android_app_dir, &android_data_dir, APP_SUBDIR) < 0) { 261 return -1; 262 } 263 264 // Get the android protected app directory. 265 if (copy_and_append(&android_app_private_dir, &android_data_dir, PRIVATE_APP_SUBDIR) < 0) { 266 return -1; 267 } 268 269 // Get the sd-card ASEC mount point. 270 if (get_path_from_env(&android_asec_dir, "ASEC_MOUNTPOINT") < 0) { 271 return -1; 272 } 273 274 // Take note of the system and vendor directories. 275 android_system_dirs.count = 2; 276 277 android_system_dirs.dirs = calloc(android_system_dirs.count, sizeof(dir_rec_t)); 278 if (android_system_dirs.dirs == NULL) { 279 LOGE("Couldn't allocate array for dirs; aborting\n"); 280 return -1; 281 } 282 283 // system 284 if (get_path_from_env(&android_system_dirs.dirs[0], "ANDROID_ROOT") < 0) { 285 free_globals(); 286 return -1; 287 } 288 289 // vendor 290 // TODO replace this with an environment variable (doesn't exist yet) 291 android_system_dirs.dirs[1].path = "/vendor/"; 292 android_system_dirs.dirs[1].len = strlen(android_system_dirs.dirs[1].path); 293 294 return 0; 295} 296 297int main(const int argc, const char *argv[]) { 298 char buf[BUFFER_MAX]; 299 struct sockaddr addr; 300 socklen_t alen; 301 int lsocket, s, count; 302 303 if (initialize_globals() < 0) { 304 LOGE("Could not initialize globals; exiting.\n"); 305 exit(1); 306 } 307 308 lsocket = android_get_control_socket(SOCKET_PATH); 309 if (lsocket < 0) { 310 LOGE("Failed to get socket from environment: %s\n", strerror(errno)); 311 exit(1); 312 } 313 if (listen(lsocket, 5)) { 314 LOGE("Listen on socket failed: %s\n", strerror(errno)); 315 exit(1); 316 } 317 fcntl(lsocket, F_SETFD, FD_CLOEXEC); 318 319 for (;;) { 320 alen = sizeof(addr); 321 s = accept(lsocket, &addr, &alen); 322 if (s < 0) { 323 LOGE("Accept failed: %s\n", strerror(errno)); 324 continue; 325 } 326 fcntl(s, F_SETFD, FD_CLOEXEC); 327 328 LOGI("new connection\n"); 329 for (;;) { 330 unsigned short count; 331 if (readx(s, &count, sizeof(count))) { 332 LOGE("failed to read size\n"); 333 break; 334 } 335 if ((count < 1) || (count >= BUFFER_MAX)) { 336 LOGE("invalid size %d\n", count); 337 break; 338 } 339 if (readx(s, buf, count)) { 340 LOGE("failed to read command\n"); 341 break; 342 } 343 buf[count] = 0; 344 if (execute(s, buf)) break; 345 } 346 LOGI("closing connection\n"); 347 close(s); 348 } 349 350 return 0; 351} 352