Subversion Repositories MK-Marlin

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
1 ron 1
/**
2
 * Marlin 3D Printer Firmware
3
 * Copyright (C) 2016 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
4
 *
5
 * Based on Sprinter and grbl.
6
 * Copyright (C) 2011 Camiel Gubbels / Erik van der Zalm
7
 *
8
 * This program is free software: you can redistribute it and/or modify
9
 * it under the terms of the GNU General Public License as published by
10
 * the Free Software Foundation, either version 3 of the License, or
11
 * (at your option) any later version.
12
 *
13
 * This program is distributed in the hope that it will be useful,
14
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16
 * GNU General Public License for more details.
17
 *
18
 * You should have received a copy of the GNU General Public License
19
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
20
 *
21
 */
22
 
23
/**
24
 * Arduino SdFat Library
25
 * Copyright (C) 2009 by William Greiman
26
 *
27
 * This file is part of the Arduino Sd2Card Library
28
 */
29
 
30
#include "MarlinConfig.h"
31
 
32
#if ENABLED(SDSUPPORT)
33
 
34
#include "SdBaseFile.h"
35
#include "Marlin.h"
36
 
37
SdBaseFile* SdBaseFile::cwd_ = 0;   // Pointer to Current Working Directory
38
 
39
// callback function for date/time
40
void (*SdBaseFile::dateTime_)(uint16_t* date, uint16_t* time) = 0;
41
 
42
// add a cluster to a file
43
bool SdBaseFile::addCluster() {
44
  if (!vol_->allocContiguous(1, &curCluster_)) return false;
45
 
46
  // if first cluster of file link to directory entry
47
  if (firstCluster_ == 0) {
48
    firstCluster_ = curCluster_;
49
    flags_ |= F_FILE_DIR_DIRTY;
50
  }
51
  return true;
52
}
53
 
54
// Add a cluster to a directory file and zero the cluster.
55
// return with first block of cluster in the cache
56
bool SdBaseFile::addDirCluster() {
57
  uint32_t block;
58
  // max folder size
59
  if (fileSize_ / sizeof(dir_t) >= 0xFFFF) return false;
60
 
61
  if (!addCluster()) return false;
62
  if (!vol_->cacheFlush()) return false;
63
 
64
  block = vol_->clusterStartBlock(curCluster_);
65
 
66
  // set cache to first block of cluster
67
  vol_->cacheSetBlockNumber(block, true);
68
 
69
  // zero first block of cluster
70
  memset(vol_->cacheBuffer_.data, 0, 512);
71
 
72
  // zero rest of cluster
73
  for (uint8_t i = 1; i < vol_->blocksPerCluster_; i++) {
74
    if (!vol_->writeBlock(block + i, vol_->cacheBuffer_.data)) return false;
75
  }
76
  // Increase directory file size by cluster size
77
  fileSize_ += 512UL << vol_->clusterSizeShift_;
78
  return true;
79
}
80
 
81
// cache a file's directory entry
82
// return pointer to cached entry or null for failure
83
dir_t* SdBaseFile::cacheDirEntry(uint8_t action) {
84
  if (!vol_->cacheRawBlock(dirBlock_, action)) return NULL;
85
  return vol_->cache()->dir + dirIndex_;
86
}
87
 
88
/**
89
 * Close a file and force cached data and directory information
90
 *  to be written to the storage device.
91
 *
92
 * \return true for success, false for failure.
93
 * Reasons for failure include no file is open or an I/O error.
94
 */
95
bool SdBaseFile::close() {
96
  bool rtn = sync();
97
  type_ = FAT_FILE_TYPE_CLOSED;
98
  return rtn;
99
}
100
 
101
/**
102
 * Check for contiguous file and return its raw block range.
103
 *
104
 * \param[out] bgnBlock the first block address for the file.
105
 * \param[out] endBlock the last  block address for the file.
106
 *
107
 * \return true for success, false for failure.
108
 * Reasons for failure include file is not contiguous, file has zero length
109
 * or an I/O error occurred.
110
 */
111
bool SdBaseFile::contiguousRange(uint32_t* bgnBlock, uint32_t* endBlock) {
112
  // error if no blocks
113
  if (firstCluster_ == 0) return false;
114
 
115
  for (uint32_t c = firstCluster_; ; c++) {
116
    uint32_t next;
117
    if (!vol_->fatGet(c, &next)) return false;
118
 
119
    // check for contiguous
120
    if (next != (c + 1)) {
121
      // error if not end of chain
122
      if (!vol_->isEOC(next)) return false;
123
      *bgnBlock = vol_->clusterStartBlock(firstCluster_);
124
      *endBlock = vol_->clusterStartBlock(c)
125
                  + vol_->blocksPerCluster_ - 1;
126
      return true;
127
    }
128
  }
129
  return false;
130
}
131
 
132
/**
133
 * Create and open a new contiguous file of a specified size.
134
 *
135
 * \note This function only supports short DOS 8.3 names.
136
 * See open() for more information.
137
 *
138
 * \param[in] dirFile The directory where the file will be created.
139
 * \param[in] path A path with a valid DOS 8.3 file name.
140
 * \param[in] size The desired file size.
141
 *
142
 * \return true for success, false for failure.
143
 * Reasons for failure include \a path contains
144
 * an invalid DOS 8.3 file name, the FAT volume has not been initialized,
145
 * a file is already open, the file already exists, the root
146
 * directory is full or an I/O error.
147
 *
148
 */
149
bool SdBaseFile::createContiguous(SdBaseFile* dirFile, const char* path, uint32_t size) {
150
  uint32_t count;
151
  // don't allow zero length file
152
  if (size == 0) return false;
153
  if (!open(dirFile, path, O_CREAT | O_EXCL | O_RDWR)) return false;
154
 
155
  // calculate number of clusters needed
156
  count = ((size - 1) >> (vol_->clusterSizeShift_ + 9)) + 1;
157
 
158
  // allocate clusters
159
  if (!vol_->allocContiguous(count, &firstCluster_)) {
160
    remove();
161
    return false;
162
  }
163
  fileSize_ = size;
164
 
165
  // insure sync() will update dir entry
166
  flags_ |= F_FILE_DIR_DIRTY;
167
 
168
  return sync();
169
}
170
 
171
/**
172
 * Return a file's directory entry.
173
 *
174
 * \param[out] dir Location for return of the file's directory entry.
175
 *
176
 * \return true for success, false for failure.
177
 */
178
bool SdBaseFile::dirEntry(dir_t* dir) {
179
  dir_t* p;
180
  // make sure fields on SD are correct
181
  if (!sync()) return false;
182
 
183
  // read entry
184
  p = cacheDirEntry(SdVolume::CACHE_FOR_READ);
185
  if (!p) return false;
186
 
187
  // copy to caller's struct
188
  memcpy(dir, p, sizeof(dir_t));
189
  return true;
190
}
191
 
192
/**
193
 * Format the name field of \a dir into the 13 byte array
194
 * \a name in standard 8.3 short name format.
195
 *
196
 * \param[in] dir The directory structure containing the name.
197
 * \param[out] name A 13 byte char array for the formatted name.
198
 */
199
void SdBaseFile::dirName(const dir_t& dir, char* name) {
200
  uint8_t j = 0;
201
  for (uint8_t i = 0; i < 11; i++) {
202
    if (dir.name[i] == ' ')continue;
203
    if (i == 8) name[j++] = '.';
204
    name[j++] = dir.name[i];
205
  }
206
  name[j] = 0;
207
}
208
 
209
/**
210
 * Test for the existence of a file in a directory
211
 *
212
 * \param[in] name Name of the file to be tested for.
213
 *
214
 * The calling instance must be an open directory file.
215
 *
216
 * dirFile.exists("TOFIND.TXT") searches for "TOFIND.TXT" in  the directory
217
 * dirFile.
218
 *
219
 * \return true if the file exists else false.
220
 */
221
bool SdBaseFile::exists(const char* name) {
222
  SdBaseFile file;
223
  return file.open(this, name, O_READ);
224
}
225
 
