|
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252 |
-
- #include <SdFat.h>
- #include <avr/pgmspace.h>
- #include <Arduino.h>
-
-
- void (*SdFile::dateTime_)(uint16_t* date, uint16_t* time) = NULL;
-
- #if ALLOW_DEPRECATED_FUNCTIONS
-
- void (*SdFile::oldDateTime_)(uint16_t& date, uint16_t& time) = NULL;
- #endif
-
-
- uint8_t SdFile::addCluster() {
- if (!vol_->allocContiguous(1, &curCluster_)) return false;
-
-
- if (firstCluster_ == 0) {
- firstCluster_ = curCluster_;
- flags_ |= F_FILE_DIR_DIRTY;
- }
- return true;
- }
-
-
-
- uint8_t SdFile::addDirCluster(void) {
- if (!addCluster()) return false;
-
-
- uint32_t block = vol_->clusterStartBlock(curCluster_);
- for (uint8_t i = vol_->blocksPerCluster_; i != 0; i--) {
- if (!SdVolume::cacheZeroBlock(block + i - 1)) return false;
- }
-
- fileSize_ += 512UL << vol_->clusterSizeShift_;
- return true;
- }
-
-
-
- dir_t* SdFile::cacheDirEntry(uint8_t action) {
- if (!SdVolume::cacheRawBlock(dirBlock_, action)) return NULL;
- return SdVolume::cacheBuffer_.dir + dirIndex_;
- }
-
-
- uint8_t SdFile::close(void) {
- if (!sync())return false;
- type_ = FAT_FILE_TYPE_CLOSED;
- return true;
- }
-
-
- uint8_t SdFile::contiguousRange(uint32_t* bgnBlock, uint32_t* endBlock) {
-
- if (firstCluster_ == 0) return false;
-
- for (uint32_t c = firstCluster_; ; c++) {
- uint32_t next;
- if (!vol_->fatGet(c, &next)) return false;
-
-
- if (next != (c + 1)) {
-
- if (!vol_->isEOC(next)) return false;
- *bgnBlock = vol_->clusterStartBlock(firstCluster_);
- *endBlock = vol_->clusterStartBlock(c)
- + vol_->blocksPerCluster_ - 1;
- return true;
- }
- }
- }
-
-
- uint8_t SdFile::createContiguous(SdFile* dirFile,
- const char* fileName, uint32_t size) {
-
- if (size == 0) return false;
- if (!open(dirFile, fileName, O_CREAT | O_EXCL | O_RDWR)) return false;
-
-
- uint32_t count = ((size - 1) >> (vol_->clusterSizeShift_ + 9)) + 1;
-
-
- if (!vol_->allocContiguous(count, &firstCluster_)) {
- remove();
- return false;
- }
- fileSize_ = size;
-
-
- flags_ |= F_FILE_DIR_DIRTY;
- return sync();
- }
-
-
- uint8_t SdFile::dirEntry(dir_t* dir) {
-
- if (!sync()) return false;
-
-
- dir_t* p = cacheDirEntry(SdVolume::CACHE_FOR_READ);
- if (!p) return false;
-
-
- memcpy(dir, p, sizeof(dir_t));
- return true;
- }
-
-
- void SdFile::dirName(const dir_t& dir, char* name) {
- uint8_t j = 0;
- for (uint8_t i = 0; i < 11; i++) {
- if (dir.name[i] == ' ')continue;
- if (i == 8) name[j++] = '.';
- name[j++] = dir.name[i];
- }
- name[j] = 0;
- }
-
-
- void SdFile::ls(uint8_t flags, uint8_t indent) {
- dir_t* p;
-
- rewind();
- while ((p = readDirCache())) {
-
- if (p->name[0] == DIR_NAME_FREE) break;
-
-
- if (p->name[0] == DIR_NAME_DELETED || p->name[0] == '.') continue;
-
-
- if (!DIR_IS_FILE_OR_SUBDIR(p)) continue;
-
-
- for (int8_t i = 0; i < indent; i++) Serial.print(' ');
-
-
- printDirName(*p, flags & (LS_DATE | LS_SIZE) ? 14 : 0);
-
-
- if (flags & LS_DATE) {
- printFatDate(p->lastWriteDate);
- Serial.print(' ');
- printFatTime(p->lastWriteTime);
- }
-
- if (!DIR_IS_SUBDIR(p) && (flags & LS_SIZE)) {
- Serial.print(' ');
- Serial.print(p->fileSize);
- }
- Serial.println();
-
-
- if ((flags & LS_R) && DIR_IS_SUBDIR(p)) {
- uint16_t index = curPosition()/32 - 1;
- SdFile s;
- if (s.open(this, index, O_READ)) s.ls(flags, indent + 2);
- seekSet(32 * (index + 1));
- }
- }
- }
-
-
- uint8_t SdFile::make83Name(const char* str, uint8_t* name) {
- uint8_t c;
- uint8_t n = 7;
- uint8_t i = 0;
-
- while (i < 11) name[i++] = ' ';
- i = 0;
- while ((c = *str++) != '\0') {
- if (c == '.') {
- if (n == 10) return false;
- n = 10;
- i = 8;
- } else {
-
- PGM_P p = PSTR("|<>^+=?/[];,*\"\\");
- uint8_t b;
- while ((b = pgm_read_byte(p++))) if (b == c) return false;
-
- if (i > n || c < 0X21 || c > 0X7E)return false;
-
- name[i++] = c < 'a' || c > 'z' ? c : c + ('A' - 'a');
- }
- }
-
- return name[0] != ' ';
- }
-
-
- uint8_t SdFile::makeDir(SdFile* dir, const char* dirName) {
- dir_t d;
-
-
- if (!open(dir, dirName, O_CREAT | O_EXCL | O_RDWR)) return false;
-
-
- flags_ = O_READ;
- type_ = FAT_FILE_TYPE_SUBDIR;
-
-
- if (!addDirCluster())return false;
-
-
- if (!sync()) return false;
-
-
- dir_t* p = cacheDirEntry(SdVolume::CACHE_FOR_WRITE);
- if (!p) return false;
-
-
- p->attributes = DIR_ATT_DIRECTORY;
-
-
- memcpy(&d, p, sizeof(d));
- for (uint8_t i = 1; i < 11; i++) d.name[i] = ' ';
- d.name[0] = '.';
-
-
- uint32_t block = vol_->clusterStartBlock(firstCluster_);
- if (!SdVolume::cacheRawBlock(block, SdVolume::CACHE_FOR_WRITE)) return false;
-
-
- memcpy(&SdVolume::cacheBuffer_.dir[0], &d, sizeof(d));
-
-
- d.name[1] = '.';
- if (dir->isRoot()) {
- d.firstClusterLow = 0;
- d.firstClusterHigh = 0;
- } else {
- d.firstClusterLow = dir->firstCluster_ & 0XFFFF;
- d.firstClusterHigh = dir->firstCluster_ >> 16;
- }
-
- memcpy(&SdVolume::cacheBuffer_.dir[1], &d, sizeof(d));
-
-
- curPosition_ = 2 * sizeof(d);
-
-
- return SdVolume::cacheFlush();
- }
-
-
- uint8_t SdFile::open(SdFile* dirFile, const char* fileName, uint8_t oflag) {
- uint8_t dname[11];
- dir_t* p;
-
-
- if (isOpen())return false;
-
- if (!make83Name(fileName, dname)) return false;
- vol_ = dirFile->vol_;
- dirFile->rewind();
-
-
- uint8_t emptyFound = false;
-
-
- while (dirFile->curPosition_ < dirFile->fileSize_) {
- uint8_t index = 0XF & (dirFile->curPosition_ >> 5);
- p = dirFile->readDirCache();
- if (p == NULL) return false;
-
- if (p->name[0] == DIR_NAME_FREE || p->name[0] == DIR_NAME_DELETED) {
-
- if (!emptyFound) {
- emptyFound = true;
- dirIndex_ = index;
- dirBlock_ = SdVolume::cacheBlockNumber_;
- }
-
- if (p->name[0] == DIR_NAME_FREE) break;
- } else if (!memcmp(dname, p->name, 11)) {
-
- if ((oflag & (O_CREAT | O_EXCL)) == (O_CREAT | O_EXCL)) return false;
-
-
- return openCachedEntry(0XF & index, oflag);
- }
- }
-
- if ((oflag & (O_CREAT | O_WRITE)) != (O_CREAT | O_WRITE)) return false;
-
-
- if (emptyFound) {
- p = cacheDirEntry(SdVolume::CACHE_FOR_WRITE);
- if (!p) return false;
- } else {
- if (dirFile->type_ == FAT_FILE_TYPE_ROOT16) return false;
-
-
- if (!dirFile->addDirCluster()) return false;
-
-
- dirIndex_ = 0;
- p = SdVolume::cacheBuffer_.dir;
- }
-
- memset(p, 0, sizeof(dir_t));
- memcpy(p->name, dname, 11);
-
-
- if (dateTime_) {
-
- dateTime_(&p->creationDate, &p->creationTime);
- } else {
-
- p->creationDate = FAT_DEFAULT_DATE;
- p->creationTime = FAT_DEFAULT_TIME;
- }
- p->lastAccessDate = p->creationDate;
- p->lastWriteDate = p->creationDate;
- p->lastWriteTime = p->creationTime;
-
-
- if (!SdVolume::cacheFlush()) return false;
-
-
- return openCachedEntry(dirIndex_, oflag);
- }
-
-
- uint8_t SdFile::open(SdFile* dirFile, uint16_t index, uint8_t oflag) {
-
- if (isOpen())return false;
-
-
- if ((oflag & (O_CREAT | O_EXCL)) == (O_CREAT | O_EXCL)) return false;
-
- vol_ = dirFile->vol_;
-
-
- if (!dirFile->seekSet(32 * index)) return false;
-
-
- dir_t* p = dirFile->readDirCache();
- if (p == NULL) return false;
-
-
- if (p->name[0] == DIR_NAME_FREE ||
- p->name[0] == DIR_NAME_DELETED || p->name[0] == '.') {
- return false;
- }
-
- return openCachedEntry(index & 0XF, oflag);
- }
-
-
- uint8_t SdFile::openCachedEntry(uint8_t dirIndex, uint8_t oflag) {
-
- dir_t* p = SdVolume::cacheBuffer_.dir + dirIndex;
-
-
- if (p->attributes & (DIR_ATT_READ_ONLY | DIR_ATT_DIRECTORY)) {
- if (oflag & (O_WRITE | O_TRUNC)) return false;
- }
-
- dirIndex_ = dirIndex;
- dirBlock_ = SdVolume::cacheBlockNumber_;
-
-
- firstCluster_ = (uint32_t)p->firstClusterHigh << 16;
- firstCluster_ |= p->firstClusterLow;
-
-
- if (DIR_IS_FILE(p)) {
- fileSize_ = p->fileSize;
- type_ = FAT_FILE_TYPE_NORMAL;
- } else if (DIR_IS_SUBDIR(p)) {
- if (!vol_->chainSize(firstCluster_, &fileSize_)) return false;
- type_ = FAT_FILE_TYPE_SUBDIR;
- } else {
- return false;
- }
-
- flags_ = oflag & (O_ACCMODE | O_SYNC | O_APPEND);
-
-
- curCluster_ = 0;
- curPosition_ = 0;
-
-
- if (oflag & O_TRUNC) return truncate(0);
- return true;
- }
-
-
- uint8_t SdFile::openRoot(SdVolume* vol) {
-
- if (isOpen()) return false;
-
- if (vol->fatType() == 16) {
- type_ = FAT_FILE_TYPE_ROOT16;
- firstCluster_ = 0;
- fileSize_ = 32 * vol->rootDirEntryCount();
- } else if (vol->fatType() == 32) {
- type_ = FAT_FILE_TYPE_ROOT32;
- firstCluster_ = vol->rootDirStart();
- if (!vol->chainSize(firstCluster_, &fileSize_)) return false;
- } else {
-
- return false;
- }
- vol_ = vol;
-
- flags_ = O_READ;
-
-
- curCluster_ = 0;
- curPosition_ = 0;
-
-
- dirBlock_ = 0;
- dirIndex_ = 0;
- return true;
- }
-
-
- void SdFile::printDirName(const dir_t& dir, uint8_t width) {
- uint8_t w = 0;
- for (uint8_t i = 0; i < 11; i++) {
- if (dir.name[i] == ' ')continue;
- if (i == 8) {
- Serial.print('.');
- w++;
- }
- Serial.write(dir.name[i]);
- w++;
- }
- if (DIR_IS_SUBDIR(&dir)) {
- Serial.print('/');
- w++;
- }
- while (w < width) {
- Serial.print(' ');
- w++;
- }
- }
-
-
- void SdFile::printFatDate(uint16_t fatDate) {
- Serial.print(FAT_YEAR(fatDate));
- Serial.print('-');
- printTwoDigits(FAT_MONTH(fatDate));
- Serial.print('-');
- printTwoDigits(FAT_DAY(fatDate));
- }
-
-
- void SdFile::printFatTime(uint16_t fatTime) {
- printTwoDigits(FAT_HOUR(fatTime));
- Serial.print(':');
- printTwoDigits(FAT_MINUTE(fatTime));
- Serial.print(':');
- printTwoDigits(FAT_SECOND(fatTime));
- }
-
-
- void SdFile::printTwoDigits(uint8_t v) {
- char str[3];
- str[0] = '0' + v/10;
- str[1] = '0' + v % 10;
- str[2] = 0;
- Serial.print(str);
- }
-
-
- int32_t SdFile::read(void* buf, size_t nbyte) {
- uint8_t* dst = reinterpret_cast<uint8_t*>(buf);
-
-
- if (!isOpen() || !(flags_ & O_READ)) return -1;
-
-
- if (nbyte > (fileSize_ - curPosition_)) nbyte = fileSize_ - curPosition_;
-
-
- uint32_t toRead = nbyte;
- while (toRead > 0) {
- uint32_t block;
- uint16_t offset = curPosition_ & 0X1FF;
- if (type_ == FAT_FILE_TYPE_ROOT16) {
- block = vol_->rootDirStart() + (curPosition_ >> 9);
- } else {
- uint8_t blockOfCluster = vol_->blockOfCluster(curPosition_);
- if (offset == 0 && blockOfCluster == 0) {
-
- if (curPosition_ == 0) {
-
- curCluster_ = firstCluster_;
- } else {
-
- if (!vol_->fatGet(curCluster_, &curCluster_)) return -1;
- }
- }
- block = vol_->clusterStartBlock(curCluster_) + blockOfCluster;
- }
- int32_t n = toRead;
-
-
- if (n > (512 - offset)) n = 512 - offset;
-
-
- if ((unbufferedRead() || n == 512) && block != SdVolume::cacheBlockNumber_) {
- if (!vol_->readBlock(block, dst)) return -1;
- dst += n;
- } else {
-
- if (!SdVolume::cacheRawBlock(block, SdVolume::CACHE_FOR_READ)) return -1;
- uint8_t* src = SdVolume::cacheBuffer_.data + offset;
- uint8_t* end = src + n;
- while (src != end) *dst++ = *src++;
- }
- curPosition_ += n;
- toRead -= n;
- }
- return nbyte;
- }
-
-
- int8_t SdFile::readDir(dir_t* dir) {
- int8_t n;
-
- if (!isDir() || (0X1F & curPosition_)) return -1;
-
- while ((n = read(dir, sizeof(dir_t))) == sizeof(dir_t)) {
-
- if (dir->name[0] == DIR_NAME_FREE) break;
-
- if (dir->name[0] == DIR_NAME_DELETED || dir->name[0] == '.') continue;
-
- if (DIR_IS_FILE_OR_SUBDIR(dir)) return n;
- }
-
- return n < 0 ? -1 : 0;
- }
-
-
-
- dir_t* SdFile::readDirCache(void) {
-
- if (!isDir()) return NULL;
-
-
- uint8_t i = (curPosition_ >> 5) & 0XF;
-
-
- if (read() < 0) return NULL;
-
-
- curPosition_ += 31;
-
-
- return (SdVolume::cacheBuffer_.dir + i);
- }
-
-
- uint8_t SdFile::remove(void) {
-
- if (!truncate(0)) return false;
-
-
- dir_t* d = cacheDirEntry(SdVolume::CACHE_FOR_WRITE);
- if (!d) return false;
-
-
- d->name[0] = DIR_NAME_DELETED;
-
-
- type_ = FAT_FILE_TYPE_CLOSED;
-
-
- return SdVolume::cacheFlush();
- }
-
-
- uint8_t SdFile::remove(SdFile* dirFile, const char* fileName) {
- SdFile file;
- if (!file.open(dirFile, fileName, O_WRITE)) return false;
- return file.remove();
- }
-
-
- uint8_t SdFile::rmDir(void) {
-
- if (!isSubDir()) return false;
-
- rewind();
-
-
- while (curPosition_ < fileSize_) {
- dir_t* p = readDirCache();
- if (p == NULL) return false;
-
- if (p->name[0] == DIR_NAME_FREE) break;
-
- if (p->name[0] == DIR_NAME_DELETED || p->name[0] == '.') continue;
-
- if (DIR_IS_FILE_OR_SUBDIR(p)) return false;
- }
-
- type_ = FAT_FILE_TYPE_NORMAL;
- flags_ |= O_WRITE;
- return remove();
- }
-
-
- uint8_t SdFile::rmRfStar(void) {
- rewind();
- while (curPosition_ < fileSize_) {
- SdFile f;
-
-
- uint16_t index = curPosition_/32;
-
- dir_t* p = readDirCache();
- if (!p) return false;
-
-
- if (p->name[0] == DIR_NAME_FREE) break;
-
-
- if (p->name[0] == DIR_NAME_DELETED || p->name[0] == '.') continue;
-
-
- if (!DIR_IS_FILE_OR_SUBDIR(p)) continue;
-
- if (!f.open(this, index, O_READ)) return false;
- if (f.isSubDir()) {
-
- if (!f.rmRfStar()) return false;
- } else {
-
- f.flags_ |= O_WRITE;
- if (!f.remove()) return false;
- }
-
- if (curPosition_ != (uint32_t)(32*(index + 1))) {
- if (!seekSet(32*(index + 1))) return false;
- }
- }
-
- if (isRoot()) return true;
- return rmDir();
- }
-
-
- uint8_t SdFile::seekSet(uint32_t pos) {
-
- if (!isOpen() || pos > fileSize_) return false;
-
- if (type_ == FAT_FILE_TYPE_ROOT16) {
- curPosition_ = pos;
- return true;
- }
- if (pos == 0) {
-
- curCluster_ = 0;
- curPosition_ = 0;
- return true;
- }
-
- uint32_t nCur = (curPosition_ - 1) >> (vol_->clusterSizeShift_ + 9);
- uint32_t nNew = (pos - 1) >> (vol_->clusterSizeShift_ + 9);
-
- if (nNew < nCur || curPosition_ == 0) {
-
- curCluster_ = firstCluster_;
- } else {
-
- nNew -= nCur;
- }
- while (nNew--) {
- if (!vol_->fatGet(curCluster_, &curCluster_)) return false;
- }
- curPosition_ = pos;
- return true;
- }
-
-
- uint8_t SdFile::sync(void) {
-
- if (!isOpen()) return false;
-
- if (flags_ & F_FILE_DIR_DIRTY) {
- dir_t* d = cacheDirEntry(SdVolume::CACHE_FOR_WRITE);
- if (!d) return false;
-
-
- if (!isDir()) d->fileSize = fileSize_;
-
-
- d->firstClusterLow = firstCluster_ & 0XFFFF;
- d->firstClusterHigh = firstCluster_ >> 16;
-
-
- if (dateTime_) {
- dateTime_(&d->lastWriteDate, &d->lastWriteTime);
- d->lastAccessDate = d->lastWriteDate;
- }
-
- flags_ &= ~F_FILE_DIR_DIRTY;
- }
- return SdVolume::cacheFlush();
- }
-
-
- uint8_t SdFile::timestamp(uint8_t flags, uint16_t year, uint8_t month,
- uint8_t day, uint8_t hour, uint8_t minute, uint8_t second) {
- if (!isOpen()
- || year < 1980
- || year > 2107
- || month < 1
- || month > 12
- || day < 1
- || day > 31
- || hour > 23
- || minute > 59
- || second > 59) {
- return false;
- }
- dir_t* d = cacheDirEntry(SdVolume::CACHE_FOR_WRITE);
- if (!d) return false;
-
- uint16_t dirDate = FAT_DATE(year, month, day);
- uint16_t dirTime = FAT_TIME(hour, minute, second);
- if (flags & T_ACCESS) {
- d->lastAccessDate = dirDate;
- }
- if (flags & T_CREATE) {
- d->creationDate = dirDate;
- d->creationTime = dirTime;
-
- d->creationTimeTenths = second & 1 ? 100 : 0;
- }
- if (flags & T_WRITE) {
- d->lastWriteDate = dirDate;
- d->lastWriteTime = dirTime;
- }
- SdVolume::cacheSetDirty();
- return sync();
- }
-
-
- uint8_t SdFile::truncate(uint32_t length) {
-
- if (!isFile() || !(flags_ & O_WRITE)) return false;
-
-
- if (length > fileSize_) return false;
-
-
- if (fileSize_ == 0) return true;
-
-
- uint32_t newPos = curPosition_ > length ? length : curPosition_;
-
-
- if (!seekSet(length)) return false;
-
- if (length == 0) {
-
- if (!vol_->freeChain(firstCluster_)) return false;
- firstCluster_ = 0;
- } else {
- uint32_t toFree;
- if (!vol_->fatGet(curCluster_, &toFree)) return false;
-
- if (!vol_->isEOC(toFree)) {
-
- if (!vol_->freeChain(toFree)) return false;
-
-
- if (!vol_->fatPutEOC(curCluster_)) return false;
- }
- }
- fileSize_ = length;
-
-
- flags_ |= F_FILE_DIR_DIRTY;
-
- if (!sync()) return false;
-
-
- return seekSet(newPos);
- }
-
-
- size_t SdFile::write(const void* buf, size_t nbyte) {
-
- const uint8_t* src = reinterpret_cast<const uint8_t*>(buf);
-
-
- size_t nToWrite = nbyte;
-
-
- if (!isFile() || !(flags_ & O_WRITE)) goto writeErrorReturn;
-
-
- if ((flags_ & O_APPEND) && curPosition_ != fileSize_) {
- if (!seekEnd()) goto writeErrorReturn;
- }
-
- while (nToWrite > 0) {
- uint8_t blockOfCluster = vol_->blockOfCluster(curPosition_);
- uint16_t blockOffset = curPosition_ & 0X1FF;
- if (blockOfCluster == 0 && blockOffset == 0) {
-
- if (curCluster_ == 0) {
- if (firstCluster_ == 0) {
-
- if (!addCluster()) goto writeErrorReturn;
- } else {
- curCluster_ = firstCluster_;
- }
- } else {
- uint32_t next;
- if (!vol_->fatGet(curCluster_, &next)) return false;
- if (vol_->isEOC(next)) {
-
- if (!addCluster()) goto writeErrorReturn;
- } else {
- curCluster_ = next;
- }
- }
- }
-
- uint16_t n = 512 - blockOffset;
-
-
- if (n > nToWrite) n = nToWrite;
-
-
- uint32_t block = vol_->clusterStartBlock(curCluster_) + blockOfCluster;
- if (n == 512) {
-
-
- if (SdVolume::cacheBlockNumber_ == block) {
- SdVolume::cacheBlockNumber_ = 0XFFFFFFFF;
- }
- if (!vol_->writeBlock(block, src)) goto writeErrorReturn;
- src += 512;
- } else {
- if (blockOffset == 0 && curPosition_ >= fileSize_) {
-
- if (!SdVolume::cacheFlush()) goto writeErrorReturn;
- SdVolume::cacheBlockNumber_ = block;
- SdVolume::cacheSetDirty();
- } else {
-
- if (!SdVolume::cacheRawBlock(block, SdVolume::CACHE_FOR_WRITE)) {
- goto writeErrorReturn;
- }
- }
- uint8_t* dst = SdVolume::cacheBuffer_.data + blockOffset;
- uint8_t* end = dst + n;
- while (dst != end) *dst++ = *src++;
- }
- nToWrite -= n;
- curPosition_ += n;
- }
- if (curPosition_ > fileSize_) {
-
- fileSize_ = curPosition_;
- flags_ |= F_FILE_DIR_DIRTY;
- } else if (dateTime_ && nbyte) {
-
- flags_ |= F_FILE_DIR_DIRTY;
- }
-
- if (flags_ & O_SYNC) {
- if (!sync()) goto writeErrorReturn;
- }
- return nbyte;
-
- writeErrorReturn:
-
-
- setWriteError();
- return 0;
- }
-
-
- size_t SdFile::write(uint8_t b) {
- return write(&b, 1);
- }
-
-
- size_t SdFile::write(const char* str) {
- return write(str, strlen(str));
- }
-
-
- void SdFile::write_P(PGM_P str) {
- for (uint8_t c; (c = pgm_read_byte(str)); str++) write(c);
- }
-
-
- void SdFile::writeln_P(PGM_P str) {
- write_P(str);
- println();
- }
|