CommandListener.cpp revision 2b22552f9a3b077f9d0a3624ac6f9b8b332f8a7a
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 VolumeCmd()); 37 registerCmd(new AsecCmd()); 38 registerCmd(new ShareCmd()); 39} 40 41CommandListener::VolumeCmd::VolumeCmd() : 42 VoldCommand("volume") { 43} 44 45int CommandListener::VolumeCmd::runCommand(SocketClient *cli, 46 int argc, char **argv) { 47 if (argc < 2) { 48 cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing Argument", false); 49 return 0; 50 } 51 52 VolumeManager *vm = VolumeManager::Instance(); 53 int rc = 0; 54 55 if (!strcmp(argv[1], "list")) { 56 return vm->listVolumes(cli); 57 } else if (!strcmp(argv[1], "mount")) { 58 rc = vm->mountVolume(argv[2]); 59 } else if (!strcmp(argv[1], "unmount")) { 60 rc = vm->unmountVolume(argv[2]); 61 } else if (!strcmp(argv[1], "format")) { 62 rc = vm->formatVolume(argv[2]); 63 } else if (!strcmp(argv[1], "share")) { 64 rc = vm->shareVolume(argv[1], argv[2]); 65 } else if (!strcmp(argv[1], "unshare")) { 66 rc = vm->unshareVolume(argv[1], argv[2]); 67 } else if (!strcmp(argv[1], "shared")) { 68 bool enabled = false; 69 70 if (vm->shareEnabled(argv[2], argv[3], &enabled)) { 71 cli->sendMsg( 72 ResponseCode::OperationFailed, "Failed to determine share enable state", true); 73 } else { 74 cli->sendMsg(ResponseCode::ShareEnabledResult, 75 (enabled ? "Share enabled" : "Share disabled"), false); 76 } 77 } else { 78 cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown volume cmd", false); 79 } 80 81 if (!rc) { 82 cli->sendMsg(ResponseCode::CommandOkay, "volume operation succeeded", false); 83 } else { 84 /* 85 * Failed 86 */ 87 if (errno == ENODEV) { 88 rc = ResponseCode::OpFailedNoMedia; 89 } else if (errno == ENODATA) { 90 rc = ResponseCode::OpFailedMediaBlank; 91 } else if (errno == EIO) { 92 rc = ResponseCode::OpFailedMediaCorrupt; 93 } else if (errno == EBUSY) { 94 rc = ResponseCode::OpFailedVolBusy; 95 } else { 96 rc = ResponseCode::OperationFailed; 97 } 98 cli->sendMsg(rc, "volume operation failed", true); 99 } 100 101 return 0; 102} 103 104CommandListener::ShareCmd::ShareCmd() : 105 VoldCommand("share") { 106} 107 108int CommandListener::ShareCmd::runCommand(SocketClient *cli, 109 int argc, char **argv) { 110 if (argc < 2) { 111 cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing Argument", false); 112 return 0; 113 } 114 115 VolumeManager *vm = VolumeManager::Instance(); 116 int rc = 0; 117 118 if (!strcmp(argv[1], "status")) { 119 bool avail = false; 120 121 if (vm->shareAvailable(argv[2], &avail)) { 122 cli->sendMsg( 123 ResponseCode::OperationFailed, "Failed to determine share availability", true); 124 } else { 125 cli->sendMsg(ResponseCode::ShareStatusResult, 126 (avail ? "Share available" : "Share unavailable"), false); 127 } 128 } else { 129 cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown share cmd", false); 130 } 131 132 return 0; 133} 134 135CommandListener::AsecCmd::AsecCmd() : 136 VoldCommand("asec") { 137} 138 139int CommandListener::AsecCmd::runCommand(SocketClient *cli, 140 int argc, char **argv) { 141 if (argc < 2) { 142 cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing Argument", false); 143 return 0; 144 } 145 146 VolumeManager *vm = VolumeManager::Instance(); 147 int rc = 0; 148 149 if (!strcmp(argv[1], "list")) { 150 DIR *d = opendir("/sdcard/android_secure"); 151 152 if (!d) { 153 cli->sendMsg(ResponseCode::OperationFailed, "Failed to open asec dir", true); 154 return 0; 155 } 156 157 struct dirent *dent; 158 while ((dent = readdir(d))) { 159 if (dent->d_name[0] == '.') 160 continue; 161 if (!strcmp(&dent->d_name[strlen(dent->d_name)-5], ".asec")) { 162 char id[255]; 163 memset(id, 0, sizeof(id)); 164 strncpy(id, dent->d_name, strlen(dent->d_name) -5); 165 cli->sendMsg(ResponseCode::AsecListResult, id, false); 166 } 167 } 168 closedir(d); 169 cli->sendMsg(ResponseCode::CommandOkay, "ASEC listing complete", false); 170 } else if (!strcmp(argv[1], "create")) { 171 if (argc != 7) { 172 cli->sendMsg(ResponseCode::CommandSyntaxError, 173 "Usage: asec create <container-id> <size_mb> <fstype> <key> <ownerUid>", false); 174 return 0; 175 } 176 177 unsigned int numSectors = (atoi(argv[3]) * (1024 * 1024)) / 512; 178 if (vm->createAsec(argv[2], numSectors, argv[4], argv[5], atoi(argv[6]))) { 179 cli->sendMsg(ResponseCode::OperationFailed, "Container creation failed", true); 180 } else { 181 cli->sendMsg(ResponseCode::CommandOkay, "Container created", false); 182 } 183 } else if (!strcmp(argv[1], "finalize")) { 184 if (argc != 3) { 185 cli->sendMsg(ResponseCode::CommandSyntaxError, "Usage: asec finalize <container-id>", false); 186 return 0; 187 } 188 if (vm->finalizeAsec(argv[2])) { 189 cli->sendMsg(ResponseCode::OperationFailed, "Container finalize failed", true); 190 } else { 191 cli->sendMsg(ResponseCode::CommandOkay, "Container finalized", false); 192 } 193 } else if (!strcmp(argv[1], "destroy")) { 194 if (argc != 3) { 195 cli->sendMsg(ResponseCode::CommandSyntaxError, "Usage: asec destroy <container-id>", false); 196 return 0; 197 } 198 if (vm->destroyAsec(argv[2])) { 199 cli->sendMsg(ResponseCode::OperationFailed, "Container destroy failed", true); 200 } else { 201 cli->sendMsg(ResponseCode::CommandOkay, "Container destroyed", false); 202 } 203 } else if (!strcmp(argv[1], "mount")) { 204 if (argc != 5) { 205 cli->sendMsg(ResponseCode::CommandSyntaxError, 206 "Usage: asec mount <namespace-id> <key> <ownerUid>", false); 207 return 0; 208 } 209 210 int rc = vm->mountAsec(argv[2], argv[3], atoi(argv[4])); 211 212 if (rc < 0) { 213 cli->sendMsg(ResponseCode::OperationFailed, "Mount failed", true); 214 } else { 215 cli->sendMsg(ResponseCode::CommandOkay, "Mount succeeded", false); 216 } 217 218 } else if (!strcmp(argv[1], "unmount")) { 219 if (argc != 3) { 220 cli->sendMsg(ResponseCode::CommandSyntaxError, "Usage: asec unmount <container-id>", false); 221 return 0; 222 } 223 if (vm->unmountAsec(argv[2])) { 224 cli->sendMsg(ResponseCode::OperationFailed, "Container unmount failed", true); 225 } else { 226 cli->sendMsg(ResponseCode::CommandOkay, "Container unmounted", false); 227 } 228 } else if (!strcmp(argv[1], "rename")) { 229 if (argc != 4) { 230 cli->sendMsg(ResponseCode::CommandSyntaxError, 231 "Usage: asec rename <old_id> <new_id>", false); 232 return 0; 233 } 234 if (vm->renameAsec(argv[2], argv[3])) { 235 cli->sendMsg(ResponseCode::OperationFailed, "Container rename failed", true); 236 } else { 237 cli->sendMsg(ResponseCode::CommandOkay, "Container renamed", false); 238 } 239 } else if (!strcmp(argv[1], "path")) { 240 if (argc != 3) { 241 cli->sendMsg(ResponseCode::CommandSyntaxError, "Usage: asec path <container-id>", false); 242 return 0; 243 } 244 char path[255]; 245 246 if (vm->getAsecMountPath(argv[2], path, sizeof(path))) { 247 cli->sendMsg(ResponseCode::OperationFailed, "Failed to get path", true); 248 } else { 249 cli->sendMsg(ResponseCode::AsecPathResult, path, false); 250 } 251 } else { 252 cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown asec cmd", false); 253 } 254 255 return 0; 256} 257