• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 <stdio.h>
18  #include <fcntl.h>
19  #include <unistd.h>
20  #include <errno.h>
21  #include <string.h>
22  
23  #include <sys/types.h>
24  #include <sys/ioctl.h>
25  #include <sys/stat.h>
26  
27  #include <linux/kdev_t.h>
28  
29  #define LOG_TAG "Vold"
30  
31  #include <cutils/log.h>
32  
33  #include <sysutils/SocketClient.h>
34  
35  #include "Devmapper.h"
36  
dumpState(SocketClient * c)37  int Devmapper::dumpState(SocketClient *c) {
38  
39      char *buffer = (char *) malloc(1024 * 64);
40      if (!buffer) {
41          SLOGE("Error allocating memory (%s)", strerror(errno));
42          return -1;
43      }
44      memset(buffer, 0, (1024 * 64));
45  
46      char *buffer2 = (char *) malloc(4096);
47      if (!buffer2) {
48          SLOGE("Error allocating memory (%s)", strerror(errno));
49          free(buffer);
50          return -1;
51      }
52  
53      int fd;
54      if ((fd = open("/dev/device-mapper", O_RDWR)) < 0) {
55          SLOGE("Error opening devmapper (%s)", strerror(errno));
56          free(buffer);
57          free(buffer2);
58          return -1;
59      }
60  
61      struct dm_ioctl *io = (struct dm_ioctl *) buffer;
62      ioctlInit(io, (1024 * 64), NULL, 0);
63  
64      if (ioctl(fd, DM_LIST_DEVICES, io)) {
65          SLOGE("DM_LIST_DEVICES ioctl failed (%s)", strerror(errno));
66          free(buffer);
67          free(buffer2);
68          close(fd);
69          return -1;
70      }
71  
72      struct dm_name_list *n = (struct dm_name_list *) (((char *) buffer) + io->data_start);
73      if (!n->dev) {
74          free(buffer);
75          free(buffer2);
76          close(fd);
77          return 0;
78      }
79  
80      unsigned nxt = 0;
81      do {
82          n = (struct dm_name_list *) (((char *) n) + nxt);
83  
84          memset(buffer2, 0, 4096);
85          struct dm_ioctl *io2 = (struct dm_ioctl *) buffer2;
86          ioctlInit(io2, 4096, n->name, 0);
87          if (ioctl(fd, DM_DEV_STATUS, io2)) {
88              if (errno != ENXIO) {
89                  SLOGE("DM_DEV_STATUS ioctl failed (%s)", strerror(errno));
90              }
91              io2 = NULL;
92          }
93  
94          char *tmp;
95          if (!io2) {
96              asprintf(&tmp, "%s %llu:%llu (no status available)", n->name, MAJOR(n->dev), MINOR(n->dev));
97          } else {
98              asprintf(&tmp, "%s %llu:%llu %d %d 0x%.8x %llu:%llu", n->name, MAJOR(n->dev),
99                      MINOR(n->dev), io2->target_count, io2->open_count, io2->flags, MAJOR(io2->dev),
100                              MINOR(io2->dev));
101          }
102          c->sendMsg(0, tmp, false);
103          free(tmp);
104          nxt = n->next;
105      } while (nxt);
106  
107      free(buffer);
108      free(buffer2);
109      close(fd);
110      return 0;
111  }
112  
ioctlInit(struct dm_ioctl * io,size_t dataSize,const char * name,unsigned flags)113  void Devmapper::ioctlInit(struct dm_ioctl *io, size_t dataSize,
114                            const char *name, unsigned flags) {
115      memset(io, 0, dataSize);
116      io->data_size = dataSize;
117      io->data_start = sizeof(struct dm_ioctl);
118      io->version[0] = 4;
119      io->version[1] = 0;
120      io->version[2] = 0;
121      io->flags = flags;
122      if (name) {
123          strncpy(io->name, name, sizeof(io->name));
124      }
125  }
126  
lookupActive(const char * name,char * ubuffer,size_t len)127  int Devmapper::lookupActive(const char *name, char *ubuffer, size_t len) {
128      char *buffer = (char *) malloc(4096);
129      if (!buffer) {
130          SLOGE("Error allocating memory (%s)", strerror(errno));
131          return -1;
132      }
133  
134      int fd;
135      if ((fd = open("/dev/device-mapper", O_RDWR)) < 0) {
136          SLOGE("Error opening devmapper (%s)", strerror(errno));
137          free(buffer);
138          return -1;
139      }
140  
141      struct dm_ioctl *io = (struct dm_ioctl *) buffer;
142  
143      ioctlInit(io, 4096, name, 0);
144      if (ioctl(fd, DM_DEV_STATUS, io)) {
145          if (errno != ENXIO) {
146              SLOGE("DM_DEV_STATUS ioctl failed for lookup (%s)", strerror(errno));
147          }
148          free(buffer);
149          close(fd);
150          return -1;
151      }
152      close(fd);
153  
154      unsigned minor = (io->dev & 0xff) | ((io->dev >> 12) & 0xfff00);
155      free(buffer);
156      snprintf(ubuffer, len, "/dev/block/dm-%u", minor);
157      return 0;
158  }
159  
create(const char * name,const char * loopFile,const char * key,unsigned int numSectors,char * ubuffer,size_t len)160  int Devmapper::create(const char *name, const char *loopFile, const char *key,
161                        unsigned int numSectors, char *ubuffer, size_t len) {
162      char *buffer = (char *) malloc(4096);
163      if (!buffer) {
164          SLOGE("Error allocating memory (%s)", strerror(errno));
165          return -1;
166      }
167  
168      int fd;
169      if ((fd = open("/dev/device-mapper", O_RDWR)) < 0) {
170          SLOGE("Error opening devmapper (%s)", strerror(errno));
171          free(buffer);
172          return -1;
173      }
174  
175      struct dm_ioctl *io = (struct dm_ioctl *) buffer;
176  
177      // Create the DM device
178      ioctlInit(io, 4096, name, 0);
179  
180      if (ioctl(fd, DM_DEV_CREATE, io)) {
181          SLOGE("Error creating device mapping (%s)", strerror(errno));
182          free(buffer);
183          close(fd);
184          return -1;
185      }
186  
187      // Set the legacy geometry
188      ioctlInit(io, 4096, name, 0);
189  
190      char *geoParams = buffer + sizeof(struct dm_ioctl);
191      // 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
192      strcpy(geoParams, "0 64 63 0");
193      geoParams += strlen(geoParams) + 1;
194      geoParams = (char *) _align(geoParams, 8);
195      if (ioctl(fd, DM_DEV_SET_GEOMETRY, io)) {
196          SLOGE("Error setting device geometry (%s)", strerror(errno));
197          free(buffer);
198          close(fd);
199          return -1;
200      }
201  
202      // Retrieve the device number we were allocated
203      ioctlInit(io, 4096, name, 0);
204      if (ioctl(fd, DM_DEV_STATUS, io)) {
205          SLOGE("Error retrieving devmapper status (%s)", strerror(errno));
206          free(buffer);
207          close(fd);
208          return -1;
209      }
210  
211      unsigned minor = (io->dev & 0xff) | ((io->dev >> 12) & 0xfff00);
212      snprintf(ubuffer, len, "/dev/block/dm-%u", minor);
213  
214      // Load the table
215      struct dm_target_spec *tgt;
216      tgt = (struct dm_target_spec *) &buffer[sizeof(struct dm_ioctl)];
217  
218      ioctlInit(io, 4096, name, DM_STATUS_TABLE_FLAG);
219      io->target_count = 1;
220      tgt->status = 0;
221  
222      tgt->sector_start = 0;
223      tgt->length = numSectors;
224  
225      strcpy(tgt->target_type, "crypt");
226  
227      char *cryptParams = buffer + sizeof(struct dm_ioctl) + sizeof(struct dm_target_spec);
228      sprintf(cryptParams, "twofish %s 0 %s 0", key, loopFile);
229      cryptParams += strlen(cryptParams) + 1;
230      cryptParams = (char *) _align(cryptParams, 8);
231      tgt->next = cryptParams - buffer;
232  
233      if (ioctl(fd, DM_TABLE_LOAD, io)) {
234          SLOGE("Error loading mapping table (%s)", strerror(errno));
235          free(buffer);
236          close(fd);
237          return -1;
238      }
239  
240      // Resume the new table
241      ioctlInit(io, 4096, name, 0);
242  
243      if (ioctl(fd, DM_DEV_SUSPEND, io)) {
244          SLOGE("Error Resuming (%s)", strerror(errno));
245          free(buffer);
246          close(fd);
247          return -1;
248      }
249  
250      free(buffer);
251  
252      close(fd);
253      return 0;
254  }
255  
destroy(const char * name)256  int Devmapper::destroy(const char *name) {
257      char *buffer = (char *) malloc(4096);
258      if (!buffer) {
259          SLOGE("Error allocating memory (%s)", strerror(errno));
260          return -1;
261      }
262  
263      int fd;
264      if ((fd = open("/dev/device-mapper", O_RDWR)) < 0) {
265          SLOGE("Error opening devmapper (%s)", strerror(errno));
266          free(buffer);
267          return -1;
268      }
269  
270      struct dm_ioctl *io = (struct dm_ioctl *) buffer;
271  
272      // Create the DM device
273      ioctlInit(io, 4096, name, 0);
274  
275      if (ioctl(fd, DM_DEV_REMOVE, io)) {
276          if (errno != ENXIO) {
277              SLOGE("Error destroying device mapping (%s)", strerror(errno));
278          }
279          free(buffer);
280          close(fd);
281          return -1;
282      }
283  
284      free(buffer);
285      close(fd);
286      return 0;
287  }
288  
_align(void * ptr,unsigned int a)289  void *Devmapper::_align(void *ptr, unsigned int a)
290  {
291          register unsigned long agn = --a;
292  
293          return (void *) (((unsigned long) ptr + agn) & ~agn);
294  }
295  
296