From 8e42500fddfe06aa4240d3a9ee0ee3773783db8c Mon Sep 17 00:00:00 2001 From: Arisotura Date: Tue, 28 Sep 2021 00:20:29 +0200 Subject: [PATCH] commit some work --- src/FATStorage.cpp | 169 ++++++++++++++++++++++++++++++++++++++++++++- src/FATStorage.h | 24 ++++++- 2 files changed, 190 insertions(+), 3 deletions(-) diff --git a/src/FATStorage.cpp b/src/FATStorage.cpp index 3829ff78..939d2a05 100644 --- a/src/FATStorage.cpp +++ b/src/FATStorage.cpp @@ -23,10 +23,13 @@ #endif // __WIN32__ #include #include +#include #include "FATStorage.h" #include "Platform.h" +namespace fs = std::filesystem; + static int GetDirEntryType(const char* path, struct dirent* entry) { @@ -110,6 +113,115 @@ UINT FATStorage::FF_WriteStorage(BYTE* buf, LBA_t sector, UINT num) } +void FATStorage::LoadIndex() +{ + Index.clear(); + + FILE* f = Platform::OpenLocalFile(IndexPath.c_str(), "r"); + if (!f) return; + + char linebuf[1536]; + while (!feof(f)) + { + if (fgets(linebuf, 1536, f) == nullptr) + break; + + u64 fsize; + s64 lastmodified; + char fpath[1536] = {0}; + int ret = sscanf(linebuf, "FILE %" PRIu64 " %" PRId64 " %[^\t\r\n]", &fsize, &lastmodified, fpath); + if (ret < 3) continue; + + for (int i = 0; i < 1536 && fpath[i] != '\0'; i++) + { + if (fpath[i] == '\\') + fpath[i] = '/'; + } + + IndexEntry entry; + entry.Path = fpath; + entry.Size = fsize; + entry.LastModified = lastmodified; + + Index[entry.Path] = entry; + } + + fclose(f); +} + +void FATStorage::SaveIndex() +{ + FILE* f = Platform::OpenLocalFile(IndexPath.c_str(), "w"); + if (!f) return; + + for (const auto& [key, val] : Index) + { + fprintf(f, "FILE %" PRIu64 " %" PRId64 " %s\r\n", val.Size, val.LastModified, val.Path.c_str()); + } + + fclose(f); +} + + +int FATStorage::CleanupDirectory(std::string path, int level) +{ + if (level >= 32) return 44203; + + fDIR dir; + FILINFO info; + FRESULT res; + + res = f_opendir(&dir, path); + if (res != FR_OK) return 0; + + std::vector deletelist; + std::vector subdirlist; + int survivors = 0; + + for (;;) + { + res = f_readdir(&dir, &info); + if (res != FR_OK) return; + if (!info.fname[0]) return; + + std::string fullpath = path + info.fname; + + if (info.fattrib & AM_DIR) + { + subdirlist.push_back(fullpath); + } + else + { + if (Index.count(fullpath) < 1) + deletelist.push_back(fullpath); + else + survivors++; + } + } + + f_closedir(&dir); + + for (auto& entry : deletelist) + { + std::string fullpath = "0:/" + entry; + f_unlink(fullpath.c_str()); + } + + for (auto& entry : subdirlist) + { + int res = CleanupDirectory(entry+"/", level+1); + if (res < 1) + { + std::string fullpath = "0:/" + entry; + f_unlink(fullpath.c_str()); + } + else + survivors++; + } + + return survivors; +} + bool FATStorage::ImportFile(const char* path, const char* in) { FIL file; @@ -159,6 +271,57 @@ bool FATStorage::BuildSubdirectory(const char* sourcedir, const char* path, int return false; } + if (level == 0) + { + // remove whatever isn't in the index, as well as empty directories + CleanupDirectory("", 0); + + int srclen = strlen(sourcedir); + + for (auto& entry : fs::recursive_directory_iterator(sourcedir)) + { + std::string fullpath = entry.path().string(); + std::string innerpath = fullpath.substr(srclen); + if (innerpath[0] == '/' || innerpath[0] == '\\') + innerpath = innerpath.substr(1); + + int ilen = innerpath.length(); + for (int i = 0; i < ilen; i++) + { + if (innerpath[i] == '\\') + innerpath[i] = '/'; + } + + //std::chrono::duration bourf(lastmodified_raw); + //printf("DORP: %016llX\n", bourf.count()); + + if (entry.is_directory()) + { + innerpath = "0:/" + innerpath; + f_mkdir(innerpath.c_str()); + } + else if (entry.is_regular_file()) + { + u64 filesize = entry.file_size(); + + auto lastmodified = entry.last_write_time(); + s64 lastmodified_raw = std::chrono::duration_cast(lastmodified.time_since_epoch()).count(); + + IndexEntry derpo; + derpo.Path = entry.path().string(); + derpo.Size = filesize; + derpo.LastModified = lastmodified_raw; + + Index[derpo.Path] = derpo; + } + + } + + SaveIndex(); + + return false; + } + char fullpath[1024] = {0}; snprintf(fullpath, 1023, "%s%s", sourcedir, path); @@ -216,12 +379,16 @@ bool FATStorage::BuildSubdirectory(const char* sourcedir, const char* path, int bool FATStorage::Build(const char* sourcedir, u64 size, const char* filename) { - filesize = size; + FilePath = filename; + FileSize = size; FF_File = Platform::OpenLocalFile(filename, "w+b"); if (!FF_File) return false; + IndexPath = FilePath + ".idx"; + LoadIndex(); + FF_FileSize = size; ff_disk_open(FF_ReadStorage, FF_WriteStorage, (LBA_t)(size>>9)); diff --git a/src/FATStorage.h b/src/FATStorage.h index 5eabe79a..749f9cd9 100644 --- a/src/FATStorage.h +++ b/src/FATStorage.h @@ -20,6 +20,9 @@ #define FATSTORAGE_H #include +#include +#include +#include #include "types.h" #include "fatfs/ff.h" @@ -32,17 +35,34 @@ public: ~FATStorage(); private: - FILE* file; - u64 filesize; + std::string FilePath; + std::string IndexPath; + + FILE* File; + u64 FileSize; static FILE* FF_File; static u64 FF_FileSize; static UINT FF_ReadStorage(BYTE* buf, LBA_t sector, UINT num); static UINT FF_WriteStorage(BYTE* buf, LBA_t sector, UINT num); + void LoadIndex(); + void SaveIndex(); + + int CleanupDirectory(std::string path, int level); bool ImportFile(const char* path, const char* in); bool BuildSubdirectory(const char* sourcedir, const char* path, int level); bool Build(const char* sourcedir, u64 size, const char* filename); + + typedef struct + { + std::string Path; + u64 Size; + s64 LastModified; + + } IndexEntry; + + std::map Index; }; #endif // FATSTORAGE_H