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