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