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 bitmap size: %"PRIu64" (expected %u)",
315 le64_to_cpu(bitmap->size), (ef->cmap.size + 7) / 8);
318 ef->cmap.start_cluster = le32_to_cpu(bitmap->start_cluster);
319 /* FIXME bitmap can be rather big, up to 512 MB */
320 ef->cmap.chunk_size = ef->cmap.size;
321 ef->cmap.chunk = malloc(le64_to_cpu(bitmap->size));
322 if (ef->cmap.chunk == NULL)
324 exfat_error("failed to allocate clusters map chunk "
325 "(%"PRIu64" bytes)", le64_to_cpu(bitmap->size));
329 exfat_read_raw(ef->cmap.chunk, le64_to_cpu(bitmap->size),
330 exfat_c2o(ef, ef->cmap.start_cluster), ef->fd);
333 case EXFAT_ENTRY_LABEL:
334 label = (const struct exfat_entry_label*) entry;
335 if (label->length > EXFAT_ENAME_MAX)
337 exfat_error("too long label (%hhu chars)", label->length);
343 if (entry->type & EXFAT_ENTRY_VALID)
345 exfat_error("unknown entry type 0x%hhu", entry->type);
351 if (fetch_next_entry(ef, parent, it) != 0)
354 /* we never reach here */
362 int exfat_cache_directory(struct exfat* ef, struct exfat_node* dir)
366 struct exfat_node* node;
367 struct exfat_node* current = NULL;
369 if (dir->flags & EXFAT_ATTRIB_CACHED)
370 return 0; /* already cached */
372 rc = opendir(ef, dir, &it);
375 while ((rc = readdir(ef, dir, &node, &it)) == 0)
380 current->next = node;
381 node->prev = current;
393 for (current = dir->child; current; current = node)
395 node = current->next;
402 dir->flags |= EXFAT_ATTRIB_CACHED;
406 static void reset_cache(struct exfat* ef, struct exfat_node* node)
408 struct exfat_node* child;
409 struct exfat_node* next;
411 for (child = node->child; child; child = next)
413 reset_cache(ef, child);
417 if (node->references != 0)
419 char buffer[EXFAT_NAME_MAX + 1];
420 exfat_get_name(node, buffer, EXFAT_NAME_MAX);
421 exfat_warn("non-zero reference counter (%d) for `%s'",
422 node->references, buffer);
424 while (node->references--)
425 exfat_put_node(ef, node);
427 node->flags &= ~EXFAT_ATTRIB_CACHED;
430 void exfat_reset_cache(struct exfat* ef)
432 reset_cache(ef, ef->root);
435 void next_entry(struct exfat* ef, const struct exfat_node* parent,
436 cluster_t* cluster, off_t* offset)
438 if (*offset + sizeof(struct exfat_entry) == CLUSTER_SIZE(*ef->sb))
440 /* next cluster cannot be invalid */
441 *cluster = exfat_next_cluster(ef, parent, *cluster);
445 *offset += sizeof(struct exfat_entry);
449 void exfat_flush_node(struct exfat* ef, struct exfat_node* node)
453 off_t meta1_offset, meta2_offset;
454 struct exfat_entry_meta1 meta1;
455 struct exfat_entry_meta2 meta2;
458 exfat_bug("unable to flush node to read-only FS");
460 if (node->parent == NULL)
461 return; /* do not flush unlinked node */
463 cluster = node->entry_cluster;
464 offset = node->entry_offset;
465 meta1_offset = exfat_c2o(ef, cluster) + offset;
466 next_entry(ef, node->parent, &cluster, &offset);
467 meta2_offset = exfat_c2o(ef, cluster) + offset;
469 exfat_read_raw(&meta1, sizeof(meta1), meta1_offset, ef->fd);
470 if (meta1.type != EXFAT_ENTRY_FILE)
471 exfat_bug("invalid type of meta1: 0x%hhx", meta1.type);
472 meta1.attrib = cpu_to_le16(node->flags);
473 exfat_unix2exfat(node->mtime, &meta1.mdate, &meta1.mtime);
474 exfat_unix2exfat(node->atime, &meta1.adate, &meta1.atime);
476 exfat_read_raw(&meta2, sizeof(meta2), meta2_offset, ef->fd);
477 if (meta2.type != EXFAT_ENTRY_FILE_INFO)
478 exfat_bug("invalid type of meta2: 0x%hhx", meta2.type);
479 meta2.size = meta2.real_size = cpu_to_le64(node->size);
480 meta2.start_cluster = cpu_to_le32(node->start_cluster);
481 /* empty files must be marked as fragmented */
482 if (node->size != 0 && IS_CONTIGUOUS(*node))
483 meta2.flag = EXFAT_FLAG_CONTIGUOUS;
485 meta2.flag = EXFAT_FLAG_FRAGMENTED;
486 /* name hash remains unchanged, no need to recalculate it */
488 meta1.checksum = exfat_calc_checksum(&meta1, &meta2, node->name);
490 exfat_write_raw(&meta1, sizeof(meta1), meta1_offset, ef->fd);
491 exfat_write_raw(&meta2, sizeof(meta2), meta2_offset, ef->fd);
493 node->flags &= ~EXFAT_ATTRIB_DIRTY;
496 static void erase_entry(struct exfat* ef, struct exfat_node* node)
498 cluster_t cluster = node->entry_cluster;
499 off_t offset = node->entry_offset;
500 int name_entries = DIV_ROUND_UP(utf16_length(node->name), EXFAT_ENAME_MAX);
503 entry_type = EXFAT_ENTRY_FILE & ~EXFAT_ENTRY_VALID;
504 exfat_write_raw(&entry_type, 1, exfat_c2o(ef, cluster) + offset, ef->fd);
506 next_entry(ef, node->parent, &cluster, &offset);
507 entry_type = EXFAT_ENTRY_FILE_INFO & ~EXFAT_ENTRY_VALID;
508 exfat_write_raw(&entry_type, 1, exfat_c2o(ef, cluster) + offset, ef->fd);
510 while (name_entries--)
512 next_entry(ef, node->parent, &cluster, &offset);
513 entry_type = EXFAT_ENTRY_FILE_NAME & ~EXFAT_ENTRY_VALID;
514 exfat_write_raw(&entry_type, 1, exfat_c2o(ef, cluster) + offset,
519 static void tree_detach(struct exfat_node* node)
522 node->prev->next = node->next;
523 else /* this is the first node in the list */
524 node->parent->child = node->next;
526 node->next->prev = node->prev;
532 static void tree_attach(struct exfat_node* dir, struct exfat_node* node)
537 dir->child->prev = node;
538 node->next = dir->child;
543 static void delete(struct exfat* ef, struct exfat_node* node)
545 erase_entry(ef, node);
546 exfat_update_mtime(node->parent);
548 /* file clusters will be freed when node reference counter becomes 0 */
549 node->flags |= EXFAT_ATTRIB_UNLINKED;
552 int exfat_unlink(struct exfat* ef, struct exfat_node* node)
554 if (node->flags & EXFAT_ATTRIB_DIR)
560 int exfat_rmdir(struct exfat* ef, struct exfat_node* node)
562 if (!(node->flags & EXFAT_ATTRIB_DIR))
564 /* check that directory is empty */
565 exfat_cache_directory(ef, node);
572 static int grow_directory(struct exfat* ef, struct exfat_node* dir,
573 uint64_t asize, uint32_t difference)
575 return exfat_truncate(ef, dir,
576 DIV_ROUND_UP(asize + difference, CLUSTER_SIZE(*ef->sb))
577 * CLUSTER_SIZE(*ef->sb));
580 static int find_slot(struct exfat* ef, struct exfat_node* dir,
581 cluster_t* cluster, off_t* offset, int subentries)
585 const struct exfat_entry* entry;
588 rc = opendir(ef, dir, &it);
595 *cluster = it.cluster;
596 *offset = it.offset % CLUSTER_SIZE(*ef->sb);
598 entry = (const struct exfat_entry*)
599 (it.chunk + it.offset % CLUSTER_SIZE(*ef->sb));
600 if (entry->type == EXFAT_ENTRY_EOD)
602 rc = grow_directory(ef, dir,
603 it.offset + sizeof(struct exfat_entry), /* actual size */
604 (subentries - contiguous) * sizeof(struct exfat_entry));
612 if (entry->type & EXFAT_ENTRY_VALID)
616 if (contiguous == subentries)
617 break; /* suitable slot it found */
618 if (fetch_next_entry(ef, dir, &it) != 0)
628 static int write_entry(struct exfat* ef, struct exfat_node* dir,
629 const le16_t* name, cluster_t cluster, off_t offset, uint16_t attrib)
631 struct exfat_node* node;
632 struct exfat_entry_meta1 meta1;
633 struct exfat_entry_meta2 meta2;
634 const size_t name_length = utf16_length(name);
635 const int name_entries = DIV_ROUND_UP(name_length, EXFAT_ENAME_MAX);
638 node = allocate_node();
641 node->entry_cluster = cluster;
642 node->entry_offset = offset;
643 memcpy(node->name, name, name_length * sizeof(le16_t));
645 memset(&meta1, 0, sizeof(meta1));
646 meta1.type = EXFAT_ENTRY_FILE;
647 meta1.continuations = 1 + name_entries;
648 meta1.attrib = cpu_to_le16(attrib);
649 exfat_unix2exfat(time(NULL), &meta1.crdate, &meta1.crtime);
650 meta1.adate = meta1.mdate = meta1.crdate;
651 meta1.atime = meta1.mtime = meta1.crtime;
652 /* crtime_cs and mtime_cs contain addition to the time in centiseconds;
653 just ignore those fields because we operate with 2 sec resolution */
655 memset(&meta2, 0, sizeof(meta2));
656 meta2.type = EXFAT_ENTRY_FILE_INFO;
657 meta2.flag = EXFAT_FLAG_FRAGMENTED;
658 meta2.name_length = name_length;
659 meta2.name_hash = exfat_calc_name_hash(ef, node->name);
660 meta2.start_cluster = cpu_to_le32(EXFAT_CLUSTER_FREE);
662 meta1.checksum = exfat_calc_checksum(&meta1, &meta2, node->name);
664 exfat_write_raw(&meta1, sizeof(meta1), exfat_c2o(ef, cluster) + offset,
666 next_entry(ef, dir, &cluster, &offset);
667 exfat_write_raw(&meta2, sizeof(meta2), exfat_c2o(ef, cluster) + offset,
669 for (i = 0; i < name_entries; i++)
671 struct exfat_entry_name name_entry = {EXFAT_ENTRY_FILE_NAME, 0};
672 memcpy(name_entry.name, node->name + i * EXFAT_ENAME_MAX,
673 EXFAT_ENAME_MAX * sizeof(le16_t));
674 next_entry(ef, dir, &cluster, &offset);
675 exfat_write_raw(&name_entry, sizeof(name_entry),
676 exfat_c2o(ef, cluster) + offset, ef->fd);
679 init_node_meta1(node, &meta1);
680 init_node_meta2(node, &meta2);
682 tree_attach(dir, node);
683 exfat_update_mtime(dir);
687 static int create(struct exfat* ef, const char* path, uint16_t attrib)
689 struct exfat_node* dir;
690 struct exfat_node* existing;
691 cluster_t cluster = EXFAT_CLUSTER_BAD;
693 le16_t name[EXFAT_NAME_MAX + 1];
696 rc = exfat_split(ef, &dir, &existing, name, path);
699 if (existing != NULL)
701 exfat_put_node(ef, existing);
702 exfat_put_node(ef, dir);
706 rc = find_slot(ef, dir, &cluster, &offset,
707 2 + DIV_ROUND_UP(utf16_length(name), EXFAT_ENAME_MAX));
710 exfat_put_node(ef, dir);
713 rc = write_entry(ef, dir, name, cluster, offset, attrib);
714 exfat_put_node(ef, dir);
718 int exfat_mknod(struct exfat* ef, const char* path)
720 return create(ef, path, EXFAT_ATTRIB_ARCH);
723 int exfat_mkdir(struct exfat* ef, const char* path)
726 struct exfat_node* node;
728 rc = create(ef, path, EXFAT_ATTRIB_ARCH | EXFAT_ATTRIB_DIR);
731 rc = exfat_lookup(ef, &node, path);
734 /* directories always have at least one cluster */
735 rc = exfat_truncate(ef, node, CLUSTER_SIZE(*ef->sb));
739 exfat_put_node(ef, node);
742 exfat_put_node(ef, node);
746 static void rename_entry(struct exfat* ef, struct exfat_node* dir,
747 struct exfat_node* node, const le16_t* name, cluster_t new_cluster,
750 struct exfat_entry_meta1 meta1;
751 struct exfat_entry_meta2 meta2;
752 cluster_t old_cluster = node->entry_cluster;
753 off_t old_offset = node->entry_offset;
754 const size_t name_length = utf16_length(name);
755 const int name_entries = DIV_ROUND_UP(name_length, EXFAT_ENAME_MAX);
758 exfat_read_raw(&meta1, sizeof(meta1),
759 exfat_c2o(ef, old_cluster) + old_offset, ef->fd);
760 next_entry(ef, node->parent, &old_cluster, &old_offset);
761 exfat_read_raw(&meta2, sizeof(meta2),
762 exfat_c2o(ef, old_cluster) + old_offset, ef->fd);
763 meta1.continuations = 1 + name_entries;
764 meta2.name_hash = exfat_calc_name_hash(ef, name);
765 meta2.name_length = name_length;
766 meta1.checksum = exfat_calc_checksum(&meta1, &meta2, name);
768 erase_entry(ef, node);
770 node->entry_cluster = new_cluster;
771 node->entry_offset = new_offset;
773 exfat_write_raw(&meta1, sizeof(meta1),
774 exfat_c2o(ef, new_cluster) + new_offset, ef->fd);
775 next_entry(ef, dir, &new_cluster, &new_offset);
776 exfat_write_raw(&meta2, sizeof(meta2),
777 exfat_c2o(ef, new_cluster) + new_offset, ef->fd);
779 for (i = 0; i < name_entries; i++)
781 struct exfat_entry_name name_entry = {EXFAT_ENTRY_FILE_NAME, 0};
782 memcpy(name_entry.name, name + i * EXFAT_ENAME_MAX,
783 EXFAT_ENAME_MAX * sizeof(le16_t));
784 next_entry(ef, dir, &new_cluster, &new_offset);
785 exfat_write_raw(&name_entry, sizeof(name_entry),
786 exfat_c2o(ef, new_cluster) + new_offset, ef->fd);
789 memcpy(node->name, name, (name_length + 1) * sizeof(le16_t));
791 tree_attach(dir, node);
794 int exfat_rename(struct exfat* ef, const char* old_path, const char* new_path)
796 struct exfat_node* node;
797 struct exfat_node* existing;
798 struct exfat_node* dir;
799 cluster_t cluster = EXFAT_CLUSTER_BAD;
801 le16_t name[EXFAT_NAME_MAX + 1];
804 rc = exfat_lookup(ef, &node, old_path);
808 memset(name, 0, (EXFAT_NAME_MAX + 1) * sizeof(le16_t));
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;