You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

323 lines
9.6KB

  1. /* Arduino SdFat Library
  2. * Copyright (C) 2012 by William Greiman
  3. *
  4. * This file is part of the Arduino SdFat Library
  5. *
  6. * This Library is free software: you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License as published by
  8. * the Free Software Foundation, either version 3 of the License, or
  9. * (at your option) any later version.
  10. *
  11. * This Library is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU General Public License
  17. * along with the Arduino SdFat Library. If not, see
  18. * <http://www.gnu.org/licenses/>.
  19. */
  20. #include <SdFat.h>
  21. #include <utility/FmtNumber.h>
  22. //------------------------------------------------------------------------------
  23. /** List directory contents to stdOut.
  24. *
  25. * \param[in] flags The inclusive OR of
  26. *
  27. * LS_DATE - %Print file modification date
  28. *
  29. * LS_SIZE - %Print file size.
  30. *
  31. * LS_R - Recursive list of subdirectories.
  32. */
  33. void SdBaseFile::ls(uint8_t flags) {
  34. ls(SdFat::stdOut(), flags, 0);
  35. }
  36. //------------------------------------------------------------------------------
  37. /** List directory contents.
  38. *
  39. * \param[in] pr Print stream for list.
  40. *
  41. * \param[in] flags The inclusive OR of
  42. *
  43. * LS_DATE - %Print file modification date
  44. *
  45. * LS_SIZE - %Print file size.
  46. *
  47. * LS_R - Recursive list of subdirectories.
  48. *
  49. * \param[in] indent Amount of space before file name. Used for recursive
  50. * list to indicate subdirectory level.
  51. */
  52. //------------------------------------------------------------------------------
  53. void SdBaseFile::ls(Print* pr, uint8_t flags, uint8_t indent) {
  54. if (!isDir()) {
  55. pr->println(F("bad dir"));
  56. return;
  57. }
  58. rewind();
  59. int8_t status;
  60. while ((status = lsPrintNext(pr, flags, indent))) {
  61. if (status > 1 && (flags & LS_R)) {
  62. uint16_t index = curPosition()/32 - 1;
  63. SdBaseFile s;
  64. if (s.open(this, index, O_READ)) s.ls(pr, flags, indent + 2);
  65. seekSet(32 * (index + 1));
  66. }
  67. }
  68. }
  69. //------------------------------------------------------------------------------
  70. // saves 32 bytes on stack for ls recursion
  71. // return 0 - EOF, 1 - normal file, or 2 - directory
  72. int8_t SdBaseFile::lsPrintNext(Print *pr, uint8_t flags, uint8_t indent) {
  73. dir_t dir;
  74. uint8_t w = 0;
  75. while (1) {
  76. if (read(&dir, sizeof(dir)) != sizeof(dir)) return 0;
  77. if (dir.name[0] == DIR_NAME_FREE) return 0;
  78. // skip deleted entry and entries for . and ..
  79. if (dir.name[0] != DIR_NAME_DELETED && dir.name[0] != '.'
  80. && DIR_IS_FILE_OR_SUBDIR(&dir)) break;
  81. }
  82. // indent for dir level
  83. for (uint8_t i = 0; i < indent; i++) pr->write(' ');
  84. // print name
  85. for (uint8_t i = 0; i < 11; i++) {
  86. if (dir.name[i] == ' ')continue;
  87. if (i == 8) {
  88. pr->write('.');
  89. w++;
  90. }
  91. pr->write(dir.name[i]);
  92. w++;
  93. }
  94. if (DIR_IS_SUBDIR(&dir)) {
  95. pr->write('/');
  96. w++;
  97. }
  98. if (flags & (LS_DATE | LS_SIZE)) {
  99. while (w++ < 14) pr->write(' ');
  100. }
  101. // print modify date/time if requested
  102. if (flags & LS_DATE) {
  103. pr->write(' ');
  104. printFatDate(pr, dir.lastWriteDate);
  105. pr->write(' ');
  106. printFatTime(pr, dir.lastWriteTime);
  107. }
  108. // print size if requested
  109. if (!DIR_IS_SUBDIR(&dir) && (flags & LS_SIZE)) {
  110. pr->write(' ');
  111. pr->print(dir.fileSize);
  112. }
  113. pr->println();
  114. return DIR_IS_FILE(&dir) ? 1 : 2;
  115. }
  116. //------------------------------------------------------------------------------
  117. // print uint8_t with width 2
  118. static void print2u(Print* pr, uint8_t v) {
  119. if (v < 10) pr->write('0');
  120. pr->print(v, DEC);
  121. }
  122. //------------------------------------------------------------------------------
  123. /** Print a file's creation date and time
  124. *
  125. * \param[in] pr Print stream for output.
  126. *
  127. * \return The value one, true, is returned for success and
  128. * the value zero, false, is returned for failure.
  129. */
  130. bool SdBaseFile::printCreateDateTime(Print* pr) {
  131. dir_t dir;
  132. if (!dirEntry(&dir)) {
  133. DBG_FAIL_MACRO;
  134. goto fail;
  135. }
  136. printFatDate(pr, dir.creationDate);
  137. pr->write(' ');
  138. printFatTime(pr, dir.creationTime);
  139. return true;
  140. fail:
  141. return false;
  142. }
  143. //------------------------------------------------------------------------------
  144. /** %Print a directory date field to stdOut.
  145. *
  146. * Format is yyyy-mm-dd.
  147. *
  148. * \param[in] fatDate The date field from a directory entry.
  149. */
  150. void SdBaseFile::printFatDate(uint16_t fatDate) {
  151. printFatDate(SdFat::stdOut(), fatDate);
  152. }
  153. //------------------------------------------------------------------------------
  154. /** %Print a directory date field.
  155. *
  156. * Format is yyyy-mm-dd.
  157. *
  158. * \param[in] pr Print stream for output.
  159. * \param[in] fatDate The date field from a directory entry.
  160. */
  161. void SdBaseFile::printFatDate(Print* pr, uint16_t fatDate) {
  162. pr->print(FAT_YEAR(fatDate));
  163. pr->write('-');
  164. print2u(pr, FAT_MONTH(fatDate));
  165. pr->write('-');
  166. print2u(pr, FAT_DAY(fatDate));
  167. }
  168. //------------------------------------------------------------------------------
  169. /** %Print a directory time field to stdOut.
  170. *
  171. * Format is hh:mm:ss.
  172. *
  173. * \param[in] fatTime The time field from a directory entry.
  174. */
  175. void SdBaseFile::printFatTime(uint16_t fatTime) {
  176. printFatTime(SdFat::stdOut(), fatTime);
  177. }
  178. //------------------------------------------------------------------------------
  179. /** %Print a directory time field.
  180. *
  181. * Format is hh:mm:ss.
  182. *
  183. * \param[in] pr Print stream for output.
  184. * \param[in] fatTime The time field from a directory entry.
  185. */
  186. void SdBaseFile::printFatTime(Print* pr, uint16_t fatTime) {
  187. print2u(pr, FAT_HOUR(fatTime));
  188. pr->write(':');
  189. print2u(pr, FAT_MINUTE(fatTime));
  190. pr->write(':');
  191. print2u(pr, FAT_SECOND(fatTime));
  192. }
  193. //------------------------------------------------------------------------------
  194. /** Template for SdBaseFile::printField() */
  195. template <typename Type>
  196. static int printFieldT(SdBaseFile* file, char sign, Type value, char term) {
  197. char buf[3*sizeof(Type) + 3];
  198. char* str = &buf[sizeof(buf)];
  199. if (term) {
  200. *--str = term;
  201. if (term == '\n') {
  202. *--str = '\r';
  203. }
  204. }
  205. do {
  206. Type m = value;
  207. value /= 10;
  208. *--str = '0' + m - 10*value;
  209. } while (value);
  210. if (sign) {
  211. *--str = sign;
  212. }
  213. return file->write(str, &buf[sizeof(buf)] - str);
  214. }
  215. //------------------------------------------------------------------------------
  216. /** Print a number followed by a field terminator.
  217. * \param[in] value The number to be printed.
  218. * \param[in] term The field terminator. Use '\\n' for CR LF.
  219. * \return The number of bytes written or -1 if an error occurs.
  220. */
  221. int SdBaseFile::printField(uint16_t value, char term) {
  222. return printFieldT(this, 0, value, term);
  223. }
  224. //------------------------------------------------------------------------------
  225. /** Print a number followed by a field terminator.
  226. * \param[in] value The number to be printed.
  227. * \param[in] term The field terminator. Use '\\n' for CR LF.
  228. * \return The number of bytes written or -1 if an error occurs.
  229. */
  230. int SdBaseFile::printField(int16_t value, char term) {
  231. char sign = 0;
  232. if (value < 0) {
  233. sign = '-';
  234. value = -value;
  235. }
  236. return printFieldT(this, sign, (uint16_t)value, term);
  237. }
  238. //------------------------------------------------------------------------------
  239. /** Print a number followed by a field terminator.
  240. * \param[in] value The number to be printed.
  241. * \param[in] term The field terminator. Use '\\n' for CR LF.
  242. * \return The number of bytes written or -1 if an error occurs.
  243. */
  244. int SdBaseFile::printField(uint32_t value, char term) {
  245. return printFieldT(this, 0, value, term);
  246. }
  247. //------------------------------------------------------------------------------
  248. /** Print a number followed by a field terminator.
  249. * \param[in] value The number to be printed.
  250. * \param[in] term The field terminator. Use '\\n' for CR LF.
  251. * \return The number of bytes written or -1 if an error occurs.
  252. */
  253. int SdBaseFile::printField(int32_t value, char term) {
  254. char sign = 0;
  255. if (value < 0) {
  256. sign = '-';
  257. value = -value;
  258. }
  259. return printFieldT(this, sign, (uint32_t)value, term);
  260. }
  261. //------------------------------------------------------------------------------
  262. /** Print a file's modify date and time
  263. *
  264. * \param[in] pr Print stream for output.
  265. *
  266. * \return The value one, true, is returned for success and
  267. * the value zero, false, is returned for failure.
  268. */
  269. bool SdBaseFile::printModifyDateTime(Print* pr) {
  270. dir_t dir;
  271. if (!dirEntry(&dir)) {
  272. DBG_FAIL_MACRO;
  273. goto fail;
  274. }
  275. printFatDate(pr, dir.lastWriteDate);
  276. pr->write(' ');
  277. printFatTime(pr, dir.lastWriteTime);
  278. return true;
  279. fail:
  280. return false;
  281. }
  282. //------------------------------------------------------------------------------
  283. /** Print a file's name
  284. *
  285. * \param[in] pr Print stream for output.
  286. *
  287. * \return The value one, true, is returned for success and
  288. * the value zero, false, is returned for failure.
  289. */
  290. size_t SdBaseFile::printName(Print* pr) {
  291. char name[13];
  292. if (!getFilename(name)) {
  293. DBG_FAIL_MACRO;
  294. goto fail;
  295. }
  296. return pr->print(name);
  297. fail:
  298. return 0;
  299. }
  300. //------------------------------------------------------------------------------
  301. /** Print a file's name to stdOut
  302. *
  303. * \return The value one, true, is returned for success and
  304. * the value zero, false, is returned for failure.
  305. */
  306. size_t SdBaseFile::printName() {
  307. return printName(SdFat::stdOut());
  308. }
  309. //------------------------------------------------------------------------------
  310. size_t SdBaseFile::printFileSize(Print* pr) {
  311. char buf[10];
  312. char *ptr = fmtDec(fileSize(), buf + sizeof(buf));
  313. while (ptr > buf) *--ptr = ' ';
  314. return pr->write(reinterpret_cast<uint8_t *>(buf), sizeof(buf));
  315. }