CommandListener.cpp revision 2350c44ff39b4cb2940893964a05f778fc80a436
1/* 2 * Copyright (C) 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 <stdlib.h> 18#include <sys/socket.h> 19#include <sys/types.h> 20#include <netinet/in.h> 21#include <arpa/inet.h> 22#include <dirent.h> 23#include <errno.h> 24#include <fcntl.h> 25 26#define LOG_TAG "CommandListener" 27#include <cutils/log.h> 28 29#include <sysutils/SocketClient.h> 30 31#include "CommandListener.h" 32#include "VolumeManager.h" 33#include "ResponseCode.h" 34#include "Process.h" 35#include "Xwarp.h" 36 37CommandListener::CommandListener() : 38 FrameworkListener("vold") { 39 registerCmd(new VolumeCmd()); 40 registerCmd(new AsecCmd()); 41 registerCmd(new ShareCmd()); 42 registerCmd(new StorageCmd()); 43 registerCmd(new XwarpCmd()); 44} 45 46CommandListener::VolumeCmd::VolumeCmd() : 47 VoldCommand("volume") { 48} 49 50int CommandListener::VolumeCmd::runCommand(SocketClient *cli, 51 int argc, char **argv) { 52 if (argc < 2) { 53 cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing Argument", false); 54 return 0; 55 } 56 57 VolumeManager *vm = VolumeManager::Instance(); 58 int rc = 0; 59 60 if (!strcmp(argv[1], "list")) { 61 return vm->listVolumes(cli); 62 } else if (!strcmp(argv[1], "mount")) { 63 rc = vm->mountVolume(argv[2]); 64 } else if (!strcmp(argv[1], "unmount")) { 65 bool force = false; 66 if (argc >= 4 && !strcmp(argv[3], "force")) { 67 force = true; 68 } 69 rc = vm->unmountVolume(argv[2], force); 70 } else if (!strcmp(argv[1], "format")) { 71 rc = vm->formatVolume(argv[2]); 72 } else if (!strcmp(argv[1], "share")) { 73 rc = vm->shareVolume(argv[2], argv[3]); 74 } else if (!strcmp(argv[1], "unshare")) { 75 rc = vm->unshareVolume(argv[2], argv[3]); 76 } else if (!strcmp(argv[1], "shared")) { 77 bool enabled = false; 78 79 if (vm->shareEnabled(argv[2], argv[3], &enabled)) { 80 cli->sendMsg( 81 ResponseCode::OperationFailed, "Failed to determine share enable state", true); 82 } else { 83 cli->sendMsg(ResponseCode::ShareEnabledResult, 84 (enabled ? "Share enabled" : "Share disabled"), false); 85 } 86 return 0; 87 } else { 88 cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown volume cmd", false); 89 } 90 91 if (!rc) { 92 cli->sendMsg(ResponseCode::CommandOkay, "volume operation succeeded", false); 93 } else { 94 int erno = errno; 95 rc = ResponseCode::convertFromErrno(); 96 cli->sendMsg(rc, "volume operation failed", true); 97 } 98 99 return 0; 100} 101 102CommandListener::ShareCmd::ShareCmd() : 103 VoldCommand("share") { 104} 105 106int CommandListener::ShareCmd::runCommand(SocketClient *cli, 107 int argc, char **argv) { 108 if (argc < 2) { 109 cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing Argument", false); 110 return 0; 111 } 112 113 VolumeManager *vm = VolumeManager::Instance(); 114 int rc = 0; 115 116 if (!strcmp(argv[1], "status")) { 117 bool avail = false; 118 119 if (vm->shareAvailable(argv[2], &avail)) { 120 cli->sendMsg( 121 ResponseCode::OperationFailed, "Failed to determine share availability", true); 122 } else { 123 cli->sendMsg(ResponseCode::ShareStatusResult, 124 (avail ? "Share available" : "Share unavailable"), false); 125 } 126 } else { 127 cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown share cmd", false); 128 } 129 130 return 0; 131} 132 133CommandListener::StorageCmd::StorageCmd() : 134 VoldCommand("storage") { 135} 136 137int CommandListener::StorageCmd::runCommand(SocketClient *cli, 138 int argc, char **argv) { 139 if (argc < 2) { 140 cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing Argument", false); 141 return 0; 142 } 143 144 if (!strcmp(argv[1], "users")) { 145 DIR *dir; 146 struct dirent *de; 147 148 if (!(dir = opendir("/proc"))) { 149 cli->sendMsg(ResponseCode::OperationFailed, "Failed to open /proc", true); 150 return 0; 151 } 152 153 while ((de = readdir(dir))) { 154 int pid = Process::getPid(de->d_name); 155 156 if (pid < 0) { 157 continue; 158 } 159 160 char processName[255]; 161 Process::getProcessName(pid, processName, sizeof(processName)); 162 163 if (Process::checkFileDescriptorSymLinks(pid, argv[2]) || 164 Process::checkFileMaps(pid, argv[2]) || 165 Process::checkSymLink(pid, argv[2], "cwd") || 166 Process::checkSymLink(pid, argv[2], "root") || 167 Process::checkSymLink(pid, argv[2], "exe")) { 168 169 char msg[1024]; 170 snprintf(msg, sizeof(msg), "%d %s", pid, processName); 171 cli->sendMsg(ResponseCode::StorageUsersListResult, msg, false); 172 } 173 } 174 closedir(dir); 175 cli->sendMsg(ResponseCode::CommandOkay, "Storage user list complete", false); 176 } else { 177 cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown storage cmd", false); 178 } 179 return 0; 180} 181 182CommandListener::AsecCmd::AsecCmd() : 183 VoldCommand("asec") { 184} 185 186int CommandListener::AsecCmd::runCommand(SocketClient *cli, 187 int argc, char **argv) { 188 if (argc < 2) { 189 cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing Argument", false); 190 return 0; 191 } 192 193 VolumeManager *vm = VolumeManager::Instance(); 194 int rc = 0; 195 196 if (!strcmp(argv[1], "list")) { 197 DIR *d = opendir(Volume::SEC_ASECDIR); 198 199 if (!d) { 200 cli->sendMsg(ResponseCode::OperationFailed, "Failed to open asec dir", true); 201 return 0; 202 } 203 204 struct dirent *dent; 205 while ((dent = readdir(d))) { 206 if (dent->d_name[0] == '.') 207 continue; 208 if (!strcmp(&dent->d_name[strlen(dent->d_name)-5], ".asec")) { 209 char id[255]; 210 memset(id, 0, sizeof(id)); 211 strncpy(id, dent->d_name, strlen(dent->d_name) -5); 212 cli->sendMsg(ResponseCode::AsecListResult, id, false); 213 } 214 } 215 closedir(d); 216 } else if (!strcmp(argv[1], "create")) { 217 if (argc != 7) { 218 cli->sendMsg(ResponseCode::CommandSyntaxError, 219 "Usage: asec create <container-id> <size_mb> <fstype> <key> <ownerUid>", false); 220 return 0; 221 } 222 223 unsigned int numSectors = (atoi(argv[3]) * (1024 * 1024)) / 512; 224 rc = vm->createAsec(argv[2], numSectors, argv[4], argv[5], atoi(argv[6])); 225 } else if (!strcmp(argv[1], "finalize")) { 226 if (argc != 3) { 227 cli->sendMsg(ResponseCode::CommandSyntaxError, "Usage: asec finalize <container-id>", false); 228 return 0; 229 } 230 rc = vm->finalizeAsec(argv[2]); 231 } else if (!strcmp(argv[1], "destroy")) { 232 if (argc < 3) { 233 cli->sendMsg(ResponseCode::CommandSyntaxError, "Usage: asec destroy <container-id> [force]", false); 234 return 0; 235 } 236 bool force = false; 237 if (argc > 3 && !strcmp(argv[3], "force")) { 238 force = true; 239 } 240 rc = vm->destroyAsec(argv[2], force); 241 } else if (!strcmp(argv[1], "mount")) { 242 if (argc != 5) { 243 cli->sendMsg(ResponseCode::CommandSyntaxError, 244 "Usage: asec mount <namespace-id> <key> <ownerUid>", false); 245 return 0; 246 } 247 rc = vm->mountAsec(argv[2], argv[3], atoi(argv[4])); 248 } else if (!strcmp(argv[1], "unmount")) { 249 if (argc < 3) { 250 cli->sendMsg(ResponseCode::CommandSyntaxError, "Usage: asec unmount <container-id> [force]", false); 251 return 0; 252 } 253 bool force = false; 254 if (argc > 3 && !strcmp(argv[3], "force")) { 255 force = true; 256 } 257 rc = vm->unmountAsec(argv[2], force); 258 } else if (!strcmp(argv[1], "rename")) { 259 if (argc != 4) { 260 cli->sendMsg(ResponseCode::CommandSyntaxError, 261 "Usage: asec rename <old_id> <new_id>", false); 262 return 0; 263 } 264 rc = vm->renameAsec(argv[2], argv[3]); 265 } else if (!strcmp(argv[1], "path")) { 266 if (argc != 3) { 267 cli->sendMsg(ResponseCode::CommandSyntaxError, "Usage: asec path <container-id>", false); 268 return 0; 269 } 270 char path[255]; 271 272 if (vm->getAsecMountPath(argv[2], path, sizeof(path))) { 273 cli->sendMsg(ResponseCode::OperationFailed, "Failed to get path", true); 274 } else { 275 cli->sendMsg(ResponseCode::AsecPathResult, path, false); 276 } 277 return 0; 278 } else { 279 cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown asec cmd", false); 280 } 281 282 if (!rc) { 283 cli->sendMsg(ResponseCode::CommandOkay, "asec operation succeeded", false); 284 } else { 285 rc = ResponseCode::convertFromErrno(); 286 cli->sendMsg(rc, "asec operation failed", true); 287 } 288 289 return 0; 290} 291 292CommandListener::XwarpCmd::XwarpCmd() : 293 VoldCommand("xwarp") { 294} 295 296int CommandListener::XwarpCmd::runCommand(SocketClient *cli, 297 int argc, char **argv) { 298 if (argc < 2) { 299 cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing Argument", false); 300 return 0; 301 } 302 303 if (!strcmp(argv[1], "enable")) { 304 if (Xwarp::enable()) { 305 cli->sendMsg(ResponseCode::OperationFailed, "Failed to enable xwarp", true); 306 return 0; 307 } 308 309 cli->sendMsg(ResponseCode::CommandOkay, "Xwarp mirroring started", false); 310 } else if (!strcmp(argv[1], "disable")) { 311 if (Xwarp::disable()) { 312 cli->sendMsg(ResponseCode::OperationFailed, "Failed to disable xwarp", true); 313 return 0; 314 } 315 316 cli->sendMsg(ResponseCode::CommandOkay, "Xwarp disabled", false); 317 } else if (!strcmp(argv[1], "status")) { 318 char msg[255]; 319 bool r; 320 unsigned mirrorPos, maxSize; 321 322 if (Xwarp::status(&r, &mirrorPos, &maxSize)) { 323 cli->sendMsg(ResponseCode::OperationFailed, "Failed to get xwarp status", true); 324 return 0; 325 } 326 snprintf(msg, sizeof(msg), "%s %u %u", (r ? "ready" : "not-ready"), mirrorPos, maxSize); 327 cli->sendMsg(ResponseCode::XwarpStatusResult, msg, false); 328 } else { 329 cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown storage cmd", false); 330 } 331 332 return 0; 333} 334 335