CommandListener.cpp 18.9 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
#include <string.h>
26

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

#include <sysutils/SocketClient.h>
31
#include <private/android_filesystem_config.h>
32 33 34

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

CommandListener::CommandListener() :
43
                 FrameworkListener("vold", true) {
San Mehat's avatar
San Mehat committed
44
    registerCmd(new DumpCmd());
San Mehat's avatar
San Mehat committed
45 46
    registerCmd(new VolumeCmd());
    registerCmd(new AsecCmd());
Kenny Root's avatar
Kenny Root committed
47
    registerCmd(new ObbCmd());
48
    registerCmd(new StorageCmd());
San Mehat's avatar
San Mehat committed
49
    registerCmd(new XwarpCmd());
50
    registerCmd(new CryptfsCmd());
51 52
}

San Mehat's avatar
San Mehat committed
53 54 55 56 57 58 59
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++) {
60
        unsigned int len = strlen(argv[i]) + 1; // Account for space
San Mehat's avatar
San Mehat committed
61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77
        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++ = ' ';
            }
        }
    }
San Mehat's avatar
San Mehat committed
78
    SLOGD("%s", buffer);
San Mehat's avatar
San Mehat committed
79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94
}

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);
    }
95 96 97 98 99 100 101 102 103 104
    cli->sendMsg(0, "Dumping mounted filesystems", false);
    FILE *fp = fopen("/proc/mounts", "r");
    if (fp) {
        char line[1024];
        while (fgets(line, sizeof(line), fp)) {
            line[strlen(line)-1] = '\0';
            cli->sendMsg(0, line, false);;
        }
        fclose(fp);
    }
San Mehat's avatar
San Mehat committed
105 106 107 108 109 110

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


San Mehat's avatar
San Mehat committed
111 112
CommandListener::VolumeCmd::VolumeCmd() :
                 VoldCommand("volume") {
113 114
}

