CommandListener.cpp revision 048b0801fcd6fcfbb8fa812284c751181e4821b8
1/*
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>
19#include <sys/types.h>
20#include <netinet/in.h>
21#include <arpa/inet.h>
22#include <dirent.h>
23#include <errno.h>
24
25#define LOG_TAG "CommandListener"
26#include <cutils/log.h>
27
28#include <sysutils/SocketClient.h>
29
30#include "CommandListener.h"
31#include "VolumeManager.h"
32#include "ResponseCode.h"
33
34CommandListener::CommandListener() :
35                 FrameworkListener("vold") {
36    registerCmd(new ListVolumesCmd());
37    registerCmd(new MountCmd());
38    registerCmd(new UnmountCmd());
39    registerCmd(new ShareCmd());
40    registerCmd(new UnshareCmd());
41    registerCmd(new ShareAvailableCmd());
42    registerCmd(new SimulateCmd());
43    registerCmd(new FormatCmd());
44    registerCmd(new CreateAsecCmd());
45    registerCmd(new FinalizeAsecCmd());
46    registerCmd(new DestroyAsecCmd());
47    registerCmd(new MountAsecCmd());
48    registerCmd(new UnmountAsecCmd());
49    registerCmd(new RenameAsecCmd());
50    registerCmd(new ListAsecCmd());
51    registerCmd(new AsecPathCmd());
52}
53
54CommandListener::ListVolumesCmd::ListVolumesCmd() :
55                 VoldCommand("list_volumes") {
56}
57
58int CommandListener::ListVolumesCmd::runCommand(SocketClient *cli,
59                                                      int argc, char **argv) {
60    return VolumeManager::Instance()->listVolumes(cli);
61}
62
63CommandListener::MountCmd::MountCmd() :
64                 VoldCommand("mount") {
65}
66
67int CommandListener::MountCmd::runCommand(SocketClient *cli,
68                                                      int argc, char **argv) {
69    /* Synchronously mount a volume */
70    if (VolumeManager::Instance()->mountVolume(argv[1])) {
71        cli->sendMsg(ResponseCode::OperationFailed, "Failed to mount volume.", true);
72    } else {
73        cli->sendMsg(ResponseCode::CommandOkay, "Volume mounted.", false);
74    }
75
76    return 0;
77}
78
79CommandListener::UnmountCmd::UnmountCmd() :
80                 VoldCommand("unmount") {
81}
82
83int CommandListener::UnmountCmd::runCommand(SocketClient *cli,
84                                                      int argc, char **argv) {
85    /* Synchronously unmount a volume */
86    if (VolumeManager::Instance()->unmountVolume(argv[1])) {
87        cli->sendMsg(ResponseCode::OperationFailed, "Failed to unmount volume.", true);
88    } else {
89        cli->sendMsg(ResponseCode::CommandOkay, "Volume unmounted.", false);
90    }
91
92    return 0;
93}
94
95CommandListener::ShareCmd::ShareCmd() :
96                 VoldCommand("share") {
97}
98
99int CommandListener::ShareCmd::runCommand(SocketClient *cli,
100                                                      int argc, char **argv) {
101    if (VolumeManager::Instance()->shareVolume(argv[1], argv[2])) {
102        cli->sendMsg(ResponseCode::OperationFailed, "Failed to share volume.", true);
103    } else {
104        cli->sendMsg(ResponseCode::CommandOkay, "Volume shared.", false);
105    }
106
107    return 0;
108}
109
110CommandListener::UnshareCmd::UnshareCmd() :
111                 VoldCommand("unshare") {
112}
113
114int CommandListener::UnshareCmd::runCommand(SocketClient *cli,
115                                                      int argc, char **argv) {
116    if (VolumeManager::Instance()->unshareVolume(argv[1], argv[2])) {
117        cli->sendMsg(ResponseCode::OperationFailed, "Failed to unshare volume.", true);
118    } else {
119        cli->sendMsg(ResponseCode::CommandOkay, "Volume unshared.", false);
120    }
121
122    return 0;
123}
124
125CommandListener::ShareAvailableCmd::ShareAvailableCmd() :
126                 VoldCommand("share_available") {
127}
128
129int CommandListener::ShareAvailableCmd::runCommand(SocketClient *cli,
130                                                      int argc, char **argv) {
131    bool avail = false;
132
133    if (VolumeManager::Instance()->shareAvailable(argv[1], &avail)) {
134        cli->sendMsg(ResponseCode::OperationFailed,
135                     "Failed to determine share availability", true);
136    } else {
137        cli->sendMsg(ResponseCode::ShareAvailabilityResult,
138                     (avail ? "Share available" : "Share unavailable"),
139                     false);
140    }
141    return 0;
142}
143
144CommandListener::SimulateCmd::SimulateCmd() :
145                 VoldCommand("simulate") {
146}
147
148int CommandListener::SimulateCmd::runCommand(SocketClient *cli,
149                                            int argc, char **argv) {
150    if (VolumeManager::Instance()->simulate(argv[1], argv[2])) {
151        cli->sendMsg(ResponseCode::OperationFailed, "Failed to execute.", true);
152    } else {
153        cli->sendMsg(ResponseCode::CommandOkay, "Simulation executed.", false);
154    }
155
156    return 0;
157}
158
159CommandListener::FormatCmd::FormatCmd() :
160                 VoldCommand("format") {
161}
162
163int CommandListener::FormatCmd::runCommand(SocketClient *cli,
164                                            int argc, char **argv) {
165    if (VolumeManager::Instance()->formatVolume(argv[1])) {
166        cli->sendMsg(ResponseCode::OperationFailed, "Failed to format", true);
167    } else {
168        cli->sendMsg(ResponseCode::CommandOkay, "Volume formatted.", false);
169    }
170
171    return 0;
172}
173
174CommandListener::CreateAsecCmd::CreateAsecCmd() :
175                 VoldCommand("create_asec") {
176}
177
178int CommandListener::CreateAsecCmd::runCommand(SocketClient *cli,
179                                            int argc, char **argv) {
180    if (argc != 6) {
181        cli->sendMsg(ResponseCode::CommandSyntaxError,
182                     "Usage: create_asec <namespace-id> <size_mb> <fstype> <key> <ownerUid>",
183                     false);
184        return 0;
185    }
186
187    unsigned int numSectors = (atoi(argv[2]) * (1024 * 1024)) / 512;
188    if (VolumeManager::Instance()->createAsec(argv[1], numSectors,
189                                              argv[3], argv[4],
190                                              atoi(argv[5]))) {
191        cli->sendMsg(ResponseCode::OperationFailed, "Container creation failed", true);
192    } else {
193        cli->sendMsg(ResponseCode::CommandOkay, "Container created", false);
194    }
195
196    return 0;
197}
198
199CommandListener::FinalizeAsecCmd::FinalizeAsecCmd() :
200                 VoldCommand("finalize_asec") {
201}
202
203int CommandListener::FinalizeAsecCmd::runCommand(SocketClient *cli,
204                                            int argc, char **argv) {
205    if (argc != 2) {
206        cli->sendMsg(ResponseCode::CommandSyntaxError,
207                     "Usage: finalize_asec <namespace-id>", false);
208        return 0;
209    }
210
211    if (VolumeManager::Instance()->finalizeAsec(argv[1])) {
212        cli->sendMsg(ResponseCode::OperationFailed, "Container finalize failed", true);
213    } else {
214        cli->sendMsg(ResponseCode::CommandOkay, "Container finalized", false);
215    }
216    return 0;
217}
218
219CommandListener::DestroyAsecCmd::DestroyAsecCmd() :
220                 VoldCommand("destroy_asec") {
221}
222
223int CommandListener::DestroyAsecCmd::runCommand(SocketClient *cli,
224                                            int argc, char **argv) {
225    if (argc != 2) {
226        cli->sendMsg(ResponseCode::CommandSyntaxError,
227                     "Usage: destroy_asec <namespace-id>", false);
228        return 0;
229    }
230
231    if (VolumeManager::Instance()->destroyAsec(argv[1])) {
232        cli->sendMsg(ResponseCode::OperationFailed, "Destroy failed", true);
233    } else {
234        cli->sendMsg(ResponseCode::CommandOkay, "Container Destroyed", false);
235    }
236    return 0;
237}
238
239CommandListener::MountAsecCmd::MountAsecCmd() :
240                 VoldCommand("mount_asec") {
241}
242
243int CommandListener::MountAsecCmd::runCommand(SocketClient *cli,
244                                            int argc, char **argv) {
245    if (argc != 4) {
246        cli->sendMsg(ResponseCode::CommandSyntaxError,
247                     "Usage: mount_asec <namespace-id> <key> <ownerUid>", false);
248        return 0;
249    }
250
251    if (VolumeManager::Instance()->mountAsec(argv[1], argv[2], atoi(argv[3]))) {
252        cli->sendMsg(ResponseCode::OperationFailed, "Mount failed", true);
253    } else {
254        cli->sendMsg(ResponseCode::CommandOkay, "Mount succeeded", false);
255    }
256    return 0;
257}
258
259CommandListener::UnmountAsecCmd::UnmountAsecCmd() :
260                 VoldCommand("unmount_asec") {
261}
262
263int CommandListener::UnmountAsecCmd::runCommand(SocketClient *cli,
264                                            int argc, char **argv) {
265    if (argc != 2) {
266        cli->sendMsg(ResponseCode::CommandSyntaxError,
267                     "Usage: unmount_asec <namespace-id>", false);
268        return 0;
269    }
270
271    if (VolumeManager::Instance()->unmountAsec(argv[1])) {
272        cli->sendMsg(ResponseCode::OperationFailed, "Unmount failed", true);
273    } else {
274        cli->sendMsg(ResponseCode::CommandOkay, "Unmount succeeded", false);
275    }
276    return 0;
277}
278
279CommandListener::RenameAsecCmd::RenameAsecCmd() :
280                 VoldCommand("rename_asec") {
281}
282
283int CommandListener::RenameAsecCmd::runCommand(SocketClient *cli,
284                                            int argc, char **argv) {
285    if (argc != 3) {
286        cli->sendMsg(ResponseCode::CommandSyntaxError,
287                     "Usage: rename_asec <id1> <id2>", false);
288        return 0;
289    }
290
291    if (VolumeManager::Instance()->renameAsec(argv[1], argv[2])) {
292        cli->sendMsg(ResponseCode::OperationFailed, "Rename failed", true);
293    } else {
294        cli->sendMsg(ResponseCode::CommandOkay, "Rename succeeded", false);
295    }
296    return 0;
297}
298
299CommandListener::ListAsecCmd::ListAsecCmd() :
300                 VoldCommand("list_asec") {
301
302}
303
304int CommandListener::ListAsecCmd::runCommand(SocketClient *cli,
305                                            int argc, char **argv) {
306    DIR *d = opendir("/sdcard/android_secure");
307
308    if (!d) {
309        cli->sendMsg(ResponseCode::OperationFailed, "Failed to open asec dir", true);
310        return 0;
311    }
312
313    struct dirent *dent;
314    while ((dent = readdir(d))) {
315        if (dent->d_name[0] == '.')
316            continue;
317        if (!strcmp(&dent->d_name[strlen(dent->d_name)-5], ".asec")) {
318            char id[255];
319            memset(id, 0, sizeof(id));
320            strncpy(id, dent->d_name, strlen(dent->d_name) -5);
321            cli->sendMsg(ResponseCode::AsecListResult, id, false);
322        }
323    }
324    closedir(d);
325    cli->sendMsg(ResponseCode::CommandOkay, "ASEC listing complete", false);
326
327    return 0;
328}
329
330CommandListener::AsecPathCmd::AsecPathCmd() :
331                 VoldCommand("asec_path") {
332}
333
334int CommandListener::AsecPathCmd::runCommand(SocketClient *cli,
335                                            int argc, char **argv) {
336    if (argc != 2) {
337        cli->sendMsg(ResponseCode::CommandSyntaxError,
338                     "Usage: asec_path <namespace-id>", false);
339        return 0;
340    }
341
342    char mountPath[255];
343
344    if (VolumeManager::Instance()->getAsecMountPath(argv[1], mountPath,
345                                                    sizeof(mountPath))) {
346        cli->sendMsg(ResponseCode::OperationFailed, "Failed to get mount path", true);
347    } else {
348        cli->sendMsg(ResponseCode::AsecPathResult, mountPath, false);
349    }
350
351    return 0;
352}
353