226
/**
227
 * Get a string from a file.
228
 *
229
 * fgets() reads bytes from a file into the array pointed to by \a str, until
230
 * \a num - 1 bytes are read, or a delimiter is read and transferred to \a str,
231
 * or end-of-file is encountered. The string is then terminated
232
 * with a null byte.
233
 *
234
 * fgets() deletes CR, '\\r', from the string.  This insures only a '\\n'
235
 * terminates the string for Windows text files which use CRLF for newline.
236
 *
237
 * \param[out] str Pointer to the array where the string is stored.
238
 * \param[in] num Maximum number of characters to be read
239
 * (including the final null byte). Usually the length
240
 * of the array \a str is used.
241
 * \param[in] delim Optional set of delimiters. The default is "\n".
242
 *
243
 * \return For success fgets() returns the length of the string in \a str.
244
 * If no data is read, fgets() returns zero for EOF or -1 if an error occurred.
245
 **/
246
int16_t SdBaseFile::fgets(char* str, int16_t num, char* delim) {
247
  char ch;
248
  int16_t n = 0;
249
  int16_t r = -1;
250
  while ((n + 1) < num && (r = read(&ch, 1)) == 1) {
251
    // delete CR
252
    if (ch == '\r') continue;
253
    str[n++] = ch;
254
    if (!delim) {
255
      if (ch == '\n') break;
256
    }
257
    else {
258
      if (strchr(delim, ch)) break;
259
    }
260
  }
261
  if (r < 0) {
262
    // read error
263
    return -1;
264
  }
265
  str[n] = '\0';
266
  return n;
267
}
268
 
269
/**
270
 * Get a file's name
271
 *
272
 * \param[out] name An array of 13 characters for the file's name.
273
 *
274
 * \return true for success, false for failure.
275
 */
276
bool SdBaseFile::getFilename(char * const name) {
277
  if (!isOpen()) return false;
278
 
279
  if (isRoot()) {
280
    name[0] = '/';
281
    name[1] = '\0';
282
    return true;
283
  }
284
  // cache entry
285
  dir_t* p = cacheDirEntry(SdVolume::CACHE_FOR_READ);
286
  if (!p) return false;
287
 
288
  // format name
289
  dirName(*p, name);
290
  return true;
291
}
292
 
293
void SdBaseFile::getpos(filepos_t* pos) {
294
  pos->position = curPosition_;
295
  pos->cluster = curCluster_;
296
}
297
 
298
/**
299
 * List directory contents.
300
 *
301
 * \param[in] pr Print stream for list.
302
 *
303
 * \param[in] flags The inclusive OR of
304
 *
305
 * LS_DATE - %Print file modification date
306
 *
307
 * LS_SIZE - %Print file size.
308
 *
309
 * LS_R - Recursive list of subdirectories.
310
 *
311
 * \param[in] indent Amount of space before file name. Used for recursive
312
 * list to indicate subdirectory level.
313
 */
314
void SdBaseFile::ls(uint8_t flags, uint8_t indent) {
315
  rewind();
316
  int8_t status;
317
  while ((status = lsPrintNext(flags, indent))) {
318
    if (status > 1 && (flags & LS_R)) {
319
      uint16_t index = curPosition() / 32 - 1;
320
      SdBaseFile s;
321
      if (s.open(this, index, O_READ)) s.ls(flags, indent + 2);
322
      seekSet(32 * (index + 1));
323
    }
324
  }
325
}
326
 
327
// saves 32 bytes on stack for ls recursion
328
// return 0 - EOF, 1 - normal file, or 2 - directory
329
int8_t SdBaseFile::lsPrintNext(uint8_t flags, uint8_t indent) {
330
  dir_t dir;
331
  uint8_t w = 0;
332
 
333
  while (1) {
334
    if (read(&dir, sizeof(dir)) != sizeof(dir)) return 0;
335
    if (dir.name[0] == DIR_NAME_FREE) return 0;
336
 
337
    // skip deleted entry and entries for . and  ..
338
    if (dir.name[0] != DIR_NAME_DELETED && dir.name[0] != '.'
339
        && DIR_IS_FILE_OR_SUBDIR(&dir)) break;
340
  }
341
  // indent for dir level
342
  for (uint8_t i = 0; i < indent; i++) SERIAL_CHAR(' ');
343
 
344
  // print name
345
  for (uint8_t i = 0; i < 11; i++) {
346
    if (dir.name[i] == ' ')continue;
347
    if (i == 8) {
348
      SERIAL_CHAR('.');
349
      w++;
350
    }
351
    SERIAL_CHAR(dir.name[i]);
352
    w++;
353
  }
354
  if (DIR_IS_SUBDIR(&dir)) {
355
    SERIAL_CHAR('/');
356
    w++;
357
  }
358
  if (flags & (LS_DATE | LS_SIZE)) {
359
    while (w++ < 14) SERIAL_CHAR(' ');
360
  }
361
  // print modify date/time if requested
362
  if (flags & LS_DATE) {
363
    SERIAL_CHAR(' ');
364
    printFatDate(dir.lastWriteDate);
365
    SERIAL_CHAR(' ');
366
    printFatTime(dir.lastWriteTime);
367
  }
368
  // print size if requested
369
  if (!DIR_IS_SUBDIR(&dir) && (flags & LS_SIZE)) {
370
    SERIAL_CHAR(' ');
371
    SERIAL_ECHO(dir.fileSize);
372
  }
373
  SERIAL_EOL();
374
  return DIR_IS_FILE(&dir) ? 1 : 2;
375
}
376
 
377
// Format directory name field from a 8.3 name string
378
bool SdBaseFile::make83Name(const char* str, uint8_t* name, const char** ptr) {
379
  uint8_t n = 7,                      // Max index until a dot is found
380
          i = 11;
381
  while (i) name[--i] = ' ';          // Set whole FILENAME.EXT to spaces
382
  while (*str && *str != '/') {       // For each character, until nul or '/'
383
    uint8_t c = *str++;               // Get char and advance
384
    if (c == '.') {                   // For a dot...
385
      if (n == 10) return false;      // Already moved the max index? fail!
386
      n = 10;                         // Move the max index for full 8.3 name
387
      i = 8;                          // Move up to the extension place
388
    }
389
    else {
390
      // Fail for illegal characters
391
      PGM_P p = PSTR("|<>^+=?/[];,*\"\\");
392
      while (uint8_t b = pgm_read_byte(p++)) if (b == c) return false;
393
      if (i > n || c < 0x21 || c == 0x7F) return false;           // Check size, non-printable characters
394
      name[i++] = (c < 'a' || c > 'z') ? (c) : (c + ('A' - 'a')); // Uppercase required for 8.3 name
395
    }
396
  }
397
  *ptr = str;                         // Set passed pointer to the end
398
  return name[0] != ' ';              // Return true if any name was set
399
}
400
 
401
/**
402
 * Make a new directory.
403
 *
404
 * \param[in] parent An open SdFat instance for the directory that will contain
405
 * the new directory.
406
 *
407
 * \param[in] path A path with a valid 8.3 DOS name for the new directory.
408
 *
409
 * \param[in] pFlag Create missing parent directories if true.
410
 *
411
 * \return true for success, false for failure.
412
 * Reasons for failure include this file is already open, \a parent is not a
413
 * directory, \a path is invalid or already exists in \a parent.
414
 */
415
bool SdBaseFile::mkdir(SdBaseFile* parent, const char* path, bool pFlag) {
416
  uint8_t dname[11];
417
  SdBaseFile dir1, dir2;
418
  SdBaseFile* sub = &dir1;
419
  SdBaseFile* start = parent;
420
 
421
  if (!parent || isOpen()) return false;
422
 
423
  if (*path == '/') {
424
    while (*path == '/') path++;
425
    if (!parent->isRoot()) {
426
      if (!dir2.openRoot(parent->vol_)) return false;
427
      parent = &dir2;
428
    }
429
  }
430
  while (1) {
431
    if (!make83Name(path, dname, &path)) return false;
432
    while (*path == '/') path++;
433
    if (!*path) break;
434
    if (!sub->open(parent, dname, O_READ)) {
435
      if (!pFlag || !sub->mkdir(parent, dname))
436
        return false;
437
    }
438
    if (parent != start) parent->close();
439
    parent = sub;
440
    sub = parent != &dir1 ? &dir1 : &dir2;
441
  }
442
  return mkdir(parent, dname);
443
}
444
 
