SdBaseFile.h

changeset 0
2c8ba1964db7
equal deleted inserted replaced
-1:000000000000 0:2c8ba1964db7
1 /* Arduino SdFat Library
2 * Copyright (C) 2009 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 "Marlin.h"
21 #ifdef SDSUPPORT
22
23 #ifndef SdBaseFile_h
24 #define SdBaseFile_h
25 /**
26 * \file
27 * \brief SdBaseFile class
28 */
29 #include "Marlin.h"
30 #include "SdFatConfig.h"
31 #include "SdVolume.h"
32 //------------------------------------------------------------------------------
33 /**
34 * \struct fpos_t
35 * \brief internal type for istream
36 * do not use in user apps
37 */
38 struct fpos_t {
39 /** stream position */
40 uint32_t position;
41 /** cluster for position */
42 uint32_t cluster;
43 fpos_t() : position(0), cluster(0) {}
44 };
45
46 // use the gnu style oflag in open()
47 /** open() oflag for reading */
48 uint8_t const O_READ = 0X01;
49 /** open() oflag - same as O_IN */
50 uint8_t const O_RDONLY = O_READ;
51 /** open() oflag for write */
52 uint8_t const O_WRITE = 0X02;
53 /** open() oflag - same as O_WRITE */
54 uint8_t const O_WRONLY = O_WRITE;
55 /** open() oflag for reading and writing */
56 uint8_t const O_RDWR = (O_READ | O_WRITE);
57 /** open() oflag mask for access modes */
58 uint8_t const O_ACCMODE = (O_READ | O_WRITE);
59 /** The file offset shall be set to the end of the file prior to each write. */
60 uint8_t const O_APPEND = 0X04;
61 /** synchronous writes - call sync() after each write */
62 uint8_t const O_SYNC = 0X08;
63 /** truncate the file to zero length */
64 uint8_t const O_TRUNC = 0X10;
65 /** set the initial position at the end of the file */
66 uint8_t const O_AT_END = 0X20;
67 /** create the file if nonexistent */
68 uint8_t const O_CREAT = 0X40;
69 /** If O_CREAT and O_EXCL are set, open() shall fail if the file exists */
70 uint8_t const O_EXCL = 0X80;
71
72 // SdBaseFile class static and const definitions
73 // flags for ls()
74 /** ls() flag to print modify date */
75 uint8_t const LS_DATE = 1;
76 /** ls() flag to print file size */
77 uint8_t const LS_SIZE = 2;
78 /** ls() flag for recursive list of subdirectories */
79 uint8_t const LS_R = 4;
80
81
82 // flags for timestamp
83 /** set the file's last access date */
84 uint8_t const T_ACCESS = 1;
85 /** set the file's creation date and time */
86 uint8_t const T_CREATE = 2;
87 /** Set the file's write date and time */
88 uint8_t const T_WRITE = 4;
89 // values for type_
90 /** This file has not been opened. */
91 uint8_t const FAT_FILE_TYPE_CLOSED = 0;
92 /** A normal file */
93 uint8_t const FAT_FILE_TYPE_NORMAL = 1;
94 /** A FAT12 or FAT16 root directory */
95 uint8_t const FAT_FILE_TYPE_ROOT_FIXED = 2;
96 /** A FAT32 root directory */
97 uint8_t const FAT_FILE_TYPE_ROOT32 = 3;
98 /** A subdirectory file*/
99 uint8_t const FAT_FILE_TYPE_SUBDIR = 4;
100 /** Test value for directory type */
101 uint8_t const FAT_FILE_TYPE_MIN_DIR = FAT_FILE_TYPE_ROOT_FIXED;
102
103 /** date field for FAT directory entry
104 * \param[in] year [1980,2107]
105 * \param[in] month [1,12]
106 * \param[in] day [1,31]
107 *
108 * \return Packed date for dir_t entry.
109 */
110 static inline uint16_t FAT_DATE(uint16_t year, uint8_t month, uint8_t day) {
111 return (year - 1980) << 9 | month << 5 | day;
112 }
113 /** year part of FAT directory date field
114 * \param[in] fatDate Date in packed dir format.
115 *
116 * \return Extracted year [1980,2107]
117 */
118 static inline uint16_t FAT_YEAR(uint16_t fatDate) {
119 return 1980 + (fatDate >> 9);
120 }
121 /** month part of FAT directory date field
122 * \param[in] fatDate Date in packed dir format.
123 *
124 * \return Extracted month [1,12]
125 */
126 static inline uint8_t FAT_MONTH(uint16_t fatDate) {
127 return (fatDate >> 5) & 0XF;
128 }
129 /** day part of FAT directory date field
130 * \param[in] fatDate Date in packed dir format.
131 *
132 * \return Extracted day [1,31]
133 */
134 static inline uint8_t FAT_DAY(uint16_t fatDate) {
135 return fatDate & 0X1F;
136 }
137 /** time field for FAT directory entry
138 * \param[in] hour [0,23]
139 * \param[in] minute [0,59]
140 * \param[in] second [0,59]
141 *
142 * \return Packed time for dir_t entry.
143 */
144 static inline uint16_t FAT_TIME(uint8_t hour, uint8_t minute, uint8_t second) {
145 return hour << 11 | minute << 5 | second >> 1;
146 }
147 /** hour part of FAT directory time field
148 * \param[in] fatTime Time in packed dir format.
149 *
150 * \return Extracted hour [0,23]
151 */
152 static inline uint8_t FAT_HOUR(uint16_t fatTime) {
153 return fatTime >> 11;
154 }
155 /** minute part of FAT directory time field
156 * \param[in] fatTime Time in packed dir format.
157 *
158 * \return Extracted minute [0,59]
159 */
160 static inline uint8_t FAT_MINUTE(uint16_t fatTime) {
161 return(fatTime >> 5) & 0X3F;
162 }
163 /** second part of FAT directory time field
164 * Note second/2 is stored in packed time.
165 *
166 * \param[in] fatTime Time in packed dir format.
167 *
168 * \return Extracted second [0,58]
169 */
170 static inline uint8_t FAT_SECOND(uint16_t fatTime) {
171 return 2*(fatTime & 0X1F);
172 }
173 /** Default date for file timestamps is 1 Jan 2000 */
174 uint16_t const FAT_DEFAULT_DATE = ((2000 - 1980) << 9) | (1 << 5) | 1;
175 /** Default time for file timestamp is 1 am */
176 uint16_t const FAT_DEFAULT_TIME = (1 << 11);
177 //------------------------------------------------------------------------------
178 /**
179 * \class SdBaseFile
180 * \brief Base class for SdFile with Print and C++ streams.
181 */
182 class SdBaseFile {
183 public:
184 /** Create an instance. */
185 SdBaseFile() : writeError(false), type_(FAT_FILE_TYPE_CLOSED) {}
186 SdBaseFile(const char* path, uint8_t oflag);
187 ~SdBaseFile() {if(isOpen()) close();}
188 /**
189 * writeError is set to true if an error occurs during a write().
190 * Set writeError to false before calling print() and/or write() and check
191 * for true after calls to print() and/or write().
192 */
193 bool writeError;
194 //----------------------------------------------------------------------------
195 // helpers for stream classes
196 /** get position for streams
197 * \param[out] pos struct to receive position
198 */
199 void getpos(fpos_t* pos);
200 /** set position for streams
201 * \param[out] pos struct with value for new position
202 */
203 void setpos(fpos_t* pos);
204 //----------------------------------------------------------------------------
205 bool close();
206 bool contiguousRange(uint32_t* bgnBlock, uint32_t* endBlock);
207 bool createContiguous(SdBaseFile* dirFile,
208 const char* path, uint32_t size);
209 /** \return The current cluster number for a file or directory. */
210 uint32_t curCluster() const {return curCluster_;}
211 /** \return The current position for a file or directory. */
212 uint32_t curPosition() const {return curPosition_;}
213 /** \return Current working directory */
214 static SdBaseFile* cwd() {return cwd_;}
215 /** Set the date/time callback function
216 *
217 * \param[in] dateTime The user's call back function. The callback
218 * function is of the form:
219 *
220 * \code
221 * void dateTime(uint16_t* date, uint16_t* time) {
222 * uint16_t year;
223 * uint8_t month, day, hour, minute, second;
224 *
225 * // User gets date and time from GPS or real-time clock here
226 *
227 * // return date using FAT_DATE macro to format fields
228 * *date = FAT_DATE(year, month, day);
229 *
230 * // return time using FAT_TIME macro to format fields
231 * *time = FAT_TIME(hour, minute, second);
232 * }
233 * \endcode
234 *
235 * Sets the function that is called when a file is created or when
236 * a file's directory entry is modified by sync(). All timestamps,
237 * access, creation, and modify, are set when a file is created.
238 * sync() maintains the last access date and last modify date/time.
239 *
240 * See the timestamp() function.
241 */
242 static void dateTimeCallback(
243 void (*dateTime)(uint16_t* date, uint16_t* time)) {
244 dateTime_ = dateTime;
245 }
246 /** Cancel the date/time callback function. */
247 static void dateTimeCallbackCancel() {dateTime_ = 0;}
248 bool dirEntry(dir_t* dir);
249 static void dirName(const dir_t& dir, char* name);
250 bool exists(const char* name);
251 int16_t fgets(char* str, int16_t num, char* delim = 0);
252 /** \return The total number of bytes in a file or directory. */
253 uint32_t fileSize() const {return fileSize_;}
254 /** \return The first cluster number for a file or directory. */
255 uint32_t firstCluster() const {return firstCluster_;}
256 bool getFilename(char* name);
257 /** \return True if this is a directory else false. */
258 bool isDir() const {return type_ >= FAT_FILE_TYPE_MIN_DIR;}
259 /** \return True if this is a normal file else false. */
260 bool isFile() const {return type_ == FAT_FILE_TYPE_NORMAL;}
261 /** \return True if this is an open file/directory else false. */
262 bool isOpen() const {return type_ != FAT_FILE_TYPE_CLOSED;}
263 /** \return True if this is a subdirectory else false. */
264 bool isSubDir() const {return type_ == FAT_FILE_TYPE_SUBDIR;}
265 /** \return True if this is the root directory. */
266 bool isRoot() const {
267 return type_ == FAT_FILE_TYPE_ROOT_FIXED || type_ == FAT_FILE_TYPE_ROOT32;
268 }
269 void ls( uint8_t flags = 0, uint8_t indent = 0);
270 bool mkdir(SdBaseFile* dir, const char* path, bool pFlag = true);
271 // alias for backward compactability
272 bool makeDir(SdBaseFile* dir, const char* path) {
273 return mkdir(dir, path, false);
274 }
275 bool open(SdBaseFile* dirFile, uint16_t index, uint8_t oflag);
276 bool open(SdBaseFile* dirFile, const char* path, uint8_t oflag);
277 bool open(const char* path, uint8_t oflag = O_READ);
278 bool openNext(SdBaseFile* dirFile, uint8_t oflag);
279 bool openRoot(SdVolume* vol);
280 int peek();
281 static void printFatDate(uint16_t fatDate);
282 static void printFatTime( uint16_t fatTime);
283 bool printName();
284 int16_t read();
285 int16_t read(void* buf, uint16_t nbyte);
286 int8_t readDir(dir_t* dir);
287 static bool remove(SdBaseFile* dirFile, const char* path);
288 bool remove();
289 /** Set the file's current position to zero. */
290 void rewind() {seekSet(0);}
291 bool rename(SdBaseFile* dirFile, const char* newPath);
292 bool rmdir();
293 // for backward compatibility
294 bool rmDir() {return rmdir();}
295 bool rmRfStar();
296 /** Set the files position to current position + \a pos. See seekSet().
297 * \param[in] offset The new position in bytes from the current position.
298 * \return true for success or false for failure.
299 */
300 bool seekCur(int32_t offset) {
301 return seekSet(curPosition_ + offset);
302 }
303 /** Set the files position to end-of-file + \a offset. See seekSet().
304 * \param[in] offset The new position in bytes from end-of-file.
305 * \return true for success or false for failure.
306 */
307 bool seekEnd(int32_t offset = 0) {return seekSet(fileSize_ + offset);}
308 bool seekSet(uint32_t pos);
309 bool sync();
310 bool timestamp(SdBaseFile* file);
311 bool timestamp(uint8_t flag, uint16_t year, uint8_t month, uint8_t day,
312 uint8_t hour, uint8_t minute, uint8_t second);
313 /** Type of file. You should use isFile() or isDir() instead of type()
314 * if possible.
315 *
316 * \return The file or directory type.
317 */
318 uint8_t type() const {return type_;}
319 bool truncate(uint32_t size);
320 /** \return SdVolume that contains this file. */
321 SdVolume* volume() const {return vol_;}
322 int16_t write(const void* buf, uint16_t nbyte);
323 //------------------------------------------------------------------------------
324 private:
325 // allow SdFat to set cwd_
326 friend class SdFat;
327 // global pointer to cwd dir
328 static SdBaseFile* cwd_;
329 // data time callback function
330 static void (*dateTime_)(uint16_t* date, uint16_t* time);
331 // bits defined in flags_
332 // should be 0X0F
333 static uint8_t const F_OFLAG = (O_ACCMODE | O_APPEND | O_SYNC);
334 // sync of directory entry required
335 static uint8_t const F_FILE_DIR_DIRTY = 0X80;
336
337 // private data
338 uint8_t flags_; // See above for definition of flags_ bits
339 uint8_t fstate_; // error and eof indicator
340 uint8_t type_; // type of file see above for values
341 uint32_t curCluster_; // cluster for current file position
342 uint32_t curPosition_; // current file position in bytes from beginning
343 uint32_t dirBlock_; // block for this files directory entry
344 uint8_t dirIndex_; // index of directory entry in dirBlock
345 uint32_t fileSize_; // file size in bytes
346 uint32_t firstCluster_; // first cluster of file
347 SdVolume* vol_; // volume where file is located
348
349 /** experimental don't use */
350 bool openParent(SdBaseFile* dir);
351 // private functions
352 bool addCluster();
353 bool addDirCluster();
354 dir_t* cacheDirEntry(uint8_t action);
355 int8_t lsPrintNext( uint8_t flags, uint8_t indent);
356 static bool make83Name(const char* str, uint8_t* name, const char** ptr);
357 bool mkdir(SdBaseFile* parent, const uint8_t dname[11]);
358 bool open(SdBaseFile* dirFile, const uint8_t dname[11], uint8_t oflag);
359 bool openCachedEntry(uint8_t cacheIndex, uint8_t oflags);
360 dir_t* readDirCache();
361 //------------------------------------------------------------------------------
362 // to be deleted
363 static void printDirName( const dir_t& dir,
364 uint8_t width, bool printSlash);
365 //------------------------------------------------------------------------------
366 // Deprecated functions - suppress cpplint warnings with NOLINT comment
367 #if ALLOW_DEPRECATED_FUNCTIONS && !defined(DOXYGEN)
368 public:
369 /** \deprecated Use:
370 * bool contiguousRange(uint32_t* bgnBlock, uint32_t* endBlock);
371 * \param[out] bgnBlock the first block address for the file.
372 * \param[out] endBlock the last block address for the file.
373 * \return true for success or false for failure.
374 */
375 bool contiguousRange(uint32_t& bgnBlock, uint32_t& endBlock) { // NOLINT
376 return contiguousRange(&bgnBlock, &endBlock);
377 }
378 /** \deprecated Use:
379 * bool createContiguous(SdBaseFile* dirFile,
380 * const char* path, uint32_t size)
381 * \param[in] dirFile The directory where the file will be created.
382 * \param[in] path A path with a valid DOS 8.3 file name.
383 * \param[in] size The desired file size.
384 * \return true for success or false for failure.
385 */
386 bool createContiguous(SdBaseFile& dirFile, // NOLINT
387 const char* path, uint32_t size) {
388 return createContiguous(&dirFile, path, size);
389 }
390 /** \deprecated Use:
391 * static void dateTimeCallback(
392 * void (*dateTime)(uint16_t* date, uint16_t* time));
393 * \param[in] dateTime The user's call back function.
394 */
395 static void dateTimeCallback(
396 void (*dateTime)(uint16_t& date, uint16_t& time)) { // NOLINT
397 oldDateTime_ = dateTime;
398 dateTime_ = dateTime ? oldToNew : 0;
399 }
400 /** \deprecated Use: bool dirEntry(dir_t* dir);
401 * \param[out] dir Location for return of the file's directory entry.
402 * \return true for success or false for failure.
403 */
404 bool dirEntry(dir_t& dir) {return dirEntry(&dir);} // NOLINT
405 /** \deprecated Use:
406 * bool mkdir(SdBaseFile* dir, const char* path);
407 * \param[in] dir An open SdFat instance for the directory that will contain
408 * the new directory.
409 * \param[in] path A path with a valid 8.3 DOS name for the new directory.
410 * \return true for success or false for failure.
411 */
412 bool mkdir(SdBaseFile& dir, const char* path) { // NOLINT
413 return mkdir(&dir, path);
414 }
415 /** \deprecated Use:
416 * bool open(SdBaseFile* dirFile, const char* path, uint8_t oflag);
417 * \param[in] dirFile An open SdFat instance for the directory containing the
418 * file to be opened.
419 * \param[in] path A path with a valid 8.3 DOS name for the file.
420 * \param[in] oflag Values for \a oflag are constructed by a bitwise-inclusive
421 * OR of flags O_READ, O_WRITE, O_TRUNC, and O_SYNC.
422 * \return true for success or false for failure.
423 */
424 bool open(SdBaseFile& dirFile, // NOLINT
425 const char* path, uint8_t oflag) {
426 return open(&dirFile, path, oflag);
427 }
428 /** \deprecated Do not use in new apps
429 * \param[in] dirFile An open SdFat instance for the directory containing the
430 * file to be opened.
431 * \param[in] path A path with a valid 8.3 DOS name for a file to be opened.
432 * \return true for success or false for failure.
433 */
434 bool open(SdBaseFile& dirFile, const char* path) { // NOLINT
435 return open(dirFile, path, O_RDWR);
436 }
437 /** \deprecated Use:
438 * bool open(SdBaseFile* dirFile, uint16_t index, uint8_t oflag);
439 * \param[in] dirFile An open SdFat instance for the directory.
440 * \param[in] index The \a index of the directory entry for the file to be
441 * opened. The value for \a index is (directory file position)/32.
442 * \param[in] oflag Values for \a oflag are constructed by a bitwise-inclusive
443 * OR of flags O_READ, O_WRITE, O_TRUNC, and O_SYNC.
444 * \return true for success or false for failure.
445 */
446 bool open(SdBaseFile& dirFile, uint16_t index, uint8_t oflag) { // NOLINT
447 return open(&dirFile, index, oflag);
448 }
449 /** \deprecated Use: bool openRoot(SdVolume* vol);
450 * \param[in] vol The FAT volume containing the root directory to be opened.
451 * \return true for success or false for failure.
452 */
453 bool openRoot(SdVolume& vol) {return openRoot(&vol);} // NOLINT
454 /** \deprecated Use: int8_t readDir(dir_t* dir);
455 * \param[out] dir The dir_t struct that will receive the data.
456 * \return bytes read for success zero for eof or -1 for failure.
457 */
458 int8_t readDir(dir_t& dir) {return readDir(&dir);} // NOLINT
459 /** \deprecated Use:
460 * static uint8_t remove(SdBaseFile* dirFile, const char* path);
461 * \param[in] dirFile The directory that contains the file.
462 * \param[in] path The name of the file to be removed.
463 * \return true for success or false for failure.
464 */
465 static bool remove(SdBaseFile& dirFile, const char* path) { // NOLINT
466 return remove(&dirFile, path);
467 }
468 //------------------------------------------------------------------------------
469 // rest are private
470 private:
471 static void (*oldDateTime_)(uint16_t& date, uint16_t& time); // NOLINT
472 static void oldToNew(uint16_t* date, uint16_t* time) {
473 uint16_t d;
474 uint16_t t;
475 oldDateTime_(d, t);
476 *date = d;
477 *time = t;
478 }
479 #endif // ALLOW_DEPRECATED_FUNCTIONS
480 };
481
482 #endif // SdBaseFile_h
483 #endif

mercurial