D:/DRISSI/arduino-0022/arduino-0022/libraries/SD/utility/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 <avr/pgmspace.h>
00022 #include <WProgram.h>
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 //------------------------------------------------------------------------------
00074 uint8_t SdFile::close(void) {
00075   if (!sync())return false;
00076   type_ = FAT_FILE_TYPE_CLOSED;
00077   return true;
00078 }
00079 //------------------------------------------------------------------------------
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 //------------------------------------------------------------------------------
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 //------------------------------------------------------------------------------
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 //------------------------------------------------------------------------------
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 //------------------------------------------------------------------------------
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.print(' ');
00225        printFatTime(p->lastWriteTime);
00226     }
00227     // print size if requested
00228     if (!DIR_IS_SUBDIR(p) && (flags & LS_SIZE)) {
00229       Serial.print(' ');
00230       Serial.print(p->fileSize);
00231     }
00232     Serial.println();
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 //------------------------------------------------------------------------------
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 //------------------------------------------------------------------------------
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 //------------------------------------------------------------------------------
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 //------------------------------------------------------------------------------
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 //------------------------------------------------------------------------------
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.print(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 //------------------------------------------------------------------------------
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 //------------------------------------------------------------------------------
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 //------------------------------------------------------------------------------
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 //------------------------------------------------------------------------------
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 //------------------------------------------------------------------------------
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 //------------------------------------------------------------------------------
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 //------------------------------------------------------------------------------
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 //------------------------------------------------------------------------------
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 //------------------------------------------------------------------------------
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 //------------------------------------------------------------------------------
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 //------------------------------------------------------------------------------
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 //------------------------------------------------------------------------------
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 //------------------------------------------------------------------------------
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 //------------------------------------------------------------------------------
01124 int16_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   return -1;
01215 }
01216 //------------------------------------------------------------------------------
01222 void SdFile::write(uint8_t b) {
01223   write(&b, 1);
01224 }
01225 //------------------------------------------------------------------------------
01231 void SdFile::write(const char* str) {
01232   write(str, strlen(str));
01233 }
01234 //------------------------------------------------------------------------------
01240 void SdFile::write_P(PGM_P str) {
01241   for (uint8_t c; (c = pgm_read_byte(str)); str++) write(c);
01242 }
01243 //------------------------------------------------------------------------------
01249 void SdFile::writeln_P(PGM_P str) {
01250   write_P(str);
01251   println();
01252 }