Skip to content

Commit ea911f7

Browse files
authored
Merge pull request #2 from rabbitholecomputing/fix/2.2.3-gpt-exfat
Fix exFat code reporting incorrect file size for preallocated files
2 parents 22a482b + 048ecd3 commit ea911f7

File tree

10 files changed

+78
-29
lines changed

10 files changed

+78
-29
lines changed

examples/debug/CardBusyTest/CardBusyTest.ino

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,8 @@ void loop() {
9898
maxWrite = m;
9999
}
100100
}
101+
// Remove any extra space in the file.
102+
file.truncate();
101103
file.close();
102104
ms = millis() - ms;
103105
Serial.println(F("\nTimes in micros"));

src/ExFatLib/ExFatDbg.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -399,14 +399,14 @@ void ExFatPartition::dmpFat(print_t* pr, uint32_t start, uint32_t count) {
399399
}
400400
}
401401
//------------------------------------------------------------------------------
402-
void ExFatPartition::dmpSector(print_t* pr, uint32_t sector) {
403-
uint8_t* cache = dataCachePrepare(sector, FsCache::CACHE_FOR_READ);
402+
void ExFatPartition::dmpSector(print_t* pr, uint32_t sector, uint8_t w) {
403+
const uint8_t* cache = dataCachePrepare(sector, FsCache::CACHE_FOR_READ);
404404
if (!cache) {
405405
pr->println(F("dmpSector failed"));
406406
return;
407407
}
408408
for (uint16_t i = 0; i < m_bytesPerSector; i++) {
409-
if (i % 32 == 0) {
409+
if (i % w == 0) {
410410
if (i) {
411411
pr->println();
412412
}

src/ExFatLib/ExFatFile.cpp

Lines changed: 22 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@ bool ExFatFile::contiguousRange(uint32_t* bgnSector, uint32_t* endSector) {
8888
}
8989
if (endSector) {
9090
*endSector =
91-
firstSector() + ((m_validLength - 1) >> m_vol->bytesPerSectorShift());
91+
firstSector() + ((m_dataLength - 1) >> m_vol->bytesPerSectorShift());
9292
}
9393
return true;
9494
}
@@ -98,7 +98,7 @@ void ExFatFile::fgetpos(fspos_t* pos) const {
9898
pos->cluster = m_curCluster;
9999
}
100100
//------------------------------------------------------------------------------
101-
int ExFatFile::fgets(char* str, int num, char* delim) {
101+
int ExFatFile::fgets(char* str, int num, const char* delim) {
102102
char ch;
103103
int n = 0;
104104
int r = -1;
@@ -578,7 +578,10 @@ int ExFatFile::peek() {
578578
int ExFatFile::read(void* buf, size_t count) {
579579
uint8_t* dst = reinterpret_cast<uint8_t*>(buf);
580580
int8_t fg;
581-
size_t toRead = count;
581+
uint64_t maxRead;
582+
size_t toRead;
583+
size_t toFill;
584+
size_t rtn = 0;
582585
size_t n;
583586
uint8_t* cache;
584587
uint16_t sectorOffset;
@@ -590,9 +593,15 @@ int ExFatFile::read(void* buf, size_t count) {
590593
goto fail;
591594
}
592595
if (isContiguous() || isFile()) {
593-
if ((m_curPosition + count) > m_validLength) {
594-
count = toRead = m_validLength - m_curPosition;
596+
if (count > (m_dataLength - m_curPosition)) {
597+
count = m_dataLength - m_curPosition;
595598
}
599+
maxRead = m_curPosition < m_validLength ? m_validLength - m_curPosition : 0;
600+
toRead = count < maxRead ? count : maxRead;
601+
toFill = count > toRead ? count - toRead : 0;
602+
} else {
603+
toRead = count;
604+
toFill = 0;
596605
}
597606
while (toRead) {
598607
clusterOffset = m_curPosition & m_vol->clusterMask();
@@ -659,10 +668,16 @@ int ExFatFile::read(void* buf, size_t count) {
659668
}
660669
}
661670
dst += n;
671+
rtn += n;
662672
m_curPosition += n;
663673
toRead -= n;
664674
}
665-
return count - toRead;
675+
if (toFill) {
676+
memset(dst, 0, toFill);
677+
seekCur(toFill);
678+
rtn += toFill;
679+
}
680+
return rtn;
666681

667682
fail:
668683
m_error |= READ_ERROR;
@@ -700,7 +715,7 @@ bool ExFatFile::seekSet(uint64_t pos) {
700715
goto done;
701716
}
702717
if (isFile()) {
703-
if (pos > m_validLength) {
718+
if (pos > m_dataLength) {
704719
DBG_FAIL_MACRO;
705720
goto fail;
706721
}

src/ExFatLib/ExFatFile.h

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -207,6 +207,8 @@ class ExFatFile {
207207
uint64_t dataLength() const { return m_dataLength; }
208208
/** \return Directory entry index. */
209209
uint32_t dirIndex() const { return m_dirPos.position / FS_DIR_SIZE; }
210+
/** \return The first cluster number for a file or directory. */
211+
uint32_t firstCluster() const { return m_firstCluster; }
210212
/** Test for the existence of a file in a directory
211213
*
212214
* \param[in] path Path of the file to be tested for.
@@ -247,9 +249,9 @@ class ExFatFile {
247249
* If no data is read, fgets() returns zero for EOF or -1 if an error
248250
* occurred.
249251
*/
250-
int fgets(char* str, int num, char* delim = nullptr);
252+
int fgets(char* str, int num, const char* delim = nullptr);
251253
/** \return The total number of bytes in a file. */
252-
uint64_t fileSize() const { return m_validLength; }
254+
uint64_t fileSize() const { return m_dataLength; }
253255
/** \return Address of first sector or zero for empty file. */
254256
uint32_t firstSector() const;
255257
/** Set position for streams
@@ -713,7 +715,7 @@ class ExFatFile {
713715
* \return true for success or false for failure.
714716
*/
715717
bool seekEnd(int64_t offset = 0) {
716-
return isFile() ? seekSet(m_validLength + offset) : false;
718+
return isFile() ? seekSet(m_dataLength + offset) : false;
717719
}
718720
/** Sets a file's position.
719721
*

src/ExFatLib/ExFatFilePrint.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,7 @@ size_t ExFatFile::printCreateDateTime(print_t* pr) {
117117
}
118118
//------------------------------------------------------------------------------
119119
size_t ExFatFile::printFileSize(print_t* pr) {
120-
uint64_t n = m_validLength;
120+
uint64_t n = fileSize();
121121
char buf[21];
122122
char* str = &buf[sizeof(buf) - 1];
123123
char* bgn = str - 12;

src/ExFatLib/ExFatFileWrite.cpp

Lines changed: 30 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -588,8 +588,8 @@ bool ExFatFile::truncate() {
588588
}
589589
}
590590
}
591+
m_validLength = m_curPosition > m_validLength ? m_validLength : m_curPosition;
591592
m_dataLength = m_curPosition;
592-
m_validLength = m_curPosition;
593593
m_flags |= FILE_FLAG_DIR_DIRTY;
594594
return sync();
595595

@@ -605,18 +605,25 @@ size_t ExFatFile::write(const void* buf, size_t nbyte) {
605605
uint16_t sectorOffset;
606606
uint32_t sector;
607607
uint32_t clusterOffset;
608-
609-
// number of bytes left to write - must be before goto statements
608+
uint64_t toFill = 0;
610609
size_t toWrite = nbyte;
611610
size_t n;
611+
612612
// error if not an open file or is read-only
613613
if (!isWritable()) {
614614
DBG_FAIL_MACRO;
615615
goto fail;
616616
}
617617
// seek to end of file if append flag
618618
if ((m_flags & FILE_FLAG_APPEND)) {
619-
if (!seekSet(m_validLength)) {
619+
if (!seekSet(m_dataLength)) {
620+
DBG_FAIL_MACRO;
621+
goto fail;
622+
}
623+
}
624+
if (m_curPosition > m_validLength) {
625+
toFill = m_curPosition - m_validLength;
626+
if (!seekSet(m_validLength)) {
620627
DBG_FAIL_MACRO;
621628
goto fail;
622629
}
@@ -669,14 +676,10 @@ size_t ExFatFile::write(const void* buf, size_t nbyte) {
669676
sector = m_vol->clusterStartSector(m_curCluster) +
670677
(clusterOffset >> m_vol->bytesPerSectorShift());
671678

672-
if (sectorOffset != 0 || toWrite < m_vol->bytesPerSector()) {
679+
if (sectorOffset != 0 || toWrite < m_vol->bytesPerSector() || toFill) {
673680
// partial sector - must use cache
674681
// max space in sector
675682
n = m_vol->bytesPerSector() - sectorOffset;
676-
// lesser of space and amount to write
677-
if (n > toWrite) {
678-
n = toWrite;
679-
}
680683

681684
if (sectorOffset == 0 && m_curPosition >= m_validLength) {
682685
// start of new sector don't need to read into cache
@@ -691,7 +694,18 @@ size_t ExFatFile::write(const void* buf, size_t nbyte) {
691694
goto fail;
692695
}
693696
uint8_t* dst = cache + sectorOffset;
694-
memcpy(dst, src, n);
697+
698+
if (toFill) {
699+
if (n > toFill) {
700+
n = toFill;
701+
}
702+
memset(dst, 0, n);
703+
} else {
704+
if (n > toWrite) {
705+
n = toWrite;
706+
}
707+
memcpy(dst, src, n);
708+
}
695709
if (m_vol->bytesPerSector() == (n + sectorOffset)) {
696710
// Force write if sector is full - improves large writes.
697711
if (!m_vol->dataCacheSync()) {
@@ -723,8 +737,12 @@ size_t ExFatFile::write(const void* buf, size_t nbyte) {
723737
}
724738
}
725739
m_curPosition += n;
726-
src += n;
727-
toWrite -= n;
740+
if (toFill) {
741+
toFill -= n;
742+
} else {
743+
src += n;
744+
toWrite -= n;
745+
}
728746
if (m_curPosition > m_validLength) {
729747
m_flags |= FILE_FLAG_DIR_DIRTY;
730748
m_validLength = m_curPosition;

src/ExFatLib/ExFatPartition.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -131,7 +131,7 @@ class ExFatPartition {
131131
void dmpCluster(print_t* pr, uint32_t cluster, uint32_t offset,
132132
uint32_t count);
133133
void dmpFat(print_t* pr, uint32_t start, uint32_t count);
134-
void dmpSector(print_t* pr, uint32_t sector);
134+
void dmpSector(print_t* pr, uint32_t sector, uint8_t w = 16);
135135
bool printVolInfo(print_t* pr);
136136
void printFat(print_t* pr);
137137
void printUpcase(print_t* pr);

src/FatLib/FatFile.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -237,7 +237,7 @@ uint32_t FatFile::dirSize() {
237237
return 512UL * n;
238238
}
239239
//------------------------------------------------------------------------------
240-
int FatFile::fgets(char* str, int num, char* delim) {
240+
int FatFile::fgets(char* str, int num, const char* delim) {
241241
char ch;
242242
int n = 0;
243243
int r = -1;

src/FatLib/FatFile.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -330,7 +330,9 @@ class FatFile {
330330
* If no data is read, fgets() returns zero for EOF or -1 if an error
331331
* occurred.
332332
*/
333-
int fgets(char* str, int num, char* delim = nullptr);
333+
int fgets(char* str, int num, const char* delim = nullptr);
334+
/** \return The first cluster number for a file or directory. */
335+
uint32_t firstCluster() const { return m_firstCluster; }
334336
/** \return The total number of bytes in a file. */
335337
uint32_t fileSize() const { return m_fileSize; }
336338
/** \return first sector of file or zero for empty file. */

src/FsLib/FsFile.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -246,6 +246,12 @@ class FsBaseFile {
246246
uint64_t fileSize() const {
247247
return m_fFile ? m_fFile->fileSize() : m_xFile ? m_xFile->fileSize() : 0;
248248
}
249+
/** \return The first cluster number for a file or directory. */
250+
uint32_t firstCluster() const {
251+
return m_fFile ? m_fFile->firstCluster()
252+
: m_xFile ? m_xFile->firstCluster()
253+
: 0;
254+
}
249255
/** \return Address of first sector or zero for empty file. */
250256
uint32_t firstSector() const {
251257
return m_fFile ? m_fFile->firstSector()
@@ -876,6 +882,10 @@ class FsBaseFile {
876882
: m_xFile ? m_xFile->truncate(length)
877883
: false;
878884
}
885+
/** \return The valid number of bytes in a file. */
886+
uint64_t validLength() const {
887+
return m_fFile ? m_fFile->fileSize() : m_xFile ? m_xFile->validLength() : 0;
888+
}
879889
/** Write a string to a file. Used by the Arduino Print class.
880890
* \param[in] str Pointer to the string.
881891
* Use getWriteError to check for errors.

0 commit comments

Comments
 (0)