445
bool SdBaseFile::mkdir(SdBaseFile* parent, const uint8_t dname[11]) {
446
  uint32_t block;
447
  dir_t d;
448
  dir_t* p;
449
 
450
  if (!parent->isDir()) return false;
451
 
452
  // create a normal file
453
  if (!open(parent, dname, O_CREAT | O_EXCL | O_RDWR)) return false;
454
 
455
  // convert file to directory
456
  flags_ = O_READ;
457
  type_ = FAT_FILE_TYPE_SUBDIR;
458
 
459
  // allocate and zero first cluster
460
  if (!addDirCluster()) return false;
461
 
462
  // force entry to SD
463
  if (!sync()) return false;
464
 
465
  // cache entry - should already be in cache due to sync() call
466
  p = cacheDirEntry(SdVolume::CACHE_FOR_WRITE);
467
  if (!p) return false;
468
 
469
  // change directory entry  attribute
470
  p->attributes = DIR_ATT_DIRECTORY;
471
 
472
  // make entry for '.'
473
  memcpy(&d, p, sizeof(d));
474
  d.name[0] = '.';
475
  for (uint8_t i = 1; i < 11; i++) d.name[i] = ' ';
476
 
477
  // cache block for '.'  and '..'
478
  block = vol_->clusterStartBlock(firstCluster_);
479
  if (!vol_->cacheRawBlock(block, SdVolume::CACHE_FOR_WRITE)) return false;
480
 
481
  // copy '.' to block
482
  memcpy(&vol_->cache()->dir[0], &d, sizeof(d));
483
 
484
  // make entry for '..'
485
  d.name[1] = '.';
486
  if (parent->isRoot()) {
487
    d.firstClusterLow = 0;
488
    d.firstClusterHigh = 0;
489
  }
490
  else {
491
    d.firstClusterLow = parent->firstCluster_ & 0xFFFF;
492
    d.firstClusterHigh = parent->firstCluster_ >> 16;
493
  }
494
  // copy '..' to block
495
  memcpy(&vol_->cache()->dir[1], &d, sizeof(d));
496
 
497
  // write first block
498
  return vol_->cacheFlush();
499
}
500
 
501
/**
502
 * Open a file in the current working directory.
503
 *
504
 * \param[in] path A path with a valid 8.3 DOS name for a file to be opened.
505
 *
506
 * \param[in] oflag Values for \a oflag are constructed by a bitwise-inclusive
507
 * OR of open flags. see SdBaseFile::open(SdBaseFile*, const char*, uint8_t).
508
 *
509
 * \return true for success, false for failure.
510
 */
511
bool SdBaseFile::open(const char* path, uint8_t oflag) {
512
  return open(cwd_, path, oflag);
513
}
514
 
515
/**
516
 * Open a file or directory by name.
517
 *
518
 * \param[in] dirFile An open SdFat instance for the directory containing the
519
 * file to be opened.
520
 *
521
 * \param[in] path A path with a valid 8.3 DOS name for a file to be opened.
522
 *
523
 * \param[in] oflag Values for \a oflag are constructed by a bitwise-inclusive
524
 * OR of flags from the following list
525
 *
526
 * O_READ - Open for reading.
527
 *
528
 * O_RDONLY - Same as O_READ.
529
 *
530
 * O_WRITE - Open for writing.
531
 *
532
 * O_WRONLY - Same as O_WRITE.
533
 *
534
 * O_RDWR - Open for reading and writing.
535
 *
536
 * O_APPEND - If set, the file offset shall be set to the end of the
537
 * file prior to each write.
538
 *
539
 * O_AT_END - Set the initial position at the end of the file.
540
 *
541
 * O_CREAT - If the file exists, this flag has no effect except as noted
542
 * under O_EXCL below. Otherwise, the file shall be created
543
 *
544
 * O_EXCL - If O_CREAT and O_EXCL are set, open() shall fail if the file exists.
545
 *
546
 * O_SYNC - Call sync() after each write.  This flag should not be used with
547
 * write(uint8_t), write_P(PGM_P), writeln_P(PGM_P), or the Arduino Print class.
548
 * These functions do character at a time writes so sync() will be called
549
 * after each byte.
550
 *
551
 * O_TRUNC - If the file exists and is a regular file, and the file is
552
 * successfully opened and is not read only, its length shall be truncated to 0.
553
 *
554
 * WARNING: A given file must not be opened by more than one SdBaseFile object
555
 * of file corruption may occur.
556
 *
557
 * \note Directory files must be opened read only.  Write and truncation is
558
 * not allowed for directory files.
559
 *
560
 * \return true for success, false for failure.
561
 * Reasons for failure include this file is already open, \a dirFile is not
562
 * a directory, \a path is invalid, the file does not exist
563
 * or can't be opened in the access mode specified by oflag.
564
 */
565
bool SdBaseFile::open(SdBaseFile* dirFile, const char* path, uint8_t oflag) {
566
  uint8_t dname[11];
567
  SdBaseFile dir1, dir2;
568
  SdBaseFile *parent = dirFile, *sub = &dir1;
569
 
570
  if (!dirFile || isOpen()) return false;
571
 
572
  if (*path == '/') {                                         // Path starts with '/'
573
    if (!dirFile->isRoot()) {                                 // Is the passed dirFile the root?
574
      if (!dir2.openRoot(dirFile->vol_)) return false;        // Get the root in dir2, if possible
575
      parent = &dir2;                                         // Change 'parent' to point at the root dir
576
    }
577
    while (*path == '/') path++;                              // Skip all leading slashes
578
  }
579
 
580
  for (;;) {
581
    if (!make83Name(path, dname, &path)) return false;
582
    while (*path == '/') path++;
583
    if (!*path) break;
584
    if (!sub->open(parent, dname, O_READ)) return false;
585
    if (parent != dirFile) parent->close();
586
    parent = sub;
587
    sub = parent != &dir1 ? &dir1 : &dir2;
588
  }
589
  return open(parent, dname, oflag);
590
}
591
 
592
// open with filename in dname
593
bool SdBaseFile::open(SdBaseFile* dirFile, const uint8_t dname[11], uint8_t oflag) {
594
  bool emptyFound = false, fileFound = false;
595
  uint8_t index;
596
  dir_t* p;
597
 
598
  vol_ = dirFile->vol_;
599
 
600
  dirFile->rewind();
601
  // search for file
602
 
603
  while (dirFile->curPosition_ < dirFile->fileSize_) {
604
    index = 0xF & (dirFile->curPosition_ >> 5);
605
    p = dirFile->readDirCache();
606
    if (!p) return false;
607
 
608
    if (p->name[0] == DIR_NAME_FREE || p->name[0] == DIR_NAME_DELETED) {
609
      // remember first empty slot
610
      if (!emptyFound) {
611
        dirBlock_ = dirFile->vol_->cacheBlockNumber();
612
        dirIndex_ = index;
613
        emptyFound = true;
614
      }
615
      // done if no entries follow
616
      if (p->name[0] == DIR_NAME_FREE) break;
617
    }
618
    else if (!memcmp(dname, p->name, 11)) {
619
      fileFound = true;
620
      break;
621
    }
622
  }
623
  if (fileFound) {
624
    // don't open existing file if O_EXCL
625
    if (oflag & O_EXCL) return false;
626
  }
627
  else {
628
    // don't create unless O_CREAT and O_WRITE
629
    if (!(oflag & O_CREAT) || !(oflag & O_WRITE)) return false;
630
    if (emptyFound) {
631
      index = dirIndex_;
632
      p = cacheDirEntry(SdVolume::CACHE_FOR_WRITE);
633
      if (!p) return false;
634
    }
635
    else {
636
      if (dirFile->type_ == FAT_FILE_TYPE_ROOT_FIXED) return false;
637
 
638
      // add and zero cluster for dirFile - first cluster is in cache for write
639
      if (!dirFile->addDirCluster()) return false;
640
 
641
      // use first entry in cluster
642
      p = dirFile->vol_->cache()->dir;
643
      index = 0;
644
    }
645
    // initialize as empty file
646
    memset(p, 0, sizeof(*p));
647
    memcpy(p->name, dname, 11);
648
 
649
    // set timestamps
650
    if (dateTime_) {
651
      // call user date/time function
652
      dateTime_(&p->creationDate, &p->creationTime);
653
    }
654
    else {
655
      // use default date/time
656
      p->creationDate = FAT_DEFAULT_DATE;
657
      p->creationTime = FAT_DEFAULT_TIME;
658
    }
659
    p->lastAccessDate = p->creationDate;
660
    p->lastWriteDate = p->creationDate;
661
    p->lastWriteTime = p->creationTime;
662
 
663
    // write entry to SD
664
    if (!dirFile->vol_->cacheFlush()) return false;
665
  }
666
  // open entry in cache
667
  return openCachedEntry(index, oflag);
668
}
669
 
