30 while (i < 11) name[i++] =
' ';
32 while ((c = *str++) !=
'\0') {
34 if (n == 10)
return (
false);
39 PGM_P p = (PGM_P)
PSTR(
"|<>^+=?/[];,*\"\\");
41 while ((b = pgm_read_byte(p++)))
if (b == c)
return (
false);
42 if (i > n || c < 0X21 || c > 0X7E)
return (
false);
43 name[i++] = c < 'a' || c >
'z' ? c : c + (
'A' -
'a');
46 return (name[0] !=
' ');
71 if (
UNLIKELY(part > 4))
return (
false);
73 uint32_t volumeStartBlock = 0;
102 || (totalBlocks > 0X800000)
126 if (!d)
return (
false);
137 m_flags &= ~F_FILE_DIR_DIRTY;
152 if (!
make83Name(fileName, dname))
return (
false);
158 if (empty < 0) empty = index;
162 else if (!memcmp(dname, p->
name, 11)) {
166 return (open(index, oflag));
171 if (empty < 0)
return (
false);
178 memset(p, 0,
sizeof(
dir_t));
179 memcpy(p->
name, dname, 11);
196 return (open(empty, oflag));
206 if (!d)
return (
false);
219 m_dirEntryIndex = index;
223 if (oflag & O_TRUNC)
return (truncate(0));
231 if (!(m_flags &
O_WRITE))
return (
false);
232 if (m_firstCluster && !freeChain(m_firstCluster))
return (
false);
234 if (!d)
return (
false);
244 return (
read(&res,
sizeof(res)) ==
sizeof(res) ? res : -1);
251 uint8_t* dst =
reinterpret_cast<uint8_t*
>(buf);
257 if ((m_curPosition + nbyte) > m_fileSize) nbyte = m_fileSize - m_curPosition;
260 uint16_t nToRead = nbyte;
261 while (nToRead > 0) {
264 if (blkOfCluster == 0 && blockOffset == 0) {
266 if (m_curCluster == 0) {
267 m_curCluster = m_firstCluster;
272 if (m_curCluster < 2 || isEOC(m_curCluster))
return (
IOStream::EOF);
283 uint16_t n = 512 - blockOffset;
286 if (n > nToRead) n = nToRead;
301 uint16_t nToWrite = nbyte;
302 const uint8_t* src =
reinterpret_cast<const uint8_t*
>(buf);
308 if ((m_flags &
O_APPEND) && m_curPosition != m_fileSize) {
312 while (nToWrite > 0) {
315 if (blkOfCluster == 0 && blockOffset == 0) {
317 if (m_curCluster == 0) {
318 if (m_firstCluster == 0) {
322 m_curCluster = m_firstCluster;
335 uint32_t lba =
dataBlockLba(m_curCluster, blkOfCluster);
336 if (blockOffset == 0 && m_curPosition >= m_fileSize) {
348 uint16_t n = 512 - blockOffset;
351 if (n > nToWrite) n = nToWrite;
360 if (m_curPosition > m_fileSize) {
362 m_fileSize = m_curPosition;
379 return (write(&c,
sizeof(c)));
385 if (whence ==
SEEK_CUR) pos += m_curPosition;
386 else if (whence ==
SEEK_END) pos = m_fileSize;
387 else if (whence !=
SEEK_SET)
return (
false);
390 if (!is_open() || pos > m_fileSize)
return (
false);
398 if (pos < m_curPosition || m_curPosition == 0) {
400 m_curCluster = m_firstCluster;
406 if (!
fatGet(m_curCluster, &m_curCluster))
return (
false);
416 if (!(m_flags &
O_WRITE))
return (
false);
418 if (length > m_fileSize)
return (
false);
421 if (m_fileSize == 0)
return (
true);
422 uint32_t newPos = m_curPosition > length ? length : m_curPosition;
425 if (!freeChain(m_firstCluster))
return (
false);
426 m_curCluster = m_firstCluster = 0;
430 if (!seek(length))
return (
false);
431 if (!
fatGet(m_curCluster, &toFree))
return (
false);
432 if (!isEOC(toFree)) {
435 if (!freeChain(toFree))
return (
false);
440 if (!sync())
return (
false);
447 if (!sync())
return (
false);
449 if (!p)
return (
false);
450 memcpy(dir, p,
sizeof(
dir_t));
458 for (uint16_t i = *index; ; i++) {
478 memcpy(dir, p,
sizeof(
dir_t));
486 for (uint8_t i = 0; i < 11; i++) {
487 if (dir.
name[i] ==
' ')
continue;
492 outs << (char) dir.
name[i];
517 outs << date <<
' ' << time;
532 fat_t freeCluster = m_curCluster ? m_curCluster : 1;
534 for (
fat_t i = 0; ; i++) {
541 if (!
fatGet(freeCluster, &value))
return (
false);
542 if (value == 0)
break;
548 if (m_curCluster != 0) {
550 if (!
fatPut(m_curCluster, freeCluster))
return (
false);
554 m_firstCluster = freeCluster;
556 m_curCluster = freeCluster;
613 if (cluster < 2)
return (
false);
630 if (!
fatGet(cluster, &next))
return (
false);
631 if (!
fatPut(cluster, 0))
return (
false);
632 if (isEOC(next))
return (
true);
640 outs << date.
YEAR() <<
'-';
641 uint8_t month = date.
MONTH();
642 if (month < 9) outs <<
'0';
643 outs << month <<
'-';
644 uint8_t day = date.
DAY();
645 if (day < 9) outs <<
'0';
653 uint8_t hours = time.
HOURS();
654 if (hours < 9) outs <<
'0';
655 outs << hours <<
':';
656 uint8_t minutes = time.
MINUTES();
657 if (minutes < 9) outs <<
'0';
658 outs << minutes <<
':';
659 uint8_t seconds = time.
SECONDS();
660 if (seconds < 9) outs <<
'0';
static uint16_t const EOC16
static void(* dateTime)(uint16_t *date, uint16_t *time)
virtual int putchar(char c)
static uint8_t cacheDirty
virtual int read(void *buf, size_t size)
static bool volumeInitialized
static uint8_t const BOOTSIG1
static uint8_t const DIR_ATT_DIRECTORY
static uint8_t const CACHE_FOR_WRITE
uint16_t rootDirEntryCount
static uint8_t const DIR_NAME_FREE
bool dirEntry(dir_t *dir)
bool open(const char *fileName, uint8_t oflag)
static uint8_t blockOfCluster(uint32_t position)
bool write(uint32_t block, const uint8_t *src)
static uint32_t rootDirStartBlock
static const uint16_t DEFAULT_TIME
static const uint16_t DEFAULT_DATE
static uint8_t const DIR_ATT_VOLUME_ID
static uint8_t const DIR_ATT_READ_ONLY
static fat_t clusterCount
bool freeChain(fat_t cluster)
static uint32_t dataBlockLba(fat_t cluster, uint8_t blockOfCluster)
static uint32_t fatStartBlock
static uint8_t const BOOTSIG0
static uint32_t cacheMirrorBlock
static uint8_t const DIR_NAME_DELETED
Truncate the file to zero length.
static bool fatGet(fat_t cluster, fat_t *value)
static void printDirName(IOStream &outs, const dir_t &dir, uint8_t width)
static uint8_t blocksPerCluster
bool truncate(uint32_t size)
uint8_t sectorsPerCluster
static uint8_t const DIR_ATT_LONG_NAME
static fat_t blocksPerFat
virtual int write(const void *buf, size_t size)
static bool begin(SD *sd, uint8_t partion)
IOStream & endl(IOStream &outs)
bool read(CMD command, uint32_t arg, void *buf, size_t count)
Open for reading and writing.
bool seek(uint32_t pos, uint8_t whence=SEEK_SET)
static uint8_t cacheRawBlock(uint32_t blockNumber, uint8_t action=0)
static uint8_t DIR_IS_FILE(const dir_t *dir)
static uint8_t DIR_IS_SUBDIR(const dir_t *dir)
static bool make83Name(const char *str, uint8_t *name)
static void cacheSetDirty(void)
static uint8_t cacheFlush(void)
Relative to current position.
static void ls(IOStream &outs, uint8_t flags=0)
friend IOStream & operator<<(IOStream &outs, date_t &date)
static uint32_t dataStartBlock
static uint16_t rootDirEntryCount
static uint8_t const DIR_ATT_LONG_NAME_MASK
Create the file if nonexistent.
static uint32_t cacheBlockNumber
static bool fatPut(fat_t cluster, fat_t value)
static bool read(dir_t *dir, uint16_t *index, uint8_t skip=DIR_ATT_SKIP)
uint16_t reservedSectorCount
static dir_t * cacheDirEntry(uint16_t index, uint8_t action=0)
static uint8_t const F_FILE_DIR_DIRTY
static cache16_t cacheBuffer
static uint16_t cacheDataOffset(uint32_t position)