// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved. // For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md #pragma once #include #include #include #include #include #include #include #include #ifdef TARGET_Linux #include #else #include "ff_stdio.h" #include "board/cross/eMMC/eMMC.hpp" #endif #define PATH_SYS "/sys" #define PATH_USER "user" #define PATH_CURRENT "current" #define PATH_PREVIOUS "previous" #define PATH_UPDATES "updates" #define PATH_TMP "tmp" #define PATH_BACKUP "backup" #define PATH_FACTORY "factory" // this just concatenates two strings and creates a /user/ subdirectory filename #define USER_PATH(file) PATH_SYS "/" PATH_USER "/" file namespace fs = std::filesystem; namespace purefs { namespace dir { const inline fs::path eMMC_disk = PATH_SYS; const inline fs::path user_disk = eMMC_disk / PATH_USER; const inline fs::path os_current = eMMC_disk / PATH_CURRENT; const inline fs::path os_previous = eMMC_disk / PATH_PREVIOUS; const inline fs::path os_updates = eMMC_disk / PATH_UPDATES; const inline fs::path tmp = eMMC_disk / PATH_TMP; const inline fs::path os_backup = eMMC_disk / PATH_BACKUP; const inline fs::path os_factory = eMMC_disk / PATH_FACTORY; } // namespace dir namespace file { const inline fs::path boot_json = ".boot.json"; const inline fs::path boot_bin = "boot.bin"; }; // namespace file namespace extension { const inline std::string crc32 = ".crc32"; } namespace buffer { const inline int crc_buf = 1024; const inline int crc_char_size = 9; const inline int crc_radix = 16; const inline int tar_buf = 8192 * 4; const inline int copy_buf = 8192 * 4; } // namespace buffer namespace json { const inline std::string main = "main"; const inline std::string os_type = "ostype"; const inline std::string os_image = "imagename"; const inline std::string os_version = "version"; const inline std::string version_major = "major"; const inline std::string version_inor = "minor"; const inline std::string version_patch = "patch"; const inline std::string version_string = "string"; const inline std::string timestamp = "timestamp"; const inline std::string misc = "misc"; const inline std::string builddate = "builddate"; const inline std::string git_info = "git"; const inline std::string os_git_tag = "git_tag"; const inline std::string os_git_revision = "git_commit"; const inline std::string os_git_branch = "git_branch"; const inline std::string bootloader = "bootloader"; } // namespace json struct BootConfig { std::string os_image; std::string os_type; std::string os_version; std::string bootloader_verion; std::string timestamp; json11::Json boot_json_parsed; fs::path os_root_path; fs::path boot_json; static int version_compare(const std::string &v1, const std::string &v2); [[nodiscard]] json11::Json to_json() const; }; }; // namespace purefs class vfs { public: #ifdef TARGET_Linux using FILE = std::FILE; #else using FILE = FF_FILE; #endif enum class FileAttributes { ReadOnly, Writable, Directory }; struct DirectoryEntry { std::string fileName; FileAttributes attributes; uint32_t fileSize; json11::Json to_json() const { return (json11::Json::object{{"name", fileName}, {"size", std::to_string(fileSize)}}); } }; struct FilesystemStats { std::string type; uint32_t freeMbytes; uint32_t freePercent; uint32_t totalMbytes; }; vfs(); ~vfs(); void Init(); FILE *fopen(const char *filename, const char *mode); int fclose(FILE *stream); int remove(const char *name); size_t fread(void *ptr, size_t size, size_t count, FILE *stream); size_t fwrite(const void *ptr, size_t size, size_t count, FILE *stream); int fseek(FILE *stream, long int offset, int origin); long int ftell(FILE *stream); void rewind(FILE *stream); size_t filelength(FILE *stream); std::string getcurrdir(); char *fgets(char *buffer, size_t count, FILE *stream); bool eof(FILE *stream); std::vector listdir(const char *path, const std::string &ext = "", const bool bypassRootCheck = false); std::string getline(FILE *stream, uint32_t length = 1024); size_t fprintf(FILE *stream, const char *format, ...); FilesystemStats getFilesystemStats(); std::string relativeToRoot(const std::string path); std::string lastErrnoToStr(); bool isDir(const char *path); bool fileExists(const char *path); int deltree(const char *path); int mkdir(const char *dir); int rename(const char *oldname, const char *newname); std::string loadFileAsString(const fs::path &fileToLoad); bool replaceWithString(const fs::path &fileToModify, const std::string &stringToWrite); void updateTimestamp(); struct purefs::BootConfig &getBootConfig() { return bootConfig; } #ifndef TARGET_Linux bsp::eMMC emmc; FF_Disk_t *emmcFFDisk; #endif static void computeCRC32(FILE *file, unsigned long *outCrc32); static bool verifyCRC(const std::string filePath, const unsigned long crc32); static bool verifyCRC(const fs::path filePath); static std::string generateRandomId(size_t length); private: bool updateFileCRC32(const fs::path &file); const fs::path getCurrentBootJSON(); bool loadBootConfig(const fs::path &bootJsonPath); bool updateBootConfig(const fs::path &bootJsonPath); struct purefs::BootConfig bootConfig; }; extern vfs vfs;