San Mehat's avatar
San Mehat committed
115
int CommandListener::VolumeCmd::runCommand(SocketClient *cli,
116
                                                      int argc, char **argv) {
San Mehat's avatar
San Mehat committed
117 118
    dumpArgs(argc, argv, -1);

San Mehat's avatar
San Mehat committed
119 120 121 122
    if (argc < 2) {
        cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing Argument", false);
        return 0;
    }
123

San Mehat's avatar
San Mehat committed
124 125 126 127 128
    VolumeManager *vm = VolumeManager::Instance();
    int rc = 0;

    if (!strcmp(argv[1], "list")) {
        return vm->listVolumes(cli);
San Mehat's avatar
San Mehat committed
129
    } else if (!strcmp(argv[1], "debug")) {
130 131 132 133 134
        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
135
    } else if (!strcmp(argv[1], "mount")) {
136 137 138 139
        if (argc != 3) {
            cli->sendMsg(ResponseCode::CommandSyntaxError, "Usage: volume mount <path>", false);
            return 0;
        }
San Mehat's avatar
San Mehat committed
140 141
        rc = vm->mountVolume(argv[2]);
    } else if (!strcmp(argv[1], "unmount")) {
142 143 144 145
        if (argc < 3 || argc > 4 ||
           ((argc == 4 && strcmp(argv[3], "force")) &&
            (argc == 4 && strcmp(argv[3], "force_and_revert")))) {
            cli->sendMsg(ResponseCode::CommandSyntaxError, "Usage: volume unmount <path> [force|force_and_revert]", false);
146 147 148
            return 0;
        }

149
        bool force = false;
150
        bool revert = false;
151 152
        if (argc >= 4 && !strcmp(argv[3], "force")) {
            force = true;
153 154 155
        } else if (argc >= 4 && !strcmp(argv[3], "force_and_revert")) {
            force = true;
            revert = true;
156
        }
157
        rc = vm->unmountVolume(argv[2], force, revert);
San Mehat's avatar
San Mehat committed
158
    } else if (!strcmp(argv[1], "format")) {
159 160 161 162
        if (argc != 3) {
            cli->sendMsg(ResponseCode::CommandSyntaxError, "Usage: volume format <path>", false);
            return 0;
        }
San Mehat's avatar
San Mehat committed
163 164
        rc = vm->formatVolume(argv[2]);
    } else if (!strcmp(argv[1], "share")) {
165 166 167 168 169
        if (argc != 4) {
            cli->sendMsg(ResponseCode::CommandSyntaxError,
                    "Usage: volume share <path> <method>", false);
            return 0;
        }
San Mehat's avatar
San Mehat committed
170
        rc = vm->shareVolume(argv[2], argv[3]);
San Mehat's avatar
San Mehat committed
171
    } else if (!strcmp(argv[1], "unshare")) {
172 173 174 175 176
        if (argc != 4) {
            cli->sendMsg(ResponseCode::CommandSyntaxError,
                    "Usage: volume unshare <path> <method>", false);
            return 0;
        }
San Mehat's avatar
San Mehat committed
177
        rc = vm->unshareVolume(argv[2], argv[3]);
San Mehat's avatar
San Mehat committed
178 179
    } else if (!strcmp(argv[1], "shared")) {
        bool enabled = false;
180 181 182 183 184
        if (argc != 4) {
            cli->sendMsg(ResponseCode::CommandSyntaxError,
                    "Usage: volume shared <path> <method>", false);
            return 0;
        }
San Mehat's avatar
San Mehat committed
185

186
        if (vm->shareEnabled(argv[2], argv[3], &enabled)) {
San Mehat's avatar
San Mehat committed
187 188 189 190 191 192
            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
193
        return 0;
194
    } else {
San Mehat's avatar
San Mehat committed
195
        cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown volume cmd", false);
196 197
    }

San Mehat's avatar
San Mehat committed
198 199
    if (!rc) {
        cli->sendMsg(ResponseCode::CommandOkay, "volume operation succeeded", false);
200
    } else {
201 202
        int erno = errno;
        rc = ResponseCode::convertFromErrno();
San Mehat's avatar
San Mehat committed
203
        cli->sendMsg(rc, "volume operation failed", true);
204 205 206 207 208
    }

    return 0;
}

209 210 211 212 213 214
CommandListener::StorageCmd::StorageCmd() :
                 VoldCommand("storage") {
}

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

217 218 219 220 221 222 223 224 225 226 227 228 229 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
    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
260 261
CommandListener::AsecCmd::AsecCmd() :
                 VoldCommand("asec") {
262 263
}

San Mehat's avatar
San Mehat committed
264 265 266 267
int CommandListener::AsecCmd::runCommand(SocketClient *cli,
                                                      int argc, char **argv) {
    if (argc < 2) {
        cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing Argument", false);
268 269 270
        return 0;
    }

San Mehat's avatar
San Mehat committed
271 272
    VolumeManager *vm = VolumeManager::Instance();
    int rc = 0;
273

San Mehat's avatar
San Mehat committed
274
    if (!strcmp(argv[1], "list")) {
San Mehat's avatar
San Mehat committed
275
        dumpArgs(argc, argv, -1);
276
        DIR *d = opendir(Volume::SEC_ASECDIR);
277

San Mehat's avatar
San Mehat committed
278 279 280 281
        if (!d) {
            cli->sendMsg(ResponseCode::OperationFailed, "Failed to open asec dir", true);
            return 0;
        }
282

San Mehat's avatar
San Mehat committed
283 284 285 286 287 288 289 290 291 292 293 294 295
        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
296
        dumpArgs(argc, argv, 5);
San Mehat's avatar
San Mehat committed
297 298 299 300
        if (argc != 7) {
            cli->sendMsg(ResponseCode::CommandSyntaxError,
                    "Usage: asec create <container-id> <size_mb> <fstype> <key> <ownerUid>", false);
            return 0;
301 302
        }

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

358
        if (!(rc = vm->getAsecMountPath(argv[2], path, sizeof(path)))) {
San Mehat's avatar
San Mehat committed
359
            cli->sendMsg(ResponseCode::AsecPathResult, path, false);
360
            return 0;
San Mehat's avatar
San Mehat committed
361
        }
362 363 364 365 366 367 368 369 370 371 372 373
    } else if (!strcmp(argv[1], "fspath")) {
        dumpArgs(argc, argv, -1);
        if (argc != 3) {
            cli->sendMsg(ResponseCode::CommandSyntaxError, "Usage: asec fspath <container-id>", false);
            return 0;
        }
        char path[255];

        if (!(rc = vm->getAsecFilesystemPath(argv[2], path, sizeof(path)))) {
            cli->sendMsg(ResponseCode::AsecPathResult, path, false);
            return 0;
        }
374
    } else {
San Mehat's avatar
San Mehat committed
375
        dumpArgs(argc, argv, -1);
San Mehat's avatar
San Mehat committed
376
        cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown asec cmd", false);
377 378
    }

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

386 387
    return 0;
}
San Mehat's avatar
San Mehat committed
388

Kenny Root's avatar
Kenny Root committed
389 390
CommandListener::ObbCmd::ObbCmd() :
                 VoldCommand("obb") {
391 392
}

Kenny Root's avatar
Kenny Root committed
393
int CommandListener::ObbCmd::runCommand(SocketClient *cli,
394 395 396 397 398 399 400 401 402
                                                      int argc, char **argv) {
    if (argc < 2) {
        cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing Argument", false);
        return 0;
    }

    VolumeManager *vm = VolumeManager::Instance();
    int rc = 0;

Kenny Root's avatar
Kenny Root committed
403 404 405 406 407
    if (!strcmp(argv[1], "list")) {
        dumpArgs(argc, argv, -1);

        rc = vm->listMountedObbs(cli);
    } else if (!strcmp(argv[1], "mount")) {
408 409 410
            dumpArgs(argc, argv, 3);
            if (argc != 5) {
                cli->sendMsg(ResponseCode::CommandSyntaxError,
Kenny Root's avatar
Kenny Root committed
411
                        "Usage: obb mount <filename> <key> <ownerUid>", false);
412 413
                return 0;
            }
Kenny Root's avatar
Kenny Root committed
414
            rc = vm->mountObb(argv[2], argv[3], atoi(argv[4]));
415 416 417
    } else if (!strcmp(argv[1], "unmount")) {
        dumpArgs(argc, argv, -1);
        if (argc < 3) {
Kenny Root's avatar
Kenny Root committed
418
            cli->sendMsg(ResponseCode::CommandSyntaxError, "Usage: obb unmount <source file> [force]", false);
419 420 421 422 423 424
            return 0;
        }
        bool force = false;
        if (argc > 3 && !strcmp(argv[3], "force")) {
            force = true;
        }
Kenny Root's avatar
Kenny Root committed
425 426 427 428 429 430 431 432 433 434 435 436 437
        rc = vm->unmountObb(argv[2], force);
    } else if (!strcmp(argv[1], "path")) {
        dumpArgs(argc, argv, -1);
        if (argc != 3) {
            cli->sendMsg(ResponseCode::CommandSyntaxError, "Usage: obb path <source file>", false);
            return 0;
        }
        char path[255];

        if (!(rc = vm->getObbMountPath(argv[2], path, sizeof(path)))) {
            cli->sendMsg(ResponseCode::AsecPathResult, path, false);
            return 0;
        }
438 439
    } else {
        dumpArgs(argc, argv, -1);
Kenny Root's avatar
Kenny Root committed
440
        cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown obb cmd", false);
441 442 443
    }

    if (!rc) {
Kenny Root's avatar
Kenny Root committed
444
        cli->sendMsg(ResponseCode::CommandOkay, "obb operation succeeded", false);
445 446
    } else {
        rc = ResponseCode::convertFromErrno();
Kenny Root's avatar
Kenny Root committed
447
        cli->sendMsg(rc, "obb operation failed", true);
448 449 450 451 452
    }

    return 0;
}

San Mehat's avatar
San Mehat committed
453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494
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;
}
495 496 497 498 499 500 501

