From c2ba1ea3c2d40359845b1517812bac2facf44799 Mon Sep 17 00:00:00 2001 From: Krzysztof Jackiewicz Date: Tue, 2 Oct 2018 10:07:10 +0200 Subject: [PATCH] Use proper numeric types in ext4 tool Modify the numeric types used to represent filesystem features to solve the problem of unnecessary casts, loss of precision and possible integer overflow. Simplify few related parts: - Add template function in ProgressBar to handle different integer types. - Move duplicated fast encryption logic inside copyInPlace. - Remove unnecessary variables and calculations from Ext4Tool::readInfo(). Change-Id: Id4fc83390e9b26cc84fcb7e08cde6e467a6a93c4 --- fota/fota.cpp | 5 +- server/engine/encryption/dmcrypt-engine.cpp | 58 ++++++------------ server/engine/encryption/ecryptfs-engine.cpp | 8 ++- server/engine/encryption/ext4-engine.cpp | 8 ++- server/engine/erase/erase-engine.cpp | 23 ++++--- server/engine/erase/erase-engine.h | 3 +- server/engine/erase/mmc-engine.cpp | 22 +++---- server/engine/erase/mmc-engine.h | 3 +- server/ext4-tool.cpp | 92 ++++++++++++++++++---------- server/ext4-tool.h | 10 +-- server/external-encryption.cpp | 2 +- server/internal-encryption.cpp | 2 +- server/progress-bar.cpp | 7 +-- server/progress-bar.h | 29 +++++++-- server/secure-erase.cpp | 2 +- tests/dmcrypt-engine.cpp | 2 +- tests/ecryptfs-engine.cpp | 2 +- tests/ext4-engine.cpp | 2 +- 18 files changed, 161 insertions(+), 119 deletions(-) diff --git a/fota/fota.cpp b/fota/fota.cpp index c747af7..ccbdafe 100644 --- a/fota/fota.cpp +++ b/fota/fota.cpp @@ -33,8 +33,7 @@ namespace ode { ProgressBar::ProgressBar(UpdateFunc const&) : updateValue(0) {} ProgressBar::~ProgressBar() {} -void ProgressBar::update(int) {} -void ProgressBar::update(int, int, int) {} +void ProgressBar::update(unsigned) {} void ProgressBar::done(void) {} } // namespace ode @@ -71,7 +70,7 @@ int main(int argc, char* argv[]) if (MOUNT == argv[1]) { auto masterKey = UpgradeSupport::loadMasterKey(DEV_PATH); - DMCryptEngine dmcrypt(DEV_PATH, INTERNAL_PATH, ProgressBar([](int){})); + DMCryptEngine dmcrypt(DEV_PATH, INTERNAL_PATH, ProgressBar([](unsigned){})); // mount options are ignored by mount() dmcrypt.mount(masterKey, 0); diff --git a/server/engine/encryption/dmcrypt-engine.cpp b/server/engine/encryption/dmcrypt-engine.cpp index 838816a..e8d8d9e 100644 --- a/server/engine/encryption/dmcrypt-engine.cpp +++ b/server/engine/encryption/dmcrypt-engine.cpp @@ -44,18 +44,18 @@ namespace ode { namespace { -blkcnt_t getBlockCount(const std::string &src) +unsigned long getBlockCount(const std::string &src) { int fd = open(src.c_str(), O_RDONLY); if (fd < 0) return 0; - unsigned long long size = 0; + unsigned long size = 0; if ((ioctl(fd, BLKGETSIZE, &size)) == -1) size = 0; close(fd); - return (blkcnt_t)size; + return size; } const std::string convertToHex(const BinaryData &binary) @@ -237,20 +237,28 @@ BinaryData sanitizeKey(const BinaryData &key) } void copyInPlace(const std::string &source, const std::string &destination, - const std::function &isTarget, - const std::function &addProgress) + unsigned int options, + ProgressBar& progress) { Ext4Tool ext4tool(source); - const blksize_t srcBlockSize = ext4tool.getBlockSize(); - const blkcnt_t srcTotalBlockCount = ext4tool.getTotalBlockCount(); + const uint32_t srcBlockSize = ext4tool.getBlockSize(); + const uint32_t srcTotalBlockCount = ext4tool.getTotalBlockCount(); char buf[srcBlockSize]; + bool fastEncryption = true; + + if (!(options & OPTION_INCLUDE_UNUSED_REGION)) { + INFO(SINK, "FastEncryption: Disabled"); + fastEncryption = false; + } else { + INFO(SINK, "FastEncryption: Enabled"); + } runtime::File src(source, O_RDONLY); runtime::File dst(destination, O_WRONLY); off_t pos = 0; - for (blkcnt_t n = 0; n < srcTotalBlockCount; n++, pos += srcBlockSize) { - if (!isTarget(n)) { + for (uint32_t n = 0; n < srcTotalBlockCount; n++, pos += srcBlockSize) { + if (!fastEncryption && !ext4tool.isUsedBlock(n)) { continue; } @@ -260,7 +268,7 @@ void copyInPlace(const std::string &source, const std::string &destination, src.read(buf, srcBlockSize); dst.write(buf, srcBlockSize); - addProgress(n, srcTotalBlockCount); + progress.update(n, srcTotalBlockCount); } } @@ -327,21 +335,8 @@ void DMCryptEngine::encrypt(const BinaryData &key, unsigned int options) // should be encrypted here. auto cryptoBlkDev = createCryptoBlkDev(source, DM_DEFAULT_LABEL_NAME, sanitizeKey(key), DM_DEFAULT_CRYPTO_NAME); - std::function isTarget; - if (!(options & OPTION_INCLUDE_UNUSED_REGION)) { - INFO(SINK, "FastEncryption: Disabled"); - isTarget = std::bind(&Ext4Tool::isUsedBlock, &ext4Source, _1); - } else { - INFO(SINK, "FastEncryption: Enabled"); - isTarget = [](unsigned int n) { - return true; - }; - } - // We always do In-place encryption - copyInPlace(source, cryptoBlkDev, isTarget, - std::bind((void(ProgressBar::*)(int, int, int))&ProgressBar::update, - &progress, _1, _2, 1)); + copyInPlace(source, cryptoBlkDev, options, progress); // remove crypto type device mapper destroyCryptoBlkDev(DM_DEFAULT_LABEL_NAME); @@ -368,21 +363,8 @@ void DMCryptEngine::decrypt(const BinaryData &key, unsigned int options) break; } - std::function isTarget; - if (!(options & OPTION_INCLUDE_UNUSED_REGION)) { - INFO(SINK, "FastEncryption: Disabled"); - isTarget = std::bind(&Ext4Tool::isUsedBlock, &ext4CryptoBlkDev, _1); - } else { - INFO(SINK, "FastEncryption: Enabled"); - isTarget = [](unsigned int n) { - return true; - }; - } - // We always do In-place decryption - copyInPlace(cryptoBlkDev, source, isTarget, - std::bind((void(ProgressBar::*)(int, int, int))&ProgressBar::update, - &progress, _1, _2, 1)); + copyInPlace(cryptoBlkDev, source, options, progress); // remove crypto type device mapper destroyCryptoBlkDev(DM_DEFAULT_LABEL_NAME); diff --git a/server/engine/encryption/ecryptfs-engine.cpp b/server/engine/encryption/ecryptfs-engine.cpp index 61538c5..18f3ba9 100644 --- a/server/engine/encryption/ecryptfs-engine.cpp +++ b/server/engine/encryption/ecryptfs-engine.cpp @@ -392,8 +392,10 @@ void EcryptfsEngine::encrypt(const BinaryData &key, unsigned int options) return true; }, [¤t, &totalSize, this](off_t size) { + if (current > std::numeric_limits::max() - size) + throw runtime::Exception("Offset too big"); current += size; - this->progress.update(current * 100 / totalSize); + this->progress.update(current, totalSize); }); } @@ -434,8 +436,10 @@ void EcryptfsEngine::decrypt(const BinaryData &key, unsigned int options) copyInPlace(tempMountpoint.getPath(), source, tempDir.getPath(), wasEncrypted, [¤t, &totalSize, this](off_t size) { + if (current > std::numeric_limits::max() - size) + throw runtime::Exception("Offset too big"); current += size; - this->progress.update(current * 100 / totalSize); + this->progress.update(current, totalSize); }); ecryptfsUmount(tempMountpoint.getPath()); diff --git a/server/engine/encryption/ext4-engine.cpp b/server/engine/encryption/ext4-engine.cpp index 6934340..b5ef2ea 100755 --- a/server/engine/encryption/ext4-engine.cpp +++ b/server/engine/encryption/ext4-engine.cpp @@ -352,8 +352,10 @@ void Ext4Engine::encrypt(const BinaryData& key, unsigned int options) off_t totalSize = getUsedSpace(source), current = 0; copyInPlace(destination, encrypted.getPath(), [¤t, &totalSize, this](off_t size) { + if (current > std::numeric_limits::max() - size) + throw runtime::Exception("Offset too big"); current += size; - this->progress.update(current, totalSize, 1); + this->progress.update(current, totalSize); }); if (::mount(encrypted.getPath().c_str(), destination.c_str(), NULL, MS_BIND, 0) < 0) { @@ -380,8 +382,10 @@ void Ext4Engine::decrypt(const BinaryData& key, unsigned int options) off_t totalSize = getUsedSpace(source), current = 0; copyInPlace(encrypted.getPath(), destination, [¤t, &totalSize, this](off_t size) { + if (current > std::numeric_limits::max() - size) + throw runtime::Exception("Offset too big"); current += size; - this->progress.update(current, totalSize, 1); + this->progress.update(current, totalSize); }); encrypted.remove(true); diff --git a/server/engine/erase/erase-engine.cpp b/server/engine/erase/erase-engine.cpp index ca508de..9bca4e1 100644 --- a/server/engine/erase/erase-engine.cpp +++ b/server/engine/erase/erase-engine.cpp @@ -16,6 +16,8 @@ */ #include "erase-engine.h" +#include + #define ERASE_SIZE 4096 namespace ode { @@ -29,12 +31,15 @@ EraseEngine::~EraseEngine() { } -void EraseEngine::discardBlock(unsigned long long offset, blksize_t size) +void EraseEngine::discardBlock(uint64_t offset, uint32_t size) { char zero[ERASE_SIZE] = {}; if (size > ERASE_SIZE) { throw runtime::Exception("[eraseBlock] : size is too big"); } + if (offset > std::numeric_limits::max()) { + throw runtime::Exception("[eraseBlock] : offset is too big"); + } runtime::File device(target); device.open(O_WRONLY); @@ -45,21 +50,21 @@ void EraseEngine::discardBlock(unsigned long long offset, blksize_t size) void EraseEngine::cleanDevice(const std::string &path) { - blkcnt_t totalBlockCount = 0; - blksize_t blockSize = 0; - unsigned long long offset = 0; + uint32_t totalBlockCount = 0; + uint32_t blockSize = 0; + uint64_t offset = 0; target = path; Ext4Tool ext4Tool(target); - totalBlockCount = (blkcnt_t)ext4Tool.getTotalBlockCount(); - blockSize = (blksize_t)ext4Tool.getBlockSize(); + totalBlockCount = ext4Tool.getTotalBlockCount(); + blockSize = ext4Tool.getBlockSize(); - for (blkcnt_t i = 0; i < totalBlockCount; i++) { + for (uint32_t i = 0; i < totalBlockCount; i++) { if (!ext4Tool.isUsedBlock(i)) { - offset = (unsigned long long)i * (unsigned long long)blockSize; + offset = static_cast(i) * blockSize; discardBlock(offset, blockSize); } - progressBar.update(i, totalBlockCount, 1); + progressBar.update(i, totalBlockCount); } progressBar.done(); } diff --git a/server/engine/erase/erase-engine.h b/server/engine/erase/erase-engine.h index 2ad61dd..d2f2d26 100644 --- a/server/engine/erase/erase-engine.h +++ b/server/engine/erase/erase-engine.h @@ -22,6 +22,7 @@ #include #include #include +#include #include #include #include @@ -44,7 +45,7 @@ public: void cleanDevice(const std::string &path); private: - void discardBlock(unsigned long long offset, blksize_t size); + void discardBlock(uint64_t offset, uint32_t size); private: ProgressBar progressBar; std::string target; diff --git a/server/engine/erase/mmc-engine.cpp b/server/engine/erase/mmc-engine.cpp index 70cec3d..79bfcea 100644 --- a/server/engine/erase/mmc-engine.cpp +++ b/server/engine/erase/mmc-engine.cpp @@ -41,10 +41,10 @@ void MMCEraseEngine::synchronization(void) return; } -void MMCEraseEngine::discardBlock(unsigned long long offset, blksize_t size) +void MMCEraseEngine::discardBlock(uint64_t offset, uint64_t size) { int descriptor = 0, ret = 0; - unsigned long long range[2] = {0, }; + uint64_t range[2] = {0, }; descriptor = ::open(target.c_str(), O_WRONLY); if (descriptor < 0) { @@ -52,7 +52,7 @@ void MMCEraseEngine::discardBlock(unsigned long long offset, blksize_t size) } range[0] = offset; - range[1] = (unsigned long long)size; + range[1] = size; ret = ::ioctl(descriptor, BLKDISCARD, &range); ::close(descriptor); @@ -63,21 +63,21 @@ void MMCEraseEngine::discardBlock(unsigned long long offset, blksize_t size) void MMCEraseEngine::cleanDevice(const std::string &path) { - blkcnt_t totalBlockCount = 0; - blksize_t blockSize = 0; - unsigned long long offset = 0; + uint32_t totalBlockCount = 0; + uint32_t blockSize = 0; + uint64_t offset = 0; target.append(path); Ext4Tool ext4Tool(target); - totalBlockCount = (blkcnt_t)ext4Tool.getTotalBlockCount(); - blockSize = (blksize_t)ext4Tool.getBlockSize(); + totalBlockCount = ext4Tool.getTotalBlockCount(); + blockSize = ext4Tool.getBlockSize(); - for (blkcnt_t i = 0; i < totalBlockCount; i++) { + for (uint32_t i = 0; i < totalBlockCount; i++) { if (!ext4Tool.isUsedBlock(i)) { - offset = (unsigned long long)i * (unsigned long long)blockSize; + offset = static_cast(i) * blockSize; discardBlock(offset, blockSize); } - progressBar.update(i, totalBlockCount, 1); + progressBar.update(i, totalBlockCount); } progressBar.done(); synchronization(); diff --git a/server/engine/erase/mmc-engine.h b/server/engine/erase/mmc-engine.h index f6f969e..5cb2f25 100644 --- a/server/engine/erase/mmc-engine.h +++ b/server/engine/erase/mmc-engine.h @@ -19,6 +19,7 @@ #define __MMC_ERASE_ENGINE_H__ #include +#include #include #include @@ -48,7 +49,7 @@ public: void cleanDevice(const std::string &target); private: void synchronization(void); - void discardBlock(unsigned long long offset, blksize_t size); + void discardBlock(uint64_t offset, uint64_t size); private: ProgressBar progressBar; std::string target; diff --git a/server/ext4-tool.cpp b/server/ext4-tool.cpp index 2fc1ffe..47ffe49 100644 --- a/server/ext4-tool.cpp +++ b/server/ext4-tool.cpp @@ -17,6 +17,7 @@ #include #include +#include #include #include @@ -37,7 +38,7 @@ namespace ode { namespace { -unsigned int divCeilSafely(unsigned int a, unsigned int b) +uint32_t divCeilSafely(uint32_t a, uint32_t b) { if (!a) return 0; @@ -102,10 +103,11 @@ bool Ext4Tool::isExt(const std::string &src) void Ext4Tool::readInfo() { - unsigned int firstDataBlock = 0; - unsigned int blocksPerGroup = 0; - unsigned int clustersPerGroup = 0; - unsigned short descSize = 0; + // TODO this function should be rewritten + uint32_t firstDataBlock = 0; + uint32_t blocksPerGroup = 0; + uint32_t clustersPerGroup = 0; + uint16_t descSize = 0; runtime::File device(source); if (!device.exists()) @@ -115,95 +117,123 @@ void Ext4Tool::readInfo() // read totalBlockCount device.lseek(ODE_SUPERBLOCK_OFFSET + 4, SEEK_SET); - device.read(&totalBlockCount, 4); + device.read(&totalBlockCount, sizeof(totalBlockCount)); // read firstDataBlock device.lseek(ODE_SUPERBLOCK_OFFSET + 20, SEEK_SET); - device.read(&firstDataBlock, 4); + device.read(&firstDataBlock, sizeof(firstDataBlock)); // read blockSize device.lseek(ODE_SUPERBLOCK_OFFSET + 24, SEEK_SET); - device.read(&blockSize, 4); + device.read(&blockSize, sizeof(blockSize)); + if ((std::numeric_limits::max() >> blockSize) < ODE_EXT2_MIN_BLOCK_SIZE) + throw runtime::Exception("Block size too big"); // blockSize must be <= 21 blockSize = (ODE_EXT2_MIN_BLOCK_SIZE << blockSize); // read blocksPerGroup device.lseek(ODE_SUPERBLOCK_OFFSET + 32, SEEK_SET); - device.read(&blocksPerGroup, 4); + device.read(&blocksPerGroup, sizeof(blocksPerGroup)); // read clustersPerGroup device.lseek(ODE_SUPERBLOCK_OFFSET + 36, SEEK_SET); - device.read(&clustersPerGroup, 4); + device.read(&clustersPerGroup, sizeof(clustersPerGroup)); // read descSize device.lseek(ODE_SUPERBLOCK_OFFSET + 0xFE, SEEK_SET); - device.read(&descSize, 2); + device.read(&descSize, sizeof(descSize)); if (descSize < ODE_EXT2_MIN_DESC_SIZE) { descSize = ODE_EXT2_MIN_DESC_SIZE; } - unsigned int groupDescCount = divCeilSafely(totalBlockCount - firstDataBlock, blocksPerGroup); - int blockNbytes = clustersPerGroup / 8; + if (firstDataBlock >= totalBlockCount) + throw runtime::Exception("Invalid block info"); + uint32_t groupDescCount = divCeilSafely(totalBlockCount - firstDataBlock, blocksPerGroup); // read group_desc - unsigned int descPerBlock = blockSize / descSize; - unsigned int descBlockCount = divCeilSafely(groupDescCount, descPerBlock); + uint32_t descPerBlock = blockSize / descSize; + uint32_t descBlockCount = divCeilSafely(groupDescCount, descPerBlock); // read first meta block + if (descBlockCount > std::numeric_limits::max() / blockSize) + throw runtime::Exception("Size too big for BinaryData"); BinaryData group_desc(descBlockCount * blockSize); + // firstDataBlock < totalBlockCount so no overflow is possible device.lseek((firstDataBlock + 1) * blockSize, SEEK_SET); - device.read(group_desc.data(), (descBlockCount * blockSize)); + device.read(group_desc.data(), group_desc.size()); - unsigned int cnt = blockNbytes << 3; - unsigned int blkItr = firstDataBlock; + uint32_t blkItr = firstDataBlock; // this structure just is used for easy type-casting. struct odeExtGroupDesc { - unsigned int blockBitmap; /* Blocks bitmap block */ + uint32_t blockBitmap; /* Blocks bitmap block */ /* skip other member */ }; // read bitmap { - unsigned int start = firstDataBlock; - unsigned int real_end = blocksPerGroup * groupDescCount - 1 + start; - size_t size = (size_t) (((real_end - start) / 8) + 1); + uint32_t start = firstDataBlock; + uint32_t real_end = totalBlockCount - 1; + + uint32_t size = (real_end - start) / 8 + 1; size = (size + 7) & ~3; + if (std::numeric_limits::max() <= size) + throw runtime::Exception("Bitmap size too big"); + bitmap.resize(size); } - for (unsigned int i = 0; i < groupDescCount; i++) { - unsigned int blk = (((struct odeExtGroupDesc *)(((unsigned char *)(group_desc.data())) + i * descSize))->blockBitmap); + if (groupDescCount >= group_desc.size() / descSize) + throw runtime::Exception("Group descriptors buffer too small"); + + if (blockSize > std::numeric_limits::max()) + throw runtime::Exception("Block size too big"); + + if (clustersPerGroup > std::numeric_limits::max() - 7) + throw runtime::Exception("Too many clusters per group"); + + if (groupDescCount > (std::numeric_limits::max() - blkItr) / clustersPerGroup + 1) + throw runtime::Exception("Block iterator may get too big"); + + if (((blkItr + clustersPerGroup * (groupDescCount - 1)) >> 3) + ((clustersPerGroup + 7) >> 3) > bitmap.size()) + throw runtime::Exception("Bitmap size too small"); + + for (uint32_t i = 0; i < groupDescCount; i++) { + uint32_t blk = reinterpret_cast(group_desc.data() + i * descSize)->blockBitmap; try { BinaryData block_bitmap(blockSize); + + if (blk > std::numeric_limits::max() / blockSize) + throw runtime::Exception("Block bitmap index too big"); + device.lseek(blk * blockSize, SEEK_SET); device.read(block_bitmap.data(), blockSize); - memcpy(bitmap.data() + (blkItr >> 3), block_bitmap.data(), (cnt + 7) >> 3); + memcpy(bitmap.data() + (blkItr >> 3), block_bitmap.data(), (clustersPerGroup + 7) >> 3); } catch (runtime::Exception &e) { WARN(SINK, "Block " + std::to_string(blk) + " is missing"); - memset(bitmap.data() + (blkItr >> 3), 0, (cnt + 7) >> 3); + memset(bitmap.data() + (blkItr >> 3), 0, (clustersPerGroup + 7) >> 3); } - blkItr += cnt; + blkItr += clustersPerGroup; } device.close(); } -unsigned int Ext4Tool::getBlockSize() +uint32_t Ext4Tool::getBlockSize() { return blockSize; } -unsigned int Ext4Tool::getTotalBlockCount() +uint32_t Ext4Tool::getTotalBlockCount() { return totalBlockCount; } -bool Ext4Tool::isUsedBlock(unsigned int blockIndex) +bool Ext4Tool::isUsedBlock(uint32_t blockIndex) { unsigned char *addr = (bitmap.data() + (blockIndex >> 3)); - int mask = 1 << (blockIndex & 0x07); + unsigned char mask = 1 << (blockIndex & 0x07); if (mask & *addr) return true; diff --git a/server/ext4-tool.h b/server/ext4-tool.h index 711d093..0b0d43c 100644 --- a/server/ext4-tool.h +++ b/server/ext4-tool.h @@ -17,6 +17,8 @@ #ifndef __EXT4_TOOL_H__ #define __EXT4_TOOL_H__ +#include + #include #include @@ -35,9 +37,9 @@ public: Ext4Tool &operator=(const Ext4Tool &) = delete; Ext4Tool &operator=(Ext4Tool &&) = delete; - unsigned int getBlockSize(); - unsigned int getTotalBlockCount(); - bool isUsedBlock(unsigned int blockIndex); + uint32_t getBlockSize(); + uint32_t getTotalBlockCount(); + bool isUsedBlock(uint32_t blockIndex); void forceCleanUp(); static bool isExt(const std::string &src); @@ -46,7 +48,7 @@ public: private: void readInfo(); std::string source; - unsigned int blockSize, totalBlockCount; + uint32_t blockSize, totalBlockCount; BinaryData bitmap; }; diff --git a/server/external-encryption.cpp b/server/external-encryption.cpp index 09af99f..261a097 100644 --- a/server/external-encryption.cpp +++ b/server/external-encryption.cpp @@ -206,7 +206,7 @@ ExternalEncryptionServer::ExternalEncryptionServer(ServerContext &srv, engine.reset(new EXTERNAL_ENGINE( EXTERNAL_PATH, EXTERNAL_PATH, - ProgressBar([](int v) { + ProgressBar([](unsigned v) { ::vconf_set_str(VCONFKEY_SDE_ENCRYPT_PROGRESS, std::to_string(v).c_str()); }) diff --git a/server/internal-encryption.cpp b/server/internal-encryption.cpp index 3bc21b2..5e86b0c 100644 --- a/server/internal-encryption.cpp +++ b/server/internal-encryption.cpp @@ -316,7 +316,7 @@ InternalEncryptionServer::InternalEncryptionServer(ServerContext& srv, KeyServer engine.reset(new INTERNAL_ENGINE( source, INTERNAL_PATH, - ProgressBar([](int v) { + ProgressBar([](unsigned v) { ::vconf_set_str(VCONFKEY_ODE_ENCRYPT_PROGRESS, std::to_string(v).c_str()); }) diff --git a/server/progress-bar.cpp b/server/progress-bar.cpp index 6feef7c..cc9ea47 100644 --- a/server/progress-bar.cpp +++ b/server/progress-bar.cpp @@ -28,7 +28,7 @@ ProgressBar::~ProgressBar() { } -void ProgressBar::update(int value) +void ProgressBar::update(unsigned value) { if (updateValue != value) { updateValue = value; @@ -36,11 +36,6 @@ void ProgressBar::update(int value) } } -void ProgressBar::update(int curCount, int totalCount, int unit) -{ - update(((curCount * 100) / totalCount) * unit); -} - void ProgressBar::done(void) { updateValue = 100; diff --git a/server/progress-bar.h b/server/progress-bar.h index f2a7bb8..e28778a 100644 --- a/server/progress-bar.h +++ b/server/progress-bar.h @@ -18,26 +18,45 @@ #define __ODE_PROGRESS_BAR_H__ #include +#include +#include namespace ode { class ProgressBar { public: - typedef std::function UpdateFunc; + typedef std::function UpdateFunc; ProgressBar() = delete; - ProgressBar(UpdateFunc const &updater); + explicit ProgressBar(UpdateFunc const &updater); ~ProgressBar(); - void update(int value); - void update(int count, int totalCount, int unit); + void update(unsigned value); + + template + void update(T count, T totalCount); + void done(void); private: UpdateFunc updater; - int updateValue; + unsigned updateValue; }; + +template +void ProgressBar::update(T count, T totalCount) +{ + assert(count <= totalCount); + assert(totalCount > 0); + + if (count > std::numeric_limits::max() / 100) + update(count / (totalCount / 100)); + else + update((count * 100) / totalCount); +} + + } // namespace ode #endif //__ODE_PROGRESS_BAR_H__ diff --git a/server/secure-erase.cpp b/server/secure-erase.cpp index 025c2a2..7cbfab3 100644 --- a/server/secure-erase.cpp +++ b/server/secure-erase.cpp @@ -55,7 +55,7 @@ SecureEraseServer::SecureEraseServer(ServerContext &srv) : { server.expose(this, PRIVILEGE_PLATFORM, (int)(SecureEraseServer::clean)(std::string)); - engine.reset(new ERASE_ENGINE(ProgressBar([](int v) { + engine.reset(new ERASE_ENGINE(ProgressBar([](unsigned v) { ::vconf_set_str(VCONFKEY_ODE_ERASE_PROGRESS, std::to_string(v).c_str()); })) ); diff --git a/tests/dmcrypt-engine.cpp b/tests/dmcrypt-engine.cpp index 74c207f..051801f 100644 --- a/tests/dmcrypt-engine.cpp +++ b/tests/dmcrypt-engine.cpp @@ -39,7 +39,7 @@ using namespace ode; namespace { -ProgressBar progress([](int v) {}); +ProgressBar progress([](unsigned) {}); } diff --git a/tests/ecryptfs-engine.cpp b/tests/ecryptfs-engine.cpp index 6d13631..97005be 100644 --- a/tests/ecryptfs-engine.cpp +++ b/tests/ecryptfs-engine.cpp @@ -25,7 +25,7 @@ TESTCASE(EcryptfsGetPathTest) { try { - ode::ProgressBar progress([](int v) {}); + ode::ProgressBar progress([](unsigned v) {}); ode::EcryptfsEngine engine("/dev/mmcblkp0", "/opt/usr", progress); if (engine.getSource() != "/dev/mmcblkp0") { throw runtime::Exception("Source doen't match"); diff --git a/tests/ext4-engine.cpp b/tests/ext4-engine.cpp index 97b3350..4c3d5a1 100755 --- a/tests/ext4-engine.cpp +++ b/tests/ext4-engine.cpp @@ -25,7 +25,7 @@ TESTCASE(Ext4GetPathTest) { try { - ode::ProgressBar progress([](int v) {}); + ode::ProgressBar progress([](unsigned v) {}); ode::Ext4Engine engine("/dev/mmcblkp0", "/opt/usr", progress); if (engine.getSource() != "/dev/mmcblkp0") { throw runtime::Exception("Source doen't match"); -- 2.7.4