3 exFAT file system implementation library.
5 Copyright (C) 2009, 2010 Andrew Nayenko
7 This program is free software: you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation, either version 3 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program. If not, see <http://www.gnu.org/licenses/>.
26 /* on-disk nodes iterator */
35 struct exfat_node* exfat_get_node(struct exfat_node* node)
37 /* if we switch to multi-threaded mode we will need atomic
38 increment here and atomic decrement in exfat_put_node() */
43 void exfat_put_node(struct exfat* ef, struct exfat_node* node)
45 if (--node->references < 0)
47 char buffer[EXFAT_NAME_MAX + 1];
48 exfat_get_name(node, buffer, EXFAT_NAME_MAX);
49 exfat_bug("reference counter of `%s' is below zero", buffer);
52 if (node->references == 0)
54 if (node->flags & EXFAT_ATTRIB_DIRTY)
55 exfat_flush_node(ef, node);
56 if (node->flags & EXFAT_ATTRIB_UNLINKED)
58 /* free all clusters and node structure itself */
59 exfat_truncate(ef, node, 0);
68 * Cluster + offset from the beginning of the directory to absolute offset.
70 static off_t co2o(struct exfat* ef, cluster_t cluster, off_t offset)
72 return exfat_c2o(ef, cluster) + offset % CLUSTER_SIZE(*ef->sb);
75 static int opendir(struct exfat* ef, const struct exfat_node* dir,
78 if (!(dir->flags & EXFAT_ATTRIB_DIR))
79 exfat_bug("not a directory");
80 it->cluster = dir->start_cluster;
82 it->contiguous = IS_CONTIGUOUS(*dir);
83 it->chunk = malloc(CLUSTER_SIZE(*ef->sb));
84 if (it->chunk == NULL)
86 exfat_error("out of memory");
89 exfat_read_raw(it->chunk, CLUSTER_SIZE(*ef->sb),
90 exfat_c2o(ef, it->cluster), ef->fd);
94 static void closedir(struct iterator* it)
103 static int fetch_next_entry(struct exfat* ef, const struct exfat_node* parent,
106 /* move iterator to the next entry in the directory */
107 it->offset += sizeof(struct exfat_entry);
108 /* fetch the next cluster if needed */
109 if ((it->offset & (CLUSTER_SIZE(*ef->sb) - 1)) == 0)
111 it->cluster = exfat_next_cluster(ef, parent, it->cluster);
112 if (CLUSTER_INVALID(it->cluster))
114 exfat_error("invalid cluster while reading directory");
117 exfat_read_raw(it->chunk, CLUSTER_SIZE(*ef->sb),
118 exfat_c2o(ef, it->cluster), ef->fd);
123 static struct exfat_node* allocate_node(void)
125 struct exfat_node* node = malloc(sizeof(struct exfat_node));
128 exfat_error("failed to allocate node");
131 memset(node, 0, sizeof(struct exfat_node));
135 static void init_node_meta1(struct exfat_node* node,
136 const struct exfat_entry_meta1* meta1)
138 node->flags = le16_to_cpu(meta1->attrib);
139 node->mtime = exfat_exfat2unix(meta1->mdate, meta1->mtime);
140 node->atime = exfat_exfat2unix(meta1->adate, meta1->atime);
143 static void init_node_meta2(struct exfat_node* node,
144 const struct exfat_entry_meta2* meta2)
146 node->size = le64_to_cpu(meta2->size);
147 node->start_cluster = le32_to_cpu(meta2->start_cluster);
148 node->fptr_cluster = node->start_cluster;
149 if (meta2->flag == EXFAT_FLAG_CONTIGUOUS)
150 node->flags |= EXFAT_ATTRIB_CONTIGUOUS;
154 * Reads one entry in directory at position pointed by iterator and fills
157 static int readdir(struct exfat* ef, const struct exfat_node* parent,
158 struct exfat_node** node, struct iterator* it)
160 const struct exfat_entry* entry;
161 const struct exfat_entry_meta1* meta1;
162 const struct exfat_entry_meta2* meta2;
163 const struct exfat_entry_name* file_name;
164 const struct exfat_entry_upcase* upcase;
165 const struct exfat_entry_bitmap* bitmap;
166 const struct exfat_entry_label* label;
167 uint8_t continuations = 0;
168 le16_t* namep = NULL;
169 uint16_t reference_checksum = 0;
170 uint16_t actual_checksum = 0;
176 /* every directory (even empty one) occupies at least one cluster and
177 must contain EOD entry */
178 entry = (const struct exfat_entry*)
179 (it->chunk + it->offset % CLUSTER_SIZE(*ef->sb));
183 case EXFAT_ENTRY_EOD:
184 if (continuations != 0)
186 exfat_error("expected %hhu continuations before EOD",
190 return -ENOENT; /* that's OK, means end of directory */
192 case EXFAT_ENTRY_FILE:
193 if (continuations != 0)
195 exfat_error("expected %hhu continuations before new entry",
199 meta1 = (const struct exfat_entry_meta1*) entry;
200 continuations = meta1->continuations;
201 /* each file entry must have at least 2 continuations:
203 if (continuations < 2)
205 exfat_error("too few continuations (%hhu)", continuations);
208 reference_checksum = le16_to_cpu(meta1->checksum);
209 actual_checksum = exfat_start_checksum(meta1);
210 *node = allocate_node();
213 /* new node has zero reference counter */
214 (*node)->entry_cluster = it->cluster;
215 (*node)->entry_offset = it->offset;
216 init_node_meta1(*node, meta1);
217 namep = (*node)->name;
220 case EXFAT_ENTRY_FILE_INFO:
221 if (continuations < 2)
223 exfat_error("unexpected continuation (%hhu)",
227 meta2 = (const struct exfat_entry_meta2*) entry;
228 init_node_meta2(*node, meta2);
229 actual_checksum = exfat_add_checksum(entry, actual_checksum);
230 /* There are two fields that contain file size. Maybe they plan
231 to add compression support in the future and one of those
232 fields is visible (uncompressed) size and the other is real
233 (compressed) size. Anyway, currently it looks like exFAT does
234 not support compression and both fields must be equal. */
235 if (le64_to_cpu(meta2->real_size) != (*node)->size)
237 exfat_error("real size does not equal to size "
238 "(%"PRIu64" != %"PRIu64")",
239 le64_to_cpu(meta2->real_size), (*node)->size);
242 /* directories must be aligned on at cluster boundary */
243 if (((*node)->flags & EXFAT_ATTRIB_DIR) &&
244 (*node)->size % CLUSTER_SIZE(*ef->sb) != 0)
246 char buffer[EXFAT_NAME_MAX + 1];
248 exfat_get_name(*node, buffer, EXFAT_NAME_MAX);
249 exfat_error("directory `%s' has invalid size %"PRIu64" bytes",
250 buffer, (*node)->size);
256 case EXFAT_ENTRY_FILE_NAME:
257 if (continuations == 0)
259 exfat_error("unexpected continuation");
262 file_name = (const struct exfat_entry_name*) entry;
263 actual_checksum = exfat_add_checksum(entry, actual_checksum);
265 memcpy(namep, file_name->name, EXFAT_ENAME_MAX * sizeof(le16_t));
266 namep += EXFAT_ENAME_MAX;
267 if (--continuations == 0)
269 if (actual_checksum != reference_checksum)
271 exfat_error("invalid checksum (0x%hx != 0x%hx)",
272 actual_checksum, reference_checksum);
275 if (fetch_next_entry(ef, parent, it) != 0)
277 return 0; /* entry completed */
281 case EXFAT_ENTRY_UPCASE:
282 if (ef->upcase != NULL)
284 upcase = (const struct exfat_entry_upcase*) entry;
285 if (CLUSTER_INVALID(le32_to_cpu(upcase->start_cluster)))
287 exfat_error("invalid cluster in upcase table");
290 if (le64_to_cpu(upcase->size) == 0 ||
291 le64_to_cpu(upcase->size) > 0xffff * sizeof(uint16_t) ||
292 le64_to_cpu(upcase->size) % sizeof(uint16_t) != 0)
294 exfat_error("bad upcase table size (%"PRIu64" bytes)",
295 le64_to_cpu(upcase->size));
298 ef->upcase = malloc(le64_to_cpu(upcase->size));
299 if (ef->upcase == NULL)
301 exfat_error("failed to allocate upcase table (%"PRIu64" bytes)",
302 le64_to_cpu(upcase->size));
305 ef->upcase_chars = le64_to_cpu(upcase->size) / sizeof(le16_t);
307 exfat_read_raw(ef->upcase, le64_to_cpu(upcase->size),
308 exfat_c2o(ef, le32_to_cpu(upcase->start_cluster)), ef->fd);
311 case EXFAT_ENTRY_BITMAP:
312 bitmap = (const struct exfat_entry_bitmap*) entry;
313 if (CLUSTER_INVALID(le32_to_cpu(bitmap->start_cluster)))
315 exfat_error("invalid cluster in clusters bitmap");
318 ef->cmap.size = le32_to_cpu(ef->sb->cluster_count) -
319 EXFAT_FIRST_DATA_CLUSTER;
320 if (le64_to_cpu(bitmap->size) < (ef->cmap.size + 7) / 8)
322 exfat_error("invalid clusters bitmap size: %"PRIu64
323 " (expected at least %u)",
324 le64_to_cpu(bitmap->size), (ef->cmap.size + 7) / 8);
327 ef->cmap.start_cluster = le32_to_cpu(bitmap->start_cluster);
328 /* FIXME bitmap can be rather big, up to 512 MB */
329 ef->cmap.chunk_size = ef->cmap.size;
330 ef->cmap.chunk = malloc(le64_to_cpu(bitmap->size));
331 if (ef->cmap.chunk == NULL)
333 exfat_error("failed to allocate clusters bitmap chunk "
334 "(%"PRIu64" bytes)", le64_to_cpu(bitmap->size));
338 exfat_read_raw(ef->cmap.chunk, le64_to_cpu(bitmap->size),
339 exfat_c2o(ef, ef->cmap.start_cluster), ef->fd);
342 case EXFAT_ENTRY_LABEL:
343 label = (const struct exfat_entry_label*) entry;
344 if (label->length > EXFAT_ENAME_MAX)
346 exfat_error("too long label (%hhu chars)", label->length);
352 if (entry->type & EXFAT_ENTRY_VALID)
354 exfat_error("unknown entry type 0x%hhu", entry->type);
360 if (fetch_next_entry(ef, parent, it) != 0)
363 /* we never reach here */
371 int exfat_cache_directory(struct exfat* ef, struct exfat_node* dir)
375 struct exfat_node* node;
376 struct exfat_node* current = NULL;
378 if (dir->flags & EXFAT_ATTRIB_CACHED)
379 return 0; /* already cached */
381 rc = opendir(ef, dir, &it);
384 while ((rc = readdir(ef, dir, &node, &it)) == 0)
389 current->next = node;
390 node->prev = current;
402 for (current = dir->child; current; current = node)
404 node = current->next;
411 dir->flags |= EXFAT_ATTRIB_CACHED;
415 static void reset_cache(struct exfat* ef, struct exfat_node* node)
417 struct exfat_node* child;
418 struct exfat_node* next;
420 for (child = node->child; child; child = next)
422 reset_cache(ef, child);
426 if (node->references != 0)
428 char buffer[EXFAT_NAME_MAX + 1];
429 exfat_get_name(node, buffer, EXFAT_NAME_MAX);
430 exfat_warn("non-zero reference counter (%d) for `%s'",
431 node->references, buffer);
433 while (node->references--)
434 exfat_put_node(ef, node);
436 node->flags &= ~EXFAT_ATTRIB_CACHED;
439 void exfat_reset_cache(struct exfat* ef)
441 reset_cache(ef, ef->root);
444 void next_entry(struct exfat* ef, const struct exfat_node* parent,
445 cluster_t* cluster, off_t* offset)
447 *offset += sizeof(struct exfat_entry);
448 if (*offset % CLUSTER_SIZE(*ef->sb) == 0)
449 /* next cluster cannot be invalid */
450 *cluster = exfat_next_cluster(ef, parent, *cluster);
453 void exfat_flush_node(struct exfat* ef, struct exfat_node* node)
457 off_t meta1_offset, meta2_offset;
458 struct exfat_entry_meta1 meta1;
459 struct exfat_entry_meta2 meta2;
462 exfat_bug("unable to flush node to read-only FS");
464 if (node->parent == NULL)
465 return; /* do not flush unlinked node */
467 cluster = node->entry_cluster;
468 offset = node->entry_offset;
469 meta1_offset = co2o(ef, cluster, offset);
470 next_entry(ef, node->parent, &cluster, &offset);
471 meta2_offset = co2o(ef, cluster, offset);
473 exfat_read_raw(&meta1, sizeof(meta1), meta1_offset, ef->fd);
474 if (meta1.type != EXFAT_ENTRY_FILE)
475 exfat_bug("invalid type of meta1: 0x%hhx", meta1.type);
476 meta1.attrib = cpu_to_le16(node->flags);
477 exfat_unix2exfat(node->mtime, &meta1.mdate, &meta1.mtime);
478 exfat_unix2exfat(node->atime, &meta1.adate, &meta1.atime);
480 exfat_read_raw(&meta2, sizeof(meta2), meta2_offset, ef->fd);
481 if (meta2.type != EXFAT_ENTRY_FILE_INFO)
482 exfat_bug("invalid type of meta2: 0x%hhx", meta2.type);
483 meta2.size = meta2.real_size = cpu_to_le64(node->size);
484 meta2.start_cluster = cpu_to_le32(node->start_cluster);
485 /* empty files must be marked as fragmented */
486 if (node->size != 0 && IS_CONTIGUOUS(*node))
487 meta2.flag = EXFAT_FLAG_CONTIGUOUS;
489 meta2.flag = EXFAT_FLAG_FRAGMENTED;
490 /* name hash remains unchanged, no need to recalculate it */
492 meta1.checksum = exfat_calc_checksum(&meta1, &meta2, node->name);
494 exfat_write_raw(&meta1, sizeof(meta1), meta1_offset, ef->fd);
495 exfat_write_raw(&meta2, sizeof(meta2), meta2_offset, ef->fd);
497 node->flags &= ~EXFAT_ATTRIB_DIRTY;
500 static void erase_entry(struct exfat* ef, struct exfat_node* node)
502 cluster_t cluster = node->entry_cluster;
503 off_t offset = node->entry_offset;
504 int name_entries = DIV_ROUND_UP(utf16_length(node->name), EXFAT_ENAME_MAX);
507 entry_type = EXFAT_ENTRY_FILE & ~EXFAT_ENTRY_VALID;
508 exfat_write_raw(&entry_type, 1, co2o(ef, cluster, offset), ef->fd);
510 next_entry(ef, node->parent, &cluster, &offset);
511 entry_type = EXFAT_ENTRY_FILE_INFO & ~EXFAT_ENTRY_VALID;
512 exfat_write_raw(&entry_type, 1, co2o(ef, cluster, offset), ef->fd);
514 while (name_entries--)
516 next_entry(ef, node->parent, &cluster, &offset);
517 entry_type = EXFAT_ENTRY_FILE_NAME & ~EXFAT_ENTRY_VALID;
518 exfat_write_raw(&entry_type, 1, co2o(ef, cluster, offset), ef->fd);
522 static void tree_detach(struct exfat_node* node)
525 node->prev->next = node->next;
526 else /* this is the first node in the list */
527 node->parent->child = node->next;
529 node->next->prev = node->prev;
535 static void tree_attach(struct exfat_node* dir, struct exfat_node* node)
540 dir->child->prev = node;
541 node->next = dir->child;
546 static void delete(struct exfat* ef, struct exfat_node* node)
548 erase_entry(ef, node);
549 exfat_update_mtime(node->parent);
551 /* file clusters will be freed when node reference counter becomes 0 */
552 node->flags |= EXFAT_ATTRIB_UNLINKED;
555 int exfat_unlink(struct exfat* ef, struct exfat_node* node)
557 if (node->flags & EXFAT_ATTRIB_DIR)
563 int exfat_rmdir(struct exfat* ef, struct exfat_node* node)
565 if (!(node->flags & EXFAT_ATTRIB_DIR))
567 /* check that directory is empty */
568 exfat_cache_directory(ef, node);
575 static int grow_directory(struct exfat* ef, struct exfat_node* dir,
576 uint64_t asize, uint32_t difference)
578 return exfat_truncate(ef, dir,
579 DIV_ROUND_UP(asize + difference, CLUSTER_SIZE(*ef->sb))
580 * CLUSTER_SIZE(*ef->sb));
583 static int find_slot(struct exfat* ef, struct exfat_node* dir,
584 cluster_t* cluster, off_t* offset, int subentries)
588 const struct exfat_entry* entry;
591 rc = opendir(ef, dir, &it);
598 *cluster = it.cluster;
601 entry = (const struct exfat_entry*)
602 (it.chunk + it.offset % CLUSTER_SIZE(*ef->sb));
603 if (entry->type == EXFAT_ENTRY_EOD)
605 rc = grow_directory(ef, dir,
606 it.offset + sizeof(struct exfat_entry), /* actual size */
607 (subentries - contiguous) * sizeof(struct exfat_entry));
615 if (entry->type & EXFAT_ENTRY_VALID)
619 if (contiguous == subentries)
620 break; /* suitable slot it found */
621 if (fetch_next_entry(ef, dir, &it) != 0)
631 static int write_entry(struct exfat* ef, struct exfat_node* dir,
632 const le16_t* name, cluster_t cluster, off_t offset, uint16_t attrib)
634 struct exfat_node* node;
635 struct exfat_entry_meta1 meta1;
636 struct exfat_entry_meta2 meta2;
637 const size_t name_length = utf16_length(name);
638 const int name_entries = DIV_ROUND_UP(name_length, EXFAT_ENAME_MAX);
641 node = allocate_node();
644 node->entry_cluster = cluster;
645 node->entry_offset = offset;
646 memcpy(node->name, name, name_length * sizeof(le16_t));
648 memset(&meta1, 0, sizeof(meta1));
649 meta1.type = EXFAT_ENTRY_FILE;
650 meta1.continuations = 1 + name_entries;
651 meta1.attrib = cpu_to_le16(attrib);
652 exfat_unix2exfat(time(NULL), &meta1.crdate, &meta1.crtime);
653 meta1.adate = meta1.mdate = meta1.crdate;
654 meta1.atime = meta1.mtime = meta1.crtime;
655 /* crtime_cs and mtime_cs contain addition to the time in centiseconds;
656 just ignore those fields because we operate with 2 sec resolution */
658 memset(&meta2, 0, sizeof(meta2));
659 meta2.type = EXFAT_ENTRY_FILE_INFO;
660 meta2.flag = EXFAT_FLAG_FRAGMENTED;
661 meta2.name_length = name_length;
662 meta2.name_hash = exfat_calc_name_hash(ef, node->name);
663 meta2.start_cluster = cpu_to_le32(EXFAT_CLUSTER_FREE);
665 meta1.checksum = exfat_calc_checksum(&meta1, &meta2, node->name);
667 exfat_write_raw(&meta1, sizeof(meta1), co2o(ef, cluster, offset), ef->fd);
668 next_entry(ef, dir, &cluster, &offset);
669 exfat_write_raw(&meta2, sizeof(meta2), co2o(ef, cluster, offset), ef->fd);
670 for (i = 0; i < name_entries; i++)
672 struct exfat_entry_name name_entry = {EXFAT_ENTRY_FILE_NAME, 0};
673 memcpy(name_entry.name, node->name + i * EXFAT_ENAME_MAX,
674 EXFAT_ENAME_MAX * sizeof(le16_t));
675 next_entry(ef, dir, &cluster, &offset);
676 exfat_write_raw(&name_entry, sizeof(name_entry),
677 co2o(ef, cluster, offset), ef->fd);
680 init_node_meta1(node, &meta1);
681 init_node_meta2(node, &meta2);
683 tree_attach(dir, node);
684 exfat_update_mtime(dir);
688 static int create(struct exfat* ef, const char* path, uint16_t attrib)
690 struct exfat_node* dir;
691 struct exfat_node* existing;
692 cluster_t cluster = EXFAT_CLUSTER_BAD;
694 le16_t name[EXFAT_NAME_MAX + 1];
697 rc = exfat_split(ef, &dir, &existing, name, path);
700 if (existing != NULL)
702 exfat_put_node(ef, existing);
703 exfat_put_node(ef, dir);
707 rc = find_slot(ef, dir, &cluster, &offset,
708 2 + DIV_ROUND_UP(utf16_length(name), EXFAT_ENAME_MAX));
711 exfat_put_node(ef, dir);
714 rc = write_entry(ef, dir, name, cluster, offset, attrib);
715 exfat_put_node(ef, dir);
719 int exfat_mknod(struct exfat* ef, const char* path)
721 return create(ef, path, EXFAT_ATTRIB_ARCH);
724 int exfat_mkdir(struct exfat* ef, const char* path)
727 struct exfat_node* node;
729 rc = create(ef, path, EXFAT_ATTRIB_ARCH | EXFAT_ATTRIB_DIR);
732 rc = exfat_lookup(ef, &node, path);
735 /* directories always have at least one cluster */
736 rc = exfat_truncate(ef, node, CLUSTER_SIZE(*ef->sb));
740 exfat_put_node(ef, node);
743 exfat_put_node(ef, node);
747 static void rename_entry(struct exfat* ef, struct exfat_node* dir,
748 struct exfat_node* node, const le16_t* name, cluster_t new_cluster,
751 struct exfat_entry_meta1 meta1;
752 struct exfat_entry_meta2 meta2;
753 cluster_t old_cluster = node->entry_cluster;
754 off_t old_offset = node->entry_offset;
755 const size_t name_length = utf16_length(name);
756 const int name_entries = DIV_ROUND_UP(name_length, EXFAT_ENAME_MAX);
759 exfat_read_raw(&meta1, sizeof(meta1), co2o(ef, old_cluster, old_offset),
761 next_entry(ef, node->parent, &old_cluster, &old_offset);
762 exfat_read_raw(&meta2, sizeof(meta2), co2o(ef, old_cluster, old_offset),
764 meta1.continuations = 1 + name_entries;
765 meta2.name_hash = exfat_calc_name_hash(ef, name);
766 meta2.name_length = name_length;
767 meta1.checksum = exfat_calc_checksum(&meta1, &meta2, name);
769 erase_entry(ef, node);
771 node->entry_cluster = new_cluster;
772 node->entry_offset = new_offset;
774 exfat_write_raw(&meta1, sizeof(meta1), co2o(ef, new_cluster, new_offset),
776 next_entry(ef, dir, &new_cluster, &new_offset);
777 exfat_write_raw(&meta2, sizeof(meta2), co2o(ef, new_cluster, new_offset),
780 for (i = 0; i < name_entries; i++)
782 struct exfat_entry_name name_entry = {EXFAT_ENTRY_FILE_NAME, 0};
783 memcpy(name_entry.name, name + i * EXFAT_ENAME_MAX,
784 EXFAT_ENAME_MAX * sizeof(le16_t));
785 next_entry(ef, dir, &new_cluster, &new_offset);
786 exfat_write_raw(&name_entry, sizeof(name_entry),
787 co2o(ef, new_cluster, new_offset), ef->fd);
790 memcpy(node->name, name, (EXFAT_NAME_MAX + 1) * sizeof(le16_t));
792 tree_attach(dir, node);
795 int exfat_rename(struct exfat* ef, const char* old_path, const char* new_path)
797 struct exfat_node* node;
798 struct exfat_node* existing;
799 struct exfat_node* dir;
800 cluster_t cluster = EXFAT_CLUSTER_BAD;
802 le16_t name[EXFAT_NAME_MAX + 1];
805 rc = exfat_lookup(ef, &node, old_path);
809 rc = exfat_split(ef, &dir, &existing, name, new_path);
812 exfat_put_node(ef, node);
815 if (existing != NULL)
817 if (existing->flags & EXFAT_ATTRIB_DIR)
819 if (node->flags & EXFAT_ATTRIB_DIR)
820 rc = exfat_rmdir(ef, existing);
826 if (!(node->flags & EXFAT_ATTRIB_DIR))
827 rc = exfat_unlink(ef, existing);
831 exfat_put_node(ef, existing);
834 exfat_put_node(ef, dir);
835 exfat_put_node(ef, node);
840 rc = find_slot(ef, dir, &cluster, &offset,
841 2 + DIV_ROUND_UP(utf16_length(name), EXFAT_ENAME_MAX));
844 exfat_put_node(ef, dir);
845 exfat_put_node(ef, node);
848 rename_entry(ef, dir, node, name, cluster, offset);
849 exfat_put_node(ef, dir);
850 exfat_put_node(ef, node);
854 void exfat_utimes(struct exfat_node* node, const struct timespec tv[2])
856 node->atime = tv[0].tv_sec;
857 node->mtime = tv[1].tv_sec;
858 node->flags |= EXFAT_ATTRIB_DIRTY;
861 void exfat_update_atime(struct exfat_node* node)
863 node->atime = time(NULL);
864 node->flags |= EXFAT_ATTRIB_DIRTY;
867 void exfat_update_mtime(struct exfat_node* node)
869 node->mtime = time(NULL);
870 node->flags |= EXFAT_ATTRIB_DIRTY;