blob: 9a22a64e0304ef8e87056837256d16dfb65133b2 [file] [log] [blame]
San Mehatb78a32c2010-01-10 13:02:12 -08001/*
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 <stdio.h>
Olivier Bailly37dcda62010-11-16 10:41:53 -080018#include <stdlib.h>
San Mehatb78a32c2010-01-10 13:02:12 -080019#include <fcntl.h>
20#include <unistd.h>
21#include <errno.h>
22#include <string.h>
23
24#include <sys/types.h>
25#include <sys/ioctl.h>
26#include <sys/stat.h>
27
San Mehatd9a4e352010-03-12 13:32:47 -080028#include <linux/kdev_t.h>
29
San Mehatb78a32c2010-01-10 13:02:12 -080030#define LOG_TAG "Vold"
31
32#include <cutils/log.h>
33
San Mehatd9a4e352010-03-12 13:32:47 -080034#include <sysutils/SocketClient.h>
35
San Mehatb78a32c2010-01-10 13:02:12 -080036#include "Devmapper.h"
37
San Mehatd9a4e352010-03-12 13:32:47 -080038int Devmapper::dumpState(SocketClient *c) {
39
40 char *buffer = (char *) malloc(1024 * 64);
41 if (!buffer) {
San Mehat97ac40e2010-03-24 10:24:19 -070042 SLOGE("Error allocating memory (%s)", strerror(errno));
San Mehatd9a4e352010-03-12 13:32:47 -080043 return -1;
44 }
45 memset(buffer, 0, (1024 * 64));
46
47 char *buffer2 = (char *) malloc(4096);
48 if (!buffer2) {
San Mehat97ac40e2010-03-24 10:24:19 -070049 SLOGE("Error allocating memory (%s)", strerror(errno));
San Mehatd9a4e352010-03-12 13:32:47 -080050 free(buffer);
51 return -1;
52 }
53
54 int fd;
55 if ((fd = open("/dev/device-mapper", O_RDWR)) < 0) {
San Mehat97ac40e2010-03-24 10:24:19 -070056 SLOGE("Error opening devmapper (%s)", strerror(errno));
San Mehatd9a4e352010-03-12 13:32:47 -080057 free(buffer);
58 free(buffer2);
59 return -1;
60 }
61
62 struct dm_ioctl *io = (struct dm_ioctl *) buffer;
63 ioctlInit(io, (1024 * 64), NULL, 0);
64
65 if (ioctl(fd, DM_LIST_DEVICES, io)) {
San Mehat97ac40e2010-03-24 10:24:19 -070066 SLOGE("DM_LIST_DEVICES ioctl failed (%s)", strerror(errno));
San Mehatd9a4e352010-03-12 13:32:47 -080067 free(buffer);
68 free(buffer2);
69 close(fd);
70 return -1;
71 }
72
73 struct dm_name_list *n = (struct dm_name_list *) (((char *) buffer) + io->data_start);
74 if (!n->dev) {
75 free(buffer);
76 free(buffer2);
77 close(fd);
78 return 0;
79 }
80
81 unsigned nxt = 0;
82 do {
83 n = (struct dm_name_list *) (((char *) n) + nxt);
84
85 memset(buffer2, 0, 4096);
86 struct dm_ioctl *io2 = (struct dm_ioctl *) buffer2;
87 ioctlInit(io2, 4096, n->name, 0);
88 if (ioctl(fd, DM_DEV_STATUS, io2)) {
89 if (errno != ENXIO) {
San Mehat97ac40e2010-03-24 10:24:19 -070090 SLOGE("DM_DEV_STATUS ioctl failed (%s)", strerror(errno));
San Mehatd9a4e352010-03-12 13:32:47 -080091 }
92 io2 = NULL;
93 }
94
95 char *tmp;
96 if (!io2) {
97 asprintf(&tmp, "%s %llu:%llu (no status available)", n->name, MAJOR(n->dev), MINOR(n->dev));
98 } else {
99 asprintf(&tmp, "%s %llu:%llu %d %d 0x%.8x %llu:%llu", n->name, MAJOR(n->dev),
100 MINOR(n->dev), io2->target_count, io2->open_count, io2->flags, MAJOR(io2->dev),
101 MINOR(io2->dev));
102 }
103 c->sendMsg(0, tmp, false);
104 free(tmp);
105 nxt = n->next;
106 } while (nxt);
107
108 free(buffer);
109 free(buffer2);
110 close(fd);
111 return 0;
112}
113
San Mehatb78a32c2010-01-10 13:02:12 -0800114void Devmapper::ioctlInit(struct dm_ioctl *io, size_t dataSize,
115 const char *name, unsigned flags) {
116 memset(io, 0, dataSize);
117 io->data_size = dataSize;
118 io->data_start = sizeof(struct dm_ioctl);
119 io->version[0] = 4;
120 io->version[1] = 0;
121 io->version[2] = 0;
122 io->flags = flags;
San Mehatd9a4e352010-03-12 13:32:47 -0800123 if (name) {
124 strncpy(io->name, name, sizeof(io->name));
125 }
San Mehatb78a32c2010-01-10 13:02:12 -0800126}
127
128int Devmapper::lookupActive(const char *name, char *ubuffer, size_t len) {
129 char *buffer = (char *) malloc(4096);
130 if (!buffer) {
San Mehat97ac40e2010-03-24 10:24:19 -0700131 SLOGE("Error allocating memory (%s)", strerror(errno));
San Mehatb78a32c2010-01-10 13:02:12 -0800132 return -1;
133 }
134
135 int fd;
136 if ((fd = open("/dev/device-mapper", O_RDWR)) < 0) {
San Mehat97ac40e2010-03-24 10:24:19 -0700137 SLOGE("Error opening devmapper (%s)", strerror(errno));
San Mehatb78a32c2010-01-10 13:02:12 -0800138 free(buffer);
139 return -1;
140 }
141
142 struct dm_ioctl *io = (struct dm_ioctl *) buffer;
143
144 ioctlInit(io, 4096, name, 0);
145 if (ioctl(fd, DM_DEV_STATUS, io)) {
San Mehat8b8f71b2010-01-11 09:17:25 -0800146 if (errno != ENXIO) {
San Mehat97ac40e2010-03-24 10:24:19 -0700147 SLOGE("DM_DEV_STATUS ioctl failed for lookup (%s)", strerror(errno));
San Mehatb78a32c2010-01-10 13:02:12 -0800148 }
149 free(buffer);
150 close(fd);
151 return -1;
152 }
153 close(fd);
154
155 unsigned minor = (io->dev & 0xff) | ((io->dev >> 12) & 0xfff00);
156 free(buffer);
San Mehatb78a32c2010-01-10 13:02:12 -0800157 snprintf(ubuffer, len, "/dev/block/dm-%u", minor);
158 return 0;
159}
160
San Mehat8b8f71b2010-01-11 09:17:25 -0800161int Devmapper::create(const char *name, const char *loopFile, const char *key,
162 unsigned int numSectors, char *ubuffer, size_t len) {
San Mehatb78a32c2010-01-10 13:02:12 -0800163 char *buffer = (char *) malloc(4096);
164 if (!buffer) {
San Mehat97ac40e2010-03-24 10:24:19 -0700165 SLOGE("Error allocating memory (%s)", strerror(errno));
San Mehatb78a32c2010-01-10 13:02:12 -0800166 return -1;
167 }
168
169 int fd;
170 if ((fd = open("/dev/device-mapper", O_RDWR)) < 0) {
San Mehat97ac40e2010-03-24 10:24:19 -0700171 SLOGE("Error opening devmapper (%s)", strerror(errno));
San Mehatb78a32c2010-01-10 13:02:12 -0800172 free(buffer);
173 return -1;
174 }
175
176 struct dm_ioctl *io = (struct dm_ioctl *) buffer;
177
178 // Create the DM device
179 ioctlInit(io, 4096, name, 0);
180
181 if (ioctl(fd, DM_DEV_CREATE, io)) {
San Mehat97ac40e2010-03-24 10:24:19 -0700182 SLOGE("Error creating device mapping (%s)", strerror(errno));
San Mehatb78a32c2010-01-10 13:02:12 -0800183 free(buffer);
184 close(fd);
185 return -1;
186 }
187
188 // Set the legacy geometry
189 ioctlInit(io, 4096, name, 0);
190
191 char *geoParams = buffer + sizeof(struct dm_ioctl);
192 // bps=512 spc=8 res=32 nft=2 sec=8190 mid=0xf0 spt=63 hds=64 hid=0 bspf=8 rdcl=2 infs=1 bkbs=2
193 strcpy(geoParams, "0 64 63 0");
194 geoParams += strlen(geoParams) + 1;
195 geoParams = (char *) _align(geoParams, 8);
196 if (ioctl(fd, DM_DEV_SET_GEOMETRY, io)) {
San Mehat97ac40e2010-03-24 10:24:19 -0700197 SLOGE("Error setting device geometry (%s)", strerror(errno));
San Mehatb78a32c2010-01-10 13:02:12 -0800198 free(buffer);
199 close(fd);
200 return -1;
201 }
202
203 // Retrieve the device number we were allocated
204 ioctlInit(io, 4096, name, 0);
205 if (ioctl(fd, DM_DEV_STATUS, io)) {
San Mehat97ac40e2010-03-24 10:24:19 -0700206 SLOGE("Error retrieving devmapper status (%s)", strerror(errno));
San Mehatb78a32c2010-01-10 13:02:12 -0800207 free(buffer);
208 close(fd);
209 return -1;
210 }
211
212 unsigned minor = (io->dev & 0xff) | ((io->dev >> 12) & 0xfff00);
San Mehatb78a32c2010-01-10 13:02:12 -0800213 snprintf(ubuffer, len, "/dev/block/dm-%u", minor);
214
215 // Load the table
216 struct dm_target_spec *tgt;
217 tgt = (struct dm_target_spec *) &buffer[sizeof(struct dm_ioctl)];
218
219 ioctlInit(io, 4096, name, DM_STATUS_TABLE_FLAG);
220 io->target_count = 1;
221 tgt->status = 0;
San Mehatfcf24fe2010-03-03 12:37:32 -0800222
San Mehatb78a32c2010-01-10 13:02:12 -0800223 tgt->sector_start = 0;
San Mehat8b8f71b2010-01-11 09:17:25 -0800224 tgt->length = numSectors;
San Mehatfcf24fe2010-03-03 12:37:32 -0800225
San Mehatb78a32c2010-01-10 13:02:12 -0800226 strcpy(tgt->target_type, "crypt");
227
228 char *cryptParams = buffer + sizeof(struct dm_ioctl) + sizeof(struct dm_target_spec);
229 sprintf(cryptParams, "twofish %s 0 %s 0", key, loopFile);
230 cryptParams += strlen(cryptParams) + 1;
231 cryptParams = (char *) _align(cryptParams, 8);
232 tgt->next = cryptParams - buffer;
233
234 if (ioctl(fd, DM_TABLE_LOAD, io)) {
San Mehat97ac40e2010-03-24 10:24:19 -0700235 SLOGE("Error loading mapping table (%s)", strerror(errno));
San Mehatb78a32c2010-01-10 13:02:12 -0800236 free(buffer);
237 close(fd);
238 return -1;
239 }
240
241 // Resume the new table
242 ioctlInit(io, 4096, name, 0);
243
244 if (ioctl(fd, DM_DEV_SUSPEND, io)) {
San Mehat97ac40e2010-03-24 10:24:19 -0700245 SLOGE("Error Resuming (%s)", strerror(errno));
San Mehatb78a32c2010-01-10 13:02:12 -0800246 free(buffer);
247 close(fd);
248 return -1;
249 }
250
251 free(buffer);
252
San Mehat8c940ef2010-02-13 14:19:53 -0800253 close(fd);
San Mehatb78a32c2010-01-10 13:02:12 -0800254 return 0;
255}
256
257int Devmapper::destroy(const char *name) {
258 char *buffer = (char *) malloc(4096);
259 if (!buffer) {
San Mehat97ac40e2010-03-24 10:24:19 -0700260 SLOGE("Error allocating memory (%s)", strerror(errno));
San Mehatb78a32c2010-01-10 13:02:12 -0800261 return -1;
262 }
263
264 int fd;
265 if ((fd = open("/dev/device-mapper", O_RDWR)) < 0) {
San Mehat97ac40e2010-03-24 10:24:19 -0700266 SLOGE("Error opening devmapper (%s)", strerror(errno));
San Mehatb78a32c2010-01-10 13:02:12 -0800267 free(buffer);
268 return -1;
269 }
270
271 struct dm_ioctl *io = (struct dm_ioctl *) buffer;
272
273 // Create the DM device
274 ioctlInit(io, 4096, name, 0);
275
276 if (ioctl(fd, DM_DEV_REMOVE, io)) {
San Mehat0586d542010-01-12 15:38:59 -0800277 if (errno != ENXIO) {
San Mehat97ac40e2010-03-24 10:24:19 -0700278 SLOGE("Error destroying device mapping (%s)", strerror(errno));
San Mehat0586d542010-01-12 15:38:59 -0800279 }
San Mehatb78a32c2010-01-10 13:02:12 -0800280 free(buffer);
281 close(fd);
282 return -1;
283 }
284
285 free(buffer);
286 close(fd);
287 return 0;
288}
289
290void *Devmapper::_align(void *ptr, unsigned int a)
291{
292 register unsigned long agn = --a;
293
294 return (void *) (((unsigned long) ptr + agn) & ~agn);
295}