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 #define ATRACE_TAG ATRACE_TAG_PACKAGE_MANAGER
18 
19 #include <errno.h>
20 #include <fcntl.h>
21 #include <stdio.h>
22 #include <stdlib.h>
23 #include <string.h>
24 #include <unistd.h>
25 
26 #include <sys/stat.h>
27 #include <sys/types.h>
28 
29 #include <linux/kdev_t.h>
30 
31 #include <android-base/logging.h>
32 #include <android-base/stringprintf.h>
33 #include <android-base/strings.h>
34 #include <libdm/dm.h>
35 #include <utils/Trace.h>
36 
37 #include "Devmapper.h"
38 
39 using android::base::StringPrintf;
40 using namespace android::dm;
41 
42 static const char* kVoldPrefix = "vold:";
43 
create(const char * name_raw,const char * loopFile,const char * key,unsigned long numSectors,char * ubuffer,size_t len)44 int Devmapper::create(const char* name_raw, const char* loopFile, const char* key,
45                       unsigned long numSectors, char* ubuffer, size_t len) {
46     auto& dm = DeviceMapper::Instance();
47     auto name_string = StringPrintf("%s%s", kVoldPrefix, name_raw);
48 
49     DmTable table;
50     table.Emplace<DmTargetCrypt>(0, numSectors, "twofish", key, 0, loopFile, 0);
51 
52     if (!dm.CreateDevice(name_string, table)) {
53         LOG(ERROR) << "Failed to create device-mapper device " << name_string;
54         return -1;
55     }
56 
57     std::string path;
58     if (!dm.GetDmDevicePathByName(name_string, &path)) {
59         LOG(ERROR) << "Failed to get device-mapper device path for " << name_string;
60         return -1;
61     }
62     snprintf(ubuffer, len, "%s", path.c_str());
63     return 0;
64 }
65 
destroy(const char * name_raw)66 int Devmapper::destroy(const char* name_raw) {
67     auto& dm = DeviceMapper::Instance();
68 
69     auto name_string = StringPrintf("%s%s", kVoldPrefix, name_raw);
70     if (!dm.DeleteDevice(name_string)) {
71         if (errno != ENXIO) {
72             PLOG(ERROR) << "Failed DM_DEV_REMOVE";
73         }
74         return -1;
75     }
76     return 0;
77 }
78 
destroyAll()79 int Devmapper::destroyAll() {
80     ATRACE_NAME("Devmapper::destroyAll");
81 
82     auto& dm = DeviceMapper::Instance();
83     std::vector<DeviceMapper::DmBlockDevice> devices;
84     if (!dm.GetAvailableDevices(&devices)) {
85         LOG(ERROR) << "Failed to get dm devices";
86         return -1;
87     }
88 
89     for (const auto& device : devices) {
90         if (android::base::StartsWith(device.name(), kVoldPrefix)) {
91             LOG(DEBUG) << "Tearing down stale dm device named " << device.name();
92             if (!dm.DeleteDevice(device.name())) {
93                 if (errno != ENXIO) {
94                     PLOG(WARNING) << "Failed to destroy dm device named " << device.name();
95                 }
96             }
97         } else {
98             LOG(DEBUG) << "Found unmanaged dm device named " << device.name();
99         }
100     }
101     return 0;
102 }
103