CommandListener.cpp revision 048b0801fcd6fcfbb8fa812284c751181e4821b8
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 34CommandListener::CommandListener() : 35 FrameworkListener("vold") { 36 registerCmd(new ListVolumesCmd()); 37 registerCmd(new MountCmd()); 38 registerCmd(new UnmountCmd()); 39 registerCmd(new ShareCmd()); 40 registerCmd(new UnshareCmd()); 41 registerCmd(new ShareAvailableCmd()); 42 registerCmd(new SimulateCmd()); 43 registerCmd(new FormatCmd()); 44 registerCmd(new CreateAsecCmd()); 45 registerCmd(new FinalizeAsecCmd()); 46 registerCmd(new DestroyAsecCmd()); 47 registerCmd(new MountAsecCmd()); 48 registerCmd(new UnmountAsecCmd()); 49 registerCmd(new RenameAsecCmd()); 50 registerCmd(new ListAsecCmd()); 51 registerCmd(new AsecPathCmd()); 52} 53 54CommandListener::ListVolumesCmd::ListVolumesCmd() : 55 VoldCommand("list_volumes") { 56} 57 58int CommandListener::ListVolumesCmd::runCommand(SocketClient *cli, 59 int argc, char **argv) { 60 return VolumeManager::Instance()->listVolumes(cli); 61} 62 63CommandListener::MountCmd::MountCmd() : 64 VoldCommand("mount") { 65} 66 67int CommandListener::MountCmd::runCommand(SocketClient *cli, 68 int argc, char **argv) { 69 /* Synchronously mount a volume */ 70 if (VolumeManager::Instance()->mountVolume(argv[1])) { 71 cli->sendMsg(ResponseCode::OperationFailed, "Failed to mount volume.", true); 72 } else { 73 cli->sendMsg(ResponseCode::CommandOkay, "Volume mounted.", false); 74 } 75 76 return 0; 77} 78 79CommandListener::UnmountCmd::UnmountCmd() : 80 VoldCommand("unmount") { 81} 82 83int CommandListener::UnmountCmd::runCommand(SocketClient *cli, 84 int argc, char **argv) { 85 /* Synchronously unmount a volume */ 86 if (VolumeManager::Instance()->unmountVolume(argv[1])) { 87 cli->sendMsg(ResponseCode::OperationFailed, "Failed to unmount volume.", true); 88 } else { 89 cli->sendMsg(ResponseCode::CommandOkay, "Volume unmounted.", false); 90 } 91 92 return 0; 93} 94 95CommandListener::ShareCmd::ShareCmd() : 96 VoldCommand("share") { 97} 98 99int CommandListener::ShareCmd::runCommand(SocketClient *cli, 100 int argc, char **argv) { 101 if (VolumeManager::Instance()->shareVolume(argv[1], argv[2])) { 102 cli->sendMsg(ResponseCode::OperationFailed, "Failed to share volume.", true); 103 } else { 104 cli->sendMsg(ResponseCode::CommandOkay, "Volume shared.", false); 105 } 106 107 return 0; 108} 109 110CommandListener::UnshareCmd::UnshareCmd() : 111 VoldCommand("unshare") { 112} 113 114int CommandListener::UnshareCmd::runCommand(SocketClient *cli, 115 int argc, char **argv) { 116 if (VolumeManager::Instance()->unshareVolume(argv[1], argv[2])) { 117 cli->sendMsg(ResponseCode::OperationFailed, "Failed to unshare volume.", true); 118 } else { 119 cli->sendMsg(ResponseCode::CommandOkay, "Volume unshared.", false); 120 } 121 122 return 0; 123} 124 125CommandListener::ShareAvailableCmd::ShareAvailableCmd() : 126 VoldCommand("share_available") { 127} 128 129int CommandListener::ShareAvailableCmd::runCommand(SocketClient *cli, 130 int argc, char **argv) { 131 bool avail = false; 132 133 if (VolumeManager::Instance()->shareAvailable(argv[1], &avail)) { 134 cli->sendMsg(ResponseCode::OperationFailed, 135 "Failed to determine share availability", true); 136 } else { 137 cli->sendMsg(ResponseCode::ShareAvailabilityResult, 138 (avail ? "Share available" : "Share unavailable"), 139 false); 140 } 141 return 0; 142} 143 144CommandListener::SimulateCmd::SimulateCmd() : 145 VoldCommand("simulate") { 146} 147 148int CommandListener::SimulateCmd::runCommand(SocketClient *cli, 149 int argc, char **argv) { 150 if (VolumeManager::Instance()->simulate(argv[1], argv[2])) { 151 cli->sendMsg(ResponseCode::OperationFailed, "Failed to execute.", true); 152 } else { 153 cli->sendMsg(ResponseCode::CommandOkay, "Simulation executed.", false); 154 } 155 156 return 0; 157} 158 159CommandListener::FormatCmd::FormatCmd() : 160 VoldCommand("format") { 161} 162 163int CommandListener::FormatCmd::runCommand(SocketClient *cli, 164 int argc, char **argv) { 165 if (VolumeManager::Instance()->formatVolume(argv[1])) { 166 cli->sendMsg(ResponseCode::OperationFailed, "Failed to format", true); 167 } else { 168 cli->sendMsg(ResponseCode::CommandOkay, "Volume formatted.", false); 169 } 170 171 return 0; 172} 173 174CommandListener::CreateAsecCmd::CreateAsecCmd() : 175 VoldCommand("create_asec") { 176} 177 178int CommandListener::CreateAsecCmd::runCommand(SocketClient *cli, 179 int argc, char **argv) { 180 if (argc != 6) { 181 cli->sendMsg(ResponseCode::CommandSyntaxError, 182 "Usage: create_asec <namespace-id> <size_mb> <fstype> <key> <ownerUid>", 183 false); 184 return 0; 185 } 186 187 unsigned int numSectors = (atoi(argv[2]) * (1024 * 1024)) / 512; 188 if (VolumeManager::Instance()->createAsec(argv[1], numSectors, 189 argv[3], argv[4], 190 atoi(argv[5]))) { 191 cli->sendMsg(ResponseCode::OperationFailed, "Container creation failed", true); 192 } else { 193 cli->sendMsg(ResponseCode::CommandOkay, "Container created", false); 194 } 195 196 return 0; 197} 198 199CommandListener::FinalizeAsecCmd::FinalizeAsecCmd() : 200 VoldCommand("finalize_asec") { 201} 202 203int CommandListener::FinalizeAsecCmd::runCommand(SocketClient *cli, 204 int argc, char **argv) { 205 if (argc != 2) { 206 cli->sendMsg(ResponseCode::CommandSyntaxError, 207 "Usage: finalize_asec <namespace-id>", false); 208 return 0; 209 } 210 211 if (VolumeManager::Instance()->finalizeAsec(argv[1])) { 212 cli->sendMsg(ResponseCode::OperationFailed, "Container finalize failed", true); 213 } else { 214 cli->sendMsg(ResponseCode::CommandOkay, "Container finalized", false); 215 } 216 return 0; 217} 218 219CommandListener::DestroyAsecCmd::DestroyAsecCmd() : 220 VoldCommand("destroy_asec") { 221} 222 223int CommandListener::DestroyAsecCmd::runCommand(SocketClient *cli, 224 int argc, char **argv) { 225 if (argc != 2) { 226 cli->sendMsg(ResponseCode::CommandSyntaxError, 227 "Usage: destroy_asec <namespace-id>", false); 228 return 0; 229 } 230 231 if (VolumeManager::Instance()->destroyAsec(argv[1])) { 232 cli->sendMsg(ResponseCode::OperationFailed, "Destroy failed", true); 233 } else { 234 cli->sendMsg(ResponseCode::CommandOkay, "Container Destroyed", false); 235 } 236 return 0; 237} 238 239CommandListener::MountAsecCmd::MountAsecCmd() : 240 VoldCommand("mount_asec") { 241} 242 243int CommandListener::MountAsecCmd::runCommand(SocketClient *cli, 244 int argc, char **argv) { 245 if (argc != 4) { 246 cli->sendMsg(ResponseCode::CommandSyntaxError, 247 "Usage: mount_asec <namespace-id> <key> <ownerUid>", false); 248 return 0; 249 } 250 251 if (VolumeManager::Instance()->mountAsec(argv[1], argv[2], atoi(argv[3]))) { 252 cli->sendMsg(ResponseCode::OperationFailed, "Mount failed", true); 253 } else { 254 cli->sendMsg(ResponseCode::CommandOkay, "Mount succeeded", false); 255 } 256 return 0; 257} 258 259CommandListener::UnmountAsecCmd::UnmountAsecCmd() : 260 VoldCommand("unmount_asec") { 261} 262 263int CommandListener::UnmountAsecCmd::runCommand(SocketClient *cli, 264 int argc, char **argv) { 265 if (argc != 2) { 266 cli->sendMsg(ResponseCode::CommandSyntaxError, 267 "Usage: unmount_asec <namespace-id>", false); 268 return 0; 269 } 270 271 if (VolumeManager::Instance()->unmountAsec(argv[1])) { 272 cli->sendMsg(ResponseCode::OperationFailed, "Unmount failed", true); 273 } else { 274 cli->sendMsg(ResponseCode::CommandOkay, "Unmount succeeded", false); 275 } 276 return 0; 277} 278 279CommandListener::RenameAsecCmd::RenameAsecCmd() : 280 VoldCommand("rename_asec") { 281} 282 283int CommandListener::RenameAsecCmd::runCommand(SocketClient *cli, 284 int argc, char **argv) { 285 if (argc != 3) { 286 cli->sendMsg(ResponseCode::CommandSyntaxError, 287 "Usage: rename_asec <id1> <id2>", false); 288 return 0; 289 } 290 291 if (VolumeManager::Instance()->renameAsec(argv[1], argv[2])) { 292 cli->sendMsg(ResponseCode::OperationFailed, "Rename failed", true); 293 } else { 294 cli->sendMsg(ResponseCode::CommandOkay, "Rename succeeded", false); 295 } 296 return 0; 297} 298 299CommandListener::ListAsecCmd::ListAsecCmd() : 300 VoldCommand("list_asec") { 301 302} 303 304int CommandListener::ListAsecCmd::runCommand(SocketClient *cli, 305 int argc, char **argv) { 306 DIR *d = opendir("/sdcard/android_secure"); 307 308 if (!d) { 309 cli->sendMsg(ResponseCode::OperationFailed, "Failed to open asec dir", true); 310 return 0; 311 } 312 313 struct dirent *dent; 314 while ((dent = readdir(d))) { 315 if (dent->d_name[0] == '.') 316 continue; 317 if (!strcmp(&dent->d_name[strlen(dent->d_name)-5], ".asec")) { 318 char id[255]; 319 memset(id, 0, sizeof(id)); 320 strncpy(id, dent->d_name, strlen(dent->d_name) -5); 321 cli->sendMsg(ResponseCode::AsecListResult, id, false); 322 } 323 } 324 closedir(d); 325 cli->sendMsg(ResponseCode::CommandOkay, "ASEC listing complete", false); 326 327 return 0; 328} 329 330CommandListener::AsecPathCmd::AsecPathCmd() : 331 VoldCommand("asec_path") { 332} 333 334int CommandListener::AsecPathCmd::runCommand(SocketClient *cli, 335 int argc, char **argv) { 336 if (argc != 2) { 337 cli->sendMsg(ResponseCode::CommandSyntaxError, 338 "Usage: asec_path <namespace-id>", false); 339 return 0; 340 } 341 342 char mountPath[255]; 343 344 if (VolumeManager::Instance()->getAsecMountPath(argv[1], mountPath, 345 sizeof(mountPath))) { 346 cli->sendMsg(ResponseCode::OperationFailed, "Failed to get mount path", true); 347 } else { 348 cli->sendMsg(ResponseCode::AsecPathResult, mountPath, false); 349 } 350 351 return 0; 352} 353