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