ExFatFile.h 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864
  1. /**
  2. * Copyright (c) 2011-2022 Bill Greiman
  3. * This file is part of the SdFat library for SD memory cards.
  4. *
  5. * MIT License
  6. *
  7. * Permission is hereby granted, free of charge, to any person obtaining a
  8. * copy of this software and associated documentation files (the "Software"),
  9. * to deal in the Software without restriction, including without limitation
  10. * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  11. * and/or sell copies of the Software, and to permit persons to whom the
  12. * Software is furnished to do so, subject to the following conditions:
  13. *
  14. * The above copyright notice and this permission notice shall be included
  15. * in all copies or substantial portions of the Software.
  16. *
  17. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
  18. * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  19. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  20. * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  21. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  22. * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  23. * DEALINGS IN THE SOFTWARE.
  24. */
  25. #ifndef ExFatFile_h
  26. #define ExFatFile_h
  27. /**
  28. * \file
  29. * \brief ExFatFile class
  30. */
  31. #include <limits.h>
  32. #include <string.h>
  33. #include "../common/FsDateTime.h"
  34. #include "../common/FsApiConstants.h"
  35. #include "../common/FmtNumber.h"
  36. #include "../common/FsName.h"
  37. #include "ExFatPartition.h"
  38. class ExFatVolume;
  39. //------------------------------------------------------------------------------
  40. /** Expression for path name separator. */
  41. #define isDirSeparator(c) ((c) == '/')
  42. //------------------------------------------------------------------------------
  43. /**
  44. * \class ExName_t
  45. * \brief Internal type for file name - do not use in user apps.
  46. */
  47. class ExName_t : public FsName {
  48. public:
  49. /** Length of UTF-16 name */
  50. size_t nameLength;
  51. /** Hash for UTF-16 name */
  52. uint16_t nameHash;
  53. };
  54. //------------------------------------------------------------------------------
  55. /**
  56. * \class ExFatFile
  57. * \brief Basic file class.
  58. */
  59. class ExFatFile {
  60. public:
  61. /** Create an instance. */
  62. ExFatFile() {}
  63. /** Create a file object and open it in the current working directory.
  64. *
  65. * \param[in] path A path for a file to be opened.
  66. *
  67. * \param[in] oflag Values for \a oflag are constructed by a bitwise-inclusive
  68. * OR of open flags. see FatFile::open(FatFile*, const char*, uint8_t).
  69. */
  70. ExFatFile(const char* path, oflag_t oflag) {
  71. open(path, oflag);
  72. }
  73. #if DESTRUCTOR_CLOSES_FILE
  74. ~ExFatFile() {
  75. if (isOpen()) {
  76. close();
  77. }
  78. }
  79. #endif // DESTRUCTOR_CLOSES_FILE
  80. /** The parenthesis operator.
  81. *
  82. * \return true if a file is open.
  83. */
  84. operator bool() {
  85. return isOpen();
  86. }
  87. /**
  88. * \return user settable file attributes for success else -1.
  89. */
  90. int attrib() {
  91. return isFileOrSubDir() ? m_attributes & FS_ATTRIB_COPY : -1;
  92. }
  93. /** Set file attributes
  94. *
  95. * \param[in] bits bit-wise or of selected attributes: FS_ATTRIB_READ_ONLY,
  96. * FS_ATTRIB_HIDDEN, FS_ATTRIB_SYSTEM, FS_ATTRIB_ARCHIVE.
  97. *
  98. * \note attrib() will fail for set read-only if the file is open for write.
  99. * \return true for success or false for failure.
  100. */
  101. bool attrib(uint8_t bits);
  102. /** \return The number of bytes available from the current position
  103. * to EOF for normal files. INT_MAX is returned for very large files.
  104. *
  105. * available64() is recommended for very large files.
  106. *
  107. * Zero is returned for directory files.
  108. *
  109. */
  110. int available() {
  111. uint64_t n = available64();
  112. return n > INT_MAX ? INT_MAX : n;
  113. }
  114. /** \return The number of bytes available from the current position
  115. * to EOF for normal files. Zero is returned for directory files.
  116. */
  117. uint64_t available64() {
  118. return isFile() ? fileSize() - curPosition() : 0;
  119. }
  120. /** Clear all error bits. */
  121. void clearError() {
  122. m_error = 0;
  123. }
  124. /** Clear writeError. */
  125. void clearWriteError() {
  126. m_error &= ~WRITE_ERROR;
  127. }
  128. /** Close a file and force cached data and directory information
  129. * to be written to the storage device.
  130. *
  131. * \return true for success or false for failure.
  132. */
  133. bool close();
  134. /** Check for contiguous file and return its raw sector range.
  135. *
  136. * \param[out] bgnSector the first sector address for the file.
  137. * \param[out] endSector the last sector address for the file.
  138. *
  139. * Parameters may be nullptr.
  140. *
  141. * \return true for success or false for failure.
  142. */
  143. bool contiguousRange(uint32_t* bgnSector, uint32_t* endSector);
  144. /** \return The current cluster number for a file or directory. */
  145. uint32_t curCluster() const {return m_curCluster;}
  146. /** \return The current position for a file or directory. */
  147. uint64_t curPosition() const {return m_curPosition;}
  148. /** \return Total data length for file. */
  149. uint64_t dataLength() const {return m_dataLength;}
  150. /** \return Directory entry index. */
  151. uint32_t dirIndex() const {return m_dirPos.position/FS_DIR_SIZE;}
  152. /** Test for the existence of a file in a directory
  153. *
  154. * \param[in] path Path of the file to be tested for.
  155. *
  156. * The calling instance must be an open directory file.
  157. *
  158. * dirFile.exists("TOFIND.TXT") searches for "TOFIND.TXT" in the directory
  159. * dirFile.
  160. *
  161. * \return true if the file exists else false.
  162. */
  163. bool exists(const char* path) {
  164. ExFatFile file;
  165. return file.open(this, path, O_RDONLY);
  166. }
  167. /** get position for streams
  168. * \param[out] pos struct to receive position
  169. */
  170. void fgetpos(fspos_t* pos) const;
  171. /**
  172. * Get a string from a file.
  173. *
  174. * fgets() reads bytes from a file into the array pointed to by \a str, until
  175. * \a num - 1 bytes are read, or a delimiter is read and transferred to
  176. * \a str, or end-of-file is encountered. The string is then terminated
  177. * with a null byte.
  178. *
  179. * fgets() deletes CR, '\\r', from the string. This insures only a '\\n'
  180. * terminates the string for Windows text files which use CRLF for newline.
  181. *
  182. * \param[out] str Pointer to the array where the string is stored.
  183. * \param[in] num Maximum number of characters to be read
  184. * (including the final null byte). Usually the length
  185. * of the array \a str is used.
  186. * \param[in] delim Optional set of delimiters. The default is "\n".
  187. *
  188. * \return For success fgets() returns the length of the string in \a str.
  189. * If no data is read, fgets() returns zero for EOF or -1 if an error
  190. * occurred.
  191. */
  192. int fgets(char* str, int num, char* delim = nullptr);
  193. /** \return The total number of bytes in a file. */
  194. uint64_t fileSize() const {return m_validLength;}
  195. /** \return Address of first sector or zero for empty file. */
  196. uint32_t firstSector() const;
  197. /** Set position for streams
  198. * \param[in] pos struct with value for new position
  199. */
  200. void fsetpos(const fspos_t* pos);
  201. /** Arduino name for sync() */
  202. void flush() {sync();}
  203. /** Get a file's access date and time.
  204. *
  205. * \param[out] pdate Packed date for directory entry.
  206. * \param[out] ptime Packed time for directory entry.
  207. *
  208. * \return true for success or false for failure.
  209. */
  210. bool getAccessDateTime(uint16_t* pdate, uint16_t* ptime);
  211. /** Get a file's create date and time.
  212. *
  213. * \param[out] pdate Packed date for directory entry.
  214. * \param[out] ptime Packed time for directory entry.
  215. *
  216. * \return true for success or false for failure.
  217. */
  218. bool getCreateDateTime(uint16_t* pdate, uint16_t* ptime);
  219. /** \return All error bits. */
  220. uint8_t getError() const {
  221. return isOpen() ? m_error : 0XFF;
  222. }
  223. /** Get a file's modify date and time.
  224. *
  225. * \param[out] pdate Packed date for directory entry.
  226. * \param[out] ptime Packed time for directory entry.
  227. *
  228. * \return true for success or false for failure.
  229. */
  230. bool getModifyDateTime(uint16_t* pdate, uint16_t* ptime);
  231. /**
  232. * Get a file's name followed by a zero.
  233. *
  234. * \param[out] name An array of characters for the file's name.
  235. * \param[in] size The size of the array in characters.
  236. * \return the name length.
  237. */
  238. size_t getName(char* name, size_t size) {
  239. #if USE_UTF8_LONG_NAMES
  240. return getName8(name, size);
  241. #else // USE_UTF8_LONG_NAMES
  242. return getName7(name, size);
  243. #endif // USE_UTF8_LONG_NAMES
  244. }
  245. /**
  246. * Get a file's ASCII name followed by a zero.
  247. *
  248. * \param[out] name An array of characters for the file's name.
  249. * \param[in] size The size of the array in characters.
  250. * \return the name length.
  251. */
  252. size_t getName7(char* name, size_t size);
  253. /**
  254. * Get a file's UTF-8 name followed by a zero.
  255. *
  256. * \param[out] name An array of characters for the file's name.
  257. * \param[in] size The size of the array in characters.
  258. * \return the name length.
  259. */
  260. size_t getName8(char* name, size_t size);
  261. /** \return value of writeError */
  262. bool getWriteError() const {
  263. return isOpen() ? m_error & WRITE_ERROR : true;
  264. }
  265. /**
  266. * Check for FsBlockDevice busy.
  267. *
  268. * \return true if busy else false.
  269. */
  270. bool isBusy();
  271. /** \return True if the file is contiguous. */
  272. bool isContiguous() const {return m_flags & FILE_FLAG_CONTIGUOUS;}
  273. /** \return True if this is a directory. */
  274. bool isDir() const {return m_attributes & FILE_ATTR_DIR;}
  275. /** \return True if this is a normal file. */
  276. bool isFile() const {return m_attributes & FILE_ATTR_FILE;}
  277. /** \return True if this is a normal file or sub-directory. */
  278. bool isFileOrSubDir() const {return isFile() || isSubDir();}
  279. /** \return True if this is a hidden. */
  280. bool isHidden() const {return m_attributes & FS_ATTRIB_HIDDEN;}
  281. /** \return true if the file is open. */
  282. bool isOpen() const {return m_attributes;}
  283. /** \return True if file is read-only */
  284. bool isReadOnly() const {return m_attributes & FS_ATTRIB_READ_ONLY;}
  285. /** \return True if this is the root directory. */
  286. bool isRoot() const {return m_attributes & FILE_ATTR_ROOT;}
  287. /** \return True file is readable. */
  288. bool isReadable() const {return m_flags & FILE_FLAG_READ;}
  289. /** \return True if this is a sub-directory. */
  290. bool isSubDir() const {return m_attributes & FILE_ATTR_SUBDIR;}
  291. /** \return True if this is a system file. */
  292. bool isSystem() const {return m_attributes & FS_ATTRIB_SYSTEM;}
  293. /** \return True file is writable. */
  294. bool isWritable() const {return m_flags & FILE_FLAG_WRITE;}
  295. /** List directory contents.
  296. *
  297. * \param[in] pr Print stream for list.
  298. * \return true for success or false for failure.
  299. */
  300. bool ls(print_t* pr);
  301. /** List directory contents.
  302. *
  303. * \param[in] pr Print stream for list.
  304. *
  305. * \param[in] flags The inclusive OR of
  306. *
  307. * LS_DATE - %Print file modification date
  308. *
  309. * LS_SIZE - %Print file size.
  310. *
  311. * LS_R - Recursive list of sub-directories.
  312. *
  313. * \param[in] indent Amount of space before file name. Used for recursive
  314. * list to indicate sub-directory level.
  315. *
  316. * \return true for success or false for failure.
  317. */
  318. bool ls(print_t* pr, uint8_t flags, uint8_t indent = 0);
  319. /** Make a new directory.
  320. *
  321. * \param[in] parent An open directory file that will
  322. * contain the new directory.
  323. *
  324. * \param[in] path A path with a valid name for the new directory.
  325. *
  326. * \param[in] pFlag Create missing parent directories if true.
  327. *
  328. * \return true for success or false for failure.
  329. */
  330. bool mkdir(ExFatFile* parent, const char* path, bool pFlag = true);
  331. /** Open a file or directory by name.
  332. *
  333. * \param[in] dirFile An open directory containing the file to be opened.
  334. *
  335. * \param[in] path The path for a file to be opened.
  336. *
  337. * \param[in] oflag Values for \a oflag are constructed by a
  338. * bitwise-inclusive OR of flags from the following list.
  339. * Only one of O_RDONLY, O_READ, O_WRONLY, O_WRITE, or
  340. * O_RDWR is allowed.
  341. *
  342. * O_RDONLY - Open for reading.
  343. *
  344. * O_READ - Same as O_RDONLY.
  345. *
  346. * O_WRONLY - Open for writing.
  347. *
  348. * O_WRITE - Same as O_WRONLY.
  349. *
  350. * O_RDWR - Open for reading and writing.
  351. *
  352. * O_APPEND - If set, the file offset shall be set to the end of the
  353. * file prior to each write.
  354. *
  355. * O_AT_END - Set the initial position at the end of the file.
  356. *
  357. * O_CREAT - If the file exists, this flag has no effect except as noted
  358. * under O_EXCL below. Otherwise, the file shall be created
  359. *
  360. * O_EXCL - If O_CREAT and O_EXCL are set, open() shall fail if the file
  361. * exists.
  362. *
  363. * O_TRUNC - If the file exists and is a regular file, and the file is
  364. * successfully opened and is not read only, its length shall be truncated
  365. * to 0.
  366. *
  367. * WARNING: A given file must not be opened by more than one file object
  368. * or file corruption may occur.
  369. *
  370. * \note Directory files must be opened read only. Write and truncation is
  371. * not allowed for directory files.
  372. *
  373. * \return true for success or false for failure.
  374. */
  375. bool open(ExFatFile* dirFile, const char* path, oflag_t oflag = O_RDONLY);
  376. /** Open a file in the volume working directory.
  377. *
  378. * \param[in] vol Volume where the file is located.
  379. *
  380. * \param[in] path with a valid name for a file to be opened.
  381. *
  382. * \param[in] oflag bitwise-inclusive OR of open flags.
  383. * See see open(ExFatFile*, const char*, uint8_t).
  384. *
  385. * \return true for success or false for failure.
  386. */
  387. bool open(ExFatVolume* vol, const char* path, oflag_t oflag = O_RDONLY);
  388. /** Open a file by index.
  389. *
  390. * \param[in] dirFile An open ExFatFile instance for the directory.
  391. *
  392. * \param[in] index The \a index of the directory entry for the file to be
  393. * opened. The value for \a index is (directory file position)/32.
  394. *
  395. * \param[in] oflag bitwise-inclusive OR of open flags.
  396. * See see ExFatFile::open(ExFatFile*, const char*, uint8_t).
  397. *
  398. * See open() by path for definition of flags.
  399. * \return true for success or false for failure.
  400. */
  401. bool open(ExFatFile* dirFile, uint32_t index, oflag_t oflag = O_RDONLY);
  402. /** Open a file by index in the current working directory.
  403. *
  404. * \param[in] index The \a index of the directory entry for the file to be
  405. * opened. The value for \a index is (directory file position)/32.
  406. *
  407. * \param[in] oflag bitwise-inclusive OR of open flags.
  408. * See see FatFile::open(FatFile*, const char*, uint8_t).
  409. *
  410. * See open() by path for definition of flags.
  411. * \return true for success or false for failure.
  412. */
  413. bool open(uint32_t index, oflag_t oflag = O_RDONLY);
  414. /** Open a file in the current working directory.
  415. *
  416. * \param[in] path A path with a valid name for a file to be opened.
  417. *
  418. * \param[in] oflag bitwise-inclusive OR of open flags.
  419. * See see ExFatFile::open(ExFatFile*, const char*, uint8_t).
  420. *
  421. * \return true for success or false for failure.
  422. */
  423. bool open(const char* path, oflag_t oflag = O_RDONLY);
  424. /** Open the current working directory.
  425. *
  426. * \return true for success or false for failure.
  427. */
  428. bool openCwd();
  429. /** Open the next file or subdirectory in a directory.
  430. *
  431. * \param[in] dirFile An open instance for the directory
  432. * containing the file to be opened.
  433. *
  434. * \param[in] oflag bitwise-inclusive OR of open flags.
  435. * See see open(ExFatFile*, const char*, uint8_t).
  436. *
  437. * \return true for success or false for failure.
  438. */
  439. bool openNext(ExFatFile* dirFile, oflag_t oflag = O_RDONLY);
  440. /** Open a volume's root directory.
  441. *
  442. * \param[in] vol The FAT volume containing the root directory to be opened.
  443. *
  444. * \return true for success or false for failure.
  445. */
  446. bool openRoot(ExFatVolume* vol);
  447. /** Return the next available byte without consuming it.
  448. *
  449. * \return The byte if no error and not at eof else -1;
  450. */
  451. int peek();
  452. /** Allocate contiguous clusters to an empty file.
  453. *
  454. * The file must be empty with no clusters allocated.
  455. *
  456. * The file will have zero validLength and dataLength
  457. * will equal the requested length.
  458. *
  459. * \param[in] length size of allocated space in bytes.
  460. * \return true for success or false for failure.
  461. */
  462. bool preAllocate(uint64_t length);
  463. /** Print a file's access date and time
  464. *
  465. * \param[in] pr Print stream for output.
  466. *
  467. * \return true for success or false for failure.
  468. */
  469. size_t printAccessDateTime(print_t* pr);
  470. /** Print a file's creation date and time
  471. *
  472. * \param[in] pr Print stream for output.
  473. *
  474. * \return true for success or false for failure.
  475. */
  476. size_t printCreateDateTime(print_t* pr);
  477. /** Print a number followed by a field terminator.
  478. * \param[in] value The number to be printed.
  479. * \param[in] term The field terminator. Use '\\n' for CR LF.
  480. * \param[in] prec Number of digits after decimal point.
  481. * \return The number of bytes written or -1 if an error occurs.
  482. */
  483. size_t printField(double value, char term, uint8_t prec = 2) {
  484. char buf[24];
  485. char* str = buf + sizeof(buf);
  486. if (term) {
  487. *--str = term;
  488. if (term == '\n') {
  489. *--str = '\r';
  490. }
  491. }
  492. str = fmtDouble(str, value, prec, false);
  493. return write(str, buf + sizeof(buf) - str);
  494. }
  495. /** Print a number followed by a field terminator.
  496. * \param[in] value The number to be printed.
  497. * \param[in] term The field terminator. Use '\\n' for CR LF.
  498. * \param[in] prec Number of digits after decimal point.
  499. * \return The number of bytes written or -1 if an error occurs.
  500. */
  501. size_t printField(float value, char term, uint8_t prec = 2) {
  502. return printField(static_cast<double>(value), term, prec);
  503. }
  504. /** Print a number followed by a field terminator.
  505. * \param[in] value The number to be printed.
  506. * \param[in] term The field terminator. Use '\\n' for CR LF.
  507. * \return The number of bytes written or -1 if an error occurs.
  508. */
  509. template <typename Type>
  510. size_t printField(Type value, char term) {
  511. char sign = 0;
  512. char buf[3*sizeof(Type) + 3];
  513. char* str = buf + sizeof(buf);
  514. if (term) {
  515. *--str = term;
  516. if (term == '\n') {
  517. *--str = '\r';
  518. }
  519. }
  520. if (value < 0) {
  521. value = -value;
  522. sign = '-';
  523. }
  524. if (sizeof(Type) < 4) {
  525. str = fmtBase10(str, (uint16_t)value);
  526. } else {
  527. str = fmtBase10(str, (uint32_t)value);
  528. }
  529. if (sign) {
  530. *--str = sign;
  531. }
  532. return write(str, &buf[sizeof(buf)] - str);
  533. }
  534. /** Print a file's size in bytes.
  535. * \param[in] pr Prtin stream for the output.
  536. * \return The number of bytes printed.
  537. */
  538. size_t printFileSize(print_t* pr);
  539. /** Print a file's modify date and time
  540. *
  541. * \param[in] pr Print stream for output.
  542. *
  543. * \return true for success or false for failure.
  544. */
  545. size_t printModifyDateTime(print_t* pr);
  546. /** Print a file's name
  547. *
  548. * \param[in] pr Print stream for output.
  549. *
  550. * \return length for success or zero for failure.
  551. */
  552. size_t printName(print_t* pr) {
  553. #if USE_UTF8_LONG_NAMES
  554. return printName8(pr);
  555. #else // USE_UTF8_LONG_NAMES
  556. return printName7(pr);
  557. #endif // USE_UTF8_LONG_NAMES
  558. }
  559. /** Print a file's ASCII name
  560. *
  561. * \param[in] pr Print stream for output.
  562. *
  563. * \return true for success or false for failure.
  564. */
  565. size_t printName7(print_t* pr);
  566. /** Print a file's UTF-8 name
  567. *
  568. * \param[in] pr Print stream for output.
  569. *
  570. * \return true for success or false for failure.
  571. */
  572. size_t printName8(print_t* pr);
  573. /** Read the next byte from a file.
  574. *
  575. * \return For success read returns the next byte in the file as an int.
  576. * If an error occurs or end of file is reached -1 is returned.
  577. */
  578. int read() {
  579. uint8_t b;
  580. return read(&b, 1) == 1 ? b : -1;
  581. }
  582. /** Read data from a file starting at the current position.
  583. *
  584. * \param[out] buf Pointer to the location that will receive the data.
  585. *
  586. * \param[in] count Maximum number of bytes to read.
  587. *
  588. * \return For success read() returns the number of bytes read.
  589. * A value less than \a nbyte, including zero, will be returned
  590. * if end of file is reached.
  591. * If an error occurs, read() returns -1.
  592. */
  593. int read(void* buf, size_t count);
  594. /** Remove a file.
  595. *
  596. * The directory entry and all data for the file are deleted.
  597. *
  598. * \note This function should not be used to delete the 8.3 version of a
  599. * file that has a long name. For example if a file has the long name
  600. * "New Text Document.txt" you should not delete the 8.3 name "NEWTEX~1.TXT".
  601. *
  602. * \return true for success or false for failure.
  603. */
  604. bool remove();
  605. /** Remove a file.
  606. *
  607. * The directory entry and all data for the file are deleted.
  608. *
  609. * \param[in] path Path for the file to be removed.
  610. *
  611. * Example use: dirFile.remove(filenameToRemove);
  612. *
  613. * \note This function should not be used to delete the 8.3 version of a
  614. * file that has a long name. For example if a file has the long name
  615. * "New Text Document.txt" you should not delete the 8.3 name "NEWTEX~1.TXT".
  616. *
  617. * \return true for success or false for failure.
  618. */
  619. bool remove(const char* path);
  620. /** Rename a file or subdirectory.
  621. *
  622. * \param[in] newPath New path name for the file/directory.
  623. *
  624. * \return true for success or false for failure.
  625. */
  626. bool rename(const char* newPath);
  627. /** Rename a file or subdirectory.
  628. *
  629. * \param[in] dirFile Directory for the new path.
  630. * \param[in] newPath New path name for the file/directory.
  631. *
  632. * \return true for success or false for failure.
  633. */
  634. bool rename(ExFatFile* dirFile, const char* newPath);
  635. /** Set the file's current position to zero. */
  636. void rewind() {
  637. seekSet(0);
  638. }
  639. /** Remove a directory file.
  640. *
  641. * The directory file will be removed only if it is empty and is not the
  642. * root directory. rmdir() follows DOS and Windows and ignores the
  643. * read-only attribute for the directory.
  644. *
  645. * \note This function should not be used to delete the 8.3 version of a
  646. * directory that has a long name. For example if a directory has the
  647. * long name "New folder" you should not delete the 8.3 name "NEWFOL~1".
  648. *
  649. * \return true for success or false for failure.
  650. */
  651. bool rmdir();
  652. /** Set the files position to current position + \a pos. See seekSet().
  653. * \param[in] offset The new position in bytes from the current position.
  654. * \return true for success or false for failure.
  655. */
  656. bool seekCur(int64_t offset) {
  657. return seekSet(m_curPosition + offset);
  658. }
  659. /** Set the files position to end-of-file + \a offset. See seekSet().
  660. * Can't be used for directory files since file size is not defined.
  661. * \param[in] offset The new position in bytes from end-of-file.
  662. * \return true for success or false for failure.
  663. */
  664. bool seekEnd(int64_t offset = 0) {
  665. return isFile() ? seekSet(m_validLength + offset) : false;
  666. }
  667. /** Sets a file's position.
  668. *
  669. * \param[in] pos The new position in bytes from the beginning of the file.
  670. *
  671. * \return true for success or false for failure.
  672. */
  673. bool seekSet(uint64_t pos);
  674. /** \return directory set count */
  675. uint8_t setCount() const {return m_setCount;}
  676. /** The sync() call causes all modified data and directory fields
  677. * to be written to the storage device.
  678. *
  679. * \return true for success or false for failure.
  680. */
  681. bool sync();
  682. /** Truncate a file at the current file position.
  683. *
  684. * \return true for success or false for failure.
  685. */
  686. /** Set a file's timestamps in its directory entry.
  687. *
  688. * \param[in] flags Values for \a flags are constructed by a
  689. * bitwise-inclusive OR of flags from the following list
  690. *
  691. * T_ACCESS - Set the file's last access date and time.
  692. *
  693. * T_CREATE - Set the file's creation date and time.
  694. *
  695. * T_WRITE - Set the file's last write/modification date and time.
  696. *
  697. * \param[in] year Valid range 1980 - 2107 inclusive.
  698. *
  699. * \param[in] month Valid range 1 - 12 inclusive.
  700. *
  701. * \param[in] day Valid range 1 - 31 inclusive.
  702. *
  703. * \param[in] hour Valid range 0 - 23 inclusive.
  704. *
  705. * \param[in] minute Valid range 0 - 59 inclusive.
  706. *
  707. * \param[in] second Valid range 0 - 59 inclusive
  708. *
  709. * \note It is possible to set an invalid date since there is no check for
  710. * the number of days in a month.
  711. *
  712. * \note
  713. * Modify and access timestamps may be overwritten if a date time callback
  714. * function has been set by dateTimeCallback().
  715. *
  716. * \return true for success or false for failure.
  717. */
  718. bool timestamp(uint8_t flags, uint16_t year, uint8_t month, uint8_t day,
  719. uint8_t hour, uint8_t minute, uint8_t second);
  720. /** Truncate a file at the current file position.
  721. * will be maintained if it is less than or equal to \a length otherwise
  722. * it will be set to end of file.
  723. *
  724. * \return true for success or false for failure.
  725. */
  726. bool truncate();
  727. /** Truncate a file to a specified length. The current file position
  728. * will be set to end of file.
  729. *
  730. * \param[in] length The desired length for the file.
  731. *
  732. * \return true for success or false for failure.
  733. */
  734. bool truncate(uint64_t length) {
  735. return seekSet(length) && truncate();
  736. }
  737. /** \return The valid number of bytes in a file. */
  738. uint64_t validLength() const {return m_validLength;}
  739. /** Write a string to a file. Used by the Arduino Print class.
  740. * \param[in] str Pointer to the string.
  741. * Use getWriteError to check for errors.
  742. * \return count of characters written for success or -1 for failure.
  743. */
  744. size_t write(const char* str) {
  745. return write(str, strlen(str));
  746. }
  747. /** Write a single byte.
  748. * \param[in] b The byte to be written.
  749. * \return +1 for success or zero for failure.
  750. */
  751. size_t write(uint8_t b) {return write(&b, 1);}
  752. /** Write data to an open file.
  753. *
  754. * \note Data is moved to the cache but may not be written to the
  755. * storage device until sync() is called.
  756. *
  757. * \param[in] buf Pointer to the location of the data to be written.
  758. *
  759. * \param[in] count Number of bytes to write.
  760. *
  761. * \return For success write() returns the number of bytes written, always
  762. * \a count. If an error occurs, write() returns zero and writeError is set.
  763. */
  764. size_t write(const void* buf, size_t count);
  765. //------------------------------------------------------------------------------
  766. #if ENABLE_ARDUINO_SERIAL
  767. /** List directory contents.
  768. *
  769. * \param[in] flags The inclusive OR of
  770. *
  771. * LS_DATE - %Print file modification date
  772. *
  773. * LS_SIZE - %Print file size.
  774. *
  775. * LS_R - Recursive list of subdirectories.
  776. *
  777. * \return true for success or false for failure.
  778. */
  779. bool ls(uint8_t flags = 0) {
  780. return ls(&Serial, flags);
  781. }
  782. /** Print a file's name.
  783. *
  784. * \return length for success or zero for failure.
  785. */
  786. size_t printName() {
  787. return ExFatFile::printName(&Serial);
  788. }
  789. #endif // ENABLE_ARDUINO_SERIAL
  790. private:
  791. /** ExFatVolume allowed access to private members. */
  792. friend class ExFatVolume;
  793. bool addCluster();
  794. bool addDirCluster();
  795. bool cmpName(const DirName_t* dirName, ExName_t* fname);
  796. uint8_t* dirCache(uint8_t set, uint8_t options);
  797. bool hashName(ExName_t* fname);
  798. bool mkdir(ExFatFile* parent, ExName_t* fname);
  799. bool openPrivate(ExFatFile* dir, ExName_t* fname, oflag_t oflag);
  800. bool parsePathName(const char* path,
  801. ExName_t* fname, const char** ptr);
  802. ExFatVolume* volume() const {return m_vol;}
  803. bool syncDir();
  804. //----------------------------------------------------------------------------
  805. static const uint8_t WRITE_ERROR = 0X1;
  806. static const uint8_t READ_ERROR = 0X2;
  807. /** This file has not been opened. */
  808. static const uint8_t FILE_ATTR_CLOSED = 0;
  809. /** Entry for normal data file */
  810. static const uint8_t FILE_ATTR_FILE = 0X08;
  811. /** Entry is for a subdirectory */
  812. static const uint8_t FILE_ATTR_SUBDIR = FS_ATTRIB_DIRECTORY;
  813. /** Root directory */
  814. static const uint8_t FILE_ATTR_ROOT = 0X40;
  815. /** Directory type bits */
  816. static const uint8_t FILE_ATTR_DIR = FILE_ATTR_SUBDIR | FILE_ATTR_ROOT;
  817. static const uint8_t FILE_FLAG_READ = 0X01;
  818. static const uint8_t FILE_FLAG_WRITE = 0X02;
  819. static const uint8_t FILE_FLAG_APPEND = 0X08;
  820. static const uint8_t FILE_FLAG_CONTIGUOUS = 0X40;
  821. static const uint8_t FILE_FLAG_DIR_DIRTY = 0X80;
  822. uint64_t m_curPosition;
  823. uint64_t m_dataLength;
  824. uint64_t m_validLength;
  825. uint32_t m_curCluster;
  826. uint32_t m_firstCluster;
  827. ExFatVolume* m_vol;
  828. DirPos_t m_dirPos;
  829. uint8_t m_setCount;
  830. uint8_t m_attributes = FILE_ATTR_CLOSED;
  831. uint8_t m_error = 0;
  832. uint8_t m_flags = 0;
  833. };
  834. #include "../common/ArduinoFiles.h"
  835. /**
  836. * \class ExFile
  837. * \brief exFAT file with Arduino Stream.
  838. */
  839. class ExFile : public StreamFile<ExFatFile, uint64_t> {
  840. public:
  841. /** Opens the next file or folder in a directory.
  842. *
  843. * \param[in] oflag open flags.
  844. * \return a FatStream object.
  845. */
  846. ExFile openNextFile(oflag_t oflag = O_RDONLY) {
  847. ExFile tmpFile;
  848. tmpFile.openNext(this, oflag);
  849. return tmpFile;
  850. }
  851. };
  852. #endif // ExFatFile_h