Jackson Lv / utility

Dependents:   SD

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers SdFile.cpp Source File

SdFile.cpp

00001 /* Arduino SdFat Library
00002  * Copyright (C) 2009 by William Greiman
00003  *
00004  * This file is part of the Arduino SdFat Library
00005  *
00006  * This Library is free software: you can redistribute it and/or modify
00007  * it under the terms of the GNU General Public License as published by
00008  * the Free Software Foundation, either version 3 of the License, or
00009  * (at your option) any later version.
00010  *
00011  * This Library is distributed in the hope that it will be useful,
00012  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014  * GNU General Public License for more details.
00015  *
00016  * You should have received a copy of the GNU General Public License
00017  * along with the Arduino SdFat Library.  If not, see
00018  * <http://www.gnu.org/licenses/>.
00019  */
00020 #include <SdFat.h>
00021 #include "mbed.h"
00022 
00023 //------------------------------------------------------------------------------
00024 // callback function for date/time
00025 void (*SdFile::dateTime_)(uint16_t* date, uint16_t* time) = NULL;
00026 
00027 #if ALLOW_DEPRECATED_FUNCTIONS
00028 // suppress cpplint warnings with NOLINT comment
00029 void (*SdFile::oldDateTime_)(uint16_t& date, uint16_t& time) = NULL;  // NOLINT
00030 #endif  // ALLOW_DEPRECATED_FUNCTIONS
00031 //------------------------------------------------------------------------------
00032 // add a cluster to a file
00033 uint8_t SdFile::addCluster() {
00034   if (!vol_->allocContiguous(1, &curCluster_)) return false;
00035 
00036   // if first cluster of file link to directory entry
00037   if (firstCluster_ == 0) {
00038     firstCluster_ = curCluster_;
00039     flags_ |= F_FILE_DIR_DIRTY;
00040   }
00041   return true;
00042 }
00043 //------------------------------------------------------------------------------
00044 // Add a cluster to a directory file and zero the cluster.
00045 // return with first block of cluster in the cache
00046 uint8_t SdFile::addDirCluster(void) {
00047   if (!addCluster()) return false;
00048 
00049   // zero data in cluster insure first cluster is in cache
00050   uint32_t block = vol_->clusterStartBlock(curCluster_);
00051   for (uint8_t i = vol_->blocksPerCluster_; i != 0; i--) {
00052     if (!SdVolume::cacheZeroBlock(block + i - 1)) return false;
00053   }
00054   // Increase directory file size by cluster size
00055   fileSize_ += 512UL << vol_->clusterSizeShift_;
00056   return true;
00057 }
00058 //------------------------------------------------------------------------------
00059 // cache a file's directory entry
00060 // return pointer to cached entry or null for failure
00061 dir_t* SdFile::cacheDirEntry(uint8_t action) {
00062   if (!SdVolume::cacheRawBlock(dirBlock_, action)) return NULL;
00063   return SdVolume::cacheBuffer_.dir + dirIndex_;
00064 }
00065 //------------------------------------------------------------------------------
00066 /**
00067  *  Close a file and force cached data and directory information
00068  *  to be written to the storage device.
00069  *
00070  * \return The value one, true, is returned for success and
00071  * the value zero, false, is returned for failure.
00072  * Reasons for failure include no file is open or an I/O error.
00073  */
00074 uint8_t SdFile::close(void) {
00075   if (!sync())return false;
00076   type_ = FAT_FILE_TYPE_CLOSED;
00077   return true;
00078 }
00079 //------------------------------------------------------------------------------
00080 /**
00081  * Check for contiguous file and return its raw block range.
00082  *
00083  * \param[out] bgnBlock the first block address for the file.
00084  * \param[out] endBlock the last  block address for the file.
00085  *
00086  * \return The value one, true, is returned for success and
00087  * the value zero, false, is returned for failure.
00088  * Reasons for failure include file is not contiguous, file has zero length
00089  * or an I/O error occurred.
00090  */
00091 uint8_t SdFile::contiguousRange(uint32_t* bgnBlock, uint32_t* endBlock) {
00092   // error if no blocks
00093   if (firstCluster_ == 0) return false;
00094 
00095   for (uint32_t c = firstCluster_; ; c++) {
00096     uint32_t next;
00097     if (!vol_->fatGet(c, &next)) return false;
00098 
00099     // check for contiguous
00100     if (next != (c + 1)) {
00101       // error if not end of chain
00102       if (!vol_->isEOC(next)) return false;
00103       *bgnBlock = vol_->clusterStartBlock(firstCluster_);
00104       *endBlock = vol_->clusterStartBlock(c)
00105                   + vol_->blocksPerCluster_ - 1;
00106       return true;
00107     }
00108   }
00109 }
00110 //------------------------------------------------------------------------------
00111 /**
00112  * Create and open a new contiguous file of a specified size.
00113  *
00114  * \note This function only supports short DOS 8.3 names.
00115  * See open() for more information.
00116  *
00117  * \param[in] dirFile The directory where the file will be created.
00118  * \param[in] fileName A valid DOS 8.3 file name.
00119  * \param[in] size The desired file size.
00120  *
00121  * \return The value one, true, is returned for success and
00122  * the value zero, false, is returned for failure.
00123  * Reasons for failure include \a fileName contains
00124  * an invalid DOS 8.3 file name, the FAT volume has not been initialized,
00125  * a file is already open, the file already exists, the root
00126  * directory is full or an I/O error.
00127  *
00128  */
00129 uint8_t SdFile::createContiguous(SdFile* dirFile,
00130         const char* fileName, uint32_t size) {
00131   // don't allow zero length file
00132   if (size == 0) return false;
00133   if (!open(dirFile, fileName, O_CREAT | O_EXCL | O_RDWR)) return false;
00134 
00135   // calculate number of clusters needed
00136   uint32_t count = ((size - 1) >> (vol_->clusterSizeShift_ + 9)) + 1;
00137 
00138   // allocate clusters
00139   if (!vol_->allocContiguous(count, &firstCluster_)) {
00140     remove();
00141     return false;
00142   }
00143   fileSize_ = size;
00144 
00145   // insure sync() will update dir entry
00146   flags_ |= F_FILE_DIR_DIRTY;
00147   return sync();
00148 }
00149 //------------------------------------------------------------------------------
00150 /**
00151  * Return a files directory entry
00152  *
00153  * \param[out] dir Location for return of the files directory entry.
00154  *
00155  * \return The value one, true, is returned for success and
00156  * the value zero, false, is returned for failure.
00157  */
00158 uint8_t SdFile::dirEntry(dir_t* dir) {
00159   // make sure fields on SD are correct
00160   if (!sync()) return false;
00161 
00162   // read entry
00163   dir_t* p = cacheDirEntry(SdVolume::CACHE_FOR_READ);
00164   if (!p) return false;
00165 
00166   // copy to caller's struct
00167   memcpy(dir, p, sizeof(dir_t));
00168   return true;
00169 }
00170 //------------------------------------------------------------------------------
00171 /**
00172  * Format the name field of \a dir into the 13 byte array
00173  * \a name in standard 8.3 short name format.
00174  *
00175  * \param[in] dir The directory structure containing the name.
00176  * \param[out] name A 13 byte char array for the formatted name.
00177  */
00178 void SdFile::dirName(const dir_t& dir, char* name) {
00179   uint8_t j = 0;
00180   for (uint8_t i = 0; i < 11; i++) {
00181     if (dir.name[i] == ' ')continue;
00182     if (i == 8) name[j++] = '.';
00183     name[j++] = dir.name[i];
00184   }
00185   name[j] = 0;
00186 }
00187 //------------------------------------------------------------------------------
00188 /** List directory contents to Serial.
00189  *
00190  * \param[in] flags The inclusive OR of
00191  *
00192  * LS_DATE - %Print file modification date
00193  *
00194  * LS_SIZE - %Print file size.
00195  *
00196  * LS_R - Recursive list of subdirectories.
00197  *
00198  * \param[in] indent Amount of space before file name. Used for recursive
00199  * list to indicate subdirectory level.
00200  */
00201 void SdFile::ls(uint8_t flags, uint8_t indent) {
00202   dir_t* p;
00203 
00204   rewind();
00205   while ((p = readDirCache())) {
00206     // done if past last used entry
00207     if (p->name[0] == DIR_NAME_FREE) break;
00208 
00209     // skip deleted entry and entries for . and  ..
00210     if (p->name[0] == DIR_NAME_DELETED || p->name[0] == '.') continue;
00211 
00212     // only list subdirectories and files
00213     if (!DIR_IS_FILE_OR_SUBDIR(p)) continue;
00214 
00215     // print any indent spaces
00216     for (int8_t i = 0; i < indent; i++) Serial.print(' ');
00217 
00218     // print file name with possible blank fill
00219     printDirName(*p, flags & (LS_DATE | LS_SIZE) ? 14 : 0);
00220 
00221     // print modify date/time if requested
00222     if (flags & LS_DATE) {
00223        printFatDate(p->lastWriteDate);
00224        Serial.putc(' ');
00225        printFatTime(p->lastWriteTime);
00226     }
00227     // print size if requested
00228     if (!DIR_IS_SUBDIR(p) && (flags & LS_SIZE)) {
00229       Serial.putc(' ');
00230       Serial.printf(p->fileSize);
00231     }
00232     Serial.putc('/n');
00233 
00234     // list subdirectory content if requested
00235     if ((flags & LS_R) && DIR_IS_SUBDIR(p)) {
00236       uint16_t index = curPosition ()/32 - 1;
00237       SdFile s;
00238       if (s.open(this, index, O_READ)) s.ls(flags, indent + 2);
00239       seekSet(32 * (index + 1));
00240     }
00241   }
00242 }
00243 //------------------------------------------------------------------------------
00244 // format directory name field from a 8.3 name string
00245 uint8_t SdFile::make83Name(const char* str, uint8_t* name) {
00246   uint8_t c;
00247   uint8_t n = 7;  // max index for part before dot
00248   uint8_t i = 0;
00249   // blank fill name and extension
00250   while (i < 11) name[i++] = ' ';
00251   i = 0;
00252   while ((c = *str++) != '\0') {
00253     if (c == '.') {
00254       if (n == 10) return false;  // only one dot allowed
00255       n = 10;  // max index for full 8.3 name
00256       i = 8;   // place for extension
00257     } else {
00258       // illegal FAT characters
00259       PGM_P p = PSTR("|<>^+=?/[];,*\"\\");
00260       uint8_t b;
00261       while ((b = pgm_read_byte(p++))) if (b == c) return false;
00262       // check size and only allow ASCII printable characters
00263       if (i > n || c < 0X21 || c > 0X7E)return false;
00264       // only upper case allowed in 8.3 names - convert lower to upper
00265       name[i++] = c < 'a' || c > 'z' ?  c : c + ('A' - 'a');
00266     }
00267   }
00268   // must have a file name, extension is optional
00269   return name[0] != ' ';
00270 }
00271 //------------------------------------------------------------------------------
00272 /** Make a new directory.
00273  *
00274  * \param[in] dir An open SdFat instance for the directory that will containing
00275  * the new directory.
00276  *
00277  * \param[in] dirName A valid 8.3 DOS name for the new directory.
00278  *
00279  * \return The value one, true, is returned for success and
00280  * the value zero, false, is returned for failure.
00281  * Reasons for failure include this SdFile is already open, \a dir is not a
00282  * directory, \a dirName is invalid or already exists in \a dir.
00283  */
00284 uint8_t SdFile::makeDir(SdFile* dir, const char* dirName) {
00285   dir_t d;
00286 
00287   // create a normal file
00288   if (!open(dir, dirName, O_CREAT | O_EXCL | O_RDWR)) return false;
00289 
00290   // convert SdFile to directory
00291   flags_ = O_READ;
00292   type_ = FAT_FILE_TYPE_SUBDIR;
00293 
00294   // allocate and zero first cluster
00295   if (!addDirCluster())return false;
00296 
00297   // force entry to SD
00298   if (!sync()) return false;
00299 
00300   // cache entry - should already be in cache due to sync() call
00301   dir_t* p = cacheDirEntry(SdVolume::CACHE_FOR_WRITE);
00302   if (!p) return false;
00303 
00304   // change directory entry  attribute
00305   p->attributes = DIR_ATT_DIRECTORY;
00306 
00307   // make entry for '.'
00308   memcpy(&d, p, sizeof(d));
00309   for (uint8_t i = 1; i < 11; i++) d.name[i] = ' ';
00310   d.name[0] = '.';
00311 
00312   // cache block for '.'  and '..'
00313   uint32_t block = vol_->clusterStartBlock(firstCluster_);
00314   if (!SdVolume::cacheRawBlock(block, SdVolume::CACHE_FOR_WRITE)) return false;
00315 
00316   // copy '.' to block
00317   memcpy(&SdVolume::cacheBuffer_.dir[0], &d, sizeof(d));
00318 
00319   // make entry for '..'
00320   d.name[1] = '.';
00321   if (dir->isRoot()) {
00322     d.firstClusterLow = 0;
00323     d.firstClusterHigh = 0;
00324   } else {
00325     d.firstClusterLow = dir->firstCluster_ & 0XFFFF;
00326     d.firstClusterHigh = dir->firstCluster_ >> 16;
00327   }
00328   // copy '..' to block
00329   memcpy(&SdVolume::cacheBuffer_.dir[1], &d, sizeof(d));
00330 
00331   // set position after '..'
00332   curPosition_ = 2 * sizeof(d);
00333 
00334   // write first block
00335   return SdVolume::cacheFlush();
00336 }
00337 //------------------------------------------------------------------------------
00338 /**
00339  * Open a file or directory by name.
00340  *
00341  * \param[in] dirFile An open SdFat instance for the directory containing the
00342  * file to be opened.
00343  *
00344  * \param[in] fileName A valid 8.3 DOS name for a file to be opened.
00345  *
00346  * \param[in] oflag Values for \a oflag are constructed by a bitwise-inclusive
00347  * OR of flags from the following list
00348  *
00349  * O_READ - Open for reading.
00350  *
00351  * O_RDONLY - Same as O_READ.
00352  *
00353  * O_WRITE - Open for writing.
00354  *
00355  * O_WRONLY - Same as O_WRITE.
00356  *
00357  * O_RDWR - Open for reading and writing.
00358  *
00359  * O_APPEND - If set, the file offset shall be set to the end of the
00360  * file prior to each write.
00361  *
00362  * O_CREAT - If the file exists, this flag has no effect except as noted
00363  * under O_EXCL below. Otherwise, the file shall be created
00364  *
00365  * O_EXCL - If O_CREAT and O_EXCL are set, open() shall fail if the file exists.
00366  *
00367  * O_SYNC - Call sync() after each write.  This flag should not be used with
00368  * write(uint8_t), write_P(PGM_P), writeln_P(PGM_P), or the Arduino Print class.
00369  * These functions do character at a time writes so sync() will be called
00370  * after each byte.
00371  *
00372  * O_TRUNC - If the file exists and is a regular file, and the file is
00373  * successfully opened and is not read only, its length shall be truncated to 0.
00374  *
00375  * \note Directory files must be opened read only.  Write and truncation is
00376  * not allowed for directory files.
00377  *
00378  * \return The value one, true, is returned for success and
00379  * the value zero, false, is returned for failure.
00380  * Reasons for failure include this SdFile is already open, \a difFile is not
00381  * a directory, \a fileName is invalid, the file does not exist
00382  * or can't be opened in the access mode specified by oflag.
00383  */
00384 uint8_t SdFile::open(SdFile* dirFile, const char* fileName, uint8_t oflag) {
00385   uint8_t dname[11];
00386   dir_t* p;
00387 
00388   // error if already open
00389   if (isOpen ())return false;
00390 
00391   if (!make83Name(fileName, dname)) return false;
00392   vol_ = dirFile->vol_;
00393   dirFile->rewind();
00394 
00395   // bool for empty entry found
00396   uint8_t emptyFound = false;
00397 
00398   // search for file
00399   while (dirFile->curPosition_ < dirFile->fileSize_) {
00400     uint8_t index = 0XF & (dirFile->curPosition_ >> 5);
00401     p = dirFile->readDirCache();
00402     if (p == NULL) return false;
00403 
00404     if (p->name[0] == DIR_NAME_FREE || p->name[0] == DIR_NAME_DELETED) {
00405       // remember first empty slot
00406       if (!emptyFound) {
00407         emptyFound = true;
00408         dirIndex_ = index;
00409         dirBlock_ = SdVolume::cacheBlockNumber_;
00410       }
00411       // done if no entries follow
00412       if (p->name[0] == DIR_NAME_FREE) break;
00413     } else if (!memcmp(dname, p->name, 11)) {
00414       // don't open existing file if O_CREAT and O_EXCL
00415       if ((oflag & (O_CREAT | O_EXCL)) == (O_CREAT | O_EXCL)) return false;
00416 
00417       // open found file
00418       return openCachedEntry(0XF & index, oflag);
00419     }
00420   }
00421   // only create file if O_CREAT and O_WRITE
00422   if ((oflag & (O_CREAT | O_WRITE)) != (O_CREAT | O_WRITE)) return false;
00423 
00424   // cache found slot or add cluster if end of file
00425   if (emptyFound) {
00426     p = cacheDirEntry(SdVolume::CACHE_FOR_WRITE);
00427     if (!p) return false;
00428   } else {
00429     if (dirFile->type_ == FAT_FILE_TYPE_ROOT16) return false;
00430 
00431     // add and zero cluster for dirFile - first cluster is in cache for write
00432     if (!dirFile->addDirCluster()) return false;
00433 
00434     // use first entry in cluster
00435     dirIndex_ = 0;
00436     p = SdVolume::cacheBuffer_.dir;
00437   }
00438   // initialize as empty file
00439   memset(p, 0, sizeof(dir_t));
00440   memcpy(p->name, dname, 11);
00441 
00442   // set timestamps
00443   if (dateTime_) {
00444     // call user function
00445     dateTime_(&p->creationDate, &p->creationTime);
00446   } else {
00447     // use default date/time
00448     p->creationDate = FAT_DEFAULT_DATE;
00449     p->creationTime = FAT_DEFAULT_TIME;
00450   }
00451   p->lastAccessDate = p->creationDate;
00452   p->lastWriteDate = p->creationDate;
00453   p->lastWriteTime = p->creationTime;
00454 
00455   // force write of entry to SD
00456   if (!SdVolume::cacheFlush()) return false;
00457 
00458   // open entry in cache
00459   return openCachedEntry(dirIndex_, oflag);
00460 }
00461 //------------------------------------------------------------------------------
00462 /**
00463  * Open a file by index.
00464  *
00465  * \param[in] dirFile An open SdFat instance for the directory.
00466  *
00467  * \param[in] index The \a index of the directory entry for the file to be
00468  * opened.  The value for \a index is (directory file position)/32.
00469  *
00470  * \param[in] oflag Values for \a oflag are constructed by a bitwise-inclusive
00471  * OR of flags O_READ, O_WRITE, O_TRUNC, and O_SYNC.
00472  *
00473  * See open() by fileName for definition of flags and return values.
00474  *
00475  */
00476 uint8_t SdFile::open(SdFile* dirFile, uint16_t index, uint8_t oflag) {
00477   // error if already open
00478   if (isOpen ())return false;
00479 
00480   // don't open existing file if O_CREAT and O_EXCL - user call error
00481   if ((oflag & (O_CREAT | O_EXCL)) == (O_CREAT | O_EXCL)) return false;
00482 
00483   vol_ = dirFile->vol_;
00484 
00485   // seek to location of entry
00486   if (!dirFile->seekSet(32 * index)) return false;
00487 
00488   // read entry into cache
00489   dir_t* p = dirFile->readDirCache();
00490   if (p == NULL) return false;
00491 
00492   // error if empty slot or '.' or '..'
00493   if (p->name[0] == DIR_NAME_FREE ||
00494       p->name[0] == DIR_NAME_DELETED || p->name[0] == '.') {
00495     return false;
00496   }
00497   // open cached entry
00498   return openCachedEntry(index & 0XF, oflag);
00499 }
00500 //------------------------------------------------------------------------------
00501 // open a cached directory entry. Assumes vol_ is initializes
00502 uint8_t SdFile::openCachedEntry(uint8_t dirIndex , uint8_t oflag) {
00503   // location of entry in cache
00504   dir_t* p = SdVolume::cacheBuffer_.dir + dirIndex ;
00505 
00506   // write or truncate is an error for a directory or read-only file
00507   if (p->attributes & (DIR_ATT_READ_ONLY | DIR_ATT_DIRECTORY)) {
00508     if (oflag & (O_WRITE | O_TRUNC)) return false;
00509   }
00510   // remember location of directory entry on SD
00511   dirIndex_ = dirIndex ;
00512   dirBlock_ = SdVolume::cacheBlockNumber_;
00513 
00514   // copy first cluster number for directory fields
00515   firstCluster_ = (uint32_t)p->firstClusterHigh << 16;
00516   firstCluster_ |= p->firstClusterLow;
00517 
00518   // make sure it is a normal file or subdirectory
00519   if (DIR_IS_FILE(p)) {
00520     fileSize_ = p->fileSize;
00521     type_ = FAT_FILE_TYPE_NORMAL;
00522   } else if (DIR_IS_SUBDIR(p)) {
00523     if (!vol_->chainSize(firstCluster_, &fileSize_)) return false;
00524     type_ = FAT_FILE_TYPE_SUBDIR;
00525   } else {
00526     return false;
00527   }
00528   // save open flags for read/write
00529   flags_ = oflag & (O_ACCMODE | O_SYNC | O_APPEND);
00530 
00531   // set to start of file
00532   curCluster_ = 0;
00533   curPosition_ = 0;
00534 
00535   // truncate file to zero length if requested
00536   if (oflag & O_TRUNC) return truncate(0);
00537   return true;
00538 }
00539 //------------------------------------------------------------------------------
00540 /**
00541  * Open a volume's root directory.
00542  *
00543  * \param[in] vol The FAT volume containing the root directory to be opened.
00544  *
00545  * \return The value one, true, is returned for success and
00546  * the value zero, false, is returned for failure.
00547  * Reasons for failure include the FAT volume has not been initialized
00548  * or it a FAT12 volume.
00549  */
00550 uint8_t SdFile::openRoot(SdVolume* vol) {
00551   // error if file is already open
00552   if (isOpen ()) return false;
00553 
00554   if (vol->fatType () == 16) {
00555     type_ = FAT_FILE_TYPE_ROOT16;
00556     firstCluster_ = 0;
00557     fileSize_ = 32 * vol->rootDirEntryCount ();
00558   } else if (vol->fatType () == 32) {
00559     type_ = FAT_FILE_TYPE_ROOT32;
00560     firstCluster_ = vol->rootDirStart ();
00561     if (!vol->chainSize(firstCluster_, &fileSize_)) return false;
00562   } else {
00563     // volume is not initialized or FAT12
00564     return false;
00565   }
00566   vol_ = vol;
00567   // read only
00568   flags_ = O_READ;
00569 
00570   // set to start of file
00571   curCluster_ = 0;
00572   curPosition_ = 0;
00573 
00574   // root has no directory entry
00575   dirBlock_ = 0;
00576   dirIndex_ = 0;
00577   return true;
00578 }
00579 //------------------------------------------------------------------------------
00580 /** %Print the name field of a directory entry in 8.3 format to Serial.
00581  *
00582  * \param[in] dir The directory structure containing the name.
00583  * \param[in] width Blank fill name if length is less than \a width.
00584  */
00585 void SdFile::printDirName(const dir_t& dir, uint8_t width) {
00586   uint8_t w = 0;
00587   for (uint8_t i = 0; i < 11; i++) {
00588     if (dir.name[i] == ' ')continue;
00589     if (i == 8) {
00590       Serial.print('.');
00591       w++;
00592     }
00593     Serial.write(dir.name[i]);
00594     w++;
00595   }
00596   if (DIR_IS_SUBDIR(&dir)) {
00597     Serial.print('/');
00598     w++;
00599   }
00600   while (w < width) {
00601     Serial.print(' ');
00602     w++;
00603   }
00604 }
00605 //------------------------------------------------------------------------------
00606 /** %Print a directory date field to Serial.
00607  *
00608  *  Format is yyyy-mm-dd.
00609  *
00610  * \param[in] fatDate The date field from a directory entry.
00611  */
00612 void SdFile::printFatDate(uint16_t fatDate) {
00613   Serial.print(FAT_YEAR(fatDate));
00614   Serial.print('-');
00615   printTwoDigits(FAT_MONTH(fatDate));
00616   Serial.print('-');
00617   printTwoDigits(FAT_DAY(fatDate));
00618 }
00619 //------------------------------------------------------------------------------
00620 /** %Print a directory time field to Serial.
00621  *
00622  * Format is hh:mm:ss.
00623  *
00624  * \param[in] fatTime The time field from a directory entry.
00625  */
00626 void SdFile::printFatTime(uint16_t fatTime) {
00627   printTwoDigits(FAT_HOUR(fatTime));
00628   Serial.print(':');
00629   printTwoDigits(FAT_MINUTE(fatTime));
00630   Serial.print(':');
00631   printTwoDigits(FAT_SECOND(fatTime));
00632 }
00633 //------------------------------------------------------------------------------
00634 /** %Print a value as two digits to Serial.
00635  *
00636  * \param[in] v Value to be printed, 0 <= \a v <= 99
00637  */
00638 void SdFile::printTwoDigits(uint8_t v) {
00639   char str[3];
00640   str[0] = '0' + v/10;
00641   str[1] = '0' + v % 10;
00642   str[2] = 0;
00643   Serial.print(str);
00644 }
00645 //------------------------------------------------------------------------------
00646 /**
00647  * Read data from a file starting at the current position.
00648  *
00649  * \param[out] buf Pointer to the location that will receive the data.
00650  *
00651  * \param[in] nbyte Maximum number of bytes to read.
00652  *
00653  * \return For success read() returns the number of bytes read.
00654  * A value less than \a nbyte, including zero, will be returned
00655  * if end of file is reached.
00656  * If an error occurs, read() returns -1.  Possible errors include
00657  * read() called before a file has been opened, corrupt file system
00658  * or an I/O error occurred.
00659  */
00660 int16_t SdFile::read(void* buf, uint16_t nbyte) {
00661   uint8_t* dst = reinterpret_cast<uint8_t*>(buf);
00662 
00663   // error if not open or write only
00664   if (!isOpen () || !(flags_ & O_READ)) return -1;
00665 
00666   // max bytes left in file
00667   if (nbyte > (fileSize_ - curPosition_)) nbyte = fileSize_ - curPosition_;
00668 
00669   // amount left to read
00670   uint16_t toRead = nbyte;
00671   while (toRead > 0) {
00672     uint32_t block;  // raw device block number
00673     uint16_t offset = curPosition_ & 0X1FF;  // offset in block
00674     if (type_ == FAT_FILE_TYPE_ROOT16) {
00675       block = vol_->rootDirStart () + (curPosition_ >> 9);
00676     } else {
00677       uint8_t blockOfCluster = vol_->blockOfCluster(curPosition_);
00678       if (offset == 0 && blockOfCluster == 0) {
00679         // start of new cluster
00680         if (curPosition_ == 0) {
00681           // use first cluster in file
00682           curCluster_ = firstCluster_;
00683         } else {
00684           // get next cluster from FAT
00685           if (!vol_->fatGet(curCluster_, &curCluster_)) return -1;
00686         }
00687       }
00688       block = vol_->clusterStartBlock(curCluster_) + blockOfCluster;
00689     }
00690     uint16_t n = toRead;
00691 
00692     // amount to be read from current block
00693     if (n > (512 - offset)) n = 512 - offset;
00694 
00695     // no buffering needed if n == 512 or user requests no buffering
00696     if ((unbufferedRead () || n == 512) &&
00697       block != SdVolume::cacheBlockNumber_) {
00698       if (!vol_->readData(block, offset, n, dst)) return -1;
00699       dst += n;
00700     } else {
00701       // read block to cache and copy data to caller
00702       if (!SdVolume::cacheRawBlock(block, SdVolume::CACHE_FOR_READ)) return -1;
00703       uint8_t* src = SdVolume::cacheBuffer_.data + offset;
00704       uint8_t* end = src + n;
00705       while (src != end) *dst++ = *src++;
00706     }
00707     curPosition_ += n;
00708     toRead -= n;
00709   }
00710   return nbyte;
00711 }
00712 //------------------------------------------------------------------------------
00713 /**
00714  * Read the next directory entry from a directory file.
00715  *
00716  * \param[out] dir The dir_t struct that will receive the data.
00717  *
00718  * \return For success readDir() returns the number of bytes read.
00719  * A value of zero will be returned if end of file is reached.
00720  * If an error occurs, readDir() returns -1.  Possible errors include
00721  * readDir() called before a directory has been opened, this is not
00722  * a directory file or an I/O error occurred.
00723  */
00724 int8_t SdFile::readDir(dir_t* dir) {
00725   int8_t n;
00726   // if not a directory file or miss-positioned return an error
00727   if (!isDir () || (0X1F & curPosition_)) return -1;
00728 
00729   while ((n = read(dir, sizeof(dir_t))) == sizeof(dir_t)) {
00730     // last entry if DIR_NAME_FREE
00731     if (dir->name[0] == DIR_NAME_FREE) break;
00732     // skip empty entries and entry for .  and ..
00733     if (dir->name[0] == DIR_NAME_DELETED || dir->name[0] == '.') continue;
00734     // return if normal file or subdirectory
00735     if (DIR_IS_FILE_OR_SUBDIR(dir)) return n;
00736   }
00737   // error, end of file, or past last entry
00738   return n < 0 ? -1 : 0;
00739 }
00740 //------------------------------------------------------------------------------
00741 // Read next directory entry into the cache
00742 // Assumes file is correctly positioned
00743 dir_t* SdFile::readDirCache(void) {
00744   // error if not directory
00745   if (!isDir ()) return NULL;
00746 
00747   // index of entry in cache
00748   uint8_t i = (curPosition_ >> 5) & 0XF;
00749 
00750   // use read to locate and cache block
00751   if (read() < 0) return NULL;
00752 
00753   // advance to next entry
00754   curPosition_ += 31;
00755 
00756   // return pointer to entry
00757   return (SdVolume::cacheBuffer_.dir + i);
00758 }
00759 //------------------------------------------------------------------------------
00760 /**
00761  * Remove a file.
00762  *
00763  * The directory entry and all data for the file are deleted.
00764  *
00765  * \note This function should not be used to delete the 8.3 version of a
00766  * file that has a long name. For example if a file has the long name
00767  * "New Text Document.txt" you should not delete the 8.3 name "NEWTEX~1.TXT".
00768  *
00769  * \return The value one, true, is returned for success and
00770  * the value zero, false, is returned for failure.
00771  * Reasons for failure include the file read-only, is a directory,
00772  * or an I/O error occurred.
00773  */
00774 uint8_t SdFile::remove(void) {
00775   // free any clusters - will fail if read-only or directory
00776   if (!truncate(0)) return false;
00777 
00778   // cache directory entry
00779   dir_t* d = cacheDirEntry(SdVolume::CACHE_FOR_WRITE);
00780   if (!d) return false;
00781 
00782   // mark entry deleted
00783   d->name[0] = DIR_NAME_DELETED;
00784 
00785   // set this SdFile closed
00786   type_ = FAT_FILE_TYPE_CLOSED;
00787 
00788   // write entry to SD
00789   return SdVolume::cacheFlush();
00790 }
00791 //------------------------------------------------------------------------------
00792 /**
00793  * Remove a file.
00794  *
00795  * The directory entry and all data for the file are deleted.
00796  *
00797  * \param[in] dirFile The directory that contains the file.
00798  * \param[in] fileName The name of the file to be removed.
00799  *
00800  * \note This function should not be used to delete the 8.3 version of a
00801  * file that has a long name. For example if a file has the long name
00802  * "New Text Document.txt" you should not delete the 8.3 name "NEWTEX~1.TXT".
00803  *
00804  * \return The value one, true, is returned for success and
00805  * the value zero, false, is returned for failure.
00806  * Reasons for failure include the file is a directory, is read only,
00807  * \a dirFile is not a directory, \a fileName is not found
00808  * or an I/O error occurred.
00809  */
00810 uint8_t SdFile::remove(SdFile* dirFile, const char* fileName) {
00811   SdFile file;
00812   if (!file.open(dirFile, fileName, O_WRITE)) return false;
00813   return file.remove();
00814 }
00815 //------------------------------------------------------------------------------
00816 /** Remove a directory file.
00817  *
00818  * The directory file will be removed only if it is empty and is not the
00819  * root directory.  rmDir() follows DOS and Windows and ignores the
00820  * read-only attribute for the directory.
00821  *
00822  * \note This function should not be used to delete the 8.3 version of a
00823  * directory that has a long name. For example if a directory has the
00824  * long name "New folder" you should not delete the 8.3 name "NEWFOL~1".
00825  *
00826  * \return The value one, true, is returned for success and
00827  * the value zero, false, is returned for failure.
00828  * Reasons for failure include the file is not a directory, is the root
00829  * directory, is not empty, or an I/O error occurred.
00830  */
00831 uint8_t SdFile::rmDir(void) {
00832   // must be open subdirectory
00833   if (!isSubDir ()) return false;
00834 
00835   rewind();
00836 
00837   // make sure directory is empty
00838   while (curPosition_ < fileSize_) {
00839     dir_t* p = readDirCache();
00840     if (p == NULL) return false;
00841     // done if past last used entry
00842     if (p->name[0] == DIR_NAME_FREE) break;
00843     // skip empty slot or '.' or '..'
00844     if (p->name[0] == DIR_NAME_DELETED || p->name[0] == '.') continue;
00845     // error not empty
00846     if (DIR_IS_FILE_OR_SUBDIR(p)) return false;
00847   }
00848   // convert empty directory to normal file for remove
00849   type_ = FAT_FILE_TYPE_NORMAL;
00850   flags_ |= O_WRITE;
00851   return remove();
00852 }
00853 //------------------------------------------------------------------------------
00854 /** Recursively delete a directory and all contained files.
00855  *
00856  * This is like the Unix/Linux 'rm -rf *' if called with the root directory
00857  * hence the name.
00858  *
00859  * Warning - This will remove all contents of the directory including
00860  * subdirectories.  The directory will then be removed if it is not root.
00861  * The read-only attribute for files will be ignored.
00862  *
00863  * \note This function should not be used to delete the 8.3 version of
00864  * a directory that has a long name.  See remove() and rmDir().
00865  *
00866  * \return The value one, true, is returned for success and
00867  * the value zero, false, is returned for failure.
00868  */
00869 uint8_t SdFile::rmRfStar(void) {
00870   rewind();
00871   while (curPosition_ < fileSize_) {
00872     SdFile f;
00873 
00874     // remember position
00875     uint16_t index = curPosition_/32;
00876 
00877     dir_t* p = readDirCache();
00878     if (!p) return false;
00879 
00880     // done if past last entry
00881     if (p->name[0] == DIR_NAME_FREE) break;
00882 
00883     // skip empty slot or '.' or '..'
00884     if (p->name[0] == DIR_NAME_DELETED || p->name[0] == '.') continue;
00885 
00886     // skip if part of long file name or volume label in root
00887     if (!DIR_IS_FILE_OR_SUBDIR(p)) continue;
00888 
00889     if (!f.open(this, index, O_READ)) return false;
00890     if (f.isSubDir ()) {
00891       // recursively delete
00892       if (!f.rmRfStar()) return false;
00893     } else {
00894       // ignore read-only
00895       f.flags_ |= O_WRITE;
00896       if (!f.remove()) return false;
00897     }
00898     // position to next entry if required
00899     if (curPosition_ != (32*(index + 1))) {
00900       if (!seekSet(32*(index + 1))) return false;
00901     }
00902   }
00903   // don't try to delete root
00904   if (isRoot ()) return true;
00905   return rmDir();
00906 }
00907 //------------------------------------------------------------------------------
00908 /**
00909  * Sets a file's position.
00910  *
00911  * \param[in] pos The new position in bytes from the beginning of the file.
00912  *
00913  * \return The value one, true, is returned for success and
00914  * the value zero, false, is returned for failure.
00915  */
00916 uint8_t SdFile::seekSet(uint32_t pos) {
00917   // error if file not open or seek past end of file
00918   if (!isOpen () || pos > fileSize_) return false;
00919 
00920   if (type_ == FAT_FILE_TYPE_ROOT16) {
00921     curPosition_ = pos;
00922     return true;
00923   }
00924   if (pos == 0) {
00925     // set position to start of file
00926     curCluster_ = 0;
00927     curPosition_ = 0;
00928     return true;
00929   }
00930   // calculate cluster index for cur and new position
00931   uint32_t nCur = (curPosition_ - 1) >> (vol_->clusterSizeShift_ + 9);
00932   uint32_t nNew = (pos - 1) >> (vol_->clusterSizeShift_ + 9);
00933 
00934   if (nNew < nCur || curPosition_ == 0) {
00935     // must follow chain from first cluster
00936     curCluster_ = firstCluster_;
00937   } else {
00938     // advance from curPosition
00939     nNew -= nCur;
00940   }
00941   while (nNew--) {
00942     if (!vol_->fatGet(curCluster_, &curCluster_)) return false;
00943   }
00944   curPosition_ = pos;
00945   return true;
00946 }
00947 //------------------------------------------------------------------------------
00948 /**
00949  * The sync() call causes all modified data and directory fields
00950  * to be written to the storage device.
00951  *
00952  * \return The value one, true, is returned for success and
00953  * the value zero, false, is returned for failure.
00954  * Reasons for failure include a call to sync() before a file has been
00955  * opened or an I/O error.
00956  */
00957 uint8_t SdFile::sync(void) {
00958   // only allow open files and directories
00959   if (!isOpen ()) return false;
00960 
00961   if (flags_ & F_FILE_DIR_DIRTY) {
00962     dir_t* d = cacheDirEntry(SdVolume::CACHE_FOR_WRITE);
00963     if (!d) return false;
00964 
00965     // do not set filesize for dir files
00966     if (!isDir ()) d->fileSize = fileSize_;
00967 
00968     // update first cluster fields
00969     d->firstClusterLow = firstCluster_ & 0XFFFF;
00970     d->firstClusterHigh = firstCluster_ >> 16;
00971 
00972     // set modify time if user supplied a callback date/time function
00973     if (dateTime_) {
00974       dateTime_(&d->lastWriteDate, &d->lastWriteTime);
00975       d->lastAccessDate = d->lastWriteDate;
00976     }
00977     // clear directory dirty
00978     flags_ &= ~F_FILE_DIR_DIRTY;
00979   }
00980   return SdVolume::cacheFlush();
00981 }
00982 //------------------------------------------------------------------------------
00983 /**
00984  * Set a file's timestamps in its directory entry.
00985  *
00986  * \param[in] flags Values for \a flags are constructed by a bitwise-inclusive
00987  * OR of flags from the following list
00988  *
00989  * T_ACCESS - Set the file's last access date.
00990  *
00991  * T_CREATE - Set the file's creation date and time.
00992  *
00993  * T_WRITE - Set the file's last write/modification date and time.
00994  *
00995  * \param[in] year Valid range 1980 - 2107 inclusive.
00996  *
00997  * \param[in] month Valid range 1 - 12 inclusive.
00998  *
00999  * \param[in] day Valid range 1 - 31 inclusive.
01000  *
01001  * \param[in] hour Valid range 0 - 23 inclusive.
01002  *
01003  * \param[in] minute Valid range 0 - 59 inclusive.
01004  *
01005  * \param[in] second Valid range 0 - 59 inclusive
01006  *
01007  * \note It is possible to set an invalid date since there is no check for
01008  * the number of days in a month.
01009  *
01010  * \note
01011  * Modify and access timestamps may be overwritten if a date time callback
01012  * function has been set by dateTimeCallback().
01013  *
01014  * \return The value one, true, is returned for success and
01015  * the value zero, false, is returned for failure.
01016  */
01017 uint8_t SdFile::timestamp(uint8_t flags, uint16_t year, uint8_t month,
01018          uint8_t day, uint8_t hour, uint8_t minute, uint8_t second) {
01019   if (!isOpen ()
01020     || year < 1980
01021     || year > 2107
01022     || month < 1
01023     || month > 12
01024     || day < 1
01025     || day > 31
01026     || hour > 23
01027     || minute > 59
01028     || second > 59) {
01029       return false;
01030   }
01031   dir_t* d = cacheDirEntry(SdVolume::CACHE_FOR_WRITE);
01032   if (!d) return false;
01033 
01034   uint16_t dirDate = FAT_DATE(year, month, day);
01035   uint16_t dirTime = FAT_TIME(hour, minute, second);
01036   if (flags & T_ACCESS) {
01037     d->lastAccessDate = dirDate;
01038   }
01039   if (flags & T_CREATE) {
01040     d->creationDate = dirDate;
01041     d->creationTime = dirTime;
01042     // seems to be units of 1/100 second not 1/10 as Microsoft states
01043     d->creationTimeTenths = second & 1 ? 100 : 0;
01044   }
01045   if (flags & T_WRITE) {
01046     d->lastWriteDate = dirDate;
01047     d->lastWriteTime = dirTime;
01048   }
01049   SdVolume::cacheSetDirty();
01050   return sync();
01051 }
01052 //------------------------------------------------------------------------------
01053 /**
01054  * Truncate a file to a specified length.  The current file position
01055  * will be maintained if it is less than or equal to \a length otherwise
01056  * it will be set to end of file.
01057  *
01058  * \param[in] length The desired length for the file.
01059  *
01060  * \return The value one, true, is returned for success and
01061  * the value zero, false, is returned for failure.
01062  * Reasons for failure include file is read only, file is a directory,
01063  * \a length is greater than the current file size or an I/O error occurs.
01064  */
01065 uint8_t SdFile::truncate(uint32_t length) {
01066 // error if not a normal file or read-only
01067   if (!isFile () || !(flags_ & O_WRITE)) return false;
01068 
01069   // error if length is greater than current size
01070   if (length > fileSize_) return false;
01071 
01072   // fileSize and length are zero - nothing to do
01073   if (fileSize_ == 0) return true;
01074 
01075   // remember position for seek after truncation
01076   uint32_t newPos = curPosition_ > length ? length : curPosition_;
01077 
01078   // position to last cluster in truncated file
01079   if (!seekSet(length)) return false;
01080 
01081   if (length == 0) {
01082     // free all clusters
01083     if (!vol_->freeChain(firstCluster_)) return false;
01084     firstCluster_ = 0;
01085   } else {
01086     uint32_t toFree;
01087     if (!vol_->fatGet(curCluster_, &toFree)) return false;
01088 
01089     if (!vol_->isEOC(toFree)) {
01090       // free extra clusters
01091       if (!vol_->freeChain(toFree)) return false;
01092 
01093       // current cluster is end of chain
01094       if (!vol_->fatPutEOC(curCluster_)) return false;
01095     }
01096   }
01097   fileSize_ = length;
01098 
01099   // need to update directory entry
01100   flags_ |= F_FILE_DIR_DIRTY;
01101 
01102   if (!sync()) return false;
01103 
01104   // set file to correct position
01105   return seekSet(newPos);
01106 }
01107 //------------------------------------------------------------------------------
01108 /**
01109  * Write data to an open file.
01110  *
01111  * \note Data is moved to the cache but may not be written to the
01112  * storage device until sync() is called.
01113  *
01114  * \param[in] buf Pointer to the location of the data to be written.
01115  *
01116  * \param[in] nbyte Number of bytes to write.
01117  *
01118  * \return For success write() returns the number of bytes written, always
01119  * \a nbyte.  If an error occurs, write() returns -1.  Possible errors
01120  * include write() is called before a file has been opened, write is called
01121  * for a read-only file, device is full, a corrupt file system or an I/O error.
01122  *
01123  */
01124 size_t SdFile::write(const void* buf, uint16_t nbyte) {
01125   // convert void* to uint8_t*  -  must be before goto statements
01126   const uint8_t* src = reinterpret_cast<const uint8_t*>(buf);
01127 
01128   // number of bytes left to write  -  must be before goto statements
01129   uint16_t nToWrite = nbyte;
01130 
01131   // error if not a normal file or is read-only
01132   if (!isFile () || !(flags_ & O_WRITE)) goto writeErrorReturn;
01133 
01134   // seek to end of file if append flag
01135   if ((flags_ & O_APPEND) && curPosition_ != fileSize_) {
01136     if (!seekEnd()) goto writeErrorReturn;
01137   }
01138 
01139   while (nToWrite > 0) {
01140     uint8_t blockOfCluster = vol_->blockOfCluster(curPosition_);
01141     uint16_t blockOffset = curPosition_ & 0X1FF;
01142     if (blockOfCluster == 0 && blockOffset == 0) {
01143       // start of new cluster
01144       if (curCluster_ == 0) {
01145         if (firstCluster_ == 0) {
01146           // allocate first cluster of file
01147           if (!addCluster()) goto writeErrorReturn;
01148         } else {
01149           curCluster_ = firstCluster_;
01150         }
01151       } else {
01152         uint32_t next;
01153         if (!vol_->fatGet(curCluster_, &next)) return false;
01154         if (vol_->isEOC(next)) {
01155           // add cluster if at end of chain
01156           if (!addCluster()) goto writeErrorReturn;
01157         } else {
01158           curCluster_ = next;
01159         }
01160       }
01161     }
01162     // max space in block
01163     uint16_t n = 512 - blockOffset;
01164 
01165     // lesser of space and amount to write
01166     if (n > nToWrite) n = nToWrite;
01167 
01168     // block for data write
01169     uint32_t block = vol_->clusterStartBlock(curCluster_) + blockOfCluster;
01170     if (n == 512) {
01171       // full block - don't need to use cache
01172       // invalidate cache if block is in cache
01173       if (SdVolume::cacheBlockNumber_ == block) {
01174         SdVolume::cacheBlockNumber_ = 0XFFFFFFFF;
01175       }
01176       if (!vol_->writeBlock(block, src)) goto writeErrorReturn;
01177       src += 512;
01178     } else {
01179       if (blockOffset == 0 && curPosition_ >= fileSize_) {
01180         // start of new block don't need to read into cache
01181         if (!SdVolume::cacheFlush()) goto writeErrorReturn;
01182         SdVolume::cacheBlockNumber_ = block;
01183         SdVolume::cacheSetDirty();
01184       } else {
01185         // rewrite part of block
01186         if (!SdVolume::cacheRawBlock(block, SdVolume::CACHE_FOR_WRITE)) {
01187           goto writeErrorReturn;
01188         }
01189       }
01190       uint8_t* dst = SdVolume::cacheBuffer_.data + blockOffset;
01191       uint8_t* end = dst + n;
01192       while (dst != end) *dst++ = *src++;
01193     }
01194     nToWrite -= n;
01195     curPosition_ += n;
01196   }
01197   if (curPosition_ > fileSize_) {
01198     // update fileSize and insure sync will update dir entry
01199     fileSize_ = curPosition_;
01200     flags_ |= F_FILE_DIR_DIRTY;
01201   } else if (dateTime_ && nbyte) {
01202     // insure sync will update modified date and time
01203     flags_ |= F_FILE_DIR_DIRTY;
01204   }
01205 
01206   if (flags_ & O_SYNC) {
01207     if (!sync()) goto writeErrorReturn;
01208   }
01209   return nbyte;
01210 
01211  writeErrorReturn:
01212   // return for write error
01213   //writeError = true;
01214   setWriteError();
01215   return 0;
01216 }
01217 //------------------------------------------------------------------------------
01218 /**
01219  * Write a byte to a file. Required by the Arduino Print class.
01220  *
01221  * Use SdFile::writeError to check for errors.
01222  */
01223 size_t SdFile::write(uint8_t b) {
01224   return write(&b, 1);
01225 }
01226 //------------------------------------------------------------------------------
01227 /**
01228  * Write a string to a file. Used by the Arduino Print class.
01229  *
01230  * Use SdFile::writeError to check for errors.
01231  */
01232 size_t SdFile::write(const char* str) {
01233   return write(str, strlen(str));
01234 }
01235 //------------------------------------------------------------------------------
01236 /**
01237  * Write a PROGMEM string to a file.
01238  *
01239  * Use SdFile::writeError to check for errors.
01240  */
01241 void SdFile::write_P(PGM_P str) {
01242   for (uint8_t c; (c = pgm_read_byte(str)); str++) write(c);
01243 }
01244 //------------------------------------------------------------------------------
01245 /**
01246  * Write a PROGMEM string followed by CR/LF to a file.
01247  *
01248  * Use SdFile::writeError to check for errors.
01249  */
01250 void SdFile::writeln_P(PGM_P str) {
01251   write_P(str);
01252   println();
01253 }