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);
67 static int opendir(struct exfat* ef, const struct exfat_node* dir,
70 if (!(dir->flags & EXFAT_ATTRIB_DIR))
71 exfat_bug("not a directory");
72 it->cluster = dir->start_cluster;
74 it->contiguous = IS_CONTIGUOUS(*dir);
75 it->chunk = malloc(CLUSTER_SIZE(*ef->sb));
76 if (it->chunk == NULL)
78 exfat_error("out of memory");
81 exfat_read_raw(it->chunk, CLUSTER_SIZE(*ef->sb),
82 exfat_c2o(ef, it->cluster), ef->fd);
86 static void closedir(struct iterator* it)
95 static int fetch_next_entry(struct exfat* ef, const struct exfat_node* parent,
98 /* move iterator to the next entry in the directory */
99 it->offset += sizeof(struct exfat_entry);
100 /* fetch the next cluster if needed */
101 if ((it->offset & (CLUSTER_SIZE(*ef->sb) - 1)) == 0)
103 it->cluster = exfat_next_cluster(ef, parent, it->cluster);
104 if (CLUSTER_INVALID(it->cluster))
106 exfat_error("invalid cluster while reading directory");
109 exfat_read_raw(it->chunk, CLUSTER_SIZE(*ef->sb),
110 exfat_c2o(ef, it->cluster), ef->fd);
115 static struct exfat_node* allocate_node(void)
117 struct exfat_node* node = malloc(sizeof(struct exfat_node));
120 exfat_error("failed to allocate node");
123 memset(node, 0, sizeof(struct exfat_node));
127 static void init_node_meta1(struct exfat_node* node,
128 const struct exfat_entry_meta1* meta1)
130 node->flags = le16_to_cpu(meta1->attrib);
131 node->mtime = exfat_exfat2unix(meta1->mdate, meta1->mtime);
132 node->atime = exfat_exfat2unix(meta1->adate, meta1->atime);
135 static void init_node_meta2(struct exfat_node* node,
136 const struct exfat_entry_meta2* meta2)
138 node->size = le64_to_cpu(meta2->size);
139 node->start_cluster = le32_to_cpu(meta2->start_cluster);
140 node->fptr_cluster = node->start_cluster;
141 if (meta2->flag == EXFAT_FLAG_CONTIGUOUS)
142 node->flags |= EXFAT_ATTRIB_CONTIGUOUS;
146 * Reads one entry in directory at position pointed by iterator and fills
149 static int readdir(struct exfat* ef, const struct exfat_node* parent,
150 struct exfat_node** node, struct iterator* it)
152 const struct exfat_entry* entry;
153 const struct exfat_entry_meta1* meta1;
154 const struct exfat_entry_meta2* meta2;
155 const struct exfat_entry_name* file_name;
156 const struct exfat_entry_upcase* upcase;
157 const struct exfat_entry_bitmap* bitmap;
158 const struct exfat_entry_label* label;
159 uint8_t continuations = 0;
160 le16_t* namep = NULL;
161 uint16_t reference_checksum = 0;
162 uint16_t actual_checksum = 0;
168 /* every directory (even empty one) occupies at least one cluster and
169 must contain EOD entry */
170 entry = (const struct exfat_entry*)
171 (it->chunk + it->offset % CLUSTER_SIZE(*ef->sb));
175 case EXFAT_ENTRY_EOD:
176 if (continuations != 0)
178 exfat_error("expected %hhu continuations before EOD",
182 return -ENOENT; /* that's OK, means end of directory */
184 case EXFAT_ENTRY_FILE:
185 if (continuations != 0)
187 exfat_error("expected %hhu continuations before new entry",
191 meta1 = (const struct exfat_entry_meta1*) entry;
192 continuations = meta1->continuations;
193 /* each file entry must have at least 2 continuations:
195 if (continuations < 2)
197 exfat_error("too few continuations (%hhu)", continuations);
200 reference_checksum = le16_to_cpu(meta1->checksum);
201 actual_checksum = exfat_start_checksum(meta1);
202 *node = allocate_node();
205 /* new node has zero reference counter */
206 (*node)->entry_cluster = it->cluster;
207 (*node)->entry_offset = it->offset % CLUSTER_SIZE(*ef->sb);
208 init_node_meta1(*node, meta1);
209 namep = (*node)->name;
212 case EXFAT_ENTRY_FILE_INFO:
213 if (continuations < 2)
215 exfat_error("unexpected continuation (%hhu)",
219 meta2 = (const struct exfat_entry_meta2*) entry;
220 init_node_meta2(*node, meta2);
221 actual_checksum = exfat_add_checksum(entry, actual_checksum);
222 /* There are two fields that contain file size. Maybe they plan
223 to add compression support in the future and one of those
224 fields is visible (uncompressed) size and the other is real
225 (compressed) size. Anyway, currently it looks like exFAT does
226 not support compression and both fields must be equal. */
227 if (le64_to_cpu(meta2->real_size) != (*node)->size)
229 exfat_error("real size does not equal to size "
230 "(%"PRIu64" != %"PRIu64")",
231 le64_to_cpu(meta2->real_size), (*node)->size);
234 /* directories must be aligned on at cluster boundary */
235 if (((*node)->flags & EXFAT_ATTRIB_DIR) &&
236 (*node)->size % CLUSTER_SIZE(*ef->sb) != 0)
238 char buffer[EXFAT_NAME_MAX + 1];
240 exfat_get_name(*node, buffer, EXFAT_NAME_MAX);
241 exfat_error("directory `%s' has invalid size %"PRIu64" bytes",
242 buffer, (*node)->size);
248 case EXFAT_ENTRY_FILE_NAME:
249 if (continuations == 0)
251 exfat_error("unexpected continuation");
254 file_name = (const struct exfat_entry_name*) entry;
255 actual_checksum = exfat_add_checksum(entry, actual_checksum);
257 memcpy(namep, file_name->name, EXFAT_ENAME_MAX * sizeof(le16_t));
258 namep += EXFAT_ENAME_MAX;
259 if (--continuations == 0)
261 if (actual_checksum != reference_checksum)
263 exfat_error("invalid checksum (0x%hx != 0x%hx)",
264 actual_checksum, reference_checksum);
267 if (fetch_next_entry(ef, parent, it) != 0)
269 return 0; /* entry completed */
273 case EXFAT_ENTRY_UPCASE:
274 if (ef->upcase != NULL)
276 upcase = (const struct exfat_entry_upcase*) entry;
277 if (CLUSTER_INVALID(le32_to_cpu(upcase->start_cluster)))
279 exfat_error("invalid cluster in upcase table");
282 if (le64_to_cpu(upcase->size) == 0 ||
283 le64_to_cpu(upcase->size) > 0xffff * sizeof(uint16_t) ||
284 le64_to_cpu(upcase->size) % sizeof(uint16_t) != 0)
286 exfat_error("bad upcase table size (%"PRIu64" bytes)",
287 le64_to_cpu(upcase->size));
290 ef->upcase = malloc(le64_to_cpu(upcase->size));
291 if (ef->upcase == NULL)
293 exfat_error("failed to allocate upcase table (%"PRIu64" bytes)",
294 le64_to_cpu(upcase->size));
297 ef->upcase_chars = le64_to_cpu(upcase->size) / sizeof(le16_t);
299 exfat_read_raw(ef->upcase, le64_to_cpu(upcase->size),
300 exfat_c2o(ef, le32_to_cpu(upcase->start_cluster)), ef->fd);
303 case EXFAT_ENTRY_BITMAP:
304 bitmap = (const struct exfat_entry_bitmap*) entry;
305 if (CLUSTER_INVALID(le32_to_cpu(bitmap->start_cluster)))
307 exfat_error("invalid cluster in clusters bitmap");
310 ef->cmap.size = le32_to_cpu(ef->sb->cluster_count) -
311 EXFAT_FIRST_DATA_CLUSTER;
312 if (le64_to_cpu(bitmap->size) < (ef->cmap.size + 7) / 8)
314 exfat_error("invalid clusters bitmap size: %"PRIu64
315 " (expected at least %u)",
316 le64_to_cpu(bitmap->size), (ef->cmap.size + 7) / 8);
319 ef->cmap.start_cluster = le32_to_cpu(bitmap->start_cluster);
320 /* FIXME bitmap can be rather big, up to 512 MB */
321 ef->cmap.chunk_size = ef->cmap.size;
322 ef->cmap.chunk = malloc(le64_to_cpu(bitmap->size));
323 if (ef->cmap.chunk == NULL)
325 exfat_error("failed to allocate clusters bitmap chunk "
326 "(%"PRIu64" bytes)", le64_to_cpu(bitmap->size));
330 exfat_read_raw(ef->cmap.chunk, le64_to_cpu(bitmap->size),
331 exfat_c2o(ef, ef->cmap.start_cluster), ef->fd);
334 case EXFAT_ENTRY_LABEL:
335 label = (const struct exfat_entry_label*) entry;
336 if (label->length > EXFAT_ENAME_MAX)
338 exfat_error("too long label (%hhu chars)", label->length);
344 if (entry->type & EXFAT_ENTRY_VALID)
346 exfat_error("unknown entry type 0x%hhu", entry->type);
352 if (fetch_next_entry(ef, parent, it) != 0)
355 /* we never reach here */
363 int exfat_cache_directory(struct exfat* ef, struct exfat_node* dir)
367 struct exfat_node* node;
368 struct exfat_node* current = NULL;
370 if (dir->flags & EXFAT_ATTRIB_CACHED)
371 return 0; /* already cached */
373 rc = opendir(ef, dir, &it);
376 while ((rc = readdir(ef, dir, &node, &it)) == 0)
381 current->next = node;
382 node->prev = current;
394 for (current = dir->child; current; current = node)
396 node = current->next;
403 dir->flags |= EXFAT_ATTRIB_CACHED;
407 static void reset_cache(struct exfat* ef, struct exfat_node* node)
409 struct exfat_node* child;
410 struct exfat_node* next;
412 for (child = node->child; child; child = next)
414 reset_cache(ef, child);
418 if (node->references != 0)
420 char buffer[EXFAT_NAME_MAX + 1];
421 exfat_get_name(node, buffer, EXFAT_NAME_MAX);
422 exfat_warn("non-zero reference counter (%d) for `%s'",
423 node->references, buffer);
425 while (node->references--)
426 exfat_put_node(ef, node);
428 node->flags &= ~EXFAT_ATTRIB_CACHED;
431 void exfat_reset_cache(struct exfat* ef)
433 reset_cache(ef, ef->root);
436 void next_entry(struct exfat* ef, const struct exfat_node* parent,
437 cluster_t* cluster, off_t* offset)
439 if (*offset + sizeof(struct exfat_entry) == CLUSTER_SIZE(*ef->sb))
441 /* next cluster cannot be invalid */
442 *cluster = exfat_next_cluster(ef, parent, *cluster);
446 *offset += sizeof(struct exfat_entry);
450 void exfat_flush_node(struct exfat* ef, struct exfat_node* node)
454 off_t meta1_offset, meta2_offset;
455 struct exfat_entry_meta1 meta1;
456 struct exfat_entry_meta2 meta2;
459 exfat_bug("unable to flush node to read-only FS");
461 if (node->parent == NULL)
462 return; /* do not flush unlinked node */
464 cluster = node->entry_cluster;
465 offset = node->entry_offset;
466 meta1_offset = exfat_c2o(ef, cluster) + offset;
467 next_entry(ef, node->parent, &cluster, &offset);
468 meta2_offset = exfat_c2o(ef, cluster) + offset;
470 exfat_read_raw(&meta1, sizeof(meta1), meta1_offset, ef->fd);
471 if (meta1.type != EXFAT_ENTRY_FILE)
472 exfat_bug("invalid type of meta1: 0x%hhx", meta1.type);
473 meta1.attrib = cpu_to_le16(node->flags);
474 exfat_unix2exfat(node->mtime, &meta1.mdate, &meta1.mtime);
475 exfat_unix2exfat(node->atime, &meta1.adate, &meta1.atime);
477 exfat_read_raw(&meta2, sizeof(meta2), meta2_offset, ef->fd);
478 if (meta2.type != EXFAT_ENTRY_FILE_INFO)
479 exfat_bug("invalid type of meta2: 0x%hhx", meta2.type);
480 meta2.size = meta2.real_size = cpu_to_le64(node->size);
481 meta2.start_cluster = cpu_to_le32(node->start_cluster);
482 /* empty files must be marked as fragmented */
483 if (node->size != 0 && IS_CONTIGUOUS(*node))
484 meta2.flag = EXFAT_FLAG_CONTIGUOUS;
486 meta2.flag = EXFAT_FLAG_FRAGMENTED;
487 /* name hash remains unchanged, no need to recalculate it */
489 meta1.checksum = exfat_calc_checksum(&meta1, &meta2, node->name);
491 exfat_write_raw(&meta1, sizeof(meta1), meta1_offset, ef->fd);
492 exfat_write_raw(&meta2, sizeof(meta2), meta2_offset, ef->fd);
494 node->flags &= ~EXFAT_ATTRIB_DIRTY;
497 static void erase_entry(struct exfat* ef, struct exfat_node* node)
499 cluster_t cluster = node->entry_cluster;
500 off_t offset = node->entry_offset;
501 int name_entries = DIV_ROUND_UP(utf16_length(node->name), EXFAT_ENAME_MAX);
504 entry_type = EXFAT_ENTRY_FILE & ~EXFAT_ENTRY_VALID;
505 exfat_write_raw(&entry_type, 1, exfat_c2o(ef, cluster) + offset, ef->fd);
507 next_entry(ef, node->parent, &cluster, &offset);
508 entry_type = EXFAT_ENTRY_FILE_INFO & ~EXFAT_ENTRY_VALID;
509 exfat_write_raw(&entry_type, 1, exfat_c2o(ef, cluster) + offset, ef->fd);
511 while (name_entries--)
513 next_entry(ef, node->parent, &cluster, &offset);
514 entry_type = EXFAT_ENTRY_FILE_NAME & ~EXFAT_ENTRY_VALID;
515 exfat_write_raw(&entry_type, 1, exfat_c2o(ef, cluster) + offset,
520 static void tree_detach(struct exfat_node* node)
523 node->prev->next = node->next;
524 else /* this is the first node in the list */
525 node->parent->child = node->next;
527 node->next->prev = node->prev;
533 static void tree_attach(struct exfat_node* dir, struct exfat_node* node)
538 dir->child->prev = node;
539 node->next = dir->child;
544 static void delete(struct exfat* ef, struct exfat_node* node)
546 erase_entry(ef, node);
547 exfat_update_mtime(node->parent);
549 /* file clusters will be freed when node reference counter becomes 0 */
550 node->flags |= EXFAT_ATTRIB_UNLINKED;
553 int exfat_unlink(struct exfat* ef, struct exfat_node* node)
555 if (node->flags & EXFAT_ATTRIB_DIR)
561 int exfat_rmdir(struct exfat* ef, struct exfat_node* node)
563 if (!(node->flags & EXFAT_ATTRIB_DIR))
565 /* check that directory is empty */
566 exfat_cache_directory(ef, node);
573 static int grow_directory(struct exfat* ef, struct exfat_node* dir,
574 uint64_t asize, uint32_t difference)
576 return exfat_truncate(ef, dir,
577 DIV_ROUND_UP(asize + difference, CLUSTER_SIZE(*ef->sb))
578 * CLUSTER_SIZE(*ef->sb));
581 static int find_slot(struct exfat* ef, struct exfat_node* dir,
582 cluster_t* cluster, off_t* offset, int subentries)
586 const struct exfat_entry* entry;
589 rc = opendir(ef, dir, &it);
596 *cluster = it.cluster;
597 *offset = it.offset % CLUSTER_SIZE(*ef->sb);
599 entry = (const struct exfat_entry*)
600 (it.chunk + it.offset % CLUSTER_SIZE(*ef->sb));
601 if (entry->type == EXFAT_ENTRY_EOD)
603 rc = grow_directory(ef, dir,
604 it.offset + sizeof(struct exfat_entry), /* actual size */
605 (subentries - contiguous) * sizeof(struct exfat_entry));
613 if (entry->type & EXFAT_ENTRY_VALID)
617 if (contiguous == subentries)
618 break; /* suitable slot it found */
619 if (fetch_next_entry(ef, dir, &it) != 0)
629 static int write_entry(struct exfat* ef, struct exfat_node* dir,
630 const le16_t* name, cluster_t cluster, off_t offset, uint16_t attrib)
632 struct exfat_node* node;
633 struct exfat_entry_meta1 meta1;
634 struct exfat_entry_meta2 meta2;
635 const size_t name_length = utf16_length(name);
636 const int name_entries = DIV_ROUND_UP(name_length, EXFAT_ENAME_MAX);
639 node = allocate_node();
642 node->entry_cluster = cluster;
643 node->entry_offset = offset;
644 memcpy(node->name, name, name_length * sizeof(le16_t));
646 memset(&meta1, 0, sizeof(meta1));
647 meta1.type = EXFAT_ENTRY_FILE;
648 meta1.continuations = 1 + name_entries;
649 meta1.attrib = cpu_to_le16(attrib);
650 exfat_unix2exfat(time(NULL), &meta1.crdate, &meta1.crtime);
651 meta1.adate = meta1.mdate = meta1.crdate;
652 meta1.atime = meta1.mtime = meta1.crtime;
653 /* crtime_cs and mtime_cs contain addition to the time in centiseconds;
654 just ignore those fields because we operate with 2 sec resolution */
656 memset(&meta2, 0, sizeof(meta2));
657 meta2.type = EXFAT_ENTRY_FILE_INFO;
658 meta2.flag = EXFAT_FLAG_FRAGMENTED;
659 meta2.name_length = name_length;
660 meta2.name_hash = exfat_calc_name_hash(ef, node->name);
661 meta2.start_cluster = cpu_to_le32(EXFAT_CLUSTER_FREE);
663 meta1.checksum = exfat_calc_checksum(&meta1, &meta2, node->name);
665 exfat_write_raw(&meta1, sizeof(meta1), exfat_c2o(ef, cluster) + offset,
667 next_entry(ef, dir, &cluster, &offset);
668 exfat_write_raw(&meta2, sizeof(meta2), exfat_c2o(ef, cluster) + offset,
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 exfat_c2o(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),
760 exfat_c2o(ef, old_cluster) + old_offset, ef->fd);
761 next_entry(ef, node->parent, &old_cluster, &old_offset);
762 exfat_read_raw(&meta2, sizeof(meta2),
763 exfat_c2o(ef, old_cluster) + old_offset, ef->fd);
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),
775 exfat_c2o(ef, new_cluster) + new_offset, ef->fd);
776 next_entry(ef, dir, &new_cluster, &new_offset);
777 exfat_write_raw(&meta2, sizeof(meta2),
778 exfat_c2o(ef, new_cluster) + new_offset, ef->fd);
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 exfat_c2o(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;