"git@repo.buzztime.com:halo/system_extras.git" did not exist on "17ba6f0d475126d0a89d5f276d0973bc87df6bc9"
CommandListener.cpp 14.1 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
/*
 * Copyright (C) 2008 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include <stdlib.h>
#include <sys/socket.h>
19
#include <sys/types.h>
20 21
#include <netinet/in.h>
#include <arpa/inet.h>
22
#include <dirent.h>
23
#include <errno.h>
San Mehat's avatar
San Mehat committed
24
#include <fcntl.h>
25

San Mehat's avatar
San Mehat committed
26
#define LOG_TAG "VoldCmdListener"
27 28 29 30 31 32
#include <cutils/log.h>

#include <sysutils/SocketClient.h>

#include "CommandListener.h"
#include "VolumeManager.h"
33
#include "ResponseCode.h"
34
#include "Process.h"
San Mehat's avatar
San Mehat committed
35
#include "Xwarp.h"
San Mehat's avatar
San Mehat committed
36 37
#include "Loop.h"
#include "Devmapper.h"
38 39 40

CommandListener::CommandListener() :
                 FrameworkListener("vold") {
San Mehat's avatar
San Mehat committed
41
    registerCmd(new DumpCmd());
San Mehat's avatar
San Mehat committed
42 43
    registerCmd(new VolumeCmd());
    registerCmd(new AsecCmd());
44
    registerCmd(new ShareCmd());
45
    registerCmd(new StorageCmd());
San Mehat's avatar
San Mehat committed
46
    registerCmd(new XwarpCmd());
47 48
}

San Mehat's avatar
San Mehat committed
49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96
void CommandListener::dumpArgs(int argc, char **argv, int argObscure) {
    char buffer[4096];
    char *p = buffer;

    memset(buffer, 0, sizeof(buffer));
    int i;
    for (i = 0; i < argc; i++) {
        int len = strlen(argv[i]) + 1; // Account for space
        if (i == argObscure) {
            len += 2; // Account for {}
        }
        if (((p - buffer) + len) < (sizeof(buffer)-1)) {
            if (i == argObscure) {
                *p++ = '{';
                *p++ = '}';
                *p++ = ' ';
                continue;
            }
            strcpy(p, argv[i]);
            p+= strlen(argv[i]);
            if (i != (argc -1)) {
                *p++ = ' ';
            }
        }
    }
    LOGD("%s", buffer);
}

CommandListener::DumpCmd::DumpCmd() :
                 VoldCommand("dump") {
}

int CommandListener::DumpCmd::runCommand(SocketClient *cli,
                                         int argc, char **argv) {
    cli->sendMsg(0, "Dumping loop status", false);
    if (Loop::dumpState(cli)) {
        cli->sendMsg(ResponseCode::CommandOkay, "Loop dump failed", true);
    }
    cli->sendMsg(0, "Dumping DM status", false);
    if (Devmapper::dumpState(cli)) {
        cli->sendMsg(ResponseCode::CommandOkay, "Devmapper dump failed", true);
    }

    cli->sendMsg(ResponseCode::CommandOkay, "dump complete", false);
    return 0;
}


San Mehat's avatar
San Mehat committed
97 98
CommandListener::VolumeCmd::VolumeCmd() :
                 VoldCommand("volume") {
99 100
}

San Mehat's avatar
San Mehat committed
101
int CommandListener::VolumeCmd::runCommand(SocketClient *cli,
102
                                                      int argc, char **argv) {
San Mehat's avatar
San Mehat committed
103 104
    dumpArgs(argc, argv, -1);

San Mehat's avatar
San Mehat committed
105 106 107 108
    if (argc < 2) {
        cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing Argument", false);
        return 0;
    }
109

San Mehat's avatar
San Mehat committed
110 111 112 113 114
    VolumeManager *vm = VolumeManager::Instance();
    int rc = 0;

    if (!strcmp(argv[1], "list")) {
        return vm->listVolumes(cli);
San Mehat's avatar
San Mehat committed
115
    } else if (!strcmp(argv[1], "debug")) {
116 117 118 119 120
        if (argc != 3 || (argc == 3 && (strcmp(argv[2], "off") && strcmp(argv[2], "on")))) {
            cli->sendMsg(ResponseCode::CommandSyntaxError, "Usage: volume debug <off/on>", false);
            return 0;
        }
        vm->setDebug(!strcmp(argv[2], "on") ? true : false);
San Mehat's avatar
San Mehat committed
121
    } else if (!strcmp(argv[1], "mount")) {
122 123 124 125
        if (argc != 3) {
            cli->sendMsg(ResponseCode::CommandSyntaxError, "Usage: volume mount <path>", false);
            return 0;
        }
San Mehat's avatar
San Mehat committed
126 127
        rc = vm->mountVolume(argv[2]);
    } else if (!strcmp(argv[1], "unmount")) {
128 129 130 131 132
        if (argc < 3 || argc > 4 || (argc == 4 && strcmp(argv[3], "force"))) {
            cli->sendMsg(ResponseCode::CommandSyntaxError, "Usage: volume unmount <path> [force]", false);
            return 0;
        }

133 134 135 136 137
        bool force = false;
        if (argc >= 4 && !strcmp(argv[3], "force")) {
            force = true;
        }
        rc = vm->unmountVolume(argv[2], force);
San Mehat's avatar
San Mehat committed
138
    } else if (!strcmp(argv[1], "format")) {
139 140 141 142
        if (argc != 3) {
            cli->sendMsg(ResponseCode::CommandSyntaxError, "Usage: volume format <path>", false);
            return 0;
        }
San Mehat's avatar
San Mehat committed
143 144
        rc = vm->formatVolume(argv[2]);
    } else if (!strcmp(argv[1], "share")) {
145 146 147 148 149
        if (argc != 4) {
            cli->sendMsg(ResponseCode::CommandSyntaxError,
                    "Usage: volume share <path> <method>", false);
            return 0;
        }
San Mehat's avatar
San Mehat committed
150
        rc = vm->shareVolume(argv[2], argv[3]);
San Mehat's avatar
San Mehat committed
151
    } else if (!strcmp(argv[1], "unshare")) {
152 153 154 155 156
        if (argc != 4) {
            cli->sendMsg(ResponseCode::CommandSyntaxError,
                    "Usage: volume unshare <path> <method>", false);
            return 0;
        }
San Mehat's avatar
San Mehat committed
157
        rc = vm->unshareVolume(argv[2], argv[3]);
San Mehat's avatar
San Mehat committed
158 159
    } else if (!strcmp(argv[1], "shared")) {
        bool enabled = false;
160 161 162 163 164
        if (argc != 4) {
            cli->sendMsg(ResponseCode::CommandSyntaxError,
                    "Usage: volume shared <path> <method>", false);
            return 0;
        }
San Mehat's avatar
San Mehat committed
165

166
        if (vm->shareEnabled(argv[2], argv[3], &enabled)) {
San Mehat's avatar
San Mehat committed
167 168 169 170 171 172
            cli->sendMsg(
                    ResponseCode::OperationFailed, "Failed to determine share enable state", true);
        } else {
            cli->sendMsg(ResponseCode::ShareEnabledResult,
                    (enabled ? "Share enabled" : "Share disabled"), false);
        }
San Mehat's avatar
San Mehat committed
173
        return 0;
174
    } else {
San Mehat's avatar
San Mehat committed
175
        cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown volume cmd", false);
176 177
    }

San Mehat's avatar
San Mehat committed
178 179
    if (!rc) {
        cli->sendMsg(ResponseCode::CommandOkay, "volume operation succeeded", false);
180
    } else {
181 182
        int erno = errno;
        rc = ResponseCode::convertFromErrno();
San Mehat's avatar
San Mehat committed
183
        cli->sendMsg(rc, "volume operation failed", true);
184 185 186 187 188 189 190 191 192 193 194
    }

    return 0;
}

CommandListener::ShareCmd::ShareCmd() :
                 VoldCommand("share") {
}

int CommandListener::ShareCmd::runCommand(SocketClient *cli,
                                                      int argc, char **argv) {
San Mehat's avatar
San Mehat committed
195 196
    dumpArgs(argc, argv, -1);

San Mehat's avatar
San Mehat committed
197 198
    if (argc < 2) {
        cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing Argument", false);
199 200 201
        return 0;
    }

San Mehat's avatar
San Mehat committed
202 203
    VolumeManager *vm = VolumeManager::Instance();
    int rc = 0;
204

San Mehat's avatar
San Mehat committed
205 206
    if (!strcmp(argv[1], "status")) {
        bool avail = false;
207

San Mehat's avatar
San Mehat committed
208 209 210 211 212 213 214
        if (vm->shareAvailable(argv[2], &avail)) {
            cli->sendMsg(
                    ResponseCode::OperationFailed, "Failed to determine share availability", true);
        } else {
            cli->sendMsg(ResponseCode::ShareStatusResult,
                    (avail ? "Share available" : "Share unavailable"), false);
        }
215
    } else {
San Mehat's avatar
San Mehat committed
216
        cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown share cmd", false);
217
    }
218 219 220 221

    return 0;
}

222 223 224 225 226 227
CommandListener::StorageCmd::StorageCmd() :
                 VoldCommand("storage") {
}

int CommandListener::StorageCmd::runCommand(SocketClient *cli,
                                                      int argc, char **argv) {
San Mehat's avatar
San Mehat committed
228 229
    dumpArgs(argc, argv, -1);

230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272
    if (argc < 2) {
        cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing Argument", false);
        return 0;
    }

    if (!strcmp(argv[1], "users")) {
        DIR *dir;
        struct dirent *de;

        if (!(dir = opendir("/proc"))) {
            cli->sendMsg(ResponseCode::OperationFailed, "Failed to open /proc", true);
            return 0;
        }

        while ((de = readdir(dir))) {
            int pid = Process::getPid(de->d_name);

            if (pid < 0) {
                continue;
            }

            char processName[255];
            Process::getProcessName(pid, processName, sizeof(processName));

            if (Process::checkFileDescriptorSymLinks(pid, argv[2]) ||
                Process::checkFileMaps(pid, argv[2]) ||
                Process::checkSymLink(pid, argv[2], "cwd") ||
                Process::checkSymLink(pid, argv[2], "root") ||
                Process::checkSymLink(pid, argv[2], "exe")) {

                char msg[1024];
                snprintf(msg, sizeof(msg), "%d %s", pid, processName);
                cli->sendMsg(ResponseCode::StorageUsersListResult, msg, false);
            }
        }
        closedir(dir);
        cli->sendMsg(ResponseCode::CommandOkay, "Storage user list complete", false);
    } else {
        cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown storage cmd", false);
    }
    return 0;
}

San Mehat's avatar
San Mehat committed
273 274
CommandListener::AsecCmd::AsecCmd() :
                 VoldCommand("asec") {
275 276
}

San Mehat's avatar
San Mehat committed
277 278 279 280
int CommandListener::AsecCmd::runCommand(SocketClient *cli,
                                                      int argc, char **argv) {
    if (argc < 2) {
        cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing Argument", false);
281 282 283
        return 0;
    }

San Mehat's avatar
San Mehat committed
284 285
    VolumeManager *vm = VolumeManager::Instance();
    int rc = 0;
286

San Mehat's avatar
San Mehat committed
287
    if (!strcmp(argv[1], "list")) {
San Mehat's avatar
San Mehat committed
288
        dumpArgs(argc, argv, -1);
289
        DIR *d = opendir(Volume::SEC_ASECDIR);
290

San Mehat's avatar
San Mehat committed
291 292 293 294
        if (!d) {
            cli->sendMsg(ResponseCode::OperationFailed, "Failed to open asec dir", true);
            return 0;
        }
295

San Mehat's avatar
San Mehat committed
296 297 298 299 300 301 302 303 304 305 306 307 308
        struct dirent *dent;
        while ((dent = readdir(d))) {
            if (dent->d_name[0] == '.')
                continue;
            if (!strcmp(&dent->d_name[strlen(dent->d_name)-5], ".asec")) {
                char id[255];
                memset(id, 0, sizeof(id));
                strncpy(id, dent->d_name, strlen(dent->d_name) -5);
                cli->sendMsg(ResponseCode::AsecListResult, id, false);
            }
        }
        closedir(d);
    } else if (!strcmp(argv[1], "create")) {
San Mehat's avatar
San Mehat committed
309
        dumpArgs(argc, argv, 5);
San Mehat's avatar
San Mehat committed
310 311 312 313
        if (argc != 7) {
            cli->sendMsg(ResponseCode::CommandSyntaxError,
                    "Usage: asec create <container-id> <size_mb> <fstype> <key> <ownerUid>", false);
            return 0;
314 315
        }

San Mehat's avatar
San Mehat committed
316
        unsigned int numSectors = (atoi(argv[3]) * (1024 * 1024)) / 512;
317
        rc = vm->createAsec(argv[2], numSectors, argv[4], argv[5], atoi(argv[6]));
San Mehat's avatar
San Mehat committed
318
    } else if (!strcmp(argv[1], "finalize")) {
San Mehat's avatar
San Mehat committed
319
        dumpArgs(argc, argv, -1);
San Mehat's avatar
San Mehat committed
320 321 322 323
        if (argc != 3) {
            cli->sendMsg(ResponseCode::CommandSyntaxError, "Usage: asec finalize <container-id>", false);
            return 0;
        }
324
        rc = vm->finalizeAsec(argv[2]);
San Mehat's avatar
San Mehat committed
325
    } else if (!strcmp(argv[1], "destroy")) {
San Mehat's avatar
San Mehat committed
326
        dumpArgs(argc, argv, -1);
327 328
        if (argc < 3) {
            cli->sendMsg(ResponseCode::CommandSyntaxError, "Usage: asec destroy <container-id> [force]", false);
San Mehat's avatar
San Mehat committed
329 330
            return 0;
        }
331 332 333 334
        bool force = false;
        if (argc > 3 && !strcmp(argv[3], "force")) {
            force = true;
        }
335
        rc = vm->destroyAsec(argv[2], force);
San Mehat's avatar
San Mehat committed
336
    } else if (!strcmp(argv[1], "mount")) {
San Mehat's avatar
San Mehat committed
337
        dumpArgs(argc, argv, 3);
San Mehat's avatar
San Mehat committed
338 339 340 341 342
        if (argc != 5) {
            cli->sendMsg(ResponseCode::CommandSyntaxError,
                    "Usage: asec mount <namespace-id> <key> <ownerUid>", false);
            return 0;
        }
343
        rc = vm->mountAsec(argv[2], argv[3], atoi(argv[4]));
San Mehat's avatar
San Mehat committed
344
    } else if (!strcmp(argv[1], "unmount")) {
San Mehat's avatar
San Mehat committed
345
        dumpArgs(argc, argv, -1);
346 347
        if (argc < 3) {
            cli->sendMsg(ResponseCode::CommandSyntaxError, "Usage: asec unmount <container-id> [force]", false);
San Mehat's avatar
San Mehat committed
348 349
            return 0;
        }
350 351 352 353
        bool force = false;
        if (argc > 3 && !strcmp(argv[3], "force")) {
            force = true;
        }
354
        rc = vm->unmountAsec(argv[2], force);
San Mehat's avatar
San Mehat committed
355
    } else if (!strcmp(argv[1], "rename")) {
San Mehat's avatar
San Mehat committed
356
        dumpArgs(argc, argv, -1);
San Mehat's avatar
San Mehat committed
357 358 359 360 361
        if (argc != 4) {
            cli->sendMsg(ResponseCode::CommandSyntaxError,
                    "Usage: asec rename <old_id> <new_id>", false);
            return 0;
        }
362
        rc = vm->renameAsec(argv[2], argv[3]);
San Mehat's avatar
San Mehat committed
363
    } else if (!strcmp(argv[1], "path")) {
San Mehat's avatar
San Mehat committed
364
        dumpArgs(argc, argv, -1);
San Mehat's avatar
San Mehat committed
365 366 367 368 369
        if (argc != 3) {
            cli->sendMsg(ResponseCode::CommandSyntaxError, "Usage: asec path <container-id>", false);
            return 0;
        }
        char path[255];
370

San Mehat's avatar
San Mehat committed
371 372 373 374 375
        if (vm->getAsecMountPath(argv[2], path, sizeof(path))) {
            cli->sendMsg(ResponseCode::OperationFailed, "Failed to get path", true);
        } else {
            cli->sendMsg(ResponseCode::AsecPathResult, path, false);
        }
376
        return 0;
377
    } else {
San Mehat's avatar
San Mehat committed
378
        dumpArgs(argc, argv, -1);
San Mehat's avatar
San Mehat committed
379
        cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown asec cmd", false);
380 381
    }

382 383 384 385 386 387 388
    if (!rc) {
        cli->sendMsg(ResponseCode::CommandOkay, "asec operation succeeded", false);
    } else {
        rc = ResponseCode::convertFromErrno();
        cli->sendMsg(rc, "asec operation failed", true);
    }

389 390
    return 0;
}
San Mehat's avatar
San Mehat committed
391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434

CommandListener::XwarpCmd::XwarpCmd() :
                 VoldCommand("xwarp") {
}

int CommandListener::XwarpCmd::runCommand(SocketClient *cli,
                                                      int argc, char **argv) {
    if (argc < 2) {
        cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing Argument", false);
        return 0;
    }

    if (!strcmp(argv[1], "enable")) {
        if (Xwarp::enable()) {
            cli->sendMsg(ResponseCode::OperationFailed, "Failed to enable xwarp", true);
            return 0;
        }

        cli->sendMsg(ResponseCode::CommandOkay, "Xwarp mirroring started", false);
    } else if (!strcmp(argv[1], "disable")) {
        if (Xwarp::disable()) {
            cli->sendMsg(ResponseCode::OperationFailed, "Failed to disable xwarp", true);
            return 0;
        }

        cli->sendMsg(ResponseCode::CommandOkay, "Xwarp disabled", false);
    } else if (!strcmp(argv[1], "status")) {
        char msg[255];
        bool r;
        unsigned mirrorPos, maxSize;

        if (Xwarp::status(&r, &mirrorPos, &maxSize)) {
            cli->sendMsg(ResponseCode::OperationFailed, "Failed to get xwarp status", true);
            return 0;
        }
        snprintf(msg, sizeof(msg), "%s %u %u", (r ? "ready" : "not-ready"), mirrorPos, maxSize);
        cli->sendMsg(ResponseCode::XwarpStatusResult, msg, false);
    } else {
        cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown storage cmd", false);
    }

    return 0;
}