3 exFAT file system implementation library.
5 Free exFAT implementation.
6 Copyright (C) 2010-2013 Andrew Nayenko
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 2 of the License, or
11 (at your option) any later version.
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.
18 You should have received a copy of the GNU General Public License along
19 with this program; if not, write to the Free Software Foundation, Inc.,
20 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
28 /* on-disk nodes iterator */
37 struct exfat_node* exfat_get_node(struct exfat_node* node)
39 /* if we switch to multi-threaded mode we will need atomic
40 increment here and atomic decrement in exfat_put_node() */
45 void exfat_put_node(struct exfat* ef, struct exfat_node* node)
47 if (--node->references < 0)
49 char buffer[UTF8_BYTES(EXFAT_NAME_MAX) + 1];
50 exfat_get_name(node, buffer, sizeof(buffer) - 1);
51 exfat_bug("reference counter of `%s' is below zero", buffer);
54 if (node->references == 0)
56 exfat_flush_node(ef, node);
57 if (node->flags & EXFAT_ATTRIB_UNLINKED)
59 /* free all clusters and node structure itself */
60 exfat_truncate(ef, node, 0, true);
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 0x%x while reading directory",
122 exfat_pread(ef->dev, it->chunk, CLUSTER_SIZE(*ef->sb),
123 exfat_c2o(ef, it->cluster));
128 static struct exfat_node* allocate_node(void)
130 struct exfat_node* node = malloc(sizeof(struct exfat_node));
133 exfat_error("failed to allocate node");
136 memset(node, 0, sizeof(struct exfat_node));
140 static void init_node_meta1(struct exfat_node* node,
141 const struct exfat_entry_meta1* meta1)
143 node->flags = le16_to_cpu(meta1->attrib);
144 node->mtime = exfat_exfat2unix(meta1->mdate, meta1->mtime,
146 /* there is no centiseconds field for atime */
147 node->atime = exfat_exfat2unix(meta1->adate, meta1->atime, 0);
150 static void init_node_meta2(struct exfat_node* node,
151 const struct exfat_entry_meta2* meta2)
153 node->size = le64_to_cpu(meta2->size);
154 node->start_cluster = le32_to_cpu(meta2->start_cluster);
155 node->fptr_cluster = node->start_cluster;
156 if (meta2->flags & EXFAT_FLAG_CONTIGUOUS)
157 node->flags |= EXFAT_ATTRIB_CONTIGUOUS;
160 static const struct exfat_entry* get_entry_ptr(const struct exfat* ef,
161 const struct iterator* it)
163 return (const struct exfat_entry*)
164 (it->chunk + it->offset % CLUSTER_SIZE(*ef->sb));
168 * Reads one entry in directory at position pointed by iterator and fills
171 static int readdir(struct exfat* ef, const struct exfat_node* parent,
172 struct exfat_node** node, struct iterator* it)
175 const struct exfat_entry* entry;
176 const struct exfat_entry_meta1* meta1;
177 const struct exfat_entry_meta2* meta2;
178 const struct exfat_entry_name* file_name;
179 const struct exfat_entry_upcase* upcase;
180 const struct exfat_entry_bitmap* bitmap;
181 const struct exfat_entry_label* label;
182 uint8_t continuations = 0;
183 le16_t* namep = NULL;
184 uint16_t reference_checksum = 0;
185 uint16_t actual_checksum = 0;
186 uint64_t real_size = 0;
192 if (it->offset >= parent->size)
194 if (continuations != 0)
196 exfat_error("expected %hhu continuations", continuations);
199 return -ENOENT; /* that's OK, means end of directory */
202 entry = get_entry_ptr(ef, it);
205 case EXFAT_ENTRY_FILE:
206 if (continuations != 0)
208 exfat_error("expected %hhu continuations before new entry",
212 meta1 = (const struct exfat_entry_meta1*) entry;
213 continuations = meta1->continuations;
214 /* each file entry must have at least 2 continuations:
216 if (continuations < 2)
218 exfat_error("too few continuations (%hhu)", continuations);
221 if (continuations > 1 +
222 DIV_ROUND_UP(EXFAT_NAME_MAX, EXFAT_ENAME_MAX))
224 exfat_error("too many continuations (%hhu)", continuations);
227 reference_checksum = le16_to_cpu(meta1->checksum);
228 actual_checksum = exfat_start_checksum(meta1);
229 *node = allocate_node();
235 /* new node has zero reference counter */
236 (*node)->entry_cluster = it->cluster;
237 (*node)->entry_offset = it->offset;
238 init_node_meta1(*node, meta1);
239 namep = (*node)->name;
242 case EXFAT_ENTRY_FILE_INFO:
243 if (continuations < 2)
245 exfat_error("unexpected continuation (%hhu)",
249 meta2 = (const struct exfat_entry_meta2*) entry;
250 if (meta2->flags & ~(EXFAT_FLAG_ALWAYS1 | EXFAT_FLAG_CONTIGUOUS))
252 exfat_error("unknown flags in meta2 (0x%hhx)", meta2->flags);
255 init_node_meta2(*node, meta2);
256 actual_checksum = exfat_add_checksum(entry, actual_checksum);
257 real_size = le64_to_cpu(meta2->real_size);
258 /* empty files must be marked as non-contiguous */
259 if ((*node)->size == 0 && (meta2->flags & EXFAT_FLAG_CONTIGUOUS))
261 exfat_error("empty file marked as contiguous (0x%hhx)",
265 /* directories must be aligned on at cluster boundary */
266 if (((*node)->flags & EXFAT_ATTRIB_DIR) &&
267 (*node)->size % CLUSTER_SIZE(*ef->sb) != 0)
269 exfat_error("directory has invalid size %"PRIu64" bytes",
276 case EXFAT_ENTRY_FILE_NAME:
277 if (continuations == 0)
279 exfat_error("unexpected continuation");
282 file_name = (const struct exfat_entry_name*) entry;
283 actual_checksum = exfat_add_checksum(entry, actual_checksum);
285 memcpy(namep, file_name->name,
287 ((*node)->name + EXFAT_NAME_MAX - namep)) *
289 namep += EXFAT_ENAME_MAX;
290 if (--continuations == 0)
293 There are two fields that contain file size. Maybe they
294 plan to add compression support in the future and one of
295 those fields is visible (uncompressed) size and the other
296 is real (compressed) size. Anyway, currently it looks like
297 exFAT does not support compression and both fields must be
300 There is an exception though: pagefile.sys (its real_size
303 if (real_size != (*node)->size)
305 char buffer[UTF8_BYTES(EXFAT_NAME_MAX) + 1];
307 exfat_get_name(*node, buffer, sizeof(buffer) - 1);
308 exfat_error("`%s' real size does not equal to size "
309 "(%"PRIu64" != %"PRIu64")", buffer,
310 real_size, (*node)->size);
313 if (actual_checksum != reference_checksum)
315 char buffer[UTF8_BYTES(EXFAT_NAME_MAX) + 1];
317 exfat_get_name(*node, buffer, sizeof(buffer) - 1);
318 exfat_error("`%s' has invalid checksum (0x%hx != 0x%hx)",
319 buffer, actual_checksum, reference_checksum);
322 if (fetch_next_entry(ef, parent, it) != 0)
324 return 0; /* entry completed */
328 case EXFAT_ENTRY_UPCASE:
329 if (ef->upcase != NULL)
331 upcase = (const struct exfat_entry_upcase*) entry;
332 if (CLUSTER_INVALID(le32_to_cpu(upcase->start_cluster)))
334 exfat_error("invalid cluster 0x%x in upcase table",
335 le32_to_cpu(upcase->start_cluster));
338 if (le64_to_cpu(upcase->size) == 0 ||
339 le64_to_cpu(upcase->size) > 0xffff * sizeof(uint16_t) ||
340 le64_to_cpu(upcase->size) % sizeof(uint16_t) != 0)
342 exfat_error("bad upcase table size (%"PRIu64" bytes)",
343 le64_to_cpu(upcase->size));
346 ef->upcase = malloc(le64_to_cpu(upcase->size));
347 if (ef->upcase == NULL)
349 exfat_error("failed to allocate upcase table (%"PRIu64" bytes)",
350 le64_to_cpu(upcase->size));
354 ef->upcase_chars = le64_to_cpu(upcase->size) / sizeof(le16_t);
356 exfat_pread(ef->dev, ef->upcase, le64_to_cpu(upcase->size),
357 exfat_c2o(ef, le32_to_cpu(upcase->start_cluster)));
360 case EXFAT_ENTRY_BITMAP:
361 bitmap = (const struct exfat_entry_bitmap*) entry;
362 ef->cmap.start_cluster = le32_to_cpu(bitmap->start_cluster);
363 if (CLUSTER_INVALID(ef->cmap.start_cluster))
365 exfat_error("invalid cluster 0x%x in clusters bitmap",
366 ef->cmap.start_cluster);
369 ef->cmap.size = le32_to_cpu(ef->sb->cluster_count) -
370 EXFAT_FIRST_DATA_CLUSTER;
371 if (le64_to_cpu(bitmap->size) < DIV_ROUND_UP(ef->cmap.size, 8))
373 exfat_error("invalid clusters bitmap size: %"PRIu64
374 " (expected at least %u)",
375 le64_to_cpu(bitmap->size),
376 DIV_ROUND_UP(ef->cmap.size, 8));
379 /* FIXME bitmap can be rather big, up to 512 MB */
380 ef->cmap.chunk_size = ef->cmap.size;
381 ef->cmap.chunk = malloc(BMAP_SIZE(ef->cmap.chunk_size));
382 if (ef->cmap.chunk == NULL)
384 exfat_error("failed to allocate clusters bitmap chunk "
385 "(%"PRIu64" bytes)", le64_to_cpu(bitmap->size));
390 exfat_pread(ef->dev, ef->cmap.chunk,
391 BMAP_SIZE(ef->cmap.chunk_size),
392 exfat_c2o(ef, ef->cmap.start_cluster));
395 case EXFAT_ENTRY_LABEL:
396 label = (const struct exfat_entry_label*) entry;
397 if (label->length > EXFAT_ENAME_MAX)
399 exfat_error("too long label (%hhu chars)", label->length);
402 if (utf16_to_utf8(ef->label, label->name,
403 sizeof(ef->label) - 1, EXFAT_ENAME_MAX) != 0)
408 if (entry->type & EXFAT_ENTRY_VALID)
410 exfat_error("unknown entry type 0x%hhx", entry->type);
416 if (fetch_next_entry(ef, parent, it) != 0)
419 /* we never reach here */
427 int exfat_cache_directory(struct exfat* ef, struct exfat_node* dir)
431 struct exfat_node* node;
432 struct exfat_node* current = NULL;
434 if (dir->flags & EXFAT_ATTRIB_CACHED)
435 return 0; /* already cached */
437 rc = opendir(ef, dir, &it);
440 while ((rc = readdir(ef, dir, &node, &it)) == 0)
445 current->next = node;
446 node->prev = current;
458 for (current = dir->child; current; current = node)
460 node = current->next;
467 dir->flags |= EXFAT_ATTRIB_CACHED;
471 static void tree_attach(struct exfat_node* dir, struct exfat_node* node)
476 dir->child->prev = node;
477 node->next = dir->child;
482 static void tree_detach(struct exfat_node* node)
485 node->prev->next = node->next;
486 else /* this is the first node in the list */
487 node->parent->child = node->next;
489 node->next->prev = node->prev;
495 static void reset_cache(struct exfat* ef, struct exfat_node* node)
499 struct exfat_node* p = node->child;
504 node->flags &= ~EXFAT_ATTRIB_CACHED;
505 if (node->references != 0)
507 char buffer[UTF8_BYTES(EXFAT_NAME_MAX) + 1];
508 exfat_get_name(node, buffer, sizeof(buffer) - 1);
509 exfat_warn("non-zero reference counter (%d) for `%s'",
510 node->references, buffer);
512 while (node->references)
513 exfat_put_node(ef, node);
516 void exfat_reset_cache(struct exfat* ef)
518 reset_cache(ef, ef->root);
521 static void next_entry(struct exfat* ef, const struct exfat_node* parent,
522 cluster_t* cluster, off_t* offset)
524 *offset += sizeof(struct exfat_entry);
525 if (*offset % CLUSTER_SIZE(*ef->sb) == 0)
526 /* next cluster cannot be invalid */
527 *cluster = exfat_next_cluster(ef, parent, *cluster);
530 void exfat_flush_node(struct exfat* ef, struct exfat_node* node)
534 off_t meta1_offset, meta2_offset;
535 struct exfat_entry_meta1 meta1;
536 struct exfat_entry_meta2 meta2;
538 if (!(node->flags & EXFAT_ATTRIB_DIRTY))
539 return; /* no need to flush */
542 exfat_bug("unable to flush node to read-only FS");
544 if (node->parent == NULL)
545 return; /* do not flush unlinked node */
547 cluster = node->entry_cluster;
548 offset = node->entry_offset;
549 meta1_offset = co2o(ef, cluster, offset);
550 next_entry(ef, node->parent, &cluster, &offset);
551 meta2_offset = co2o(ef, cluster, offset);
553 exfat_pread(ef->dev, &meta1, sizeof(meta1), meta1_offset);
554 if (meta1.type != EXFAT_ENTRY_FILE)
555 exfat_bug("invalid type of meta1: 0x%hhx", meta1.type);
556 meta1.attrib = cpu_to_le16(node->flags);
557 exfat_unix2exfat(node->mtime, &meta1.mdate, &meta1.mtime, &meta1.mtime_cs);
558 exfat_unix2exfat(node->atime, &meta1.adate, &meta1.atime, NULL);
560 exfat_pread(ef->dev, &meta2, sizeof(meta2), meta2_offset);
561 if (meta2.type != EXFAT_ENTRY_FILE_INFO)
562 exfat_bug("invalid type of meta2: 0x%hhx", meta2.type);
563 meta2.size = meta2.real_size = cpu_to_le64(node->size);
564 meta2.start_cluster = cpu_to_le32(node->start_cluster);
565 meta2.flags = EXFAT_FLAG_ALWAYS1;
566 /* empty files must not be marked as contiguous */
567 if (node->size != 0 && IS_CONTIGUOUS(*node))
568 meta2.flags |= EXFAT_FLAG_CONTIGUOUS;
569 /* name hash remains unchanged, no need to recalculate it */
571 meta1.checksum = exfat_calc_checksum(&meta1, &meta2, node->name);
573 exfat_pwrite(ef->dev, &meta1, sizeof(meta1), meta1_offset);
574 exfat_pwrite(ef->dev, &meta2, sizeof(meta2), meta2_offset);
576 node->flags &= ~EXFAT_ATTRIB_DIRTY;
579 static void erase_entry(struct exfat* ef, struct exfat_node* node)
581 cluster_t cluster = node->entry_cluster;
582 off_t offset = node->entry_offset;
583 int name_entries = DIV_ROUND_UP(utf16_length(node->name), EXFAT_ENAME_MAX);
586 entry_type = EXFAT_ENTRY_FILE & ~EXFAT_ENTRY_VALID;
587 exfat_pwrite(ef->dev, &entry_type, 1, co2o(ef, cluster, offset));
589 next_entry(ef, node->parent, &cluster, &offset);
590 entry_type = EXFAT_ENTRY_FILE_INFO & ~EXFAT_ENTRY_VALID;
591 exfat_pwrite(ef->dev, &entry_type, 1, co2o(ef, cluster, offset));
593 while (name_entries--)
595 next_entry(ef, node->parent, &cluster, &offset);
596 entry_type = EXFAT_ENTRY_FILE_NAME & ~EXFAT_ENTRY_VALID;
597 exfat_pwrite(ef->dev, &entry_type, 1, co2o(ef, cluster, offset));
601 static int shrink_directory(struct exfat* ef, struct exfat_node* dir,
602 off_t deleted_offset)
604 const struct exfat_node* node;
605 const struct exfat_node* last_node;
606 uint64_t entries = 0;
610 if (!(dir->flags & EXFAT_ATTRIB_DIR))
611 exfat_bug("attempted to shrink a file");
612 if (!(dir->flags & EXFAT_ATTRIB_CACHED))
613 exfat_bug("attempted to shrink uncached directory");
615 for (last_node = node = dir->child; node; node = node->next)
617 if (deleted_offset < node->entry_offset)
619 /* there are other entries after the removed one, no way to shrink
623 if (last_node->entry_offset < node->entry_offset)
629 /* offset of the last entry */
630 entries += last_node->entry_offset / sizeof(struct exfat_entry);
631 /* two subentries with meta info */
633 /* subentries with file name */
634 entries += DIV_ROUND_UP(utf16_length(last_node->name),
638 new_size = DIV_ROUND_UP(entries * sizeof(struct exfat_entry),
639 CLUSTER_SIZE(*ef->sb)) * CLUSTER_SIZE(*ef->sb);
640 if (new_size == 0) /* directory always has at least 1 cluster */
641 new_size = CLUSTER_SIZE(*ef->sb);
642 if (new_size == dir->size)
644 rc = exfat_truncate(ef, dir, new_size, true);
650 static int delete(struct exfat* ef, struct exfat_node* node)
652 struct exfat_node* parent = node->parent;
653 off_t deleted_offset = node->entry_offset;
656 exfat_get_node(parent);
657 erase_entry(ef, node);
658 exfat_update_mtime(parent);
660 rc = shrink_directory(ef, parent, deleted_offset);
661 exfat_put_node(ef, parent);
662 /* file clusters will be freed when node reference counter becomes 0 */
663 node->flags |= EXFAT_ATTRIB_UNLINKED;
667 int exfat_unlink(struct exfat* ef, struct exfat_node* node)
669 if (node->flags & EXFAT_ATTRIB_DIR)
671 return delete(ef, node);
674 int exfat_rmdir(struct exfat* ef, struct exfat_node* node)
676 if (!(node->flags & EXFAT_ATTRIB_DIR))
678 /* check that directory is empty */
679 exfat_cache_directory(ef, node);
682 return delete(ef, node);
685 static int grow_directory(struct exfat* ef, struct exfat_node* dir,
686 uint64_t asize, uint32_t difference)
688 return exfat_truncate(ef, dir,
689 DIV_ROUND_UP(asize + difference, CLUSTER_SIZE(*ef->sb))
690 * CLUSTER_SIZE(*ef->sb), true);
693 static int find_slot(struct exfat* ef, struct exfat_node* dir,
694 cluster_t* cluster, off_t* offset, int subentries)
698 const struct exfat_entry* entry;
701 rc = opendir(ef, dir, &it);
708 *cluster = it.cluster;
711 entry = get_entry_ptr(ef, &it);
712 if (entry->type & EXFAT_ENTRY_VALID)
716 if (contiguous == subentries)
717 break; /* suitable slot is found */
718 if (it.offset + sizeof(struct exfat_entry) >= dir->size)
720 rc = grow_directory(ef, dir, dir->size,
721 (subentries - contiguous) * sizeof(struct exfat_entry));
728 if (fetch_next_entry(ef, dir, &it) != 0)
738 static int write_entry(struct exfat* ef, struct exfat_node* dir,
739 const le16_t* name, cluster_t cluster, off_t offset, uint16_t attrib)
741 struct exfat_node* node;
742 struct exfat_entry_meta1 meta1;
743 struct exfat_entry_meta2 meta2;
744 const size_t name_length = utf16_length(name);
745 const int name_entries = DIV_ROUND_UP(name_length, EXFAT_ENAME_MAX);
748 node = allocate_node();
751 node->entry_cluster = cluster;
752 node->entry_offset = offset;
753 memcpy(node->name, name, name_length * sizeof(le16_t));
755 memset(&meta1, 0, sizeof(meta1));
756 meta1.type = EXFAT_ENTRY_FILE;
757 meta1.continuations = 1 + name_entries;
758 meta1.attrib = cpu_to_le16(attrib);
759 exfat_unix2exfat(time(NULL), &meta1.crdate, &meta1.crtime,
761 meta1.adate = meta1.mdate = meta1.crdate;
762 meta1.atime = meta1.mtime = meta1.crtime;
763 meta1.mtime_cs = meta1.crtime_cs; /* there is no atime_cs */
765 memset(&meta2, 0, sizeof(meta2));
766 meta2.type = EXFAT_ENTRY_FILE_INFO;
767 meta2.flags = EXFAT_FLAG_ALWAYS1;
768 meta2.name_length = name_length;
769 meta2.name_hash = exfat_calc_name_hash(ef, node->name);
770 meta2.start_cluster = cpu_to_le32(EXFAT_CLUSTER_FREE);
772 meta1.checksum = exfat_calc_checksum(&meta1, &meta2, node->name);
774 exfat_pwrite(ef->dev, &meta1, sizeof(meta1), co2o(ef, cluster, offset));
775 next_entry(ef, dir, &cluster, &offset);
776 exfat_pwrite(ef->dev, &meta2, sizeof(meta2), co2o(ef, cluster, offset));
777 for (i = 0; i < name_entries; i++)
779 struct exfat_entry_name name_entry = {EXFAT_ENTRY_FILE_NAME, 0};
780 memcpy(name_entry.name, node->name + i * EXFAT_ENAME_MAX,
781 MIN(EXFAT_ENAME_MAX, EXFAT_NAME_MAX - i * EXFAT_ENAME_MAX) *
783 next_entry(ef, dir, &cluster, &offset);
784 exfat_pwrite(ef->dev, &name_entry, sizeof(name_entry),
785 co2o(ef, cluster, offset));
788 init_node_meta1(node, &meta1);
789 init_node_meta2(node, &meta2);
791 tree_attach(dir, node);
792 exfat_update_mtime(dir);
796 static int create(struct exfat* ef, const char* path, uint16_t attrib)
798 struct exfat_node* dir;
799 struct exfat_node* existing;
800 cluster_t cluster = EXFAT_CLUSTER_BAD;
802 le16_t name[EXFAT_NAME_MAX + 1];
805 rc = exfat_split(ef, &dir, &existing, name, path);
808 if (existing != NULL)
810 exfat_put_node(ef, existing);
811 exfat_put_node(ef, dir);
815 rc = find_slot(ef, dir, &cluster, &offset,
816 2 + DIV_ROUND_UP(utf16_length(name), EXFAT_ENAME_MAX));
819 exfat_put_node(ef, dir);
822 rc = write_entry(ef, dir, name, cluster, offset, attrib);
823 exfat_put_node(ef, dir);
827 int exfat_mknod(struct exfat* ef, const char* path)
829 return create(ef, path, EXFAT_ATTRIB_ARCH);
832 int exfat_mkdir(struct exfat* ef, const char* path)
835 struct exfat_node* node;
837 rc = create(ef, path, EXFAT_ATTRIB_ARCH | EXFAT_ATTRIB_DIR);
840 rc = exfat_lookup(ef, &node, path);
843 /* directories always have at least one cluster */
844 rc = exfat_truncate(ef, node, CLUSTER_SIZE(*ef->sb), true);
848 exfat_put_node(ef, node);
851 exfat_put_node(ef, node);
855 static void rename_entry(struct exfat* ef, struct exfat_node* dir,
856 struct exfat_node* node, const le16_t* name, cluster_t new_cluster,
859 struct exfat_entry_meta1 meta1;
860 struct exfat_entry_meta2 meta2;
861 cluster_t old_cluster = node->entry_cluster;
862 off_t old_offset = node->entry_offset;
863 const size_t name_length = utf16_length(name);
864 const int name_entries = DIV_ROUND_UP(name_length, EXFAT_ENAME_MAX);
867 exfat_pread(ef->dev, &meta1, sizeof(meta1),
868 co2o(ef, old_cluster, old_offset));
869 next_entry(ef, node->parent, &old_cluster, &old_offset);
870 exfat_pread(ef->dev, &meta2, sizeof(meta2),
871 co2o(ef, old_cluster, old_offset));
872 meta1.continuations = 1 + name_entries;
873 meta2.name_hash = exfat_calc_name_hash(ef, name);
874 meta2.name_length = name_length;
875 meta1.checksum = exfat_calc_checksum(&meta1, &meta2, name);
877 erase_entry(ef, node);
879 node->entry_cluster = new_cluster;
880 node->entry_offset = new_offset;
882 exfat_pwrite(ef->dev, &meta1, sizeof(meta1),
883 co2o(ef, new_cluster, new_offset));
884 next_entry(ef, dir, &new_cluster, &new_offset);
885 exfat_pwrite(ef->dev, &meta2, sizeof(meta2),
886 co2o(ef, new_cluster, new_offset));
888 for (i = 0; i < name_entries; i++)
890 struct exfat_entry_name name_entry = {EXFAT_ENTRY_FILE_NAME, 0};
891 memcpy(name_entry.name, name + i * EXFAT_ENAME_MAX,
892 EXFAT_ENAME_MAX * sizeof(le16_t));
893 next_entry(ef, dir, &new_cluster, &new_offset);
894 exfat_pwrite(ef->dev, &name_entry, sizeof(name_entry),
895 co2o(ef, new_cluster, new_offset));
898 memcpy(node->name, name, (EXFAT_NAME_MAX + 1) * sizeof(le16_t));
900 tree_attach(dir, node);
903 int exfat_rename(struct exfat* ef, const char* old_path, const char* new_path)
905 struct exfat_node* node;
906 struct exfat_node* existing;
907 struct exfat_node* dir;
908 cluster_t cluster = EXFAT_CLUSTER_BAD;
910 le16_t name[EXFAT_NAME_MAX + 1];
913 rc = exfat_lookup(ef, &node, old_path);
917 rc = exfat_split(ef, &dir, &existing, name, new_path);
920 exfat_put_node(ef, node);
924 /* check that target is not a subdirectory of the source */
925 if (node->flags & EXFAT_ATTRIB_DIR)
927 struct exfat_node* p;
929 for (p = dir; p; p = p->parent)
932 if (existing != NULL)
933 exfat_put_node(ef, existing);
934 exfat_put_node(ef, dir);
935 exfat_put_node(ef, node);
940 if (existing != NULL)
942 /* remove target if it's not the same node as source */
943 if (existing != node)
945 if (existing->flags & EXFAT_ATTRIB_DIR)
947 if (node->flags & EXFAT_ATTRIB_DIR)
948 rc = exfat_rmdir(ef, existing);
954 if (!(node->flags & EXFAT_ATTRIB_DIR))
955 rc = exfat_unlink(ef, existing);
959 exfat_put_node(ef, existing);
962 exfat_put_node(ef, dir);
963 exfat_put_node(ef, node);
968 exfat_put_node(ef, existing);
971 rc = find_slot(ef, dir, &cluster, &offset,
972 2 + DIV_ROUND_UP(utf16_length(name), EXFAT_ENAME_MAX));
975 exfat_put_node(ef, dir);
976 exfat_put_node(ef, node);
979 rename_entry(ef, dir, node, name, cluster, offset);
980 exfat_put_node(ef, dir);
981 exfat_put_node(ef, node);
985 void exfat_utimes(struct exfat_node* node, const struct timespec tv[2])
987 node->atime = tv[0].tv_sec;
988 node->mtime = tv[1].tv_sec;
989 node->flags |= EXFAT_ATTRIB_DIRTY;
992 void exfat_update_atime(struct exfat_node* node)
994 node->atime = time(NULL);
995 node->flags |= EXFAT_ATTRIB_DIRTY;
998 void exfat_update_mtime(struct exfat_node* node)
1000 node->mtime = time(NULL);
1001 node->flags |= EXFAT_ATTRIB_DIRTY;
1004 const char* exfat_get_label(struct exfat* ef)
1009 static int find_label(struct exfat* ef, cluster_t* cluster, off_t* offset)
1014 rc = opendir(ef, ef->root, &it);
1020 if (it.offset >= ef->root->size)
1026 if (get_entry_ptr(ef, &it)->type == EXFAT_ENTRY_LABEL)
1028 *cluster = it.cluster;
1029 *offset = it.offset;
1034 if (fetch_next_entry(ef, ef->root, &it) != 0)
1042 int exfat_set_label(struct exfat* ef, const char* label)
1044 le16_t label_utf16[EXFAT_ENAME_MAX + 1];
1048 struct exfat_entry_label entry;
1050 memset(label_utf16, 0, sizeof(label_utf16));
1051 rc = utf8_to_utf16(label_utf16, label, EXFAT_ENAME_MAX, strlen(label));
1055 rc = find_label(ef, &cluster, &offset);
1057 rc = find_slot(ef, ef->root, &cluster, &offset, 1);
1061 entry.type = EXFAT_ENTRY_LABEL;
1062 entry.length = utf16_length(label_utf16);
1063 memcpy(entry.name, label_utf16, sizeof(entry.name));
1064 if (entry.length == 0)
1065 entry.type ^= EXFAT_ENTRY_VALID;
1067 exfat_pwrite(ef->dev, &entry, sizeof(struct exfat_entry_label),
1068 co2o(ef, cluster, offset));
1069 strcpy(ef->label, label);