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 "ext4-tool.h"
29 #include "block-device.h"
30 #include "progress-bar.h"
31 #include "rmi/secure-erase.h"
33 #define PRIVILEGE_PLATFORM "http://tizen.org/privilege/internal/default/platform"
39 std::unique_ptr<ProgressBar> progressBar;
41 static int totalFileCount = 0;
42 static int erasedFileCount = 0;
44 static int getTotalFileCount(const std::string &name)
47 runtime::DirectoryIterator iter(name), end;
50 std::string next = name + "/" + iter->getName();
51 runtime::File file(next);
58 } else if (file.isDirectory()) {
59 int subTotal = getTotalFileCount(next);
71 SecureErase::SecureErase(ODEControlContext &ctx) :
72 context(ctx), devicePath("")
74 context.expose(this, PRIVILEGE_PLATFORM, (int)(SecureErase::erase)(std::string));
75 context.expose(this, PRIVILEGE_PLATFORM, (int)(SecureErase::clean)(std::string));
77 progressBar.reset(new ProgressBar([](int v) {
78 ::vconf_set_str(VCONFKEY_ODE_ERASE_PROGRESS, std::to_string(v).c_str());
82 SecureErase::~SecureErase()
86 int SecureErase::erase(const std::string &name)
88 auto eraseWorker = [name, this]() {
90 runtime::File file(name);
92 BlockDevice blockDevice(name);
93 devicePath = blockDevice.getName();
98 } else if (file.isDirectory()) {
99 totalFileCount = getTotalFileCount(name);
101 directoryErase(name);
102 } else if (file.isDevice()) {
103 Ext4Tool ext4Tool(name);
104 unsigned int totalBlock = ext4Tool.getTotalBlockCount();
105 unsigned int blockSize = (unsigned int)blockDevice.getSize();
107 for (unsigned int i = 0; i < totalBlock; i++) {
108 Block block(i * blockSize, blockSize);
109 blockDevice.discard(block);
110 progressBar->update(i, totalBlock, 1);
115 } catch (runtime::Exception &e) {}
118 std::thread asyncWork(eraseWorker);
124 int SecureErase::clean(const std::string &name)
127 runtime::File file(name, O_WRONLY);
128 if (!file.exists() || !file.isDevice())
130 } catch (runtime::Exception &e) {}
132 auto cleanWorker = [name, this]() {
134 BlockDevice blockDevice(name);
135 unsigned totalBlock, blockSize;
137 Ext4Tool ext4Tool(name);
138 totalBlock = ext4Tool.getTotalBlockCount();
139 blockSize = (unsigned int) blockDevice.getSize();
141 for (unsigned int i = 0; i < totalBlock; i++) {
142 if (!ext4Tool.isUsedBlock(i)) {
143 Block block(i * blockSize, blockSize);
144 blockDevice.discard(block);
147 progressBar->update(i, totalBlock, 1);
151 } catch (runtime::Exception &e) {}
154 std::thread asyncWork(cleanWorker);
160 int SecureErase::fileErase(const std::string &name)
163 int extentBlockCount = 0;
165 struct fiemap *fmap = (struct fiemap *)buf;
166 struct fiemap_extent *fm_ext = NULL;
167 int count = (sizeof(buf) - sizeof(*fmap)) / sizeof(struct fiemap_extent);
169 /* [TBD] stop the related process */
171 BlockDevice blockDevice(devicePath);
173 ::memset(fmap, 0, sizeof(struct fiemap));
175 fd = ::open(name.c_str(), O_RDONLY);
180 fmap->fm_length = ~0ULL;
182 fmap->fm_extent_count = count;
184 ret = ::ioctl(fd, FS_IOC_FIEMAP, (unsigned long)fmap);
192 fm_ext = &fmap->fm_extents[0];
193 extentBlockCount = (int)fmap->fm_mapped_extents;
195 for (int i = 0; i < extentBlockCount; i++) {
196 Block block(fm_ext[i].fe_physical, fm_ext[i].fe_length);
197 ret = blockDevice.secDiscard(block);
202 if (totalFileCount == 1) {
203 progressBar->update(i, extentBlockCount, 1);
210 int SecureErase::directoryErase(const std::string &name)
212 runtime::DirectoryIterator iter(name), end;
213 while (iter != end) {
214 std::string next = name + "/" + iter->getName();
215 runtime::File file(next);
216 if (!file.exists()) {
222 ::remove(next.c_str());
224 progressBar->update(erasedFileCount, totalFileCount, 1);
225 } else if (file.isDirectory()) {
226 directoryErase(next);
232 ::rmdir(name.c_str());
236 void SecureErase::dropCachePage()
240 file.open("/proc/sys/vm/drop_caches");
242 throw runtime::Exception("Failed to access drop_caches file");