3 exFAT file system implementation library.
5 Copyright (C) 2010-2012 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_pread(ef->dev, it->chunk, CLUSTER_SIZE(*ef->sb),
90 exfat_c2o(ef, it->cluster));
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 /* reached the end of directory; the caller should check this
113 if (it->offset >= parent->size)
115 it->cluster = exfat_next_cluster(ef, parent, it->cluster);
116 if (CLUSTER_INVALID(it->cluster))
118 exfat_error("invalid cluster while reading directory");
121 exfat_pread(ef->dev, it->chunk, CLUSTER_SIZE(*ef->sb),
122 exfat_c2o(ef, it->cluster));
127 static struct exfat_node* allocate_node(void)
129 struct exfat_node* node = malloc(sizeof(struct exfat_node));
132 exfat_error("failed to allocate node");
135 memset(node, 0, sizeof(struct exfat_node));
139 static void init_node_meta1(struct exfat_node* node,
140 const struct exfat_entry_meta1* meta1)
142 node->flags = le16_to_cpu(meta1->attrib);
143 node->mtime = exfat_exfat2unix(meta1->mdate, meta1->mtime,
145 /* there is no centiseconds field for atime */
146 node->atime = exfat_exfat2unix(meta1->adate, meta1->atime, 0);
149 static void init_node_meta2(struct exfat_node* node,
150 const struct exfat_entry_meta2* meta2)
152 node->size = le64_to_cpu(meta2->size);
153 node->start_cluster = le32_to_cpu(meta2->start_cluster);
154 node->fptr_cluster = node->start_cluster;
155 if (meta2->flags & EXFAT_FLAG_CONTIGUOUS)
156 node->flags |= EXFAT_ATTRIB_CONTIGUOUS;
159 static const struct exfat_entry* get_entry_ptr(const struct exfat* ef,
160 const struct iterator* it)
162 return (const struct exfat_entry*)
163 (it->chunk + it->offset % CLUSTER_SIZE(*ef->sb));
167 * Reads one entry in directory at position pointed by iterator and fills
170 static int readdir(struct exfat* ef, const struct exfat_node* parent,
171 struct exfat_node** node, struct iterator* it)
174 const struct exfat_entry* entry;
175 const struct exfat_entry_meta1* meta1;
176 const struct exfat_entry_meta2* meta2;
177 const struct exfat_entry_name* file_name;
178 const struct exfat_entry_upcase* upcase;
179 const struct exfat_entry_bitmap* bitmap;
180 const struct exfat_entry_label* label;
181 uint8_t continuations = 0;
182 le16_t* namep = NULL;
183 uint16_t reference_checksum = 0;
184 uint16_t actual_checksum = 0;
190 if (it->offset >= parent->size)
192 if (continuations != 0)
194 exfat_error("expected %hhu continuations", continuations);
197 return -ENOENT; /* that's OK, means end of directory */
200 entry = get_entry_ptr(ef, it);
203 case EXFAT_ENTRY_FILE:
204 if (continuations != 0)
206 exfat_error("expected %hhu continuations before new entry",
210 meta1 = (const struct exfat_entry_meta1*) entry;
211 continuations = meta1->continuations;
212 /* each file entry must have at least 2 continuations:
214 if (continuations < 2)
216 exfat_error("too few continuations (%hhu)", continuations);
219 reference_checksum = le16_to_cpu(meta1->checksum);
220 actual_checksum = exfat_start_checksum(meta1);
221 *node = allocate_node();
227 /* new node has zero reference counter */
228 (*node)->entry_cluster = it->cluster;
229 (*node)->entry_offset = it->offset;
230 init_node_meta1(*node, meta1);
231 namep = (*node)->name;
234 case EXFAT_ENTRY_FILE_INFO:
235 if (continuations < 2)
237 exfat_error("unexpected continuation (%hhu)",
241 meta2 = (const struct exfat_entry_meta2*) entry;
242 if (meta2->flags & ~(EXFAT_FLAG_ALWAYS1 | EXFAT_FLAG_CONTIGUOUS))
244 exfat_error("unknown flags in meta2 (0x%hhx)", meta2->flags);
247 init_node_meta2(*node, meta2);
248 actual_checksum = exfat_add_checksum(entry, actual_checksum);
249 /* There are two fields that contain file size. Maybe they plan
250 to add compression support in the future and one of those
251 fields is visible (uncompressed) size and the other is real
252 (compressed) size. Anyway, currently it looks like exFAT does
253 not support compression and both fields must be equal. */
254 if (le64_to_cpu(meta2->real_size) != (*node)->size)
256 exfat_error("real size does not equal to size "
257 "(%"PRIu64" != %"PRIu64")",
258 le64_to_cpu(meta2->real_size), (*node)->size);
261 /* empty files must be marked as non-contiguous */
262 if ((*node)->size == 0 && (meta2->flags & EXFAT_FLAG_CONTIGUOUS))
264 exfat_error("empty file marked as contiguous (0x%hhx)",
268 /* directories must be aligned on at cluster boundary */
269 if (((*node)->flags & EXFAT_ATTRIB_DIR) &&
270 (*node)->size % CLUSTER_SIZE(*ef->sb) != 0)
272 char buffer[EXFAT_NAME_MAX + 1];
274 exfat_get_name(*node, buffer, EXFAT_NAME_MAX);
275 exfat_error("directory `%s' has invalid size %"PRIu64" bytes",
276 buffer, (*node)->size);
282 case EXFAT_ENTRY_FILE_NAME:
283 if (continuations == 0)
285 exfat_error("unexpected continuation");
288 file_name = (const struct exfat_entry_name*) entry;
289 actual_checksum = exfat_add_checksum(entry, actual_checksum);
291 memcpy(namep, file_name->name, EXFAT_ENAME_MAX * sizeof(le16_t));
292 namep += EXFAT_ENAME_MAX;
293 if (--continuations == 0)
295 if (actual_checksum != reference_checksum)
297 exfat_error("invalid checksum (0x%hx != 0x%hx)",
298 actual_checksum, reference_checksum);
301 if (fetch_next_entry(ef, parent, it) != 0)
303 return 0; /* entry completed */
307 case EXFAT_ENTRY_UPCASE:
308 if (ef->upcase != NULL)
310 upcase = (const struct exfat_entry_upcase*) entry;
311 if (CLUSTER_INVALID(le32_to_cpu(upcase->start_cluster)))
313 exfat_error("invalid cluster in upcase table");
316 if (le64_to_cpu(upcase->size) == 0 ||
317 le64_to_cpu(upcase->size) > 0xffff * sizeof(uint16_t) ||
318 le64_to_cpu(upcase->size) % sizeof(uint16_t) != 0)
320 exfat_error("bad upcase table size (%"PRIu64" bytes)",
321 le64_to_cpu(upcase->size));
324 ef->upcase = malloc(le64_to_cpu(upcase->size));
325 if (ef->upcase == NULL)
327 exfat_error("failed to allocate upcase table (%"PRIu64" bytes)",
328 le64_to_cpu(upcase->size));
332 ef->upcase_chars = le64_to_cpu(upcase->size) / sizeof(le16_t);
334 exfat_pread(ef->dev, ef->upcase, le64_to_cpu(upcase->size),
335 exfat_c2o(ef, le32_to_cpu(upcase->start_cluster)));
338 case EXFAT_ENTRY_BITMAP:
339 bitmap = (const struct exfat_entry_bitmap*) entry;
340 if (CLUSTER_INVALID(le32_to_cpu(bitmap->start_cluster)))
342 exfat_error("invalid cluster in clusters bitmap");
345 ef->cmap.size = le32_to_cpu(ef->sb->cluster_count) -
346 EXFAT_FIRST_DATA_CLUSTER;
347 if (le64_to_cpu(bitmap->size) < (ef->cmap.size + 7) / 8)
349 exfat_error("invalid clusters bitmap size: %"PRIu64
350 " (expected at least %u)",
351 le64_to_cpu(bitmap->size), (ef->cmap.size + 7) / 8);
354 ef->cmap.start_cluster = le32_to_cpu(bitmap->start_cluster);
355 /* FIXME bitmap can be rather big, up to 512 MB */
356 ef->cmap.chunk_size = ef->cmap.size;
357 ef->cmap.chunk = malloc(le64_to_cpu(bitmap->size));
358 if (ef->cmap.chunk == NULL)
360 exfat_error("failed to allocate clusters bitmap chunk "
361 "(%"PRIu64" bytes)", le64_to_cpu(bitmap->size));
366 exfat_pread(ef->dev, ef->cmap.chunk, le64_to_cpu(bitmap->size),
367 exfat_c2o(ef, ef->cmap.start_cluster));
370 case EXFAT_ENTRY_LABEL:
371 label = (const struct exfat_entry_label*) entry;
372 if (label->length > EXFAT_ENAME_MAX)
374 exfat_error("too long label (%hhu chars)", label->length);
377 if (utf16_to_utf8(ef->label, label->name,
378 sizeof(ef->label), EXFAT_ENAME_MAX) != 0)
383 if (entry->type & EXFAT_ENTRY_VALID)
385 exfat_error("unknown entry type 0x%hhx", entry->type);
391 if (fetch_next_entry(ef, parent, it) != 0)
394 /* we never reach here */
402 int exfat_cache_directory(struct exfat* ef, struct exfat_node* dir)
406 struct exfat_node* node;
407 struct exfat_node* current = NULL;
409 if (dir->flags & EXFAT_ATTRIB_CACHED)
410 return 0; /* already cached */
412 rc = opendir(ef, dir, &it);
415 while ((rc = readdir(ef, dir, &node, &it)) == 0)
420 current->next = node;
421 node->prev = current;
433 for (current = dir->child; current; current = node)
435 node = current->next;
442 dir->flags |= EXFAT_ATTRIB_CACHED;
446 static void reset_cache(struct exfat* ef, struct exfat_node* node)
448 struct exfat_node* child;
449 struct exfat_node* next;
451 for (child = node->child; child; child = next)
453 reset_cache(ef, child);
457 if (node->references != 0)
459 char buffer[EXFAT_NAME_MAX + 1];
460 exfat_get_name(node, buffer, EXFAT_NAME_MAX);
461 exfat_warn("non-zero reference counter (%d) for `%s'",
462 node->references, buffer);
464 while (node->references--)
465 exfat_put_node(ef, node);
467 node->flags &= ~EXFAT_ATTRIB_CACHED;
470 void exfat_reset_cache(struct exfat* ef)
472 reset_cache(ef, ef->root);
475 void next_entry(struct exfat* ef, const struct exfat_node* parent,
476 cluster_t* cluster, off_t* offset)
478 *offset += sizeof(struct exfat_entry);
479 if (*offset % CLUSTER_SIZE(*ef->sb) == 0)
480 /* next cluster cannot be invalid */
481 *cluster = exfat_next_cluster(ef, parent, *cluster);
484 void exfat_flush_node(struct exfat* ef, struct exfat_node* node)
488 off_t meta1_offset, meta2_offset;
489 struct exfat_entry_meta1 meta1;
490 struct exfat_entry_meta2 meta2;
493 exfat_bug("unable to flush node to read-only FS");
495 if (node->parent == NULL)
496 return; /* do not flush unlinked node */
498 cluster = node->entry_cluster;
499 offset = node->entry_offset;
500 meta1_offset = co2o(ef, cluster, offset);
501 next_entry(ef, node->parent, &cluster, &offset);
502 meta2_offset = co2o(ef, cluster, offset);
504 exfat_pread(ef->dev, &meta1, sizeof(meta1), meta1_offset);
505 if (meta1.type != EXFAT_ENTRY_FILE)
506 exfat_bug("invalid type of meta1: 0x%hhx", meta1.type);
507 meta1.attrib = cpu_to_le16(node->flags);
508 exfat_unix2exfat(node->mtime, &meta1.mdate, &meta1.mtime, &meta1.mtime_cs);
509 exfat_unix2exfat(node->atime, &meta1.adate, &meta1.atime, NULL);
511 exfat_pread(ef->dev, &meta2, sizeof(meta2), meta2_offset);
512 if (meta2.type != EXFAT_ENTRY_FILE_INFO)
513 exfat_bug("invalid type of meta2: 0x%hhx", meta2.type);
514 meta2.size = meta2.real_size = cpu_to_le64(node->size);
515 meta2.start_cluster = cpu_to_le32(node->start_cluster);
516 meta2.flags = EXFAT_FLAG_ALWAYS1;
517 /* empty files must not be marked as contiguous */
518 if (node->size != 0 && IS_CONTIGUOUS(*node))
519 meta2.flags |= EXFAT_FLAG_CONTIGUOUS;
520 /* name hash remains unchanged, no need to recalculate it */
522 meta1.checksum = exfat_calc_checksum(&meta1, &meta2, node->name);
524 exfat_pwrite(ef->dev, &meta1, sizeof(meta1), meta1_offset);
525 exfat_pwrite(ef->dev, &meta2, sizeof(meta2), meta2_offset);
527 node->flags &= ~EXFAT_ATTRIB_DIRTY;
530 static void erase_entry(struct exfat* ef, struct exfat_node* node)
532 cluster_t cluster = node->entry_cluster;
533 off_t offset = node->entry_offset;
534 int name_entries = DIV_ROUND_UP(utf16_length(node->name), EXFAT_ENAME_MAX);
537 entry_type = EXFAT_ENTRY_FILE & ~EXFAT_ENTRY_VALID;
538 exfat_pwrite(ef->dev, &entry_type, 1, co2o(ef, cluster, offset));
540 next_entry(ef, node->parent, &cluster, &offset);
541 entry_type = EXFAT_ENTRY_FILE_INFO & ~EXFAT_ENTRY_VALID;
542 exfat_pwrite(ef->dev, &entry_type, 1, co2o(ef, cluster, offset));
544 while (name_entries--)
546 next_entry(ef, node->parent, &cluster, &offset);
547 entry_type = EXFAT_ENTRY_FILE_NAME & ~EXFAT_ENTRY_VALID;
548 exfat_pwrite(ef->dev, &entry_type, 1, co2o(ef, cluster, offset));
552 static void tree_detach(struct exfat_node* node)
555 node->prev->next = node->next;
556 else /* this is the first node in the list */
557 node->parent->child = node->next;
559 node->next->prev = node->prev;
565 static void tree_attach(struct exfat_node* dir, struct exfat_node* node)
570 dir->child->prev = node;
571 node->next = dir->child;
576 static int shrink_directory(struct exfat* ef, struct exfat_node* dir,
577 off_t deleted_offset)
579 const struct exfat_node* node;
580 const struct exfat_node* last_node;
581 uint64_t entries = 0;
585 if (!(dir->flags & EXFAT_ATTRIB_DIR))
586 exfat_bug("attempted to shrink a file");
587 if (!(dir->flags & EXFAT_ATTRIB_CACHED))
588 exfat_bug("attempted to shrink uncached directory");
590 for (last_node = node = dir->child; node; node = node->next)
592 if (deleted_offset < node->entry_offset)
594 /* there are other entries after the removed one, no way to shrink
598 if (last_node->entry_offset < node->entry_offset)
604 /* offset of the last entry */
605 entries += last_node->entry_offset / sizeof(struct exfat_entry);
606 /* two subentries with meta info */
608 /* subentries with file name */
609 entries += DIV_ROUND_UP(utf16_length(last_node->name),
613 new_size = DIV_ROUND_UP(entries * sizeof(struct exfat_entry),
614 CLUSTER_SIZE(*ef->sb)) * CLUSTER_SIZE(*ef->sb);
615 if (new_size == 0) /* directory always has at least 1 cluster */
616 new_size = CLUSTER_SIZE(*ef->sb);
617 if (new_size == dir->size)
619 rc = exfat_truncate(ef, dir, new_size);
625 static int delete(struct exfat* ef, struct exfat_node* node)
627 struct exfat_node* parent = node->parent;
628 off_t deleted_offset = node->entry_offset;
631 exfat_get_node(parent);
632 erase_entry(ef, node);
633 exfat_update_mtime(parent);
635 rc = shrink_directory(ef, parent, deleted_offset);
636 exfat_put_node(ef, parent);
637 /* file clusters will be freed when node reference counter becomes 0 */
638 node->flags |= EXFAT_ATTRIB_UNLINKED;
642 int exfat_unlink(struct exfat* ef, struct exfat_node* node)
644 if (node->flags & EXFAT_ATTRIB_DIR)
646 return delete(ef, node);
649 int exfat_rmdir(struct exfat* ef, struct exfat_node* node)
651 if (!(node->flags & EXFAT_ATTRIB_DIR))
653 /* check that directory is empty */
654 exfat_cache_directory(ef, node);
657 return delete(ef, node);
660 static int grow_directory(struct exfat* ef, struct exfat_node* dir,
661 uint64_t asize, uint32_t difference)
663 return exfat_truncate(ef, dir,
664 DIV_ROUND_UP(asize + difference, CLUSTER_SIZE(*ef->sb))
665 * CLUSTER_SIZE(*ef->sb));
668 static int find_slot(struct exfat* ef, struct exfat_node* dir,
669 cluster_t* cluster, off_t* offset, int subentries)
673 const struct exfat_entry* entry;
676 rc = opendir(ef, dir, &it);
683 *cluster = it.cluster;
686 entry = get_entry_ptr(ef, &it);
687 if (entry->type & EXFAT_ENTRY_VALID)
691 if (contiguous == subentries)
692 break; /* suitable slot is found */
693 if (it.offset + sizeof(struct exfat_entry) >= dir->size)
695 rc = grow_directory(ef, dir, dir->size,
696 (subentries - contiguous) * sizeof(struct exfat_entry));
703 if (fetch_next_entry(ef, dir, &it) != 0)
713 static int write_entry(struct exfat* ef, struct exfat_node* dir,
714 const le16_t* name, cluster_t cluster, off_t offset, uint16_t attrib)
716 struct exfat_node* node;
717 struct exfat_entry_meta1 meta1;
718 struct exfat_entry_meta2 meta2;
719 const size_t name_length = utf16_length(name);
720 const int name_entries = DIV_ROUND_UP(name_length, EXFAT_ENAME_MAX);
723 node = allocate_node();
726 node->entry_cluster = cluster;
727 node->entry_offset = offset;
728 memcpy(node->name, name, name_length * sizeof(le16_t));
730 memset(&meta1, 0, sizeof(meta1));
731 meta1.type = EXFAT_ENTRY_FILE;
732 meta1.continuations = 1 + name_entries;
733 meta1.attrib = cpu_to_le16(attrib);
734 exfat_unix2exfat(time(NULL), &meta1.crdate, &meta1.crtime,
736 meta1.adate = meta1.mdate = meta1.crdate;
737 meta1.atime = meta1.mtime = meta1.crtime;
738 meta1.mtime_cs = meta1.crtime_cs; /* there is no atime_cs */
740 memset(&meta2, 0, sizeof(meta2));
741 meta2.type = EXFAT_ENTRY_FILE_INFO;
742 meta2.flags = EXFAT_FLAG_ALWAYS1;
743 meta2.name_length = name_length;
744 meta2.name_hash = exfat_calc_name_hash(ef, node->name);
745 meta2.start_cluster = cpu_to_le32(EXFAT_CLUSTER_FREE);
747 meta1.checksum = exfat_calc_checksum(&meta1, &meta2, node->name);
749 exfat_pwrite(ef->dev, &meta1, sizeof(meta1), co2o(ef, cluster, offset));
750 next_entry(ef, dir, &cluster, &offset);
751 exfat_pwrite(ef->dev, &meta2, sizeof(meta2), co2o(ef, cluster, offset));
752 for (i = 0; i < name_entries; i++)
754 struct exfat_entry_name name_entry = {EXFAT_ENTRY_FILE_NAME, 0};
755 memcpy(name_entry.name, node->name + i * EXFAT_ENAME_MAX,
756 EXFAT_ENAME_MAX * sizeof(le16_t));
757 next_entry(ef, dir, &cluster, &offset);
758 exfat_pwrite(ef->dev, &name_entry, sizeof(name_entry),
759 co2o(ef, cluster, offset));
762 init_node_meta1(node, &meta1);
763 init_node_meta2(node, &meta2);
765 tree_attach(dir, node);
766 exfat_update_mtime(dir);
770 static int create(struct exfat* ef, const char* path, uint16_t attrib)
772 struct exfat_node* dir;
773 struct exfat_node* existing;
774 cluster_t cluster = EXFAT_CLUSTER_BAD;
776 le16_t name[EXFAT_NAME_MAX + 1];
779 rc = exfat_split(ef, &dir, &existing, name, path);
782 if (existing != NULL)
784 exfat_put_node(ef, existing);
785 exfat_put_node(ef, dir);
789 rc = find_slot(ef, dir, &cluster, &offset,
790 2 + DIV_ROUND_UP(utf16_length(name), EXFAT_ENAME_MAX));
793 exfat_put_node(ef, dir);
796 rc = write_entry(ef, dir, name, cluster, offset, attrib);
797 exfat_put_node(ef, dir);
801 int exfat_mknod(struct exfat* ef, const char* path)
803 return create(ef, path, EXFAT_ATTRIB_ARCH);
806 int exfat_mkdir(struct exfat* ef, const char* path)
809 struct exfat_node* node;
811 rc = create(ef, path, EXFAT_ATTRIB_ARCH | EXFAT_ATTRIB_DIR);
814 rc = exfat_lookup(ef, &node, path);
817 /* directories always have at least one cluster */
818 rc = exfat_truncate(ef, node, CLUSTER_SIZE(*ef->sb));
822 exfat_put_node(ef, node);
825 exfat_put_node(ef, node);
829 static void rename_entry(struct exfat* ef, struct exfat_node* dir,
830 struct exfat_node* node, const le16_t* name, cluster_t new_cluster,
833 struct exfat_entry_meta1 meta1;
834 struct exfat_entry_meta2 meta2;
835 cluster_t old_cluster = node->entry_cluster;
836 off_t old_offset = node->entry_offset;
837 const size_t name_length = utf16_length(name);
838 const int name_entries = DIV_ROUND_UP(name_length, EXFAT_ENAME_MAX);
841 exfat_pread(ef->dev, &meta1, sizeof(meta1),
842 co2o(ef, old_cluster, old_offset));
843 next_entry(ef, node->parent, &old_cluster, &old_offset);
844 exfat_pread(ef->dev, &meta2, sizeof(meta2),
845 co2o(ef, old_cluster, old_offset));
846 meta1.continuations = 1 + name_entries;
847 meta2.name_hash = exfat_calc_name_hash(ef, name);
848 meta2.name_length = name_length;
849 meta1.checksum = exfat_calc_checksum(&meta1, &meta2, name);
851 erase_entry(ef, node);
853 node->entry_cluster = new_cluster;
854 node->entry_offset = new_offset;
856 exfat_pwrite(ef->dev, &meta1, sizeof(meta1),
857 co2o(ef, new_cluster, new_offset));
858 next_entry(ef, dir, &new_cluster, &new_offset);
859 exfat_pwrite(ef->dev, &meta2, sizeof(meta2),
860 co2o(ef, new_cluster, new_offset));
862 for (i = 0; i < name_entries; i++)
864 struct exfat_entry_name name_entry = {EXFAT_ENTRY_FILE_NAME, 0};
865 memcpy(name_entry.name, name + i * EXFAT_ENAME_MAX,
866 EXFAT_ENAME_MAX * sizeof(le16_t));
867 next_entry(ef, dir, &new_cluster, &new_offset);
868 exfat_pwrite(ef->dev, &name_entry, sizeof(name_entry),
869 co2o(ef, new_cluster, new_offset));
872 memcpy(node->name, name, (EXFAT_NAME_MAX + 1) * sizeof(le16_t));
874 tree_attach(dir, node);
877 int exfat_rename(struct exfat* ef, const char* old_path, const char* new_path)
879 struct exfat_node* node;
880 struct exfat_node* existing;
881 struct exfat_node* dir;
882 cluster_t cluster = EXFAT_CLUSTER_BAD;
884 le16_t name[EXFAT_NAME_MAX + 1];
887 rc = exfat_lookup(ef, &node, old_path);
891 rc = exfat_split(ef, &dir, &existing, name, new_path);
894 exfat_put_node(ef, node);
897 if (existing != NULL)
899 if (existing->flags & EXFAT_ATTRIB_DIR)
901 if (node->flags & EXFAT_ATTRIB_DIR)
902 rc = exfat_rmdir(ef, existing);
908 if (!(node->flags & EXFAT_ATTRIB_DIR))
909 rc = exfat_unlink(ef, existing);
913 exfat_put_node(ef, existing);
916 exfat_put_node(ef, dir);
917 exfat_put_node(ef, node);
922 rc = find_slot(ef, dir, &cluster, &offset,
923 2 + DIV_ROUND_UP(utf16_length(name), EXFAT_ENAME_MAX));
926 exfat_put_node(ef, dir);
927 exfat_put_node(ef, node);
930 rename_entry(ef, dir, node, name, cluster, offset);
931 exfat_put_node(ef, dir);
932 exfat_put_node(ef, node);
936 void exfat_utimes(struct exfat_node* node, const struct timespec tv[2])
938 node->atime = tv[0].tv_sec;
939 node->mtime = tv[1].tv_sec;
940 node->flags |= EXFAT_ATTRIB_DIRTY;
943 void exfat_update_atime(struct exfat_node* node)
945 node->atime = time(NULL);
946 node->flags |= EXFAT_ATTRIB_DIRTY;
949 void exfat_update_mtime(struct exfat_node* node)
951 node->mtime = time(NULL);
952 node->flags |= EXFAT_ATTRIB_DIRTY;
955 const char* exfat_get_label(struct exfat* ef)
960 static int find_label(struct exfat* ef, cluster_t* cluster, off_t* offset)
965 rc = opendir(ef, ef->root, &it);
971 if (it.offset >= ef->root->size)
977 if (get_entry_ptr(ef, &it)->type == EXFAT_ENTRY_LABEL)
979 *cluster = it.cluster;
985 if (fetch_next_entry(ef, ef->root, &it) != 0)
993 int exfat_set_label(struct exfat* ef, const char* label)
995 le16_t label_utf16[EXFAT_ENAME_MAX + 1];
999 struct exfat_entry_label entry;
1001 memset(label_utf16, 0, sizeof(label_utf16));
1002 rc = utf8_to_utf16(label_utf16, label, EXFAT_ENAME_MAX, strlen(label));
1006 rc = find_label(ef, &cluster, &offset);
1008 rc = find_slot(ef, ef->root, &cluster, &offset, 1);
1012 entry.type = EXFAT_ENTRY_LABEL;
1013 entry.length = utf16_length(label_utf16);
1014 memcpy(entry.name, label_utf16, sizeof(entry.name));
1015 if (entry.length == 0)
1016 entry.type ^= EXFAT_ENTRY_VALID;
1018 exfat_pwrite(ef->dev, &entry, sizeof(struct exfat_entry_label),
1019 co2o(ef, cluster, offset));