blob: 3e984a1157c7532d521b0c9ebfa000ac1792d467 [file] [log] [blame]
San Mehatf1b736b2009-10-10 17:22:08 -07001/*
2 * Copyright (C) 2008 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include <stdlib.h>
18#include <sys/socket.h>
San Mehata19b2502010-01-06 10:33:53 -080019#include <sys/types.h>
San Mehatf1b736b2009-10-10 17:22:08 -070020#include <netinet/in.h>
21#include <arpa/inet.h>
San Mehata19b2502010-01-06 10:33:53 -080022#include <dirent.h>
San Mehatf1b736b2009-10-10 17:22:08 -070023#include <errno.h>
San Mehat2350c442010-03-02 13:16:50 -080024#include <fcntl.h>
Mohamad Ayyash7929aa72014-03-10 15:55:33 -070025#include <fs_mgr.h>
Olivier Bailly37dcda62010-11-16 10:41:53 -080026#include <string.h>
San Mehatf1b736b2009-10-10 17:22:08 -070027
San Mehatd9a4e352010-03-12 13:32:47 -080028#define LOG_TAG "VoldCmdListener"
San Mehatf1b736b2009-10-10 17:22:08 -070029#include <cutils/log.h>
30
31#include <sysutils/SocketClient.h>
Ken Sumrall3ad90722011-10-04 20:38:29 -070032#include <private/android_filesystem_config.h>
San Mehatf1b736b2009-10-10 17:22:08 -070033
34#include "CommandListener.h"
35#include "VolumeManager.h"
San Mehata2677e42009-12-13 10:40:18 -080036#include "ResponseCode.h"
San Mehat586536c2010-02-16 17:12:00 -080037#include "Process.h"
San Mehatd9a4e352010-03-12 13:32:47 -080038#include "Loop.h"
39#include "Devmapper.h"
Ken Sumrall8f869aa2010-12-03 03:47:09 -080040#include "cryptfs.h"
Ken Sumrallb87937c2013-03-19 21:46:39 -070041#include "fstrim.h"
San Mehatf1b736b2009-10-10 17:22:08 -070042
Dianne Hackborn3fd60b42012-11-27 16:00:04 -080043#define DUMP_ARGS 0
44
San Mehatf1b736b2009-10-10 17:22:08 -070045CommandListener::CommandListener() :
Robert Greenwalt149aa3e2012-02-16 14:43:03 -080046 FrameworkListener("vold", true) {
San Mehatd9a4e352010-03-12 13:32:47 -080047 registerCmd(new DumpCmd());
San Mehateba65e92010-01-29 05:15:16 -080048 registerCmd(new VolumeCmd());
49 registerCmd(new AsecCmd());
Kenny Root508c0e12010-07-12 09:59:49 -070050 registerCmd(new ObbCmd());
San Mehat586536c2010-02-16 17:12:00 -080051 registerCmd(new StorageCmd());
Ken Sumrall8f869aa2010-12-03 03:47:09 -080052 registerCmd(new CryptfsCmd());
Ken Sumrallb87937c2013-03-19 21:46:39 -070053 registerCmd(new FstrimCmd());
San Mehatf1b736b2009-10-10 17:22:08 -070054}
55
Dianne Hackborn3fd60b42012-11-27 16:00:04 -080056#if DUMP_ARGS
Mark Salyzyn3e971272014-01-21 13:27:04 -080057void CommandListener::dumpArgs(int argc, char **argv, int argObscure) {
San Mehatd9a4e352010-03-12 13:32:47 -080058 char buffer[4096];
59 char *p = buffer;
60
61 memset(buffer, 0, sizeof(buffer));
62 int i;
63 for (i = 0; i < argc; i++) {
Ken Sumrall8f869aa2010-12-03 03:47:09 -080064 unsigned int len = strlen(argv[i]) + 1; // Account for space
San Mehatd9a4e352010-03-12 13:32:47 -080065 if (i == argObscure) {
66 len += 2; // Account for {}
67 }
68 if (((p - buffer) + len) < (sizeof(buffer)-1)) {
69 if (i == argObscure) {
70 *p++ = '{';
71 *p++ = '}';
72 *p++ = ' ';
73 continue;
74 }
75 strcpy(p, argv[i]);
76 p+= strlen(argv[i]);
77 if (i != (argc -1)) {
78 *p++ = ' ';
79 }
80 }
81 }
San Mehat97ac40e2010-03-24 10:24:19 -070082 SLOGD("%s", buffer);
San Mehatd9a4e352010-03-12 13:32:47 -080083}
Mark Salyzyn3e971272014-01-21 13:27:04 -080084#else
85void CommandListener::dumpArgs(int /*argc*/, char ** /*argv*/, int /*argObscure*/) { }
86#endif
San Mehatd9a4e352010-03-12 13:32:47 -080087
88CommandListener::DumpCmd::DumpCmd() :
89 VoldCommand("dump") {
90}
91
92int CommandListener::DumpCmd::runCommand(SocketClient *cli,
Mark Salyzyn3e971272014-01-21 13:27:04 -080093 int /*argc*/, char ** /*argv*/) {
San Mehatd9a4e352010-03-12 13:32:47 -080094 cli->sendMsg(0, "Dumping loop status", false);
95 if (Loop::dumpState(cli)) {
96 cli->sendMsg(ResponseCode::CommandOkay, "Loop dump failed", true);
97 }
98 cli->sendMsg(0, "Dumping DM status", false);
99 if (Devmapper::dumpState(cli)) {
100 cli->sendMsg(ResponseCode::CommandOkay, "Devmapper dump failed", true);
101 }
San Mehat96597e82010-03-17 09:50:54 -0700102 cli->sendMsg(0, "Dumping mounted filesystems", false);
103 FILE *fp = fopen("/proc/mounts", "r");
104 if (fp) {
105 char line[1024];
106 while (fgets(line, sizeof(line), fp)) {
107 line[strlen(line)-1] = '\0';
108 cli->sendMsg(0, line, false);;
109 }
110 fclose(fp);
111 }
San Mehatd9a4e352010-03-12 13:32:47 -0800112
113 cli->sendMsg(ResponseCode::CommandOkay, "dump complete", false);
114 return 0;
115}
116
San Mehateba65e92010-01-29 05:15:16 -0800117CommandListener::VolumeCmd::VolumeCmd() :
118 VoldCommand("volume") {
San Mehatf1b736b2009-10-10 17:22:08 -0700119}
120
San Mehateba65e92010-01-29 05:15:16 -0800121int CommandListener::VolumeCmd::runCommand(SocketClient *cli,
Mohamad Ayyash7929aa72014-03-10 15:55:33 -0700122 int argc, char **argv) {
San Mehatd9a4e352010-03-12 13:32:47 -0800123 dumpArgs(argc, argv, -1);
124
San Mehateba65e92010-01-29 05:15:16 -0800125 if (argc < 2) {
126 cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing Argument", false);
127 return 0;
San Mehat49e2bce2009-10-12 16:29:01 -0700128 }
129
San Mehateba65e92010-01-29 05:15:16 -0800130 VolumeManager *vm = VolumeManager::Instance();
131 int rc = 0;
San Mehatf1b736b2009-10-10 17:22:08 -0700132
San Mehateba65e92010-01-29 05:15:16 -0800133 if (!strcmp(argv[1], "list")) {
134 return vm->listVolumes(cli);
San Mehatd9a4e352010-03-12 13:32:47 -0800135 } else if (!strcmp(argv[1], "debug")) {
San Mehat57df7bf2010-03-14 13:41:27 -0700136 if (argc != 3 || (argc == 3 && (strcmp(argv[2], "off") && strcmp(argv[2], "on")))) {
137 cli->sendMsg(ResponseCode::CommandSyntaxError, "Usage: volume debug <off/on>", false);
138 return 0;
139 }
140 vm->setDebug(!strcmp(argv[2], "on") ? true : false);
San Mehateba65e92010-01-29 05:15:16 -0800141 } else if (!strcmp(argv[1], "mount")) {
San Mehat57df7bf2010-03-14 13:41:27 -0700142 if (argc != 3) {
143 cli->sendMsg(ResponseCode::CommandSyntaxError, "Usage: volume mount <path>", false);
144 return 0;
145 }
San Mehateba65e92010-01-29 05:15:16 -0800146 rc = vm->mountVolume(argv[2]);
147 } else if (!strcmp(argv[1], "unmount")) {
Ken Sumrall0b8b5972011-08-31 16:14:23 -0700148 if (argc < 3 || argc > 4 ||
149 ((argc == 4 && strcmp(argv[3], "force")) &&
150 (argc == 4 && strcmp(argv[3], "force_and_revert")))) {
151 cli->sendMsg(ResponseCode::CommandSyntaxError, "Usage: volume unmount <path> [force|force_and_revert]", false);
San Mehat57df7bf2010-03-14 13:41:27 -0700152 return 0;
153 }
154
San Mehat4ba89482010-02-18 09:00:18 -0800155 bool force = false;
Ken Sumrall0b8b5972011-08-31 16:14:23 -0700156 bool revert = false;
San Mehat4ba89482010-02-18 09:00:18 -0800157 if (argc >= 4 && !strcmp(argv[3], "force")) {
158 force = true;
Ken Sumrall0b8b5972011-08-31 16:14:23 -0700159 } else if (argc >= 4 && !strcmp(argv[3], "force_and_revert")) {
160 force = true;
161 revert = true;
San Mehat4ba89482010-02-18 09:00:18 -0800162 }
Ken Sumrall0b8b5972011-08-31 16:14:23 -0700163 rc = vm->unmountVolume(argv[2], force, revert);
San Mehateba65e92010-01-29 05:15:16 -0800164 } else if (!strcmp(argv[1], "format")) {
Ken Sumrall9caab762013-06-11 19:10:20 -0700165 if (argc < 3 || argc > 4 ||
166 (argc == 4 && strcmp(argv[3], "wipe"))) {
167 cli->sendMsg(ResponseCode::CommandSyntaxError, "Usage: volume format <path> [wipe]", false);
San Mehat57df7bf2010-03-14 13:41:27 -0700168 return 0;
169 }
Ken Sumrall9caab762013-06-11 19:10:20 -0700170 bool wipe = false;
171 if (argc >= 4 && !strcmp(argv[3], "wipe")) {
172 wipe = true;
173 }
174 rc = vm->formatVolume(argv[2], wipe);
San Mehateba65e92010-01-29 05:15:16 -0800175 } else if (!strcmp(argv[1], "share")) {
San Mehat57df7bf2010-03-14 13:41:27 -0700176 if (argc != 4) {
177 cli->sendMsg(ResponseCode::CommandSyntaxError,
178 "Usage: volume share <path> <method>", false);
179 return 0;
180 }
San Mehatb9aed742010-02-04 15:07:01 -0800181 rc = vm->shareVolume(argv[2], argv[3]);
San Mehateba65e92010-01-29 05:15:16 -0800182 } else if (!strcmp(argv[1], "unshare")) {
San Mehat57df7bf2010-03-14 13:41:27 -0700183 if (argc != 4) {
184 cli->sendMsg(ResponseCode::CommandSyntaxError,
185 "Usage: volume unshare <path> <method>", false);
186 return 0;
187 }
San Mehatb9aed742010-02-04 15:07:01 -0800188 rc = vm->unshareVolume(argv[2], argv[3]);
San Mehateba65e92010-01-29 05:15:16 -0800189 } else if (!strcmp(argv[1], "shared")) {
190 bool enabled = false;
San Mehat57df7bf2010-03-14 13:41:27 -0700191 if (argc != 4) {
192 cli->sendMsg(ResponseCode::CommandSyntaxError,
193 "Usage: volume shared <path> <method>", false);
194 return 0;
195 }
San Mehatf1b736b2009-10-10 17:22:08 -0700196
San Mehat2b225522010-02-03 10:26:40 -0800197 if (vm->shareEnabled(argv[2], argv[3], &enabled)) {
San Mehateba65e92010-01-29 05:15:16 -0800198 cli->sendMsg(
199 ResponseCode::OperationFailed, "Failed to determine share enable state", true);
200 } else {
201 cli->sendMsg(ResponseCode::ShareEnabledResult,
202 (enabled ? "Share enabled" : "Share disabled"), false);
203 }
San Mehatb9aed742010-02-04 15:07:01 -0800204 return 0;
Jeff Sharkey71ebe152013-09-17 17:24:38 -0700205 } else if (!strcmp(argv[1], "mkdirs")) {
206 if (argc != 3) {
207 cli->sendMsg(ResponseCode::CommandSyntaxError, "Usage: volume mkdirs <path>", false);
208 return 0;
209 }
210 rc = vm->mkdirs(argv[2]);
San Mehat49e2bce2009-10-12 16:29:01 -0700211 } else {
San Mehateba65e92010-01-29 05:15:16 -0800212 cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown volume cmd", false);
213 }
214
215 if (!rc) {
216 cli->sendMsg(ResponseCode::CommandOkay, "volume operation succeeded", false);
217 } else {
San Mehat8f2875b2010-02-18 11:40:49 -0800218 int erno = errno;
219 rc = ResponseCode::convertFromErrno();
San Mehateba65e92010-01-29 05:15:16 -0800220 cli->sendMsg(rc, "volume operation failed", true);
San Mehat49e2bce2009-10-12 16:29:01 -0700221 }
222
San Mehatf1b736b2009-10-10 17:22:08 -0700223 return 0;
224}
225
San Mehat586536c2010-02-16 17:12:00 -0800226CommandListener::StorageCmd::StorageCmd() :
227 VoldCommand("storage") {
228}
229
230int CommandListener::StorageCmd::runCommand(SocketClient *cli,
231 int argc, char **argv) {
Mohamad Ayyash7929aa72014-03-10 15:55:33 -0700232 /* Guarantied to be initialized by vold's main() before the CommandListener is active */
233 extern struct fstab *fstab;
234
San Mehatd9a4e352010-03-12 13:32:47 -0800235 dumpArgs(argc, argv, -1);
236
San Mehat586536c2010-02-16 17:12:00 -0800237 if (argc < 2) {
238 cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing Argument", false);
239 return 0;
240 }
241
Mohamad Ayyash7929aa72014-03-10 15:55:33 -0700242 if (!strcmp(argv[1], "mountall")) {
243 if (argc != 2) {
244 cli->sendMsg(ResponseCode::CommandSyntaxError, "Usage: mountall", false);
245 return 0;
246 }
247 fs_mgr_mount_all(fstab);
248 cli->sendMsg(ResponseCode::CommandOkay, "Mountall ran successfully", false);
249 return 0;
250 }
San Mehat586536c2010-02-16 17:12:00 -0800251 if (!strcmp(argv[1], "users")) {
252 DIR *dir;
253 struct dirent *de;
254
JP Abgralledf7adf2014-03-12 10:41:05 -0700255 if (argc < 3) {
256 cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing Argument: user <mountpoint>", false);
257 return 0;
258 }
San Mehat586536c2010-02-16 17:12:00 -0800259 if (!(dir = opendir("/proc"))) {
260 cli->sendMsg(ResponseCode::OperationFailed, "Failed to open /proc", true);
261 return 0;
262 }
263
264 while ((de = readdir(dir))) {
265 int pid = Process::getPid(de->d_name);
266
267 if (pid < 0) {
268 continue;
269 }
270
271 char processName[255];
272 Process::getProcessName(pid, processName, sizeof(processName));
273
274 if (Process::checkFileDescriptorSymLinks(pid, argv[2]) ||
275 Process::checkFileMaps(pid, argv[2]) ||
276 Process::checkSymLink(pid, argv[2], "cwd") ||
277 Process::checkSymLink(pid, argv[2], "root") ||
278 Process::checkSymLink(pid, argv[2], "exe")) {
279
280 char msg[1024];
281 snprintf(msg, sizeof(msg), "%d %s", pid, processName);
282 cli->sendMsg(ResponseCode::StorageUsersListResult, msg, false);
283 }
284 }
285 closedir(dir);
286 cli->sendMsg(ResponseCode::CommandOkay, "Storage user list complete", false);
287 } else {
288 cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown storage cmd", false);
289 }
290 return 0;
291}
292
San Mehateba65e92010-01-29 05:15:16 -0800293CommandListener::AsecCmd::AsecCmd() :
294 VoldCommand("asec") {
San Mehata19b2502010-01-06 10:33:53 -0800295}
296
Kenny Root344ca102012-04-03 17:23:01 -0700297void CommandListener::AsecCmd::listAsecsInDirectory(SocketClient *cli, const char *directory) {
298 DIR *d = opendir(directory);
299
300 if (!d) {
301 cli->sendMsg(ResponseCode::OperationFailed, "Failed to open asec dir", true);
302 return;
303 }
304
305 size_t dirent_len = offsetof(struct dirent, d_name) +
Elliott Hughes8c480f72012-10-26 16:57:19 -0700306 fpathconf(dirfd(d), _PC_NAME_MAX) + 1;
Kenny Root344ca102012-04-03 17:23:01 -0700307
308 struct dirent *dent = (struct dirent *) malloc(dirent_len);
309 if (dent == NULL) {
310 cli->sendMsg(ResponseCode::OperationFailed, "Failed to allocate memory", true);
311 return;
312 }
313
314 struct dirent *result;
315
316 while (!readdir_r(d, dent, &result) && result != NULL) {
317 if (dent->d_name[0] == '.')
318 continue;
319 if (dent->d_type != DT_REG)
320 continue;
321 size_t name_len = strlen(dent->d_name);
322 if (name_len > 5 && name_len < 260 &&
323 !strcmp(&dent->d_name[name_len - 5], ".asec")) {
324 char id[255];
325 memset(id, 0, sizeof(id));
Kenny Root7b0bc852012-04-27 15:33:58 -0700326 strlcpy(id, dent->d_name, name_len - 4);
Kenny Root344ca102012-04-03 17:23:01 -0700327 cli->sendMsg(ResponseCode::AsecListResult, id, false);
328 }
329 }
330 closedir(d);
331
332 free(dent);
333}
334
San Mehateba65e92010-01-29 05:15:16 -0800335int CommandListener::AsecCmd::runCommand(SocketClient *cli,
336 int argc, char **argv) {
337 if (argc < 2) {
338 cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing Argument", false);
San Mehata19b2502010-01-06 10:33:53 -0800339 return 0;
340 }
341
San Mehateba65e92010-01-29 05:15:16 -0800342 VolumeManager *vm = VolumeManager::Instance();
343 int rc = 0;
San Mehata19b2502010-01-06 10:33:53 -0800344
San Mehateba65e92010-01-29 05:15:16 -0800345 if (!strcmp(argv[1], "list")) {
San Mehatd9a4e352010-03-12 13:32:47 -0800346 dumpArgs(argc, argv, -1);
San Mehateba65e92010-01-29 05:15:16 -0800347
Kenny Root344ca102012-04-03 17:23:01 -0700348 listAsecsInDirectory(cli, Volume::SEC_ASECDIR_EXT);
349 listAsecsInDirectory(cli, Volume::SEC_ASECDIR_INT);
San Mehateba65e92010-01-29 05:15:16 -0800350 } else if (!strcmp(argv[1], "create")) {
San Mehatd9a4e352010-03-12 13:32:47 -0800351 dumpArgs(argc, argv, 5);
Kenny Root344ca102012-04-03 17:23:01 -0700352 if (argc != 8) {
San Mehateba65e92010-01-29 05:15:16 -0800353 cli->sendMsg(ResponseCode::CommandSyntaxError,
Kenny Root344ca102012-04-03 17:23:01 -0700354 "Usage: asec create <container-id> <size_mb> <fstype> <key> <ownerUid> "
355 "<isExternal>", false);
San Mehateba65e92010-01-29 05:15:16 -0800356 return 0;
357 }
358
359 unsigned int numSectors = (atoi(argv[3]) * (1024 * 1024)) / 512;
Kenny Root344ca102012-04-03 17:23:01 -0700360 const bool isExternal = (atoi(argv[7]) == 1);
361 rc = vm->createAsec(argv[2], numSectors, argv[4], argv[5], atoi(argv[6]), isExternal);
San Mehateba65e92010-01-29 05:15:16 -0800362 } else if (!strcmp(argv[1], "finalize")) {
San Mehatd9a4e352010-03-12 13:32:47 -0800363 dumpArgs(argc, argv, -1);
San Mehateba65e92010-01-29 05:15:16 -0800364 if (argc != 3) {
365 cli->sendMsg(ResponseCode::CommandSyntaxError, "Usage: asec finalize <container-id>", false);
366 return 0;
367 }
San Mehat8f2875b2010-02-18 11:40:49 -0800368 rc = vm->finalizeAsec(argv[2]);
Kenny Root344ca102012-04-03 17:23:01 -0700369 } else if (!strcmp(argv[1], "fixperms")) {
370 dumpArgs(argc, argv, -1);
371 if (argc != 5) {
372 cli->sendMsg(ResponseCode::CommandSyntaxError, "Usage: asec fixperms <container-id> <gid> <filename>", false);
373 return 0;
374 }
375
376 char *endptr;
377 gid_t gid = (gid_t) strtoul(argv[3], &endptr, 10);
378 if (*endptr != '\0') {
379 cli->sendMsg(ResponseCode::CommandSyntaxError, "Usage: asec fixperms <container-id> <gid> <filename>", false);
380 return 0;
381 }
382
383 rc = vm->fixupAsecPermissions(argv[2], gid, argv[4]);
San Mehateba65e92010-01-29 05:15:16 -0800384 } else if (!strcmp(argv[1], "destroy")) {
San Mehatd9a4e352010-03-12 13:32:47 -0800385 dumpArgs(argc, argv, -1);
San Mehat4ba89482010-02-18 09:00:18 -0800386 if (argc < 3) {
387 cli->sendMsg(ResponseCode::CommandSyntaxError, "Usage: asec destroy <container-id> [force]", false);
San Mehateba65e92010-01-29 05:15:16 -0800388 return 0;
389 }
San Mehat4ba89482010-02-18 09:00:18 -0800390 bool force = false;
391 if (argc > 3 && !strcmp(argv[3], "force")) {
392 force = true;
393 }
San Mehat8f2875b2010-02-18 11:40:49 -0800394 rc = vm->destroyAsec(argv[2], force);
San Mehateba65e92010-01-29 05:15:16 -0800395 } else if (!strcmp(argv[1], "mount")) {
San Mehatd9a4e352010-03-12 13:32:47 -0800396 dumpArgs(argc, argv, 3);
San Mehateba65e92010-01-29 05:15:16 -0800397 if (argc != 5) {
398 cli->sendMsg(ResponseCode::CommandSyntaxError,
399 "Usage: asec mount <namespace-id> <key> <ownerUid>", false);
400 return 0;
401 }
San Mehat8f2875b2010-02-18 11:40:49 -0800402 rc = vm->mountAsec(argv[2], argv[3], atoi(argv[4]));
San Mehateba65e92010-01-29 05:15:16 -0800403 } else if (!strcmp(argv[1], "unmount")) {
San Mehatd9a4e352010-03-12 13:32:47 -0800404 dumpArgs(argc, argv, -1);
San Mehat4ba89482010-02-18 09:00:18 -0800405 if (argc < 3) {
406 cli->sendMsg(ResponseCode::CommandSyntaxError, "Usage: asec unmount <container-id> [force]", false);
San Mehateba65e92010-01-29 05:15:16 -0800407 return 0;
408 }
San Mehat4ba89482010-02-18 09:00:18 -0800409 bool force = false;
410 if (argc > 3 && !strcmp(argv[3], "force")) {
411 force = true;
412 }
San Mehat8f2875b2010-02-18 11:40:49 -0800413 rc = vm->unmountAsec(argv[2], force);
San Mehateba65e92010-01-29 05:15:16 -0800414 } else if (!strcmp(argv[1], "rename")) {
San Mehatd9a4e352010-03-12 13:32:47 -0800415 dumpArgs(argc, argv, -1);
San Mehateba65e92010-01-29 05:15:16 -0800416 if (argc != 4) {
417 cli->sendMsg(ResponseCode::CommandSyntaxError,
418 "Usage: asec rename <old_id> <new_id>", false);
419 return 0;
420 }
San Mehat8f2875b2010-02-18 11:40:49 -0800421 rc = vm->renameAsec(argv[2], argv[3]);
San Mehateba65e92010-01-29 05:15:16 -0800422 } else if (!strcmp(argv[1], "path")) {
San Mehatd9a4e352010-03-12 13:32:47 -0800423 dumpArgs(argc, argv, -1);
San Mehateba65e92010-01-29 05:15:16 -0800424 if (argc != 3) {
425 cli->sendMsg(ResponseCode::CommandSyntaxError, "Usage: asec path <container-id>", false);
426 return 0;
427 }
428 char path[255];
429
San Mehat88ac2c02010-03-23 11:15:58 -0700430 if (!(rc = vm->getAsecMountPath(argv[2], path, sizeof(path)))) {
San Mehateba65e92010-01-29 05:15:16 -0800431 cli->sendMsg(ResponseCode::AsecPathResult, path, false);
San Mehat88ac2c02010-03-23 11:15:58 -0700432 return 0;
San Mehateba65e92010-01-29 05:15:16 -0800433 }
Dianne Hackborn736910c2011-06-27 13:37:07 -0700434 } else if (!strcmp(argv[1], "fspath")) {
435 dumpArgs(argc, argv, -1);
436 if (argc != 3) {
437 cli->sendMsg(ResponseCode::CommandSyntaxError, "Usage: asec fspath <container-id>", false);
438 return 0;
439 }
440 char path[255];
441
442 if (!(rc = vm->getAsecFilesystemPath(argv[2], path, sizeof(path)))) {
443 cli->sendMsg(ResponseCode::AsecPathResult, path, false);
444 return 0;
445 }
San Mehata19b2502010-01-06 10:33:53 -0800446 } else {
San Mehatd9a4e352010-03-12 13:32:47 -0800447 dumpArgs(argc, argv, -1);
San Mehateba65e92010-01-29 05:15:16 -0800448 cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown asec cmd", false);
San Mehata19b2502010-01-06 10:33:53 -0800449 }
450
San Mehat8f2875b2010-02-18 11:40:49 -0800451 if (!rc) {
452 cli->sendMsg(ResponseCode::CommandOkay, "asec operation succeeded", false);
453 } else {
454 rc = ResponseCode::convertFromErrno();
455 cli->sendMsg(rc, "asec operation failed", true);
456 }
457
San Mehata19b2502010-01-06 10:33:53 -0800458 return 0;
459}
San Mehat2350c442010-03-02 13:16:50 -0800460
Kenny Root508c0e12010-07-12 09:59:49 -0700461CommandListener::ObbCmd::ObbCmd() :
462 VoldCommand("obb") {
Kenny Rootfb7c4d52010-06-30 18:48:41 -0700463}
464
Kenny Root508c0e12010-07-12 09:59:49 -0700465int CommandListener::ObbCmd::runCommand(SocketClient *cli,
Kenny Rootfb7c4d52010-06-30 18:48:41 -0700466 int argc, char **argv) {
467 if (argc < 2) {
468 cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing Argument", false);
469 return 0;
470 }
471
472 VolumeManager *vm = VolumeManager::Instance();
473 int rc = 0;
474
Kenny Root508c0e12010-07-12 09:59:49 -0700475 if (!strcmp(argv[1], "list")) {
476 dumpArgs(argc, argv, -1);
477
478 rc = vm->listMountedObbs(cli);
479 } else if (!strcmp(argv[1], "mount")) {
Kenny Rootfb7c4d52010-06-30 18:48:41 -0700480 dumpArgs(argc, argv, 3);
481 if (argc != 5) {
482 cli->sendMsg(ResponseCode::CommandSyntaxError,
Jeff Sharkey69479042012-09-25 16:14:57 -0700483 "Usage: obb mount <filename> <key> <ownerGid>", false);
Kenny Rootfb7c4d52010-06-30 18:48:41 -0700484 return 0;
485 }
Kenny Root508c0e12010-07-12 09:59:49 -0700486 rc = vm->mountObb(argv[2], argv[3], atoi(argv[4]));
Kenny Rootfb7c4d52010-06-30 18:48:41 -0700487 } else if (!strcmp(argv[1], "unmount")) {
488 dumpArgs(argc, argv, -1);
489 if (argc < 3) {
Kenny Root508c0e12010-07-12 09:59:49 -0700490 cli->sendMsg(ResponseCode::CommandSyntaxError, "Usage: obb unmount <source file> [force]", false);
Kenny Rootfb7c4d52010-06-30 18:48:41 -0700491 return 0;
492 }
493 bool force = false;
494 if (argc > 3 && !strcmp(argv[3], "force")) {
495 force = true;
496 }
Kenny Root508c0e12010-07-12 09:59:49 -0700497 rc = vm->unmountObb(argv[2], force);
498 } else if (!strcmp(argv[1], "path")) {
499 dumpArgs(argc, argv, -1);
500 if (argc != 3) {
501 cli->sendMsg(ResponseCode::CommandSyntaxError, "Usage: obb path <source file>", false);
502 return 0;
503 }
504 char path[255];
505
506 if (!(rc = vm->getObbMountPath(argv[2], path, sizeof(path)))) {
507 cli->sendMsg(ResponseCode::AsecPathResult, path, false);
508 return 0;
509 }
Kenny Rootfb7c4d52010-06-30 18:48:41 -0700510 } else {
511 dumpArgs(argc, argv, -1);
Kenny Root508c0e12010-07-12 09:59:49 -0700512 cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown obb cmd", false);
Kenny Rootfb7c4d52010-06-30 18:48:41 -0700513 }
514
515 if (!rc) {
Kenny Root508c0e12010-07-12 09:59:49 -0700516 cli->sendMsg(ResponseCode::CommandOkay, "obb operation succeeded", false);
Kenny Rootfb7c4d52010-06-30 18:48:41 -0700517 } else {
518 rc = ResponseCode::convertFromErrno();
Kenny Root508c0e12010-07-12 09:59:49 -0700519 cli->sendMsg(rc, "obb operation failed", true);
Kenny Rootfb7c4d52010-06-30 18:48:41 -0700520 }
521
522 return 0;
523}
524
Ken Sumrall8f869aa2010-12-03 03:47:09 -0800525CommandListener::CryptfsCmd::CryptfsCmd() :
526 VoldCommand("cryptfs") {
527}
528
Paul Lawrence45f10532014-04-04 18:11:56 +0000529static int getType(const char* type)
530{
531 if (!strcmp(type, "default")) {
532 return CRYPT_TYPE_DEFAULT;
533 } else if (!strcmp(type, "password")) {
534 return CRYPT_TYPE_PASSWORD;
535 } else if (!strcmp(type, "pin")) {
536 return CRYPT_TYPE_PIN;
537 } else if (!strcmp(type, "pattern")) {
538 return CRYPT_TYPE_PATTERN;
539 } else {
540 return -1;
541 }
542}
543
Ken Sumrall8f869aa2010-12-03 03:47:09 -0800544int CommandListener::CryptfsCmd::runCommand(SocketClient *cli,
545 int argc, char **argv) {
Ken Sumrall3ad90722011-10-04 20:38:29 -0700546 if ((cli->getUid() != 0) && (cli->getUid() != AID_SYSTEM)) {
547 cli->sendMsg(ResponseCode::CommandNoPermission, "No permission to run cryptfs commands", false);
548 return 0;
549 }
550
Ken Sumrall8f869aa2010-12-03 03:47:09 -0800551 if (argc < 2) {
552 cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing Argument", false);
553 return 0;
554 }
555
556 int rc = 0;
557
558 if (!strcmp(argv[1], "checkpw")) {
559 if (argc != 3) {
560 cli->sendMsg(ResponseCode::CommandSyntaxError, "Usage: cryptfs checkpw <passwd>", false);
561 return 0;
562 }
Ken Sumrall8ddbe402011-01-17 15:26:29 -0800563 dumpArgs(argc, argv, 2);
Ken Sumrall8f869aa2010-12-03 03:47:09 -0800564 rc = cryptfs_check_passwd(argv[2]);
Ken Sumrall6864b7e2011-01-14 15:20:02 -0800565 } else if (!strcmp(argv[1], "restart")) {
566 if (argc != 2) {
567 cli->sendMsg(ResponseCode::CommandSyntaxError, "Usage: cryptfs restart", false);
568 return 0;
569 }
Ken Sumrall8ddbe402011-01-17 15:26:29 -0800570 dumpArgs(argc, argv, -1);
Ken Sumrall6864b7e2011-01-14 15:20:02 -0800571 rc = cryptfs_restart();
Ken Sumrall7f7dbaa2011-02-01 15:46:41 -0800572 } else if (!strcmp(argv[1], "cryptocomplete")) {
573 if (argc != 2) {
574 cli->sendMsg(ResponseCode::CommandSyntaxError, "Usage: cryptfs cryptocomplete", false);
575 return 0;
576 }
577 dumpArgs(argc, argv, -1);
578 rc = cryptfs_crypto_complete();
Ken Sumrall8f869aa2010-12-03 03:47:09 -0800579 } else if (!strcmp(argv[1], "enablecrypto")) {
Paul Lawrence45f10532014-04-04 18:11:56 +0000580 const char* syntax = "Usage: cryptfs enablecrypto <wipe|inplace> "
581 "default|password|pin|pattern [passwd]";
582 if ( (argc != 4 && argc != 5)
Paul Lawrence13486032014-02-03 13:28:11 -0800583 || (strcmp(argv[2], "wipe") && strcmp(argv[2], "inplace")) ) {
Paul Lawrence45f10532014-04-04 18:11:56 +0000584 cli->sendMsg(ResponseCode::CommandSyntaxError, syntax, false);
Ken Sumrall8f869aa2010-12-03 03:47:09 -0800585 return 0;
586 }
Paul Lawrence45f10532014-04-04 18:11:56 +0000587 dumpArgs(argc, argv, 4);
JP Abgrall502dc742013-11-01 13:06:20 -0700588
Paul Lawrence13486032014-02-03 13:28:11 -0800589 int tries;
590 for (tries = 0; tries < 2; ++tries) {
Paul Lawrence45f10532014-04-04 18:11:56 +0000591 int type = getType(argv[3]);
592 if (type == -1) {
593 cli->sendMsg(ResponseCode::CommandSyntaxError, syntax,
594 false);
595 return 0;
596 } else if (type == CRYPT_TYPE_DEFAULT) {
597 rc = cryptfs_enable_default(argv[2], /*allow_reboot*/false);
598 } else {
599 rc = cryptfs_enable(argv[2], type, argv[4],
600 /*allow_reboot*/false);
601 }
Paul Lawrence13486032014-02-03 13:28:11 -0800602
603 if (rc == 0) {
604 break;
605 } else if (tries == 0) {
606 Process::killProcessesWithOpenFiles(DATA_MNT_POINT, 2);
607 }
608 }
Ken Sumrall8ddbe402011-01-17 15:26:29 -0800609 } else if (!strcmp(argv[1], "changepw")) {
Paul Lawrencef4faa572014-01-29 13:31:03 -0800610 const char* syntax = "Usage: cryptfs changepw "
611 "default|password|pin|pattern [newpasswd]";
Paul Lawrence13486032014-02-03 13:28:11 -0800612 const char* password;
Paul Lawrencef4faa572014-01-29 13:31:03 -0800613 if (argc == 3) {
614 password = "";
615 } else if (argc == 4) {
616 password = argv[3];
617 } else {
618 cli->sendMsg(ResponseCode::CommandSyntaxError, syntax, false);
Ken Sumrall8ddbe402011-01-17 15:26:29 -0800619 return 0;
Paul Lawrencef4faa572014-01-29 13:31:03 -0800620 }
Paul Lawrence45f10532014-04-04 18:11:56 +0000621 int type = getType(argv[2]);
622 if (type == -1) {
Paul Lawrencef4faa572014-01-29 13:31:03 -0800623 cli->sendMsg(ResponseCode::CommandSyntaxError, syntax, false);
624 return 0;
625 }
626 SLOGD("cryptfs changepw %s {}", argv[2]);
627 rc = cryptfs_changepw(type, password);
Ken Sumrall3ad90722011-10-04 20:38:29 -0700628 } else if (!strcmp(argv[1], "verifypw")) {
629 if (argc != 3) {
630 cli->sendMsg(ResponseCode::CommandSyntaxError, "Usage: cryptfs verifypw <passwd>", false);
631 return 0;
632 }
633 SLOGD("cryptfs verifypw {}");
634 rc = cryptfs_verify_passwd(argv[2]);
Ken Sumrall160b4d62013-04-22 12:15:39 -0700635 } else if (!strcmp(argv[1], "getfield")) {
636 char valbuf[PROPERTY_VALUE_MAX];
637
638 if (argc != 3) {
639 cli->sendMsg(ResponseCode::CommandSyntaxError, "Usage: cryptfs getfield <fieldname>", false);
640 return 0;
641 }
642 dumpArgs(argc, argv, -1);
643 rc = cryptfs_getfield(argv[2], valbuf, sizeof(valbuf));
644 if (rc == 0) {
645 cli->sendMsg(ResponseCode::CryptfsGetfieldResult, valbuf, false);
646 }
647 } else if (!strcmp(argv[1], "setfield")) {
648 if (argc != 4) {
649 cli->sendMsg(ResponseCode::CommandSyntaxError, "Usage: cryptfs setfield <fieldname> <value>", false);
650 return 0;
651 }
652 dumpArgs(argc, argv, -1);
653 rc = cryptfs_setfield(argv[2], argv[3]);
Paul Lawrencef4faa572014-01-29 13:31:03 -0800654 } else if (!strcmp(argv[1], "mountdefaultencrypted")) {
655 SLOGD("cryptfs mountdefaultencrypted");
656 dumpArgs(argc, argv, -1);
657 rc = cryptfs_mount_default_encrypted();
658 } else if (!strcmp(argv[1], "getpwtype")) {
659 SLOGD("cryptfs getpwtype");
660 dumpArgs(argc, argv, -1);
661 switch(cryptfs_get_password_type()) {
662 case CRYPT_TYPE_PASSWORD:
663 cli->sendMsg(ResponseCode::PasswordTypeResult, "password", false);
664 return 0;
665 case CRYPT_TYPE_PATTERN:
666 cli->sendMsg(ResponseCode::PasswordTypeResult, "pattern", false);
667 return 0;
668 case CRYPT_TYPE_PIN:
669 cli->sendMsg(ResponseCode::PasswordTypeResult, "pin", false);
670 return 0;
671 case CRYPT_TYPE_DEFAULT:
672 cli->sendMsg(ResponseCode::PasswordTypeResult, "default", false);
673 return 0;
674 default:
675 /** @TODO better error and make sure handled by callers */
676 cli->sendMsg(ResponseCode::OpFailedStorageNotFound, "Error", false);
677 return 0;
678 }
Paul Lawrence399317e2014-03-10 13:20:50 -0700679 } else if (!strcmp(argv[1], "getpw")) {
680 SLOGD("cryptfs getpw");
Paul Lawrence684dbdf2014-02-07 12:07:22 -0800681 dumpArgs(argc, argv, -1);
Paul Lawrence399317e2014-03-10 13:20:50 -0700682 char* password = cryptfs_get_password();
683 if (password) {
684 cli->sendMsg(ResponseCode::CommandOkay, password, false);
685 return 0;
686 }
687 rc = -1;
688 } else if (!strcmp(argv[1], "clearpw")) {
689 SLOGD("cryptfs clearpw");
690 dumpArgs(argc, argv, -1);
691 cryptfs_clear_password();
692 rc = 0;
Ken Sumrall8f869aa2010-12-03 03:47:09 -0800693 } else {
Ken Sumrall8ddbe402011-01-17 15:26:29 -0800694 dumpArgs(argc, argv, -1);
Ken Sumrall8f869aa2010-12-03 03:47:09 -0800695 cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown cryptfs cmd", false);
Paul Lawrencef4faa572014-01-29 13:31:03 -0800696 return 0;
Ken Sumrall8f869aa2010-12-03 03:47:09 -0800697 }
698
Jason parks0167cb12011-01-20 18:30:39 -0600699 // Always report that the command succeeded and return the error code.
700 // The caller will check the return value to see what the error was.
701 char msg[255];
702 snprintf(msg, sizeof(msg), "%d", rc);
703 cli->sendMsg(ResponseCode::CommandOkay, msg, false);
Ken Sumrall8f869aa2010-12-03 03:47:09 -0800704
705 return 0;
706}
Ken Sumrallb87937c2013-03-19 21:46:39 -0700707
708CommandListener::FstrimCmd::FstrimCmd() :
709 VoldCommand("fstrim") {
710}
711int CommandListener::FstrimCmd::runCommand(SocketClient *cli,
712 int argc, char **argv) {
713 if ((cli->getUid() != 0) && (cli->getUid() != AID_SYSTEM)) {
714 cli->sendMsg(ResponseCode::CommandNoPermission, "No permission to run fstrim commands", false);
715 return 0;
716 }
717
718 if (argc < 2) {
719 cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing Argument", false);
720 return 0;
721 }
722
723 int rc = 0;
724
725 if (!strcmp(argv[1], "dotrim")) {
726 if (argc != 2) {
727 cli->sendMsg(ResponseCode::CommandSyntaxError, "Usage: fstrim dotrim", false);
728 return 0;
729 }
730 dumpArgs(argc, argv, -1);
731 rc = fstrim_filesystems();
732 } else {
733 dumpArgs(argc, argv, -1);
734 cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown fstrim cmd", false);
735 }
736
737 // Always report that the command succeeded and return the error code.
738 // The caller will check the return value to see what the error was.
739 char msg[255];
740 snprintf(msg, sizeof(msg), "%d", rc);
741 cli->sendMsg(ResponseCode::CommandOkay, msg, false);
742
743 return 0;
744}