670
/**
671
 * Open a file by index.
672
 *
673
 * \param[in] dirFile An open SdFat instance for the directory.
674
 *
675
 * \param[in] index The \a index of the directory entry for the file to be
676
 * opened.  The value for \a index is (directory file position)/32.
677
 *
678
 * \param[in] oflag Values for \a oflag are constructed by a bitwise-inclusive
679
 * OR of flags O_READ, O_WRITE, O_TRUNC, and O_SYNC.
680
 *
681
 * See open() by path for definition of flags.
682
 * \return true for success or false for failure.
683
 */
684
bool SdBaseFile::open(SdBaseFile* dirFile, uint16_t index, uint8_t oflag) {
685
  dir_t* p;
686
 
687
  vol_ = dirFile->vol_;
688
 
689
  // error if already open
690
  if (isOpen() || !dirFile) return false;
691
 
692
  // don't open existing file if O_EXCL - user call error
693
  if (oflag & O_EXCL) return false;
694
 
695
  // seek to location of entry
696
  if (!dirFile->seekSet(32 * index)) return false;
697
 
698
  // read entry into cache
699
  p = dirFile->readDirCache();
700
  if (!p) return false;
701
 
702
  // error if empty slot or '.' or '..'
703
  if (p->name[0] == DIR_NAME_FREE ||
704
      p->name[0] == DIR_NAME_DELETED || p->name[0] == '.') {
705
    return false;
706
  }
707
  // open cached entry
708
  return openCachedEntry(index & 0xF, oflag);
709
}
710
 
711
// open a cached directory entry. Assumes vol_ is initialized
712
bool SdBaseFile::openCachedEntry(uint8_t dirIndex, uint8_t oflag) {
713
  // location of entry in cache
714
  dir_t* p = &vol_->cache()->dir[dirIndex];
715
 
716
  // write or truncate is an error for a directory or read-only file
717
  if (p->attributes & (DIR_ATT_READ_ONLY | DIR_ATT_DIRECTORY)) {
718
    if (oflag & (O_WRITE | O_TRUNC)) goto FAIL;
719
  }
720
  // remember location of directory entry on SD
721
  dirBlock_ = vol_->cacheBlockNumber();
722
  dirIndex_ = dirIndex;
723
 
724
  // copy first cluster number for directory fields
725
  firstCluster_ = (uint32_t)p->firstClusterHigh << 16;
726
  firstCluster_ |= p->firstClusterLow;
727
 
728
  // make sure it is a normal file or subdirectory
729
  if (DIR_IS_FILE(p)) {
730
    fileSize_ = p->fileSize;
731
    type_ = FAT_FILE_TYPE_NORMAL;
732
  }
733
  else if (DIR_IS_SUBDIR(p)) {
734
    if (!vol_->chainSize(firstCluster_, &fileSize_)) goto FAIL;
735
    type_ = FAT_FILE_TYPE_SUBDIR;
736
  }
737
  else
738
    goto FAIL;
739
 
740
  // save open flags for read/write
741
  flags_ = oflag & F_OFLAG;
742
 
743
  // set to start of file
744
  curCluster_ = 0;
745
  curPosition_ = 0;
746
  if ((oflag & O_TRUNC) && !truncate(0)) return false;
747
  return oflag & O_AT_END ? seekEnd(0) : true;
748
 
749
  FAIL:
750
  type_ = FAT_FILE_TYPE_CLOSED;
751
  return false;
752
}
753
 
754
/**
755
 * Open the next file or subdirectory in a directory.
756
 *
757
 * \param[in] dirFile An open SdFat instance for the directory containing the
758
 * file to be opened.
759
 *
760
 * \param[in] oflag Values for \a oflag are constructed by a bitwise-inclusive
761
 * OR of flags O_READ, O_WRITE, O_TRUNC, and O_SYNC.
762
 *
763
 * See open() by path for definition of flags.
764
 * \return true for success or false for failure.
765
 */
766
bool SdBaseFile::openNext(SdBaseFile* dirFile, uint8_t oflag) {
767
  dir_t* p;
768
  uint8_t index;
769
 
770
  if (!dirFile) return false;
771
 
772
  // error if already open
773
  if (isOpen()) return false;
774
 
775
  vol_ = dirFile->vol_;
776
 
777
  while (1) {
778
    index = 0xF & (dirFile->curPosition_ >> 5);
779
 
780
    // read entry into cache
781
    p = dirFile->readDirCache();
782
    if (!p) return false;
783
 
784
    // done if last entry
785
    if (p->name[0] == DIR_NAME_FREE) return false;
786
 
787
    // skip empty slot or '.' or '..'
788
    if (p->name[0] == DIR_NAME_DELETED || p->name[0] == '.') {
789
      continue;
790
    }
791
    // must be file or dir
792
    if (DIR_IS_FILE_OR_SUBDIR(p)) {
793
      return openCachedEntry(index, oflag);
794
    }
795
  }
796
  return false;
797
}
798
 
799
#if 0
800
/**
801
 * Open a directory's parent directory.
802
 *
803
 * \param[in] dir Parent of this directory will be opened.  Must not be root.
804
 *
805
 * \return true for success, false for failure.
806
 */
807
bool SdBaseFile::openParent(SdBaseFile* dir) {
808
  dir_t entry;
809
  dir_t* p;
810
  SdBaseFile file;
811
  uint32_t c;
812
  uint32_t cluster;
813
  uint32_t lbn;
814
  // error if already open or dir is root or dir is not a directory
815
  if (isOpen() || !dir || dir->isRoot() || !dir->isDir()) return false;
816
  vol_ = dir->vol_;
817
  // position to '..'
818
  if (!dir->seekSet(32)) return false;
819
  // read '..' entry
820
  if (dir->read(&entry, sizeof(entry)) != 32) return false;
821
  // verify it is '..'
822
  if (entry.name[0] != '.' || entry.name[1] != '.') return false;
823
  // start cluster for '..'
824
  cluster = entry.firstClusterLow;
825
  cluster |= (uint32_t)entry.firstClusterHigh << 16;
826
  if (cluster == 0) return openRoot(vol_);
827
  // start block for '..'
828
  lbn = vol_->clusterStartBlock(cluster);
829
  // first block of parent dir
830
  if (!vol_->cacheRawBlock(lbn, SdVolume::CACHE_FOR_READ)) return false;
831
 
832
  p = &vol_->cacheBuffer_.dir[1];
833
  // verify name for '../..'
834
  if (p->name[0] != '.' || p->name[1] != '.') return false;
835
  // '..' is pointer to first cluster of parent. open '../..' to find parent
836
  if (p->firstClusterHigh == 0 && p->firstClusterLow == 0) {
837
    if (!file.openRoot(dir->volume())) return false;
838
  }
839
  else if (!file.openCachedEntry(1, O_READ))
840
    return false;
841
 
842
  // search for parent in '../..'
843
  do {
844
    if (file.readDir(&entry, NULL) != 32) return false;
845
    c = entry.firstClusterLow;
846
    c |= (uint32_t)entry.firstClusterHigh << 16;
847
  } while (c != cluster);
848
 
849
  // open parent
850
  return open(&file, file.curPosition() / 32 - 1, O_READ);
851
}
852
#endif
853
 
854
/**
855
 * Open a volume's root directory.
856
 *
857
 * \param[in] vol The FAT volume containing the root directory to be opened.
858
 *
859
 * \return true for success, false for failure.
860
 * Reasons for failure include the file is already open, the FAT volume has
861
 * not been initialized or it a FAT12 volume.
862
 */
863
bool SdBaseFile::openRoot(SdVolume* vol) {
864
  // error if file is already open
865
  if (isOpen()) return false;
866
 
867
  if (vol->fatType() == 16 || (FAT12_SUPPORT && vol->fatType() == 12)) {
868
    type_ = FAT_FILE_TYPE_ROOT_FIXED;
869
    firstCluster_ = 0;
870
    fileSize_ = 32 * vol->rootDirEntryCount();
871
  }
872
  else if (vol->fatType() == 32) {
873
    type_ = FAT_FILE_TYPE_ROOT32;
874
    firstCluster_ = vol->rootDirStart();
875
    if (!vol->chainSize(firstCluster_, &fileSize_)) return false;
876
  }
877
  else // volume is not initialized, invalid, or FAT12 without support
878
    return false;
879
 
880
  vol_ = vol;
881
  // read only
882
  flags_ = O_READ;
883
 
884
  // set to start of file
885
  curCluster_ = curPosition_ = 0;
886
 
887
  // root has no directory entry
888
  dirBlock_ = dirIndex_ = 0;
889
  return true;
890
}
891
 
