From 5c898219fae6a48ef8e1cf14a5e4751b758b5e5f Mon Sep 17 00:00:00 2001 From: Seok Hong Date: Tue, 10 Jan 2017 17:51:45 +0900 Subject: [PATCH] Add ProgressBar Change-Id: I7de1b8666c69708df8e72ea9e6e31cfc7e5ebe65 Signed-off-by: Seok Hong --- server/CMakeLists.txt | 2 + server/engine/dmcrypt-engine.cpp | 19 ++++--- server/engine/dmcrypt-engine.h | 10 +++- server/engine/ecryptfs-engine.cpp | 26 ++++++++- server/engine/ecryptfs-engine.h | 9 ++- server/engine/ext4-engine.cpp | 92 ++++++++++++++++++++++++++----- server/engine/ext4-engine.h | 8 ++- server/external-encryption.cpp | 28 ++++++---- server/internal-encryption.cpp | 7 ++- server/progress-bar.cpp | 54 ++++++++++++++++++ server/progress-bar.h | 46 ++++++++++++++++ server/progress-vconf-backend.cpp | 45 +++++++++++++++ server/progress-vconf-backend.h | 39 +++++++++++++ server/secure-erase.cpp | 66 ++++++++++++++++++---- tests/CMakeLists.txt | 5 +- tests/dmcrypt-engine.cpp | 13 +++-- tests/ecryptfs-engine.cpp | 12 ++-- tests/ext4-engine.cpp | 4 +- tools/apps/CMakeLists.txt | 1 + tools/apps/ode-gui/src/ui.c | 50 +++++++++++++++-- tools/apps/secure-erase/src/ui.c | 9 ++- 21 files changed, 478 insertions(+), 67 deletions(-) create mode 100644 server/progress-bar.cpp create mode 100644 server/progress-bar.h create mode 100644 server/progress-vconf-backend.cpp create mode 100644 server/progress-vconf-backend.h diff --git a/server/CMakeLists.txt b/server/CMakeLists.txt index 79ab042..2074888 100644 --- a/server/CMakeLists.txt +++ b/server/CMakeLists.txt @@ -20,6 +20,8 @@ SET(SERVER_SRCS main.cpp app-bundle.cpp file-footer.cpp secure-erase.cpp + progress-bar.cpp + progress-vconf-backend.cpp block-device.cpp internal-encryption.cpp external-encryption.cpp diff --git a/server/engine/dmcrypt-engine.cpp b/server/engine/dmcrypt-engine.cpp index 383b5cb..292d73f 100644 --- a/server/engine/dmcrypt-engine.cpp +++ b/server/engine/dmcrypt-engine.cpp @@ -80,8 +80,8 @@ static void convertKeyToHexASCII(const DMCryptEngine::data &key, key_ascii[a] = '\0'; } -DMCryptEngine::DMCryptEngine(const std::string &src, const std::string &dest) : - source(src), destination(dest) +DMCryptEngine::DMCryptEngine(const std::string &src, const std::string &dest, const ProgressBar &prgsBar) : + source(src), destination(dest), progressBar(prgsBar) { // 1. Get Real Block device(src)'s infomation cryptInfo.init(src, "aes-cbc-essiv:sha256"); @@ -275,9 +275,9 @@ void DMCryptEngine::umount() #define CRYPT_INPLACE_BUFSIZE 4096 #define CRYPT_SECTORS_PER_BUFSIZE (CRYPT_INPLACE_BUFSIZE / 512) -static void encryptInPlace(const std::string &dest_blkdev, - const std::string &src_blkdev, - const long src_blkdev_size) +void DMCryptEngine::encryptInPlace(const std::string &dst_blkdev, + const std::string &src_blkdev, + const long src_blkdev_size) { // TODO(seok85.hong): support fast-encryption @@ -285,14 +285,17 @@ static void encryptInPlace(const std::string &dest_blkdev, off64_t numblocks = src_blkdev_size / CRYPT_SECTORS_PER_BUFSIZE; off64_t remainder = src_blkdev_size % CRYPT_SECTORS_PER_BUFSIZE; + off64_t total = numblocks + remainder; - runtime::File dest(dest_blkdev, O_WRONLY); + runtime::File dst(dst_blkdev, O_WRONLY); runtime::File src(src_blkdev, O_RDONLY); - for (off64_t n = 0; n < (numblocks + remainder); n++) { + for (off64_t n = 0; n < total; n++) { src.read(buff, CRYPT_INPLACE_BUFSIZE); - dest.write(buff, CRYPT_INPLACE_BUFSIZE); + dst.write(buff, CRYPT_INPLACE_BUFSIZE); + progressBar.update(n, total, 1); } + progressBar.done(); } void DMCryptEngine::encrypt(const DMCryptEngine::data &key) diff --git a/server/engine/dmcrypt-engine.h b/server/engine/dmcrypt-engine.h index 7dd368d..b63a848 100644 --- a/server/engine/dmcrypt-engine.h +++ b/server/engine/dmcrypt-engine.h @@ -20,6 +20,8 @@ #include #include +#include "progress-bar.h" + namespace ode { class CryptInfo { @@ -40,7 +42,7 @@ private: class DMCryptEngine final { public: - DMCryptEngine(const std::string &src, const std::string &dest); + DMCryptEngine(const std::string &src, const std::string &dest, const ProgressBar &prgsBar); DMCryptEngine(const DMCryptEngine &) = delete; DMCryptEngine(DMCryptEngine &&) = delete; ~DMCryptEngine(); @@ -69,9 +71,15 @@ public: const data getKeyMeta(); void setKeyMeta(const data &data); +private: + void encryptInPlace(const std::string &dst_blkdev, + const std::string &src_blkdev, + const long src_blkdev_size); + private: std::string source, destination; CryptInfo cryptInfo; + ProgressBar progressBar; }; } // namespace ode diff --git a/server/engine/ecryptfs-engine.cpp b/server/engine/ecryptfs-engine.cpp index dd48a2e..21c5677 100644 --- a/server/engine/ecryptfs-engine.cpp +++ b/server/engine/ecryptfs-engine.cpp @@ -23,8 +23,8 @@ namespace ode { -EcryptfsEngine::EcryptfsEngine(const std::string &src, const std::string &dest) : - mSource(src), mDestination(dest) +EcryptfsEngine::EcryptfsEngine(const std::string &src, const std::string &dest, const ProgressBar &prgsBar) : + mSource(src), mDestination(dest), progressBar(prgsBar) { } @@ -270,11 +270,14 @@ int EcryptfsEngine::DoEncrypt(const data &key) if (mTotalFileCt) { mTotalCopied = 0; + mLastProg = 0; + progressBar.update(mLastProg); INFO("calling the recursive function EncryptFile (" + std::string(mPath) + ")"); if (cryptInplace(mPath, "", false) != 0) { INFO("Ecryptfs: Full Encryption couldn't complete"); goto error; } + progressBar.done(); } return 0; @@ -305,11 +308,14 @@ int EcryptfsEngine::DoDecrypt(const data &key) if (mTotalFileCt) { mTotalCopied = 0; + mLastProg = 0; + progressBar.update(mLastProg); INFO("calling the recursive function EncryptFile (" + std::string(mPath) + ")"); if (cryptInplace(mPath, "", true) != 0) { INFO("Ecryptfs: Full Decryption couldn't complete"); goto error; } + progressBar.done(); } deleteEncryptMetaData(mMetaDataFile); @@ -322,6 +328,20 @@ error: return -1; } +void EcryptfsEngine::progress(long long size) +{ + int complPercentage = 0; + + if (mTotalStSz != 0) { + complPercentage = (size * 100) / mTotalStSz; + if ((complPercentage - mLastProg) >= DELTA_PROGRESS) { + INFO("Progress: " + std::to_string(complPercentage) + "%, Total Size: " + std::to_string(mTotalStSz)); + mLastProg = complPercentage; + progressBar.update(mLastProg); + } + } +} + long long EcryptfsEngine::CopyImpl(int sfd, int dfd, long long fullsz, bool enctype) { long long ret = -1; @@ -353,6 +373,8 @@ long long EcryptfsEngine::CopyImpl(int sfd, int dfd, long long fullsz, bool enct } total += rdsz; mTotalCopied += rdsz; + + progress(mTotalCopied); } return ret ? -1 : total; diff --git a/server/engine/ecryptfs-engine.h b/server/engine/ecryptfs-engine.h index b0d5b44..9fb7c86 100644 --- a/server/engine/ecryptfs-engine.h +++ b/server/engine/ecryptfs-engine.h @@ -29,6 +29,8 @@ #include #include +#include "../progress-bar.h" + #define __u32 unsigned int #define ECRYPTFS_SIG_SIZE 8 @@ -96,13 +98,15 @@ typedef int32_t key_serial_t; #define WAS_ENCRYPTED 0 #define WAS_ENCRYPTED_OTHER_DEVICE 1 +#define DELTA_PROGRESS 1 + #define check_dots(p) ((p)[0] == '.' && (!(p)[1] || ((p)[1] =='.'&& !(p)[2]))) namespace ode { class EcryptfsEngine final { public: - EcryptfsEngine(const std::string& src, const std::string& dest); + EcryptfsEngine(const std::string& src, const std::string& dest, const ProgressBar& prgsBar); EcryptfsEngine(const EcryptfsEngine&) = delete; EcryptfsEngine(EcryptfsEngine&&) = delete; ~EcryptfsEngine(); @@ -205,6 +209,7 @@ public: int DoCrypt(const data &key, const char *path, int reqEnc, int excludeMedia); int DoEncrypt(const data &key); int DoDecrypt(const data &key); + void progress(long long size); long long CopyImpl(int sfd, int dfd, long long fullsz, bool enctype); ssize_t FullRead (int fd, void * buf, size_t count); ssize_t FullWrite (int fd, const void * buf, size_t len); @@ -232,9 +237,11 @@ private: int mExcludeMedia; int mPreScanEncryptErr; int mPreScanDecryptErr; + int mLastProg; int mTotalFileCt; long long mTotalStSz; long long mTotalCopied; + ProgressBar progressBar; }; } // namespace ode diff --git a/server/engine/ext4-engine.cpp b/server/engine/ext4-engine.cpp index 61e3a9f..c9a0d8d 100644 --- a/server/engine/ext4-engine.cpp +++ b/server/engine/ext4-engine.cpp @@ -80,12 +80,14 @@ struct ext4_encryption_key { unsigned int size; } __attribute__((__packed__)); -// for now, It only suits for "/opt/usr" +/* for now, It only suits for "/opt/usr" */ namespace { std::string secondMountPoint("/opt/usr_encrypt"); std::string bindMountPoint("/opt/usr_encrypt/secure"); std::string ext4KeyringType("logon"); std::string smackAccessLabel("security.SMACK64"); + long long totalSize = 0; + long long curSize = 0; } const Ext4Engine::data generateKeyDesc(const ode::Ext4Engine::data& key) @@ -160,7 +162,7 @@ static void copySmackLabel(std::string& srcPath, std::string& destPath) throw runtime::Exception(runtime::GetSystemErrorMessage()); } -static int copy(std::string& src, std::string& dest) +int Ext4Engine::copy(std::string& src, std::string& dest) { int readFd, writeFd, ret; struct stat st; @@ -180,9 +182,14 @@ static int copy(std::string& src, std::string& dest) copySmackLabel(src, dest); if (::chown(dest.c_str(), st.st_uid, st.st_gid) == -1) throw runtime::Exception(dest + runtime::GetSystemErrorMessage()); - if (::sendfile(writeFd, readFd, 0, st.st_size)) + if (::sendfile(writeFd, readFd, 0, st.st_size) == -1) return 1; + /* progress bar update */ + curSize += st.st_size; + INFO("curSize is " + std::to_string(curSize)); + progressBar.update(curSize, totalSize, 1); + if (::fsync(writeFd) != 0) throw runtime::Exception(dest + runtime::GetSystemErrorMessage()); @@ -194,7 +201,57 @@ static int copy(std::string& src, std::string& dest) return 0; } -static void listDir(std::string& source, std::string& dest, bool excludeFlag) +static void preScanDir(std::string& dir) +{ + DIR* d; + + d = ::opendir(dir.c_str()); + + if (!d) + throw runtime::Exception(dir + runtime::GetSystemErrorMessage()); + + while(1) { + struct dirent* entry; + std::string dName; + + entry = ::readdir(d); + if (!entry) { + break; + } + dName = entry->d_name; + if (!(entry->d_type & DT_DIR)) { + std::string file = dir + "/" + dName; + struct stat st; + int statRet; + + statRet = ::stat(file.c_str(), &st); + if (statRet != 0) + throw runtime::Exception(file + runtime::GetSystemErrorMessage()); + INFO("[preListDir] " + file + " totalSize = " + std::to_string(totalSize) + " " +std::to_string(st.st_size)); + totalSize += st.st_size; + } + + if (entry->d_type & DT_DIR) { + if (dName.compare(".") != 0 && dName.compare("..") != 0) { + std::string path; + + path = dir + "/" + dName; + + + if (path.size() >= PATH_MAX) + throw runtime::Exception(path + " :path length has got too long"); + + preScanDir(path); + } + } + } + + if (::closedir(d)) + throw runtime::Exception(runtime::GetSystemErrorMessage()); + +} + +void Ext4Engine::listDir(std::string& source, std::string& dest, bool excludeFlag) { DIR* d; @@ -231,7 +288,7 @@ static void listDir(std::string& source, std::string& dest, bool excludeFlag) pathS = source + "/" + dName; pathD = dest + "/" +dName; - // make new directory + /* make new directory */ int mkdirRet, statRet; struct stat st; statRet = ::stat(pathS.c_str(), &st); @@ -353,8 +410,8 @@ static bool getPolicy(const std::string& dirName) return true; } -Ext4Engine::Ext4Engine(const std::string& src, const std::string& dest) : - source(src), destination(dest) +Ext4Engine::Ext4Engine(const std::string& src, const std::string& dest, const ProgressBar &prgsBar) : + source(src), destination(dest), progressBar(prgsBar) { } @@ -365,17 +422,17 @@ Ext4Engine::~Ext4Engine() void Ext4Engine::mount(const Ext4Engine::data& key) { addKey(key); - // mount : /dev/mmcblk0p21 /opt/usr_encrypt + /* mount : /dev/mmcblk0p21 /opt/usr_encrypt */ if (::mount(source.c_str(), secondMountPoint.c_str(), "ext4", 0, 0) < 0) throw runtime::Exception(runtime::GetSystemErrorMessage()); - // bind mount :/opt/usr_encrypt/secure /opt/usr + /* bind mount :/opt/usr_encrypt/secure /opt/usr */ if (::mount(bindMountPoint.c_str(), destination.c_str(), "ext4", MS_BIND, 0) < 0) throw runtime::Exception(runtime::GetSystemErrorMessage()); } void Ext4Engine::umount() { - // for decrypt, umount /opt/usr + /* for decrypt, umount /opt/usr */ if (::umount(destination.c_str())) throw runtime::Exception(runtime::GetSystemErrorMessage()); } @@ -394,14 +451,17 @@ void Ext4Engine::encrypt(const Ext4Engine::data& key) if (!(copyFlag = prepareEncryptDir(sourceDir, destDir))) throw runtime::Exception("prepareEncryptDir failed"); - // key add to keyring + preScanDir(secondMountPoint); + /* key add to keyring */ addKeyToKeyring(key); - // set policy + /* set policy */ setPolicy(bindMountPoint, key); if (copyFlag) listDir(secondMountPoint, bindMountPoint, true); INFO("[ext4 encrypt] copy done"); + + progressBar.done(); if (::mount(bindMountPoint.c_str(), destDir.c_str(), "ext4", MS_BIND, 0) < 0) throw runtime::Exception(runtime::GetSystemErrorMessage()); } @@ -414,15 +474,19 @@ void Ext4Engine::decrypt(const Ext4Engine::data& key) throw runtime::Exception("directory isn't encrypted"); addKeyToKeyring(key); + preScanDir(bindMountPoint); + listDir(bindMountPoint, secondMountPoint, false); INFO("[ext4 decrypt] copy done"); + progressBar.done(); + if (::open(bindMountPoint.c_str(), O_RDONLY) != -1) ::remove(bindMountPoint.c_str()); - // umount /opt/usr_encrypt + /* umount /opt/usr_encrypt */ if (::umount(secondMountPoint.c_str())) throw runtime::Exception(runtime::GetSystemErrorMessage()); - // mount /dev/mmcblk0p21 /opt/usr + /* mount /dev/mmcblk0p21 /opt/usr */ if (::mount(source.c_str(), destination.c_str(), "ext4", 0, 0) < 0) throw runtime::Exception(runtime::GetSystemErrorMessage()); diff --git a/server/engine/ext4-engine.h b/server/engine/ext4-engine.h index 80922a9..e9cdb22 100644 --- a/server/engine/ext4-engine.h +++ b/server/engine/ext4-engine.h @@ -20,11 +20,13 @@ #include #include +#include "progress-bar.h" + namespace ode { class Ext4Engine final { public: - Ext4Engine(const std::string &src, const std::string &dest); + Ext4Engine(const std::string& src, const std::string& dest, const ProgressBar &prgsBar); Ext4Engine(const Ext4Engine&) = delete; Ext4Engine(Ext4Engine&&) = delete; ~Ext4Engine(); @@ -54,8 +56,12 @@ public: const data getKeyMeta(); void setKeyMeta(const data &data); + int copy(std::string& src, std::string& dest); + void listDir(std::string& source, std::string& dest, bool excludeFlag); + private: std::string source, destination; + ProgressBar progressBar; }; } // namespace ode diff --git a/server/external-encryption.cpp b/server/external-encryption.cpp index c54e5bd..b7cd063 100644 --- a/server/external-encryption.cpp +++ b/server/external-encryption.cpp @@ -32,8 +32,10 @@ #include #include "rmi/external-encryption.h" +#include "progress-bar.h" +#include "progress-vconf-backend.h" -#define EXTERNAL_STORAGE_PATH "/opt/media/SDCardA1" +#define EXTERNAL_STORAGE_PATH "/opt/media/SDCardA1" #define DEFAULT_USER "owner" #define EXTERNAL_STORAGE_VCONF_KEY VCONFKEY_SDE_CRYPTO_STATE @@ -41,7 +43,10 @@ namespace ode { namespace { -EcryptfsEngine engine(EXTERNAL_STORAGE_PATH, EXTERNAL_STORAGE_PATH); +VConfBackend vconfBackend(VCONFKEY_SDE_ENCRYPT_PROGRESS); +ProgressBar progressBar(std::bind(&VConfBackend::update, &vconfBackend, std::placeholders::_1)); + +EcryptfsEngine engine(EXTERNAL_STORAGE_PATH, EXTERNAL_STORAGE_PATH, progressBar); void killDependedApplications() { @@ -51,11 +56,12 @@ void killDependedApplications() } } -void showProgressUI(const std::string type) { +void showProgressUI(const std::string type) +{ AppBundle bundle; bundle.add("mode", "progress"); bundle.add("type", type); - bundle.add("target", "SD card encryption"); + bundle.add("target", "External"); Launchpad launchpad(::tzplatform_getuid(TZ_SYS_DEFAULT_USER)); launchpad.launch("org.tizen.ode-gui", bundle); @@ -132,7 +138,7 @@ void externalCheckMount() } -ExternalEncryption::ExternalEncryption(ODEControlContext& ctx) : +ExternalEncryption::ExternalEncryption(ODEControlContext &ctx) : context(ctx) { context.registerParametricMethod(this, "", (int)(ExternalEncryption::mount)(std::string)); @@ -151,7 +157,7 @@ ExternalEncryption::~ExternalEncryption() { } -int ExternalEncryption::mount(const std::string& password) +int ExternalEncryption::mount(const std::string &password) { KeyManager::data pwData(password.begin(), password.end()); KeyManager keyManager(engine.getKeyMeta()); @@ -174,7 +180,7 @@ int ExternalEncryption::umount() return 0; } -int ExternalEncryption::encrypt(const std::string& password) +int ExternalEncryption::encrypt(const std::string &password) { KeyManager::data pwData(password.begin(), password.end()); KeyManager keyManager; @@ -201,7 +207,7 @@ int ExternalEncryption::encrypt(const std::string& password) return 0; } -int ExternalEncryption::decrypt(const std::string& password) +int ExternalEncryption::decrypt(const std::string &password) { KeyManager::data pwData(password.begin(), password.end()); KeyManager keyManager(engine.getKeyMeta()); @@ -219,7 +225,7 @@ int ExternalEncryption::decrypt(const std::string& password) INFO("Umount internal storage..."); try { engine.umount(); - } catch (runtime::Exception& e) {} + } catch (runtime::Exception &e) {} INFO("Decryption started..."); engine.decrypt(MasterKey); @@ -234,8 +240,8 @@ int ExternalEncryption::decrypt(const std::string& password) return 0; } -int ExternalEncryption::changePassword(const std::string& oldPassword, - const std::string& newPassword) +int ExternalEncryption::changePassword(const std::string &oldPassword, + const std::string &newPassword) { KeyManager::data oldPwData(oldPassword.begin(), oldPassword.end()); KeyManager::data newPwData(newPassword.begin(), newPassword.end()); diff --git a/server/internal-encryption.cpp b/server/internal-encryption.cpp index d0c4a27..1a50b5b 100644 --- a/server/internal-encryption.cpp +++ b/server/internal-encryption.cpp @@ -39,7 +39,10 @@ namespace ode { namespace { -DMCryptEngine engine("/dev/mmcblk0p25", INTERNAL_STORAGE_PATH); +VConfBackend vconfBackend(VCONFKEY_ODE_ENCRYPT_PROGRESS); +ProgressBar progressBar(std::bind(&VConfBackend::update, &vconfBackend, std::placeholders::_1)); + +DMCryptEngine engine("/dev/mmcblk0p25", INTERNAL_STORAGE_PATH, progressBar); void stopDependedSystemdServices() { @@ -74,7 +77,7 @@ void stopDependedSystemdServices() void showProgressUI(const std::string type) { std::vector args = { - "ode-gui", "progress", type, "Internal storage encryption" + "ode-gui", "progress", type, "Internal" }; runtime::Process proc("/usr/bin/ode-gui", args); diff --git a/server/progress-bar.cpp b/server/progress-bar.cpp new file mode 100644 index 0000000..0c1ed83 --- /dev/null +++ b/server/progress-bar.cpp @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2017 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License + */ + +#include "progress-bar.h" + +namespace ode { + +ProgressBar::ProgressBar(CALLBACK const &callback) + : updater(callback), updateValue(0) +{ +} + +ProgressBar::~ProgressBar() +{ +} + +void ProgressBar::update(int value) +{ + if (updateValue != value) { + updateValue = value; + updater(updateValue); + } +} + +void ProgressBar::update(int curCount, int totalCount, int unit) +{ + int percentage = ((curCount * 100) / totalCount) * unit; + + if (updateValue != percentage) { + updateValue = percentage; + updater(updateValue); + } +} + +void ProgressBar::done(void) +{ + updateValue = 100; + updater(100); +} + +} // namespace ode diff --git a/server/progress-bar.h b/server/progress-bar.h new file mode 100644 index 0000000..45a30a7 --- /dev/null +++ b/server/progress-bar.h @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2017 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License + */ + +#ifndef __ODE_PROGRESS_BAR_H__ +#define __ODE_PROGRESS_BAR_H__ + +#include +#include + +#include "progress-vconf-backend.h" + +namespace ode { + +class ProgressBar { +public: + typedef std::function CALLBACK; + + ProgressBar() = delete; + ProgressBar(CALLBACK const &callback); + ~ProgressBar(); + + void update(int value); + void update(int count, int totalCount, int unit); + void done(void); + +private: + CALLBACK updater; + int updateValue; +}; + +} // namespace ode + +#endif //__ODE_PROGRESS_BAR_H__ diff --git a/server/progress-vconf-backend.cpp b/server/progress-vconf-backend.cpp new file mode 100644 index 0000000..12c5b65 --- /dev/null +++ b/server/progress-vconf-backend.cpp @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2017 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License + */ +#include "progress-vconf-backend.h" + +namespace ode { + +VConfBackend::VConfBackend(const std::string &k) + : key(k) +{ +} + +VConfBackend::~VConfBackend() +{ +} + +void VConfBackend::update(int value) +{ + // TODO + int ret = 0; + ret = ::vconf_set_str(key.c_str(), std::to_string(value).c_str()); + if (ret != 0) { + /* [TBD] throw exception */ + } +} +#if 0 +const std::string VconfBackend::getProgress(void) +{ + return ::vconf_get_str(key.c_str()); +} +#endif + +} // namespace ode diff --git a/server/progress-vconf-backend.h b/server/progress-vconf-backend.h new file mode 100644 index 0000000..0e18ba7 --- /dev/null +++ b/server/progress-vconf-backend.h @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2017 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License + */ + +#ifndef __ODE_PROGRESS_VCONF_BACKEND_H__ +#define __ODE_PROGRESS_VCONF_BACKEND_H__ + +#include +#include + +namespace ode { + +class VConfBackend { +public: + VConfBackend() = delete; + VConfBackend(const std::string &k); + ~VConfBackend(); + + void update(int value); + +private: + std::string key; +}; + +} // namespace ode + +#endif //__ODE_PROGRESS_VCONF_BACKEND_H__ diff --git a/server/secure-erase.cpp b/server/secure-erase.cpp index f91bc94..fe72e10 100644 --- a/server/secure-erase.cpp +++ b/server/secure-erase.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved + * Copyright (c) 2017 Samsung Electronics Co., Ltd All Rights Reserved * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -20,16 +20,53 @@ #include #include +#include #include #include #include #include "rmi/secure-erase.h" +#include "progress-bar.h" +#include "progress-vconf-backend.h" #include "block-device.h" #include "ext4-tool.h" namespace ode { +namespace { +VConfBackend vconfBackend(VCONFKEY_ODE_ERASE_PROGRESS); +ProgressBar progressBar(std::bind(&VConfBackend::update, &vconfBackend, std::placeholders::_1)); + +static int totalFileCount = 0; +static int erasedFileCount = 0; + +static int getTotalFileCount(const std::string &name) +{ + int total = 0; + runtime::DirectoryIterator iter(name), end; + + while (iter != end) { + std::string next = name + "/" + iter->getName(); + runtime::File file(next); + if (!file.exists()) { + return -1; + } + + if (file.isFile()) { + total++; + } else if (file.isDirectory()) { + int subTotal = getTotalFileCount(next); + if (subTotal != -1) + total += subTotal; + } + ++iter; + } + + return total; +} + +} /* namespace */ + SecureErase::SecureErase(ODEControlContext &ctx) : context(ctx), devicePath("") { @@ -51,10 +88,11 @@ int SecureErase::erase(const std::string &name) devicePath = blockDevice.getName(); if (file.isFile()) { - /* TBD */ + totalFileCount = 1; fileErase(name); } else if (file.isDirectory()) { - /* TBD */ + totalFileCount = getTotalFileCount(name); + erasedFileCount = 0; directoryErase(name); } else if (file.isDevice()) { Ext4Tool ext4Tool(name); @@ -62,11 +100,13 @@ int SecureErase::erase(const std::string &name) unsigned int blockSize = (unsigned int)blockDevice.getSize(); for (unsigned int i = 0; i < totalBlock; i++) { - Block block(i*blockSize, blockSize); + Block block(i * blockSize, blockSize); blockDevice.discard(block); + progressBar.update(i, totalBlock, 1); } } dropCachePage(); + progressBar.done(); } catch (runtime::Exception &e) {} }; @@ -84,7 +124,7 @@ int SecureErase::clean(const std::string &name) return -1; } catch (runtime::Exception &e) {} - auto cleanWorker = [name, this] () { + auto cleanWorker = [name, this]() { try { BlockDevice blockDevice(name); unsigned totalBlock, blockSize; @@ -95,11 +135,14 @@ int SecureErase::clean(const std::string &name) for (unsigned int i = 0; i < totalBlock; i++) { if (!ext4Tool.isUsedBlock(i)) { - Block block(i*blockSize, blockSize); + Block block(i * blockSize, blockSize); blockDevice.discard(block); } + + progressBar.update(i, totalBlock, 1); } dropCachePage(); + progressBar.done(); } catch (runtime::Exception &e) {} }; @@ -150,6 +193,10 @@ int SecureErase::fileErase(const std::string &name) if (ret < 0) { return -1; } + + if (totalFileCount == 1) { + progressBar.update(i, extentBlockCount, 1); + } } return ret; @@ -157,8 +204,6 @@ int SecureErase::fileErase(const std::string &name) int SecureErase::directoryErase(const std::string &name) { - int ret = 0; - runtime::DirectoryIterator iter(name), end; while (iter != end) { std::string next = name + "/" + iter->getName(); @@ -170,6 +215,8 @@ int SecureErase::directoryErase(const std::string &name) if (file.isFile()) { fileErase(next); ::remove(next.c_str()); + erasedFileCount++; + progressBar.update(erasedFileCount, totalFileCount, 1); } else if (file.isDirectory()) { directoryErase(next); } @@ -178,8 +225,7 @@ int SecureErase::directoryErase(const std::string &name) fileErase(name); ::rmdir(name.c_str()); - - return ret; + return 0; } void SecureErase::dropCachePage() diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index eff1d8b..a8c9773 100755 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -25,6 +25,8 @@ SET(TEST_SRC main.cpp ../server/engine/ecryptfs-engine.cpp ../server/key-manager/key-generator.cpp ../server/key-manager/anti-forensics.cpp + ../server/progress-bar.cpp + ../server/progress-vconf-backend.cpp ) ADD_EXECUTABLE(${PROJECT_NAME} ${TEST_SRC}) @@ -33,9 +35,10 @@ PKG_CHECK_MODULES(TEST_DEPS REQUIRED klay glib-2.0 gio-2.0 openssl + vconf ) -INCLUDE_DIRECTORIES(SYSTEM ${TEST_DEPS_INCLUDE_DIRS}) +INCLUDE_DIRECTORIES(SYSTEM ${TEST_DEPS_INCLUDE_DIRS} ../server) TARGET_LINK_LIBRARIES(${PROJECT_NAME} ${TEST_DEPS_LIBRARIES}) diff --git a/tests/dmcrypt-engine.cpp b/tests/dmcrypt-engine.cpp index 082207b..ee4e44d 100644 --- a/tests/dmcrypt-engine.cpp +++ b/tests/dmcrypt-engine.cpp @@ -29,6 +29,8 @@ #include #include +#include "../server/progress-bar.h" +#include "../server/progress-vconf-backend.h" #include "../server/engine/dmcrypt-engine.cpp" #define TEST_USERDATA_NAME "userdata" @@ -42,6 +44,9 @@ static std::string test_real_mntpoint; // ode::DMCryptEngine gvTest("/dev/mmcblk0p25", "/opt/usr"); +ode::VConfBackend vconfBackend(VCONFKEY_ODE_ENCRYPT_PROGRESS); +ode::ProgressBar progressBar(std::bind(&ode::VConfBackend::update, &vconfBackend, std::placeholders::_1)); + } //////////////////////////////////////////////////////////////////////////////////////// @@ -321,7 +326,7 @@ TESTCASE(DMCryptSanitizeKey) TESTCASE(DMCryptGetPathTest) { try { - ode::DMCryptEngine engine("/dev/mmcblk0p1", TEST_USERDATA_PATH); + ode::DMCryptEngine engine("/dev/mmcblk0p1", TEST_USERDATA_PATH, progressBar); if (engine.getSource() != "/dev/mmcblk0p1") { throw runtime::Exception("Source doen't match"); } @@ -340,7 +345,7 @@ TESTCASE(DMCryptEncryptAndDecrypt) const std::string keystring = "01020304050607080910111213141516"; const ode::DMCryptEngine::data key32bit(keystring.begin(), keystring.end()); - ode::DMCryptEngine engine(test_real_blkdev, test_real_mntpoint); + ode::DMCryptEngine engine(test_real_blkdev, test_real_mntpoint, progressBar); engine.encrypt(key32bit); // check the encryption result of test_real_blkdev(/dev/loop0) @@ -383,7 +388,7 @@ TESTCASE(DMCryptEncryptMountUnmountDecrypt) const std::string keystring = "01020304050607080910111213141516"; const ode::DMCryptEngine::data key32bit(keystring.begin(), keystring.end()); - ode::DMCryptEngine engine(test_real_blkdev, test_real_mntpoint); + ode::DMCryptEngine engine(test_real_blkdev, test_real_mntpoint, progressBar); engine.encrypt(key32bit); engine.mount(key32bit); { @@ -437,7 +442,7 @@ TESTCASE(DMCryptEncryptButDecryptWithWrongKey) const std::string wrongkeystring = "SIZE_IS_SAME_BUT_WRONG_DECKEY___"; const ode::DMCryptEngine::data wrongkey32bit(wrongkeystring.begin(), wrongkeystring.end()); - ode::DMCryptEngine engine(test_real_blkdev, test_real_mntpoint); + ode::DMCryptEngine engine(test_real_blkdev, test_real_mntpoint, progressBar); engine.encrypt(key32bit); // check the encryption result of test_real_blkdev(/dev/loop0) diff --git a/tests/ecryptfs-engine.cpp b/tests/ecryptfs-engine.cpp index cd00460..0f77ef4 100644 --- a/tests/ecryptfs-engine.cpp +++ b/tests/ecryptfs-engine.cpp @@ -19,20 +19,24 @@ #include #include "../server/engine/ecryptfs-engine.h" +#include "../server/progress-bar.h" +#include "../server/progress-vconf-backend.h" -#define TEST_PATH "/opt/usr" +#define TEST_PATH "/opt/usr" TESTCASE(EcryptfsGetPathTest) { try { - ode::EcryptfsEngine engine("/dev/mmcblkp0", "/opt/usr"); - if (engine.getDestination() != "/dev/mmcblkp0") { + ode::VConfBackend vconfBackend(VCONFKEY_SDE_ENCRYPT_PROGRESS); + ode::ProgressBar progressBar(std::bind(&ode::VConfBackend::update, &vconfBackend, std::placeholders::_1)); + ode::EcryptfsEngine engine("/dev/mmcblkp0", "/opt/usr", progressBar); + if (engine.getSource() != "/dev/mmcblkp0") { throw runtime::Exception("Source doen't match"); } if (engine.getDestination() != "/opt/usr") { throw runtime::Exception("Destination doen't match"); } - } catch (runtime::Exception& e) { + } catch (runtime::Exception &e) { TEST_FAIL(e.what()); } } diff --git a/tests/ext4-engine.cpp b/tests/ext4-engine.cpp index 7f6627d..c909347 100755 --- a/tests/ext4-engine.cpp +++ b/tests/ext4-engine.cpp @@ -25,7 +25,9 @@ TESTCASE(Ext4GetPathTest) { try { - ode::Ext4Engine engine("/dev/mmcblkp0", "/opt/usr"); + ode::VConfBackend vconfBackend(VCONFKEY_ODE_ENCRYPT_PROGRESS); + ode::ProgressBar progressBar(std::bind(&ode::VConfBackend::update, &vconfBackend, std::placeholders::_1)); + ode::Ext4Engine engine("/dev/mmcblkp0", "/opt/usr", progressBar); if (engine.getDestination() != "/dev/mmcblkp0") { throw runtime::Exception("Source doen't match"); } diff --git a/tools/apps/CMakeLists.txt b/tools/apps/CMakeLists.txt index 611c30b..5811840 100755 --- a/tools/apps/CMakeLists.txt +++ b/tools/apps/CMakeLists.txt @@ -24,6 +24,7 @@ PKG_CHECK_MODULES(EFL_APP REQUIRED capi-appfw-application capi-ui-efl-util evas + vconf ) SET(ODE_APPS_ODE ${ODE_APPS}/ode) diff --git a/tools/apps/ode-gui/src/ui.c b/tools/apps/ode-gui/src/ui.c index 1c1bf07..f856cfd 100644 --- a/tools/apps/ode-gui/src/ui.c +++ b/tools/apps/ode-gui/src/ui.c @@ -16,12 +16,43 @@ * limitations under the License. * */ + +#include +#include + #include "ode.h" #include "widget.h" #define EDJ_PATH "/usr/apps/" PACKAGE "/res/" PACKAGE ".edj" static Evas_Object *win, *conform, *layout; +static char key[PATH_MAX] = ""; +static int done = 0; + +static Eina_Bool progressbar_timer_cb(void *data) +{ + Evas_Object *progressbar = (Evas_Object *)data; + char *progress = NULL; + int percentage = 0; + + if (done) { + ui_app_exit(); + return ECORE_CALLBACK_DONE; + } + + progress = vconf_get_str(key); + if (progress) + percentage = atoi(progress); + + elm_progressbar_value_set(progressbar, (double)(percentage / 100.0)); + + if (percentage == 100) { + done = 1; + return ECORE_CALLBACK_PASS_ON; + } + + return ECORE_CALLBACK_PASS_ON; +} void _create_base_window() { @@ -37,10 +68,17 @@ void _create_base_window() void _create_progress_view(const char *type, const char *target) { - Evas_Object *progress_layout; - Evas_Object *progressbar; + Evas_Object *progress_layout, *progressbar; Evas_Object *title, *content; - char string[256]; + char string[PATH_MAX] = ""; + + done = 0; + + if (!strcmp(target, "Internal")) { + snprintf(key, PATH_MAX, "%s", VCONFKEY_ODE_ENCRYPT_PROGRESS); + } else if (!strcmp(target, "External")) { + snprintf(key, PATH_MAX, "%s", VCONFKEY_SDE_ENCRYPT_PROGRESS); + } progress_layout = _create_layout(layout, EDJ_PATH, "progress_layout"); @@ -52,12 +90,14 @@ void _create_progress_view(const char *type, const char *target) elm_object_part_content_set(progress_layout, "message_title", title); - progressbar = _create_progressbar(progress_layout, "pending"); + progressbar = _create_progressbar(progress_layout, "default"); + elm_progressbar_unit_format_set(progressbar, "%.0f%%"); elm_object_part_content_set(progress_layout, "progress_indicator", progressbar); elm_object_part_content_set(progress_layout, "message_content", content); - elm_object_part_content_set(layout, "elm.swallow.content", progress_layout); + elm_progressbar_value_set(progressbar, 0.0); + ecore_timer_add(1, progressbar_timer_cb, progressbar); return; } diff --git a/tools/apps/secure-erase/src/ui.c b/tools/apps/secure-erase/src/ui.c index 99e926f..a1827ef 100644 --- a/tools/apps/secure-erase/src/ui.c +++ b/tools/apps/secure-erase/src/ui.c @@ -110,6 +110,7 @@ static Eina_Bool progressbar_timer_cb(void *data) notification_h handle = NULL; char *progress = NULL; int percentage = 0; + double current_progress = 0.0, noti_progress = 0.0; handle = notification_load_by_tag("secure-erase-noti"); if (handle == NULL) { @@ -131,8 +132,12 @@ static Eina_Bool progressbar_timer_cb(void *data) ui_app_exit(); return ECORE_CALLBACK_DONE; } else if (percentage < 100) { - notification_set_progress(handle, (double)(percentage / 100.0)); - notification_update(handle); + current_progress = (double)(percentage / 100.0); + notification_get_progress(handle, ¬i_progress); + if (current_progress != noti_progress) { + notification_set_progress(handle, (double)(percentage / 100.0)); + notification_update(handle); + } } return ECORE_CALLBACK_PASS_ON; -- 2.34.1