CommandListener.cpp revision c8e04c5a8285de07d2c84bfbda8eda2c14a9457d
1f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat/*
2f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat * Copyright (C) 2008 The Android Open Source Project
3f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat *
4f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat * Licensed under the Apache License, Version 2.0 (the "License");
5f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat * you may not use this file except in compliance with the License.
6f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat * You may obtain a copy of the License at
7f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat *
8f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat *      http://www.apache.org/licenses/LICENSE-2.0
9f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat *
10f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat * Unless required by applicable law or agreed to in writing, software
11f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat * distributed under the License is distributed on an "AS IS" BASIS,
12f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat * See the License for the specific language governing permissions and
14f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat * limitations under the License.
15f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat */
16f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat
17f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat#include <stdlib.h>
18f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat#include <sys/socket.h>
19a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat#include <sys/types.h>
20f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat#include <netinet/in.h>
21f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat#include <arpa/inet.h>
22a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat#include <dirent.h>
23f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat#include <errno.h>
242350c44ff39b4cb2940893964a05f778fc80a436San Mehat#include <fcntl.h>
257929aa73d0c1fa75e8e0fcd4272361ad0ea9b0e6Mohamad Ayyash#include <fs_mgr.h>
26d1104f75a736210a95ba890473d78e8dfc8b8915Yabin Cui#include <stdio.h>
2737dcda68d334f70e1f7f69a9817def65fe3ee717Olivier Bailly#include <string.h>
28f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat
29d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat#define LOG_TAG "VoldCmdListener"
30f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat#include <cutils/log.h>
31f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat
32f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat#include <sysutils/SocketClient.h>
333ad9072a5d6f6bda32123b367545649364e3c11dKen Sumrall#include <private/android_filesystem_config.h>
34f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat
35f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat#include "CommandListener.h"
36f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat#include "VolumeManager.h"
3736801cccf27152c9eca5aab6ba3527221525110fJeff Sharkey#include "VolumeBase.h"
38a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat#include "ResponseCode.h"
39586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat#include "Process.h"
40d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat#include "Loop.h"
41d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat#include "Devmapper.h"
428f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall#include "cryptfs.h"
43b87937cdea689594a293979b30b13054e7455deeKen Sumrall#include "fstrim.h"
44f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat
453fd60b428202a0f5f324fccc67c0c0402b9131baDianne Hackborn#define DUMP_ARGS 0
463fd60b428202a0f5f324fccc67c0c0402b9131baDianne Hackborn
47f1b736bc5605e92e917ab27f5abf3ba839be2270San MehatCommandListener::CommandListener() :
48149aa3eb65a8cb878781206b1476aae110e0e1fdRobert Greenwalt                 FrameworkListener("vold", true) {
49d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat    registerCmd(new DumpCmd());
50eba65e9d438a05f1c5dfd0f8d31bc463a5d08eeeSan Mehat    registerCmd(new VolumeCmd());
51eba65e9d438a05f1c5dfd0f8d31bc463a5d08eeeSan Mehat    registerCmd(new AsecCmd());
52508c0e1605b795bbb51cb47d955b89f3df26ca94Kenny Root    registerCmd(new ObbCmd());
53586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat    registerCmd(new StorageCmd());
548f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall    registerCmd(new CryptfsCmd());
55b87937cdea689594a293979b30b13054e7455deeKen Sumrall    registerCmd(new FstrimCmd());
56f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat}
57f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat
583fd60b428202a0f5f324fccc67c0c0402b9131baDianne Hackborn#if DUMP_ARGS
593e971277db0d87652af5622c989233e7159ab909Mark Salyzynvoid CommandListener::dumpArgs(int argc, char **argv, int argObscure) {
60d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat    char buffer[4096];
61d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat    char *p = buffer;
62d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat
63d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat    memset(buffer, 0, sizeof(buffer));
64d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat    int i;
65d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat    for (i = 0; i < argc; i++) {
668f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall        unsigned int len = strlen(argv[i]) + 1; // Account for space
67d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat        if (i == argObscure) {
68d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat            len += 2; // Account for {}
69d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat        }
70d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat        if (((p - buffer) + len) < (sizeof(buffer)-1)) {
71d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat            if (i == argObscure) {
72d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat                *p++ = '{';
73d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat                *p++ = '}';
74d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat                *p++ = ' ';
75d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat                continue;
76d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat            }
77d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat            strcpy(p, argv[i]);
78d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat            p+= strlen(argv[i]);
79d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat            if (i != (argc -1)) {
80d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat                *p++ = ' ';
81d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat            }
82d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat        }
83d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat    }
8497ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat    SLOGD("%s", buffer);
85d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat}
863e971277db0d87652af5622c989233e7159ab909Mark Salyzyn#else
873e971277db0d87652af5622c989233e7159ab909Mark Salyzynvoid CommandListener::dumpArgs(int /*argc*/, char ** /*argv*/, int /*argObscure*/) { }
883e971277db0d87652af5622c989233e7159ab909Mark Salyzyn#endif
89d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat
9036801cccf27152c9eca5aab6ba3527221525110fJeff Sharkeyint CommandListener::sendGenericOkFail(SocketClient *cli, int cond) {
9136801cccf27152c9eca5aab6ba3527221525110fJeff Sharkey    if (!cond) {
9236801cccf27152c9eca5aab6ba3527221525110fJeff Sharkey        return cli->sendMsg(ResponseCode::CommandOkay, "Command succeeded", false);
9336801cccf27152c9eca5aab6ba3527221525110fJeff Sharkey    } else {
9436801cccf27152c9eca5aab6ba3527221525110fJeff Sharkey        return cli->sendMsg(ResponseCode::OperationFailed, "Command failed", false);
9536801cccf27152c9eca5aab6ba3527221525110fJeff Sharkey    }
9636801cccf27152c9eca5aab6ba3527221525110fJeff Sharkey}
9736801cccf27152c9eca5aab6ba3527221525110fJeff Sharkey
98d9a4e358614a0c5f60cc76c0636ee4bb02004a32San MehatCommandListener::DumpCmd::DumpCmd() :
99d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat                 VoldCommand("dump") {
100d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat}
101d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat
102d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehatint CommandListener::DumpCmd::runCommand(SocketClient *cli,
1033e971277db0d87652af5622c989233e7159ab909Mark Salyzyn                                         int /*argc*/, char ** /*argv*/) {
104d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat    cli->sendMsg(0, "Dumping loop status", false);
105d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat    if (Loop::dumpState(cli)) {
106d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat        cli->sendMsg(ResponseCode::CommandOkay, "Loop dump failed", true);
107d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat    }
108d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat    cli->sendMsg(0, "Dumping DM status", false);
109d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat    if (Devmapper::dumpState(cli)) {
110d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat        cli->sendMsg(ResponseCode::CommandOkay, "Devmapper dump failed", true);
111d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat    }
11296597e8b840ef671fe5279f8bd64fb09a8b38d4cSan Mehat    cli->sendMsg(0, "Dumping mounted filesystems", false);
11396597e8b840ef671fe5279f8bd64fb09a8b38d4cSan Mehat    FILE *fp = fopen("/proc/mounts", "r");
11496597e8b840ef671fe5279f8bd64fb09a8b38d4cSan Mehat    if (fp) {
11596597e8b840ef671fe5279f8bd64fb09a8b38d4cSan Mehat        char line[1024];
11696597e8b840ef671fe5279f8bd64fb09a8b38d4cSan Mehat        while (fgets(line, sizeof(line), fp)) {
11796597e8b840ef671fe5279f8bd64fb09a8b38d4cSan Mehat            line[strlen(line)-1] = '\0';
11896597e8b840ef671fe5279f8bd64fb09a8b38d4cSan Mehat            cli->sendMsg(0, line, false);;
11996597e8b840ef671fe5279f8bd64fb09a8b38d4cSan Mehat        }
12096597e8b840ef671fe5279f8bd64fb09a8b38d4cSan Mehat        fclose(fp);
12196597e8b840ef671fe5279f8bd64fb09a8b38d4cSan Mehat    }
122d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat
123d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat    cli->sendMsg(ResponseCode::CommandOkay, "dump complete", false);
124d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat    return 0;
125d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat}
126d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat
127eba65e9d438a05f1c5dfd0f8d31bc463a5d08eeeSan MehatCommandListener::VolumeCmd::VolumeCmd() :
128eba65e9d438a05f1c5dfd0f8d31bc463a5d08eeeSan Mehat                 VoldCommand("volume") {
129f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat}
130f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat
131eba65e9d438a05f1c5dfd0f8d31bc463a5d08eeeSan Mehatint CommandListener::VolumeCmd::runCommand(SocketClient *cli,
1327929aa73d0c1fa75e8e0fcd4272361ad0ea9b0e6Mohamad Ayyash                                           int argc, char **argv) {
133d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat    dumpArgs(argc, argv, -1);
134d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat
135eba65e9d438a05f1c5dfd0f8d31bc463a5d08eeeSan Mehat    if (argc < 2) {
136eba65e9d438a05f1c5dfd0f8d31bc463a5d08eeeSan Mehat        cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing Argument", false);
137eba65e9d438a05f1c5dfd0f8d31bc463a5d08eeeSan Mehat        return 0;
138eba65e9d438a05f1c5dfd0f8d31bc463a5d08eeeSan Mehat    }
139f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat
140eba65e9d438a05f1c5dfd0f8d31bc463a5d08eeeSan Mehat    VolumeManager *vm = VolumeManager::Instance();
141c8e04c5a8285de07d2c84bfbda8eda2c14a9457dJeff Sharkey    std::lock_guard<std::mutex> lock(vm->getLock());
142eba65e9d438a05f1c5dfd0f8d31bc463a5d08eeeSan Mehat
14336801cccf27152c9eca5aab6ba3527221525110fJeff Sharkey    // TODO: tease out methods not directly related to volumes
14457df7bf33968d65c23f3d0dc9f30a8ce2625b1d0San Mehat
14536801cccf27152c9eca5aab6ba3527221525110fJeff Sharkey    std::string cmd(argv[1]);
14636801cccf27152c9eca5aab6ba3527221525110fJeff Sharkey    if (cmd == "reset") {
14736801cccf27152c9eca5aab6ba3527221525110fJeff Sharkey        return sendGenericOkFail(cli, vm->reset());
14836801cccf27152c9eca5aab6ba3527221525110fJeff Sharkey
14936801cccf27152c9eca5aab6ba3527221525110fJeff Sharkey    } else if (cmd == "shutdown") {
15036801cccf27152c9eca5aab6ba3527221525110fJeff Sharkey        return sendGenericOkFail(cli, vm->shutdown());
15136801cccf27152c9eca5aab6ba3527221525110fJeff Sharkey
152f1b996df6f8283aac6953b22bd9e2496d8c30c86Jeff Sharkey    } else if (cmd == "debug") {
153f1b996df6f8283aac6953b22bd9e2496d8c30c86Jeff Sharkey        return sendGenericOkFail(cli, vm->setDebug(true));
154f1b996df6f8283aac6953b22bd9e2496d8c30c86Jeff Sharkey
15536801cccf27152c9eca5aab6ba3527221525110fJeff Sharkey    } else if (cmd == "partition" && argc > 3) {
15636801cccf27152c9eca5aab6ba3527221525110fJeff Sharkey        // partition [diskId] [public|private|mixed] [ratio]
15736801cccf27152c9eca5aab6ba3527221525110fJeff Sharkey        std::string id(argv[2]);
15836801cccf27152c9eca5aab6ba3527221525110fJeff Sharkey        auto disk = vm->findDisk(id);
15936801cccf27152c9eca5aab6ba3527221525110fJeff Sharkey        if (disk == nullptr) {
16036801cccf27152c9eca5aab6ba3527221525110fJeff Sharkey            return cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown disk", false);
1619caab76c6b5aefdeeb1715a3695491ca793b8c18Ken Sumrall        }
16236801cccf27152c9eca5aab6ba3527221525110fJeff Sharkey
16336801cccf27152c9eca5aab6ba3527221525110fJeff Sharkey        std::string type(argv[3]);
16436801cccf27152c9eca5aab6ba3527221525110fJeff Sharkey        if (type == "public") {
16536801cccf27152c9eca5aab6ba3527221525110fJeff Sharkey            return sendGenericOkFail(cli, disk->partitionPublic());
16636801cccf27152c9eca5aab6ba3527221525110fJeff Sharkey        } else if (type == "private") {
16736801cccf27152c9eca5aab6ba3527221525110fJeff Sharkey            return sendGenericOkFail(cli, disk->partitionPrivate());
16836801cccf27152c9eca5aab6ba3527221525110fJeff Sharkey        } else if (type == "mixed") {
16936801cccf27152c9eca5aab6ba3527221525110fJeff Sharkey            if (argc < 4) {
17036801cccf27152c9eca5aab6ba3527221525110fJeff Sharkey                return cli->sendMsg(ResponseCode::CommandSyntaxError, nullptr, false);
17136801cccf27152c9eca5aab6ba3527221525110fJeff Sharkey            }
17236801cccf27152c9eca5aab6ba3527221525110fJeff Sharkey            int frac = atoi(argv[4]);
17336801cccf27152c9eca5aab6ba3527221525110fJeff Sharkey            return sendGenericOkFail(cli, disk->partitionMixed(frac));
17436801cccf27152c9eca5aab6ba3527221525110fJeff Sharkey        } else {
17536801cccf27152c9eca5aab6ba3527221525110fJeff Sharkey            return cli->sendMsg(ResponseCode::CommandSyntaxError, nullptr, false);
17657df7bf33968d65c23f3d0dc9f30a8ce2625b1d0San Mehat        }
17736801cccf27152c9eca5aab6ba3527221525110fJeff Sharkey
17836801cccf27152c9eca5aab6ba3527221525110fJeff Sharkey    } else if (cmd == "mkdirs" && argc > 2) {
17936801cccf27152c9eca5aab6ba3527221525110fJeff Sharkey        // mkdirs [path]
18036801cccf27152c9eca5aab6ba3527221525110fJeff Sharkey        return sendGenericOkFail(cli, vm->mkdirs(argv[2]));
18136801cccf27152c9eca5aab6ba3527221525110fJeff Sharkey
18236801cccf27152c9eca5aab6ba3527221525110fJeff Sharkey    } else if (cmd == "start_user" && argc > 2) {
18336801cccf27152c9eca5aab6ba3527221525110fJeff Sharkey        // start_user [user]
18436801cccf27152c9eca5aab6ba3527221525110fJeff Sharkey        return sendGenericOkFail(cli, vm->startUser(atoi(argv[2])));
18536801cccf27152c9eca5aab6ba3527221525110fJeff Sharkey
18636801cccf27152c9eca5aab6ba3527221525110fJeff Sharkey    } else if (cmd == "cleanup_user" && argc > 2) {
18736801cccf27152c9eca5aab6ba3527221525110fJeff Sharkey        // cleanup_user [user]
18836801cccf27152c9eca5aab6ba3527221525110fJeff Sharkey        return sendGenericOkFail(cli, vm->cleanupUser(atoi(argv[2])));
18936801cccf27152c9eca5aab6ba3527221525110fJeff Sharkey
19036801cccf27152c9eca5aab6ba3527221525110fJeff Sharkey    } else if (cmd == "mount" && argc > 2) {
19136801cccf27152c9eca5aab6ba3527221525110fJeff Sharkey        // mount [volId] [flags] [user]
19236801cccf27152c9eca5aab6ba3527221525110fJeff Sharkey        std::string id(argv[2]);
19336801cccf27152c9eca5aab6ba3527221525110fJeff Sharkey        auto vol = vm->findVolume(id);
19436801cccf27152c9eca5aab6ba3527221525110fJeff Sharkey        if (vol == nullptr) {
19536801cccf27152c9eca5aab6ba3527221525110fJeff Sharkey            return cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown volume", false);
19657df7bf33968d65c23f3d0dc9f30a8ce2625b1d0San Mehat        }
19736801cccf27152c9eca5aab6ba3527221525110fJeff Sharkey
198f1b996df6f8283aac6953b22bd9e2496d8c30c86Jeff Sharkey        int mountFlags = (argc > 3) ? atoi(argv[3]) : 0;
199f1b996df6f8283aac6953b22bd9e2496d8c30c86Jeff Sharkey        userid_t mountUserId = (argc > 4) ? atoi(argv[4]) : -1;
20036801cccf27152c9eca5aab6ba3527221525110fJeff Sharkey
201f1b996df6f8283aac6953b22bd9e2496d8c30c86Jeff Sharkey        if (mountFlags & android::vold::VolumeBase::MountFlags::kPrimary) {
20236801cccf27152c9eca5aab6ba3527221525110fJeff Sharkey            vm->setPrimary(vol);
20357df7bf33968d65c23f3d0dc9f30a8ce2625b1d0San Mehat        }
204eba65e9d438a05f1c5dfd0f8d31bc463a5d08eeeSan Mehat
205f1b996df6f8283aac6953b22bd9e2496d8c30c86Jeff Sharkey        vol->setMountFlags(mountFlags);
206f1b996df6f8283aac6953b22bd9e2496d8c30c86Jeff Sharkey        vol->setMountUserId(mountUserId);
20736801cccf27152c9eca5aab6ba3527221525110fJeff Sharkey
20836801cccf27152c9eca5aab6ba3527221525110fJeff Sharkey        return sendGenericOkFail(cli, vol->mount());
20936801cccf27152c9eca5aab6ba3527221525110fJeff Sharkey
21036801cccf27152c9eca5aab6ba3527221525110fJeff Sharkey    } else if (cmd == "unmount" && argc > 2) {
21136801cccf27152c9eca5aab6ba3527221525110fJeff Sharkey        // unmount [volId]
21236801cccf27152c9eca5aab6ba3527221525110fJeff Sharkey        std::string id(argv[2]);
21336801cccf27152c9eca5aab6ba3527221525110fJeff Sharkey        auto vol = vm->findVolume(id);
21436801cccf27152c9eca5aab6ba3527221525110fJeff Sharkey        if (vol == nullptr) {
21536801cccf27152c9eca5aab6ba3527221525110fJeff Sharkey            return cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown volume", false);
216eba65e9d438a05f1c5dfd0f8d31bc463a5d08eeeSan Mehat        }
21736801cccf27152c9eca5aab6ba3527221525110fJeff Sharkey
21836801cccf27152c9eca5aab6ba3527221525110fJeff Sharkey        return sendGenericOkFail(cli, vol->unmount());
21936801cccf27152c9eca5aab6ba3527221525110fJeff Sharkey
22036801cccf27152c9eca5aab6ba3527221525110fJeff Sharkey    } else if (cmd == "format" && argc > 2) {
22136801cccf27152c9eca5aab6ba3527221525110fJeff Sharkey        // format [volId]
22236801cccf27152c9eca5aab6ba3527221525110fJeff Sharkey        std::string id(argv[2]);
22336801cccf27152c9eca5aab6ba3527221525110fJeff Sharkey        auto vol = vm->findVolume(id);
22436801cccf27152c9eca5aab6ba3527221525110fJeff Sharkey        if (vol == nullptr) {
22536801cccf27152c9eca5aab6ba3527221525110fJeff Sharkey            return cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown volume", false);
22671ebe154a5fbbb4b394a439ff0b6b9c84fbd04f5Jeff Sharkey        }
22749e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat
22836801cccf27152c9eca5aab6ba3527221525110fJeff Sharkey        return sendGenericOkFail(cli, vol->format());
229a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    }
230a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
23136801cccf27152c9eca5aab6ba3527221525110fJeff Sharkey    return cli->sendMsg(ResponseCode::CommandSyntaxError, nullptr, false);
232a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat}
233a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
234586536c60b773e3517531ad8a6cb0de6722c67fcSan MehatCommandListener::StorageCmd::StorageCmd() :
235586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat                 VoldCommand("storage") {
236586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat}
237586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat
238586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehatint CommandListener::StorageCmd::runCommand(SocketClient *cli,
239586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat                                                      int argc, char **argv) {
2407929aa73d0c1fa75e8e0fcd4272361ad0ea9b0e6Mohamad Ayyash    /* Guarantied to be initialized by vold's main() before the CommandListener is active */
2417929aa73d0c1fa75e8e0fcd4272361ad0ea9b0e6Mohamad Ayyash    extern struct fstab *fstab;
2427929aa73d0c1fa75e8e0fcd4272361ad0ea9b0e6Mohamad Ayyash
243d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat    dumpArgs(argc, argv, -1);
244d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat
245586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat    if (argc < 2) {
246586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat        cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing Argument", false);
247586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat        return 0;
248586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat    }
249586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat
2507929aa73d0c1fa75e8e0fcd4272361ad0ea9b0e6Mohamad Ayyash    if (!strcmp(argv[1], "mountall")) {
2517929aa73d0c1fa75e8e0fcd4272361ad0ea9b0e6Mohamad Ayyash        if (argc != 2) {
2527929aa73d0c1fa75e8e0fcd4272361ad0ea9b0e6Mohamad Ayyash            cli->sendMsg(ResponseCode::CommandSyntaxError, "Usage: mountall", false);
2537929aa73d0c1fa75e8e0fcd4272361ad0ea9b0e6Mohamad Ayyash            return 0;
2547929aa73d0c1fa75e8e0fcd4272361ad0ea9b0e6Mohamad Ayyash        }
2557929aa73d0c1fa75e8e0fcd4272361ad0ea9b0e6Mohamad Ayyash        fs_mgr_mount_all(fstab);
2567929aa73d0c1fa75e8e0fcd4272361ad0ea9b0e6Mohamad Ayyash        cli->sendMsg(ResponseCode::CommandOkay, "Mountall ran successfully", false);
2577929aa73d0c1fa75e8e0fcd4272361ad0ea9b0e6Mohamad Ayyash        return 0;
2587929aa73d0c1fa75e8e0fcd4272361ad0ea9b0e6Mohamad Ayyash    }
259586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat    if (!strcmp(argv[1], "users")) {
260586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat        DIR *dir;
261586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat        struct dirent *de;
262586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat
263edf7adf21e1c210e5954b1128efb61b62f6da274JP Abgrall        if (argc < 3) {
264edf7adf21e1c210e5954b1128efb61b62f6da274JP Abgrall            cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing Argument: user <mountpoint>", false);
265edf7adf21e1c210e5954b1128efb61b62f6da274JP Abgrall            return 0;
266edf7adf21e1c210e5954b1128efb61b62f6da274JP Abgrall        }
267586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat        if (!(dir = opendir("/proc"))) {
268586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat            cli->sendMsg(ResponseCode::OperationFailed, "Failed to open /proc", true);
269586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat            return 0;
270586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat        }
271586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat
272586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat        while ((de = readdir(dir))) {
273586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat            int pid = Process::getPid(de->d_name);
274586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat
275586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat            if (pid < 0) {
276586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat                continue;
277586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat            }
278586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat
279586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat            char processName[255];
280586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat            Process::getProcessName(pid, processName, sizeof(processName));
281586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat
282586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat            if (Process::checkFileDescriptorSymLinks(pid, argv[2]) ||
283586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat                Process::checkFileMaps(pid, argv[2]) ||
284586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat                Process::checkSymLink(pid, argv[2], "cwd") ||
285586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat                Process::checkSymLink(pid, argv[2], "root") ||
286586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat                Process::checkSymLink(pid, argv[2], "exe")) {
287586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat
288586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat                char msg[1024];
289586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat                snprintf(msg, sizeof(msg), "%d %s", pid, processName);
290586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat                cli->sendMsg(ResponseCode::StorageUsersListResult, msg, false);
291586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat            }
292586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat        }
293586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat        closedir(dir);
294586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat        cli->sendMsg(ResponseCode::CommandOkay, "Storage user list complete", false);
295586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat    } else {
296586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat        cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown storage cmd", false);
297586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat    }
298586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat    return 0;
299586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat}
300586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat
301eba65e9d438a05f1c5dfd0f8d31bc463a5d08eeeSan MehatCommandListener::AsecCmd::AsecCmd() :
302eba65e9d438a05f1c5dfd0f8d31bc463a5d08eeeSan Mehat                 VoldCommand("asec") {
303048b0801fcd6fcfbb8fa812284c751181e4821b8San Mehat}
304048b0801fcd6fcfbb8fa812284c751181e4821b8San Mehat
305344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Rootvoid CommandListener::AsecCmd::listAsecsInDirectory(SocketClient *cli, const char *directory) {
306344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root    DIR *d = opendir(directory);
307344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root
308344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root    if (!d) {
309344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root        cli->sendMsg(ResponseCode::OperationFailed, "Failed to open asec dir", true);
310344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root        return;
311344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root    }
312344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root
313344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root    size_t dirent_len = offsetof(struct dirent, d_name) +
3148c480f73eed963eeca9b7df3e4c4543c6e43b0d7Elliott Hughes            fpathconf(dirfd(d), _PC_NAME_MAX) + 1;
315344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root
316344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root    struct dirent *dent = (struct dirent *) malloc(dirent_len);
317344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root    if (dent == NULL) {
318344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root        cli->sendMsg(ResponseCode::OperationFailed, "Failed to allocate memory", true);
319344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root        return;
320344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root    }
321344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root
322344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root    struct dirent *result;
323344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root
324344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root    while (!readdir_r(d, dent, &result) && result != NULL) {
325344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root        if (dent->d_name[0] == '.')
326344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root            continue;
327344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root        if (dent->d_type != DT_REG)
328344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root            continue;
329344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root        size_t name_len = strlen(dent->d_name);
330344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root        if (name_len > 5 && name_len < 260 &&
331344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root                !strcmp(&dent->d_name[name_len - 5], ".asec")) {
332344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root            char id[255];
333344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root            memset(id, 0, sizeof(id));
3347b0bc8571465666d6cba79bda60b72a97f852c05Kenny Root            strlcpy(id, dent->d_name, name_len - 4);
335344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root            cli->sendMsg(ResponseCode::AsecListResult, id, false);
336344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root        }
337344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root    }
338344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root    closedir(d);
339344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root
340344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root    free(dent);
341344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root}
342344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root
343eba65e9d438a05f1c5dfd0f8d31bc463a5d08eeeSan Mehatint CommandListener::AsecCmd::runCommand(SocketClient *cli,
344eba65e9d438a05f1c5dfd0f8d31bc463a5d08eeeSan Mehat                                                      int argc, char **argv) {
345eba65e9d438a05f1c5dfd0f8d31bc463a5d08eeeSan Mehat    if (argc < 2) {
346eba65e9d438a05f1c5dfd0f8d31bc463a5d08eeeSan Mehat        cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing Argument", false);
347048b0801fcd6fcfbb8fa812284c751181e4821b8San Mehat        return 0;
348048b0801fcd6fcfbb8fa812284c751181e4821b8San Mehat    }
349048b0801fcd6fcfbb8fa812284c751181e4821b8San Mehat
350eba65e9d438a05f1c5dfd0f8d31bc463a5d08eeeSan Mehat    VolumeManager *vm = VolumeManager::Instance();
351eba65e9d438a05f1c5dfd0f8d31bc463a5d08eeeSan Mehat    int rc = 0;
352a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
353eba65e9d438a05f1c5dfd0f8d31bc463a5d08eeeSan Mehat    if (!strcmp(argv[1], "list")) {
354d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat        dumpArgs(argc, argv, -1);
355a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
3569f18fe7807a4e4089778243dbbd08d154ec15540Jeff Sharkey        listAsecsInDirectory(cli, VolumeManager::SEC_ASECDIR_EXT);
3579f18fe7807a4e4089778243dbbd08d154ec15540Jeff Sharkey        listAsecsInDirectory(cli, VolumeManager::SEC_ASECDIR_INT);
358eba65e9d438a05f1c5dfd0f8d31bc463a5d08eeeSan Mehat    } else if (!strcmp(argv[1], "create")) {
359d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat        dumpArgs(argc, argv, 5);
360344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root        if (argc != 8) {
361eba65e9d438a05f1c5dfd0f8d31bc463a5d08eeeSan Mehat            cli->sendMsg(ResponseCode::CommandSyntaxError,
362344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root                    "Usage: asec create <container-id> <size_mb> <fstype> <key> <ownerUid> "
363344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root                    "<isExternal>", false);
364eba65e9d438a05f1c5dfd0f8d31bc463a5d08eeeSan Mehat            return 0;
365a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat        }
366a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
367eba65e9d438a05f1c5dfd0f8d31bc463a5d08eeeSan Mehat        unsigned int numSectors = (atoi(argv[3]) * (1024 * 1024)) / 512;
368344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root        const bool isExternal = (atoi(argv[7]) == 1);
369344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root        rc = vm->createAsec(argv[2], numSectors, argv[4], argv[5], atoi(argv[6]), isExternal);
370fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg    } else if (!strcmp(argv[1], "resize")) {
371fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg        dumpArgs(argc, argv, -1);
372fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg        if (argc != 5) {
373fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg            cli->sendMsg(ResponseCode::CommandSyntaxError, "Usage: asec resize <container-id> <size_mb> <key>", false);
374fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg            return 0;
375fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg        }
376fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg        unsigned int numSectors = (atoi(argv[3]) * (1024 * 1024)) / 512;
377fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg        rc = vm->resizeAsec(argv[2], numSectors, argv[4]);
378eba65e9d438a05f1c5dfd0f8d31bc463a5d08eeeSan Mehat    } else if (!strcmp(argv[1], "finalize")) {
379d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat        dumpArgs(argc, argv, -1);
380eba65e9d438a05f1c5dfd0f8d31bc463a5d08eeeSan Mehat        if (argc != 3) {
381eba65e9d438a05f1c5dfd0f8d31bc463a5d08eeeSan Mehat            cli->sendMsg(ResponseCode::CommandSyntaxError, "Usage: asec finalize <container-id>", false);
382eba65e9d438a05f1c5dfd0f8d31bc463a5d08eeeSan Mehat            return 0;
383eba65e9d438a05f1c5dfd0f8d31bc463a5d08eeeSan Mehat        }
3848f2875b29780312f4edda3d831cc8a99e1648dd5San Mehat        rc = vm->finalizeAsec(argv[2]);
385344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root    } else if (!strcmp(argv[1], "fixperms")) {
386344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root        dumpArgs(argc, argv, -1);
387344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root        if  (argc != 5) {
388344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root            cli->sendMsg(ResponseCode::CommandSyntaxError, "Usage: asec fixperms <container-id> <gid> <filename>", false);
389344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root            return 0;
390344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root        }
391344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root
392344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root        char *endptr;
393344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root        gid_t gid = (gid_t) strtoul(argv[3], &endptr, 10);
394344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root        if (*endptr != '\0') {
395344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root            cli->sendMsg(ResponseCode::CommandSyntaxError, "Usage: asec fixperms <container-id> <gid> <filename>", false);
396344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root            return 0;
397344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root        }
398344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root
399344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root        rc = vm->fixupAsecPermissions(argv[2], gid, argv[4]);
400eba65e9d438a05f1c5dfd0f8d31bc463a5d08eeeSan Mehat    } else if (!strcmp(argv[1], "destroy")) {
401d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat        dumpArgs(argc, argv, -1);
4024ba8948dc16463053e21cda5744f519a555080d0San Mehat        if (argc < 3) {
4034ba8948dc16463053e21cda5744f519a555080d0San Mehat            cli->sendMsg(ResponseCode::CommandSyntaxError, "Usage: asec destroy <container-id> [force]", false);
404eba65e9d438a05f1c5dfd0f8d31bc463a5d08eeeSan Mehat            return 0;
405eba65e9d438a05f1c5dfd0f8d31bc463a5d08eeeSan Mehat        }
4064ba8948dc16463053e21cda5744f519a555080d0San Mehat        bool force = false;
4074ba8948dc16463053e21cda5744f519a555080d0San Mehat        if (argc > 3 && !strcmp(argv[3], "force")) {
4084ba8948dc16463053e21cda5744f519a555080d0San Mehat            force = true;
4094ba8948dc16463053e21cda5744f519a555080d0San Mehat        }
4108f2875b29780312f4edda3d831cc8a99e1648dd5San Mehat        rc = vm->destroyAsec(argv[2], force);
411eba65e9d438a05f1c5dfd0f8d31bc463a5d08eeeSan Mehat    } else if (!strcmp(argv[1], "mount")) {
412d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat        dumpArgs(argc, argv, 3);
41343ed123d3fc1a3edf3660cd0e2528e971abc399eJeff Sharkey        if (argc != 6) {
414eba65e9d438a05f1c5dfd0f8d31bc463a5d08eeeSan Mehat            cli->sendMsg(ResponseCode::CommandSyntaxError,
41543ed123d3fc1a3edf3660cd0e2528e971abc399eJeff Sharkey                    "Usage: asec mount <namespace-id> <key> <ownerUid> <ro|rw>", false);
416eba65e9d438a05f1c5dfd0f8d31bc463a5d08eeeSan Mehat            return 0;
417eba65e9d438a05f1c5dfd0f8d31bc463a5d08eeeSan Mehat        }
41843ed123d3fc1a3edf3660cd0e2528e971abc399eJeff Sharkey        bool readOnly = true;
41943ed123d3fc1a3edf3660cd0e2528e971abc399eJeff Sharkey        if (!strcmp(argv[5], "rw")) {
42043ed123d3fc1a3edf3660cd0e2528e971abc399eJeff Sharkey            readOnly = false;
42143ed123d3fc1a3edf3660cd0e2528e971abc399eJeff Sharkey        }
42243ed123d3fc1a3edf3660cd0e2528e971abc399eJeff Sharkey        rc = vm->mountAsec(argv[2], argv[3], atoi(argv[4]), readOnly);
423eba65e9d438a05f1c5dfd0f8d31bc463a5d08eeeSan Mehat    } else if (!strcmp(argv[1], "unmount")) {
424d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat        dumpArgs(argc, argv, -1);
4254ba8948dc16463053e21cda5744f519a555080d0San Mehat        if (argc < 3) {
4264ba8948dc16463053e21cda5744f519a555080d0San Mehat            cli->sendMsg(ResponseCode::CommandSyntaxError, "Usage: asec unmount <container-id> [force]", false);
427eba65e9d438a05f1c5dfd0f8d31bc463a5d08eeeSan Mehat            return 0;
428eba65e9d438a05f1c5dfd0f8d31bc463a5d08eeeSan Mehat        }
4294ba8948dc16463053e21cda5744f519a555080d0San Mehat        bool force = false;
4304ba8948dc16463053e21cda5744f519a555080d0San Mehat        if (argc > 3 && !strcmp(argv[3], "force")) {
4314ba8948dc16463053e21cda5744f519a555080d0San Mehat            force = true;
4324ba8948dc16463053e21cda5744f519a555080d0San Mehat        }
4338f2875b29780312f4edda3d831cc8a99e1648dd5San Mehat        rc = vm->unmountAsec(argv[2], force);
434eba65e9d438a05f1c5dfd0f8d31bc463a5d08eeeSan Mehat    } else if (!strcmp(argv[1], "rename")) {
435d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat        dumpArgs(argc, argv, -1);
436eba65e9d438a05f1c5dfd0f8d31bc463a5d08eeeSan Mehat        if (argc != 4) {
437eba65e9d438a05f1c5dfd0f8d31bc463a5d08eeeSan Mehat            cli->sendMsg(ResponseCode::CommandSyntaxError,
438eba65e9d438a05f1c5dfd0f8d31bc463a5d08eeeSan Mehat                    "Usage: asec rename <old_id> <new_id>", false);
439eba65e9d438a05f1c5dfd0f8d31bc463a5d08eeeSan Mehat            return 0;
440eba65e9d438a05f1c5dfd0f8d31bc463a5d08eeeSan Mehat        }
4418f2875b29780312f4edda3d831cc8a99e1648dd5San Mehat        rc = vm->renameAsec(argv[2], argv[3]);
442eba65e9d438a05f1c5dfd0f8d31bc463a5d08eeeSan Mehat    } else if (!strcmp(argv[1], "path")) {
443d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat        dumpArgs(argc, argv, -1);
444eba65e9d438a05f1c5dfd0f8d31bc463a5d08eeeSan Mehat        if (argc != 3) {
445eba65e9d438a05f1c5dfd0f8d31bc463a5d08eeeSan Mehat            cli->sendMsg(ResponseCode::CommandSyntaxError, "Usage: asec path <container-id>", false);
446eba65e9d438a05f1c5dfd0f8d31bc463a5d08eeeSan Mehat            return 0;
447eba65e9d438a05f1c5dfd0f8d31bc463a5d08eeeSan Mehat        }
448eba65e9d438a05f1c5dfd0f8d31bc463a5d08eeeSan Mehat        char path[255];
449a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
45088ac2c06539485942bf414efda2d39647fa1a415San Mehat        if (!(rc = vm->getAsecMountPath(argv[2], path, sizeof(path)))) {
451eba65e9d438a05f1c5dfd0f8d31bc463a5d08eeeSan Mehat            cli->sendMsg(ResponseCode::AsecPathResult, path, false);
45288ac2c06539485942bf414efda2d39647fa1a415San Mehat            return 0;
453eba65e9d438a05f1c5dfd0f8d31bc463a5d08eeeSan Mehat        }
454736910ca99a40b9add4353bf619e778c40938948Dianne Hackborn    } else if (!strcmp(argv[1], "fspath")) {
455736910ca99a40b9add4353bf619e778c40938948Dianne Hackborn        dumpArgs(argc, argv, -1);
456736910ca99a40b9add4353bf619e778c40938948Dianne Hackborn        if (argc != 3) {
457736910ca99a40b9add4353bf619e778c40938948Dianne Hackborn            cli->sendMsg(ResponseCode::CommandSyntaxError, "Usage: asec fspath <container-id>", false);
458736910ca99a40b9add4353bf619e778c40938948Dianne Hackborn            return 0;
459736910ca99a40b9add4353bf619e778c40938948Dianne Hackborn        }
460736910ca99a40b9add4353bf619e778c40938948Dianne Hackborn        char path[255];
461736910ca99a40b9add4353bf619e778c40938948Dianne Hackborn
462736910ca99a40b9add4353bf619e778c40938948Dianne Hackborn        if (!(rc = vm->getAsecFilesystemPath(argv[2], path, sizeof(path)))) {
463736910ca99a40b9add4353bf619e778c40938948Dianne Hackborn            cli->sendMsg(ResponseCode::AsecPathResult, path, false);
464736910ca99a40b9add4353bf619e778c40938948Dianne Hackborn            return 0;
465736910ca99a40b9add4353bf619e778c40938948Dianne Hackborn        }
466a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    } else {
467d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat        dumpArgs(argc, argv, -1);
468eba65e9d438a05f1c5dfd0f8d31bc463a5d08eeeSan Mehat        cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown asec cmd", false);
469a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    }
470a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
4718f2875b29780312f4edda3d831cc8a99e1648dd5San Mehat    if (!rc) {
4728f2875b29780312f4edda3d831cc8a99e1648dd5San Mehat        cli->sendMsg(ResponseCode::CommandOkay, "asec operation succeeded", false);
4738f2875b29780312f4edda3d831cc8a99e1648dd5San Mehat    } else {
4748f2875b29780312f4edda3d831cc8a99e1648dd5San Mehat        rc = ResponseCode::convertFromErrno();
4758f2875b29780312f4edda3d831cc8a99e1648dd5San Mehat        cli->sendMsg(rc, "asec operation failed", true);
4768f2875b29780312f4edda3d831cc8a99e1648dd5San Mehat    }
4778f2875b29780312f4edda3d831cc8a99e1648dd5San Mehat
478a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    return 0;
479a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat}
4802350c44ff39b4cb2940893964a05f778fc80a436San Mehat
481508c0e1605b795bbb51cb47d955b89f3df26ca94Kenny RootCommandListener::ObbCmd::ObbCmd() :
482508c0e1605b795bbb51cb47d955b89f3df26ca94Kenny Root                 VoldCommand("obb") {
483fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root}
484fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root
485508c0e1605b795bbb51cb47d955b89f3df26ca94Kenny Rootint CommandListener::ObbCmd::runCommand(SocketClient *cli,
486fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root                                                      int argc, char **argv) {
487fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root    if (argc < 2) {
488fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root        cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing Argument", false);
489fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root        return 0;
490fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root    }
491fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root
492fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root    VolumeManager *vm = VolumeManager::Instance();
493fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root    int rc = 0;
494fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root
495508c0e1605b795bbb51cb47d955b89f3df26ca94Kenny Root    if (!strcmp(argv[1], "list")) {
496508c0e1605b795bbb51cb47d955b89f3df26ca94Kenny Root        dumpArgs(argc, argv, -1);
497508c0e1605b795bbb51cb47d955b89f3df26ca94Kenny Root
498508c0e1605b795bbb51cb47d955b89f3df26ca94Kenny Root        rc = vm->listMountedObbs(cli);
499508c0e1605b795bbb51cb47d955b89f3df26ca94Kenny Root    } else if (!strcmp(argv[1], "mount")) {
500fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root            dumpArgs(argc, argv, 3);
501fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root            if (argc != 5) {
502fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root                cli->sendMsg(ResponseCode::CommandSyntaxError,
5036947904a76b69a1db20a3ddd30c0bcd281922fdeJeff Sharkey                        "Usage: obb mount <filename> <key> <ownerGid>", false);
504fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root                return 0;
505fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root            }
506508c0e1605b795bbb51cb47d955b89f3df26ca94Kenny Root            rc = vm->mountObb(argv[2], argv[3], atoi(argv[4]));
507fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root    } else if (!strcmp(argv[1], "unmount")) {
508fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root        dumpArgs(argc, argv, -1);
509fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root        if (argc < 3) {
510508c0e1605b795bbb51cb47d955b89f3df26ca94Kenny Root            cli->sendMsg(ResponseCode::CommandSyntaxError, "Usage: obb unmount <source file> [force]", false);
511fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root            return 0;
512fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root        }
513fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root        bool force = false;
514fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root        if (argc > 3 && !strcmp(argv[3], "force")) {
515fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root            force = true;
516fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root        }
517508c0e1605b795bbb51cb47d955b89f3df26ca94Kenny Root        rc = vm->unmountObb(argv[2], force);
518508c0e1605b795bbb51cb47d955b89f3df26ca94Kenny Root    } else if (!strcmp(argv[1], "path")) {
519508c0e1605b795bbb51cb47d955b89f3df26ca94Kenny Root        dumpArgs(argc, argv, -1);
520508c0e1605b795bbb51cb47d955b89f3df26ca94Kenny Root        if (argc != 3) {
521508c0e1605b795bbb51cb47d955b89f3df26ca94Kenny Root            cli->sendMsg(ResponseCode::CommandSyntaxError, "Usage: obb path <source file>", false);
522508c0e1605b795bbb51cb47d955b89f3df26ca94Kenny Root            return 0;
523508c0e1605b795bbb51cb47d955b89f3df26ca94Kenny Root        }
524508c0e1605b795bbb51cb47d955b89f3df26ca94Kenny Root        char path[255];
525508c0e1605b795bbb51cb47d955b89f3df26ca94Kenny Root
526508c0e1605b795bbb51cb47d955b89f3df26ca94Kenny Root        if (!(rc = vm->getObbMountPath(argv[2], path, sizeof(path)))) {
527508c0e1605b795bbb51cb47d955b89f3df26ca94Kenny Root            cli->sendMsg(ResponseCode::AsecPathResult, path, false);
528508c0e1605b795bbb51cb47d955b89f3df26ca94Kenny Root            return 0;
529508c0e1605b795bbb51cb47d955b89f3df26ca94Kenny Root        }
530fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root    } else {
531fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root        dumpArgs(argc, argv, -1);
532508c0e1605b795bbb51cb47d955b89f3df26ca94Kenny Root        cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown obb cmd", false);
533fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root    }
534fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root
535fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root    if (!rc) {
536508c0e1605b795bbb51cb47d955b89f3df26ca94Kenny Root        cli->sendMsg(ResponseCode::CommandOkay, "obb operation succeeded", false);
537fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root    } else {
538fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root        rc = ResponseCode::convertFromErrno();
539508c0e1605b795bbb51cb47d955b89f3df26ca94Kenny Root        cli->sendMsg(rc, "obb operation failed", true);
540fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root    }
541fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root
542fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root    return 0;
543fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root}
544fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root
5458f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken SumrallCommandListener::CryptfsCmd::CryptfsCmd() :
5468f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall                 VoldCommand("cryptfs") {
5478f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall}
5488f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall
54945f10533f8cb2e2ec8dc9803739870cbfafffebdPaul Lawrencestatic int getType(const char* type)
55045f10533f8cb2e2ec8dc9803739870cbfafffebdPaul Lawrence{
55145f10533f8cb2e2ec8dc9803739870cbfafffebdPaul Lawrence    if (!strcmp(type, "default")) {
55245f10533f8cb2e2ec8dc9803739870cbfafffebdPaul Lawrence        return CRYPT_TYPE_DEFAULT;
55345f10533f8cb2e2ec8dc9803739870cbfafffebdPaul Lawrence    } else if (!strcmp(type, "password")) {
55445f10533f8cb2e2ec8dc9803739870cbfafffebdPaul Lawrence        return CRYPT_TYPE_PASSWORD;
55545f10533f8cb2e2ec8dc9803739870cbfafffebdPaul Lawrence    } else if (!strcmp(type, "pin")) {
55645f10533f8cb2e2ec8dc9803739870cbfafffebdPaul Lawrence        return CRYPT_TYPE_PIN;
55745f10533f8cb2e2ec8dc9803739870cbfafffebdPaul Lawrence    } else if (!strcmp(type, "pattern")) {
55845f10533f8cb2e2ec8dc9803739870cbfafffebdPaul Lawrence        return CRYPT_TYPE_PATTERN;
55945f10533f8cb2e2ec8dc9803739870cbfafffebdPaul Lawrence    } else {
56045f10533f8cb2e2ec8dc9803739870cbfafffebdPaul Lawrence        return -1;
56145f10533f8cb2e2ec8dc9803739870cbfafffebdPaul Lawrence    }
56245f10533f8cb2e2ec8dc9803739870cbfafffebdPaul Lawrence}
56345f10533f8cb2e2ec8dc9803739870cbfafffebdPaul Lawrence
5648f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrallint CommandListener::CryptfsCmd::runCommand(SocketClient *cli,
5658f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall                                                      int argc, char **argv) {
5663ad9072a5d6f6bda32123b367545649364e3c11dKen Sumrall    if ((cli->getUid() != 0) && (cli->getUid() != AID_SYSTEM)) {
5673ad9072a5d6f6bda32123b367545649364e3c11dKen Sumrall        cli->sendMsg(ResponseCode::CommandNoPermission, "No permission to run cryptfs commands", false);
5683ad9072a5d6f6bda32123b367545649364e3c11dKen Sumrall        return 0;
5693ad9072a5d6f6bda32123b367545649364e3c11dKen Sumrall    }
5703ad9072a5d6f6bda32123b367545649364e3c11dKen Sumrall
5718f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall    if (argc < 2) {
5728f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall        cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing Argument", false);
5738f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall        return 0;
5748f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall    }
5758f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall
5768f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall    int rc = 0;
5778f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall
5788f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall    if (!strcmp(argv[1], "checkpw")) {
5798f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall        if (argc != 3) {
5808f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall            cli->sendMsg(ResponseCode::CommandSyntaxError, "Usage: cryptfs checkpw <passwd>", false);
5818f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall            return 0;
5828f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall        }
5838ddbe40a8a8708dac7c472fa8c098c8f7b24534cKen Sumrall        dumpArgs(argc, argv, 2);
5848f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall        rc = cryptfs_check_passwd(argv[2]);
5856864b7ec94a57b73c300457955d86dc604aeddf5Ken Sumrall    } else if (!strcmp(argv[1], "restart")) {
5866864b7ec94a57b73c300457955d86dc604aeddf5Ken Sumrall        if (argc != 2) {
5876864b7ec94a57b73c300457955d86dc604aeddf5Ken Sumrall            cli->sendMsg(ResponseCode::CommandSyntaxError, "Usage: cryptfs restart", false);
5886864b7ec94a57b73c300457955d86dc604aeddf5Ken Sumrall            return 0;
5896864b7ec94a57b73c300457955d86dc604aeddf5Ken Sumrall        }
5908ddbe40a8a8708dac7c472fa8c098c8f7b24534cKen Sumrall        dumpArgs(argc, argv, -1);
5916864b7ec94a57b73c300457955d86dc604aeddf5Ken Sumrall        rc = cryptfs_restart();
5927f7dbaa2784c10fd2989fb303e5edfb8136d53dcKen Sumrall    } else if (!strcmp(argv[1], "cryptocomplete")) {
5937f7dbaa2784c10fd2989fb303e5edfb8136d53dcKen Sumrall        if (argc != 2) {
5947f7dbaa2784c10fd2989fb303e5edfb8136d53dcKen Sumrall            cli->sendMsg(ResponseCode::CommandSyntaxError, "Usage: cryptfs cryptocomplete", false);
5957f7dbaa2784c10fd2989fb303e5edfb8136d53dcKen Sumrall            return 0;
5967f7dbaa2784c10fd2989fb303e5edfb8136d53dcKen Sumrall        }
5977f7dbaa2784c10fd2989fb303e5edfb8136d53dcKen Sumrall        dumpArgs(argc, argv, -1);
5987f7dbaa2784c10fd2989fb303e5edfb8136d53dcKen Sumrall        rc = cryptfs_crypto_complete();
5998f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall    } else if (!strcmp(argv[1], "enablecrypto")) {
60045f10533f8cb2e2ec8dc9803739870cbfafffebdPaul Lawrence        const char* syntax = "Usage: cryptfs enablecrypto <wipe|inplace> "
60145f10533f8cb2e2ec8dc9803739870cbfafffebdPaul Lawrence                             "default|password|pin|pattern [passwd]";
60245f10533f8cb2e2ec8dc9803739870cbfafffebdPaul Lawrence        if ( (argc != 4 && argc != 5)
60313486033575e6e4affccbb3dd201515d79f6f44bPaul Lawrence             || (strcmp(argv[2], "wipe") && strcmp(argv[2], "inplace")) ) {
60445f10533f8cb2e2ec8dc9803739870cbfafffebdPaul Lawrence            cli->sendMsg(ResponseCode::CommandSyntaxError, syntax, false);
6058f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall            return 0;
6068f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall        }
60745f10533f8cb2e2ec8dc9803739870cbfafffebdPaul Lawrence        dumpArgs(argc, argv, 4);
608502dc74153397e56d5410f8a8250b5581643b9efJP Abgrall
60913486033575e6e4affccbb3dd201515d79f6f44bPaul Lawrence        int tries;
61013486033575e6e4affccbb3dd201515d79f6f44bPaul Lawrence        for (tries = 0; tries < 2; ++tries) {
61145f10533f8cb2e2ec8dc9803739870cbfafffebdPaul Lawrence            int type = getType(argv[3]);
61245f10533f8cb2e2ec8dc9803739870cbfafffebdPaul Lawrence            if (type == -1) {
61345f10533f8cb2e2ec8dc9803739870cbfafffebdPaul Lawrence                cli->sendMsg(ResponseCode::CommandSyntaxError, syntax,
61445f10533f8cb2e2ec8dc9803739870cbfafffebdPaul Lawrence                             false);
61545f10533f8cb2e2ec8dc9803739870cbfafffebdPaul Lawrence                return 0;
61645f10533f8cb2e2ec8dc9803739870cbfafffebdPaul Lawrence            } else if (type == CRYPT_TYPE_DEFAULT) {
61745f10533f8cb2e2ec8dc9803739870cbfafffebdPaul Lawrence              rc = cryptfs_enable_default(argv[2], /*allow_reboot*/false);
61845f10533f8cb2e2ec8dc9803739870cbfafffebdPaul Lawrence            } else {
61945f10533f8cb2e2ec8dc9803739870cbfafffebdPaul Lawrence                rc = cryptfs_enable(argv[2], type, argv[4],
62045f10533f8cb2e2ec8dc9803739870cbfafffebdPaul Lawrence                                    /*allow_reboot*/false);
62145f10533f8cb2e2ec8dc9803739870cbfafffebdPaul Lawrence            }
62213486033575e6e4affccbb3dd201515d79f6f44bPaul Lawrence
62313486033575e6e4affccbb3dd201515d79f6f44bPaul Lawrence            if (rc == 0) {
62413486033575e6e4affccbb3dd201515d79f6f44bPaul Lawrence                break;
62513486033575e6e4affccbb3dd201515d79f6f44bPaul Lawrence            } else if (tries == 0) {
62636801cccf27152c9eca5aab6ba3527221525110fJeff Sharkey                Process::killProcessesWithOpenFiles(DATA_MNT_POINT, SIGKILL);
62713486033575e6e4affccbb3dd201515d79f6f44bPaul Lawrence            }
62813486033575e6e4affccbb3dd201515d79f6f44bPaul Lawrence        }
6298ddbe40a8a8708dac7c472fa8c098c8f7b24534cKen Sumrall    } else if (!strcmp(argv[1], "changepw")) {
630f4faa575c9fc20a8a8e133d6098865b5ce3a7ed2Paul Lawrence        const char* syntax = "Usage: cryptfs changepw "
631f4faa575c9fc20a8a8e133d6098865b5ce3a7ed2Paul Lawrence                             "default|password|pin|pattern [newpasswd]";
63213486033575e6e4affccbb3dd201515d79f6f44bPaul Lawrence        const char* password;
633f4faa575c9fc20a8a8e133d6098865b5ce3a7ed2Paul Lawrence        if (argc == 3) {
634f4faa575c9fc20a8a8e133d6098865b5ce3a7ed2Paul Lawrence            password = "";
635f4faa575c9fc20a8a8e133d6098865b5ce3a7ed2Paul Lawrence        } else if (argc == 4) {
636f4faa575c9fc20a8a8e133d6098865b5ce3a7ed2Paul Lawrence            password = argv[3];
637f4faa575c9fc20a8a8e133d6098865b5ce3a7ed2Paul Lawrence        } else {
638f4faa575c9fc20a8a8e133d6098865b5ce3a7ed2Paul Lawrence            cli->sendMsg(ResponseCode::CommandSyntaxError, syntax, false);
639f4faa575c9fc20a8a8e133d6098865b5ce3a7ed2Paul Lawrence            return 0;
640f4faa575c9fc20a8a8e133d6098865b5ce3a7ed2Paul Lawrence        }
64145f10533f8cb2e2ec8dc9803739870cbfafffebdPaul Lawrence        int type = getType(argv[2]);
64245f10533f8cb2e2ec8dc9803739870cbfafffebdPaul Lawrence        if (type == -1) {
643f4faa575c9fc20a8a8e133d6098865b5ce3a7ed2Paul Lawrence            cli->sendMsg(ResponseCode::CommandSyntaxError, syntax, false);
6448ddbe40a8a8708dac7c472fa8c098c8f7b24534cKen Sumrall            return 0;
645f4faa575c9fc20a8a8e133d6098865b5ce3a7ed2Paul Lawrence        }
646f4faa575c9fc20a8a8e133d6098865b5ce3a7ed2Paul Lawrence        SLOGD("cryptfs changepw %s {}", argv[2]);
647f4faa575c9fc20a8a8e133d6098865b5ce3a7ed2Paul Lawrence        rc = cryptfs_changepw(type, password);
6483ad9072a5d6f6bda32123b367545649364e3c11dKen Sumrall    } else if (!strcmp(argv[1], "verifypw")) {
6493ad9072a5d6f6bda32123b367545649364e3c11dKen Sumrall        if (argc != 3) {
6503ad9072a5d6f6bda32123b367545649364e3c11dKen Sumrall            cli->sendMsg(ResponseCode::CommandSyntaxError, "Usage: cryptfs verifypw <passwd>", false);
6513ad9072a5d6f6bda32123b367545649364e3c11dKen Sumrall            return 0;
6523ad9072a5d6f6bda32123b367545649364e3c11dKen Sumrall        }
6533ad9072a5d6f6bda32123b367545649364e3c11dKen Sumrall        SLOGD("cryptfs verifypw {}");
6543ad9072a5d6f6bda32123b367545649364e3c11dKen Sumrall        rc = cryptfs_verify_passwd(argv[2]);
655160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall    } else if (!strcmp(argv[1], "getfield")) {
65685c01f95c7a3c009e79867fe36181cc0793a0440Rubin Xu        char *valbuf;
65785c01f95c7a3c009e79867fe36181cc0793a0440Rubin Xu        int valbuf_len = PROPERTY_VALUE_MAX;
658160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall
659160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall        if (argc != 3) {
660160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall            cli->sendMsg(ResponseCode::CommandSyntaxError, "Usage: cryptfs getfield <fieldname>", false);
661160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall            return 0;
662160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall        }
663160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall        dumpArgs(argc, argv, -1);
66485c01f95c7a3c009e79867fe36181cc0793a0440Rubin Xu
66585c01f95c7a3c009e79867fe36181cc0793a0440Rubin Xu        // Increase the buffer size until it is big enough for the field value stored.
66685c01f95c7a3c009e79867fe36181cc0793a0440Rubin Xu        while (1) {
66785c01f95c7a3c009e79867fe36181cc0793a0440Rubin Xu            valbuf = (char*)malloc(valbuf_len);
66885c01f95c7a3c009e79867fe36181cc0793a0440Rubin Xu            if (valbuf == NULL) {
66985c01f95c7a3c009e79867fe36181cc0793a0440Rubin Xu                cli->sendMsg(ResponseCode::OperationFailed, "Failed to allocate memory", false);
67085c01f95c7a3c009e79867fe36181cc0793a0440Rubin Xu                return 0;
67185c01f95c7a3c009e79867fe36181cc0793a0440Rubin Xu            }
67285c01f95c7a3c009e79867fe36181cc0793a0440Rubin Xu            rc = cryptfs_getfield(argv[2], valbuf, valbuf_len);
67385c01f95c7a3c009e79867fe36181cc0793a0440Rubin Xu            if (rc != CRYPTO_GETFIELD_ERROR_BUF_TOO_SMALL) {
67485c01f95c7a3c009e79867fe36181cc0793a0440Rubin Xu                break;
67585c01f95c7a3c009e79867fe36181cc0793a0440Rubin Xu            }
67685c01f95c7a3c009e79867fe36181cc0793a0440Rubin Xu            free(valbuf);
67785c01f95c7a3c009e79867fe36181cc0793a0440Rubin Xu            valbuf_len *= 2;
67885c01f95c7a3c009e79867fe36181cc0793a0440Rubin Xu        }
67985c01f95c7a3c009e79867fe36181cc0793a0440Rubin Xu        if (rc == CRYPTO_GETFIELD_OK) {
680160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall            cli->sendMsg(ResponseCode::CryptfsGetfieldResult, valbuf, false);
681160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall        }
68285c01f95c7a3c009e79867fe36181cc0793a0440Rubin Xu        free(valbuf);
683160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall    } else if (!strcmp(argv[1], "setfield")) {
684160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall        if (argc != 4) {
685160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall            cli->sendMsg(ResponseCode::CommandSyntaxError, "Usage: cryptfs setfield <fieldname> <value>", false);
686160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall            return 0;
687160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall        }
688160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall        dumpArgs(argc, argv, -1);
689160b4d68ece15947057e31edde4e5608a010c695Ken Sumrall        rc = cryptfs_setfield(argv[2], argv[3]);
690f4faa575c9fc20a8a8e133d6098865b5ce3a7ed2Paul Lawrence    } else if (!strcmp(argv[1], "mountdefaultencrypted")) {
691f4faa575c9fc20a8a8e133d6098865b5ce3a7ed2Paul Lawrence        SLOGD("cryptfs mountdefaultencrypted");
692f4faa575c9fc20a8a8e133d6098865b5ce3a7ed2Paul Lawrence        dumpArgs(argc, argv, -1);
693f4faa575c9fc20a8a8e133d6098865b5ce3a7ed2Paul Lawrence        rc = cryptfs_mount_default_encrypted();
694f4faa575c9fc20a8a8e133d6098865b5ce3a7ed2Paul Lawrence    } else if (!strcmp(argv[1], "getpwtype")) {
695f4faa575c9fc20a8a8e133d6098865b5ce3a7ed2Paul Lawrence        SLOGD("cryptfs getpwtype");
696f4faa575c9fc20a8a8e133d6098865b5ce3a7ed2Paul Lawrence        dumpArgs(argc, argv, -1);
697f4faa575c9fc20a8a8e133d6098865b5ce3a7ed2Paul Lawrence        switch(cryptfs_get_password_type()) {
698f4faa575c9fc20a8a8e133d6098865b5ce3a7ed2Paul Lawrence        case CRYPT_TYPE_PASSWORD:
699f4faa575c9fc20a8a8e133d6098865b5ce3a7ed2Paul Lawrence            cli->sendMsg(ResponseCode::PasswordTypeResult, "password", false);
700f4faa575c9fc20a8a8e133d6098865b5ce3a7ed2Paul Lawrence            return 0;
701f4faa575c9fc20a8a8e133d6098865b5ce3a7ed2Paul Lawrence        case CRYPT_TYPE_PATTERN:
702f4faa575c9fc20a8a8e133d6098865b5ce3a7ed2Paul Lawrence            cli->sendMsg(ResponseCode::PasswordTypeResult, "pattern", false);
703f4faa575c9fc20a8a8e133d6098865b5ce3a7ed2Paul Lawrence            return 0;
704f4faa575c9fc20a8a8e133d6098865b5ce3a7ed2Paul Lawrence        case CRYPT_TYPE_PIN:
705f4faa575c9fc20a8a8e133d6098865b5ce3a7ed2Paul Lawrence            cli->sendMsg(ResponseCode::PasswordTypeResult, "pin", false);
706f4faa575c9fc20a8a8e133d6098865b5ce3a7ed2Paul Lawrence            return 0;
707f4faa575c9fc20a8a8e133d6098865b5ce3a7ed2Paul Lawrence        case CRYPT_TYPE_DEFAULT:
708f4faa575c9fc20a8a8e133d6098865b5ce3a7ed2Paul Lawrence            cli->sendMsg(ResponseCode::PasswordTypeResult, "default", false);
709f4faa575c9fc20a8a8e133d6098865b5ce3a7ed2Paul Lawrence            return 0;
710f4faa575c9fc20a8a8e133d6098865b5ce3a7ed2Paul Lawrence        default:
711f4faa575c9fc20a8a8e133d6098865b5ce3a7ed2Paul Lawrence          /** @TODO better error and make sure handled by callers */
712f4faa575c9fc20a8a8e133d6098865b5ce3a7ed2Paul Lawrence            cli->sendMsg(ResponseCode::OpFailedStorageNotFound, "Error", false);
713f4faa575c9fc20a8a8e133d6098865b5ce3a7ed2Paul Lawrence            return 0;
714f4faa575c9fc20a8a8e133d6098865b5ce3a7ed2Paul Lawrence        }
715399317ede45340eebc035ba204b6201b6d62dd66Paul Lawrence    } else if (!strcmp(argv[1], "getpw")) {
716399317ede45340eebc035ba204b6201b6d62dd66Paul Lawrence        SLOGD("cryptfs getpw");
717684dbdf316a02cf6a7694018f7c3a4bcd65142ccPaul Lawrence        dumpArgs(argc, argv, -1);
71805335c344d73411439774dfa548c633020e158e1Paul Lawrence        const char* password = cryptfs_get_password();
719399317ede45340eebc035ba204b6201b6d62dd66Paul Lawrence        if (password) {
720b25302e1b0232ac2f9d6ffa441f2ab1ff23a2de3Paul Lawrence            char* message = 0;
721b25302e1b0232ac2f9d6ffa441f2ab1ff23a2de3Paul Lawrence            int size = asprintf(&message, "{{sensitive}} %s", password);
722b25302e1b0232ac2f9d6ffa441f2ab1ff23a2de3Paul Lawrence            if (size != -1) {
723b25302e1b0232ac2f9d6ffa441f2ab1ff23a2de3Paul Lawrence                cli->sendMsg(ResponseCode::CommandOkay, message, false);
724b25302e1b0232ac2f9d6ffa441f2ab1ff23a2de3Paul Lawrence                memset(message, 0, size);
725b25302e1b0232ac2f9d6ffa441f2ab1ff23a2de3Paul Lawrence                free (message);
726b25302e1b0232ac2f9d6ffa441f2ab1ff23a2de3Paul Lawrence                return 0;
727b25302e1b0232ac2f9d6ffa441f2ab1ff23a2de3Paul Lawrence            }
728399317ede45340eebc035ba204b6201b6d62dd66Paul Lawrence        }
729399317ede45340eebc035ba204b6201b6d62dd66Paul Lawrence        rc = -1;
730399317ede45340eebc035ba204b6201b6d62dd66Paul Lawrence    } else if (!strcmp(argv[1], "clearpw")) {
731399317ede45340eebc035ba204b6201b6d62dd66Paul Lawrence        SLOGD("cryptfs clearpw");
732399317ede45340eebc035ba204b6201b6d62dd66Paul Lawrence        dumpArgs(argc, argv, -1);
733399317ede45340eebc035ba204b6201b6d62dd66Paul Lawrence        cryptfs_clear_password();
734399317ede45340eebc035ba204b6201b6d62dd66Paul Lawrence        rc = 0;
7358f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall    } else {
7368ddbe40a8a8708dac7c472fa8c098c8f7b24534cKen Sumrall        dumpArgs(argc, argv, -1);
7378f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall        cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown cryptfs cmd", false);
738f4faa575c9fc20a8a8e133d6098865b5ce3a7ed2Paul Lawrence        return 0;
7398f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall    }
7408f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall
7410167cb15935592deea9abbd6a8bbe904e27bd101Jason parks    // Always report that the command succeeded and return the error code.
7420167cb15935592deea9abbd6a8bbe904e27bd101Jason parks    // The caller will check the return value to see what the error was.
7430167cb15935592deea9abbd6a8bbe904e27bd101Jason parks    char msg[255];
7440167cb15935592deea9abbd6a8bbe904e27bd101Jason parks    snprintf(msg, sizeof(msg), "%d", rc);
7450167cb15935592deea9abbd6a8bbe904e27bd101Jason parks    cli->sendMsg(ResponseCode::CommandOkay, msg, false);
7468f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall
7478f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall    return 0;
7488f869aa1bc685b505c58e97b4e11a9c7491a16f9Ken Sumrall}
749b87937cdea689594a293979b30b13054e7455deeKen Sumrall
750b87937cdea689594a293979b30b13054e7455deeKen SumrallCommandListener::FstrimCmd::FstrimCmd() :
751b87937cdea689594a293979b30b13054e7455deeKen Sumrall                 VoldCommand("fstrim") {
752b87937cdea689594a293979b30b13054e7455deeKen Sumrall}
753b87937cdea689594a293979b30b13054e7455deeKen Sumrallint CommandListener::FstrimCmd::runCommand(SocketClient *cli,
754b87937cdea689594a293979b30b13054e7455deeKen Sumrall                                                      int argc, char **argv) {
755b87937cdea689594a293979b30b13054e7455deeKen Sumrall    if ((cli->getUid() != 0) && (cli->getUid() != AID_SYSTEM)) {
756b87937cdea689594a293979b30b13054e7455deeKen Sumrall        cli->sendMsg(ResponseCode::CommandNoPermission, "No permission to run fstrim commands", false);
757b87937cdea689594a293979b30b13054e7455deeKen Sumrall        return 0;
758b87937cdea689594a293979b30b13054e7455deeKen Sumrall    }
759b87937cdea689594a293979b30b13054e7455deeKen Sumrall
760b87937cdea689594a293979b30b13054e7455deeKen Sumrall    if (argc < 2) {
761b87937cdea689594a293979b30b13054e7455deeKen Sumrall        cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing Argument", false);
762b87937cdea689594a293979b30b13054e7455deeKen Sumrall        return 0;
763b87937cdea689594a293979b30b13054e7455deeKen Sumrall    }
764b87937cdea689594a293979b30b13054e7455deeKen Sumrall
765b87937cdea689594a293979b30b13054e7455deeKen Sumrall    int rc = 0;
766b87937cdea689594a293979b30b13054e7455deeKen Sumrall
767b87937cdea689594a293979b30b13054e7455deeKen Sumrall    if (!strcmp(argv[1], "dotrim")) {
768b87937cdea689594a293979b30b13054e7455deeKen Sumrall        if (argc != 2) {
769b87937cdea689594a293979b30b13054e7455deeKen Sumrall            cli->sendMsg(ResponseCode::CommandSyntaxError, "Usage: fstrim dotrim", false);
770b87937cdea689594a293979b30b13054e7455deeKen Sumrall            return 0;
771b87937cdea689594a293979b30b13054e7455deeKen Sumrall        }
772b87937cdea689594a293979b30b13054e7455deeKen Sumrall        dumpArgs(argc, argv, -1);
773422bdb7e49b39475328f05d765b00f0ef96820b8JP Abgrall        rc = fstrim_filesystems(0);
774422bdb7e49b39475328f05d765b00f0ef96820b8JP Abgrall    } else if (!strcmp(argv[1], "dodtrim")) {
775422bdb7e49b39475328f05d765b00f0ef96820b8JP Abgrall        if (argc != 2) {
776422bdb7e49b39475328f05d765b00f0ef96820b8JP Abgrall            cli->sendMsg(ResponseCode::CommandSyntaxError, "Usage: fstrim dodtrim", false);
777422bdb7e49b39475328f05d765b00f0ef96820b8JP Abgrall            return 0;
778422bdb7e49b39475328f05d765b00f0ef96820b8JP Abgrall        }
779422bdb7e49b39475328f05d765b00f0ef96820b8JP Abgrall        dumpArgs(argc, argv, -1);
780422bdb7e49b39475328f05d765b00f0ef96820b8JP Abgrall        rc = fstrim_filesystems(1);   /* Do Deep Discard trim */
781b87937cdea689594a293979b30b13054e7455deeKen Sumrall    } else {
782b87937cdea689594a293979b30b13054e7455deeKen Sumrall        dumpArgs(argc, argv, -1);
783b87937cdea689594a293979b30b13054e7455deeKen Sumrall        cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown fstrim cmd", false);
784b87937cdea689594a293979b30b13054e7455deeKen Sumrall    }
785b87937cdea689594a293979b30b13054e7455deeKen Sumrall
786b87937cdea689594a293979b30b13054e7455deeKen Sumrall    // Always report that the command succeeded and return the error code.
787b87937cdea689594a293979b30b13054e7455deeKen Sumrall    // The caller will check the return value to see what the error was.
788b87937cdea689594a293979b30b13054e7455deeKen Sumrall    char msg[255];
789b87937cdea689594a293979b30b13054e7455deeKen Sumrall    snprintf(msg, sizeof(msg), "%d", rc);
790b87937cdea689594a293979b30b13054e7455deeKen Sumrall    cli->sendMsg(ResponseCode::CommandOkay, msg, false);
791b87937cdea689594a293979b30b13054e7455deeKen Sumrall
792b87937cdea689594a293979b30b13054e7455deeKen Sumrall    return 0;
793b87937cdea689594a293979b30b13054e7455deeKen Sumrall}
794