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,
141 /* there is no centiseconds field for atime */
142 node->atime = exfat_exfat2unix(meta1->adate, meta1->atime, 0);
145 static void init_node_meta2(struct exfat_node* node,
146 const struct exfat_entry_meta2* meta2)
148 node->size = le64_to_cpu(meta2->size);
149 node->start_cluster = le32_to_cpu(meta2->start_cluster);
150 node->fptr_cluster = node->start_cluster;
151 if (meta2->flag == EXFAT_FLAG_CONTIGUOUS)
152 node->flags |= EXFAT_ATTRIB_CONTIGUOUS;
156 * Reads one entry in directory at position pointed by iterator and fills
159 static int readdir(struct exfat* ef, const struct exfat_node* parent,
160 struct exfat_node** node, struct iterator* it)
162 const struct exfat_entry* entry;
163 const struct exfat_entry_meta1* meta1;
164 const struct exfat_entry_meta2* meta2;
165 const struct exfat_entry_name* file_name;
166 const struct exfat_entry_upcase* upcase;
167 const struct exfat_entry_bitmap* bitmap;
168 const struct exfat_entry_label* label;
169 uint8_t continuations = 0;
170 le16_t* namep = NULL;
171 uint16_t reference_checksum = 0;
172 uint16_t actual_checksum = 0;
178 /* every directory (even empty one) occupies at least one cluster and
179 must contain EOD entry */
180 entry = (const struct exfat_entry*)
181 (it->chunk + it->offset % CLUSTER_SIZE(*ef->sb));
185 case EXFAT_ENTRY_EOD:
186 if (continuations != 0)
188 exfat_error("expected %hhu continuations before EOD",
192 return -ENOENT; /* that's OK, means end of directory */
194 case EXFAT_ENTRY_FILE:
195 if (continuations != 0)
197 exfat_error("expected %hhu continuations before new entry",
201 meta1 = (const struct exfat_entry_meta1*) entry;
202 continuations = meta1->continuations;
203 /* each file entry must have at least 2 continuations:
205 if (continuations < 2)
207 exfat_error("too few continuations (%hhu)", continuations);
210 reference_checksum = le16_to_cpu(meta1->checksum);
211 actual_checksum = exfat_start_checksum(meta1);
212 *node = allocate_node();
215 /* new node has zero reference counter */
216 (*node)->entry_cluster = it->cluster;
217 (*node)->entry_offset = it->offset;
218 init_node_meta1(*node, meta1);
219 namep = (*node)->name;
222 case EXFAT_ENTRY_FILE_INFO:
223 if (continuations < 2)
225 exfat_error("unexpected continuation (%hhu)",
229 meta2 = (const struct exfat_entry_meta2*) entry;
230 init_node_meta2(*node, meta2);
231 actual_checksum = exfat_add_checksum(entry, actual_checksum);
232 /* There are two fields that contain file size. Maybe they plan
233 to add compression support in the future and one of those
234 fields is visible (uncompressed) size and the other is real
235 (compressed) size. Anyway, currently it looks like exFAT does
236 not support compression and both fields must be equal. */
237 if (le64_to_cpu(meta2->real_size) != (*node)->size)
239 exfat_error("real size does not equal to size "
240 "(%"PRIu64" != %"PRIu64")",
241 le64_to_cpu(meta2->real_size), (*node)->size);
244 /* directories must be aligned on at cluster boundary */
245 if (((*node)->flags & EXFAT_ATTRIB_DIR) &&
246 (*node)->size % CLUSTER_SIZE(*ef->sb) != 0)
248 char buffer[EXFAT_NAME_MAX + 1];
250 exfat_get_name(*node, buffer, EXFAT_NAME_MAX);
251 exfat_error("directory `%s' has invalid size %"PRIu64" bytes",
252 buffer, (*node)->size);
258 case EXFAT_ENTRY_FILE_NAME:
259 if (continuations == 0)
261 exfat_error("unexpected continuation");
264 file_name = (const struct exfat_entry_name*) entry;
265 actual_checksum = exfat_add_checksum(entry, actual_checksum);
267 memcpy(namep, file_name->name, EXFAT_ENAME_MAX * sizeof(le16_t));
268 namep += EXFAT_ENAME_MAX;
269 if (--continuations == 0)
271 if (actual_checksum != reference_checksum)
273 exfat_error("invalid checksum (0x%hx != 0x%hx)",
274 actual_checksum, reference_checksum);
277 if (fetch_next_entry(ef, parent, it) != 0)
279 return 0; /* entry completed */
283 case EXFAT_ENTRY_UPCASE:
284 if (ef->upcase != NULL)
286 upcase = (const struct exfat_entry_upcase*) entry;
287 if (CLUSTER_INVALID(le32_to_cpu(upcase->start_cluster)))
289 exfat_error("invalid cluster in upcase table");
292 if (le64_to_cpu(upcase->size) == 0 ||
293 le64_to_cpu(upcase->size) > 0xffff * sizeof(uint16_t) ||
294 le64_to_cpu(upcase->size) % sizeof(uint16_t) != 0)
296 exfat_error("bad upcase table size (%"PRIu64" bytes)",
297 le64_to_cpu(upcase->size));
300 ef->upcase = malloc(le64_to_cpu(upcase->size));
301 if (ef->upcase == NULL)
303 exfat_error("failed to allocate upcase table (%"PRIu64" bytes)",
304 le64_to_cpu(upcase->size));
307 ef->upcase_chars = le64_to_cpu(upcase->size) / sizeof(le16_t);
309 exfat_read_raw(ef->upcase, le64_to_cpu(upcase->size),
310 exfat_c2o(ef, le32_to_cpu(upcase->start_cluster)), ef->fd);
313 case EXFAT_ENTRY_BITMAP:
314 bitmap = (const struct exfat_entry_bitmap*) entry;
315 if (CLUSTER_INVALID(le32_to_cpu(bitmap->start_cluster)))
317 exfat_error("invalid cluster in clusters bitmap");
320 ef->cmap.size = le32_to_cpu(ef->sb->cluster_count) -
321 EXFAT_FIRST_DATA_CLUSTER;
322 if (le64_to_cpu(bitmap->size) < (ef->cmap.size + 7) / 8)
324 exfat_error("invalid clusters bitmap size: %"PRIu64
325 " (expected at least %u)",
326 le64_to_cpu(bitmap->size), (ef->cmap.size + 7) / 8);
329 ef->cmap.start_cluster = le32_to_cpu(bitmap->start_cluster);
330 /* FIXME bitmap can be rather big, up to 512 MB */
331 ef->cmap.chunk_size = ef->cmap.size;
332 ef->cmap.chunk = malloc(le64_to_cpu(bitmap->size));
333 if (ef->cmap.chunk == NULL)
335 exfat_error("failed to allocate clusters bitmap chunk "
336 "(%"PRIu64" bytes)", le64_to_cpu(bitmap->size));
340 exfat_read_raw(ef->cmap.chunk, le64_to_cpu(bitmap->size),
341 exfat_c2o(ef, ef->cmap.start_cluster), ef->fd);
344 case EXFAT_ENTRY_LABEL:
345 label = (const struct exfat_entry_label*) entry;
346 if (label->length > EXFAT_ENAME_MAX)
348 exfat_error("too long label (%hhu chars)", label->length);
351 if (utf16_to_utf8(ef->label, label->name,
352 sizeof(ef->label), EXFAT_ENAME_MAX) != 0)
357 if (entry->type & EXFAT_ENTRY_VALID)
359 exfat_error("unknown entry type 0x%hhu", entry->type);
365 if (fetch_next_entry(ef, parent, it) != 0)
368 /* we never reach here */
376 int exfat_cache_directory(struct exfat* ef, struct exfat_node* dir)
380 struct exfat_node* node;
381 struct exfat_node* current = NULL;
383 if (dir->flags & EXFAT_ATTRIB_CACHED)
384 return 0; /* already cached */
386 rc = opendir(ef, dir, &it);
389 while ((rc = readdir(ef, dir, &node, &it)) == 0)
394 current->next = node;
395 node->prev = current;
407 for (current = dir->child; current; current = node)
409 node = current->next;
416 dir->flags |= EXFAT_ATTRIB_CACHED;
420 static void reset_cache(struct exfat* ef, struct exfat_node* node)
422 struct exfat_node* child;
423 struct exfat_node* next;
425 for (child = node->child; child; child = next)
427 reset_cache(ef, child);
431 if (node->references != 0)
433 char buffer[EXFAT_NAME_MAX + 1];
434 exfat_get_name(node, buffer, EXFAT_NAME_MAX);
435 exfat_warn("non-zero reference counter (%d) for `%s'",
436 node->references, buffer);
438 while (node->references--)
439 exfat_put_node(ef, node);
441 node->flags &= ~EXFAT_ATTRIB_CACHED;
444 void exfat_reset_cache(struct exfat* ef)
446 reset_cache(ef, ef->root);
449 void next_entry(struct exfat* ef, const struct exfat_node* parent,
450 cluster_t* cluster, off_t* offset)
452 *offset += sizeof(struct exfat_entry);
453 if (*offset % CLUSTER_SIZE(*ef->sb) == 0)
454 /* next cluster cannot be invalid */
455 *cluster = exfat_next_cluster(ef, parent, *cluster);
458 void exfat_flush_node(struct exfat* ef, struct exfat_node* node)
462 off_t meta1_offset, meta2_offset;
463 struct exfat_entry_meta1 meta1;
464 struct exfat_entry_meta2 meta2;
467 exfat_bug("unable to flush node to read-only FS");
469 if (node->parent == NULL)
470 return; /* do not flush unlinked node */
472 cluster = node->entry_cluster;
473 offset = node->entry_offset;
474 meta1_offset = co2o(ef, cluster, offset);
475 next_entry(ef, node->parent, &cluster, &offset);
476 meta2_offset = co2o(ef, cluster, offset);
478 exfat_read_raw(&meta1, sizeof(meta1), meta1_offset, ef->fd);
479 if (meta1.type != EXFAT_ENTRY_FILE)
480 exfat_bug("invalid type of meta1: 0x%hhx", meta1.type);
481 meta1.attrib = cpu_to_le16(node->flags);
482 exfat_unix2exfat(node->mtime, &meta1.mdate, &meta1.mtime, &meta1.mtime_cs);
483 exfat_unix2exfat(node->atime, &meta1.adate, &meta1.atime, NULL);
485 exfat_read_raw(&meta2, sizeof(meta2), meta2_offset, ef->fd);
486 if (meta2.type != EXFAT_ENTRY_FILE_INFO)
487 exfat_bug("invalid type of meta2: 0x%hhx", meta2.type);
488 meta2.size = meta2.real_size = cpu_to_le64(node->size);
489 meta2.start_cluster = cpu_to_le32(node->start_cluster);
490 /* empty files must be marked as fragmented */
491 if (node->size != 0 && IS_CONTIGUOUS(*node))
492 meta2.flag = EXFAT_FLAG_CONTIGUOUS;
494 meta2.flag = EXFAT_FLAG_FRAGMENTED;
495 /* name hash remains unchanged, no need to recalculate it */
497 meta1.checksum = exfat_calc_checksum(&meta1, &meta2, node->name);
499 exfat_write_raw(&meta1, sizeof(meta1), meta1_offset, ef->fd);
500 exfat_write_raw(&meta2, sizeof(meta2), meta2_offset, ef->fd);
502 node->flags &= ~EXFAT_ATTRIB_DIRTY;
505 static void erase_entry(struct exfat* ef, struct exfat_node* node)
507 cluster_t cluster = node->entry_cluster;
508 off_t offset = node->entry_offset;
509 int name_entries = DIV_ROUND_UP(utf16_length(node->name), EXFAT_ENAME_MAX);
512 entry_type = EXFAT_ENTRY_FILE & ~EXFAT_ENTRY_VALID;
513 exfat_write_raw(&entry_type, 1, co2o(ef, cluster, offset), ef->fd);
515 next_entry(ef, node->parent, &cluster, &offset);
516 entry_type = EXFAT_ENTRY_FILE_INFO & ~EXFAT_ENTRY_VALID;
517 exfat_write_raw(&entry_type, 1, co2o(ef, cluster, offset), ef->fd);
519 while (name_entries--)
521 next_entry(ef, node->parent, &cluster, &offset);
522 entry_type = EXFAT_ENTRY_FILE_NAME & ~EXFAT_ENTRY_VALID;
523 exfat_write_raw(&entry_type, 1, co2o(ef, cluster, offset), ef->fd);
527 static void tree_detach(struct exfat_node* node)
530 node->prev->next = node->next;
531 else /* this is the first node in the list */
532 node->parent->child = node->next;
534 node->next->prev = node->prev;
540 static void tree_attach(struct exfat_node* dir, struct exfat_node* node)
545 dir->child->prev = node;
546 node->next = dir->child;
551 static int shrink_directory(struct exfat* ef, struct exfat_node* dir,
552 off_t deleted_offset)
554 const struct exfat_node* node;
555 const struct exfat_node* last_node;
556 uint64_t entries = 1; /* a directory always has at leat 1 entry (EOD) */
558 struct exfat_entry eod;
562 if (!(dir->flags & EXFAT_ATTRIB_DIR))
563 exfat_bug("attempted to shrink a file");
564 if (!(dir->flags & EXFAT_ATTRIB_CACHED))
565 exfat_bug("attempted to shrink uncached directory");
567 for (last_node = node = dir->child; node; node = node->next)
569 if (deleted_offset < node->entry_offset)
571 /* there are other entries after the removed one, no way to shrink
575 if (last_node->entry_offset < node->entry_offset)
581 /* offset of the last entry */
582 entries += last_node->entry_offset / sizeof(struct exfat_entry);
583 /* two subentries with meta info */
585 /* subentries with file name */
586 entries += DIV_ROUND_UP(utf16_length(last_node->name),
590 new_size = DIV_ROUND_UP(entries * sizeof(struct exfat_entry),
591 CLUSTER_SIZE(*ef->sb)) * CLUSTER_SIZE(*ef->sb);
592 if (new_size == dir->size)
594 rc = exfat_truncate(ef, dir, new_size);
598 /* put EOD entry at the end of the last cluster */
599 memset(&eod, 0, sizeof(eod));
600 eod_offset = new_size - sizeof(struct exfat_entry);
602 exfat_write_raw(&eod, sizeof(eod),
603 co2o(ef, last_node->entry_cluster, eod_offset), ef->fd);
605 exfat_write_raw(&eod, sizeof(eod),
606 co2o(ef, dir->start_cluster, eod_offset), ef->fd);
610 static int delete(struct exfat* ef, struct exfat_node* node)
612 struct exfat_node* parent = node->parent;
613 off_t deleted_offset = node->entry_offset;
616 exfat_get_node(parent);
617 erase_entry(ef, node);
618 exfat_update_mtime(parent);
620 rc = shrink_directory(ef, parent, deleted_offset);
621 exfat_put_node(ef, parent);
622 /* file clusters will be freed when node reference counter becomes 0 */
623 node->flags |= EXFAT_ATTRIB_UNLINKED;
627 int exfat_unlink(struct exfat* ef, struct exfat_node* node)
629 if (node->flags & EXFAT_ATTRIB_DIR)
631 return delete(ef, node);
634 int exfat_rmdir(struct exfat* ef, struct exfat_node* node)
636 if (!(node->flags & EXFAT_ATTRIB_DIR))
638 /* check that directory is empty */
639 exfat_cache_directory(ef, node);
642 return delete(ef, node);
645 static int grow_directory(struct exfat* ef, struct exfat_node* dir,
646 uint64_t asize, uint32_t difference)
648 return exfat_truncate(ef, dir,
649 DIV_ROUND_UP(asize + difference, CLUSTER_SIZE(*ef->sb))
650 * CLUSTER_SIZE(*ef->sb));
653 static int find_slot(struct exfat* ef, struct exfat_node* dir,
654 cluster_t* cluster, off_t* offset, int subentries)
658 const struct exfat_entry* entry;
661 rc = opendir(ef, dir, &it);
668 *cluster = it.cluster;
671 entry = (const struct exfat_entry*)
672 (it.chunk + it.offset % CLUSTER_SIZE(*ef->sb));
673 if (entry->type == EXFAT_ENTRY_EOD)
675 rc = grow_directory(ef, dir,
676 it.offset + sizeof(struct exfat_entry), /* actual size */
677 (subentries - contiguous) * sizeof(struct exfat_entry));
685 if (entry->type & EXFAT_ENTRY_VALID)
689 if (contiguous == subentries)
690 break; /* suitable slot it found */
691 if (fetch_next_entry(ef, dir, &it) != 0)
701 static int write_entry(struct exfat* ef, struct exfat_node* dir,
702 const le16_t* name, cluster_t cluster, off_t offset, uint16_t attrib)
704 struct exfat_node* node;
705 struct exfat_entry_meta1 meta1;
706 struct exfat_entry_meta2 meta2;
707 const size_t name_length = utf16_length(name);
708 const int name_entries = DIV_ROUND_UP(name_length, EXFAT_ENAME_MAX);
711 node = allocate_node();
714 node->entry_cluster = cluster;
715 node->entry_offset = offset;
716 memcpy(node->name, name, name_length * sizeof(le16_t));
718 memset(&meta1, 0, sizeof(meta1));
719 meta1.type = EXFAT_ENTRY_FILE;
720 meta1.continuations = 1 + name_entries;
721 meta1.attrib = cpu_to_le16(attrib);
722 exfat_unix2exfat(time(NULL), &meta1.crdate, &meta1.crtime,
724 meta1.adate = meta1.mdate = meta1.crdate;
725 meta1.atime = meta1.mtime = meta1.crtime;
726 /* crtime_cs and mtime_cs contain addition to the time in centiseconds;
727 just ignore those fields because we operate with 2 sec resolution */
729 memset(&meta2, 0, sizeof(meta2));
730 meta2.type = EXFAT_ENTRY_FILE_INFO;
731 meta2.flag = EXFAT_FLAG_FRAGMENTED;
732 meta2.name_length = name_length;
733 meta2.name_hash = exfat_calc_name_hash(ef, node->name);
734 meta2.start_cluster = cpu_to_le32(EXFAT_CLUSTER_FREE);
736 meta1.checksum = exfat_calc_checksum(&meta1, &meta2, node->name);
738 exfat_write_raw(&meta1, sizeof(meta1), co2o(ef, cluster, offset), ef->fd);
739 next_entry(ef, dir, &cluster, &offset);
740 exfat_write_raw(&meta2, sizeof(meta2), co2o(ef, cluster, offset), ef->fd);
741 for (i = 0; i < name_entries; i++)
743 struct exfat_entry_name name_entry = {EXFAT_ENTRY_FILE_NAME, 0};
744 memcpy(name_entry.name, node->name + i * EXFAT_ENAME_MAX,
745 EXFAT_ENAME_MAX * sizeof(le16_t));
746 next_entry(ef, dir, &cluster, &offset);
747 exfat_write_raw(&name_entry, sizeof(name_entry),
748 co2o(ef, cluster, offset), ef->fd);
751 init_node_meta1(node, &meta1);
752 init_node_meta2(node, &meta2);
754 tree_attach(dir, node);
755 exfat_update_mtime(dir);
759 static int create(struct exfat* ef, const char* path, uint16_t attrib)
761 struct exfat_node* dir;
762 struct exfat_node* existing;
763 cluster_t cluster = EXFAT_CLUSTER_BAD;
765 le16_t name[EXFAT_NAME_MAX + 1];
768 rc = exfat_split(ef, &dir, &existing, name, path);
771 if (existing != NULL)
773 exfat_put_node(ef, existing);
774 exfat_put_node(ef, dir);
778 rc = find_slot(ef, dir, &cluster, &offset,
779 2 + DIV_ROUND_UP(utf16_length(name), EXFAT_ENAME_MAX));
782 exfat_put_node(ef, dir);
785 rc = write_entry(ef, dir, name, cluster, offset, attrib);
786 exfat_put_node(ef, dir);
790 int exfat_mknod(struct exfat* ef, const char* path)
792 return create(ef, path, EXFAT_ATTRIB_ARCH);
795 int exfat_mkdir(struct exfat* ef, const char* path)
798 struct exfat_node* node;
800 rc = create(ef, path, EXFAT_ATTRIB_ARCH | EXFAT_ATTRIB_DIR);
803 rc = exfat_lookup(ef, &node, path);
806 /* directories always have at least one cluster */
807 rc = exfat_truncate(ef, node, CLUSTER_SIZE(*ef->sb));
811 exfat_put_node(ef, node);
814 exfat_put_node(ef, node);
818 static void rename_entry(struct exfat* ef, struct exfat_node* dir,
819 struct exfat_node* node, const le16_t* name, cluster_t new_cluster,
822 struct exfat_entry_meta1 meta1;
823 struct exfat_entry_meta2 meta2;
824 cluster_t old_cluster = node->entry_cluster;
825 off_t old_offset = node->entry_offset;
826 const size_t name_length = utf16_length(name);
827 const int name_entries = DIV_ROUND_UP(name_length, EXFAT_ENAME_MAX);
830 exfat_read_raw(&meta1, sizeof(meta1), co2o(ef, old_cluster, old_offset),
832 next_entry(ef, node->parent, &old_cluster, &old_offset);
833 exfat_read_raw(&meta2, sizeof(meta2), co2o(ef, old_cluster, old_offset),
835 meta1.continuations = 1 + name_entries;
836 meta2.name_hash = exfat_calc_name_hash(ef, name);
837 meta2.name_length = name_length;
838 meta1.checksum = exfat_calc_checksum(&meta1, &meta2, name);
840 erase_entry(ef, node);
842 node->entry_cluster = new_cluster;
843 node->entry_offset = new_offset;
845 exfat_write_raw(&meta1, sizeof(meta1), co2o(ef, new_cluster, new_offset),
847 next_entry(ef, dir, &new_cluster, &new_offset);
848 exfat_write_raw(&meta2, sizeof(meta2), co2o(ef, new_cluster, new_offset),
851 for (i = 0; i < name_entries; i++)
853 struct exfat_entry_name name_entry = {EXFAT_ENTRY_FILE_NAME, 0};
854 memcpy(name_entry.name, name + i * EXFAT_ENAME_MAX,
855 EXFAT_ENAME_MAX * sizeof(le16_t));
856 next_entry(ef, dir, &new_cluster, &new_offset);
857 exfat_write_raw(&name_entry, sizeof(name_entry),
858 co2o(ef, new_cluster, new_offset), ef->fd);
861 memcpy(node->name, name, (EXFAT_NAME_MAX + 1) * sizeof(le16_t));
863 tree_attach(dir, node);
866 int exfat_rename(struct exfat* ef, const char* old_path, const char* new_path)
868 struct exfat_node* node;
869 struct exfat_node* existing;
870 struct exfat_node* dir;
871 cluster_t cluster = EXFAT_CLUSTER_BAD;
873 le16_t name[EXFAT_NAME_MAX + 1];
876 rc = exfat_lookup(ef, &node, old_path);
880 rc = exfat_split(ef, &dir, &existing, name, new_path);
883 exfat_put_node(ef, node);
886 if (existing != NULL)
888 if (existing->flags & EXFAT_ATTRIB_DIR)
890 if (node->flags & EXFAT_ATTRIB_DIR)
891 rc = exfat_rmdir(ef, existing);
897 if (!(node->flags & EXFAT_ATTRIB_DIR))
898 rc = exfat_unlink(ef, existing);
902 exfat_put_node(ef, existing);
905 exfat_put_node(ef, dir);
906 exfat_put_node(ef, node);
911 rc = find_slot(ef, dir, &cluster, &offset,
912 2 + DIV_ROUND_UP(utf16_length(name), EXFAT_ENAME_MAX));
915 exfat_put_node(ef, dir);
916 exfat_put_node(ef, node);
919 rename_entry(ef, dir, node, name, cluster, offset);
920 exfat_put_node(ef, dir);
921 exfat_put_node(ef, node);
925 void exfat_utimes(struct exfat_node* node, const struct timespec tv[2])
927 node->atime = tv[0].tv_sec;
928 node->mtime = tv[1].tv_sec;
929 node->flags |= EXFAT_ATTRIB_DIRTY;
932 void exfat_update_atime(struct exfat_node* node)
934 node->atime = time(NULL);
935 node->flags |= EXFAT_ATTRIB_DIRTY;
938 void exfat_update_mtime(struct exfat_node* node)
940 node->mtime = time(NULL);
941 node->flags |= EXFAT_ATTRIB_DIRTY;
944 const char* exfat_get_label(struct exfat* ef)
949 static int find_label(struct exfat* ef, cluster_t* cluster, off_t* offset)
953 const struct exfat_entry* entry;
955 rc = opendir(ef, ef->root, &it);
961 entry = (const struct exfat_entry*)
962 (it.chunk + it.offset % CLUSTER_SIZE(*ef->sb));
964 if (entry->type == EXFAT_ENTRY_EOD)
969 if (entry->type == EXFAT_ENTRY_LABEL)
971 *cluster = it.cluster;
977 if (fetch_next_entry(ef, ef->root, &it) != 0)
985 int exfat_set_label(struct exfat* ef, const char* label)
987 le16_t label_utf16[EXFAT_ENAME_MAX + 1];
991 struct exfat_entry_label entry;
993 memset(label_utf16, 0, sizeof(label_utf16));
994 rc = utf8_to_utf16(label_utf16, label, EXFAT_ENAME_MAX, strlen(label));
998 rc = find_label(ef, &cluster, &offset);
1000 rc = find_slot(ef, ef->root, &cluster, &offset, 1);
1004 entry.type = EXFAT_ENTRY_LABEL;
1005 entry.length = utf16_length(label_utf16);
1006 memcpy(entry.name, label_utf16, sizeof(entry.name));
1007 if (entry.length == 0)
1008 entry.type ^= EXFAT_ENTRY_VALID;
1010 exfat_write_raw(&entry, sizeof(struct exfat_entry_label),
1011 co2o(ef, cluster, offset), ef->fd);