892
/**
893
 * Return the next available byte without consuming it.
894
 *
895
 * \return The byte if no error and not at eof else -1;
896
 */
897
int SdBaseFile::peek() {
898
  filepos_t pos;
899
  getpos(&pos);
900
  int c = read();
901
  if (c >= 0) setpos(&pos);
902
  return c;
903
}
904
 
905
// print uint8_t with width 2
906
static void print2u(const uint8_t v) {
907
  if (v < 10) SERIAL_CHAR('0');
908
  SERIAL_ECHO_F(v, DEC);
909
}
910
 
911
/**
912
 * %Print a directory date field to Serial.
913
 *
914
 *  Format is yyyy-mm-dd.
915
 *
916
 * \param[in] fatDate The date field from a directory entry.
917
 */
918
 
919
 
920
/**
921
 * %Print a directory date field.
922
 *
923
 *  Format is yyyy-mm-dd.
924
 *
925
 * \param[in] pr Print stream for output.
926
 * \param[in] fatDate The date field from a directory entry.
927
 */
928
void SdBaseFile::printFatDate(uint16_t fatDate) {
929
  SERIAL_ECHO(FAT_YEAR(fatDate));
930
  SERIAL_CHAR('-');
931
  print2u(FAT_MONTH(fatDate));
932
  SERIAL_CHAR('-');
933
  print2u(FAT_DAY(fatDate));
934
}
935
 
936
 
937
/**
938
 * %Print a directory time field.
939
 *
940
 * Format is hh:mm:ss.
941
 *
942
 * \param[in] pr Print stream for output.
943
 * \param[in] fatTime The time field from a directory entry.
944
 */
945
void SdBaseFile::printFatTime(uint16_t fatTime) {
946
  print2u(FAT_HOUR(fatTime));
947
  SERIAL_CHAR(':');
948
  print2u(FAT_MINUTE(fatTime));
949
  SERIAL_CHAR(':');
950
  print2u(FAT_SECOND(fatTime));
951
}
952
 
953
/**
954
 * Print a file's name to Serial
955
 *
956
 * \return true for success, false for failure.
957
 */
958
bool SdBaseFile::printName() {
959
  char name[FILENAME_LENGTH];
960
  if (!getFilename(name)) return false;
961
  SERIAL_ECHO(name);
962
  return true;
963
}
964
 
965
/**
966
 * Read the next byte from a file.
967
 *
968
 * \return For success read returns the next byte in the file as an int.
969
 * If an error occurs or end of file is reached -1 is returned.
970
 */
971
int16_t SdBaseFile::read() {
972
  uint8_t b;
973
  return read(&b, 1) == 1 ? b : -1;
974
}
975
 
976
/**
977
 * Read data from a file starting at the current position.
978
 *
979
 * \param[out] buf Pointer to the location that will receive the data.
980
 *
981
 * \param[in] nbyte Maximum number of bytes to read.
982
 *
983
 * \return For success read() returns the number of bytes read.
984
 * A value less than \a nbyte, including zero, will be returned
985
 * if end of file is reached.
986
 * If an error occurs, read() returns -1.  Possible errors include
987
 * read() called before a file has been opened, corrupt file system
988
 * or an I/O error occurred.
989
 */
990
int16_t SdBaseFile::read(void* buf, uint16_t nbyte) {
991
  uint8_t* dst = reinterpret_cast<uint8_t*>(buf);
992
  uint16_t offset, toRead;
993
  uint32_t block;  // raw device block number
994
 
995
  // error if not open or write only
996
  if (!isOpen() || !(flags_ & O_READ)) return -1;
997
 
998
  // max bytes left in file
999
  NOMORE(nbyte, fileSize_ - curPosition_);
1000
 
1001
  // amount left to read
1002
  toRead = nbyte;
1003
  while (toRead > 0) {
1004
    offset = curPosition_ & 0x1FF;  // offset in block
1005
    if (type_ == FAT_FILE_TYPE_ROOT_FIXED) {
1006
      block = vol_->rootDirStart() + (curPosition_ >> 9);
1007
    }
1008
    else {
1009
      uint8_t blockOfCluster = vol_->blockOfCluster(curPosition_);
1010
      if (offset == 0 && blockOfCluster == 0) {
1011
        // start of new cluster
1012
        if (curPosition_ == 0)
1013
          curCluster_ = firstCluster_;                      // use first cluster in file
1014
        else if (!vol_->fatGet(curCluster_, &curCluster_))  // get next cluster from FAT
1015
          return -1;
1016
      }
1017
      block = vol_->clusterStartBlock(curCluster_) + blockOfCluster;
1018
    }
1019
    uint16_t n = toRead;
1020
 
1021
    // amount to be read from current block
1022
    NOMORE(n, 512 - offset);
1023
 
1024
    // no buffering needed if n == 512
1025
    if (n == 512 && block != vol_->cacheBlockNumber()) {
1026
      if (!vol_->readBlock(block, dst)) return -1;
1027
    }
1028
    else {
1029
      // read block to cache and copy data to caller
1030
      if (!vol_->cacheRawBlock(block, SdVolume::CACHE_FOR_READ)) return -1;
1031
      uint8_t* src = vol_->cache()->data + offset;
1032
      memcpy(dst, src, n);
1033
    }
1034
    dst += n;
1035
    curPosition_ += n;
1036
    toRead -= n;
1037
  }
1038
  return nbyte;
1039
}
1040
 
1041
/**
1042
 * Read the next entry in a directory.
1043
 *
1044
 * \param[out] dir The dir_t struct that will receive the data.
1045
 *
1046
 * \return For success readDir() returns the number of bytes read.
1047
 * A value of zero will be returned if end of file is reached.
1048
 * If an error occurs, readDir() returns -1.  Possible errors include
1049
 * readDir() called before a directory has been opened, this is not
1050
 * a directory file or an I/O error occurred.
1051
 */
1052
int8_t SdBaseFile::readDir(dir_t* dir, char* longFilename) {
1053
  int16_t n;
1054
  // if not a directory file or miss-positioned return an error
1055
  if (!isDir() || (0x1F & curPosition_)) return -1;
1056
 
1057
  // If we have a longFilename buffer, mark it as invalid.
1058
  // If a long filename is found it will be filled automatically.
1059
  if (longFilename) longFilename[0] = '\0';
1060
 
1061
  while (1) {
1062
 
1063
    n = read(dir, sizeof(dir_t));
1064
    if (n != sizeof(dir_t)) return n ? -1 : 0;
1065
 
1066
    // last entry if DIR_NAME_FREE
1067
    if (dir->name[0] == DIR_NAME_FREE) return 0;
1068
 
1069
    // skip deleted entry and entry for .  and ..
1070
    if (dir->name[0] == DIR_NAME_DELETED || dir->name[0] == '.') {
1071
      if (longFilename) longFilename[0] = '\0';     // Invalidate erased file long name, if any
1072
      continue;
1073
    }
1074
 
1075
    // Fill the long filename if we have a long filename entry.
1076
    // Long filename entries are stored before the short filename.
1077
    if (longFilename && DIR_IS_LONG_NAME(dir)) {
1078
      vfat_t* VFAT = (vfat_t*)dir;
1079
      // Sanity-check the VFAT entry. The first cluster is always set to zero. And the sequence number should be higher than 0
1080
      if (VFAT->firstClusterLow == 0) {
1081
        const uint8_t seq = VFAT->sequenceNumber & 0x1F;
1082
        if (WITHIN(seq, 1, MAX_VFAT_ENTRIES)) {
1083
          // TODO: Store the filename checksum to verify if a long-filename-unaware system modified the file table.
1084
          n = (seq - 1) * (FILENAME_LENGTH);
1085
          for (uint8_t i = 0; i < FILENAME_LENGTH; i++)
1086
            longFilename[n + i] = (i < 5) ? VFAT->name1[i] : (i < 11) ? VFAT->name2[i - 5] : VFAT->name3[i - 11];
1087
          // If this VFAT entry is the last one, add a NUL terminator at the end of the string
1088
          if (VFAT->sequenceNumber & 0x40) longFilename[n + FILENAME_LENGTH] = '\0';
1089
        }
1090
      }
1091
    }
1092
    // Return if normal file or subdirectory
1093
    if (DIR_IS_FILE_OR_SUBDIR(dir)) return n;
1094
  }
1095
}
1096
 
