Refactor secure erase and add MMC erase engine
[platform/core/security/ode.git] / server / block-device.cpp
1 /*
2  *  Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
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 <string.h>
18
19 #include <klay/filesystem.h>
20 #include <klay/exception.h>
21
22 #include "block-device.h"
23
24 namespace ode {
25
26 BlockDevice::BlockDevice(const std::string &path) : name("")
27 {
28         int ret = 0;
29         runtime::File file(path);
30         if (!file.exists()) {
31                 throw runtime::Exception("target doesn't exist");
32         }
33
34         if (!file.isDevice()) {
35                 createDeviceList();
36                 evaluateDevice(path);
37         } else {
38                 name = path;
39         }
40
41         if (name != "") {
42                 int descriptor = ::open(name.c_str(), O_RDONLY);
43                 if (descriptor > 0) {
44                         ret = ::ioctl(descriptor, FIGETBSZ, &blockSize);
45                         if (ret < 0) {
46                                 ::close(descriptor);
47                                 throw runtime::Exception("Failed to get block size");
48                         }
49                 }
50                 ::close(descriptor);
51         } else {
52                 throw runtime::Exception("Cannot find device name");
53         }
54 }
55
56 BlockDevice::~BlockDevice()
57 {
58 }
59
60 int BlockDevice::open(int flags)
61 {
62         int descriptor = 0;
63
64         if (name != "") {
65                 descriptor = ::open(name.c_str(), flags);
66                 return descriptor;
67         }
68
69         return -1;
70 }
71
72 void BlockDevice::close(int descriptor)
73 {
74         int ret = 0;
75
76         ret = ::close(descriptor);
77         if (ret < 0) {
78                 throw runtime::Exception("Cannot close descriptor");
79         }
80         return;
81 }
82
83 int BlockDevice::discard(const Block &block)
84 {
85         int devFd = 0;
86         unsigned long long range[2];
87
88         devFd = BlockDevice::open(O_WRONLY);
89         if (devFd < 0) {
90                 return -1;
91         }
92
93         range[0] = block.physicalOffset;
94         range[1] = block.length;
95
96         int ret = ::ioctl(devFd, BLKDISCARD, &range);
97
98         BlockDevice::close(devFd);
99
100         return ret;
101 }
102
103 int BlockDevice::secDiscard(const Block &block)
104 {
105         int devFd = 0;
106         unsigned long long range[2];
107
108         devFd = BlockDevice::open(O_WRONLY);
109         if (devFd < 0) {
110                 return -1;
111         }
112
113         range[0] = block.physicalOffset;
114         range[1] = block.length;
115
116         int ret = ::ioctl(devFd, BLKSECDISCARD, &range);
117
118         BlockDevice::close(devFd);
119
120         return ret;
121 }
122
123 const std::string &BlockDevice::getName() const
124 {
125         if (name == "") {
126                 throw runtime::Exception("Cannot get device name");
127         }
128         return name;
129 }
130
131 int BlockDevice::getSize()
132 {
133         if (name == "") {
134                 throw runtime::Exception("Cannot get device name");
135         }
136         return blockSize;
137 }
138
139 void BlockDevice::createDeviceList()
140 {
141         char deviceName[PATH_MAX] = "";
142         char source[PATH_MAX] = "";
143         char filesystemType[PATH_MAX] = "";
144         std::string deviceInfo = "";
145
146         std::ifstream file("/etc/mtab");
147         if (file.fail()) {
148                 throw runtime::Exception("/etc/mtab doesn't exist");
149         }
150
151         while (std::getline(file, deviceInfo)) {
152                 if (::sscanf(deviceInfo.c_str(), "%s %s %s %*s %*d %*d",
153                                          deviceName, source, filesystemType) == 3) {
154                         int fd = ::open(deviceName, O_WRONLY);
155                         if (fd < 0) {
156                                 continue;
157                         }
158
159                         if (strcmp(filesystemType, "ext2") && strcmp(filesystemType, "ext3")
160                                 && strcmp(filesystemType, "ext4")) {
161                                 ::close(fd);
162                                 continue;
163                         }
164
165                         runtime::File device(deviceName);
166                         if (!device.exists()) {
167                                 ::close(fd);
168                                 continue;
169                         }
170
171                         if (device.isDevice()) {
172                                 deviceList.insert(std::make_pair(source, deviceName));
173                         }
174                         ::close(fd);
175                 }
176         }
177
178         return;
179 }
180
181 void BlockDevice::evaluateDevice(const std::string &path)
182 {
183         DeviceListIterator matchedDevice = deviceList.find(path);
184         const std::string &subStr = path;
185         std::size_t pos = subStr.size();
186
187         if (matchedDevice != deviceList.end()) {
188                 name = matchedDevice->second;
189                 return;
190         }
191
192         while ((pos = subStr.rfind('/', pos - 1)) != std::string::npos && pos != 0) {
193                 std::string subPath = subStr.substr(0, pos);
194                 matchedDevice = deviceList.find(subPath);
195                 if (matchedDevice != deviceList.end()) {
196                         name = matchedDevice->second;
197                         return;
198                 }
199         }
200 }
201
202 } //namespace ode