installd.c revision 35ab3ad61fcc349380d7e7f2fcf9a0dfbf76ae11
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_rename(char **arg, char reply[REPLY_MAX]) 57{ 58 return renamepkg(arg[0], arg[1]); /* oldpkgname, newpkgname */ 59} 60 61static 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 66static int do_rm_cache(char **arg, char reply[REPLY_MAX]) 67{ 68 return delete_cache(arg[0]); /* pkgname */ 69} 70 71static int do_protect(char **arg, char reply[REPLY_MAX]) 72{ 73 return protect(arg[0], atoi(arg[1])); /* pkgname, gid */ 74} 75 76static 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); 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 94static int do_rm_user_data(char **arg, char reply[REPLY_MAX]) 95{ 96 return delete_user_data(arg[0]); /* pkgname */ 97} 98 99static int do_movefiles(char **arg, char reply[REPLY_MAX]) 100{ 101 return movefiles(); 102} 103 104static int do_linklib(char **arg, char reply[REPLY_MAX]) 105{ 106 return linklib(arg[0], arg[1]); 107} 108 109static int do_unlinklib(char **arg, char reply[REPLY_MAX]) 110{ 111 return unlinklib(arg[0]); 112} 113 114struct cmdinfo { 115 const char *name; 116 unsigned numargs; 117 int (*func)(char **arg, char reply[REPLY_MAX]); 118}; 119 120struct cmdinfo cmds[] = { 121 { "ping", 0, do_ping }, 122 { "install", 3, do_install }, 123 { "dexopt", 3, do_dexopt }, 124 { "movedex", 2, do_move_dex }, 125 { "rmdex", 1, do_rm_dex }, 126 { "remove", 1, do_remove }, 127 { "rename", 2, do_rename }, 128 { "freecache", 1, do_free_cache }, 129 { "rmcache", 1, do_rm_cache }, 130 { "protect", 2, do_protect }, 131 { "getsize", 3, do_get_size }, 132 { "rmuserdata", 1, do_rm_user_data }, 133 { "movefiles", 0, do_movefiles }, 134 { "linklib", 2, do_linklib }, 135 { "unlinklib", 1, do_unlinklib }, 136}; 137 138static 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 159static 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 */ 181static 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 223done: 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 238int 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