322 lines
9.6 KiB
C++
322 lines
9.6 KiB
C++
/* Arduino SdFat Library
|
|
* Copyright (C) 2012 by William Greiman
|
|
*
|
|
* This file is part of the Arduino SdFat Library
|
|
*
|
|
* This Library is free software: you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation, either version 3 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* This Library is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with the Arduino SdFat Library. If not, see
|
|
* <http://www.gnu.org/licenses/>.
|
|
*/
|
|
#include <SdFat.h>
|
|
#include <utility/FmtNumber.h>
|
|
//------------------------------------------------------------------------------
|
|
/** List directory contents to stdOut.
|
|
*
|
|
* \param[in] flags The inclusive OR of
|
|
*
|
|
* LS_DATE - %Print file modification date
|
|
*
|
|
* LS_SIZE - %Print file size.
|
|
*
|
|
* LS_R - Recursive list of subdirectories.
|
|
*/
|
|
void SdBaseFile::ls(uint8_t flags) {
|
|
ls(SdFat::stdOut(), flags, 0);
|
|
}
|
|
//------------------------------------------------------------------------------
|
|
/** List directory contents.
|
|
*
|
|
* \param[in] pr Print stream for list.
|
|
*
|
|
* \param[in] flags The inclusive OR of
|
|
*
|
|
* LS_DATE - %Print file modification date
|
|
*
|
|
* LS_SIZE - %Print file size.
|
|
*
|
|
* LS_R - Recursive list of subdirectories.
|
|
*
|
|
* \param[in] indent Amount of space before file name. Used for recursive
|
|
* list to indicate subdirectory level.
|
|
*/
|
|
//------------------------------------------------------------------------------
|
|
void SdBaseFile::ls(Print* pr, uint8_t flags, uint8_t indent) {
|
|
if (!isDir()) {
|
|
pr->println(F("bad dir"));
|
|
return;
|
|
}
|
|
rewind();
|
|
int8_t status;
|
|
while ((status = lsPrintNext(pr, flags, indent))) {
|
|
if (status > 1 && (flags & LS_R)) {
|
|
uint16_t index = curPosition()/32 - 1;
|
|
SdBaseFile s;
|
|
if (s.open(this, index, O_READ)) s.ls(pr, flags, indent + 2);
|
|
seekSet(32 * (index + 1));
|
|
}
|
|
}
|
|
}
|
|
//------------------------------------------------------------------------------
|
|
// saves 32 bytes on stack for ls recursion
|
|
// return 0 - EOF, 1 - normal file, or 2 - directory
|
|
int8_t SdBaseFile::lsPrintNext(Print *pr, uint8_t flags, uint8_t indent) {
|
|
dir_t dir;
|
|
uint8_t w = 0;
|
|
|
|
while (1) {
|
|
if (read(&dir, sizeof(dir)) != sizeof(dir)) return 0;
|
|
if (dir.name[0] == DIR_NAME_FREE) return 0;
|
|
|
|
// skip deleted entry and entries for . and ..
|
|
if (dir.name[0] != DIR_NAME_DELETED && dir.name[0] != '.'
|
|
&& DIR_IS_FILE_OR_SUBDIR(&dir)) break;
|
|
}
|
|
// indent for dir level
|
|
for (uint8_t i = 0; i < indent; i++) pr->write(' ');
|
|
|
|
// print name
|
|
for (uint8_t i = 0; i < 11; i++) {
|
|
if (dir.name[i] == ' ')continue;
|
|
if (i == 8) {
|
|
pr->write('.');
|
|
w++;
|
|
}
|
|
pr->write(dir.name[i]);
|
|
w++;
|
|
}
|
|
if (DIR_IS_SUBDIR(&dir)) {
|
|
pr->write('/');
|
|
w++;
|
|
}
|
|
if (flags & (LS_DATE | LS_SIZE)) {
|
|
while (w++ < 14) pr->write(' ');
|
|
}
|
|
// print modify date/time if requested
|
|
if (flags & LS_DATE) {
|
|
pr->write(' ');
|
|
printFatDate(pr, dir.lastWriteDate);
|
|
pr->write(' ');
|
|
printFatTime(pr, dir.lastWriteTime);
|
|
}
|
|
// print size if requested
|
|
if (!DIR_IS_SUBDIR(&dir) && (flags & LS_SIZE)) {
|
|
pr->write(' ');
|
|
pr->print(dir.fileSize);
|
|
}
|
|
pr->println();
|
|
return DIR_IS_FILE(&dir) ? 1 : 2;
|
|
}
|
|
//------------------------------------------------------------------------------
|
|
// print uint8_t with width 2
|
|
static void print2u(Print* pr, uint8_t v) {
|
|
if (v < 10) pr->write('0');
|
|
pr->print(v, DEC);
|
|
}
|
|
//------------------------------------------------------------------------------
|
|
/** Print a file's creation date and time
|
|
*
|
|
* \param[in] pr Print stream for output.
|
|
*
|
|
* \return The value one, true, is returned for success and
|
|
* the value zero, false, is returned for failure.
|
|
*/
|
|
bool SdBaseFile::printCreateDateTime(Print* pr) {
|
|
dir_t dir;
|
|
if (!dirEntry(&dir)) {
|
|
DBG_FAIL_MACRO;
|
|
goto fail;
|
|
}
|
|
printFatDate(pr, dir.creationDate);
|
|
pr->write(' ');
|
|
printFatTime(pr, dir.creationTime);
|
|
return true;
|
|
|
|
fail:
|
|
return false;
|
|
}
|
|
//------------------------------------------------------------------------------
|
|
/** %Print a directory date field to stdOut.
|
|
*
|
|
* Format is yyyy-mm-dd.
|
|
*
|
|
* \param[in] fatDate The date field from a directory entry.
|
|
*/
|
|
void SdBaseFile::printFatDate(uint16_t fatDate) {
|
|
printFatDate(SdFat::stdOut(), fatDate);
|
|
}
|
|
//------------------------------------------------------------------------------
|
|
/** %Print a directory date field.
|
|
*
|
|
* Format is yyyy-mm-dd.
|
|
*
|
|
* \param[in] pr Print stream for output.
|
|
* \param[in] fatDate The date field from a directory entry.
|
|
*/
|
|
void SdBaseFile::printFatDate(Print* pr, uint16_t fatDate) {
|
|
pr->print(FAT_YEAR(fatDate));
|
|
pr->write('-');
|
|
print2u(pr, FAT_MONTH(fatDate));
|
|
pr->write('-');
|
|
print2u(pr, FAT_DAY(fatDate));
|
|
}
|
|
//------------------------------------------------------------------------------
|
|
/** %Print a directory time field to stdOut.
|
|
*
|
|
* Format is hh:mm:ss.
|
|
*
|
|
* \param[in] fatTime The time field from a directory entry.
|
|
*/
|
|
void SdBaseFile::printFatTime(uint16_t fatTime) {
|
|
printFatTime(SdFat::stdOut(), fatTime);
|
|
}
|
|
//------------------------------------------------------------------------------
|
|
/** %Print a directory time field.
|
|
*
|
|
* Format is hh:mm:ss.
|
|
*
|
|
* \param[in] pr Print stream for output.
|
|
* \param[in] fatTime The time field from a directory entry.
|
|
*/
|
|
void SdBaseFile::printFatTime(Print* pr, uint16_t fatTime) {
|
|
print2u(pr, FAT_HOUR(fatTime));
|
|
pr->write(':');
|
|
print2u(pr, FAT_MINUTE(fatTime));
|
|
pr->write(':');
|
|
print2u(pr, FAT_SECOND(fatTime));
|
|
}
|
|
//------------------------------------------------------------------------------
|
|
/** Template for SdBaseFile::printField() */
|
|
template <typename Type>
|
|
static int printFieldT(SdBaseFile* file, char sign, Type value, char term) {
|
|
char buf[3*sizeof(Type) + 3];
|
|
char* str = &buf[sizeof(buf)];
|
|
|
|
if (term) {
|
|
*--str = term;
|
|
if (term == '\n') {
|
|
*--str = '\r';
|
|
}
|
|
}
|
|
do {
|
|
Type m = value;
|
|
value /= 10;
|
|
*--str = '0' + m - 10*value;
|
|
} while (value);
|
|
if (sign) {
|
|
*--str = sign;
|
|
}
|
|
return file->write(str, &buf[sizeof(buf)] - str);
|
|
}
|
|
//------------------------------------------------------------------------------
|
|
/** Print a number followed by a field terminator.
|
|
* \param[in] value The number to be printed.
|
|
* \param[in] term The field terminator. Use '\\n' for CR LF.
|
|
* \return The number of bytes written or -1 if an error occurs.
|
|
*/
|
|
int SdBaseFile::printField(uint16_t value, char term) {
|
|
return printFieldT(this, 0, value, term);
|
|
}
|
|
//------------------------------------------------------------------------------
|
|
/** Print a number followed by a field terminator.
|
|
* \param[in] value The number to be printed.
|
|
* \param[in] term The field terminator. Use '\\n' for CR LF.
|
|
* \return The number of bytes written or -1 if an error occurs.
|
|
*/
|
|
int SdBaseFile::printField(int16_t value, char term) {
|
|
char sign = 0;
|
|
if (value < 0) {
|
|
sign = '-';
|
|
value = -value;
|
|
}
|
|
return printFieldT(this, sign, (uint16_t)value, term);
|
|
}
|
|
//------------------------------------------------------------------------------
|
|
/** Print a number followed by a field terminator.
|
|
* \param[in] value The number to be printed.
|
|
* \param[in] term The field terminator. Use '\\n' for CR LF.
|
|
* \return The number of bytes written or -1 if an error occurs.
|
|
*/
|
|
int SdBaseFile::printField(uint32_t value, char term) {
|
|
return printFieldT(this, 0, value, term);
|
|
}
|
|
//------------------------------------------------------------------------------
|
|
/** Print a number followed by a field terminator.
|
|
* \param[in] value The number to be printed.
|
|
* \param[in] term The field terminator. Use '\\n' for CR LF.
|
|
* \return The number of bytes written or -1 if an error occurs.
|
|
*/
|
|
int SdBaseFile::printField(int32_t value, char term) {
|
|
char sign = 0;
|
|
if (value < 0) {
|
|
sign = '-';
|
|
value = -value;
|
|
}
|
|
return printFieldT(this, sign, (uint32_t)value, term);
|
|
}
|
|
//------------------------------------------------------------------------------
|
|
/** Print a file's modify date and time
|
|
*
|
|
* \param[in] pr Print stream for output.
|
|
*
|
|
* \return The value one, true, is returned for success and
|
|
* the value zero, false, is returned for failure.
|
|
*/
|
|
bool SdBaseFile::printModifyDateTime(Print* pr) {
|
|
dir_t dir;
|
|
if (!dirEntry(&dir)) {
|
|
DBG_FAIL_MACRO;
|
|
goto fail;
|
|
}
|
|
printFatDate(pr, dir.lastWriteDate);
|
|
pr->write(' ');
|
|
printFatTime(pr, dir.lastWriteTime);
|
|
return true;
|
|
|
|
fail:
|
|
return false;
|
|
}
|
|
//------------------------------------------------------------------------------
|
|
/** Print a file's name
|
|
*
|
|
* \param[in] pr Print stream for output.
|
|
*
|
|
* \return The value one, true, is returned for success and
|
|
* the value zero, false, is returned for failure.
|
|
*/
|
|
size_t SdBaseFile::printName(Print* pr) {
|
|
char name[13];
|
|
if (!getFilename(name)) {
|
|
DBG_FAIL_MACRO;
|
|
goto fail;
|
|
}
|
|
return pr->print(name);
|
|
|
|
fail:
|
|
return 0;
|
|
}
|
|
//------------------------------------------------------------------------------
|
|
/** Print a file's name to stdOut
|
|
*
|
|
* \return The value one, true, is returned for success and
|
|
* the value zero, false, is returned for failure.
|
|
*/
|
|
size_t SdBaseFile::printName() {
|
|
return printName(SdFat::stdOut());
|
|
}
|
|
//------------------------------------------------------------------------------
|
|
size_t SdBaseFile::printFileSize(Print* pr) {
|
|
char buf[10];
|
|
char *ptr = fmtDec(fileSize(), buf + sizeof(buf));
|
|
while (ptr > buf) *--ptr = ' ';
|
|
return pr->write(reinterpret_cast<uint8_t *>(buf), sizeof(buf));
|
|
}
|