1b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat/*
2b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat * Copyright (C) 2008 The Android Open Source Project
3b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat *
4b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat * Licensed under the Apache License, Version 2.0 (the "License");
5b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat * you may not use this file except in compliance with the License.
6b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat * You may obtain a copy of the License at
7b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat *
8b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat *      http://www.apache.org/licenses/LICENSE-2.0
9b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat *
10b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat * Unless required by applicable law or agreed to in writing, software
11b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat * distributed under the License is distributed on an "AS IS" BASIS,
12b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat * See the License for the specific language governing permissions and
14b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat * limitations under the License.
15b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat */
16b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat
17b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat#include <stdio.h>
1837dcda68d334f70e1f7f69a9817def65fe3ee717Olivier Bailly#include <stdlib.h>
19b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat#include <fcntl.h>
20b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat#include <unistd.h>
21b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat#include <errno.h>
22b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat#include <string.h>
23092aa1c585fedd9e169eece41b8a471f1739908aPeter Bohm#include <stdlib.h>
24b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat
25b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat#include <sys/types.h>
26b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat#include <sys/ioctl.h>
27b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat#include <sys/stat.h>
28b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat
29d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat#include <linux/kdev_t.h>
30d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat
31b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat#define LOG_TAG "Vold"
32b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat
33b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat#include <cutils/log.h>
34b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat
35d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat#include <sysutils/SocketClient.h>
36d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat
37b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat#include "Devmapper.h"
38b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat
39092aa1c585fedd9e169eece41b8a471f1739908aPeter Bohm#define DEVMAPPER_BUFFER_SIZE 4096
40092aa1c585fedd9e169eece41b8a471f1739908aPeter Bohm
41d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehatint Devmapper::dumpState(SocketClient *c) {
42d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat
43d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat    char *buffer = (char *) malloc(1024 * 64);
44d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat    if (!buffer) {
4597ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat        SLOGE("Error allocating memory (%s)", strerror(errno));
46d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat        return -1;
47d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat    }
48d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat    memset(buffer, 0, (1024 * 64));
49d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat
50092aa1c585fedd9e169eece41b8a471f1739908aPeter Bohm    char *buffer2 = (char *) malloc(DEVMAPPER_BUFFER_SIZE);
51d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat    if (!buffer2) {
5297ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat        SLOGE("Error allocating memory (%s)", strerror(errno));
53d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat        free(buffer);
54d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat        return -1;
55d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat    }
56d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat
57d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat    int fd;
58d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat    if ((fd = open("/dev/device-mapper", O_RDWR)) < 0) {
5997ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat        SLOGE("Error opening devmapper (%s)", strerror(errno));
60d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat        free(buffer);
61d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat        free(buffer2);
62d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat        return -1;
63d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat    }
64d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat
65d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat    struct dm_ioctl *io = (struct dm_ioctl *) buffer;
66d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat    ioctlInit(io, (1024 * 64), NULL, 0);
67d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat
68d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat    if (ioctl(fd, DM_LIST_DEVICES, io)) {
6997ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat        SLOGE("DM_LIST_DEVICES ioctl failed (%s)", strerror(errno));
70d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat        free(buffer);
71d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat        free(buffer2);
72d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat        close(fd);
73d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat        return -1;
74d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat    }
75d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat
76d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat    struct dm_name_list *n = (struct dm_name_list *) (((char *) buffer) + io->data_start);
77d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat    if (!n->dev) {
78d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat        free(buffer);
79d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat        free(buffer2);
80d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat        close(fd);
81d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat        return 0;
82d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat    }
83d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat
84d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat    unsigned nxt = 0;
85d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat    do {
86d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat        n = (struct dm_name_list *) (((char *) n) + nxt);
87d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat
88092aa1c585fedd9e169eece41b8a471f1739908aPeter Bohm        memset(buffer2, 0, DEVMAPPER_BUFFER_SIZE);
89d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat        struct dm_ioctl *io2 = (struct dm_ioctl *) buffer2;
90092aa1c585fedd9e169eece41b8a471f1739908aPeter Bohm        ioctlInit(io2, DEVMAPPER_BUFFER_SIZE, n->name, 0);
91d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat        if (ioctl(fd, DM_DEV_STATUS, io2)) {
92d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat            if (errno != ENXIO) {
9397ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat                SLOGE("DM_DEV_STATUS ioctl failed (%s)", strerror(errno));
94d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat            }
95d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat            io2 = NULL;
96d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat        }
97d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat
98d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat        char *tmp;
99d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat        if (!io2) {
100d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat            asprintf(&tmp, "%s %llu:%llu (no status available)", n->name, MAJOR(n->dev), MINOR(n->dev));
101d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat        } else {
102d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat            asprintf(&tmp, "%s %llu:%llu %d %d 0x%.8x %llu:%llu", n->name, MAJOR(n->dev),
103d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat                    MINOR(n->dev), io2->target_count, io2->open_count, io2->flags, MAJOR(io2->dev),
104d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat                            MINOR(io2->dev));
105d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat        }
106d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat        c->sendMsg(0, tmp, false);
107d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat        free(tmp);
108d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat        nxt = n->next;
109d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat    } while (nxt);
110d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat
111d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat    free(buffer);
112d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat    free(buffer2);
113d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat    close(fd);
114d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat    return 0;
115d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat}
116d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat
117b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehatvoid Devmapper::ioctlInit(struct dm_ioctl *io, size_t dataSize,
118b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat                          const char *name, unsigned flags) {
119b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat    memset(io, 0, dataSize);
120b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat    io->data_size = dataSize;
121b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat    io->data_start = sizeof(struct dm_ioctl);
122b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat    io->version[0] = 4;
123b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat    io->version[1] = 0;
124b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat    io->version[2] = 0;
125b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat    io->flags = flags;
126d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat    if (name) {
127092aa1c585fedd9e169eece41b8a471f1739908aPeter Bohm        int ret = strlcpy(io->name, name, sizeof(io->name));
128092aa1c585fedd9e169eece41b8a471f1739908aPeter Bohm	if (ret >= sizeof(io->name))
129092aa1c585fedd9e169eece41b8a471f1739908aPeter Bohm		abort();
130d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat    }
131b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat}
132b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat
133b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehatint Devmapper::lookupActive(const char *name, char *ubuffer, size_t len) {
134092aa1c585fedd9e169eece41b8a471f1739908aPeter Bohm    char *buffer = (char *) malloc(DEVMAPPER_BUFFER_SIZE);
135b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat    if (!buffer) {
13697ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat        SLOGE("Error allocating memory (%s)", strerror(errno));
137b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat        return -1;
138b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat    }
139b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat
140b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat    int fd;
141b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat    if ((fd = open("/dev/device-mapper", O_RDWR)) < 0) {
14297ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat        SLOGE("Error opening devmapper (%s)", strerror(errno));
143b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat        free(buffer);
144b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat        return -1;
145b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat    }
146b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat
147b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat    struct dm_ioctl *io = (struct dm_ioctl *) buffer;
148b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat
149092aa1c585fedd9e169eece41b8a471f1739908aPeter Bohm    ioctlInit(io, DEVMAPPER_BUFFER_SIZE, name, 0);
150b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat    if (ioctl(fd, DM_DEV_STATUS, io)) {
1518b8f71b1d760411279f3b07a5c97709f052c689eSan Mehat        if (errno != ENXIO) {
15297ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat            SLOGE("DM_DEV_STATUS ioctl failed for lookup (%s)", strerror(errno));
153b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat        }
154b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat        free(buffer);
155b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat        close(fd);
156b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat        return -1;
157b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat    }
158b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat    close(fd);
159b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat
160b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat    unsigned minor = (io->dev & 0xff) | ((io->dev >> 12) & 0xfff00);
161b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat    free(buffer);
162b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat    snprintf(ubuffer, len, "/dev/block/dm-%u", minor);
163b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat    return 0;
164b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat}
165b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat
1668b8f71b1d760411279f3b07a5c97709f052c689eSan Mehatint Devmapper::create(const char *name, const char *loopFile, const char *key,
1678b8f71b1d760411279f3b07a5c97709f052c689eSan Mehat                      unsigned int numSectors, char *ubuffer, size_t len) {
168092aa1c585fedd9e169eece41b8a471f1739908aPeter Bohm    char *buffer = (char *) malloc(DEVMAPPER_BUFFER_SIZE);
169b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat    if (!buffer) {
17097ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat        SLOGE("Error allocating memory (%s)", strerror(errno));
171b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat        return -1;
172b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat    }
173b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat
174b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat    int fd;
175b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat    if ((fd = open("/dev/device-mapper", O_RDWR)) < 0) {
17697ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat        SLOGE("Error opening devmapper (%s)", strerror(errno));
177b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat        free(buffer);
178b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat        return -1;
179b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat    }
180b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat
181b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat    struct dm_ioctl *io = (struct dm_ioctl *) buffer;
182b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat
183b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat    // Create the DM device
184092aa1c585fedd9e169eece41b8a471f1739908aPeter Bohm    ioctlInit(io, DEVMAPPER_BUFFER_SIZE, name, 0);
185b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat
186b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat    if (ioctl(fd, DM_DEV_CREATE, io)) {
18797ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat        SLOGE("Error creating device mapping (%s)", strerror(errno));
188b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat        free(buffer);
189b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat        close(fd);
190b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat        return -1;
191b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat    }
192b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat
193b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat    // Set the legacy geometry
194092aa1c585fedd9e169eece41b8a471f1739908aPeter Bohm    ioctlInit(io, DEVMAPPER_BUFFER_SIZE, name, 0);
195b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat
196b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat    char *geoParams = buffer + sizeof(struct dm_ioctl);
197b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat    // 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
198b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat    strcpy(geoParams, "0 64 63 0");
199b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat    geoParams += strlen(geoParams) + 1;
200b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat    geoParams = (char *) _align(geoParams, 8);
201b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat    if (ioctl(fd, DM_DEV_SET_GEOMETRY, io)) {
20297ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat        SLOGE("Error setting device geometry (%s)", strerror(errno));
203b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat        free(buffer);
204b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat        close(fd);
205b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat        return -1;
206b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat    }
207b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat
208b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat    // Retrieve the device number we were allocated
209092aa1c585fedd9e169eece41b8a471f1739908aPeter Bohm    ioctlInit(io, DEVMAPPER_BUFFER_SIZE, name, 0);
210b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat    if (ioctl(fd, DM_DEV_STATUS, io)) {
21197ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat        SLOGE("Error retrieving devmapper status (%s)", strerror(errno));
212b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat        free(buffer);
213b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat        close(fd);
214b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat        return -1;
215b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat    }
216b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat
217b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat    unsigned minor = (io->dev & 0xff) | ((io->dev >> 12) & 0xfff00);
218b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat    snprintf(ubuffer, len, "/dev/block/dm-%u", minor);
219b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat
220b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat    // Load the table
221b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat    struct dm_target_spec *tgt;
222b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat    tgt = (struct dm_target_spec *) &buffer[sizeof(struct dm_ioctl)];
223b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat
224092aa1c585fedd9e169eece41b8a471f1739908aPeter Bohm    ioctlInit(io, DEVMAPPER_BUFFER_SIZE, name, DM_STATUS_TABLE_FLAG);
225b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat    io->target_count = 1;
226b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat    tgt->status = 0;
227fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat
228b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat    tgt->sector_start = 0;
2298b8f71b1d760411279f3b07a5c97709f052c689eSan Mehat    tgt->length = numSectors;
230fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat
231092aa1c585fedd9e169eece41b8a471f1739908aPeter Bohm    strlcpy(tgt->target_type, "crypt", sizeof(tgt->target_type));
232b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat
233b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat    char *cryptParams = buffer + sizeof(struct dm_ioctl) + sizeof(struct dm_target_spec);
234092aa1c585fedd9e169eece41b8a471f1739908aPeter Bohm    snprintf(cryptParams,
235092aa1c585fedd9e169eece41b8a471f1739908aPeter Bohm            DEVMAPPER_BUFFER_SIZE - (sizeof(struct dm_ioctl) + sizeof(struct dm_target_spec)),
236092aa1c585fedd9e169eece41b8a471f1739908aPeter Bohm            "twofish %s 0 %s 0", key, loopFile);
237b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat    cryptParams += strlen(cryptParams) + 1;
238b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat    cryptParams = (char *) _align(cryptParams, 8);
239b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat    tgt->next = cryptParams - buffer;
240b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat
241b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat    if (ioctl(fd, DM_TABLE_LOAD, io)) {
24297ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat        SLOGE("Error loading mapping table (%s)", strerror(errno));
243b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat        free(buffer);
244b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat        close(fd);
245b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat        return -1;
246b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat    }
247b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat
248b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat    // Resume the new table
249092aa1c585fedd9e169eece41b8a471f1739908aPeter Bohm    ioctlInit(io, DEVMAPPER_BUFFER_SIZE, name, 0);
250b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat
251b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat    if (ioctl(fd, DM_DEV_SUSPEND, io)) {
25297ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat        SLOGE("Error Resuming (%s)", strerror(errno));
253b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat        free(buffer);
254b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat        close(fd);
255b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat        return -1;
256b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat    }
257b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat
258b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat    free(buffer);
259b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat
2608c940ef7dbd423cadc92982b44a65ed1014389e2San Mehat    close(fd);
261b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat    return 0;
262b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat}
263b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat
264b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehatint Devmapper::destroy(const char *name) {
265092aa1c585fedd9e169eece41b8a471f1739908aPeter Bohm    char *buffer = (char *) malloc(DEVMAPPER_BUFFER_SIZE);
266b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat    if (!buffer) {
26797ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat        SLOGE("Error allocating memory (%s)", strerror(errno));
268b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat        return -1;
269b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat    }
270b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat
271b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat    int fd;
272b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat    if ((fd = open("/dev/device-mapper", O_RDWR)) < 0) {
27397ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat        SLOGE("Error opening devmapper (%s)", strerror(errno));
274b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat        free(buffer);
275b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat        return -1;
276b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat    }
277b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat
278b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat    struct dm_ioctl *io = (struct dm_ioctl *) buffer;
279b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat
280b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat    // Create the DM device
281092aa1c585fedd9e169eece41b8a471f1739908aPeter Bohm    ioctlInit(io, DEVMAPPER_BUFFER_SIZE, name, 0);
282b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat
283b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat    if (ioctl(fd, DM_DEV_REMOVE, io)) {
2840586d54053ee00e6d6523d4f125282ccb9a24aabSan Mehat        if (errno != ENXIO) {
28597ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat            SLOGE("Error destroying device mapping (%s)", strerror(errno));
2860586d54053ee00e6d6523d4f125282ccb9a24aabSan Mehat        }
287b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat        free(buffer);
288b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat        close(fd);
289b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat        return -1;
290b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat    }
291b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat
292b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat    free(buffer);
293b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat    close(fd);
294b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat    return 0;
295b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat}
296b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat
297b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehatvoid *Devmapper::_align(void *ptr, unsigned int a)
298b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat{
299b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat        register unsigned long agn = --a;
300b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat
301b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat        return (void *) (((unsigned long) ptr + agn) & ~agn);
302b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat}
303