2 * Copyright (c) 2017 Samsung Electronics Co., Ltd All Rights Reserved
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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
21 #include <linux/fiemap.h>
24 #include <klay/exception.h>
25 #include <klay/filesystem.h>
26 #include <klay/audit/logger.h>
28 #include "rmi/secure-erase.h"
29 #include "progress-bar.h"
30 #include "progress-vconf-backend.h"
31 #include "block-device.h"
32 #include "ext4-tool.h"
34 #define PRIVILEGE_PLATFORM "http://tizen.org/privilege/internal/default/platform"
39 VConfBackend vconfBackend(VCONFKEY_ODE_ERASE_PROGRESS);
40 ProgressBar progressBar(std::bind(&VConfBackend::update, &vconfBackend, std::placeholders::_1));
42 static int totalFileCount = 0;
43 static int erasedFileCount = 0;
45 static int getTotalFileCount(const std::string &name)
48 runtime::DirectoryIterator iter(name), end;
51 std::string next = name + "/" + iter->getName();
52 runtime::File file(next);
59 } else if (file.isDirectory()) {
60 int subTotal = getTotalFileCount(next);
72 SecureErase::SecureErase(ODEControlContext &ctx) :
73 context(ctx), devicePath("")
75 context.expose(this, PRIVILEGE_PLATFORM, (int)(SecureErase::erase)(std::string));
76 context.expose(this, PRIVILEGE_PLATFORM, (int)(SecureErase::clean)(std::string));
79 SecureErase::~SecureErase()
83 int SecureErase::erase(const std::string &name)
85 auto eraseWorker = [name, this]() {
87 runtime::File file(name);
89 BlockDevice blockDevice(name);
90 devicePath = blockDevice.getName();
95 } else if (file.isDirectory()) {
96 totalFileCount = getTotalFileCount(name);
99 } else if (file.isDevice()) {
100 Ext4Tool ext4Tool(name);
101 unsigned int totalBlock = ext4Tool.getTotalBlockCount();
102 unsigned int blockSize = (unsigned int)blockDevice.getSize();
104 for (unsigned int i = 0; i < totalBlock; i++) {
105 Block block(i * blockSize, blockSize);
106 blockDevice.discard(block);
107 progressBar.update(i, totalBlock, 1);
112 } catch (runtime::Exception &e) {}
115 std::thread asyncWork(eraseWorker);
121 int SecureErase::clean(const std::string &name)
124 runtime::File file(name, O_WRONLY);
125 if (!file.exists() || !file.isDevice())
127 } catch (runtime::Exception &e) {}
129 auto cleanWorker = [name, this]() {
131 BlockDevice blockDevice(name);
132 unsigned totalBlock, blockSize;
134 Ext4Tool ext4Tool(name);
135 totalBlock = ext4Tool.getTotalBlockCount();
136 blockSize = (unsigned int) blockDevice.getSize();
138 for (unsigned int i = 0; i < totalBlock; i++) {
139 if (!ext4Tool.isUsedBlock(i)) {
140 Block block(i * blockSize, blockSize);
141 blockDevice.discard(block);
144 progressBar.update(i, totalBlock, 1);
148 } catch (runtime::Exception &e) {}
151 std::thread asyncWork(cleanWorker);
157 int SecureErase::fileErase(const std::string &name)
160 int extentBlockCount = 0;
162 struct fiemap *fmap = (struct fiemap *)buf;
163 struct fiemap_extent *fm_ext = NULL;
164 int count = (sizeof(buf) - sizeof(*fmap)) / sizeof(struct fiemap_extent);
166 /* [TBD] stop the related process */
168 BlockDevice blockDevice(devicePath);
170 ::memset(fmap, 0, sizeof(struct fiemap));
172 fd = ::open(name.c_str(), O_RDONLY);
177 fmap->fm_length = ~0ULL;
179 fmap->fm_extent_count = count;
181 ret = ::ioctl(fd, FS_IOC_FIEMAP, (unsigned long)fmap);
189 fm_ext = &fmap->fm_extents[0];
190 extentBlockCount = (int)fmap->fm_mapped_extents;
192 for (int i = 0; i < extentBlockCount; i++) {
193 Block block(fm_ext[i].fe_physical, fm_ext[i].fe_length);
194 ret = blockDevice.secDiscard(block);
199 if (totalFileCount == 1) {
200 progressBar.update(i, extentBlockCount, 1);
207 int SecureErase::directoryErase(const std::string &name)
209 runtime::DirectoryIterator iter(name), end;
210 while (iter != end) {
211 std::string next = name + "/" + iter->getName();
212 runtime::File file(next);
213 if (!file.exists()) {
219 ::remove(next.c_str());
221 progressBar.update(erasedFileCount, totalFileCount, 1);
222 } else if (file.isDirectory()) {
223 directoryErase(next);
229 ::rmdir(name.c_str());
233 void SecureErase::dropCachePage()
237 file.open("/proc/sys/vm/drop_caches");
239 throw runtime::Exception("Failed to access drop_caches file");