CommandListener::CryptfsCmd::CryptfsCmd() :
                 VoldCommand("cryptfs") {
}

int CommandListener::CryptfsCmd::runCommand(SocketClient *cli,
                                                      int argc, char **argv) {
502 503 504 505 506
    if ((cli->getUid() != 0) && (cli->getUid() != AID_SYSTEM)) {
        cli->sendMsg(ResponseCode::CommandNoPermission, "No permission to run cryptfs commands", false);
        return 0;
    }

507 508 509 510 511 512 513 514 515 516 517 518
    if (argc < 2) {
        cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing Argument", false);
        return 0;
    }

    int rc = 0;

    if (!strcmp(argv[1], "checkpw")) {
        if (argc != 3) {
            cli->sendMsg(ResponseCode::CommandSyntaxError, "Usage: cryptfs checkpw <passwd>", false);
            return 0;
        }
Ken Sumrall's avatar
Ken Sumrall committed
519
        dumpArgs(argc, argv, 2);
520
        rc = cryptfs_check_passwd(argv[2]);
521 522 523 524 525
    } else if (!strcmp(argv[1], "restart")) {
        if (argc != 2) {
            cli->sendMsg(ResponseCode::CommandSyntaxError, "Usage: cryptfs restart", false);
            return 0;
        }
Ken Sumrall's avatar
Ken Sumrall committed
526
        dumpArgs(argc, argv, -1);
527
        rc = cryptfs_restart();
528 529 530 531 532 533 534
    } else if (!strcmp(argv[1], "cryptocomplete")) {
        if (argc != 2) {
            cli->sendMsg(ResponseCode::CommandSyntaxError, "Usage: cryptfs cryptocomplete", false);
            return 0;
        }
        dumpArgs(argc, argv, -1);
        rc = cryptfs_crypto_complete();
535 536 537 538 539
    } else if (!strcmp(argv[1], "enablecrypto")) {
        if ( (argc != 4) || (strcmp(argv[2], "wipe") && strcmp(argv[2], "inplace")) ) {
            cli->sendMsg(ResponseCode::CommandSyntaxError, "Usage: cryptfs enablecrypto <wipe|inplace> <passwd>", false);
            return 0;
        }
Ken Sumrall's avatar
Ken Sumrall committed
540
        dumpArgs(argc, argv, 3);
541
        rc = cryptfs_enable(argv[2], argv[3]);
Ken Sumrall's avatar
Ken Sumrall committed
542
    } else if (!strcmp(argv[1], "changepw")) {
543 544
        if (argc != 3) {
            cli->sendMsg(ResponseCode::CommandSyntaxError, "Usage: cryptfs changepw <newpasswd>", false);
Ken Sumrall's avatar
Ken Sumrall committed
545 546
            return 0;
        } 
547 548
        SLOGD("cryptfs changepw {}");
        rc = cryptfs_changepw(argv[2]);
549 550 551 552 553 554 555
    } else if (!strcmp(argv[1], "verifypw")) {
        if (argc != 3) {
            cli->sendMsg(ResponseCode::CommandSyntaxError, "Usage: cryptfs verifypw <passwd>", false);
            return 0;
        }
        SLOGD("cryptfs verifypw {}");
        rc = cryptfs_verify_passwd(argv[2]);
556
    } else {
Ken Sumrall's avatar
Ken Sumrall committed
557
        dumpArgs(argc, argv, -1);
558 559 560
        cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown cryptfs cmd", false);
    }

561 562 563 564 565
    // Always report that the command succeeded and return the error code.
    // The caller will check the return value to see what the error was.
    char msg[255];
    snprintf(msg, sizeof(msg), "%d", rc);
    cli->sendMsg(ResponseCode::CommandOkay, msg, false);
566 567 568

    return 0;
}