~aleteoryx/muditaos

0f0192a8b4a92f5a8bd768da14a142b9d45b7935 — Borys Jelenski 5 years ago 2c80592
[EGD-5072] Refactor legacy VFS functions

Functions were refactored and renamed for better readability.
Some of them were moved to different files. In stat_vfs function
the order of member initializations was corrected.
M module-services/service-desktop/endpoints/update/UpdateMuditaOS.cpp => module-services/service-desktop/endpoints/update/UpdateMuditaOS.cpp +1 -2
@@ 377,14 377,13 @@ updateos::UpdateError UpdateMuditaOS::prepareRoot()

updateos::UpdateError UpdateMuditaOS::updateBootJSON()
{
    unsigned long bootJSONAbsoulteCRC = 0;
    fs::path bootJSONAbsoulte         = purefs::createPath(purefs::dir::getRootDiskPath(), purefs::file::boot_json);
    informDebug("updateBootJSON %s", bootJSONAbsoulte.c_str());

    auto *fp = std::fopen(bootJSONAbsoulte.c_str(), "r");

    if (fp != nullptr) {
        utils::filesystem::computeCRC32(fp, &bootJSONAbsoulteCRC);
        unsigned long bootJSONAbsoulteCRC = utils::filesystem::computeFileCRC32(fp);
        bootJSONAbsoulte += boot::consts::ext_crc32;

        auto *fpCRC = std::fopen(bootJSONAbsoulte.c_str(), "w");

M module-utils/Utils.cpp => module-utils/Utils.cpp +11 -13
@@ 9,7 9,7 @@ namespace utils::filesystem
{
    namespace
    {
        inline constexpr auto crc_buf = 1024;
        inline constexpr auto crc_buf_len = 1024;
    } // namespace

    long int filelength(std::FILE *file) noexcept


@@ 24,23 24,21 @@ namespace utils::filesystem
        return endPosition;
    }

    void computeCRC32(std::FILE *file, unsigned long *outCrc32) noexcept
    unsigned long computeFileCRC32(::FILE *file) noexcept
    {
        if (outCrc32 == nullptr)
            return;

        auto buf = std::make_unique<unsigned char[]>(crc_buf);
        size_t bufLen;

        *outCrc32 = 0;
        auto buf = std::make_unique<unsigned char[]>(crc_buf_len);

        unsigned long crc32 = 0;
        while (!std::feof(file)) {
            bufLen = std::fread(buf.get(), 1, crc_buf, file);
            if (bufLen <= 0)
                break;
            size_t dataLen = std::fread(buf.get(), 1, crc_buf_len, file);
            if (dataLen == 0) {
                return crc32;
            }

            *outCrc32 = Crc32_ComputeBuf(*outCrc32, buf.get(), bufLen);
            crc32 = Crc32_ComputeBuf(crc32, buf.get(), dataLen);
        }

        return crc32;
    }

    std::string generateRandomId(std::size_t length) noexcept

M module-utils/Utils.hpp => module-utils/Utils.hpp +1 -1
@@ 253,7 253,7 @@ namespace utils
    namespace filesystem
    {
        [[nodiscard]] long int filelength(std::FILE *file) noexcept;
        void computeCRC32(std::FILE *file, unsigned long *outCrc32) noexcept;
        [[nodiscard]] unsigned long computeFileCRC32(std::FILE *file) noexcept;
        [[nodiscard]] std::string generateRandomId(std::size_t length = 0) noexcept;
        [[nodiscard]] std::string getline(std::FILE *stream, uint32_t length = 1024) noexcept;
    } // namespace filesystem

M module-utils/bootconfig/include/boot/bootconfig.hpp => module-utils/bootconfig/include/boot/bootconfig.hpp +1 -3
@@ 64,9 64,7 @@ namespace boot

      private:
        bool loadBootConfig(const std::filesystem::path &bootJsonPath);
        const std::filesystem::path getCurrentBootJSON();
        bool verifyCRC(const std::filesystem::path filePath);
        bool verifyCRC(const std::string filePath, const unsigned long crc32);
        std::filesystem::path getCurrentBootJSON();

      private:
        std::string m_os_image{"boot.bin"};

M module-utils/bootconfig/src/bootconfig.cpp => module-utils/bootconfig/src/bootconfig.cpp +101 -123
@@ 3,6 3,7 @@
#include <boot/bootconfig.hpp>
#include <boot/bootconstants.hpp>

#include <module-utils/gsl/gsl_util>
#include <limits.h>
#include <purefs/filesystem_paths.hpp>
#include <source/version.hpp>


@@ 12,94 13,74 @@
#include <fstream>
#include <log/log.hpp>
#include <crc32/crc32.h>
#include <array>
#include <Utils.hpp>

namespace boot
{
    namespace
    {

        bool replaceWithString(const std::filesystem::path &fileToModify, const std::string &stringToWrite)
        bool writeToFile(const std::filesystem::path &file, const std::string &stringToWrite)
        {
            auto lamb = [](::FILE *stream) { fclose(stream); };
            std::unique_ptr<::FILE, decltype(lamb)> fp(fopen(fileToModify.c_str(), "w"), lamb);

            if (fp.get() != nullptr) {
                size_t dataWritten = fwrite(stringToWrite.c_str(), stringToWrite.length(), 1, fp.get());
                return dataWritten == 1;
            }
            else {
            auto fp = fopen(file.c_str(), "w");
            if (!fp) {
                return false;
            }
        }
        void computeCRC32(std::FILE *file, unsigned long *outCrc32)
        {
            if (outCrc32 == nullptr)
                return;
            std::unique_ptr<unsigned char[]> buf(new unsigned char[boot::consts::crc_buf]);
            size_t bufLen;

            *outCrc32 = 0;
            size_t dataWritten = fwrite(stringToWrite.c_str(), stringToWrite.length(), 1, fp);

            while (!std::feof(file)) {
                bufLen = std::fread(buf.get(), 1, boot::consts::crc_buf, file);
                if (bufLen <= 0)
                    break;
            fclose(fp);

                *outCrc32 = Crc32_ComputeBuf(*outCrc32, buf.get(), bufLen);
            }
            return dataWritten == 1;
        }

        bool updateFileCRC32(const std::filesystem::path &file)
        {
            unsigned long fileCRC32 = 0;
            auto lamb               = [](::FILE *stream) { ::fclose(stream); };

            std::unique_ptr<::FILE, decltype(lamb)> fp(fopen(file.c_str(), "r"), lamb);

            if (fp.get() != nullptr) {
                std::unique_ptr<char[]> crc32Buf(new char[boot::consts::crc_char_size]);
                int written = 0;
                computeCRC32(fp.get(), &fileCRC32);
                LOG_INFO("updateFileCRC32 writing new crc32 %08" PRIX32 " for %s",
                         static_cast<std::uint32_t>(fileCRC32),
                         file.c_str());
                if (fileCRC32 != 0) {
                    if ((written = sprintf(crc32Buf.get(), "%08" PRIX32, fileCRC32)) !=
                        (boot::consts::crc_char_size - 1)) {
                        LOG_INFO("updateFileCRC32 can't prepare string for crc32, sprintf returned %d instead of %d",
                                 written,
                                 boot::consts::crc_char_size - 1);
                        return false;
                    }
                    std::filesystem::path fileCRC32Path = file;
                    fileCRC32Path += boot::consts::ext_crc32;

                    std::unique_ptr<::FILE, decltype(lamb)> fpCRC32(fopen(fileCRC32Path.c_str(), "w"), lamb);

                    if (fpCRC32.get() != nullptr) {
                        if (fwrite(crc32Buf.get(), 1, boot::consts::crc_char_size, fpCRC32.get()) ==
                            boot::consts::crc_char_size) {
                            LOG_INFO("updateFileCRC32 wrote \"%s\" in %s", crc32Buf.get(), fileCRC32Path.c_str());
                            return true;
                        }
                        else {
                            LOG_WARN("updateFileCRC32 can't write new crc32");
                            return false;
                        }
                    }
                    else {
                        LOG_WARN("updateFileCRC32 can't open crc32 file for write");
                        return false;
                    }
                }
            }
            else {
            auto fp = fopen(file.c_str(), "r");
            if (!fp) {
                LOG_WARN("updateFileCRC32 can't open file %s for write", file.c_str());
                return false;
            }
            auto fpCloseAct = gsl::finally([fp] { fclose(fp); });

            return false;
            unsigned long fileCRC32 = utils::filesystem::computeFileCRC32(fp);
            LOG_INFO("updateFileCRC32 writing new crc32 %08" PRIX32 " for %s",
                     static_cast<std::uint32_t>(fileCRC32),
                     file.c_str());

            if (fileCRC32 == 0) {
                return false;
            }

            std::array<char, boot::consts::crc_char_size> crc32Buf;

            if (int written = sprintf(crc32Buf.data(), "%08" PRIX32, fileCRC32);
                written != boot::consts::crc_char_size - 1) {
                LOG_INFO("updateFileCRC32 can't prepare string for crc32, sprintf returned %d instead of %d",
                         written,
                         boot::consts::crc_char_size - 1);
                return false;
            }

            std::filesystem::path fileCRC32Path = file;
            fileCRC32Path += boot::consts::ext_crc32;

            auto fpCRC32 = fopen(fileCRC32Path.c_str(), "w");
            if (!fpCRC32) {
                LOG_WARN("updateFileCRC32 can't open crc32 file for write");
                return false;
            }
            auto fpCRC32CloseAct = gsl::finally([fpCRC32] { fclose(fpCRC32); });

            if (fwrite(crc32Buf.data(), 1, boot::consts::crc_char_size, fpCRC32) != boot::consts::crc_char_size) {
                LOG_WARN("updateFileCRC32 can't write new crc32");
                return false;
            }

            LOG_INFO("updateFileCRC32 wrote \"%s\" in %s", crc32Buf.data(), fileCRC32Path.c_str());
            return true;
        }

        std::string loadFileAsString(const std::filesystem::path &fileToLoad)
        {
            std::string content;


@@ 108,6 89,50 @@ namespace boot
            return content;
        }

        bool verifyCRC(const std::filesystem::path &file, const unsigned long crc32)
        {
            auto fp = fopen(file.c_str(), "r");
            if (!fp) {
                LOG_ERROR("verifyCRC can't open %s", file.c_str());
                return false;
            }
            auto fpCloseAct = gsl::finally([fp] { fclose(fp); });

            unsigned long crc32Read = utils::filesystem::computeFileCRC32(fp);
            LOG_INFO(
                "verifyCRC computed crc32 for %s is %08" PRIX32, file.c_str(), static_cast<std::uint32_t>(crc32Read));

            return crc32Read == crc32;
        }

        bool readAndVerifyCRC(const std::filesystem::path &file)
        {
            std::filesystem::path crcFilePath(file);
            crcFilePath += boot::consts::ext_crc32;

            auto fp = fopen(crcFilePath.c_str(), "r");
            if (!fp) {
                LOG_ERROR("verifyCRC can't open %s", crcFilePath.c_str());
                return false;
            }
            auto fpCloseAct = gsl::finally([fp] { fclose(fp); });

            std::array<char, boot::consts::crc_char_size> crcBuf;

            if (size_t readSize = std::fread(crcBuf.data(), 1, boot::consts::crc_char_size, fp);
                readSize != boot::consts::crc_char_size) {
                LOG_ERROR("verifyCRC fread on %s returned different size then %d [%zu]",
                          crcFilePath.c_str(),
                          boot::consts::crc_char_size,
                          readSize);
                return false;
            }

            const unsigned long crc32Read = strtoull(crcBuf.data(), nullptr, boot::consts::crc_radix);

            LOG_INFO("verifyCRC read %s string:\"%s\" hex:%08lX", crcFilePath.c_str(), crcBuf.data(), crc32Read);
            return verifyCRC(file, crc32Read);
        }
    } // namespace

    BootConfig::BootConfig() : m_os_root_path(purefs::dir::getRootDiskPath())


@@ 166,7 191,7 @@ namespace boot
        m_timestamp = utils::time::Timestamp().str("%c");
        LOG_INFO("vfs::updateTimestamp \"%s\"", to_json().dump().c_str());

        if (replaceWithString(m_boot_json, to_json().dump())) {
        if (writeToFile(m_boot_json, to_json().dump())) {
            updateFileCRC32(m_boot_json);
        }
    }


@@ 183,11 208,11 @@ namespace boot
        if (parseErrors == "") {
            m_os_type            = m_boot_json_parsed[boot::json::main][boot::json::os_type].string_value();
            m_os_image           = m_boot_json_parsed[boot::json::main][boot::json::os_image].string_value();
            m_os_root_path = purefs::createPath(purefs::dir::getRootDiskPath(), m_os_type);
            m_boot_json    = bootJsonPath;
            m_os_root_path       = purefs::createPath(purefs::dir::getRootDiskPath(), m_os_type);
            m_boot_json          = bootJsonPath;
            m_bootloader_version = m_boot_json_parsed[boot::json::bootloader][boot::json::os_version].string_value();
            m_timestamp  = utils::time::Timestamp().str("%c");
            m_os_version = std::string(VERSION);
            m_timestamp          = utils::time::Timestamp().str("%c");
            m_os_version         = std::string(VERSION);

            LOG_INFO("boot_config: %s", to_json().dump().c_str());
            return true;


@@ 203,61 228,14 @@ namespace boot
            return false;
        }
    }
    const std::filesystem::path BootConfig::getCurrentBootJSON()
    std::filesystem::path BootConfig::getCurrentBootJSON()
    {
        if (verifyCRC(purefs::file::boot_json)) {
        if (readAndVerifyCRC(purefs::file::boot_json)) {
            return purefs::createPath(purefs::dir::getRootDiskPath(), purefs::file::boot_json);
        }
        LOG_INFO("vfs::getCurrentBootJSON crc check failed on %s", purefs::file::boot_json);
        // replace broken .boot.json with a default one
        replaceWithString(purefs::dir::getRootDiskPath() / purefs::file::boot_json, to_json().dump());
        writeToFile(purefs::dir::getRootDiskPath() / purefs::file::boot_json, to_json().dump());
        return purefs::createPath(purefs::dir::getRootDiskPath(), purefs::file::boot_json);
    }

    bool BootConfig::verifyCRC(const std::string filePath, const unsigned long crc32)
    {
        unsigned long crc32Read;
        auto lamb = [](::FILE *stream) { ::fclose(stream); };

        std::unique_ptr<::FILE, decltype(lamb)> fp(::fopen(filePath.c_str(), "r"), lamb);

        if (fp.get() != nullptr) {
            computeCRC32(fp.get(), &crc32Read);
            LOG_INFO("verifyCRC computed crc32 for %s is %08" PRIX32,
                     filePath.c_str(),
                     static_cast<std::uint32_t>(crc32Read));
            return (crc32Read == crc32);
        }
        LOG_ERROR("verifyCRC can't open %s", filePath.c_str());
        return (false);
    }

    bool BootConfig::verifyCRC(const std::filesystem::path filePath)
    {
        auto lamb = [](::FILE *stream) { ::fclose(stream); };
        std::unique_ptr<char[]> crcBuf(new char[boot::consts::crc_char_size]);
        size_t readSize;
        std::filesystem::path crcFilePath(filePath);
        crcFilePath += boot::consts::ext_crc32;

        std::unique_ptr<::FILE, decltype(lamb)> fp(::fopen(crcFilePath.c_str(), "r"), lamb);

        if (fp.get() != nullptr) {
            if ((readSize = ::fread(crcBuf.get(), 1, boot::consts::crc_char_size, fp.get())) !=
                (boot::consts::crc_char_size)) {
                LOG_ERROR("verifyCRC fread on %s returned different size then %d [%zu]",
                          crcFilePath.c_str(),
                          boot::consts::crc_char_size,
                          readSize);
                return false;
            }

            const unsigned long crc32Read = strtoull(crcBuf.get(), nullptr, boot::consts::crc_radix);

            LOG_INFO("verifyCRC read %s string:\"%s\" hex:%08lX", crcFilePath.c_str(), crcBuf.get(), crc32Read);
            return verifyCRC(filePath, crc32Read);
        }
        LOG_ERROR("verifyCRC can't open %s", crcFilePath.c_str());
        return false;
    }
} // namespace boot

M module-vfs/drivers/src/purefs/fs/filesystem_littlefs.cpp => module-vfs/drivers/src/purefs/fs/filesystem_littlefs.cpp +1 -2
@@ 297,12 297,11 @@ namespace purefs::fs::drivers
            stat.f_blocks  = cfg->block_count;
            stat.f_bfree   = stat.f_blocks - lerr;
            stat.f_bavail  = stat.f_bfree;
            lerr           = 0;
            stat.f_bsize   = cfg->prog_size;
            stat.f_frsize  = cfg->block_size;
            stat.f_blocks  = cfg->block_count;
            stat.f_namemax = PATH_MAX;
            stat.f_flag    = vmnt->flags();
            lerr           = 0;
        }
        return lfs_to_errno(lerr);
    }