From ee09cbe6120f0db62ab980968e2f841de5673a23 Mon Sep 17 00:00:00 2001 From: Gregwar Date: Sat, 28 Oct 2017 11:20:32 +0200 Subject: [PATCH 01/33] Updating version in manpage --- man/fatcat.1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/man/fatcat.1 b/man/fatcat.1 index 0f83da9..2e13372 100644 --- a/man/fatcat.1 +++ b/man/fatcat.1 @@ -11,7 +11,7 @@ npage for fatcat .. .\" Contact g.passault@gmail.com to correct errors or typos. -.TH man 1 "07 August 2014" "1.0.5" "fatcat man page" +.TH man 1 "28 October 2017" "1.0.6" "fatcat man page" .SH NAME fatcat \- FAT filesystem explore, extract, repair, and forensic tool .SH SYNOPSIS From f7e590d945464734673a7c884daa87087ee83bbe Mon Sep 17 00:00:00 2001 From: Gregwar Date: Sat, 28 Oct 2017 11:21:10 +0200 Subject: [PATCH 02/33] Updating version --- src/fatcat.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/fatcat.cpp b/src/fatcat.cpp index 425f835..9e04620 100644 --- a/src/fatcat.cpp +++ b/src/fatcat.cpp @@ -20,7 +20,7 @@ using namespace std; void usage() { - cout << "fatcat v1.0.5, Gregwar " << endl; + cout << "fatcat v1.0.6, Gregwar " << endl; cout << endl; cout << "Usage: fatcat disk.img [options]" << endl; cout << " -i: display information about disk" << endl; From 306a44e47f78caa46462f3459a481ea0a4cd44fa Mon Sep 17 00:00:00 2001 From: Vitaly Sinilin Date: Sat, 5 May 2018 15:34:19 +0300 Subject: [PATCH 03/33] Restore file timestamps when extracting It's convenient that an archiving utility restores file timestamps when extracting files. See no reason for fatcat not doing so. --- src/analysis/FatExtract.cpp | 25 +++++++++++++++++++++++++ src/core/FatDate.cpp | 25 +++++++++++++++++++++++++ src/core/FatDate.h | 2 ++ 3 files changed, 52 insertions(+) diff --git a/src/analysis/FatExtract.cpp b/src/analysis/FatExtract.cpp index c31c526..db20861 100644 --- a/src/analysis/FatExtract.cpp +++ b/src/analysis/FatExtract.cpp @@ -1,7 +1,10 @@ +#include #include #include +#include #include #include +#include #include #include "FatExtract.h" @@ -33,6 +36,28 @@ void FatExtract::onEntry(FatEntry &parent, FatEntry &entry, string name) FILE *output = fopen(target.c_str(), "w+"); system.readFile(entry.cluster, entry.size, output, contiguous); fclose(output); + + time_t mtime = entry.changeDate.timestamp(); + if (mtime == (time_t)-1) { + // Files on FAT can have dates up to 2107 year inclusive (which is + // more than 2038), so it's theoretically possible that on a dated + // system with 4-byte time_t some dates cannot be represented. + // Too bad. + cerr << "! Unable to set file timestamps for " << name + << ": value cannot be represented" << endl; + } else { + struct timeval times[2]; + // Modification time + times[1].tv_sec = mtime; + times[1].tv_usec = 0; + // Access time + times[0] = times[1]; + + if (utimes(target.c_str(), times) != 0) { + cerr << "! Unable to set file timestamps for " << name + << ": " << strerror(errno) << endl; + } + } } } diff --git a/src/core/FatDate.cpp b/src/core/FatDate.cpp index e226bdd..a919308 100644 --- a/src/core/FatDate.cpp +++ b/src/core/FatDate.cpp @@ -2,6 +2,7 @@ #include #include #include +#include #include #include "FatDate.h" @@ -33,3 +34,27 @@ string FatDate::pretty() return string(buffer); } + +/** + * Returns date as a number of seconds elapsed since the Epoch, + * 1970-01-01 00:00:00 +0000 (UTC). FAT dates are considered to be in the + * current timezone not in UTC. So what this function returns depends on + * the current timezone. + */ +time_t FatDate::timestamp() const +{ + struct tm tm; + tm.tm_sec = s; // Seconds (0-60) + tm.tm_min = i; // Minutes (0-59) + tm.tm_hour = h; // Hours (0-23) + tm.tm_mday = d; // Day of the month (1-31) + tm.tm_mon = m - 1; // Month (0-11) + tm.tm_year = y - 1900; // Year - 1900 + + // A negative value of tm_isdst means that mktime() should (use timezone + // information and system databases to) attempt to determine whether DST + // is in effect at the specified time. + tm.tm_isdst = -1; // Daylight saving time + + return mktime(&tm); +} diff --git a/src/core/FatDate.h b/src/core/FatDate.h index 829b15f..28cfc1d 100644 --- a/src/core/FatDate.h +++ b/src/core/FatDate.h @@ -2,6 +2,7 @@ #define _FATCAT_FATDATE_H #include +#include using namespace std; @@ -15,6 +16,7 @@ class FatDate int y, m, d; string pretty(); + time_t timestamp() const; }; #endif // _FATCAT_FATDATE_H From a11c3405611352a3abc6be4e64259033d0386c6d Mon Sep 17 00:00:00 2001 From: Vitaly Sinilin Date: Sat, 5 May 2018 22:30:09 +0300 Subject: [PATCH 04/33] Fix FAT12 determination As per the FAT Type Determination section of "FAT32 File System Specification". --- src/core/FatSystem.cpp | 12 +++++++----- src/core/FatSystem.h | 3 +++ 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/src/core/FatSystem.cpp b/src/core/FatSystem.cpp index 43f7912..e60cb9b 100644 --- a/src/core/FatSystem.cpp +++ b/src/core/FatSystem.cpp @@ -141,20 +141,22 @@ void FatSystem::parseHeader() if (sectorsPerFat != 0) { type = FAT16; - bits = 16; diskLabel = string(buffer+FAT16_DISK_LABEL, FAT16_DISK_LABEL_SIZE); fsType = string(buffer+FAT16_DISK_FS, FAT16_DISK_FS_SIZE); rootEntries = FAT_READ_SHORT(buffer, FAT16_ROOT_ENTRIES)&0xffff; rootDirectory = 0; - if (trim(fsType) == "FAT12") { - bits = 12; - } - totalSectors = FAT_READ_SHORT(buffer, FAT16_TOTAL_SECTORS)&0xffff; if (!totalSectors) { totalSectors = FAT_READ_LONG(buffer, FAT_TOTAL_SECTORS)&0xffffffff; } + + unsigned int rootDirSectors = + (rootEntries*FAT_ENTRY_SIZE + bytesPerSector-1)/bytesPerSector; + unsigned long dataSectors = totalSectors - + (reservedSectors + fats*sectorsPerFat + rootDirSectors); + unsigned long totalClusters = dataSectors/sectorsPerCluster; + bits = (totalClusters > MAX_FAT12) ? 16 : 12; } else { type = FAT32; bits = 32; diff --git a/src/core/FatSystem.h b/src/core/FatSystem.h index 55a8421..b462cec 100644 --- a/src/core/FatSystem.h +++ b/src/core/FatSystem.h @@ -13,6 +13,9 @@ using namespace std; // Last cluster #define FAT_LAST (-1) +// Maximum number of clusters +#define MAX_FAT12 0xFF4 + // Header offsets #define FAT_BYTES_PER_SECTOR 0x0b #define FAT_SECTORS_PER_CLUSTER 0x0d From 5d5c9af0485f6c1c14dd41d489e2b96f83b11926 Mon Sep 17 00:00:00 2001 From: "Armando G. Mondul" Date: Thu, 21 Mar 2019 15:27:07 -0500 Subject: [PATCH 05/33] Fix MacOS build error --- src/core/FatSystem.h | 5 +++++ src/fatcat.cpp | 6 ++++++ 2 files changed, 11 insertions(+) diff --git a/src/core/FatSystem.h b/src/core/FatSystem.h index 55a8421..3fc81da 100644 --- a/src/core/FatSystem.h +++ b/src/core/FatSystem.h @@ -8,6 +8,11 @@ #include "FatEntry.h" #include "FatPath.h" +#ifdef __APPLE__ +#define O_LARGEFILE 0 +#define lseek64 lseek +#endif + using namespace std; // Last cluster diff --git a/src/fatcat.cpp b/src/fatcat.cpp index 9e04620..15da952 100644 --- a/src/fatcat.cpp +++ b/src/fatcat.cpp @@ -1,5 +1,11 @@ #include + +#ifdef __APPLE__ +#include +#else #include +#endif + #include #include #include From 58ac75bdf7b790d3ed6a25494014d89a9ad17041 Mon Sep 17 00:00:00 2001 From: Inbar Barkai Date: Tue, 9 Jul 2019 09:57:56 +0300 Subject: [PATCH 06/33] Added output type enum --- src/core/OutputType.h | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 src/core/OutputType.h diff --git a/src/core/OutputType.h b/src/core/OutputType.h new file mode 100644 index 0000000..7523ea5 --- /dev/null +++ b/src/core/OutputType.h @@ -0,0 +1,6 @@ +#ifndef _OUTPUTTYPE_H +#define _OUTPUTTYPE_H + +enum OutputType { Default, Json }; + +#endif \ No newline at end of file From 46b3c9624c4ad8b5f018c4c4d7ed3e671e88991c Mon Sep 17 00:00:00 2001 From: Inbar Barkai Date: Tue, 9 Jul 2019 09:58:17 +0300 Subject: [PATCH 07/33] Added format switch --- src/fatcat.cpp | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/src/fatcat.cpp b/src/fatcat.cpp index 15da952..22f5b6a 100644 --- a/src/fatcat.cpp +++ b/src/fatcat.cpp @@ -1,5 +1,5 @@ #include - +#include #ifdef __APPLE__ #include #else @@ -31,6 +31,7 @@ void usage() cout << "Usage: fatcat disk.img [options]" << endl; cout << " -i: display information about disk" << endl; cout << " -O [offset]: global offset (may be partition place)" << endl; + cout << " -F [format]: output format (default, json)" << endl; cout << endl; cout << "Browsing & extracting:" << endl; cout << " -l [dir]: list files and directories in the given path" << endl; @@ -149,9 +150,10 @@ int main(int argc, char *argv[]) // -k: entry finder bool findEntry = false; + OutputType output = Default; // Parsing command line - while ((index = getopt(argc, argv, "il:L:r:R:s:dc:hx:2@:ob:p:w:v:mt:Sze:O:fk:a:")) != -1) { + while ((index = getopt(argc, argv, "il:L:r:R:s:dc:hx:2@:ob:p:w:v:mt:Sze:O:fk:a:F:")) != -1) { switch (index) { case 'a': attributesProvided = true; @@ -246,6 +248,16 @@ int main(int argc, char *argv[]) case 'h': usage(); break; + case 'F': + if (strcmp(optarg, "json") == 0) + output = Json; + else if (strcmp(optarg, "default") == 0) + output = Default; + else + { + usage(); + } + break; } } From 661e4717559c441f3188db1233bb37eb4d63d365 Mon Sep 17 00:00:00 2001 From: Inbar Barkai Date: Tue, 9 Jul 2019 10:00:40 +0300 Subject: [PATCH 08/33] Add output format to FatSystem --- src/core/FatSystem.cpp | 5 +++-- src/core/FatSystem.h | 5 ++++- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/src/core/FatSystem.cpp b/src/core/FatSystem.cpp index 43f7912..47f8e86 100644 --- a/src/core/FatSystem.cpp +++ b/src/core/FatSystem.cpp @@ -21,7 +21,7 @@ using namespace std; /** * Opens the FAT resource */ -FatSystem::FatSystem(string filename_, unsigned long long globalOffset_) +FatSystem::FatSystem(string filename_, unsigned long long globalOffset_, OutputType outputFormat_) : strange(0), filename(filename_), globalOffset(globalOffset_), @@ -31,8 +31,9 @@ FatSystem::FatSystem(string filename_, unsigned long long globalOffset_) freeClusters(0), cacheEnabled(false), type(FAT32), - rootEntries(0) + rootEntries(0), { + this->_outputFormat = outputFormat_; fd = open(filename.c_str(), O_RDONLY|O_LARGEFILE); writeMode = false; diff --git a/src/core/FatSystem.h b/src/core/FatSystem.h index 3fc81da..5e179b6 100644 --- a/src/core/FatSystem.h +++ b/src/core/FatSystem.h @@ -7,6 +7,7 @@ #include "FatEntry.h" #include "FatPath.h" +#include "OutputType.h" #ifdef __APPLE__ #define O_LARGEFILE 0 @@ -52,7 +53,7 @@ using namespace std; class FatSystem { public: - FatSystem(string filename, unsigned long long globalOffset = 0); + FatSystem(string filename, unsigned long long globalOffset = 0, OutputType outputFormat = (OutputType)0); ~FatSystem(); /** @@ -208,6 +209,8 @@ class FatSystem * Compute the free clusters stats */ void computeStats(); + + OutputType _outputFormat; }; #endif // _FATCAT_FATSYSTEM_H From 819d596387674ebc3472f2135bb1c34b2871edac Mon Sep 17 00:00:00 2001 From: Inbar Barkai Date: Tue, 9 Jul 2019 10:00:53 +0300 Subject: [PATCH 09/33] Enabled json output for infos method --- src/core/FatSystem.cpp | 107 ++++++++++++++++++++++++++++------------- 1 file changed, 74 insertions(+), 33 deletions(-) diff --git a/src/core/FatSystem.cpp b/src/core/FatSystem.cpp index 47f8e86..de4ea3f 100644 --- a/src/core/FatSystem.cpp +++ b/src/core/FatSystem.cpp @@ -568,39 +568,80 @@ bool FatSystem::init() void FatSystem::infos() { - cout << "FAT Filesystem information" << endl << endl; - - cout << "Filesystem type: " << fsType << endl; - cout << "OEM name: " << oemName << endl; - cout << "Total sectors: " << totalSectors << endl; - cout << "Total data clusters: " << totalClusters << endl; - cout << "Data size: " << dataSize << " (" << prettySize(dataSize) << ")" << endl; - cout << "Disk size: " << totalSize << " (" << prettySize(totalSize) << ")" << endl; - cout << "Bytes per sector: " << bytesPerSector << endl; - cout << "Sectors per cluster: " << sectorsPerCluster << endl; - cout << "Bytes per cluster: " << bytesPerCluster << endl; - cout << "Reserved sectors: " << reservedSectors << endl; - if (type == FAT16) { - cout << "Root entries: " << rootEntries << endl; - cout << "Root clusters: " << rootClusters << endl; - } - cout << "Sectors per FAT: " << sectorsPerFat << endl; - cout << "Fat size: " << fatSize << " (" << prettySize(fatSize) << ")" << endl; - printf("FAT1 start address: %016llx\n", fatStart); - printf("FAT2 start address: %016llx\n", fatStart+fatSize); - printf("Data start address: %016llx\n", dataStart); - cout << "Root directory cluster: " << rootDirectory << endl; - cout << "Disk label: " << diskLabel << endl; - cout << endl; - - computeStats(); - cout << "Free clusters: " << freeClusters << "/" << totalClusters; - cout << " (" << (100*freeClusters/(double)totalClusters) << "%)" << endl; - cout << "Free space: " << (freeClusters*bytesPerCluster) << - " (" << prettySize(freeClusters*bytesPerCluster) << ")" << endl; - cout << "Used space: " << ((totalClusters-freeClusters)*bytesPerCluster) << - " (" << prettySize((totalClusters-freeClusters)*bytesPerCluster) << ")" << endl; - cout << endl; + switch (this->_outputFormat) { + case Json: { + cout << "{\"FileSystemType\":\"" << trim(fsType) << "\","; + cout << "\"OemName\":\"" << oemName << "\","; + cout << "\"TotalSectors\":" << totalSectors << ","; + cout << "\"TotalDataClusters\":" << totalClusters << ","; + cout << "\"DataSize\":" << dataSize << ","; + cout << "\"PrettyDataSize\":\"" << prettySize(dataSize) << "\","; + cout << "\"DiskSize\":" << totalSize << ","; + cout << "\"DiskSize\":\"" << prettySize(totalSize) << "\","; + cout << "\"BytesPerSector\":" << bytesPerSector << ","; + cout << "\"SectorsPerCluster\":" << sectorsPerCluster << ","; + cout << "\"BytesPerCluster\":" << bytesPerCluster << ","; + cout << "\"ReservedSectors\":" << reservedSectors << ","; + if (type == FAT16) { + cout << "\"RootEntries\":" << rootEntries << ","; + cout << "\"RootClusters\":" << rootClusters << ","; + } + cout << "\"SectorsPerFat\":" << sectorsPerFat << ","; + cout << "\"FatSize\":" << fatSize << ","; + cout << "\"PrettyFatSize\":\"" << prettySize(fatSize) << "\","; + cout << "\"Fat1StartAddress\":" << fatStart << ","; + cout << "\"Fat2StartAddress\":" << fatStart+fatSize << ","; + cout << "\"DataStartAddress\":" << dataStart << ","; + cout << "\"RootDirectoryCluster\":" << rootDirectory << ","; + cout << "\"DiskLabel\":\"" << trim(diskLabel) << "\","; + + computeStats(); + cout << "\"FreeClusters\":" << freeClusters << ",\"TotalClusters\":" << totalClusters << ","; + cout << "\"FreeClustersPercent\":" << (100*freeClusters/(double)totalClusters) << ","; + cout << "\"FreeSpace\":" << (freeClusters*bytesPerCluster) << ","; + cout << "\"PrettyFreeSpace\":\"" << prettySize(freeClusters*bytesPerCluster) << "\","; + cout << "\"UsedSpace\":" << ((totalClusters-freeClusters)*bytesPerCluster) << ","; + cout << "\"PrettyUsedSpace\":\"" << prettySize((totalClusters-freeClusters)*bytesPerCluster) << "\"}"; + cout << endl; + break; + } + default: { + cout << "FAT Filesystem information" << endl << endl; + + cout << "Filesystem type: " << fsType << endl; + cout << "OEM name: " << oemName << endl; + cout << "Total sectors: " << totalSectors << endl; + cout << "Total data clusters: " << totalClusters << endl; + cout << "Data size: " << dataSize << " (" << prettySize(dataSize) << ")" << endl; + cout << "Disk size: " << totalSize << " (" << prettySize(totalSize) << ")" << endl; + cout << "Bytes per sector: " << bytesPerSector << endl; + cout << "Sectors per cluster: " << sectorsPerCluster << endl; + cout << "Bytes per cluster: " << bytesPerCluster << endl; + cout << "Reserved sectors: " << reservedSectors << endl; + if (type == FAT16) { + cout << "Root entries: " << rootEntries << endl; + cout << "Root clusters: " << rootClusters << endl; + } + cout << "Sectors per FAT: " << sectorsPerFat << endl; + cout << "Fat size: " << fatSize << " (" << prettySize(fatSize) << ")" << endl; + printf("FAT1 start address: %016llx\n", fatStart); + printf("FAT2 start address: %016llx\n", fatStart+fatSize); + printf("Data start address: %016llx\n", dataStart); + cout << "Root directory cluster: " << rootDirectory << endl; + cout << "Disk label: " << diskLabel << endl; + cout << endl; + + computeStats(); + cout << "Free clusters: " << freeClusters << "/" << totalClusters; + cout << " (" << (100*freeClusters/(double)totalClusters) << "%)" << endl; + cout << "Free space: " << (freeClusters*bytesPerCluster) << + " (" << prettySize(freeClusters*bytesPerCluster) << ")" << endl; + cout << "Used space: " << ((totalClusters-freeClusters)*bytesPerCluster) << + " (" << prettySize((totalClusters-freeClusters)*bytesPerCluster) << ")" << endl; + cout << endl; + break; + } + } } bool FatSystem::findDirectory(FatPath &path, FatEntry &outputEntry) From f607431ba3f4f5a7c0689a55fa4d46194ba36f30 Mon Sep 17 00:00:00 2001 From: Inbar Barkai Date: Tue, 9 Jul 2019 10:01:12 +0300 Subject: [PATCH 10/33] Passing the output format to the constructor --- src/fatcat.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/fatcat.cpp b/src/fatcat.cpp index 22f5b6a..8ce3eaf 100644 --- a/src/fatcat.cpp +++ b/src/fatcat.cpp @@ -285,7 +285,7 @@ int main(int argc, char *argv[]) try { // Openning the image - FatSystem fat(image, globalOffset); + FatSystem fat(image, globalOffset, output); fat.setListDeleted(listDeleted); From 882f92e7dc6380f8e0110a174879b482ee8ff0cf Mon Sep 17 00:00:00 2001 From: Inbar Barkai Date: Tue, 9 Jul 2019 10:36:31 +0300 Subject: [PATCH 11/33] Renamed OutputType to OutputFormatType --- src/core/FatSystem.cpp | 4 ++-- src/core/FatSystem.h | 6 +++--- src/core/OutputFormatType.h | 6 ++++++ src/core/OutputType.h | 6 ------ src/fatcat.cpp | 8 ++++---- 5 files changed, 15 insertions(+), 15 deletions(-) create mode 100644 src/core/OutputFormatType.h delete mode 100644 src/core/OutputType.h diff --git a/src/core/FatSystem.cpp b/src/core/FatSystem.cpp index de4ea3f..7b5111c 100644 --- a/src/core/FatSystem.cpp +++ b/src/core/FatSystem.cpp @@ -21,7 +21,7 @@ using namespace std; /** * Opens the FAT resource */ -FatSystem::FatSystem(string filename_, unsigned long long globalOffset_, OutputType outputFormat_) +FatSystem::FatSystem(string filename_, unsigned long long globalOffset_, OutputFormatType outputFormat_) : strange(0), filename(filename_), globalOffset(globalOffset_), @@ -31,7 +31,7 @@ FatSystem::FatSystem(string filename_, unsigned long long globalOffset_, OutputT freeClusters(0), cacheEnabled(false), type(FAT32), - rootEntries(0), + rootEntries(0) { this->_outputFormat = outputFormat_; fd = open(filename.c_str(), O_RDONLY|O_LARGEFILE); diff --git a/src/core/FatSystem.h b/src/core/FatSystem.h index 5e179b6..6b9ffa7 100644 --- a/src/core/FatSystem.h +++ b/src/core/FatSystem.h @@ -7,7 +7,7 @@ #include "FatEntry.h" #include "FatPath.h" -#include "OutputType.h" +#include "OutputFormatType.h" #ifdef __APPLE__ #define O_LARGEFILE 0 @@ -53,7 +53,7 @@ using namespace std; class FatSystem { public: - FatSystem(string filename, unsigned long long globalOffset = 0, OutputType outputFormat = (OutputType)0); + FatSystem(string filename, unsigned long long globalOffset = 0, OutputFormatType outputFormat = Default); ~FatSystem(); /** @@ -210,7 +210,7 @@ class FatSystem */ void computeStats(); - OutputType _outputFormat; + OutputFormatType _outputFormat; }; #endif // _FATCAT_FATSYSTEM_H diff --git a/src/core/OutputFormatType.h b/src/core/OutputFormatType.h new file mode 100644 index 0000000..7b7292c --- /dev/null +++ b/src/core/OutputFormatType.h @@ -0,0 +1,6 @@ +#ifndef _OUTPUTFORMATTYPE_H +#define _OUTPUTFORMATTYPE_H + +enum OutputFormatType { Default, Json }; + +#endif \ No newline at end of file diff --git a/src/core/OutputType.h b/src/core/OutputType.h deleted file mode 100644 index 7523ea5..0000000 --- a/src/core/OutputType.h +++ /dev/null @@ -1,6 +0,0 @@ -#ifndef _OUTPUTTYPE_H -#define _OUTPUTTYPE_H - -enum OutputType { Default, Json }; - -#endif \ No newline at end of file diff --git a/src/fatcat.cpp b/src/fatcat.cpp index 8ce3eaf..b307b2c 100644 --- a/src/fatcat.cpp +++ b/src/fatcat.cpp @@ -150,7 +150,7 @@ int main(int argc, char *argv[]) // -k: entry finder bool findEntry = false; - OutputType output = Default; + OutputFormatType outputFormat = Default; // Parsing command line while ((index = getopt(argc, argv, "il:L:r:R:s:dc:hx:2@:ob:p:w:v:mt:Sze:O:fk:a:F:")) != -1) { @@ -250,9 +250,9 @@ int main(int argc, char *argv[]) break; case 'F': if (strcmp(optarg, "json") == 0) - output = Json; + outputFormat = Json; else if (strcmp(optarg, "default") == 0) - output = Default; + outputFormat = Default; else { usage(); @@ -285,7 +285,7 @@ int main(int argc, char *argv[]) try { // Openning the image - FatSystem fat(image, globalOffset, output); + FatSystem fat(image, globalOffset, outputFormat); fat.setListDeleted(listDeleted); From 66d381cebfdc24a0f69003e2ae10aea95c1d0d43 Mon Sep 17 00:00:00 2001 From: Inbar Barkai Date: Tue, 9 Jul 2019 10:43:34 +0300 Subject: [PATCH 12/33] Fixed disk size duplicate json key --- src/core/FatSystem.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core/FatSystem.cpp b/src/core/FatSystem.cpp index 7b5111c..8ab453d 100644 --- a/src/core/FatSystem.cpp +++ b/src/core/FatSystem.cpp @@ -577,7 +577,7 @@ void FatSystem::infos() cout << "\"DataSize\":" << dataSize << ","; cout << "\"PrettyDataSize\":\"" << prettySize(dataSize) << "\","; cout << "\"DiskSize\":" << totalSize << ","; - cout << "\"DiskSize\":\"" << prettySize(totalSize) << "\","; + cout << "\"PrettyDiskSize\":\"" << prettySize(totalSize) << "\","; cout << "\"BytesPerSector\":" << bytesPerSector << ","; cout << "\"SectorsPerCluster\":" << sectorsPerCluster << ","; cout << "\"BytesPerCluster\":" << bytesPerCluster << ","; From 9a7db38aa18a5b152f45cd2882b23378a93cf234 Mon Sep 17 00:00:00 2001 From: Inbar Barkai Date: Tue, 9 Jul 2019 11:12:19 +0300 Subject: [PATCH 13/33] Implemented isoFormat method --- src/core/FatDate.cpp | 8 ++++++++ src/core/FatDate.h | 2 ++ 2 files changed, 10 insertions(+) diff --git a/src/core/FatDate.cpp b/src/core/FatDate.cpp index e226bdd..1368bca 100644 --- a/src/core/FatDate.cpp +++ b/src/core/FatDate.cpp @@ -33,3 +33,11 @@ string FatDate::pretty() return string(buffer); } + +string FatDate::isoFormat() +{ + char buffer[128]; + sprintf(buffer, "%04d-%02d-%02dT%02d:%02d:%02d", y, m, d, h, i, s); + + return string(buffer); +} diff --git a/src/core/FatDate.h b/src/core/FatDate.h index 829b15f..2bd2279 100644 --- a/src/core/FatDate.h +++ b/src/core/FatDate.h @@ -15,6 +15,8 @@ class FatDate int y, m, d; string pretty(); + + string isoFormat(); }; #endif // _FATCAT_FATDATE_H From b0ec8db455a28c34ea0d826674b4c792706b5be5 Mon Sep 17 00:00:00 2001 From: Inbar Barkai Date: Tue, 9 Jul 2019 11:12:45 +0300 Subject: [PATCH 14/33] Added support for json output when listing entries --- src/core/FatSystem.cpp | 117 ++++++++++++++++++++++++++++++----------- 1 file changed, 87 insertions(+), 30 deletions(-) diff --git a/src/core/FatSystem.cpp b/src/core/FatSystem.cpp index 8ab453d..1d1681c 100644 --- a/src/core/FatSystem.cpp +++ b/src/core/FatSystem.cpp @@ -440,54 +440,111 @@ void FatSystem::list(unsigned int cluster) { bool hasFree = false; vector entries = getEntries(cluster, NULL, &hasFree); - printf("Directory cluster: %u\n", cluster); - if (hasFree) { + if(this->_outputFormat == Json) + cout << "{\"Cluster\":" << cluster << ","; + else + printf("Directory cluster: %u\n", cluster); + if (hasFree && this->_outputFormat != Json) { printf("Warning: this directory has free clusters that was read contiguously\n"); } + if(this->_outputFormat == Json) + cout << "\"Entries\":"; list(entries); + if(this->_outputFormat == Json) + cout << "}"; } void FatSystem::list(vector &entries) { vector::iterator it; + if(this->_outputFormat == Json){ + cout << "["; + it = entries.begin(); + FatEntry &first = *it; + for (; it!=entries.end(); it++) { + FatEntry &entry = *it; + + if (entry.isErased() && !listDeleted) { + continue; + } + if(&entry != &first) { + cout << ","; + } + cout << "{\"EntryType\":"; + if (entry.isDirectory()) { + cout << "\"Directory\","; + } else { + cout << "\"File\","; + } - for (it=entries.begin(); it!=entries.end(); it++) { - FatEntry &entry = *it; + string name = entry.getFilename(); - if (entry.isErased() && !listDeleted) { - continue; - } + cout << "\"EditDate\":\"" << entry.changeDate.isoFormat() << "\","; + cout << "\"Name\":\"" << name << "\","; + cout << "\"Cluster\":" << entry.cluster << ","; - if (entry.isDirectory()) { - printf("d"); - } else { - printf("f"); - } + if (!entry.isDirectory()) { + string pretty = prettySize(entry.size); + cout << "\"Size\":" << entry.size << ","; + cout << "\"PrettySize\":\"" << pretty << "\","; + } - string name = entry.getFilename(); - if (entry.isDirectory()) { - name += "/"; + if (entry.isHidden()) { + cout << "\"IsHidden\":true,"; + } + else { + cout << "\"IsHidden\":false,"; + } + if (entry.isErased()) { + cout << "\"IsDeleted\":true"; + } + else { + cout << "\"IsDeleted\":false"; + } + cout << "}"; + fflush(stdout); } + cout << "]"; + } + else { + for (it=entries.begin(); it!=entries.end(); it++) { + FatEntry &entry = *it; - printf(" %s ", entry.changeDate.pretty().c_str()); - printf(" %-30s", name.c_str()); + if (entry.isErased() && !listDeleted) { + continue; + } - printf(" c=%u", entry.cluster); + if (entry.isDirectory()) { + printf("d"); + } else { + printf("f"); + } - if (!entry.isDirectory()) { - string pretty = prettySize(entry.size); - printf(" s=%llu (%s)", entry.size, pretty.c_str()); - } + string name = entry.getFilename(); + if (entry.isDirectory()) { + name += "/"; + } - if (entry.isHidden()) { - printf(" h"); - } - if (entry.isErased()) { - printf(" d"); - } + printf(" %s ", entry.changeDate.pretty().c_str()); + printf(" %-30s", name.c_str()); - printf("\n"); - fflush(stdout); + printf(" c=%u", entry.cluster); + + if (!entry.isDirectory()) { + string pretty = prettySize(entry.size); + printf(" s=%llu (%s)", entry.size, pretty.c_str()); + } + + if (entry.isHidden()) { + printf(" h"); + } + if (entry.isErased()) { + printf(" d"); + } + + printf("\n"); + fflush(stdout); + } } } From 8aca56912a220857fac855239b138d5780dc3209 Mon Sep 17 00:00:00 2001 From: Inbar Barkai Date: Tue, 9 Jul 2019 15:11:41 +0300 Subject: [PATCH 15/33] Removed printing path when using json output --- src/fatcat.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/fatcat.cpp b/src/fatcat.cpp index b307b2c..e1987a7 100644 --- a/src/fatcat.cpp +++ b/src/fatcat.cpp @@ -293,7 +293,8 @@ int main(int argc, char *argv[]) if (infoFlag) { fat.infos(); } else if (listFlag) { - cout << "Listing path " << listPath << endl; + if (outputFormat != Json) + cout << "Listing path " << listPath << endl; FatPath path(listPath); fat.list(path); } else if (listClusterFlag) { From 4315c5a1ff88bfbb15b679cdc797bdd7cb9d7ce3 Mon Sep 17 00:00:00 2001 From: Inbar Barkai Date: Mon, 15 Jul 2019 13:53:03 +0300 Subject: [PATCH 16/33] Printing cluster number only if output is not json --- src/fatcat.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/fatcat.cpp b/src/fatcat.cpp index e1987a7..9d72bdb 100644 --- a/src/fatcat.cpp +++ b/src/fatcat.cpp @@ -298,7 +298,8 @@ int main(int argc, char *argv[]) FatPath path(listPath); fat.list(path); } else if (listClusterFlag) { - cout << "Listing cluster " << listCluster << endl; + if (outputFormat != Json) + cout << "Listing cluster " << listCluster << endl; fat.list(listCluster); } else if (readFlag) { FatPath path(readPath); From d62c47f3f7ce5fb52d6b37460cbc2150cac0f7cc Mon Sep 17 00:00:00 2001 From: Inbar Barkai Date: Wed, 7 Aug 2019 15:56:26 +0300 Subject: [PATCH 17/33] Added getopt alternative for windows --- CMakeLists.txt | 4 + src/xgetopt/argcargv.cpp | 127 +++++++++++++++++++++++ src/xgetopt/argcargv.h | 8 ++ src/xgetopt/stdafx.cpp | 8 ++ src/xgetopt/stdafx.h | 20 ++++ src/xgetopt/xgetopt.cpp | 215 +++++++++++++++++++++++++++++++++++++++ src/xgetopt/xgetopt.h | 24 +++++ 7 files changed, 406 insertions(+) create mode 100644 src/xgetopt/argcargv.cpp create mode 100644 src/xgetopt/argcargv.h create mode 100644 src/xgetopt/stdafx.cpp create mode 100644 src/xgetopt/stdafx.h create mode 100644 src/xgetopt/xgetopt.cpp create mode 100644 src/xgetopt/xgetopt.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 2e8fc3b..c5e792d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -18,6 +18,10 @@ set(SOURCES analysis/FatChains.cpp analysis/FatSearch.cpp analysis/FatWalk.cpp + + xgetopt/xgetopt.cpp + xgetopt/stdafx.cpp + xgetopt/argcargv.cpp ) foreach(SOURCE ${SOURCES}) diff --git a/src/xgetopt/argcargv.cpp b/src/xgetopt/argcargv.cpp new file mode 100644 index 0000000..5fc5eee --- /dev/null +++ b/src/xgetopt/argcargv.cpp @@ -0,0 +1,127 @@ +//========================================== +// LIBCTINY - Matt Pietrek 2001 +// MSDN Magazine, January 2001 +//========================================== + +// NOTE: THIS CODE HAS BEEN MODIFIED FOR THIS DEMO APP + +// The original source for the LIBCTINY library may be +// found here: www.wheaty.net + +#include "stdafx.h" +#include "argcargv.h" + +#define _MAX_CMD_LINE_ARGS 128 + +TCHAR *_ppszArgv[_MAX_CMD_LINE_ARGS + 1]; + +int _ConvertCommandLineToArgcArgv(LPCTSTR lpszSysCmdLine) +{ + if (lpszSysCmdLine == NULL || lpszSysCmdLine[0] == 0) + return 0; + + static LPVOID pHeap = NULL; + + // Set to no argv elements, in case we have to bail out + _ppszArgv[0] = 0; + + // First get a pointer to the system's version of the command line, and + // figure out how long it is. + int cbCmdLine = lstrlen(lpszSysCmdLine); + + // Allocate memory to store a copy of the command line. We'll modify + // this copy, rather than the original command line. Yes, this memory + // currently doesn't explicitly get freed, but it goes away when the + // process terminates. + if (pHeap) // in case we are called multiple times + { + HeapFree(GetProcessHeap(), 0, pHeap); + pHeap = NULL; + } + + pHeap = HeapAlloc(GetProcessHeap(), 0, cbCmdLine * sizeof(TCHAR) + 16); + + if (!pHeap) + return 0; + + LPTSTR pszCmdLine = (LPTSTR)pHeap; + + // Copy the system version of the command line into our copy + lstrcpy(pszCmdLine, lpszSysCmdLine); + + if (_T('"') == *pszCmdLine) // If command line starts with a quote ("), + { // it's a quoted filename. Skip to next quote. + pszCmdLine++; + + _ppszArgv[0] = pszCmdLine; // argv[0] == executable name + + while (*pszCmdLine && (*pszCmdLine != _T('"'))) + pszCmdLine++; + + if (*pszCmdLine) // Did we see a non-NULL ending? + *pszCmdLine++ = _T('\0'); // Null terminate and advance to next char + else + return 0; // Oops! We didn't see the end quote + } + else // A regular (non-quoted) filename + { + _ppszArgv[0] = pszCmdLine; // argv[0] == executable name + + while (*pszCmdLine && (_T(' ') != *pszCmdLine) && (_T('\t') != *pszCmdLine)) + pszCmdLine++; + + if (*pszCmdLine) + *pszCmdLine++ = _T('\0'); // Null terminate and advance to next char + } + + // Done processing argv[0] (i.e., the executable name). Now do th + // actual arguments + + int argc = 1; + + while (1) + { + // Skip over any whitespace + while (*pszCmdLine && (_T(' ') == *pszCmdLine) || (_T('\t') == *pszCmdLine)) + pszCmdLine++; + + if (_T('\0') == *pszCmdLine) // End of command line??? + return argc; + + if (_T('"') == *pszCmdLine) // Argument starting with a quote??? + { + pszCmdLine++; // Advance past quote character + + _ppszArgv[argc++] = pszCmdLine; + _ppszArgv[argc] = 0; + + // Scan to end quote, or NULL terminator + while (*pszCmdLine && (*pszCmdLine != _T('"'))) + pszCmdLine++; + + if (_T('\0') == *pszCmdLine) + return argc; + + if (*pszCmdLine) + *pszCmdLine++ = _T('\0'); // Null terminate and advance to next char + } + else // Non-quoted argument + { + _ppszArgv[argc++] = pszCmdLine; + _ppszArgv[argc] = 0; + + // Skip till whitespace or NULL terminator + while (*pszCmdLine && (_T(' ') != *pszCmdLine) && (_T('\t') != *pszCmdLine)) + pszCmdLine++; + + if (_T('\0') == *pszCmdLine) + return argc; + + if (*pszCmdLine) + *pszCmdLine++ = _T('\0'); // Null terminate and advance to next char + } + + if (argc >= (_MAX_CMD_LINE_ARGS)) + return argc; + } +} diff --git a/src/xgetopt/argcargv.h b/src/xgetopt/argcargv.h new file mode 100644 index 0000000..edb61d7 --- /dev/null +++ b/src/xgetopt/argcargv.h @@ -0,0 +1,8 @@ +#ifndef ARGCARGV_H +#define ARGCARGV_H + +extern TCHAR *_ppszArgv[]; + +int _ConvertCommandLineToArgcArgv(LPCTSTR lpszSysCmdLine); + +#endif //ARGCARGV_H diff --git a/src/xgetopt/stdafx.cpp b/src/xgetopt/stdafx.cpp new file mode 100644 index 0000000..67e2705 --- /dev/null +++ b/src/xgetopt/stdafx.cpp @@ -0,0 +1,8 @@ +// stdafx.cpp : source file that includes just the standard includes +// XGetoptTest.pch will be the pre-compiled header +// stdafx.obj will contain the pre-compiled type information + +#include "stdafx.h" + + + diff --git a/src/xgetopt/stdafx.h b/src/xgetopt/stdafx.h new file mode 100644 index 0000000..2f1c723 --- /dev/null +++ b/src/xgetopt/stdafx.h @@ -0,0 +1,20 @@ +// stdafx.h : include file for standard system include files, +// or project specific include files that are used frequently, but +// are changed infrequently +// + +#ifndef STDAFX_H +#define STDAFX_H +#define _AFXDLL 1 +#define VC_EXTRALEAN // Exclude rarely-used stuff from Windows headers +#include // MFC core and standard components +#include // MFC extensions +#include // MFC support for Internet Explorer 4 Common Controls +#ifndef _AFX_NO_AFXCMN_SUPPORT +#include // MFC support for Windows Common Controls +#endif // _AFX_NO_AFXCMN_SUPPORT + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ will insert additional declarations immediately before the previous line. + +#endif //STDAFX_H diff --git a/src/xgetopt/xgetopt.cpp b/src/xgetopt/xgetopt.cpp new file mode 100644 index 0000000..428619f --- /dev/null +++ b/src/xgetopt/xgetopt.cpp @@ -0,0 +1,215 @@ +// XGetopt.cpp Version 1.2 +// +// Author: Hans Dietrich +// hdietrich2@hotmail.com +// +// Description: +// XGetopt.cpp implements getopt(), a function to parse command lines. +// +// History +// Version 1.2 - 2003 May 17 +// - Added Unicode support +// +// Version 1.1 - 2002 March 10 +// - Added example to XGetopt.cpp module header +// +// This software is released into the public domain. +// You are free to use it in any way you like. +// +// This software is provided "as is" with no expressed +// or implied warranty. I accept no liability for any +// damage or loss of business that this software may cause. +// +/////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////// +// if you are using precompiled headers then include this line: +#include "stdafx.h" +/////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////// +// if you are not using precompiled headers then include these lines: +//#include +//#include +//#include +/////////////////////////////////////////////////////////////////////////////// + +#include "xgetopt.h" + +/////////////////////////////////////////////////////////////////////////////// +// +// X G e t o p t . c p p +// +// +// NAME +// getopt -- parse command line options +// +// SYNOPSIS +// int getopt(int argc, TCHAR *argv[], TCHAR *optstring) +// +// extern TCHAR *optarg; +// extern int optind; +// +// DESCRIPTION +// The getopt() function parses the command line arguments. Its +// arguments argc and argv are the argument count and array as +// passed into the application on program invocation. In the case +// of Visual C++ programs, argc and argv are available via the +// variables __argc and __argv (double underscores), respectively. +// getopt returns the next option letter in argv that matches a +// letter in optstring. (Note: Unicode programs should use +// __targv instead of __argv. Also, all character and string +// literals should be enclosed in _T( ) ). +// +// optstring is a string of recognized option letters; if a letter +// is followed by a colon, the option is expected to have an argument +// that may or may not be separated from it by white space. optarg +// is set to point to the start of the option argument on return from +// getopt. +// +// Option letters may be combined, e.g., "-ab" is equivalent to +// "-a -b". Option letters are case sensitive. +// +// getopt places in the external variable optind the argv index +// of the next argument to be processed. optind is initialized +// to 0 before the first call to getopt. +// +// When all options have been processed (i.e., up to the first +// non-option argument), getopt returns EOF, optarg will point +// to the argument, and optind will be set to the argv index of +// the argument. If there are no non-option arguments, optarg +// will be set to NULL. +// +// The special option "--" may be used to delimit the end of the +// options; EOF will be returned, and "--" (and everything after it) +// will be skipped. +// +// RETURN VALUE +// For option letters contained in the string optstring, getopt +// will return the option letter. getopt returns a question mark (?) +// when it encounters an option letter not included in optstring. +// EOF is returned when processing is finished. +// +// BUGS +// 1) Long options are not supported. +// 2) The GNU double-colon extension is not supported. +// 3) The environment variable POSIXLY_CORRECT is not supported. +// 4) The + syntax is not supported. +// 5) The automatic permutation of arguments is not supported. +// 6) This implementation of getopt() returns EOF if an error is +// encountered, instead of -1 as the latest standard requires. +// +// EXAMPLE +// BOOL CMyApp::ProcessCommandLine(int argc, TCHAR *argv[]) +// { +// int c; +// +// while ((c = getopt(argc, argv, _T("aBn:"))) != EOF) +// { +// switch (c) +// { +// case _T('a'): +// TRACE(_T("option a\n")); +// // +// // set some flag here +// // +// break; +// +// case _T('B'): +// TRACE( _T("option B\n")); +// // +// // set some other flag here +// // +// break; +// +// case _T('n'): +// TRACE(_T("option n: value=%d\n"), atoi(optarg)); +// // +// // do something with value here +// // +// break; +// +// case _T('?'): +// TRACE(_T("ERROR: illegal option %s\n"), argv[optind-1]); +// return FALSE; +// break; +// +// default: +// TRACE(_T("WARNING: no handler for option %c\n"), c); +// return FALSE; +// break; +// } +// } +// // +// // check for non-option args here +// // +// return TRUE; +// } +// +/////////////////////////////////////////////////////////////////////////////// + +TCHAR *optarg; // global argument pointer +int optind = 0; // global argv index + +int getopt(int argc, TCHAR *argv[], TCHAR *optstring) +{ + static TCHAR *next = NULL; + if (optind == 0) + next = NULL; + + optarg = NULL; + + if (next == NULL || *next == _T('\0')) + { + if (optind == 0) + optind++; + + if (optind >= argc || argv[optind][0] != _T('-') || argv[optind][1] == _T('\0')) + { + optarg = NULL; + if (optind < argc) + optarg = argv[optind]; + return EOF; + } + + if (_tcscmp(argv[optind], _T("--")) == 0) + { + optind++; + optarg = NULL; + if (optind < argc) + optarg = argv[optind]; + return EOF; + } + + next = argv[optind]; + next++; // skip past - + optind++; + } + + TCHAR c = *next++; + TCHAR *cp = _tcschr(optstring, c); + + if (cp == NULL || c == _T(':')) + return _T('?'); + + cp++; + if (*cp == _T(':')) + { + if (*next != _T('\0')) + { + optarg = next; + next = NULL; + } + else if (optind < argc) + { + optarg = argv[optind]; + optind++; + } + else + { + return _T('?'); + } + } + + return c; +} diff --git a/src/xgetopt/xgetopt.h b/src/xgetopt/xgetopt.h new file mode 100644 index 0000000..57c630a --- /dev/null +++ b/src/xgetopt/xgetopt.h @@ -0,0 +1,24 @@ +#include +// XGetopt.h Version 1.2 +// +// Author: Hans Dietrich +// hdietrich2@hotmail.com +// +// This software is released into the public domain. +// You are free to use it in any way you like. +// +// This software is provided "as is" with no expressed +// or implied warranty. I accept no liability for any +// damage or loss of business that this software may cause. +// +/////////////////////////////////////////////////////////////////////////////// + +#ifndef XGETOPT_H +#define XGETOPT_H + +extern int optind, opterr; +extern TCHAR *optarg; + +int getopt(int argc, TCHAR *argv[], TCHAR *optstring); + +#endif //XGETOPT_H From 9972a971e53212a8d1bd7e28eae7f4c761a94e02 Mon Sep 17 00:00:00 2001 From: Inbar Barkai Date: Wed, 7 Aug 2019 16:19:04 +0300 Subject: [PATCH 18/33] Added support for windows compilation --- src/FatUtils.h | 31 +++--- src/analysis/FatExtract.cpp | 11 +- src/core/FatSystem.cpp | 99 +++++++++++++---- src/core/FatSystem.h | 181 ++++++++++++++++--------------- src/fatcat.cpp | 209 ++++++++++++++++++------------------ 5 files changed, 303 insertions(+), 228 deletions(-) diff --git a/src/FatUtils.h b/src/FatUtils.h index 33985cb..5080f2a 100644 --- a/src/FatUtils.h +++ b/src/FatUtils.h @@ -6,6 +6,11 @@ #include #include #include +#ifdef __WIN__ +#include +#else + +#endif using namespace std; @@ -26,20 +31,20 @@ using namespace std; buffer[x+3] = ((l)>>24)&0xff; // trim from start -static inline std::string ltrim(std::string s) { - s.erase(s.begin(), std::find_if(s.begin(), s.end(), std::not1(std::ptr_fun(std::isspace)))); - return s; +static inline string ltrim(string s) { + s.erase(s.begin(), find_if(s.begin(), s.end(), not1(ptr_fun(isspace)))); + return s; } // trim from end -static inline std::string rtrim(std::string s) { - s.erase(std::find_if(s.rbegin(), s.rend(), std::not1(std::ptr_fun(std::isspace))).base(), s.end()); - return s; +static inline string rtrim(string s) { + s.erase(find_if(s.rbegin(), s.rend(), not1(ptr_fun(isspace))).base(), s.end()); + return s; } // trim from both ends -static inline std::string trim(std::string s) { - return ltrim(rtrim(s)); +static inline string trim(string s) { + return ltrim(rtrim(s)); } // split a string into vector @@ -65,17 +70,17 @@ static inline string prettySize(unsigned long long bytes) n++; } - ostringstream oss; - oss << size << units[n]; + ostringstream oss; + oss << size << units[n]; - return oss.str(); + return oss.str(); } -static inline std::string strtolower(std::string myString) +static inline string strtolower(string myString) { const int length = myString.length(); for(int i=0; i!=length; ++i) { - myString[i] = std::tolower(myString[i]); + myString[i] = tolower(myString[i]); } return myString; diff --git a/src/analysis/FatExtract.cpp b/src/analysis/FatExtract.cpp index c31c526..2aa7721 100644 --- a/src/analysis/FatExtract.cpp +++ b/src/analysis/FatExtract.cpp @@ -4,6 +4,9 @@ #include #include #include "FatExtract.h" +#ifdef __WIN__ +#include +#endif using namespace std; @@ -11,11 +14,15 @@ FatExtract::FatExtract(FatSystem &system) : FatWalk(system) { } - + void FatExtract::onDirectory(FatEntry &parent, FatEntry &entry, string name) { string directory = targetDirectory + "/" + name; +#ifdef __WIN__ + CreateDirectory(directory.c_str(), NULL); +#else mkdir(directory.c_str(), 0755); +#endif } void FatExtract::onEntry(FatEntry &parent, FatEntry &entry, string name) @@ -35,7 +42,7 @@ void FatExtract::onEntry(FatEntry &parent, FatEntry &entry, string name) fclose(output); } } - + void FatExtract::extract(unsigned int cluster, string directory, bool erased) { walkErased = erased; diff --git a/src/core/FatSystem.cpp b/src/core/FatSystem.cpp index 1d1681c..5bba16b 100644 --- a/src/core/FatSystem.cpp +++ b/src/core/FatSystem.cpp @@ -1,4 +1,8 @@ +#ifdef __WIN__ +#include +#else #include +#endif #include #include #include @@ -23,14 +27,14 @@ using namespace std; */ FatSystem::FatSystem(string filename_, unsigned long long globalOffset_, OutputFormatType outputFormat_) : strange(0), - filename(filename_), - globalOffset(globalOffset_), - totalSize(-1), - listDeleted(false), - statsComputed(false), - freeClusters(0), - cacheEnabled(false), - type(FAT32), + filename(filename_), + globalOffset(globalOffset_), + totalSize(-1), + listDeleted(false), + statsComputed(false), + freeClusters(0), + cacheEnabled(false), + type(FAT32), rootEntries(0) { this->_outputFormat = outputFormat_; @@ -193,7 +197,13 @@ void FatSystem::parseHeader() unsigned int FatSystem::nextCluster(unsigned int cluster, int fat) { int bytes = (bits == 32 ? 4 : 2); +#ifndef __WIN__ char buffer[bytes]; +#else + char *buffer = new char[bytes]; + __try + { +#endif if (!validCluster(cluster)) { return 0; @@ -237,6 +247,13 @@ unsigned int FatSystem::nextCluster(unsigned int cluster, int fat) } } } +#ifdef __WIN__ +} +__finally +{ + delete[] buffer; +} +#endif } /** @@ -245,7 +262,13 @@ unsigned int FatSystem::nextCluster(unsigned int cluster, int fat) bool FatSystem::writeNextCluster(unsigned int cluster, unsigned int next, int fat) { int bytes = (bits == 32 ? 4 : 2); +#ifndef __WIN__ char buffer[bytes]; +#else + char *buffer = new char[bytes]; + __try + { +#endif if (!validCluster(cluster)) { throw string("Trying to access a cluster outside bounds"); @@ -271,6 +294,13 @@ bool FatSystem::writeNextCluster(unsigned int cluster, unsigned int next, int fa } return writeData(offset, buffer, bytes) == bytes; +#ifdef __WIN__ +} +__finally +{ + delete[] buffer; +} +#endif } bool FatSystem::validCluster(unsigned int cluster) @@ -562,7 +592,13 @@ void FatSystem::readFile(unsigned int cluster, unsigned int size, FILE *f, bool if (toRead > bytesPerCluster || size < 0) { toRead = bytesPerCluster; } +#ifndef __WIN__ char buffer[bytesPerCluster]; +#else + char *buffer = new char[bytesPerCluster]; + __try + { +#endif readData(clusterAddress(cluster), buffer, toRead); if (size != -1) { @@ -598,7 +634,13 @@ void FatSystem::readFile(unsigned int cluster, unsigned int size, FILE *f, bool cluster = currentCluster+1; } } +#ifdef __WIN__ + } + __finally + { + delete[] buffer; } +#endif } bool FatSystem::init() @@ -632,10 +674,10 @@ void FatSystem::infos() cout << "\"TotalSectors\":" << totalSectors << ","; cout << "\"TotalDataClusters\":" << totalClusters << ","; cout << "\"DataSize\":" << dataSize << ","; - cout << "\"PrettyDataSize\":\"" << prettySize(dataSize) << "\","; - cout << "\"DiskSize\":" << totalSize << ","; - cout << "\"PrettyDiskSize\":\"" << prettySize(totalSize) << "\","; - cout << "\"BytesPerSector\":" << bytesPerSector << ","; + cout << "\"PrettyDataSize\":\"" << prettySize(dataSize) << "\","; + cout << "\"DiskSize\":" << totalSize << ","; + cout << "\"PrettyDiskSize\":\"" << prettySize(totalSize) << "\","; + cout << "\"BytesPerSector\":" << bytesPerSector << ","; cout << "\"SectorsPerCluster\":" << sectorsPerCluster << ","; cout << "\"BytesPerCluster\":" << bytesPerCluster << ","; cout << "\"ReservedSectors\":" << reservedSectors << ","; @@ -643,7 +685,7 @@ void FatSystem::infos() cout << "\"RootEntries\":" << rootEntries << ","; cout << "\"RootClusters\":" << rootClusters << ","; } - cout << "\"SectorsPerFat\":" << sectorsPerFat << ","; + cout << "\"SectorsPerFat\":" << sectorsPerFat << ","; cout << "\"FatSize\":" << fatSize << ","; cout << "\"PrettyFatSize\":\"" << prettySize(fatSize) << "\","; cout << "\"Fat1StartAddress\":" << fatStart << ","; @@ -667,11 +709,11 @@ void FatSystem::infos() cout << "Filesystem type: " << fsType << endl; cout << "OEM name: " << oemName << endl; - cout << "Total sectors: " << totalSectors << endl; - cout << "Total data clusters: " << totalClusters << endl; - cout << "Data size: " << dataSize << " (" << prettySize(dataSize) << ")" << endl; - cout << "Disk size: " << totalSize << " (" << prettySize(totalSize) << ")" << endl; - cout << "Bytes per sector: " << bytesPerSector << endl; + cout << "Total sectors: " << totalSectors << endl; + cout << "Total data clusters: " << totalClusters << endl; + cout << "Data size: " << dataSize << " (" << prettySize(dataSize) << ")" << endl; + cout << "Disk size: " << totalSize << " (" << prettySize(totalSize) << ")" << endl; + cout << "Bytes per sector: " << bytesPerSector << endl; cout << "Sectors per cluster: " << sectorsPerCluster << endl; cout << "Bytes per cluster: " << bytesPerCluster << endl; cout << "Reserved sectors: " << reservedSectors << endl; @@ -686,7 +728,7 @@ void FatSystem::infos() printf("Data start address: %016llx\n", dataStart); cout << "Root directory cluster: " << rootDirectory << endl; cout << "Disk label: " << diskLabel << endl; - cout << endl; + cout << endl; computeStats(); cout << "Free clusters: " << freeClusters << "/" << totalClusters; @@ -698,7 +740,7 @@ void FatSystem::infos() cout << endl; break; } - } + } } bool FatSystem::findDirectory(FatPath &path, FatEntry &outputEntry) @@ -821,7 +863,13 @@ void FatSystem::rewriteUnallocated(bool random) srand(time(NULL)); for (int cluster=0; cluster &entries); - void list(unsigned int cluster); - void list(FatPath &path); + void list(vector &entries); + void list(unsigned int cluster); + void list(FatPath &path); - /** + /** * Display infos about FAT */ - void infos(); + void infos(); - /** + /** * Find a directory or a file */ - bool findDirectory(FatPath &path, FatEntry &entry); - bool findFile(FatPath &path, FatEntry &entry); + bool findDirectory(FatPath &path, FatEntry &entry); + bool findFile(FatPath &path, FatEntry &entry); - /** + /** * File reading */ void readFile(FatPath &path, FILE *f = NULL); @@ -88,69 +91,69 @@ class FatSystem /** * Showing deleted file in listing */ - void setListDeleted(bool listDeleted); + void setListDeleted(bool listDeleted); - /** + /** * Is the n-th cluster free? */ - bool freeCluster(unsigned int cluster); + bool freeCluster(unsigned int cluster); - /** + /** * Returns the cluster offset in the filesystem */ - unsigned long long clusterAddress(unsigned int cluster, bool isRoot = false); + unsigned long long clusterAddress(unsigned int cluster, bool isRoot = false); - /** + /** * Enable the FAT caching */ - void enableCache(); - - // File descriptor - string filename; - unsigned long long globalOffset; - int fd; - bool writeMode; - - // Header values - int type; - string diskLabel; - string oemName; - string fsType; - unsigned long long totalSectors; - unsigned long long bytesPerSector; - unsigned long long sectorsPerCluster; - unsigned long long reservedSectors; - unsigned long long fats; - unsigned long long sectorsPerFat; - unsigned long long rootDirectory; - unsigned long long reserved; - unsigned long long strange; - unsigned int bits; - - // Specific to FAT16 - unsigned long long rootEntries; - unsigned long long rootClusters; - - // Computed values - unsigned long long fatStart; - unsigned long long dataStart; - unsigned long long bytesPerCluster; - unsigned long long totalSize; - unsigned long long dataSize; - unsigned long long fatSize; - unsigned long long totalClusters; - - // FAT Cache - bool cacheEnabled; - map cache; - - // Stats values - bool statsComputed; - unsigned long long freeClusters; - - // Flags - bool listDeleted; - + void enableCache(); + + // File descriptor + string filename; + unsigned long long globalOffset; + int fd; + bool writeMode; + + // Header values + int type; + string diskLabel; + string oemName; + string fsType; + unsigned long long totalSectors; + unsigned long long bytesPerSector; + unsigned long long sectorsPerCluster; + unsigned long long reservedSectors; + unsigned long long fats; + unsigned long long sectorsPerFat; + unsigned long long rootDirectory; + unsigned long long reserved; + unsigned long long strange; + unsigned int bits; + + // Specific to FAT16 + unsigned long long rootEntries; + unsigned long long rootClusters; + + // Computed values + unsigned long long fatStart; + unsigned long long dataStart; + unsigned long long bytesPerCluster; + unsigned long long totalSize; + unsigned long long dataSize; + unsigned long long fatSize; + unsigned long long totalClusters; + + // FAT Cache + bool cacheEnabled; + map cache; + + // Stats values + bool statsComputed; + unsigned long long freeClusters; + + // Flags + bool listDeleted; + /** * Returns the next cluster number */ @@ -164,28 +167,28 @@ class FatSystem /** * Is this cluster valid? */ - bool validCluster(unsigned int cluster); + bool validCluster(unsigned int cluster); - /** + /** * Enable write mode on the FAT system, the internal file descriptor * will be re-opened in write mode */ - void enableWrite(); + void enableWrite(); - /** + /** * Read some data from the system */ - int readData(unsigned long long address, char *buffer, int size); + int readData(unsigned long long address, char *buffer, int size); - /** + /** * Write some data to the system, write should be enabled */ - int writeData(unsigned long long address, const char *buffer, int size); + int writeData(unsigned long long address, const char *buffer, int size); - /** + /** * Get directory entries for a given cluster */ - vector getEntries(unsigned int cluster, int *clusters = NULL, bool *hasFree = NULL); + vector getEntries(unsigned int cluster, int *clusters = NULL, bool *hasFree = NULL); /** * Write random data in unallocated sectors @@ -195,22 +198,22 @@ class FatSystem /** * Return a chain size */ - int chainSize(int cluster, bool *isContiguous = NULL); - - /** + int chainSize(int cluster, bool *isContiguous = NULL); + + /** * Root directory entry */ - FatEntry rootEntry(); - - protected: - void parseHeader(); + FatEntry rootEntry(); - /** +protected: + void parseHeader(); + + /** * Compute the free clusters stats */ - void computeStats(); + void computeStats(); - OutputFormatType _outputFormat; + OutputFormatType _outputFormat; }; #endif // _FATCAT_FATSYSTEM_H diff --git a/src/fatcat.cpp b/src/fatcat.cpp index 9d72bdb..dda85b6 100644 --- a/src/fatcat.cpp +++ b/src/fatcat.cpp @@ -3,8 +3,13 @@ #ifdef __APPLE__ #include #else +#ifdef __WIN__ +#include +#include "xgetopt/xgetopt.h" +#else #include #endif +#endif #include #include @@ -155,109 +160,109 @@ int main(int argc, char *argv[]) // Parsing command line while ((index = getopt(argc, argv, "il:L:r:R:s:dc:hx:2@:ob:p:w:v:mt:Sze:O:fk:a:F:")) != -1) { switch (index) { - case 'a': - attributesProvided = true; - attributes = atoi(optarg); - break; - case 'k': - findEntry = true; - cluster = atoi(optarg); - break; - case 'f': - fixReachable = true; - break; - case 'O': - globalOffset = atoll(optarg); - break; - case 'e': - entry = true; - entryPath = string(optarg); - break; - case 'z': - zero = true; - break; - case 'S': - scramble = true; - break; - case 't': - table = ATOU(optarg); - break; - case 'm': - merge = true; - break; - case 'v': - hasValue = true; - value = ATOU(optarg); - break; - case 'w': - writeNext = true; - cluster = ATOU(optarg); - break; - case '@': - address = true; - cluster = ATOU(optarg); - break; - case 'o': - chains = true; - break; - case 'i': - infoFlag = true; - break; - case 'l': - listFlag = true; - listPath = string(optarg); - break; - case 'L': - listClusterFlag = true; - listCluster = ATOU(optarg); - break; - case 'r': - readFlag = true; - readPath = string(optarg); - break; - case 'R': - clusterRead = true; - cluster = ATOU(optarg); - break; - case 's': - size = ATOU(optarg); - sizeProvided = true; - break; - case 'd': - listDeleted = true; - break; - case 'c': - cluster = ATOU(optarg); - clusterProvided = true; - break; - case 'x': - extract = true; - extractDirectory = string(optarg); - break; - case '2': - compare = true; - break; - case 'b': - backup = true; - backupFile = string(optarg); - break; - case 'p': - patch = true; - backupFile = string(optarg); - break; - case 'h': + case 'a': + attributesProvided = true; + attributes = atoi(optarg); + break; + case 'k': + findEntry = true; + cluster = atoi(optarg); + break; + case 'f': + fixReachable = true; + break; + case 'O': + globalOffset = atoll(optarg); + break; + case 'e': + entry = true; + entryPath = string(optarg); + break; + case 'z': + zero = true; + break; + case 'S': + scramble = true; + break; + case 't': + table = ATOU(optarg); + break; + case 'm': + merge = true; + break; + case 'v': + hasValue = true; + value = ATOU(optarg); + break; + case 'w': + writeNext = true; + cluster = ATOU(optarg); + break; + case '@': + address = true; + cluster = ATOU(optarg); + break; + case 'o': + chains = true; + break; + case 'i': + infoFlag = true; + break; + case 'l': + listFlag = true; + listPath = string(optarg); + break; + case 'L': + listClusterFlag = true; + listCluster = ATOU(optarg); + break; + case 'r': + readFlag = true; + readPath = string(optarg); + break; + case 'R': + clusterRead = true; + cluster = ATOU(optarg); + break; + case 's': + size = ATOU(optarg); + sizeProvided = true; + break; + case 'd': + listDeleted = true; + break; + case 'c': + cluster = ATOU(optarg); + clusterProvided = true; + break; + case 'x': + extract = true; + extractDirectory = string(optarg); + break; + case '2': + compare = true; + break; + case 'b': + backup = true; + backupFile = string(optarg); + break; + case 'p': + patch = true; + backupFile = string(optarg); + break; + case 'h': + usage(); + break; + case 'F': + if (strcmp(optarg, "json") == 0) + outputFormat = Json; + else if (strcmp(optarg, "default") == 0) + outputFormat = Default; + else + { usage(); - break; - case 'F': - if (strcmp(optarg, "json") == 0) - outputFormat = Json; - else if (strcmp(optarg, "default") == 0) - outputFormat = Default; - else - { - usage(); - } - break; + } + break; } } From a106f866fdbf3b14944689f1392af7d033fbf04f Mon Sep 17 00:00:00 2001 From: Inbar Barkai Date: Wed, 7 Aug 2019 16:19:44 +0300 Subject: [PATCH 19/33] Added script to build fatcat with windows --- build.bat | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 build.bat diff --git a/build.bat b/build.bat new file mode 100644 index 0000000..ccc5e31 --- /dev/null +++ b/build.bat @@ -0,0 +1,5 @@ +if not exist build md build +cd build +git clean -fdx && cmake .. && "c:\Program Files (x86)\Microsoft Visual Studio\2017\Community\MSBuild\15.0\Bin\MSBuild.exe" fatcat.sln /p:OutDir=bin +cd .. +pause \ No newline at end of file From 4bee728d222aab688cd6e1a09bd71496ddca6519 Mon Sep 17 00:00:00 2001 From: Inbar Barkai Date: Wed, 7 Aug 2019 16:28:30 +0300 Subject: [PATCH 20/33] Fixed compile error --- src/core/FatSystem.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core/FatSystem.cpp b/src/core/FatSystem.cpp index 5bba16b..991f441 100644 --- a/src/core/FatSystem.cpp +++ b/src/core/FatSystem.cpp @@ -641,8 +641,8 @@ void FatSystem::readFile(unsigned int cluster, unsigned int size, FILE *f, bool delete[] buffer; } #endif + } } - bool FatSystem::init() { // Parsing header From c30f4e80dd1eeeda41557cc730a02aade5ae6dd0 Mon Sep 17 00:00:00 2001 From: Inbar Barkai Date: Thu, 15 Aug 2019 14:42:40 +0300 Subject: [PATCH 21/33] Added shell build script --- build.sh | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 build.sh diff --git a/build.sh b/build.sh new file mode 100644 index 0000000..8b88f91 --- /dev/null +++ b/build.sh @@ -0,0 +1,7 @@ +#!/bin/sh +if [ ! -d build ]; then + mkdir build +fi +cd build +git clean -fdx && cmake .. && make +cd .. \ No newline at end of file From c8ec0509491026eb5540c39fcc3b74aa73694bab Mon Sep 17 00:00:00 2001 From: Inbar Barkai Date: Thu, 15 Aug 2019 14:45:48 +0300 Subject: [PATCH 22/33] Added conditional flag for compilation --- CMakeLists.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index c5e792d..5b5bba6 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -28,6 +28,8 @@ foreach(SOURCE ${SOURCES}) set(ALL_SOURCES ${ALL_SOURCES} src/${SOURCE}) endforeach() +#add_definitions(-D__WIN__) + include_directories("${CMAKE_SOURCE_DIR}/src") add_executable(fatcat "src/fatcat.cpp" ${ALL_SOURCES}) From f647c783fe25d0a0ed33ddd2e6545e92b494fdb4 Mon Sep 17 00:00:00 2001 From: Inbar Barkai Date: Thu, 15 Aug 2019 14:46:04 +0300 Subject: [PATCH 23/33] Added __WIN__ compilation flag --- src/xgetopt/argcargv.cpp | 3 ++- src/xgetopt/stdafx.cpp | 2 ++ src/xgetopt/xgetopt.cpp | 3 ++- 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/src/xgetopt/argcargv.cpp b/src/xgetopt/argcargv.cpp index 5fc5eee..d7c9ac8 100644 --- a/src/xgetopt/argcargv.cpp +++ b/src/xgetopt/argcargv.cpp @@ -7,7 +7,7 @@ // The original source for the LIBCTINY library may be // found here: www.wheaty.net - +#ifdef __WIN__ #include "stdafx.h" #include "argcargv.h" @@ -125,3 +125,4 @@ int _ConvertCommandLineToArgcArgv(LPCTSTR lpszSysCmdLine) return argc; } } +#endif \ No newline at end of file diff --git a/src/xgetopt/stdafx.cpp b/src/xgetopt/stdafx.cpp index 67e2705..73f52ec 100644 --- a/src/xgetopt/stdafx.cpp +++ b/src/xgetopt/stdafx.cpp @@ -1,8 +1,10 @@ // stdafx.cpp : source file that includes just the standard includes // XGetoptTest.pch will be the pre-compiled header // stdafx.obj will contain the pre-compiled type information +#ifdef __WIN__ #include "stdafx.h" +#endif \ No newline at end of file diff --git a/src/xgetopt/xgetopt.cpp b/src/xgetopt/xgetopt.cpp index 428619f..e926533 100644 --- a/src/xgetopt/xgetopt.cpp +++ b/src/xgetopt/xgetopt.cpp @@ -21,7 +21,7 @@ // damage or loss of business that this software may cause. // /////////////////////////////////////////////////////////////////////////////// - +#ifdef __WIN__ /////////////////////////////////////////////////////////////////////////////// // if you are using precompiled headers then include this line: #include "stdafx.h" @@ -213,3 +213,4 @@ int getopt(int argc, TCHAR *argv[], TCHAR *optstring) return c; } +#endif \ No newline at end of file From 7bd7d3126db6da43b290dff78ff27121a7cd6c92 Mon Sep 17 00:00:00 2001 From: Inbar Barkai Date: Sun, 18 Aug 2019 10:33:59 +0300 Subject: [PATCH 24/33] Added url to original project --- src/xgetopt/xgetopt.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/xgetopt/xgetopt.cpp b/src/xgetopt/xgetopt.cpp index e926533..c39416e 100644 --- a/src/xgetopt/xgetopt.cpp +++ b/src/xgetopt/xgetopt.cpp @@ -2,6 +2,7 @@ // // Author: Hans Dietrich // hdietrich2@hotmail.com +// url: https://www.codeproject.com/Articles/1940/XGetopt-A-Unix-compatible-getopt-for-MFC-and-Win32 // // Description: // XGetopt.cpp implements getopt(), a function to parse command lines. From f224190f0cff9a400c7c21cb690c2ecc6caefba4 Mon Sep 17 00:00:00 2001 From: Inbar Barkai Date: Sun, 18 Aug 2019 10:34:37 +0300 Subject: [PATCH 25/33] Adapted scripts to enable windows compilation --- CMakeLists.txt | 6 +++++- build.bat | 2 +- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 5b5bba6..d6a2649 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,6 +1,8 @@ cmake_minimum_required(VERSION 2.8) project(fatcat) +OPTION(DEFINE_WIN "Compiling windows" OFF) + set(SOURCES core/FatEntry.cpp core/FatFilename.cpp @@ -28,7 +30,9 @@ foreach(SOURCE ${SOURCES}) set(ALL_SOURCES ${ALL_SOURCES} src/${SOURCE}) endforeach() -#add_definitions(-D__WIN__) +IF(DEFINE_WIN) + add_definitions(-D__WIN__) +ENDIF(DEFINE_WIN) include_directories("${CMAKE_SOURCE_DIR}/src") diff --git a/build.bat b/build.bat index ccc5e31..385fef6 100644 --- a/build.bat +++ b/build.bat @@ -1,5 +1,5 @@ if not exist build md build cd build -git clean -fdx && cmake .. && "c:\Program Files (x86)\Microsoft Visual Studio\2017\Community\MSBuild\15.0\Bin\MSBuild.exe" fatcat.sln /p:OutDir=bin +git clean -fdx && cmake .. -DDEFINE_WIN=ON && "c:\Program Files (x86)\Microsoft Visual Studio\2017\Community\MSBuild\15.0\Bin\MSBuild.exe" fatcat.sln /p:OutDir=bin cd .. pause \ No newline at end of file From ddd0cc4ebc6484c0816a9ccb83e6569e9a2d6ad2 Mon Sep 17 00:00:00 2001 From: Gregwar Date: Wed, 28 Aug 2019 15:42:35 +0200 Subject: [PATCH 26/33] Adding note about options order (see #12) --- README.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/README.md b/README.md index f057a76..992ead8 100644 --- a/README.md +++ b/README.md @@ -35,6 +35,9 @@ Fatcat takes an image as argument: fatcat disk.img [options] ``` +**NOTE: according to your build, you might have to specify options before ``disk.img``, i.e +``fatcat [options] disk.img``** + You can specify an offset in the file with `-O`, this could be useful if there is multiple partitions on a block devices, for instance: From 9455425299d3f15e92970e97f1f83a91632dd489 Mon Sep 17 00:00:00 2001 From: Inbar Barkai Date: Tue, 10 Sep 2019 09:07:17 +0300 Subject: [PATCH 27/33] Writing error to stderr and exiting with error code --- src/fatcat.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/fatcat.cpp b/src/fatcat.cpp index 15da952..a0f732f 100644 --- a/src/fatcat.cpp +++ b/src/fatcat.cpp @@ -394,14 +394,17 @@ int main(int argc, char *argv[]) fat.writeData(entry.address, data.c_str(), entry.data.size()); } } else { - cout << "Entry not found." << endl; + cerr << "Entry not found." << endl; + exit(EXIT_FAILURE); } } } else { - cout << "! Failed to init the FAT filesystem" << endl; + cerr << "! Failed to init the FAT filesystem" << endl; + exit(EXIT_FAILURE); } } catch (string error) { cerr << "Error: " << error << endl; + exit(EXIT_FAILURE); } exit(EXIT_SUCCESS); From 97ba6eb69ea9c22cfcaec7dd7c9aba8842f34eb8 Mon Sep 17 00:00:00 2001 From: Gregwar Date: Mon, 23 Sep 2019 16:19:34 +0200 Subject: [PATCH 28/33] Minor indentation fix --- src/core/FatSystem.cpp | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/core/FatSystem.cpp b/src/core/FatSystem.cpp index 730e4e5..c7fae33 100644 --- a/src/core/FatSystem.cpp +++ b/src/core/FatSystem.cpp @@ -676,10 +676,10 @@ void FatSystem::infos() cout << "\"TotalSectors\":" << totalSectors << ","; cout << "\"TotalDataClusters\":" << totalClusters << ","; cout << "\"DataSize\":" << dataSize << ","; - cout << "\"PrettyDataSize\":\"" << prettySize(dataSize) << "\","; - cout << "\"DiskSize\":" << totalSize << ","; - cout << "\"PrettyDiskSize\":\"" << prettySize(totalSize) << "\","; - cout << "\"BytesPerSector\":" << bytesPerSector << ","; + cout << "\"PrettyDataSize\":\"" << prettySize(dataSize) << "\","; + cout << "\"DiskSize\":" << totalSize << ","; + cout << "\"PrettyDiskSize\":\"" << prettySize(totalSize) << "\","; + cout << "\"BytesPerSector\":" << bytesPerSector << ","; cout << "\"SectorsPerCluster\":" << sectorsPerCluster << ","; cout << "\"BytesPerCluster\":" << bytesPerCluster << ","; cout << "\"ReservedSectors\":" << reservedSectors << ","; @@ -711,11 +711,11 @@ void FatSystem::infos() cout << "Filesystem type: " << fsType << endl; cout << "OEM name: " << oemName << endl; - cout << "Total sectors: " << totalSectors << endl; - cout << "Total data clusters: " << totalClusters << endl; - cout << "Data size: " << dataSize << " (" << prettySize(dataSize) << ")" << endl; - cout << "Disk size: " << totalSize << " (" << prettySize(totalSize) << ")" << endl; - cout << "Bytes per sector: " << bytesPerSector << endl; + cout << "Total sectors: " << totalSectors << endl; + cout << "Total data clusters: " << totalClusters << endl; + cout << "Data size: " << dataSize << " (" << prettySize(dataSize) << ")" << endl; + cout << "Disk size: " << totalSize << " (" << prettySize(totalSize) << ")" << endl; + cout << "Bytes per sector: " << bytesPerSector << endl; cout << "Sectors per cluster: " << sectorsPerCluster << endl; cout << "Bytes per cluster: " << bytesPerCluster << endl; cout << "Reserved sectors: " << reservedSectors << endl; From ff13a460098be07601633efc6888609d372b90b8 Mon Sep 17 00:00:00 2001 From: Gregwar Date: Tue, 8 Oct 2019 13:34:03 +0200 Subject: [PATCH 29/33] Not dying if FATs!=2, but dying on compare & merge operation (see #13) --- src/core/FatSystem.cpp | 6 +++--- src/table/FatDiff.cpp | 11 +++++++++++ 2 files changed, 14 insertions(+), 3 deletions(-) diff --git a/src/core/FatSystem.cpp b/src/core/FatSystem.cpp index 43f7912..aaf3a69 100644 --- a/src/core/FatSystem.cpp +++ b/src/core/FatSystem.cpp @@ -175,9 +175,9 @@ void FatSystem::parseHeader() strange++; } - if (fats != 2) { - printf("WARNING: Fats number different of 2 (%llu)\n", fats); - strange++; + if (fats == 0) { + printf("WARNING: Fats numbner is 0\n"); + strange++; } if (rootDirectory != 2 && type == FAT32) { diff --git a/src/table/FatDiff.cpp b/src/table/FatDiff.cpp index f4f8c1f..b9c9427 100644 --- a/src/table/FatDiff.cpp +++ b/src/table/FatDiff.cpp @@ -16,6 +16,11 @@ bool FatDiff::compare() bool mergeable = true; cout << "Comparing the FATs" << endl; + if (system.fats != 2) { + cerr << "ERROR: Compare is only suitable for 2 fats (found " << system.fats << ")" << endl; + return; + } + for (int cluster=0; cluster Date: Tue, 8 Oct 2019 13:34:36 +0200 Subject: [PATCH 30/33] Fixing error introduced in previous commit --- src/table/FatDiff.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/table/FatDiff.cpp b/src/table/FatDiff.cpp index b9c9427..412c582 100644 --- a/src/table/FatDiff.cpp +++ b/src/table/FatDiff.cpp @@ -18,7 +18,7 @@ bool FatDiff::compare() if (system.fats != 2) { cerr << "ERROR: Compare is only suitable for 2 fats (found " << system.fats << ")" << endl; - return; + return false; } for (int cluster=0; cluster Date: Thu, 24 Oct 2019 17:49:04 +0200 Subject: [PATCH 31/33] v1.1.0 --- src/fatcat.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/fatcat.cpp b/src/fatcat.cpp index fa57b15..ce23ca0 100644 --- a/src/fatcat.cpp +++ b/src/fatcat.cpp @@ -31,7 +31,7 @@ using namespace std; void usage() { - cout << "fatcat v1.0.6, Gregwar " << endl; + cout << "fatcat v1.1.0, Gregwar " << endl; cout << endl; cout << "Usage: fatcat disk.img [options]" << endl; cout << " -i: display information about disk" << endl; From d2e2b6d0da50c6ba5db2cce0a8c8da02d53c3df8 Mon Sep 17 00:00:00 2001 From: "Nathan-J. Hirschauer" Date: Sat, 18 Apr 2020 01:08:59 +0200 Subject: [PATCH 32/33] Output 8DOT3 short filenames whenever possible MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In case of the default output format, the 8DOT3 short file name is printed, when directories are listed. For the JSON-formatter, a new value »8DOT3Name« is introduced, containing the short file name. --- src/core/FatEntry.cpp | 27 ++++++++++++++++----------- src/core/FatEntry.h | 1 + src/core/FatSystem.cpp | 9 ++++++++- 3 files changed, 25 insertions(+), 12 deletions(-) diff --git a/src/core/FatEntry.cpp b/src/core/FatEntry.cpp index e07a8fa..e7258e2 100644 --- a/src/core/FatEntry.cpp +++ b/src/core/FatEntry.cpp @@ -34,22 +34,27 @@ string FatEntry::getFilename() if (longName != "") { return longName; } else { - string name; - string ext = trim(shortName.substr(8,3)); - string base = trim(shortName.substr(0,8)); + return getShortFilename(); + } +} - if (isErased()) { - base = base.substr(1); - } +string FatEntry::getShortFilename() +{ + string name; + string ext = trim(shortName.substr(8,3)); + string base = trim(shortName.substr(0,8)); - name = base; + if (isErased()) { + base = base.substr(1); + } - if (ext != "") { - name += "." + ext; - } + name = base; - return name; + if (ext != "") { + name += "." + ext; } + + return name; } bool FatEntry::isDirectory() diff --git a/src/core/FatEntry.h b/src/core/FatEntry.h index 66f3b8d..cd69ee1 100644 --- a/src/core/FatEntry.h +++ b/src/core/FatEntry.h @@ -31,6 +31,7 @@ class FatEntry FatEntry(); string getFilename(); + string getShortFilename(); bool isDirectory(); bool isHidden(); bool isErased(); diff --git a/src/core/FatSystem.cpp b/src/core/FatSystem.cpp index 37be51c..79cda8c 100644 --- a/src/core/FatSystem.cpp +++ b/src/core/FatSystem.cpp @@ -510,9 +510,11 @@ void FatSystem::list(vector &entries) } string name = entry.getFilename(); + string shrtname = entry.getShortFilename(); cout << "\"EditDate\":\"" << entry.changeDate.isoFormat() << "\","; cout << "\"Name\":\"" << name << "\","; + cout << "\"8DOT3Name\":\"" << shrtname << "\","; cout << "\"Cluster\":" << entry.cluster << ","; if (!entry.isDirectory()) { @@ -557,8 +559,13 @@ void FatSystem::list(vector &entries) name += "/"; } + string shrtname = entry.getShortFilename(); + if (name.compare(shrtname)) { + name += " (" + shrtname + ")"; + } + printf(" %s ", entry.changeDate.pretty().c_str()); - printf(" %-30s", name.c_str()); + printf(" %-50s", name.c_str()); printf(" c=%u", entry.cluster); From 4828a9c450c52fc26779d5ed85692a3e2cd6ec2e Mon Sep 17 00:00:00 2001 From: sanjay-cpu Date: Wed, 7 Oct 2020 13:38:18 +0000 Subject: [PATCH 33/33] Travis-ci: added support for ppc64le --- .travis.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.travis.yml b/.travis.yml index ea5f5b9..3e9eb0f 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,4 +1,7 @@ language: cpp +arch: + - amd64 + - ppc64le compiler: - gcc