1097
 
1098
// Read next directory entry into the cache
1099
// Assumes file is correctly positioned
1100
dir_t* SdBaseFile::readDirCache() {
1101
  uint8_t i;
1102
  // error if not directory
1103
  if (!isDir()) return 0;
1104
 
1105
  // index of entry in cache
1106
  i = (curPosition_ >> 5) & 0xF;
1107
 
1108
  // use read to locate and cache block
1109
  if (read() < 0) return 0;
1110
 
1111
  // advance to next entry
1112
  curPosition_ += 31;
1113
 
1114
  // return pointer to entry
1115
  return vol_->cache()->dir + i;
1116
}
1117
 
1118
/**
1119
 * Remove a file.
1120
 *
1121
 * The directory entry and all data for the file are deleted.
1122
 *
1123
 * \note This function should not be used to delete the 8.3 version of a
1124
 * file that has a long name. For example if a file has the long name
1125
 * "New Text Document.txt" you should not delete the 8.3 name "NEWTEX~1.TXT".
1126
 *
1127
 * \return true for success, false for failure.
1128
 * Reasons for failure include the file read-only, is a directory,
1129
 * or an I/O error occurred.
1130
 */
1131
bool SdBaseFile::remove() {
1132
  dir_t* d;
1133
  // free any clusters - will fail if read-only or directory
1134
  if (!truncate(0)) return false;
1135
 
1136
  // cache directory entry
1137
  d = cacheDirEntry(SdVolume::CACHE_FOR_WRITE);
1138
  if (!d) return false;
1139
 
1140
  // mark entry deleted
1141
  d->name[0] = DIR_NAME_DELETED;
1142
 
1143
  // set this file closed
1144
  type_ = FAT_FILE_TYPE_CLOSED;
1145
 
1146
  // write entry to SD
1147
  return vol_->cacheFlush();
1148
  return true;
1149
}
1150
 
1151
/**
1152
 * Remove a file.
1153
 *
1154
 * The directory entry and all data for the file are deleted.
1155
 *
1156
 * \param[in] dirFile The directory that contains the file.
1157
 * \param[in] path Path for the file to be removed.
1158
 *
1159
 * \note This function should not be used to delete the 8.3 version of a
1160
 * file that has a long name. For example if a file has the long name
1161
 * "New Text Document.txt" you should not delete the 8.3 name "NEWTEX~1.TXT".
1162
 *
1163
 * \return true for success, false for failure.
1164
 * Reasons for failure include the file is a directory, is read only,
1165
 * \a dirFile is not a directory, \a path is not found
1166
 * or an I/O error occurred.
1167
 */
1168
bool SdBaseFile::remove(SdBaseFile* dirFile, const char* path) {
1169
  SdBaseFile file;
1170
  return file.open(dirFile, path, O_WRITE) ? file.remove() : false;
1171
}
1172
 
1173
/**
1174
 * Rename a file or subdirectory.
1175
 *
1176
 * \param[in] dirFile Directory for the new path.
1177
 * \param[in] newPath New path name for the file/directory.
1178
 *
1179
 * \return true for success, false for failure.
1180
 * Reasons for failure include \a dirFile is not open or is not a directory
1181
 * file, newPath is invalid or already exists, or an I/O error occurs.
1182
 */
1183
bool SdBaseFile::rename(SdBaseFile* dirFile, const char* newPath) {
1184
  dir_t entry;
1185
  uint32_t dirCluster = 0;
1186
  SdBaseFile file;
1187
  dir_t* d;
1188
 
1189
  // must be an open file or subdirectory
1190
  if (!(isFile() || isSubDir())) return false;
1191
 
1192
  // can't move file
1193
  if (vol_ != dirFile->vol_) return false;
1194
 
1195
  // sync() and cache directory entry
1196
  sync();
1197
  d = cacheDirEntry(SdVolume::CACHE_FOR_WRITE);
1198
  if (!d) return false;
1199
 
1200
  // save directory entry
1201
  memcpy(&entry, d, sizeof(entry));
1202
 
1203
  // mark entry deleted
1204
  d->name[0] = DIR_NAME_DELETED;
1205
 
1206
  // make directory entry for new path
1207
  if (isFile()) {
1208
    if (!file.open(dirFile, newPath, O_CREAT | O_EXCL | O_WRITE)) {
1209
      goto restore;
1210
    }
1211
  }
1212
  else {
1213
    // don't create missing path prefix components
1214
    if (!file.mkdir(dirFile, newPath, false)) {
1215
      goto restore;
1216
    }
1217
    // save cluster containing new dot dot
1218
    dirCluster = file.firstCluster_;
1219
  }
1220
  // change to new directory entry
1221
  dirBlock_ = file.dirBlock_;
1222
  dirIndex_ = file.dirIndex_;
1223
 
1224
  // mark closed to avoid possible destructor close call
1225
  file.type_ = FAT_FILE_TYPE_CLOSED;
1226
 
1227
  // cache new directory entry
1228
  d = cacheDirEntry(SdVolume::CACHE_FOR_WRITE);
1229
  if (!d) return false;
1230
 
1231
  // copy all but name field to new directory entry
1232
  memcpy(&d->attributes, &entry.attributes, sizeof(entry) - sizeof(d->name));
1233
 
1234
  // update dot dot if directory
1235
  if (dirCluster) {
1236
    // get new dot dot
1237
    uint32_t block = vol_->clusterStartBlock(dirCluster);
1238
    if (!vol_->cacheRawBlock(block, SdVolume::CACHE_FOR_READ)) return false;
1239
    memcpy(&entry, &vol_->cache()->dir[1], sizeof(entry));
1240
 
1241
    // free unused cluster
1242
    if (!vol_->freeChain(dirCluster)) return false;
1243
 
1244
    // store new dot dot
1245
    block = vol_->clusterStartBlock(firstCluster_);
1246
    if (!vol_->cacheRawBlock(block, SdVolume::CACHE_FOR_WRITE)) return false;
1247
    memcpy(&vol_->cache()->dir[1], &entry, sizeof(entry));
1248
  }
1249
  return vol_->cacheFlush();
1250
 
1251
restore:
1252
  if ((d = cacheDirEntry(SdVolume::CACHE_FOR_WRITE))) {
1253
    // restore entry
1254
    d->name[0] = entry.name[0];
1255
    vol_->cacheFlush();
1256
  }
1257
  return false;
1258
}
1259
 
1260
/**
1261
 * Remove a directory file.
1262
 *
1263
 * The directory file will be removed only if it is empty and is not the
1264
 * root directory.  rmdir() follows DOS and Windows and ignores the
1265
 * read-only attribute for the directory.
1266
 *
1267
 * \note This function should not be used to delete the 8.3 version of a
1268
 * directory that has a long name. For example if a directory has the
1269
 * long name "New folder" you should not delete the 8.3 name "NEWFOL~1".
1270
 *
1271
 * \return true for success, false for failure.
1272
 * Reasons for failure include the file is not a directory, is the root
1273
 * directory, is not empty, or an I/O error occurred.
1274
 */
1275
bool SdBaseFile::rmdir() {
1276
  // must be open subdirectory
1277
  if (!isSubDir()) return false;
1278
 
1279
  rewind();
1280
 
1281
  // make sure directory is empty
1282
  while (curPosition_ < fileSize_) {
1283
    dir_t* p = readDirCache();
1284
    if (!p) return false;
1285
    // done if past last used entry
1286
    if (p->name[0] == DIR_NAME_FREE) break;
1287
    // skip empty slot, '.' or '..'
1288
    if (p->name[0] == DIR_NAME_DELETED || p->name[0] == '.') continue;
1289
    // error not empty
1290
    if (DIR_IS_FILE_OR_SUBDIR(p)) return false;
1291
  }
1292
  // convert empty directory to normal file for remove
1293
  type_ = FAT_FILE_TYPE_NORMAL;
1294
  flags_ |= O_WRITE;
1295
  return remove();
1296
}
1297
 
