MCPcopy Create free account
hub / github.com/MarlinFirmware/Marlin / readDir

Method readDir

Marlin/src/sd/SdBaseFile.cpp:1431–1521  ·  view source on GitHub ↗

* Read the next entry in a directory. * * \param[out] dir The dir_t struct that will receive the data. * * \return For success return a non-zero value (number of bytes read). * A value of zero will be returned if end of dir is reached. * If an error occurs, readDir() returns -1. Possible errors: * - readDir() called on unopened dir * - not a directory fi

Source from the content-addressed store, hash-verified

1429 * - I/O error
1430 */
1431int8_t SdBaseFile::readDir(dir_t * const dir, char * const longFilename) {
1432 int16_t n;
1433 // if not a directory file or miss-positioned return an error
1434 if (!isDir() || (0x1F & curPosition_)) return -1;
1435
1436 #define INVALIDATE_LONGNAME() (longFilename[0] = longFilename[1] = '\0')
1437
1438 // If we have a longFilename buffer, mark it as invalid.
1439 // If a long filename is found it will be filled automatically.
1440 if (longFilename) INVALIDATE_LONGNAME();
1441
1442 uint8_t checksum_error = 0xFF, checksum = 0;
1443
1444 while (1) {
1445
1446 n = read(dir, sizeof(dir_t));
1447 if (n != sizeof(dir_t)) return n ? -1 : 0;
1448
1449 // Last entry if DIR_NAME_FREE
1450 if (dir->name[0] == DIR_NAME_FREE) return 0;
1451
1452 // Skip deleted entry and entry for . and ..
1453 if (dir->name[0] == DIR_NAME_DELETED || dir->name[0] == '.') {
1454 if (longFilename) INVALIDATE_LONGNAME(); // Invalidate erased file long name, if any
1455 continue;
1456 }
1457
1458 if (longFilename) {
1459 // Fill the long filename if we have a long filename entry.
1460 // Long filename entries are stored before the short filename.
1461 if (DIR_IS_LONG_NAME(dir)) {
1462 vfat_t *VFAT = (vfat_t*)dir;
1463 // Sanity-check the VFAT entry. The first cluster is always set to zero. And the sequence number should be higher than 0
1464 if (VFAT->firstClusterLow == 0) {
1465 const uint8_t seq = VFAT->sequenceNumber & 0x1F;
1466 if (WITHIN(seq, 1, VFAT_ENTRIES_LIMIT)) {
1467 if (seq == 1) {
1468 checksum = VFAT->checksum;
1469 checksum_error = 0;
1470 }
1471 else if (checksum != VFAT->checksum) // orphan detected
1472 checksum_error = 1;
1473
1474 #if ENABLED(LONG_FILENAME_WRITE_SUPPORT)
1475
1476 getLFNName(VFAT, longFilename, seq); // Get chunk of LFN from VFAT entry
1477
1478 #else // !LONG_FILENAME_WRITE_SUPPORT
1479
1480 n = (seq - 1) * (FILENAME_LENGTH);
1481
1482 for (uint8_t i = 0; i < FILENAME_LENGTH; ++i) {
1483 const uint16_t utf16_ch = (i >= 11) ? VFAT->name3[i - 11] : (i >= 5) ? VFAT->name2[i - 5] : VFAT->name1[i];
1484 #if ENABLED(UTF_FILENAME_SUPPORT)
1485 // We can't reconvert to UTF-8 here as UTF-8 is variable-size encoding, but joining LFN blocks
1486 // needs static bytes addressing. So here just store full UTF-16LE words to re-convert later.
1487 uint16_t idx = (n + i) * 2; // This is fixed as FAT LFN always contain UTF-16LE encoding
1488 longFilename[idx] = utf16_ch & 0xFF;

Callers 7

openParentMethod · 0.80
countVisibleItemsMethod · 0.80
selectByIndexMethod · 0.80
selectByNameMethod · 0.80
printListingMethod · 0.80
diveToNewestFileMethod · 0.80
UpdateAssetsFunction · 0.80

Calls 3

DIR_IS_LONG_NAMEFunction · 0.85
lfn_checksumFunction · 0.85
DIR_IS_FILE_OR_SUBDIRFunction · 0.85

Tested by

no test coverage detected