|
@@ -40,7 +40,7 @@
|
40
|
40
|
#include "SdBaseFile.h"
|
41
|
41
|
|
42
|
42
|
#include "../MarlinCore.h"
|
43
|
|
-SdBaseFile* SdBaseFile::cwd_ = 0; // Pointer to Current Working Directory
|
|
43
|
+SdBaseFile *SdBaseFile::cwd_ = 0; // Pointer to Current Working Directory
|
44
|
44
|
|
45
|
45
|
// callback function for date/time
|
46
|
46
|
void (*SdBaseFile::dateTime_)(uint16_t *date, uint16_t *time) = 0;
|
|
@@ -155,7 +155,7 @@ bool SdBaseFile::contiguousRange(uint32_t *bgnBlock, uint32_t *endBlock) {
|
155
|
155
|
* a file is already open, the file already exists, the root
|
156
|
156
|
* directory is full or an I/O error.
|
157
|
157
|
*/
|
158
|
|
-bool SdBaseFile::createContiguous(SdBaseFile* dirFile, const char *path, uint32_t size) {
|
|
158
|
+bool SdBaseFile::createContiguous(SdBaseFile *dirFile, const char *path, uint32_t size) {
|
159
|
159
|
if (ENABLED(SDCARD_READONLY)) return false;
|
160
|
160
|
|
161
|
161
|
uint32_t count;
|
|
@@ -187,12 +187,11 @@ bool SdBaseFile::createContiguous(SdBaseFile* dirFile, const char *path, uint32_
|
187
|
187
|
* \return true for success, false for failure.
|
188
|
188
|
*/
|
189
|
189
|
bool SdBaseFile::dirEntry(dir_t *dir) {
|
190
|
|
- dir_t *p;
|
191
|
190
|
// make sure fields on SD are correct
|
192
|
191
|
if (!sync()) return false;
|
193
|
192
|
|
194
|
193
|
// read entry
|
195
|
|
- p = cacheDirEntry(SdVolume::CACHE_FOR_READ);
|
|
194
|
+ dir_t *p = cacheDirEntry(SdVolume::CACHE_FOR_READ);
|
196
|
195
|
if (!p) return false;
|
197
|
196
|
|
198
|
197
|
// copy to caller's struct
|
|
@@ -207,7 +206,7 @@ bool SdBaseFile::dirEntry(dir_t *dir) {
|
207
|
206
|
* \param[in] dir The directory structure containing the name.
|
208
|
207
|
* \param[out] name A 13 byte char array for the formatted name.
|
209
|
208
|
*/
|
210
|
|
-void SdBaseFile::dirName(const dir_t& dir, char *name) {
|
|
209
|
+void SdBaseFile::dirName(const dir_t &dir, char *name) {
|
211
|
210
|
uint8_t j = 0;
|
212
|
211
|
LOOP_L_N(i, 11) {
|
213
|
212
|
if (dir.name[i] == ' ')continue;
|
|
@@ -386,7 +385,7 @@ int8_t SdBaseFile::lsPrintNext(uint8_t flags, uint8_t indent) {
|
386
|
385
|
}
|
387
|
386
|
|
388
|
387
|
// Format directory name field from a 8.3 name string
|
389
|
|
-bool SdBaseFile::make83Name(const char *str, uint8_t *name, const char** ptr) {
|
|
388
|
+bool SdBaseFile::make83Name(const char *str, uint8_t *name, const char **ptr) {
|
390
|
389
|
uint8_t n = 7, // Max index until a dot is found
|
391
|
390
|
i = 11;
|
392
|
391
|
while (i) name[--i] = ' '; // Set whole FILENAME.EXT to spaces
|
|
@@ -423,13 +422,13 @@ bool SdBaseFile::make83Name(const char *str, uint8_t *name, const char** ptr) {
|
423
|
422
|
* Reasons for failure include this file is already open, \a parent is not a
|
424
|
423
|
* directory, \a path is invalid or already exists in \a parent.
|
425
|
424
|
*/
|
426
|
|
-bool SdBaseFile::mkdir(SdBaseFile* parent, const char *path, bool pFlag) {
|
|
425
|
+bool SdBaseFile::mkdir(SdBaseFile *parent, const char *path, bool pFlag) {
|
427
|
426
|
if (ENABLED(SDCARD_READONLY)) return false;
|
428
|
427
|
|
429
|
428
|
uint8_t dname[11];
|
430
|
429
|
SdBaseFile dir1, dir2;
|
431
|
|
- SdBaseFile* sub = &dir1;
|
432
|
|
- SdBaseFile* start = parent;
|
|
430
|
+ SdBaseFile *sub = &dir1;
|
|
431
|
+ SdBaseFile *start = parent;
|
433
|
432
|
|
434
|
433
|
if (!parent || isOpen()) return false;
|
435
|
434
|
|
|
@@ -455,13 +454,9 @@ bool SdBaseFile::mkdir(SdBaseFile* parent, const char *path, bool pFlag) {
|
455
|
454
|
return mkdir(parent, dname);
|
456
|
455
|
}
|
457
|
456
|
|
458
|
|
-bool SdBaseFile::mkdir(SdBaseFile* parent, const uint8_t dname[11]) {
|
|
457
|
+bool SdBaseFile::mkdir(SdBaseFile *parent, const uint8_t dname[11]) {
|
459
|
458
|
if (ENABLED(SDCARD_READONLY)) return false;
|
460
|
459
|
|
461
|
|
- uint32_t block;
|
462
|
|
- dir_t d;
|
463
|
|
- dir_t *p;
|
464
|
|
-
|
465
|
460
|
if (!parent->isDir()) return false;
|
466
|
461
|
|
467
|
462
|
// create a normal file
|
|
@@ -478,19 +473,20 @@ bool SdBaseFile::mkdir(SdBaseFile* parent, const uint8_t dname[11]) {
|
478
|
473
|
if (!sync()) return false;
|
479
|
474
|
|
480
|
475
|
// cache entry - should already be in cache due to sync() call
|
481
|
|
- p = cacheDirEntry(SdVolume::CACHE_FOR_WRITE);
|
|
476
|
+ dir_t *p = cacheDirEntry(SdVolume::CACHE_FOR_WRITE);
|
482
|
477
|
if (!p) return false;
|
483
|
478
|
|
484
|
479
|
// change directory entry attribute
|
485
|
480
|
p->attributes = DIR_ATT_DIRECTORY;
|
486
|
481
|
|
487
|
482
|
// make entry for '.'
|
|
483
|
+ dir_t d;
|
488
|
484
|
memcpy(&d, p, sizeof(d));
|
489
|
485
|
d.name[0] = '.';
|
490
|
486
|
LOOP_S_L_N(i, 1, 11) d.name[i] = ' ';
|
491
|
487
|
|
492
|
488
|
// cache block for '.' and '..'
|
493
|
|
- block = vol_->clusterStartBlock(firstCluster_);
|
|
489
|
+ uint32_t block = vol_->clusterStartBlock(firstCluster_);
|
494
|
490
|
if (!vol_->cacheRawBlock(block, SdVolume::CACHE_FOR_WRITE)) return false;
|
495
|
491
|
|
496
|
492
|
// copy '.' to block
|
|
@@ -577,7 +573,7 @@ bool SdBaseFile::open(const char *path, uint8_t oflag) {
|
577
|
573
|
* a directory, \a path is invalid, the file does not exist
|
578
|
574
|
* or can't be opened in the access mode specified by oflag.
|
579
|
575
|
*/
|
580
|
|
-bool SdBaseFile::open(SdBaseFile* dirFile, const char *path, uint8_t oflag) {
|
|
576
|
+bool SdBaseFile::open(SdBaseFile *dirFile, const char *path, uint8_t oflag) {
|
581
|
577
|
uint8_t dname[11];
|
582
|
578
|
SdBaseFile dir1, dir2;
|
583
|
579
|
SdBaseFile *parent = dirFile, *sub = &dir1;
|
|
@@ -605,7 +601,7 @@ bool SdBaseFile::open(SdBaseFile* dirFile, const char *path, uint8_t oflag) {
|
605
|
601
|
}
|
606
|
602
|
|
607
|
603
|
// open with filename in dname
|
608
|
|
-bool SdBaseFile::open(SdBaseFile* dirFile, const uint8_t dname[11], uint8_t oflag) {
|
|
604
|
+bool SdBaseFile::open(SdBaseFile *dirFile, const uint8_t dname[11], uint8_t oflag) {
|
609
|
605
|
bool emptyFound = false, fileFound = false;
|
610
|
606
|
uint8_t index;
|
611
|
607
|
dir_t *p;
|
|
@@ -696,9 +692,7 @@ bool SdBaseFile::open(SdBaseFile* dirFile, const uint8_t dname[11], uint8_t ofla
|
696
|
692
|
* See open() by path for definition of flags.
|
697
|
693
|
* \return true for success or false for failure.
|
698
|
694
|
*/
|
699
|
|
-bool SdBaseFile::open(SdBaseFile* dirFile, uint16_t index, uint8_t oflag) {
|
700
|
|
- dir_t *p;
|
701
|
|
-
|
|
695
|
+bool SdBaseFile::open(SdBaseFile *dirFile, uint16_t index, uint8_t oflag) {
|
702
|
696
|
vol_ = dirFile->vol_;
|
703
|
697
|
|
704
|
698
|
// error if already open
|
|
@@ -711,7 +705,7 @@ bool SdBaseFile::open(SdBaseFile* dirFile, uint16_t index, uint8_t oflag) {
|
711
|
705
|
if (!dirFile->seekSet(32 * index)) return false;
|
712
|
706
|
|
713
|
707
|
// read entry into cache
|
714
|
|
- p = dirFile->readDirCache();
|
|
708
|
+ dir_t *p = dirFile->readDirCache();
|
715
|
709
|
if (!p) return false;
|
716
|
710
|
|
717
|
711
|
// error if empty slot or '.' or '..'
|
|
@@ -784,10 +778,7 @@ bool SdBaseFile::openCachedEntry(uint8_t dirIndex, uint8_t oflag) {
|
784
|
778
|
* See open() by path for definition of flags.
|
785
|
779
|
* \return true for success or false for failure.
|
786
|
780
|
*/
|
787
|
|
-bool SdBaseFile::openNext(SdBaseFile* dirFile, uint8_t oflag) {
|
788
|
|
- dir_t *p;
|
789
|
|
- uint8_t index;
|
790
|
|
-
|
|
781
|
+bool SdBaseFile::openNext(SdBaseFile *dirFile, uint8_t oflag) {
|
791
|
782
|
if (!dirFile) return false;
|
792
|
783
|
|
793
|
784
|
// error if already open
|
|
@@ -796,10 +787,10 @@ bool SdBaseFile::openNext(SdBaseFile* dirFile, uint8_t oflag) {
|
796
|
787
|
vol_ = dirFile->vol_;
|
797
|
788
|
|
798
|
789
|
while (1) {
|
799
|
|
- index = 0xF & (dirFile->curPosition_ >> 5);
|
|
790
|
+ uint8_t index = 0xF & (dirFile->curPosition_ >> 5);
|
800
|
791
|
|
801
|
792
|
// read entry into cache
|
802
|
|
- p = dirFile->readDirCache();
|
|
793
|
+ dir_t *p = dirFile->readDirCache();
|
803
|
794
|
if (!p) return false;
|
804
|
795
|
|
805
|
796
|
// done if last entry
|
|
@@ -825,9 +816,8 @@ bool SdBaseFile::openNext(SdBaseFile* dirFile, uint8_t oflag) {
|
825
|
816
|
*
|
826
|
817
|
* \return true for success, false for failure.
|
827
|
818
|
*/
|
828
|
|
-bool SdBaseFile::openParent(SdBaseFile* dir) {
|
|
819
|
+bool SdBaseFile::openParent(SdBaseFile *dir) {
|
829
|
820
|
dir_t entry;
|
830
|
|
- dir_t *p;
|
831
|
821
|
SdBaseFile file;
|
832
|
822
|
uint32_t c;
|
833
|
823
|
uint32_t cluster;
|
|
@@ -850,7 +840,7 @@ bool SdBaseFile::openParent(SdBaseFile* dir) {
|
850
|
840
|
// first block of parent dir
|
851
|
841
|
if (!vol_->cacheRawBlock(lbn, SdVolume::CACHE_FOR_READ)) return false;
|
852
|
842
|
|
853
|
|
- p = &vol_->cacheBuffer_.dir[1];
|
|
843
|
+ dir_t *p = &vol_->cacheBuffer_.dir[1];
|
854
|
844
|
// verify name for '../..'
|
855
|
845
|
if (p->name[0] != '.' || p->name[1] != '.') return false;
|
856
|
846
|
// '..' is pointer to first cluster of parent. open '../..' to find parent
|
|
@@ -881,7 +871,7 @@ bool SdBaseFile::openParent(SdBaseFile* dir) {
|
881
|
871
|
* Reasons for failure include the file is already open, the FAT volume has
|
882
|
872
|
* not been initialized or it a FAT12 volume.
|
883
|
873
|
*/
|
884
|
|
-bool SdBaseFile::openRoot(SdVolume* vol) {
|
|
874
|
+bool SdBaseFile::openRoot(SdVolume *vol) {
|
885
|
875
|
// error if file is already open
|
886
|
876
|
if (isOpen()) return false;
|
887
|
877
|
|
|
@@ -1008,7 +998,7 @@ int16_t SdBaseFile::read() {
|
1008
|
998
|
* read() called before a file has been opened, corrupt file system
|
1009
|
999
|
* or an I/O error occurred.
|
1010
|
1000
|
*/
|
1011
|
|
-int16_t SdBaseFile::read(void* buf, uint16_t nbyte) {
|
|
1001
|
+int16_t SdBaseFile::read(void *buf, uint16_t nbyte) {
|
1012
|
1002
|
uint8_t *dst = reinterpret_cast<uint8_t*>(buf);
|
1013
|
1003
|
uint16_t offset, toRead;
|
1014
|
1004
|
uint32_t block; // raw device block number
|
|
@@ -1136,7 +1126,7 @@ int8_t SdBaseFile::readDir(dir_t *dir, char *longFilename) {
|
1136
|
1126
|
// Reset n to the start of the long name
|
1137
|
1127
|
n = 0;
|
1138
|
1128
|
for (uint16_t idx = 0; idx < (LONG_FILENAME_LENGTH) / 2; idx += 2) { // idx is fixed since FAT LFN always contains UTF-16LE encoding
|
1139
|
|
- uint16_t utf16_ch = longFilename[idx] | (longFilename[idx + 1] << 8);
|
|
1129
|
+ const uint16_t utf16_ch = longFilename[idx] | (longFilename[idx + 1] << 8);
|
1140
|
1130
|
if (0xD800 == (utf16_ch & 0xF800)) // Surrogate pair - encode as '_'
|
1141
|
1131
|
longFilename[n++] = '_';
|
1142
|
1132
|
else if (0 == (utf16_ch & 0xFF80)) // Encode as 1-byte UTF-8 char
|
|
@@ -1199,12 +1189,11 @@ dir_t* SdBaseFile::readDirCache() {
|
1199
|
1189
|
bool SdBaseFile::remove() {
|
1200
|
1190
|
if (ENABLED(SDCARD_READONLY)) return false;
|
1201
|
1191
|
|
1202
|
|
- dir_t *d;
|
1203
|
1192
|
// free any clusters - will fail if read-only or directory
|
1204
|
1193
|
if (!truncate(0)) return false;
|
1205
|
1194
|
|
1206
|
1195
|
// cache directory entry
|
1207
|
|
- d = cacheDirEntry(SdVolume::CACHE_FOR_WRITE);
|
|
1196
|
+ dir_t *d = cacheDirEntry(SdVolume::CACHE_FOR_WRITE);
|
1208
|
1197
|
if (!d) return false;
|
1209
|
1198
|
|
1210
|
1199
|
// mark entry deleted
|
|
@@ -1235,7 +1224,7 @@ bool SdBaseFile::remove() {
|
1235
|
1224
|
* \a dirFile is not a directory, \a path is not found
|
1236
|
1225
|
* or an I/O error occurred.
|
1237
|
1226
|
*/
|
1238
|
|
-bool SdBaseFile::remove(SdBaseFile* dirFile, const char *path) {
|
|
1227
|
+bool SdBaseFile::remove(SdBaseFile *dirFile, const char *path) {
|
1239
|
1228
|
if (ENABLED(SDCARD_READONLY)) return false;
|
1240
|
1229
|
|
1241
|
1230
|
SdBaseFile file;
|
|
@@ -1252,13 +1241,10 @@ bool SdBaseFile::remove(SdBaseFile* dirFile, const char *path) {
|
1252
|
1241
|
* Reasons for failure include \a dirFile is not open or is not a directory
|
1253
|
1242
|
* file, newPath is invalid or already exists, or an I/O error occurs.
|
1254
|
1243
|
*/
|
1255
|
|
-bool SdBaseFile::rename(SdBaseFile* dirFile, const char *newPath) {
|
|
1244
|
+bool SdBaseFile::rename(SdBaseFile *dirFile, const char *newPath) {
|
1256
|
1245
|
if (ENABLED(SDCARD_READONLY)) return false;
|
1257
|
1246
|
|
1258
|
|
- dir_t entry;
|
1259
|
1247
|
uint32_t dirCluster = 0;
|
1260
|
|
- SdBaseFile file;
|
1261
|
|
- dir_t *d;
|
1262
|
1248
|
|
1263
|
1249
|
// must be an open file or subdirectory
|
1264
|
1250
|
if (!(isFile() || isSubDir())) return false;
|
|
@@ -1268,16 +1254,18 @@ bool SdBaseFile::rename(SdBaseFile* dirFile, const char *newPath) {
|
1268
|
1254
|
|
1269
|
1255
|
// sync() and cache directory entry
|
1270
|
1256
|
sync();
|
1271
|
|
- d = cacheDirEntry(SdVolume::CACHE_FOR_WRITE);
|
|
1257
|
+ dir_t *d = cacheDirEntry(SdVolume::CACHE_FOR_WRITE);
|
1272
|
1258
|
if (!d) return false;
|
1273
|
1259
|
|
1274
|
1260
|
// save directory entry
|
|
1261
|
+ dir_t entry;
|
1275
|
1262
|
memcpy(&entry, d, sizeof(entry));
|
1276
|
1263
|
|
1277
|
1264
|
// mark entry deleted
|
1278
|
1265
|
d->name[0] = DIR_NAME_DELETED;
|
1279
|
1266
|
|
1280
|
1267
|
// make directory entry for new path
|
|
1268
|
+ SdBaseFile file;
|
1281
|
1269
|
if (isFile()) {
|
1282
|
1270
|
if (!file.open(dirFile, newPath, O_CREAT | O_EXCL | O_WRITE)) {
|
1283
|
1271
|
goto restore;
|
|
@@ -1536,8 +1524,7 @@ bool SdBaseFile::sync() {
|
1536
|
1524
|
*
|
1537
|
1525
|
* \return true for success, false for failure.
|
1538
|
1526
|
*/
|
1539
|
|
-bool SdBaseFile::timestamp(SdBaseFile* file) {
|
1540
|
|
- dir_t *d;
|
|
1527
|
+bool SdBaseFile::timestamp(SdBaseFile *file) {
|
1541
|
1528
|
dir_t dir;
|
1542
|
1529
|
|
1543
|
1530
|
// get timestamps
|
|
@@ -1546,7 +1533,7 @@ bool SdBaseFile::timestamp(SdBaseFile* file) {
|
1546
|
1533
|
// update directory fields
|
1547
|
1534
|
if (!sync()) return false;
|
1548
|
1535
|
|
1549
|
|
- d = cacheDirEntry(SdVolume::CACHE_FOR_WRITE);
|
|
1536
|
+ dir_t *d = cacheDirEntry(SdVolume::CACHE_FOR_WRITE);
|
1550
|
1537
|
if (!d) return false;
|
1551
|
1538
|
|
1552
|
1539
|
// copy timestamps
|
|
@@ -1599,7 +1586,6 @@ bool SdBaseFile::timestamp(uint8_t flags, uint16_t year, uint8_t month,
|
1599
|
1586
|
if (ENABLED(SDCARD_READONLY)) return false;
|
1600
|
1587
|
|
1601
|
1588
|
uint16_t dirDate, dirTime;
|
1602
|
|
- dir_t *d;
|
1603
|
1589
|
|
1604
|
1590
|
if (!isOpen()
|
1605
|
1591
|
|| year < 1980
|
|
@@ -1616,7 +1602,7 @@ bool SdBaseFile::timestamp(uint8_t flags, uint16_t year, uint8_t month,
|
1616
|
1602
|
// update directory entry
|
1617
|
1603
|
if (!sync()) return false;
|
1618
|
1604
|
|
1619
|
|
- d = cacheDirEntry(SdVolume::CACHE_FOR_WRITE);
|
|
1605
|
+ dir_t *d = cacheDirEntry(SdVolume::CACHE_FOR_WRITE);
|
1620
|
1606
|
if (!d) return false;
|
1621
|
1607
|
|
1622
|
1608
|
dirDate = FAT_DATE(year, month, day);
|
|
@@ -1710,7 +1696,7 @@ bool SdBaseFile::truncate(uint32_t length) {
|
1710
|
1696
|
* include write() is called before a file has been opened, write is called
|
1711
|
1697
|
* for a read-only file, device is full, a corrupt file system or an I/O error.
|
1712
|
1698
|
*/
|
1713
|
|
-int16_t SdBaseFile::write(const void* buf, uint16_t nbyte) {
|
|
1699
|
+int16_t SdBaseFile::write(const void *buf, uint16_t nbyte) {
|
1714
|
1700
|
#if ENABLED(SDCARD_READONLY)
|
1715
|
1701
|
writeError = true; return -1;
|
1716
|
1702
|
#endif
|