1298
/**
1299
 * Recursively delete a directory and all contained files.
1300
 *
1301
 * This is like the Unix/Linux 'rm -rf *' if called with the root directory
1302
 * hence the name.
1303
 *
1304
 * Warning - This will remove all contents of the directory including
1305
 * subdirectories.  The directory will then be removed if it is not root.
1306
 * The read-only attribute for files will be ignored.
1307
 *
1308
 * \note This function should not be used to delete the 8.3 version of
1309
 * a directory that has a long name.  See remove() and rmdir().
1310
 *
1311
 * \return true for success, false for failure.
1312
 */
1313
bool SdBaseFile::rmRfStar() {
1314
  uint32_t index;
1315
  SdBaseFile f;
1316
  rewind();
1317
  while (curPosition_ < fileSize_) {
1318
    // remember position
1319
    index = curPosition_ / 32;
1320
 
1321
    dir_t* p = readDirCache();
1322
    if (!p) return false;
1323
 
1324
    // done if past last entry
1325
    if (p->name[0] == DIR_NAME_FREE) break;
1326
 
1327
    // skip empty slot or '.' or '..'
1328
    if (p->name[0] == DIR_NAME_DELETED || p->name[0] == '.') continue;
1329
 
1330
    // skip if part of long file name or volume label in root
1331
    if (!DIR_IS_FILE_OR_SUBDIR(p)) continue;
1332
 
1333
    if (!f.open(this, index, O_READ)) return false;
1334
    if (f.isSubDir()) {
1335
      // recursively delete
1336
      if (!f.rmRfStar()) return false;
1337
    }
1338
    else {
1339
      // ignore read-only
1340
      f.flags_ |= O_WRITE;
1341
      if (!f.remove()) return false;
1342
    }
1343
    // position to next entry if required
1344
    if (curPosition_ != (32 * (index + 1))) {
1345
      if (!seekSet(32 * (index + 1))) return false;
1346
    }
1347
  }
1348
  // don't try to delete root
1349
  if (!isRoot()) {
1350
    if (!rmdir()) return false;
1351
  }
1352
  return true;
1353
}
1354
 
1355
/**
1356
 * Create a file object and open it in the current working directory.
1357
 *
1358
 * \param[in] path A path with a valid 8.3 DOS name for a file to be opened.
1359
 *
1360
 * \param[in] oflag Values for \a oflag are constructed by a bitwise-inclusive
1361
 * OR of open flags. see SdBaseFile::open(SdBaseFile*, const char*, uint8_t).
1362
 */
1363
SdBaseFile::SdBaseFile(const char* path, uint8_t oflag) {
1364
  type_ = FAT_FILE_TYPE_CLOSED;
1365
  writeError = false;
1366
  open(path, oflag);
1367
}
1368
 
1369
/**
1370
 * Sets a file's position.
1371
 *
1372
 * \param[in] pos The new position in bytes from the beginning of the file.
1373
 *
1374
 * \return true for success, false for failure.
1375
 */
1376
bool SdBaseFile::seekSet(const uint32_t pos) {
1377
  uint32_t nCur, nNew;
1378
  // error if file not open or seek past end of file
1379
  if (!isOpen() || pos > fileSize_) return false;
1380
 
1381
  if (type_ == FAT_FILE_TYPE_ROOT_FIXED) {
1382
    curPosition_ = pos;
1383
    return true;
1384
  }
1385
  if (pos == 0) {
1386
    curCluster_ = curPosition_ = 0;   // set position to start of file
1387
    return true;
1388
  }
1389
 
1390
  // calculate cluster index for cur and new position
1391
  nCur = (curPosition_ - 1) >> (vol_->clusterSizeShift_ + 9);
1392
  nNew = (pos - 1) >> (vol_->clusterSizeShift_ + 9);
1393
 
1394
  if (nNew < nCur || curPosition_ == 0)
1395
    curCluster_ = firstCluster_;      // must follow chain from first cluster
1396
  else
1397
    nNew -= nCur;                     // advance from curPosition
1398
 
1399
  while (nNew--)
1400
    if (!vol_->fatGet(curCluster_, &curCluster_)) return false;
1401
 
1402
  curPosition_ = pos;
1403
  return true;
1404
}
1405
 
1406
void SdBaseFile::setpos(filepos_t* pos) {
1407
  curPosition_ = pos->position;
1408
  curCluster_ = pos->cluster;
1409
}
1410
 
1411
/**
1412
 * The sync() call causes all modified data and directory fields
1413
 * to be written to the storage device.
1414
 *
1415
 * \return true for success, false for failure.
1416
 * Reasons for failure include a call to sync() before a file has been
1417
 * opened or an I/O error.
1418
 */
1419
bool SdBaseFile::sync() {
1420
  // only allow open files and directories
1421
  if (!isOpen()) goto FAIL;
1422
 
1423
  if (flags_ & F_FILE_DIR_DIRTY) {
1424
    dir_t* d = cacheDirEntry(SdVolume::CACHE_FOR_WRITE);
1425
    // check for deleted by another open file object
1426
    if (!d || d->name[0] == DIR_NAME_DELETED) goto FAIL;
1427
 
1428
    // do not set filesize for dir files
1429
    if (!isDir()) d->fileSize = fileSize_;
1430
 
1431
    // update first cluster fields
1432
    d->firstClusterLow = firstCluster_ & 0xFFFF;
1433
    d->firstClusterHigh = firstCluster_ >> 16;
1434
 
1435
    // set modify time if user supplied a callback date/time function
1436
    if (dateTime_) {
1437
      dateTime_(&d->lastWriteDate, &d->lastWriteTime);
1438
      d->lastAccessDate = d->lastWriteDate;
1439
    }
1440
    // clear directory dirty
1441
    flags_ &= ~F_FILE_DIR_DIRTY;
1442
  }
1443
  return vol_->cacheFlush();
1444
 
1445
  FAIL:
1446
  writeError = true;
1447
  return false;
1448
}
1449
 
1450
/**
1451
 * Copy a file's timestamps
1452
 *
1453
 * \param[in] file File to copy timestamps from.
1454
 *
1455
 * \note
1456
 * Modify and access timestamps may be overwritten if a date time callback
1457
 * function has been set by dateTimeCallback().
1458
 *
1459
 * \return true for success, false for failure.
1460
 */
1461
bool SdBaseFile::timestamp(SdBaseFile* file) {
1462
  dir_t* d;
1463
  dir_t dir;
1464
 
1465
  // get timestamps
1466
  if (!file->dirEntry(&dir)) return false;
1467
 
1468
  // update directory fields
1469
  if (!sync()) return false;
1470
 
1471
  d = cacheDirEntry(SdVolume::CACHE_FOR_WRITE);
1472
  if (!d) return false;
1473
 
1474
  // copy timestamps
1475
  d->lastAccessDate = dir.lastAccessDate;
1476
  d->creationDate = dir.creationDate;
1477
  d->creationTime = dir.creationTime;
1478
  d->creationTimeTenths = dir.creationTimeTenths;
1479
  d->lastWriteDate = dir.lastWriteDate;
1480
  d->lastWriteTime = dir.lastWriteTime;
1481
 
1482
  // write back entry
1483
  return vol_->cacheFlush();
1484
}
1485
 
1486
/**
1487
 * Set a file's timestamps in its directory entry.
1488
 *
1489
 * \param[in] flags Values for \a flags are constructed by a bitwise-inclusive
1490
 * OR of flags from the following list
1491
 *
1492
 * T_ACCESS - Set the file's last access date.
1493
 *
1494
 * T_CREATE - Set the file's creation date and time.
1495
 *
1496
 * T_WRITE - Set the file's last write/modification date and time.
1497
 *
1498
 * \param[in] year Valid range 1980 - 2107 inclusive.
1499
 *
1500
 * \param[in] month Valid range 1 - 12 inclusive.
1501
 *
1502
 * \param[in] day Valid range 1 - 31 inclusive.
1503
 *
1504
 * \param[in] hour Valid range 0 - 23 inclusive.
1505
 *
1506
 * \param[in] minute Valid range 0 - 59 inclusive.
1507
 *
1508
 * \param[in] second Valid range 0 - 59 inclusive
1509
 *
1510
 * \note It is possible to set an invalid date since there is no check for
1511
 * the number of days in a month.
1512
 *
1513
 * \note
1514
 * Modify and access timestamps may be overwritten if a date time callback
1515
 * function has been set by dateTimeCallback().
1516
 *
1517
 * \return true for success, false for failure.
1518
 */
