CommandListener.cpp revision 2350c44ff39b4cb2940893964a05f778fc80a436
1e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy/*
2e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy * Copyright (C) 2008 The Android Open Source Project
3e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy *
4e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy * Licensed under the Apache License, Version 2.0 (the "License");
5e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy * you may not use this file except in compliance with the License.
6e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy * You may obtain a copy of the License at
7e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy *
8e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy *      http://www.apache.org/licenses/LICENSE-2.0
9e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy *
10e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy * Unless required by applicable law or agreed to in writing, software
11e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy * distributed under the License is distributed on an "AS IS" BASIS,
12e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy * See the License for the specific language governing permissions and
14e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy * limitations under the License.
15e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy */
16e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
1785bf02fc16784d935fb9eebfa9cb20fe46ff7951Romain Guy#include <stdlib.h>
18e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy#include <sys/socket.h>
19e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy#include <sys/types.h>
20e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy#include <netinet/in.h>
21e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy#include <arpa/inet.h>
22e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy#include <dirent.h>
23bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy#include <errno.h>
24694b519ac647fe998fd396fe0784cc8e179aadc4Romain Guy#include <fcntl.h>
255cbbce535744b89df5ecea95de21ee3733298260Romain Guy
26121e2242565d5f09ad83a2d33ecd2225838802c5Romain Guy#define LOG_TAG "CommandListener"
275cbbce535744b89df5ecea95de21ee3733298260Romain Guy#include <cutils/log.h>
2885bf02fc16784d935fb9eebfa9cb20fe46ff7951Romain Guy
2985bf02fc16784d935fb9eebfa9cb20fe46ff7951Romain Guy#include <sysutils/SocketClient.h>
3051769a68a5cb34e9564740c6a854fcb93018789dRomain Guy
31e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy#include "CommandListener.h"
32e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy#include "VolumeManager.h"
339d5316e3f56d138504565ff311145ac01621dff4Romain Guy#include "ResponseCode.h"
349d5316e3f56d138504565ff311145ac01621dff4Romain Guy#include "Process.h"
359d5316e3f56d138504565ff311145ac01621dff4Romain Guy#include "Xwarp.h"
369d5316e3f56d138504565ff311145ac01621dff4Romain Guy
379d5316e3f56d138504565ff311145ac01621dff4Romain GuyCommandListener::CommandListener() :
389d5316e3f56d138504565ff311145ac01621dff4Romain Guy                 FrameworkListener("vold") {
39c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy    registerCmd(new VolumeCmd());
40c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy    registerCmd(new AsecCmd());
41f7f93556c8fcc640ab5adef79d021a80a72a645aRomain Guy    registerCmd(new ShareCmd());
42c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy    registerCmd(new StorageCmd());
43dda570201ac851dd85af3861f7e575721d3345daRomain Guy    registerCmd(new XwarpCmd());
4406f96e2652e4855b6520ad9dd70583677605b79aRomain Guy}
4506f96e2652e4855b6520ad9dd70583677605b79aRomain Guy
46121e2242565d5f09ad83a2d33ecd2225838802c5Romain GuyCommandListener::VolumeCmd::VolumeCmd() :
47121e2242565d5f09ad83a2d33ecd2225838802c5Romain Guy                 VoldCommand("volume") {
48121e2242565d5f09ad83a2d33ecd2225838802c5Romain Guy}
49dda570201ac851dd85af3861f7e575721d3345daRomain Guy
50bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guyint CommandListener::VolumeCmd::runCommand(SocketClient *cli,
519d5316e3f56d138504565ff311145ac01621dff4Romain Guy                                                      int argc, char **argv) {
529d5316e3f56d138504565ff311145ac01621dff4Romain Guy    if (argc < 2) {
539d5316e3f56d138504565ff311145ac01621dff4Romain Guy        cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing Argument", false);
549d5316e3f56d138504565ff311145ac01621dff4Romain Guy        return 0;
559d5316e3f56d138504565ff311145ac01621dff4Romain Guy    }
56026c5e16704e817cac7d9c382914c947e34f87e0Romain Guy
57026c5e16704e817cac7d9c382914c947e34f87e0Romain Guy    VolumeManager *vm = VolumeManager::Instance();
58ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy    int rc = 0;
59c1396e93b6a5286a5183c00c781b62e940a12c1fRomain Guy
60c1396e93b6a5286a5183c00c781b62e940a12c1fRomain Guy    if (!strcmp(argv[1], "list")) {
61c1396e93b6a5286a5183c00c781b62e940a12c1fRomain Guy        return vm->listVolumes(cli);
62c1396e93b6a5286a5183c00c781b62e940a12c1fRomain Guy    } else if (!strcmp(argv[1], "mount")) {
63bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy        rc = vm->mountVolume(argv[2]);
64ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy    } else if (!strcmp(argv[1], "unmount")) {
65ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy        bool force = false;
66026c5e16704e817cac7d9c382914c947e34f87e0Romain Guy        if (argc >= 4 && !strcmp(argv[3], "force")) {
67889f8d1403761d5668115ced6cbb3f767cfe966dRomain Guy            force = true;
68889f8d1403761d5668115ced6cbb3f767cfe966dRomain Guy        }
69889f8d1403761d5668115ced6cbb3f767cfe966dRomain Guy        rc = vm->unmountVolume(argv[2], force);
70889f8d1403761d5668115ced6cbb3f767cfe966dRomain Guy    } else if (!strcmp(argv[1], "format")) {
71889f8d1403761d5668115ced6cbb3f767cfe966dRomain Guy        rc = vm->formatVolume(argv[2]);
72889f8d1403761d5668115ced6cbb3f767cfe966dRomain Guy    } else if (!strcmp(argv[1], "share")) {
73889f8d1403761d5668115ced6cbb3f767cfe966dRomain Guy        rc = vm->shareVolume(argv[2], argv[3]);
74889f8d1403761d5668115ced6cbb3f767cfe966dRomain Guy    } else if (!strcmp(argv[1], "unshare")) {
75889f8d1403761d5668115ced6cbb3f767cfe966dRomain Guy        rc = vm->unshareVolume(argv[2], argv[3]);
76026c5e16704e817cac7d9c382914c947e34f87e0Romain Guy    } else if (!strcmp(argv[1], "shared")) {
77026c5e16704e817cac7d9c382914c947e34f87e0Romain Guy        bool enabled = false;
78026c5e16704e817cac7d9c382914c947e34f87e0Romain Guy
79026c5e16704e817cac7d9c382914c947e34f87e0Romain Guy        if (vm->shareEnabled(argv[2], argv[3], &enabled)) {
80026c5e16704e817cac7d9c382914c947e34f87e0Romain Guy            cli->sendMsg(
81026c5e16704e817cac7d9c382914c947e34f87e0Romain Guy                    ResponseCode::OperationFailed, "Failed to determine share enable state", true);
82026c5e16704e817cac7d9c382914c947e34f87e0Romain Guy        } else {
83026c5e16704e817cac7d9c382914c947e34f87e0Romain Guy            cli->sendMsg(ResponseCode::ShareEnabledResult,
84026c5e16704e817cac7d9c382914c947e34f87e0Romain Guy                    (enabled ? "Share enabled" : "Share disabled"), false);
85026c5e16704e817cac7d9c382914c947e34f87e0Romain Guy        }
86026c5e16704e817cac7d9c382914c947e34f87e0Romain Guy        return 0;
87026c5e16704e817cac7d9c382914c947e34f87e0Romain Guy    } else {
88026c5e16704e817cac7d9c382914c947e34f87e0Romain Guy        cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown volume cmd", false);
89026c5e16704e817cac7d9c382914c947e34f87e0Romain Guy    }
90026c5e16704e817cac7d9c382914c947e34f87e0Romain Guy
91026c5e16704e817cac7d9c382914c947e34f87e0Romain Guy    if (!rc) {
92e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy        cli->sendMsg(ResponseCode::CommandOkay, "volume operation succeeded", false);
93889f8d1403761d5668115ced6cbb3f767cfe966dRomain Guy    } else {
9406f96e2652e4855b6520ad9dd70583677605b79aRomain Guy        int erno = errno;
9506f96e2652e4855b6520ad9dd70583677605b79aRomain Guy        rc = ResponseCode::convertFromErrno();
9606f96e2652e4855b6520ad9dd70583677605b79aRomain Guy        cli->sendMsg(rc, "volume operation failed", true);
97d27977d1a91d5a6b3cc9fa7664ac7e835e7bd895Romain Guy    }
98d27977d1a91d5a6b3cc9fa7664ac7e835e7bd895Romain Guy
99f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy    return 0;
100f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy}
101f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy
102f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain GuyCommandListener::ShareCmd::ShareCmd() :
103dda570201ac851dd85af3861f7e575721d3345daRomain Guy                 VoldCommand("share") {
10482ba814ca0dea659be2cc6523bc0137679d961ceRomain Guy}
105dda570201ac851dd85af3861f7e575721d3345daRomain Guy
106f7f93556c8fcc640ab5adef79d021a80a72a645aRomain Guyint CommandListener::ShareCmd::runCommand(SocketClient *cli,
107c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy                                                      int argc, char **argv) {
108f7f93556c8fcc640ab5adef79d021a80a72a645aRomain Guy    if (argc < 2) {
10985bf02fc16784d935fb9eebfa9cb20fe46ff7951Romain Guy        cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing Argument", false);
1109d5316e3f56d138504565ff311145ac01621dff4Romain Guy        return 0;
111121e2242565d5f09ad83a2d33ecd2225838802c5Romain Guy    }
112121e2242565d5f09ad83a2d33ecd2225838802c5Romain Guy
113dda570201ac851dd85af3861f7e575721d3345daRomain Guy    VolumeManager *vm = VolumeManager::Instance();
114c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy    int rc = 0;
115dda570201ac851dd85af3861f7e575721d3345daRomain Guy
116c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy    if (!strcmp(argv[1], "status")) {
117dda570201ac851dd85af3861f7e575721d3345daRomain Guy        bool avail = false;
118dda570201ac851dd85af3861f7e575721d3345daRomain Guy
119dda570201ac851dd85af3861f7e575721d3345daRomain Guy        if (vm->shareAvailable(argv[2], &avail)) {
120dda570201ac851dd85af3861f7e575721d3345daRomain Guy            cli->sendMsg(
121c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy                    ResponseCode::OperationFailed, "Failed to determine share availability", true);
122dda570201ac851dd85af3861f7e575721d3345daRomain Guy        } else {
123c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy            cli->sendMsg(ResponseCode::ShareStatusResult,
124c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy                    (avail ? "Share available" : "Share unavailable"), false);
125c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy        }
126c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy    } else {
127c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy        cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown share cmd", false);
128c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy    }
129c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy
130c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy    return 0;
131121e2242565d5f09ad83a2d33ecd2225838802c5Romain Guy}
132121e2242565d5f09ad83a2d33ecd2225838802c5Romain Guy
133889f8d1403761d5668115ced6cbb3f767cfe966dRomain GuyCommandListener::StorageCmd::StorageCmd() :
13406f96e2652e4855b6520ad9dd70583677605b79aRomain Guy                 VoldCommand("storage") {
135db1938e0e6ef816e228c815adccebd5cb05f2aa8Romain Guy}
136026c5e16704e817cac7d9c382914c947e34f87e0Romain Guy
137ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guyint CommandListener::StorageCmd::runCommand(SocketClient *cli,
138ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy                                                      int argc, char **argv) {
139ae5575b3421c8fbe590ab046d7d5f2b36ecfd821Romain Guy    if (argc < 2) {
140ae5575b3421c8fbe590ab046d7d5f2b36ecfd821Romain Guy        cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing Argument", false);
141ae5575b3421c8fbe590ab046d7d5f2b36ecfd821Romain Guy        return 0;
142ae5575b3421c8fbe590ab046d7d5f2b36ecfd821Romain Guy    }
143ae5575b3421c8fbe590ab046d7d5f2b36ecfd821Romain Guy
144889f8d1403761d5668115ced6cbb3f767cfe966dRomain Guy    if (!strcmp(argv[1], "users")) {
145889f8d1403761d5668115ced6cbb3f767cfe966dRomain Guy        DIR *dir;
146e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy        struct dirent *de;
147e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
14885bf02fc16784d935fb9eebfa9cb20fe46ff7951Romain Guy        if (!(dir = opendir("/proc"))) {
14985bf02fc16784d935fb9eebfa9cb20fe46ff7951Romain Guy            cli->sendMsg(ResponseCode::OperationFailed, "Failed to open /proc", true);
150ce0537b80087a6225273040a987414b1dd081aa0Romain Guy            return 0;
151ce0537b80087a6225273040a987414b1dd081aa0Romain Guy        }
152dda570201ac851dd85af3861f7e575721d3345daRomain Guy
153c0ac193b9415680f0a69e20a3f5f22d16f8053beRomain Guy        while ((de = readdir(dir))) {
1546926c72e25b8dec3dd4b84af0819fa1937ae7296Romain Guy            int pid = Process::getPid(de->d_name);
155e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy
156e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy            if (pid < 0) {
157f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy                continue;
158f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy            }
159f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy
160f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy            char processName[255];
16185bf02fc16784d935fb9eebfa9cb20fe46ff7951Romain Guy            Process::getProcessName(pid, processName, sizeof(processName));
16208ae317c21ec3086b5017672bba87420cc38a407Romain Guy
16308ae317c21ec3086b5017672bba87420cc38a407Romain Guy            if (Process::checkFileDescriptorSymLinks(pid, argv[2]) ||
164260e102162322958cf17dbd895cd6bd30dc87e32Romain Guy                Process::checkFileMaps(pid, argv[2]) ||
165bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guy                Process::checkSymLink(pid, argv[2], "cwd") ||
166bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guy                Process::checkSymLink(pid, argv[2], "root") ||
167bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guy                Process::checkSymLink(pid, argv[2], "exe")) {
168ae5575b3421c8fbe590ab046d7d5f2b36ecfd821Romain Guy
169e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy                char msg[1024];
170e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy                snprintf(msg, sizeof(msg), "%d %s", pid, processName);
17185bf02fc16784d935fb9eebfa9cb20fe46ff7951Romain Guy                cli->sendMsg(ResponseCode::StorageUsersListResult, msg, false);
172b82da65cb1601be504241f36778395cd6cb9f87bRomain Guy            }
1737ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy        }
174f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy        closedir(dir);
17508ae317c21ec3086b5017672bba87420cc38a407Romain Guy        cli->sendMsg(ResponseCode::CommandOkay, "Storage user list complete", false);
176bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guy    } else {
17708ae317c21ec3086b5017672bba87420cc38a407Romain Guy        cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown storage cmd", false);
17808ae317c21ec3086b5017672bba87420cc38a407Romain Guy    }
179bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guy    return 0;
18008ae317c21ec3086b5017672bba87420cc38a407Romain Guy}
181c7d53494f1fbd9f9d74af89053ff9fdb1ccbac6cRomain Guy
182f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain GuyCommandListener::AsecCmd::AsecCmd() :
183b82da65cb1601be504241f36778395cd6cb9f87bRomain Guy                 VoldCommand("asec") {
184bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guy}
185bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guy
186f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guyint CommandListener::AsecCmd::runCommand(SocketClient *cli,
187f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy                                                      int argc, char **argv) {
188f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy    if (argc < 2) {
189f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy        cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing Argument", false);
190bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guy        return 0;
1917ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy    }
192bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guy
193bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guy    VolumeManager *vm = VolumeManager::Instance();
194bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guy    int rc = 0;
1957ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy
196bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guy    if (!strcmp(argv[1], "list")) {
197bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guy        DIR *d = opendir(Volume::SEC_ASECDIR);
198bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guy
1997ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy        if (!d) {
200bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guy            cli->sendMsg(ResponseCode::OperationFailed, "Failed to open asec dir", true);
2017ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy            return 0;
2027ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy        }
2037ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy
204bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guy        struct dirent *dent;
205bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guy        while ((dent = readdir(d))) {
206bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guy            if (dent->d_name[0] == '.')
2077ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy                continue;
208bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guy            if (!strcmp(&dent->d_name[strlen(dent->d_name)-5], ".asec")) {
2097ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy                char id[255];
210bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guy                memset(id, 0, sizeof(id));
2117ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy                strncpy(id, dent->d_name, strlen(dent->d_name) -5);
2127ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy                cli->sendMsg(ResponseCode::AsecListResult, id, false);
2137ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy            }
214bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guy        }
2157ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy        closedir(d);
2167ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy    } else if (!strcmp(argv[1], "create")) {
2177ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy        if (argc != 7) {
218bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guy            cli->sendMsg(ResponseCode::CommandSyntaxError,
219bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guy                    "Usage: asec create <container-id> <size_mb> <fstype> <key> <ownerUid>", false);
220bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guy            return 0;
2217ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy        }
2227ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy
223bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guy        unsigned int numSectors = (atoi(argv[3]) * (1024 * 1024)) / 512;
224bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guy        rc = vm->createAsec(argv[2], numSectors, argv[4], argv[5], atoi(argv[6]));
225bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guy    } else if (!strcmp(argv[1], "finalize")) {
2267ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy        if (argc != 3) {
227bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy            cli->sendMsg(ResponseCode::CommandSyntaxError, "Usage: asec finalize <container-id>", false);
228f86ef57f8bcd8ba43ce222ec6a8b4f67d3600640Romain Guy            return 0;
229bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guy        }
230bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy        rc = vm->finalizeAsec(argv[2]);
2317ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy    } else if (!strcmp(argv[1], "destroy")) {
232bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy        if (argc < 3) {
233f86ef57f8bcd8ba43ce222ec6a8b4f67d3600640Romain Guy            cli->sendMsg(ResponseCode::CommandSyntaxError, "Usage: asec destroy <container-id> [force]", false);
234260e102162322958cf17dbd895cd6bd30dc87e32Romain Guy            return 0;
235f86ef57f8bcd8ba43ce222ec6a8b4f67d3600640Romain Guy        }
236f86ef57f8bcd8ba43ce222ec6a8b4f67d3600640Romain Guy        bool force = false;
237bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy        if (argc > 3 && !strcmp(argv[3], "force")) {
238d55a86120dd1e8ebcc6906c9ffd463f7460348daRomain Guy            force = true;
239d55a86120dd1e8ebcc6906c9ffd463f7460348daRomain Guy        }
240bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy        rc = vm->destroyAsec(argv[2], force);
241d55a86120dd1e8ebcc6906c9ffd463f7460348daRomain Guy    } else if (!strcmp(argv[1], "mount")) {
242d55a86120dd1e8ebcc6906c9ffd463f7460348daRomain Guy        if (argc != 5) {
2435cbbce535744b89df5ecea95de21ee3733298260Romain Guy            cli->sendMsg(ResponseCode::CommandSyntaxError,
244d55a86120dd1e8ebcc6906c9ffd463f7460348daRomain Guy                    "Usage: asec mount <namespace-id> <key> <ownerUid>", false);
245d55a86120dd1e8ebcc6906c9ffd463f7460348daRomain Guy            return 0;
2465cbbce535744b89df5ecea95de21ee3733298260Romain Guy        }
247d55a86120dd1e8ebcc6906c9ffd463f7460348daRomain Guy        rc = vm->mountAsec(argv[2], argv[3], atoi(argv[4]));
248dda570201ac851dd85af3861f7e575721d3345daRomain Guy    } else if (!strcmp(argv[1], "unmount")) {
249dda570201ac851dd85af3861f7e575721d3345daRomain Guy        if (argc < 3) {
250dda570201ac851dd85af3861f7e575721d3345daRomain Guy            cli->sendMsg(ResponseCode::CommandSyntaxError, "Usage: asec unmount <container-id> [force]", false);
251dda570201ac851dd85af3861f7e575721d3345daRomain Guy            return 0;
252dda570201ac851dd85af3861f7e575721d3345daRomain Guy        }
253d55a86120dd1e8ebcc6906c9ffd463f7460348daRomain Guy        bool force = false;
254d55a86120dd1e8ebcc6906c9ffd463f7460348daRomain Guy        if (argc > 3 && !strcmp(argv[3], "force")) {
255d55a86120dd1e8ebcc6906c9ffd463f7460348daRomain Guy            force = true;
2565cbbce535744b89df5ecea95de21ee3733298260Romain Guy        }
257d55a86120dd1e8ebcc6906c9ffd463f7460348daRomain Guy        rc = vm->unmountAsec(argv[2], force);
258079ba2c85b15e882629b8d188f5fbdb42f7f8eeaRomain Guy    } else if (!strcmp(argv[1], "rename")) {
259d55a86120dd1e8ebcc6906c9ffd463f7460348daRomain Guy        if (argc != 4) {
260bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy            cli->sendMsg(ResponseCode::CommandSyntaxError,
261dda570201ac851dd85af3861f7e575721d3345daRomain Guy                    "Usage: asec rename <old_id> <new_id>", false);
262dda570201ac851dd85af3861f7e575721d3345daRomain Guy            return 0;
263dda570201ac851dd85af3861f7e575721d3345daRomain Guy        }
264dda570201ac851dd85af3861f7e575721d3345daRomain Guy        rc = vm->renameAsec(argv[2], argv[3]);
265a979474f15b454c8e2963f239a3770e200bb227cRomain Guy    } else if (!strcmp(argv[1], "path")) {
266bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy        if (argc != 3) {
267dda570201ac851dd85af3861f7e575721d3345daRomain Guy            cli->sendMsg(ResponseCode::CommandSyntaxError, "Usage: asec path <container-id>", false);
268f18fd99b5c182329cd8936a9611f0103d8ece44aRomain Guy            return 0;
269f18fd99b5c182329cd8936a9611f0103d8ece44aRomain Guy        }
270dda570201ac851dd85af3861f7e575721d3345daRomain Guy        char path[255];
271dda570201ac851dd85af3861f7e575721d3345daRomain Guy
272bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guy        if (vm->getAsecMountPath(argv[2], path, sizeof(path))) {
273dda570201ac851dd85af3861f7e575721d3345daRomain Guy            cli->sendMsg(ResponseCode::OperationFailed, "Failed to get path", true);
274dda570201ac851dd85af3861f7e575721d3345daRomain Guy        } else {
275dda570201ac851dd85af3861f7e575721d3345daRomain Guy            cli->sendMsg(ResponseCode::AsecPathResult, path, false);
276dda570201ac851dd85af3861f7e575721d3345daRomain Guy        }
277dda570201ac851dd85af3861f7e575721d3345daRomain Guy        return 0;
278bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guy    } else {
279bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guy        cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown asec cmd", false);
280f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy    }
281bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy
282bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy    if (!rc) {
283bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy        cli->sendMsg(ResponseCode::CommandOkay, "asec operation succeeded", false);
284bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy    } else {
285bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy        rc = ResponseCode::convertFromErrno();
286d55a86120dd1e8ebcc6906c9ffd463f7460348daRomain Guy        cli->sendMsg(rc, "asec operation failed", true);
287d55a86120dd1e8ebcc6906c9ffd463f7460348daRomain Guy    }
288d55a86120dd1e8ebcc6906c9ffd463f7460348daRomain Guy
289d55a86120dd1e8ebcc6906c9ffd463f7460348daRomain Guy    return 0;
290d55a86120dd1e8ebcc6906c9ffd463f7460348daRomain Guy}
291d55a86120dd1e8ebcc6906c9ffd463f7460348daRomain Guy
292d55a86120dd1e8ebcc6906c9ffd463f7460348daRomain GuyCommandListener::XwarpCmd::XwarpCmd() :
293d55a86120dd1e8ebcc6906c9ffd463f7460348daRomain Guy                 VoldCommand("xwarp") {
294d55a86120dd1e8ebcc6906c9ffd463f7460348daRomain Guy}
295d55a86120dd1e8ebcc6906c9ffd463f7460348daRomain Guy
296d55a86120dd1e8ebcc6906c9ffd463f7460348daRomain Guyint CommandListener::XwarpCmd::runCommand(SocketClient *cli,
297d55a86120dd1e8ebcc6906c9ffd463f7460348daRomain Guy                                                      int argc, char **argv) {
298d55a86120dd1e8ebcc6906c9ffd463f7460348daRomain Guy    if (argc < 2) {
299d55a86120dd1e8ebcc6906c9ffd463f7460348daRomain Guy        cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing Argument", false);
300d55a86120dd1e8ebcc6906c9ffd463f7460348daRomain Guy        return 0;
301d55a86120dd1e8ebcc6906c9ffd463f7460348daRomain Guy    }
302d55a86120dd1e8ebcc6906c9ffd463f7460348daRomain Guy
303d55a86120dd1e8ebcc6906c9ffd463f7460348daRomain Guy    if (!strcmp(argv[1], "enable")) {
304d55a86120dd1e8ebcc6906c9ffd463f7460348daRomain Guy        if (Xwarp::enable()) {
305bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy            cli->sendMsg(ResponseCode::OperationFailed, "Failed to enable xwarp", true);
306bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy            return 0;
307bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy        }
308bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy
309bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy        cli->sendMsg(ResponseCode::CommandOkay, "Xwarp mirroring started", false);
310d55a86120dd1e8ebcc6906c9ffd463f7460348daRomain Guy    } else if (!strcmp(argv[1], "disable")) {
311d55a86120dd1e8ebcc6906c9ffd463f7460348daRomain Guy        if (Xwarp::disable()) {
312d55a86120dd1e8ebcc6906c9ffd463f7460348daRomain Guy            cli->sendMsg(ResponseCode::OperationFailed, "Failed to disable xwarp", true);
313bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy            return 0;
314d55a86120dd1e8ebcc6906c9ffd463f7460348daRomain Guy        }
315d55a86120dd1e8ebcc6906c9ffd463f7460348daRomain Guy
316d27977d1a91d5a6b3cc9fa7664ac7e835e7bd895Romain Guy        cli->sendMsg(ResponseCode::CommandOkay, "Xwarp disabled", false);
317dda570201ac851dd85af3861f7e575721d3345daRomain Guy    } else if (!strcmp(argv[1], "status")) {
318dda570201ac851dd85af3861f7e575721d3345daRomain Guy        char msg[255];
319f18fd99b5c182329cd8936a9611f0103d8ece44aRomain Guy        bool r;
320f18fd99b5c182329cd8936a9611f0103d8ece44aRomain Guy        unsigned mirrorPos, maxSize;
321dda570201ac851dd85af3861f7e575721d3345daRomain Guy
322f18fd99b5c182329cd8936a9611f0103d8ece44aRomain Guy        if (Xwarp::status(&r, &mirrorPos, &maxSize)) {
323f18fd99b5c182329cd8936a9611f0103d8ece44aRomain Guy            cli->sendMsg(ResponseCode::OperationFailed, "Failed to get xwarp status", true);
324f18fd99b5c182329cd8936a9611f0103d8ece44aRomain Guy            return 0;
325bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy        }
326bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy        snprintf(msg, sizeof(msg), "%s %u %u", (r ? "ready" : "not-ready"), mirrorPos, maxSize);
327f18fd99b5c182329cd8936a9611f0103d8ece44aRomain Guy        cli->sendMsg(ResponseCode::XwarpStatusResult, msg, false);
328f18fd99b5c182329cd8936a9611f0103d8ece44aRomain Guy    } else {
329f86ef57f8bcd8ba43ce222ec6a8b4f67d3600640Romain Guy        cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown storage cmd", false);
330f86ef57f8bcd8ba43ce222ec6a8b4f67d3600640Romain Guy    }
331f86ef57f8bcd8ba43ce222ec6a8b4f67d3600640Romain Guy
332f86ef57f8bcd8ba43ce222ec6a8b4f67d3600640Romain Guy    return 0;
333f86ef57f8bcd8ba43ce222ec6a8b4f67d3600640Romain Guy}
334f86ef57f8bcd8ba43ce222ec6a8b4f67d3600640Romain Guy
335dda570201ac851dd85af3861f7e575721d3345daRomain Guy