~aleteoryx/muditaos

6ce0dc4df3820d0cb3cf2e5b22fb2f2feb3d0d79 — jimmorrisson 5 years ago 9c9e921
[EGD-4751] Change: new filesystem handling implementation in module services. (#1151)

Due to vfs deprecation there is need to remove all vfs calls from code. This PR covers module services. It also contains minor fixes in module-services.
M module-services/service-db/agents/file_indexer/FileIndexerAgent.cpp => module-services/service-db/agents/file_indexer/FileIndexerAgent.cpp +2 -3
@@ 6,8 6,7 @@

#include <log/log.hpp>
#include <module-sys/Service/Bus.hpp>
#include <vfs.hpp>

#include <purefs/filesystem_paths.hpp>
#include <memory>

FileIndexerAgent::FileIndexerAgent(sys::Service *parentService) : DatabaseAgent(parentService)


@@ 79,7 78,7 @@ auto FileIndexerAgent::getDbInitString() -> const std::string

auto FileIndexerAgent::getDbFilePath() -> const std::string
{
    return USER_PATH("file_indexer.db");
    return (purefs::dir::getUserDiskPath() / "file_indexer.db").string();
}
auto FileIndexerAgent::getAgentName() -> const std::string
{

M module-services/service-db/agents/settings/SettingsAgent.cpp => module-services/service-db/agents/settings/SettingsAgent.cpp +2 -3
@@ 9,7 9,7 @@
#include <Database/Database.hpp>
#include <Service/Service.hpp>
#include <module-sys/Service/Bus.hpp>
#include <vfs.hpp>
#include <purefs/filesystem_paths.hpp>

namespace settings::DbPaths
{


@@ 85,8 85,7 @@ auto SettingsAgent::getDbInitString() -> const std::string

auto SettingsAgent::getDbFilePath() -> const std::string
{

    return USER_PATH("settings_v2.db");
    return (purefs::dir::getUserDiskPath() / "settings_v2.db").string();
}
auto SettingsAgent::getAgentName() -> const std::string
{

M module-services/service-desktop/ServiceDesktop.cpp => module-services/service-desktop/ServiceDesktop.cpp +0 -1
@@ 18,7 18,6 @@
#include <module-apps/application-desktop/ApplicationDesktop.hpp>
#include <service-db/service-db/Settings.hpp>
#include <service-db/QueryMessage.hpp>
#include <vfs.hpp>

#include <cinttypes>
#include <filesystem>

M module-services/service-desktop/WorkerDesktop.cpp => module-services/service-desktop/WorkerDesktop.cpp +2 -2
@@ 154,10 154,10 @@ void WorkerDesktop::rawDataReceived(void *dataPtr, uint32_t dataLen)
            return;
        }

        const uint32_t bytesWritten = fwrite(dataPtr, 1, dataLen, fileDes);
        const uint32_t bytesWritten = std::fwrite(dataPtr, 1, dataLen, fileDes);

        if (bytesWritten != dataLen) {
            LOG_ERROR("transferDataReceived vfs write failed bytesWritten=%" PRIu32 " != dataLen=%" PRIu32,
            LOG_ERROR("transferDataReceived write failed bytesWritten=%" PRIu32 " != dataLen=%" PRIu32,
                      bytesWritten,
                      dataLen);
            return;

M module-services/service-desktop/endpoints/backup/BackupEndpoint.cpp => module-services/service-desktop/endpoints/backup/BackupEndpoint.cpp +1 -2
@@ 12,7 12,6 @@
#include <Service/Bus.hpp>
#include <json/json11.hpp>
#include <purefs/filesystem_paths.hpp>
#include <vfs.hpp>

#include <filesystem>
#include <memory>


@@ 61,7 60,7 @@ auto BackupEndpoint::request(Context &context) -> sys::ReturnCodes
auto BackupEndpoint::upload(Context &context) -> sys::ReturnCodes
{
    if (context.getBody()[json::backupUpload] == true) {
        if (const auto backupOSPath = purefs::dir::getBackupOSPath(); vfs.fileExists(backupOSPath.c_str())) {
        if (const auto backupOSPath = purefs::dir::getBackupOSPath(); std::filesystem::exists(backupOSPath.c_str())) {
            context.setResponseBody(json11::Json::object({{json::backupUpload, true}}));
        }
        else {

M module-services/service-desktop/endpoints/backup/BackupRestore.cpp => module-services/service-desktop/endpoints/backup/BackupRestore.cpp +70 -80
@@ 9,7 9,6 @@
#include <purefs/filesystem_paths.hpp>
#include <service-db/DBServiceAPI.hpp>
#include <service-db/DBServiceName.hpp>
#include <vfs.hpp>

#include <cassert>
#include <filesystem>


@@ 81,13 80,15 @@ void BackupRestore::RestoreUserFiles(sys::Service *ownerService)
bool BackupRestore::RemoveBackupDir()
{
    /* prepare directories */
    if (const auto backupOSPath = purefs::dir::getBackupOSPath(); vfs.isDir(backupOSPath.c_str())) {
    if (const auto backupOSPath = purefs::dir::getBackupOSPath(); std::filesystem::is_directory(backupOSPath.c_str())) {
        LOG_INFO("RemoveBackupDir: removing backup directory %s...", backupOSPath.c_str());

        if (vfs.deltree(backupOSPath.c_str()) != 0) {
            LOG_ERROR("RemoveBackupDir: removing backup directory %s failed, error: %s.",
                      backupOSPath.c_str(),
                      vfs.lastErrnoToStr().c_str());
        try {
            std::filesystem::remove_all(backupOSPath.c_str());
        }
        catch (const std::filesystem::filesystem_error &e) {
            LOG_ERROR(
                "RemoveBackupDir: removing backup directory %s failed, error: %s.", backupOSPath.c_str(), e.what());
            return false;
        }
    }


@@ 100,11 101,9 @@ bool BackupRestore::CreateBackupDir()
    const auto backupOSPath = purefs::dir::getBackupOSPath();
    LOG_INFO("CreateBackupDir: creating backup directory %s...", backupOSPath.c_str());

    if (vfs.isDir(backupOSPath.c_str()) == false) {
        if (vfs.mkdir(backupOSPath.c_str()) != 0) {
            LOG_ERROR("CreateBackupDir: creating backup directory %s failed, error: %s.",
                      backupOSPath.c_str(),
                      vfs.lastErrnoToStr().c_str());
    if (!std::filesystem::is_directory(backupOSPath.c_str())) {
        if (!std::filesystem::create_directory(backupOSPath.c_str())) {
            LOG_ERROR("CreateBackupDir: creating backup directory %s failed.", backupOSPath.c_str());
            return false;
        }
    }


@@ 118,19 117,13 @@ bool BackupRestore::PackUserFiles()
    backupPathDB += "/";

    const auto backupOSPath                  = purefs::dir::getBackupOSPath();
    std::vector<vfs::DirectoryEntry> dirlist = vfs.listdir(backupOSPath.c_str(), "", true);

    if (dirlist.size() <= empty_dirlist_size) {
        /* vfs.listdir also lists two extra directories ".." and "..." by default, they shall be ignored */
    if (std::filesystem::is_empty(backupOSPath.c_str())) {
        LOG_ERROR("PackUserFiles: backup dir %s is empty, nothing to backup, quitting...", backupOSPath.c_str());
        BackupRestore::RemoveBackupDir();
        return false;
    }

    LOG_INFO("PackUserFiles: backup dir %s listed with %lu files.",
             backupOSPath.c_str(),
             dirlist.size() - empty_dirlist_size);

    std::string tarFilePath = backupOSPath;
    tarFilePath += "/";
    tarFilePath += backup_file_name;


@@ 150,76 143,78 @@ bool BackupRestore::PackUserFiles()

    std::unique_ptr<unsigned char[]> buffer(new unsigned char[purefs::buffer::tar_buf]);

    for (auto &direntry : dirlist) {
        if ((direntry.fileName.compare(".") != 0) && (direntry.fileName.compare("..") != 0) &&
            (direntry.fileName.compare("...") != 0)) {
    for (auto &direntry : std::filesystem::directory_iterator(backupOSPath.c_str())) {
        if ((direntry.path().string().compare(".") != 0) && (direntry.path().string().compare("..") != 0) &&
            (direntry.path().string().compare("...") != 0)) {

            LOG_INFO("PackUserFiles: archiving file %s...", (backupPathDB + direntry.fileName).c_str());
            vfs::FILE *file = vfs.fopen((backupPathDB + direntry.fileName).c_str(), "r");
            LOG_INFO("PackUserFiles: archiving file %s...", (backupPathDB + direntry.path().string()).c_str());
            auto *file = std::fopen((backupPathDB + direntry.path().string()).c_str(), "r");

            if (file == nullptr) {
                LOG_ERROR("PackUserFiles: archiving file %s failed, cannot open file, quitting...",
                          direntry.fileName.c_str());
                          direntry.path().string().c_str());
                mtar_close(&tarFile);
                BackupRestore::RemoveBackupDir();
                return false;
            }

            LOG_INFO("PackUserFiles: writting tar header for %s...", direntry.fileName.c_str());
            LOG_INFO("PackUserFiles: writting tar header for %s...", direntry.path().string().c_str());

            if (mtar_write_file_header(&tarFile, direntry.fileName.c_str(), static_cast<unsigned>(direntry.fileSize)) !=
                MTAR_ESUCCESS) {
                LOG_ERROR("PackUserFiles: writing tar header for %s failed", direntry.fileName.c_str());
                vfs.fclose(file);
            if (mtar_write_file_header(&tarFile,
                                       direntry.path().string().c_str(),
                                       static_cast<unsigned>(std::filesystem::file_size(direntry))) != MTAR_ESUCCESS) {
                LOG_ERROR("PackUserFiles: writing tar header for %s failed", direntry.path().string().c_str());
                std::fclose(file);
                mtar_close(&tarFile);
                BackupRestore::RemoveBackupDir();
                return false;
            }

            uint32_t loopcount = (vfs.filelength(file) / purefs::buffer::tar_buf) + 1u;
            uint32_t loopcount = (utils::filesystem::filelength(file) / purefs::buffer::tar_buf) + 1u;
            uint32_t readsize  = 0u;

            for (uint32_t i = 0u; i < loopcount; i++) {
                if (i + 1u == loopcount) {
                    readsize = vfs.filelength(file) % purefs::buffer::tar_buf;
                    readsize = utils::filesystem::filelength(file) % purefs::buffer::tar_buf;
                }
                else {
                    readsize = purefs::buffer::tar_buf;
                }

                LOG_INFO("PackUserFiles: reading file %s...", direntry.fileName.c_str());
                LOG_INFO("PackUserFiles: reading file %s...", direntry.path().string().c_str());

                if (vfs.fread(buffer.get(), 1, readsize, file) != readsize) {
                    LOG_ERROR("PackUserFiles: reading file %s failed, quitting...", direntry.fileName.c_str());
                    vfs.fclose(file);
                if (std::fread(buffer.get(), 1, readsize, file) != readsize) {
                    LOG_ERROR("PackUserFiles: reading file %s failed, quitting...", direntry.path().string().c_str());
                    std::fclose(file);
                    mtar_close(&tarFile);
                    BackupRestore::RemoveBackupDir();
                    return false;
                }

                LOG_INFO("PackUserFiles: writting %s into backup...", direntry.fileName.c_str());
                LOG_INFO("PackUserFiles: writting %s into backup...", direntry.path().string().c_str());
                if (mtar_write_data(&tarFile, buffer.get(), readsize) != MTAR_ESUCCESS) {
                    LOG_ERROR("PackUserFiles: writting %s into backup failed, quitting...", direntry.fileName.c_str());
                    vfs.fclose(file);
                    LOG_ERROR("PackUserFiles: writting %s into backup failed, quitting...",
                              direntry.path().string().c_str());
                    std::fclose(file);
                    mtar_close(&tarFile);
                    BackupRestore::RemoveBackupDir();
                    return false;
                }
            }

            LOG_INFO("PackUserFiles: closing file %s...", (backupPathDB + direntry.fileName).c_str());
            if (vfs.fclose(file) != 0) {
            LOG_INFO("PackUserFiles: closing file %s...", (backupPathDB + direntry.path().string()).c_str());
            if (std::fclose(file) != 0) {
                LOG_ERROR("PackUserFiles: closing file %s failed, quitting...",
                          (backupPathDB + direntry.fileName).c_str());
                          (backupPathDB + direntry.path().string()).c_str());
                mtar_close(&tarFile);
                BackupRestore::RemoveBackupDir();
                return false;
            }

            LOG_INFO("PackUserFiles: deleting file %s...", (backupPathDB + direntry.fileName).c_str());
            if (vfs.remove((backupPathDB + direntry.fileName).c_str()) != 0) {
            LOG_INFO("PackUserFiles: deleting file %s...", (backupPathDB + direntry.path().string()).c_str());
            if (std::remove((backupPathDB + direntry.path().string()).c_str()) != 0) {
                LOG_ERROR("PackUserFiles: deleting file %s failed, quitting...",
                          (backupPathDB + direntry.fileName).c_str());
                          (backupPathDB + direntry.path().string()).c_str());
                mtar_close(&tarFile);
                BackupRestore::RemoveBackupDir();
                return false;


@@ 277,7 272,7 @@ bool BackupRestore::UnpackBackupFile()
            std::string restoreFilePath = purefs::dir::getBackupOSPath();
            restoreFilePath += "/";
            restoreFilePath += tarHeader.name;
            vfs::FILE *file = vfs.fopen(restoreFilePath.c_str(), "w");
            auto *file = std::fopen(restoreFilePath.c_str(), "w");

            if (file == nullptr) {
                LOG_ERROR("UnpackBackupFile: extracting file %s failed, quitting...", tarHeader.name);


@@ 300,22 295,22 @@ bool BackupRestore::UnpackBackupFile()
                if (mtar_read_data(&tarFile, buffer.get(), readsize) != MTAR_ESUCCESS) {
                    LOG_ERROR("UnpackBackupFile: extracting file %s failed, quitting...", tarHeader.name);
                    mtar_close(&tarFile);
                    vfs.fclose(file);
                    vfs.remove(restoreFilePath.c_str());
                    std::fclose(file);
                    std::remove(restoreFilePath.c_str());
                    return false;
                }

                if (vfs.fwrite(buffer.get(), 1, readsize, file) != readsize) {
                if (std::fwrite(buffer.get(), 1, readsize, file) != readsize) {
                    LOG_ERROR("UnpackBackupFile: writting file %s failed, quitting...", restoreFilePath.c_str());
                    mtar_close(&tarFile);
                    vfs.fclose(file);
                    vfs.remove(restoreFilePath.c_str());
                    std::fclose(file);
                    std::remove(restoreFilePath.c_str());
                    return false;
                }
            }

            LOG_INFO("UnpackBackupFile: extracting file %s succeeded", tarHeader.name);
            vfs.fclose(file);
            std::fclose(file);
        }
        else {
            LOG_INFO("UnpackBackupFile: found header %d, skipping", tarHeader.type);


@@ 327,7 322,7 @@ bool BackupRestore::UnpackBackupFile()

    LOG_INFO("UnpackBackupFile: cleaning directory from tar file...");
    mtar_close(&tarFile);
    vfs.remove(tarFilePath.c_str());
    std::remove(tarFilePath.c_str());

    return true;
}


@@ 336,53 331,48 @@ bool BackupRestore::ReplaceUserFiles()
{
    /* replace existing files that have respective backup files existing */
    const auto backupOSPath                  = purefs::dir::getBackupOSPath();
    std::vector<vfs::DirectoryEntry> dirlist = vfs.listdir(backupOSPath.c_str());

    if (dirlist.size() <= empty_dirlist_size) {
    if (std::filesystem::is_directory(backupOSPath) && std::filesystem::is_empty(backupOSPath)) {
        LOG_INFO("ReplaceUserFiles: dir emtpy, nothing to restore, quitting...");
        return false;
    }

    LOG_INFO("ReplaceUserFiles: dir listed with %lu files", dirlist.size() - empty_dirlist_size);

    std::string userFilePath = purefs::dir::getUserDiskPath();
    userFilePath += "/";

    std::string backupFilePath = purefs::dir::getBackupOSPath();
    backupFilePath += "/";

    for (auto &direntry : dirlist) {
        if ((direntry.fileName.compare(".") != 0) && (direntry.fileName.compare("..") != 0) &&
            (direntry.fileName.compare("...") != 0)) {
            LOG_INFO("ReplaceUserFiles: restoring backup file %s...", direntry.fileName.c_str());

            if (vfs.fileExists((userFilePath + direntry.fileName).c_str())) {
                if (vfs.remove((userFilePath + direntry.fileName).c_str()) == 0) {
                    if (vfs.rename((backupFilePath + direntry.fileName).c_str(),
                                   (userFilePath + direntry.fileName).c_str()) == 0) {
                        LOG_INFO("ReplaceUserFiles: restoring backup file %s succeeded", direntry.fileName.c_str());
    for (auto &direntry : std::filesystem::directory_iterator(backupOSPath.c_str())) {
        if ((direntry.path().compare(".") != 0) && (direntry.path().compare("..") != 0) &&
            (direntry.path().compare("...") != 0)) {
            LOG_INFO("ReplaceUserFiles: restoring backup file %s...", direntry.path().c_str());

            if (std::filesystem::exists((userFilePath + direntry.path().string()))) {
                if (std::filesystem::remove((userFilePath + direntry.path().string()))) {
                    try {
                        std::filesystem::rename(backupFilePath + direntry.path().string(),
                                                userFilePath + direntry.path().string());
                        LOG_INFO("ReplaceUserFiles: restoring backup file %s succeeded", direntry.path().c_str());
                    }
                    else {
                    catch (const std::exception &e) {
                        LOG_ERROR("ReplaceUserFiles: restoring backup file %s failed on error %s",
                                  direntry.fileName.c_str(),
                                  vfs.lastErrnoToStr().c_str());
                                  direntry.path().c_str(),
                                  e.what());
                    }
                }
                else {
                    LOG_ERROR("ReplaceUserFiles: restoring backup file %s failed on error %s",
                              direntry.fileName.c_str(),
                              vfs.lastErrnoToStr().c_str());
                    LOG_ERROR("ReplaceUserFiles: restoring backup file %s", direntry.path().c_str());
                }
            }
            else {
                if (vfs.rename((backupFilePath + direntry.fileName).c_str(),
                               (userFilePath + direntry.fileName).c_str()) == 0) {
                    LOG_INFO("ReplaceUserFiles: restoring backup file %s succeeded", direntry.fileName.c_str());
                try {
                    std::filesystem::rename(backupFilePath + direntry.path().string(),
                                            userFilePath + direntry.path().string());
                    LOG_INFO("ReplaceUserFiles: restoring backup file %s succeeded", direntry.path().c_str());
                }
                else {
                catch (const std::filesystem::filesystem_error &e) {
                    LOG_ERROR("ReplaceUserFiles: restoring backup file %s failed on error %s",
                              direntry.fileName.c_str(),
                              vfs.lastErrnoToStr().c_str());
                              direntry.path().c_str(),
                              e.what());
                }
            }
        }

M module-services/service-desktop/endpoints/deviceInfo/DeviceInfoEndpoint.cpp => module-services/service-desktop/endpoints/deviceInfo/DeviceInfoEndpoint.cpp +0 -1
@@ 9,7 9,6 @@
#include <json/json11.hpp>
#include <source/version.hpp>
#include <time/time_conversion.hpp>
#include <vfs.hpp>
#include <service-desktop/service-desktop/ServiceDesktop.hpp>
#include <cstdint>
#include <string>

M module-services/service-desktop/endpoints/factoryReset/FactoryReset.cpp => module-services/service-desktop/endpoints/factoryReset/FactoryReset.cpp +28 -31
@@ 7,7 7,7 @@
#include <log/log.hpp>
#include <purefs/filesystem_paths.hpp>
#include <service-db/DBServiceName.hpp>
#include <vfs.hpp>
#include <Utils.hpp>

#include <cstdint>
#include <filesystem>


@@ 24,7 24,6 @@ namespace FactoryReset
    static bool CopyFile(std::string sourcefile, std::string targetfile);

    static int recurseDepth             = 0;
    static const int empty_dirlist_size = 2;   /* vfs.listdir lists "." and ".." by default also for empty dir */
    static const int max_recurse_depth  = 120; /* 120 is just an arbitrary value of max number of recursive calls.
                                                * If more then error is assumed, not the real depth of directories."
                                                */


@@ 39,11 38,9 @@ namespace FactoryReset
        LOG_INFO("FactoryReset: restoring factory state started...");

        recurseDepth = 0;

        const auto factoryOSPath                 = purefs::dir::getFactoryOSPath();
        std::vector<vfs::DirectoryEntry> dirlist = vfs.listdir(factoryOSPath.c_str(), "");

        if (dirlist.size() <= empty_dirlist_size) {
        if (std::filesystem::is_directory(factoryOSPath.c_str()) && std::filesystem::is_empty(factoryOSPath.c_str())) {
            LOG_ERROR("FactoryReset: restoring factory state aborted");
            LOG_ERROR("FactoryReset: directory %s seems empty.", factoryOSPath.c_str());
            return false;


@@ 52,7 49,7 @@ namespace FactoryReset
        if (ownerService != nullptr) {
            LOG_INFO("FactoryReset: closing ServiceDB...");
            std::string dbServiceName = service::name::db;
            (void)sys::SystemManager::DestroyService(dbServiceName, ownerService);
            sys::SystemManager::DestroyService(dbServiceName, ownerService);
        }

        if (DeleteDirContent(purefs::dir::getRootDiskPath()) != true) {


@@ 72,20 69,21 @@ namespace FactoryReset

    bool DeleteDirContent(std::string dir)
    {
        std::vector<vfs::DirectoryEntry> dirlist = vfs.listdir(dir.c_str(), "");

        for (auto &direntry : dirlist) {
            if ((direntry.fileName.compare(".") != 0) && (direntry.fileName.compare("..") != 0) &&
                (direntry.fileName.compare("...") != 0)) {
        for (auto &direntry : std::filesystem::directory_iterator(dir.c_str())) {
            if ((direntry.path().string().compare(".") != 0) && (direntry.path().string().compare("..") != 0) &&
                (direntry.path().string().compare("...") != 0)) {

                std::string delpath = dir;
                delpath += "/";
                delpath += direntry.fileName.c_str();
                delpath += direntry.path().string().c_str();

                if (direntry.attributes == vfs::FileAttributes::Directory) {
                    if (direntry.fileName.compare(PATH_FACTORY) != 0) {
                if (std::filesystem::is_directory(direntry)) {
                    if (direntry.path().string().compare(PATH_FACTORY) != 0) {
                        LOG_INFO("FactoryReset: recursively deleting dir %s...", delpath.c_str());
                        if (vfs.deltree(delpath.c_str()) != 0) {
                        try {
                            std::filesystem::remove_all(delpath.c_str());
                        }
                        catch (const std::filesystem::filesystem_error &e) {
                            LOG_ERROR("FactoryReset: error deleting dir %s, aborting...", delpath.c_str());
                            return false;
                        }


@@ 93,7 91,7 @@ namespace FactoryReset
                }
                else {
                    LOG_INFO("FactoryReset: deleting file %s...", delpath.c_str());
                    if (vfs.remove(delpath.c_str()) != 0) {
                    if (std::filesystem::remove(delpath.c_str())) {
                        LOG_ERROR("FactoryReset: error deleting file %s, aborting...", delpath.c_str());
                        return false;
                    }


@@ 114,21 112,20 @@ namespace FactoryReset
        }

        const auto factoryOSPath                 = purefs::dir::getFactoryOSPath();
        std::vector<vfs::DirectoryEntry> dirlist = vfs.listdir(sourcedir.c_str(), "");

        for (auto &direntry : dirlist) {
            if ((direntry.fileName.compare(".") == 0) || (direntry.fileName.compare("..") == 0) ||
                (direntry.fileName.compare("...") == 0)) {
        for (auto &direntry : std::filesystem::directory_iterator(sourcedir.c_str())) {
            if ((direntry.path().string().compare(".") == 0) || (direntry.path().string().compare("..") == 0) ||
                (direntry.path().string().compare("...") == 0)) {
                continue;
            }

            std::string sourcepath = sourcedir;
            sourcepath += "/";
            sourcepath += direntry.fileName.c_str();
            sourcepath += direntry.path().string().c_str();

            std::string targetpath = targetdir;
            targetpath += "/";
            targetpath += direntry.fileName.c_str();
            targetpath += direntry.path().string().c_str();

            if ((sourcepath.size() >= max_filepath_length) || (targetpath.size() >= max_filepath_length)) {
                LOG_ERROR("FactoryReset: path length (source or target) exceeds system limit of %d",


@@ 137,14 134,14 @@ namespace FactoryReset
                return false;
            }

            if (direntry.attributes == vfs::FileAttributes::Directory) {
            if (std::filesystem::is_directory(direntry)) {
                if (targetpath.compare(factoryOSPath.c_str()) == 0) {
                    continue;
                }

                LOG_INFO("FactoryReset: restoring dir  %s into %s...", sourcepath.c_str(), targetpath.c_str());

                if (vfs.mkdir(targetpath.c_str()) != 0) {
                if (std::filesystem::create_directory(targetpath.c_str())) {
                    LOG_ERROR("FactoryReset: create dir %s failed", targetpath.c_str());
                    return false;
                }


@@ 173,30 170,30 @@ namespace FactoryReset
    static bool CopyFile(std::string sourcefile, std::string targetfile)
    {
        bool ret  = true;
        auto lamb = [](vfs::FILE *stream) { vfs.fclose(stream); };
        auto lamb = [](std::FILE *stream) { std::fclose(stream); };

        std::unique_ptr<vfs::FILE, decltype(lamb)> sf(vfs.fopen(sourcefile.c_str(), "r"), lamb);
        std::unique_ptr<vfs::FILE, decltype(lamb)> tf(vfs.fopen(targetfile.c_str(), "w"), lamb);
        std::unique_ptr<std::FILE, decltype(lamb)> sf(std::fopen(sourcefile.c_str(), "r"), lamb);
        std::unique_ptr<std::FILE, decltype(lamb)> tf(std::fopen(targetfile.c_str(), "w"), lamb);

        if ((sf.get() != nullptr) && (tf.get() != nullptr)) {
            std::unique_ptr<unsigned char[]> buffer(new unsigned char[purefs::buffer::copy_buf]);

            if (buffer.get() != nullptr) {
                uint32_t loopcount = (vfs.filelength(sf.get()) / purefs::buffer::copy_buf) + 1u;
                uint32_t loopcount = (utils::filesystem::filelength(sf.get()) / purefs::buffer::copy_buf) + 1u;
                uint32_t readsize  = purefs::buffer::copy_buf;

                for (uint32_t i = 0u; i < loopcount; i++) {
                    if (i + 1u == loopcount) {
                        readsize = vfs.filelength(sf.get()) % purefs::buffer::copy_buf;
                        readsize = utils::filesystem::filelength(sf.get()) % purefs::buffer::copy_buf;
                    }

                    if (vfs.fread(buffer.get(), 1, readsize, sf.get()) != readsize) {
                    if (std::fread(buffer.get(), 1, readsize, sf.get()) != readsize) {
                        LOG_ERROR("FactoryReset: read from sourcefile %s failed", sourcefile.c_str());
                        ret = false;
                        break;
                    }

                    if (vfs.fwrite(buffer.get(), 1, readsize, tf.get()) != readsize) {
                    if (std::fwrite(buffer.get(), 1, readsize, tf.get()) != readsize) {
                        LOG_ERROR("FactoryReset: write to targetfile %s failed", targetfile.c_str());
                        ret = false;
                        break;

M module-services/service-desktop/endpoints/filesystem/FilesystemEndpoint.cpp => module-services/service-desktop/endpoints/filesystem/FilesystemEndpoint.cpp +3 -3
@@ 4,7 4,7 @@
#include "FilesystemEndpoint.hpp"
#include "service-desktop/DesktopMessages.hpp"
#include "service-desktop/ServiceDesktop.hpp"
#include <module-vfs/include/user/purefs/filesystem_paths.hpp>
#include <purefs/filesystem_paths.hpp>

auto FilesystemEndpoint::handle(Context &context) -> void
{


@@ 19,9 19,9 @@ auto FilesystemEndpoint::handle(Context &context) -> void
}
static bool isWritable(const fs::path file)
{
    auto lamb = [](vfs::FILE *stream) { vfs.fclose(stream); };
    auto lamb = [](std::FILE *stream) { std::fclose(stream); };

    std::unique_ptr<vfs::FILE, decltype(lamb)> sf(vfs.fopen(file.c_str(), "w"), lamb);
    std::unique_ptr<std::FILE, decltype(lamb)> sf(std::fopen(file.c_str(), "w"), lamb);

    if (sf.get() != nullptr) {
        return true;

M module-services/service-desktop/endpoints/update/UpdateEndpoint.cpp => module-services/service-desktop/endpoints/update/UpdateEndpoint.cpp +1 -1
@@ 35,7 35,7 @@ auto UpdateEndpoint::run(Context &context) -> sys::ReturnCodes
{
    std::string fileName = context.getBody()["fileName"].string_value();
    auto path            = purefs::dir::getUpdatesOSPath() / fileName;
    auto fileExists      = vfs.fileExists(path.c_str());
    auto fileExists      = std::filesystem::exists(path.c_str());
    if (fileExists) {
        context.setResponseBody(json11::Json::object({{parserFSM::json::updateReady, true}}));


M module-services/service-desktop/endpoints/update/UpdateMuditaOS.cpp => module-services/service-desktop/endpoints/update/UpdateMuditaOS.cpp +111 -94
@@ 14,13 14,13 @@
#include <module-apps/application-desktop/ApplicationDesktop.hpp>
#include <service-db/service-db/Settings.hpp>
#include <purefs/filesystem_paths.hpp>
#include <vfs.hpp>
#include <time/time_conversion.hpp>
#include <filesystem>
#include <Utils.hpp>

#if defined(TARGET_RT1051)
#include <board/cross/eMMC/eMMC.hpp>
#include "bsp/watchdog/watchdog.hpp"
#include "vfs_globals.hpp"
#include <module-vfs/include/user/purefs/filesystem_paths.hpp>
#endif

#include <array>


@@ 54,10 54,10 @@ UpdateMuditaOS::UpdateMuditaOS(ServiceDesktop *ownerService) : owner(ownerServic
updateos::UpdateError UpdateMuditaOS::setUpdateFile(fs::path updateFileToUse)
{
    updateFile = purefs::dir::getUpdatesOSPath() / updateFileToUse;
    if (vfs.fileExists(updateFile.c_str())) {
    if (std::filesystem::exists(updateFile.c_str())) {
        versionInformation = UpdateMuditaOS::getVersionInfoFromFile(updateFile);
        if (mtar_open(&updateTar, updateFile.c_str(), "r") == MTAR_ESUCCESS) {
            totalBytes = vfs.filelength(updateTar.stream);
            totalBytes = utils::filesystem::filelength(updateTar.stream);
        }
        else {
            return informError(updateos::UpdateError::CantOpenUpdateFile,


@@ 148,7 148,7 @@ updateos::UpdateError UpdateMuditaOS::unpackUpdate()

        if (tarHeader.type == MTAR_TDIR) {
            fs::path tmpPath = getUpdateTmpChild(tarHeader.name);
            if (vfs.mkdir(tmpPath.c_str()) != 0) {
            if (std::filesystem::create_directory(tmpPath.c_str())) {
                return informError(updateos::UpdateError::CantCreateExtractedFile,
                                   "unpackUpdate failed to create %s when extracting update tar",
                                   tmpPath.c_str());


@@ 169,14 169,35 @@ updateos::UpdateError UpdateMuditaOS::unpackUpdate()
    return updateos::UpdateError::NoError;
}

std::string UpdateMuditaOS::readContent(const char *filename) noexcept
{
    std::unique_ptr<char[]> fcontent;
    long fsize = 0;

    auto fp = std::fopen(filename, "r");
    if (fp) {
        std::fseek(fp, 0, SEEK_END);
        fsize = std::ftell(fp);
        std::rewind(fp);

        fcontent = std::make_unique<char[]>(fsize + 1);

        std::fread(fcontent.get(), 1, fsize, fp);

        std::fclose(fp);
    }

    return std::string(fcontent.get());
}

updateos::UpdateError UpdateMuditaOS::verifyChecksums()
{
    status = updateos::UpdateState::ChecksumVerification;

    std::unique_ptr<char[]> lineBuff(
        new char[purefs::buffer::tar_buf]); // max line should be freertos max path + checksum, so this is enough
    auto lineBuff = std::make_unique<char[]>(
        purefs::buffer::tar_buf); // max line should be freertos max path + checksum, so this is enough
    fs::path checksumsFile = getUpdateTmpChild(updateos::file::checksums);
    vfs::FILE *fpChecksums = vfs.fopen(checksumsFile.c_str(), "r");
    auto fpChecksums       = std::fopen(checksumsFile.c_str(), "r");

    if (fpChecksums == nullptr) {
        return informError(updateos::UpdateError::CantOpenChecksumsFile,


@@ 184,18 205,19 @@ updateos::UpdateError UpdateMuditaOS::verifyChecksums()
                           checksumsFile.c_str());
    }

    while (!vfs.eof(fpChecksums)) {
        char *line = vfs.fgets(lineBuff.get(), purefs::buffer::tar_buf, fpChecksums);
    while (!std::feof(fpChecksums)) {
        char *line = std::fgets(lineBuff.get(), purefs::buffer::tar_buf, fpChecksums);
        std::string filePath;
        unsigned long fileCRC32;

        if (lineBuff[0] == ';' || line == nullptr)
        if (lineBuff[0] == ';' || line == nullptr) {
            continue;
        }

        getChecksumInfo(line, filePath, &fileCRC32);
        unsigned long computedCRC32 = getExtractedFileCRC32(filePath);
        if (computedCRC32 != fileCRC32) {
            vfs.fclose(fpChecksums);
            std::fclose(fpChecksums);
            return informError(updateos::UpdateError::VerifyChecksumsFailure,
                               "verifyChecksums %s crc32 match FAIL %lX != %lX",
                               filePath.c_str(),


@@ 203,7 225,7 @@ updateos::UpdateError UpdateMuditaOS::verifyChecksums()
                               computedCRC32);
        }
    }
    vfs.fclose(fpChecksums);
    std::fclose(fpChecksums);
    return updateos::UpdateError::NoError;
}



@@ 211,13 233,13 @@ updateos::UpdateError UpdateMuditaOS::verifyVersion()
{
    status = updateos::UpdateState::VersionVerificiation;

    if (!vfs.fileExists(getUpdateTmpChild(updateos::file::version).c_str())) {
    if (!std::filesystem::exists(getUpdateTmpChild(updateos::file::version).c_str())) {
        return informError(updateos::UpdateError::VerifyVersionFailure,
                           "verifyVersion %s does not exist",
                           getUpdateTmpChild(updateos::file::version).c_str());
    }

    std::string versionJsonString = vfs.loadFileAsString(getUpdateTmpChild(updateos::file::version));
    std::string versionJsonString = readContent(getUpdateTmpChild(updateos::file::version).c_str());
    std::string parserError;
    targetVersionInfo = json11::Json::parse(versionJsonString, parserError);
    if (!parserError.empty()) {


@@ 275,7 297,6 @@ void UpdateMuditaOS::getChecksumInfo(const std::string &infoLine, std::string &f
updateos::UpdateError UpdateMuditaOS::prepareRoot()
{
    informDebug("prepareRoot()");
    int ret;
    // basic needed dirs

    const auto previousOSPath = purefs::dir::getPreviousOSPath();


@@ 283,61 304,62 @@ updateos::UpdateError UpdateMuditaOS::prepareRoot()
    const auto userDiskPath   = purefs::dir::getUserDiskPath();

    informDebug("prepareRoot mkdir: %s", previousOSPath.c_str());
    vfs.mkdir(previousOSPath.c_str());
    std::filesystem::create_directory(previousOSPath.c_str());
    informDebug("prepareRoot mkdir: %s", currentOSPath.c_str());
    vfs.mkdir(currentOSPath.c_str());
    std::filesystem::create_directory(currentOSPath.c_str());
    informDebug("prepareRoot mkdir: %s", userDiskPath.c_str());
    vfs.mkdir(userDiskPath.c_str());
    std::filesystem::create_directory(userDiskPath.c_str());

    // remove the previous OS version from partition
    informDebug("prepareRoot deltree: %s", previousOSPath.c_str());
    ret = vfs.deltree(previousOSPath.c_str());

    if (ret != 0) {
        informError(updateos::UpdateError::CantDeletePreviousOS,
                    "prepareRoot ff_deltree on %s caused an error %s",
                    previousOSPath.c_str(),
                    vfs.lastErrnoToStr().c_str());
    try {
        std::filesystem::remove_all(previousOSPath.c_str());
    }

    if (vfs.isDir(purefs::dir::getPreviousOSPath().c_str())) {
    catch (const std::filesystem::filesystem_error &e) {
        return informError(updateos::UpdateError::CantDeletePreviousOS,
                           "prepareRoot ff_deltree on %s caused an error %s",
                           previousOSPath.c_str(),
                           vfs.lastErrnoToStr().c_str());
                           e.what());
    }

    if (vfs.isDir(purefs::dir::getPreviousOSPath().c_str())) {
    if (std::filesystem::is_directory(purefs::dir::getPreviousOSPath().c_str())) {
        return informError(
            updateos::UpdateError::CantDeletePreviousOS, "prepareRoot ff_deltree on %s", previousOSPath.c_str());
    }

    if (std::filesystem::is_directory(purefs::dir::getPreviousOSPath().c_str())) {
        return informError(updateos::UpdateError::CantDeletePreviousOS,
                           "prepareRoot %s still exists, we can't continue",
                           purefs::dir::getPreviousOSPath().c_str());
    }
    // rename the current OS to previous on partition
    informDebug("prepareRoot rename: %s->%s", currentOSPath.c_str(), previousOSPath.c_str());
    ret = vfs.rename(currentOSPath.c_str(), previousOSPath.c_str());

    if (ret != 0) {
    try {
        std::filesystem::rename(currentOSPath.c_str(), previousOSPath.c_str());
    }
    catch (const std::filesystem::filesystem_error &e) {
        return informError(updateos::UpdateError::CantRenameCurrentToPrevious,
                           "prepareRoot can't rename %s -> %s error %s",
                           purefs::dir::getCurrentOSPath().c_str(),
                           purefs::dir::getPreviousOSPath().c_str(),
                           vfs.lastErrnoToStr().c_str());
                           e.what());
    }

    // rename the temp directory to current (extracted update)
    informDebug("prepareRoot rename: %s->%s", updateTempDirectory.c_str(), currentOSPath.c_str());
    ret = vfs.rename(updateTempDirectory.c_str(), currentOSPath.c_str());

    if (ret != 0) {
    try {
        std::filesystem::rename(updateTempDirectory.c_str(), currentOSPath.c_str());
    }
    catch (const std::filesystem::filesystem_error &e) {
        return informError(updateos::UpdateError::CantRenameTempToCurrent,
                           "prepareRoot can't rename %s -> %s error %s",
                           updateTempDirectory.c_str(),
                           purefs::dir::getCurrentOSPath().c_str(),
                           vfs.lastErrnoToStr().c_str());
                           e.what());
    }

    // move the contents of /sys/current/user if it exists to /user
    ret = static_cast<int>(updateUserData());
    updateUserData();

    return updateBootJSON();
}


@@ 348,24 370,24 @@ updateos::UpdateError UpdateMuditaOS::updateBootJSON()
    fs::path bootJSONAbsoulte         = purefs::createPath(purefs::dir::getRootDiskPath(), purefs::file::boot_json);
    informDebug("updateBootJSON %s", bootJSONAbsoulte.c_str());

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

    if (fp != nullptr) {
        vfs.computeCRC32(fp, &bootJSONAbsoulteCRC);
        utils::filesystem::computeCRC32(fp, &bootJSONAbsoulteCRC);
        bootJSONAbsoulte += purefs::extension::crc32;

        vfs::FILE *fpCRC = vfs.fopen(bootJSONAbsoulte.c_str(), "w");
        auto *fpCRC = std::fopen(bootJSONAbsoulte.c_str(), "w");
        if (fpCRC != nullptr) {
            std::array<char, purefs::buffer::crc_char_size> crcBuf;
            snprintf(crcBuf.data(), crcBuf.size(), "%lX", bootJSONAbsoulteCRC);
            vfs.fwrite(crcBuf.data(), 1, purefs::buffer::crc_char_size, fpCRC);
            vfs.fclose(fpCRC);
            std::fwrite(crcBuf.data(), 1, purefs::buffer::crc_char_size, fpCRC);
            std::fclose(fpCRC);
        }
        else {
            return updateos::UpdateError::CantUpdateCRC32JSON;
        }

        vfs.fclose(fp);
        std::fclose(fp);
    }
    else {
        return updateos::UpdateError::CantUpdateCRC32JSON;


@@ 377,7 399,7 @@ updateos::UpdateError UpdateMuditaOS::updateBootJSON()

bool UpdateMuditaOS::unpackFileToTemp(mtar_header_t &h, unsigned long *crc32)
{
    std::unique_ptr<unsigned char[]> readBuf(new unsigned char[purefs::buffer::tar_buf]);
    auto readBuf            = std::make_unique<unsigned char[]>(purefs::buffer::tar_buf);
    const fs::path fullPath = getUpdateTmpChild(h.name);

    uint32_t blocksToRead = (h.size / purefs::buffer::tar_buf) + 1;


@@ 395,7 417,7 @@ bool UpdateMuditaOS::unpackFileToTemp(mtar_header_t &h, unsigned long *crc32)
    }

    int errCode   = MTAR_ESUCCESS;
    vfs::FILE *fp = vfs.fopen(fullPath.c_str(), "w+");
    auto *fp      = std::fopen(fullPath.c_str(), "w+");
    if (fp == nullptr) {
        informError(
            updateos::UpdateError::CantWriteToFile, "unpackFileToTemp %s can't open for writing", fullPath.c_str());


@@ 419,13 441,11 @@ bool UpdateMuditaOS::unpackFileToTemp(mtar_header_t &h, unsigned long *crc32)
            return false;
        }

        const uint32_t dataWritten = vfs.fwrite(readBuf.get(), 1, sizeToRead, fp);
        const uint32_t dataWritten = std::fwrite(readBuf.get(), 1, sizeToRead, fp);
        if (dataWritten != sizeToRead) {
            informError(updateos::UpdateError::CantWriteToFile,
                        "unpackFileToTemp %s can't write to file error: %s",
                        fullPath.c_str(),
                        vfs.lastErrnoToStr().c_str());
            vfs.fclose(fp);
            informError(
                updateos::UpdateError::CantWriteToFile, "unpackFileToTemp %s can't write to file", fullPath.c_str());
            std::fclose(fp);
            return false;
        }



@@ 433,19 453,19 @@ bool UpdateMuditaOS::unpackFileToTemp(mtar_header_t &h, unsigned long *crc32)

        *crc32 = Crc32_ComputeBuf(*crc32, readBuf.get(), sizeToRead);
    }
    vfs.fclose(fp);
    std::fclose(fp);
    return true;
}

updateos::UpdateError UpdateMuditaOS::cleanupAfterUpdate()
{
    if (vfs.isDir(updateTempDirectory.c_str()) && vfs.deltree(updateTempDirectory.c_str())) {
    if (std::filesystem::is_directory(updateTempDirectory.c_str()) &&
        std::filesystem::remove_all(updateTempDirectory.c_str())) {
        return informError(
            updateos::UpdateError::CantRemoveUniqueTmpDir, "ff_deltree failed on %s", updateTempDirectory.c_str());
            updateos::UpdateError::CantRemoveUniqueTmpDir, "remove_all failed on %s", updateTempDirectory.c_str());
    }
    mtar_close(&updateTar);

    if (vfs.remove(updateFile.c_str())) {
    if (std::remove(updateFile.c_str())) {
        return informError(updateos::UpdateError::CantRemoveUpdateFile, "Failed to delete %s", updateFile.c_str());
    }



@@ 462,26 482,23 @@ updateos::UpdateError UpdateMuditaOS::prepareTempDirForUpdate()
{
    status = updateos::UpdateState::CreatingDirectories;

    updateTempDirectory = purefs::dir::getTemporaryPath() / vfs::generateRandomId(updateos::prefix_len);
    updateTempDirectory = purefs::dir::getTemporaryPath() / utils::filesystem::generateRandomId(updateos::prefix_len);

    informDebug("Temp dir for update %s", updateTempDirectory.c_str());

    const auto updatesOSPath = purefs::dir::getUpdatesOSPath();
    if (vfs.isDir(updatesOSPath.c_str()) == false) {
        if (vfs.mkdir(updatesOSPath.c_str()) != 0) {
            return informError(updateos::UpdateError::CantCreateUpdatesDir,
                               "%s can't create it %s",
                               updatesOSPath.c_str(),
                               vfs.lastErrnoToStr().c_str());
    if (!std::filesystem::is_directory(updatesOSPath.c_str())) {
        if (!std::filesystem::create_directory(updatesOSPath.c_str())) {
            return informError(
                updateos::UpdateError::CantCreateUpdatesDir, "%s can't create it", updatesOSPath.c_str());
        }
    }

    if (vfs.isDir(purefs::dir::getUpdatesOSPath().c_str()) == false) {
        if (vfs.mkdir(purefs::dir::getUpdatesOSPath().c_str()) != 0) {
    if (!std::filesystem::is_directory(purefs::dir::getUpdatesOSPath().c_str())) {
        if (!std::filesystem::create_directory(purefs::dir::getUpdatesOSPath().c_str())) {
            return informError(updateos::UpdateError::CantCreateUpdatesDir,
                               "%s can't create it %s",
                               purefs::dir::getUpdatesOSPath().c_str(),
                               vfs.lastErrnoToStr().c_str());
                               purefs::dir::getUpdatesOSPath().c_str());
        }
        else {
            informDebug("prepareTempDirForUpdate %s created", purefs::dir::getUpdatesOSPath().c_str());


@@ 491,13 508,12 @@ updateos::UpdateError UpdateMuditaOS::prepareTempDirForUpdate()
        informDebug("prepareTempDirForUpdate %s exists", purefs::dir::getUpdatesOSPath().c_str());
    }

    if (vfs.isDir(purefs::dir::getTemporaryPath().c_str()) == false) {
    if (!std::filesystem::is_directory(purefs::dir::getTemporaryPath().c_str())) {
        informDebug("prepareTempDirForUpdate %s is not a directory", purefs::dir::getTemporaryPath().c_str());
        if (vfs.mkdir(purefs::dir::getTemporaryPath().c_str()) != 0) {
        if (!std::filesystem::create_directory(purefs::dir::getTemporaryPath().c_str())) {
            return informError(updateos::UpdateError::CantCreateTempDir,
                               "%s can't create it %s",
                               purefs::dir::getTemporaryPath().c_str(),
                               vfs.lastErrnoToStr().c_str());
                               purefs::dir::getTemporaryPath().c_str());
        }
        else {
            informDebug("prepareTempDirForUpdate %s created", purefs::dir::getTemporaryPath().c_str());


@@ 507,24 523,24 @@ updateos::UpdateError UpdateMuditaOS::prepareTempDirForUpdate()
        informDebug("prepareTempDirForUpdate %s exists", purefs::dir::getTemporaryPath().c_str());
    }

    if (vfs.isDir(updateTempDirectory.c_str())) {
    if (std::filesystem::is_directory(updateTempDirectory.c_str())) {
        informDebug("prepareTempDirForUpdate %s exists already, try to remove it", updateTempDirectory.c_str());
        if (vfs.deltree(updateTempDirectory.c_str()) != 0) {
        try {
            std::filesystem::remove_all(updateTempDirectory.c_str());
        }
        catch (const std::filesystem::filesystem_error &e) {
            return informError(updateos::UpdateError::CantRemoveUniqueTmpDir,
                               "prepareTempDirForUpdate can't remove %s",
                               updateTempDirectory.c_str());
        }
        else {
            informDebug("prepareTempDirForUpdate %s removed", updateTempDirectory.c_str());
        }
        informDebug("prepareTempDirForUpdate %s removed", updateTempDirectory.c_str());
    }

    informDebug("prepareTempDirForUpdate trying to create %s as tempDir", updateTempDirectory.c_str());
    if (vfs.mkdir(updateTempDirectory.c_str()) != 0) {
    if (!std::filesystem::create_directory(updateTempDirectory.c_str())) {
        informError(updateos::UpdateError::CantCreateUniqueTmpDir,
                    "prepareTempDirForUpdate failed to create: %s error: %s",
                    updateTempDirectory.c_str(),
                    vfs.lastErrnoToStr().c_str());
                    "prepareTempDirForUpdate failed to create: %s",
                    updateTempDirectory.c_str());
    }

    return updateos::UpdateError::NoError;


@@ 538,32 554,36 @@ updateos::UpdateError UpdateMuditaOS::writeBootloader(fs::path bootloaderFile)
    return updateos::UpdateError::NoError;
#else

    if (vfs.fileExists(bootloaderFile.c_str()) == false) {
    if (std::filesystem::exists(bootloaderFile.c_str()) == false) {
        return informError(updateos::UpdateError::NoBootloaderFile,
                           "[Bootloader Update] File %s doesn't exist!\n",
                           bootloaderFile.c_str());
    }

    auto fileHandler = vfs.fopen(bootloaderFile.c_str(), "r");
    auto fileHandler = std::fopen(bootloaderFile.c_str(), "r");
    if (fileHandler == nullptr) {
        std::fclose(fileHandler);
        return informError(updateos::UpdateError::CantOpenBootloaderFile,
                           "[Bootloader Update] Failed to open file %s\n",
                           bootloaderFile.c_str());
    }

    unsigned long fileLen = vfs.filelength(fileHandler);
    unsigned long fileLen = utils::filesystem::filelength(fileHandler);
    auto fileBuf          = std::make_unique<uint8_t[]>(fileLen);
    if (fileBuf == nullptr) {
        std::fclose(fileHandler);
        return informError(updateos::UpdateError::CantAllocateBuffer,
                           "[Bootloader Update] Failed to allocate buffer\n");
    }

    auto filesLoaded = vfs.fread(fileBuf.get(), fileLen, 1, fileHandler);
    auto filesLoaded = std::fread(fileBuf.get(), fileLen, 1, fileHandler);
    if (filesLoaded == 0) {
        std::fclose(fileHandler);
        return informError(updateos::UpdateError::CantOpenBootloaderFile,
                           "[Bootloader Update] Failed to load file %s\n",
                           bootloaderFile.c_str());
    }
    std::fclose(fileHandler);

    informUpdate(status, "[Bootloader Update] File size: %lu B, Writing...", fileLen);



@@ 574,14 594,13 @@ updateos::UpdateError UpdateMuditaOS::writeBootloader(fs::path bootloaderFile)

    informUpdate(status, "[Bootloader Update] DONE!\n");
    emmc.SwitchPartition(bsp::eMMC::Partition::UserArea);

    return updateos::UpdateError::NoError;
#endif
}

const json11::Json UpdateMuditaOS::getVersionInfoFromFile(const fs::path &updateFile)
{
    if (vfs.fileExists(updateFile.c_str())) {
    if (std::filesystem::exists(updateFile.c_str())) {
        mtar_t tar;
        mtar_header_t h;



@@ 641,17 660,15 @@ bool UpdateMuditaOS::isUpgradeToCurrent(const std::string &versionToCompare)
const fs::path UpdateMuditaOS::checkForUpdate()
{
    const auto updatesOSPath                  = purefs::dir::getUpdatesOSPath();
    std::vector<vfs::DirectoryEntry> fileList = vfs.listdir(updatesOSPath.c_str(), updateos::extension::update, true);
    for (auto &file : fileList) {

        json11::Json versionInfo = UpdateMuditaOS::getVersionInfoFromFile(updatesOSPath / file.fileName);
    for (auto &file : std::filesystem::directory_iterator(updatesOSPath.c_str())) {
        json11::Json versionInfo = UpdateMuditaOS::getVersionInfoFromFile(updatesOSPath / file.path());
        if (versionInfo.is_null())
            continue;

        if (versionInfo[purefs::json::os_version][purefs::json::version_string].is_string()) {
            if (UpdateMuditaOS::isUpgradeToCurrent(
                    versionInfo[purefs::json::os_version][purefs::json::version_string].string_value())) {
                return updatesOSPath / file.fileName;
                return updatesOSPath / file.path();
            }
        }
    }

M module-services/service-desktop/endpoints/update/UpdateMuditaOS.hpp => module-services/service-desktop/endpoints/update/UpdateMuditaOS.hpp +1 -1
@@ 5,7 5,6 @@

#include <json/json11.hpp>
#include <module-utils/microtar/src/microtar.hpp>
#include <vfs.hpp>

#include <cstdint>
#include <filesystem>


@@ 182,4 181,5 @@ class UpdateMuditaOS : public updateos::UpdateStats
    updateos::UpdateRunStatus updateRunStatus;
    json11::Json updateHistory;
    json11::Json targetVersionInfo;
    [[nodiscard]] static std::string readContent(const char *filename) noexcept;
};

M module-services/service-desktop/service-desktop/DesktopMessages.hpp => module-services/service-desktop/service-desktop/DesktopMessages.hpp +0 -1
@@ 9,7 9,6 @@
#include <Service/Message.hpp>
#include <MessageType.hpp>

#include <vfs.hpp>

namespace sdesktop
{

M module-services/service-desktop/tests/unittest.cpp => module-services/service-desktop/tests/unittest.cpp +1 -0
@@ 20,6 20,7 @@
#include <json/json11.hpp>
#include <purefs/filesystem_paths.hpp>
#include <utf8/UTF8.hpp>
#include <vfs.hpp>

#include <memory>
#include <filesystem>

M module-services/service-eink/ServiceEink.cpp => module-services/service-eink/ServiceEink.cpp +8 -9
@@ 16,7 16,6 @@
#include <MessageType.hpp>
#include <Service/Bus.hpp>
#include <service-gui/messages/GUIMessage.hpp>
#include <vfs.hpp>

#include <cstdio>
#include <cstring>


@@ 184,7 183,7 @@ bool ServiceEink::changeWaveform(EinkWaveforms_e mode, const int32_t temperature
        break;
    }

    auto file = vfs.fopen("Luts.bin", "rb");
    auto file = std::fopen("Luts.bin", "rb");
    if (file == nullptr) {
        LOG_FATAL("Could not find the LUTS.bin file. Returning");
        return false;


@@ 198,7 197,7 @@ bool ServiceEink::changeWaveform(EinkWaveforms_e mode, const int32_t temperature

    if (waveformSettings.LUTDData == nullptr) {
        LOG_ERROR("Could not allocate memory for the LUTD array");
        vfs.fclose(file);
        std::fclose(file);
        return false;
    }



@@ 209,15 208,15 @@ bool ServiceEink::changeWaveform(EinkWaveforms_e mode, const int32_t temperature
    waveformSettings.LUTCData = new uint8_t[LUTC_SIZE + 1];
    if (waveformSettings.LUTCData == nullptr) {
        LOG_ERROR("Could not allocate memory for the LUTC array");
        vfs.fclose(file);
        std::fclose(file);
        return false;
    }

    waveformSettings.LUTDData[0] = EinkLUTD;
    waveformSettings.LUTCData[0] = EinkLUTC;

    vfs.fseek(file, offset, SEEK_SET);
    vfs.fread(&waveformSettings.LUTDData[1], 1, LUTD_SIZE, file);
    std::fseek(file, offset, SEEK_SET);
    std::fread(&waveformSettings.LUTDData[1], 1, LUTD_SIZE, file);

    uint8_t frameCount = waveformSettings.LUTDData[1] + 1; // 0x00 - 1 frame, ... , 0x0F - 16 frames
    waveformSettings.LUTDSize =


@@ 225,10 224,10 @@ bool ServiceEink::changeWaveform(EinkWaveforms_e mode, const int32_t temperature
        1; // (frameCount * 64) - size of actual LUT; (+1) - the byte containing frameCount; (+1) - EinkLUTD command

    offset += LUTD_SIZE;
    vfs.fseek(file, offset, SEEK_SET);
    vfs.fread(&waveformSettings.LUTCData[1], 1, LUTC_SIZE, file);
    std::fseek(file, offset, SEEK_SET);
    std::fread(&waveformSettings.LUTCData[1], 1, LUTC_SIZE, file);

    vfs.fclose(file);
    std::fclose(file);

    EinkUpdateWaveform(&waveformSettings);


M module-services/service-fileindexer/StartupIndexer.cpp => module-services/service-fileindexer/StartupIndexer.cpp +0 -1
@@ 5,7 5,6 @@
#include "messages/FileChangeMessage.hpp"
#include <filesystem>
#include <ff_stdio_listdir_recursive.h>
#include <vfs.hpp>
#include <purefs/filesystem_paths.hpp>
#include <Service/Bus.hpp>
#include "Constants.hpp"

M module-services/service-fileindexer/notesIndexer.cpp => module-services/service-fileindexer/notesIndexer.cpp +7 -8
@@ 3,8 3,8 @@

#include <log/log.hpp>
#include "notesIndexer.hpp"
#include <vfs.hpp>
#include <cwctype>
#include <cstdio>
#include <utf8/UTF8.hpp>

namespace service::detail


@@ 12,19 12,18 @@ namespace service::detail

    notesIndexer::notesIndexer(std::string_view path)
    {
        auto file = vfs.fopen(std::string(path).c_str(), "r");
        auto file = std::fopen(std::string(path).c_str(), "r");
        if (!file) {
            LOG_INFO("Unable to open file [%s] errr: [%s] . Ignore...",
                     std::string(path).c_str(),
                     vfs.lastErrnoToStr().c_str());
            LOG_INFO("Unable to open file [%s]. Ignore...", std::string(path).c_str());
            return;
        }
        if (!vfs.eof(file)) {
            auto line = vfs.getline(file, 4096);
        if (!std::feof(file)) {
            char line[4096];
            std::fgets(line, sizeof(line), file);
            mLinesCount++;
            updateLineStats(line);
        }
        vfs.fclose(file);
        std::fclose(file);
    }
    auto notesIndexer::updateLineStats(std::string_view _line) noexcept -> void
    {

M module-utils/CMakeLists.txt => module-utils/CMakeLists.txt +2 -1
@@ 34,7 34,8 @@ set (SOURCES
        ${CMAKE_CURRENT_SOURCE_DIR}/country.hpp
        ${CMAKE_CURRENT_SOURCE_DIR}/state/ServiceState.hpp
        ${CMAKE_CURRENT_SOURCE_DIR}/ical/ParserICS.cpp
		${CMAKE_CURRENT_SOURCE_DIR}/time/TimeRangeParser.cpp
        ${CMAKE_CURRENT_SOURCE_DIR}/time/TimeRangeParser.cpp
        ${CMAKE_CURRENT_SOURCE_DIR}/Utils.cpp
)

add_library(${PROJECT_NAME} STATIC ${SOURCES} ${BOARD_SOURCES})

A module-utils/Utils.cpp => module-utils/Utils.cpp +53 -0
@@ 0,0 1,53 @@
// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#include "Utils.hpp"

namespace utils::filesystem
{
    long int filelength(std::FILE *file) noexcept
    {
        if (file == nullptr) {
            return 0;
        }
        std::fseek(file, 0, SEEK_END);
        return std::ftell(file);
    }

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

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

        *outCrc32 = 0;

        while (!std::feof(file)) {
            bufLen = std::fread(buf.get(), 1, purefs::buffer::crc_buf, file);
            if (bufLen <= 0)
                break;

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

    std::string generateRandomId(std::size_t length) noexcept
    {
        const std::string CHARACTERS = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";

        std::random_device random_device;
        std::mt19937 generator(random_device());
        generator.seed(utils::time::Timestamp().getTime());
        std::uniform_int_distribution<> distribution(0, CHARACTERS.size() - 1);

        std::string random_string;

        for (std::size_t i = 0; i < length; ++i) {
            random_string += CHARACTERS[distribution(generator)];
        }

        return random_string;
    }
} // namespace utils::filesystem

M module-utils/Utils.hpp => module-utils/Utils.hpp +7 -8
@@ 8,6 8,8 @@
#include <sstream>
#include <iomanip>
#include <cmath>
#include <random>
#include "module-utils/time/time_conversion.hpp"

#define MAGIC_ENUM_RANGE_MAX 256
#include <magic_enum.hpp>


@@ 242,13 244,10 @@ namespace utils

    namespace filesystem
    {
        static inline long int filelength(std::FILE *file) noexcept
        {
            if (file == nullptr) {
                return 0;
            }
            std::fseek(file, 0, SEEK_END);
            return std::ftell(file);
        }
        [[nodiscard]] long int filelength(std::FILE *file) noexcept;

        void computeCRC32(std::FILE *file, unsigned long *outCrc32) noexcept;

        [[nodiscard]] std::string generateRandomId(std::size_t length = 0) noexcept;
    } // namespace filesystem
} // namespace utils

M module-utils/microtar => module-utils/microtar +1 -1
@@ 1,1 1,1 @@
Subproject commit eb38c8115a33dd2be8591afd97a4c69287abbcc7
Subproject commit 4b1bb35816269d956dbac1922f9cc8b3bd481c16