1519
bool SdBaseFile::timestamp(uint8_t flags, uint16_t year, uint8_t month,
1520
                           uint8_t day, uint8_t hour, uint8_t minute, uint8_t second) {
1521
  uint16_t dirDate, dirTime;
1522
  dir_t* d;
1523
 
1524
  if (!isOpen()
1525
      || year < 1980
1526
      || year > 2107
1527
      || month < 1
1528
      || month > 12
1529
      || day < 1
1530
      || day > 31
1531
      || hour > 23
1532
      || minute > 59
1533
      || second > 59) {
1534
    return false;
1535
  }
1536
  // update directory entry
1537
  if (!sync()) return false;
1538
 
1539
  d = cacheDirEntry(SdVolume::CACHE_FOR_WRITE);
1540
  if (!d) return false;
1541
 
1542
  dirDate = FAT_DATE(year, month, day);
1543
  dirTime = FAT_TIME(hour, minute, second);
1544
  if (flags & T_ACCESS) {
1545
    d->lastAccessDate = dirDate;
1546
  }
1547
  if (flags & T_CREATE) {
1548
    d->creationDate = dirDate;
1549
    d->creationTime = dirTime;
1550
    // seems to be units of 1/100 second not 1/10 as Microsoft states
1551
    d->creationTimeTenths = second & 1 ? 100 : 0;
1552
  }
1553
  if (flags & T_WRITE) {
1554
    d->lastWriteDate = dirDate;
1555
    d->lastWriteTime = dirTime;
1556
  }
1557
  return vol_->cacheFlush();
1558
}
1559
 
1560
/**
1561
 * Truncate a file to a specified length.  The current file position
1562
 * will be maintained if it is less than or equal to \a length otherwise
1563
 * it will be set to end of file.
1564
 *
1565
 * \param[in] length The desired length for the file.
1566
 *
1567
 * \return true for success, false for failure.
1568
 * Reasons for failure include file is read only, file is a directory,
1569
 * \a length is greater than the current file size or an I/O error occurs.
1570
 */
1571
bool SdBaseFile::truncate(uint32_t length) {
1572
  uint32_t newPos;
1573
  // error if not a normal file or read-only
1574
  if (!isFile() || !(flags_ & O_WRITE)) return false;
1575
 
1576
  // error if length is greater than current size
1577
  if (length > fileSize_) return false;
1578
 
1579
  // fileSize and length are zero - nothing to do
1580
  if (fileSize_ == 0) return true;
1581
 
1582
  // remember position for seek after truncation
1583
  newPos = curPosition_ > length ? length : curPosition_;
1584
 
1585
  // position to last cluster in truncated file
1586
  if (!seekSet(length)) return false;
1587
 
1588
  if (length == 0) {
1589
    // free all clusters
1590
    if (!vol_->freeChain(firstCluster_)) return false;
1591
    firstCluster_ = 0;
1592
  }
1593
  else {
1594
    uint32_t toFree;
1595
    if (!vol_->fatGet(curCluster_, &toFree)) return false;
1596
 
1597
    if (!vol_->isEOC(toFree)) {
1598
      // free extra clusters
1599
      if (!vol_->freeChain(toFree)) return false;
1600
 
1601
      // current cluster is end of chain
1602
      if (!vol_->fatPutEOC(curCluster_)) return false;
1603
    }
1604
  }
1605
  fileSize_ = length;
1606
 
1607
  // need to update directory entry
1608
  flags_ |= F_FILE_DIR_DIRTY;
1609
 
1610
  if (!sync()) return false;
1611
 
1612
  // set file to correct position
1613
  return seekSet(newPos);
1614
}
1615
 
1616
/**
1617
 * Write data to an open file.
1618
 *
1619
 * \note Data is moved to the cache but may not be written to the
1620
 * storage device until sync() is called.
1621
 *
1622
 * \param[in] buf Pointer to the location of the data to be written.
1623
 *
1624
 * \param[in] nbyte Number of bytes to write.
1625
 *
1626
 * \return For success write() returns the number of bytes written, always
1627
 * \a nbyte.  If an error occurs, write() returns -1.  Possible errors
1628
 * include write() is called before a file has been opened, write is called
1629
 * for a read-only file, device is full, a corrupt file system or an I/O error.
1630
 *
1631
 */
1632
int16_t SdBaseFile::write(const void* buf, uint16_t nbyte) {
1633
  // convert void* to uint8_t*  -  must be before goto statements
1634
  const uint8_t* src = reinterpret_cast<const uint8_t*>(buf);
1635
 
1636
  // number of bytes left to write  -  must be before goto statements
1637
  uint16_t nToWrite = nbyte;
1638
 
1639
  // error if not a normal file or is read-only
1640
  if (!isFile() || !(flags_ & O_WRITE)) goto FAIL;
1641
 
1642
  // seek to end of file if append flag
1643
  if ((flags_ & O_APPEND) && curPosition_ != fileSize_) {
1644
    if (!seekEnd()) goto FAIL;
1645
  }
1646
 
1647
  while (nToWrite > 0) {
1648
    uint8_t blockOfCluster = vol_->blockOfCluster(curPosition_);
1649
    uint16_t blockOffset = curPosition_ & 0x1FF;
1650
    if (blockOfCluster == 0 && blockOffset == 0) {
1651
      // start of new cluster
1652
      if (curCluster_ == 0) {
1653
        if (firstCluster_ == 0) {
1654
          // allocate first cluster of file
1655
          if (!addCluster()) goto FAIL;
1656
        }
1657
        else {
1658
          curCluster_ = firstCluster_;
1659
        }
1660
      }
1661
      else {
1662
        uint32_t next;
1663
        if (!vol_->fatGet(curCluster_, &next)) goto FAIL;
1664
        if (vol_->isEOC(next)) {
1665
          // add cluster if at end of chain
1666
          if (!addCluster()) goto FAIL;
1667
        }
1668
        else {
1669
          curCluster_ = next;
1670
        }
1671
      }
1672
    }
1673
    // max space in block
1674
    uint16_t n = 512 - blockOffset;
1675
 
1676
    // lesser of space and amount to write
1677
    NOMORE(n, nToWrite);
1678
 
1679
    // block for data write
1680
    uint32_t block = vol_->clusterStartBlock(curCluster_) + blockOfCluster;
1681
    if (n == 512) {
1682
      // full block - don't need to use cache
1683
      if (vol_->cacheBlockNumber() == block) {
1684
        // invalidate cache if block is in cache
1685
        vol_->cacheSetBlockNumber(0xFFFFFFFF, false);
1686
      }
1687
      if (!vol_->writeBlock(block, src)) goto FAIL;
1688
    }
1689
    else {
1690
      if (blockOffset == 0 && curPosition_ >= fileSize_) {
1691
        // start of new block don't need to read into cache
1692
        if (!vol_->cacheFlush()) goto FAIL;
1693
        // set cache dirty and SD address of block
1694
        vol_->cacheSetBlockNumber(block, true);
1695
      }
1696
      else {
1697
        // rewrite part of block
1698
        if (!vol_->cacheRawBlock(block, SdVolume::CACHE_FOR_WRITE)) goto FAIL;
1699
      }
1700
      uint8_t* dst = vol_->cache()->data + blockOffset;
1701
      memcpy(dst, src, n);
1702
    }
1703
    curPosition_ += n;
1704
    src += n;
1705
    nToWrite -= n;
1706
  }
1707
  if (curPosition_ > fileSize_) {
1708
    // update fileSize and insure sync will update dir entry
1709
    fileSize_ = curPosition_;
1710
    flags_ |= F_FILE_DIR_DIRTY;
1711
  }
1712
  else if (dateTime_ && nbyte) {
1713
    // insure sync will update modified date and time
1714
    flags_ |= F_FILE_DIR_DIRTY;
1715
  }
1716
 
1717
  if (flags_ & O_SYNC) {
1718
    if (!sync()) goto FAIL;
1719
  }
1720
  return nbyte;
1721
 
1722
  FAIL:
1723
  // return for write error
1724
  writeError = true;
1725
  return -1;
1726
}
1727
 
1728
#endif // SDSUPPORT