3 * exFAT file system implementation library.
5 * Created by Andrew Nayenko on 09.10.09.
6 * This software is distributed under the GNU General Public License
7 * version 3 or any later.
15 /* on-disk nodes iterator */
24 struct exfat_node* exfat_get_node(struct exfat_node* node)
26 /* if we switch to multi-threaded mode we will need atomic
27 increment here and atomic decrement in exfat_put_node() */
32 void exfat_put_node(struct exfat* ef, struct exfat_node* node)
34 if (--node->references < 0)
36 char buffer[EXFAT_NAME_MAX + 1];
37 exfat_get_name(node, buffer, EXFAT_NAME_MAX);
38 exfat_bug("reference counter of `%s' is below zero", buffer);
41 if (node->references == 0)
43 if (node->flags & EXFAT_ATTRIB_DIRTY)
44 exfat_flush_node(ef, node);
45 if (node->flags & EXFAT_ATTRIB_UNLINKED)
47 /* free all clusters and node structure itself */
48 exfat_truncate(ef, node, 0);
56 static int opendir(struct exfat* ef, const struct exfat_node* dir,
59 if (!(dir->flags & EXFAT_ATTRIB_DIR))
60 exfat_bug("`%s' is not a directory", dir->name);
61 it->cluster = dir->start_cluster;
63 it->contiguous = IS_CONTIGUOUS(*dir);
64 it->chunk = malloc(CLUSTER_SIZE(*ef->sb));
65 if (it->chunk == NULL)
67 exfat_error("out of memory");
70 exfat_read_raw(it->chunk, CLUSTER_SIZE(*ef->sb),
71 exfat_c2o(ef, it->cluster), ef->fd);
75 static void closedir(struct iterator* it)
84 static int fetch_next_entry(struct exfat* ef, const struct exfat_node* parent,
87 /* move iterator to the next entry in the directory */
88 it->offset += sizeof(struct exfat_entry);
89 /* fetch the next cluster if needed */
90 if ((it->offset & (CLUSTER_SIZE(*ef->sb) - 1)) == 0)
92 it->cluster = exfat_next_cluster(ef, parent, it->cluster);
93 if (CLUSTER_INVALID(it->cluster))
95 exfat_error("invalid cluster while reading directory");
98 exfat_read_raw(it->chunk, CLUSTER_SIZE(*ef->sb),
99 exfat_c2o(ef, it->cluster), ef->fd);
105 * Reads one entry in directory at position pointed by iterator and fills
108 static int readdir(struct exfat* ef, const struct exfat_node* parent,
109 struct exfat_node** node, struct iterator* it)
111 const struct exfat_entry* entry;
112 const struct exfat_file* file;
113 const struct exfat_file_info* file_info;
114 const struct exfat_file_name* file_name;
115 const struct exfat_upcase* upcase;
116 const struct exfat_bitmap* bitmap;
117 const struct exfat_label* label;
118 uint8_t continuations = 0;
119 le16_t* namep = NULL;
120 uint16_t reference_checksum = 0;
121 uint16_t actual_checksum = 0;
127 /* every directory (even empty one) occupies at least one cluster and
128 must contain EOD entry */
129 entry = (const struct exfat_entry*)
130 (it->chunk + it->offset % CLUSTER_SIZE(*ef->sb));
134 case EXFAT_ENTRY_EOD:
135 if (continuations != 0)
137 exfat_error("expected %hhu continuations before EOD",
141 return -ENOENT; /* that's OK, means end of directory */
143 case EXFAT_ENTRY_FILE:
144 if (continuations != 0)
146 exfat_error("expected %hhu continuations before new entry",
150 file = (const struct exfat_file*) entry;
151 continuations = file->continuations;
152 /* each file entry must have at least 2 continuations:
154 if (continuations < 2)
156 exfat_error("too few continuations (%hhu)", continuations);
159 reference_checksum = le16_to_cpu(file->checksum);
160 actual_checksum = exfat_start_checksum(file);
161 *node = malloc(sizeof(struct exfat_node));
164 exfat_error("failed to allocate node");
167 memset(*node, 0, sizeof(struct exfat_node));
168 /* new node has zero reference counter */
169 (*node)->entry_cluster = it->cluster;
170 (*node)->entry_offset = it->offset % CLUSTER_SIZE(*ef->sb);
171 (*node)->flags = le16_to_cpu(file->attrib);
172 (*node)->mtime = exfat_exfat2unix(file->mdate, file->mtime);
173 (*node)->atime = exfat_exfat2unix(file->adate, file->atime);
174 namep = (*node)->name;
177 case EXFAT_ENTRY_FILE_INFO:
178 if (continuations < 2)
180 exfat_error("unexpected continuation (%hhu)",
184 file_info = (const struct exfat_file_info*) entry;
185 actual_checksum = exfat_add_checksum(entry, actual_checksum);
186 (*node)->size = le64_to_cpu(file_info->size);
187 /* directories must be aligned on at cluster boundary */
188 if (((*node)->flags & EXFAT_ATTRIB_DIR) &&
189 (*node)->size % CLUSTER_SIZE(*ef->sb) != 0)
191 char buffer[EXFAT_NAME_MAX + 1];
193 exfat_get_name(*node, buffer, EXFAT_NAME_MAX);
194 exfat_error("directory `%s' has invalid size %"PRIu64" bytes",
195 buffer, (*node)->size);
198 (*node)->start_cluster = le32_to_cpu(file_info->start_cluster);
199 (*node)->fptr_cluster = (*node)->start_cluster;
200 if (file_info->flag == EXFAT_FLAG_CONTIGUOUS)
201 (*node)->flags |= EXFAT_ATTRIB_CONTIGUOUS;
205 case EXFAT_ENTRY_FILE_NAME:
206 if (continuations == 0)
208 exfat_error("unexpected continuation");
211 file_name = (const struct exfat_file_name*) entry;
212 actual_checksum = exfat_add_checksum(entry, actual_checksum);
214 memcpy(namep, file_name->name, EXFAT_ENAME_MAX * sizeof(le16_t));
215 namep += EXFAT_ENAME_MAX;
216 if (--continuations == 0)
218 if (actual_checksum != reference_checksum)
220 exfat_error("invalid checksum (0x%hx != 0x%hx)",
221 actual_checksum, reference_checksum);
224 if (fetch_next_entry(ef, parent, it) != 0)
226 return 0; /* entry completed */
230 case EXFAT_ENTRY_UPCASE:
231 if (ef->upcase != NULL)
233 upcase = (const struct exfat_upcase*) entry;
234 if (CLUSTER_INVALID(le32_to_cpu(upcase->start_cluster)))
236 exfat_error("invalid cluster in upcase table");
239 if (le64_to_cpu(upcase->size) == 0 ||
240 le64_to_cpu(upcase->size) > 0xffff * sizeof(uint16_t) ||
241 le64_to_cpu(upcase->size) % sizeof(uint16_t) != 0)
243 exfat_error("bad upcase table size (%"PRIu64" bytes)",
244 le64_to_cpu(upcase->size));
247 ef->upcase = malloc(le64_to_cpu(upcase->size));
248 if (ef->upcase == NULL)
250 exfat_error("failed to allocate upcase table (%"PRIu64" bytes)",
251 le64_to_cpu(upcase->size));
254 ef->upcase_chars = le64_to_cpu(upcase->size) / sizeof(le16_t);
256 exfat_read_raw(ef->upcase, le64_to_cpu(upcase->size),
257 exfat_c2o(ef, le32_to_cpu(upcase->start_cluster)), ef->fd);
260 case EXFAT_ENTRY_BITMAP:
261 bitmap = (const struct exfat_bitmap*) entry;
262 if (CLUSTER_INVALID(le32_to_cpu(bitmap->start_cluster)))
264 exfat_error("invalid cluster in clusters bitmap");
267 ef->cmap.size = le32_to_cpu(ef->sb->cluster_count) -
268 EXFAT_FIRST_DATA_CLUSTER;
269 if (le64_to_cpu(bitmap->size) != (ef->cmap.size + 7) / 8)
271 exfat_error("invalid bitmap size: %"PRIu64" (expected %u)",
272 le64_to_cpu(bitmap->size), (ef->cmap.size + 7) / 8);
275 ef->cmap.start_cluster = le32_to_cpu(bitmap->start_cluster);
276 /* FIXME bitmap can be rather big, up to 512 MB */
277 ef->cmap.chunk_size = ef->cmap.size;
278 ef->cmap.chunk = malloc(le64_to_cpu(bitmap->size));
279 if (ef->cmap.chunk == NULL)
281 exfat_error("failed to allocate clusters map chunk "
282 "(%"PRIu64" bytes)", le64_to_cpu(bitmap->size));
286 exfat_read_raw(ef->cmap.chunk, le64_to_cpu(bitmap->size),
287 exfat_c2o(ef, ef->cmap.start_cluster), ef->fd);
290 case EXFAT_ENTRY_LABEL:
291 label = (const struct exfat_label*) entry;
292 if (label->length > EXFAT_ENAME_MAX)
294 exfat_error("too long label (%hhu chars)", label->length);
300 if (entry->type & EXFAT_ENTRY_VALID)
302 exfat_error("unknown entry type 0x%hhu", entry->type);
308 if (fetch_next_entry(ef, parent, it) != 0)
311 /* we never reach here */
319 int exfat_cache_directory(struct exfat* ef, struct exfat_node* dir)
323 struct exfat_node* node;
324 struct exfat_node* current = NULL;
326 if (dir->flags & EXFAT_ATTRIB_CACHED)
327 return 0; /* already cached */
329 rc = opendir(ef, dir, &it);
332 while ((rc = readdir(ef, dir, &node, &it)) == 0)
337 current->next = node;
338 node->prev = current;
350 for (current = dir->child; current; current = node)
352 node = current->next;
359 dir->flags |= EXFAT_ATTRIB_CACHED;
363 static void reset_cache(struct exfat* ef, struct exfat_node* node)
365 struct exfat_node* child;
366 struct exfat_node* next;
368 for (child = node->child; child; child = next)
370 reset_cache(ef, child);
374 if (node->references != 0)
376 char buffer[EXFAT_NAME_MAX + 1];
377 exfat_get_name(node, buffer, EXFAT_NAME_MAX);
378 exfat_warn("non-zero reference counter (%d) for `%s'",
379 node->references, buffer);
381 while (node->references--)
382 exfat_put_node(ef, node);
384 node->flags &= ~EXFAT_ATTRIB_CACHED;
387 void exfat_reset_cache(struct exfat* ef)
389 reset_cache(ef, ef->root);
392 void next_entry(struct exfat* ef, const struct exfat_node* parent,
393 cluster_t* cluster, off_t* offset)
395 if (*offset + sizeof(struct exfat_entry) == CLUSTER_SIZE(*ef->sb))
397 /* next cluster cannot be invalid */
398 *cluster = exfat_next_cluster(ef, parent, *cluster);
402 *offset += sizeof(struct exfat_entry);
406 void exfat_flush_node(struct exfat* ef, struct exfat_node* node)
410 off_t meta1_offset, meta2_offset;
411 struct exfat_file meta1;
412 struct exfat_file_info meta2;
414 if (node->parent == NULL)
415 return; /* do not flush unlinked node */
417 cluster = node->entry_cluster;
418 offset = node->entry_offset;
419 meta1_offset = exfat_c2o(ef, cluster) + offset;
420 next_entry(ef, node->parent, &cluster, &offset);
421 meta2_offset = exfat_c2o(ef, cluster) + offset;
423 exfat_read_raw(&meta1, sizeof(meta1), meta1_offset, ef->fd);
424 if (meta1.type != EXFAT_ENTRY_FILE)
425 exfat_bug("invalid type of meta1: 0x%hhx", meta1.type);
426 meta1.attrib = cpu_to_le16(node->flags);
427 exfat_unix2exfat(node->mtime, &meta1.mdate, &meta1.mtime);
428 exfat_unix2exfat(node->atime, &meta1.adate, &meta1.atime);
430 exfat_read_raw(&meta2, sizeof(meta2), meta2_offset, ef->fd);
431 if (meta2.type != EXFAT_ENTRY_FILE_INFO)
432 exfat_bug("invalid type of meta2: 0x%hhx", meta2.type);
433 meta2.size = cpu_to_le64(node->size);
434 meta2.start_cluster = cpu_to_le32(node->start_cluster);
435 meta2.flag = (IS_CONTIGUOUS(*node) ?
436 EXFAT_FLAG_CONTIGUOUS : EXFAT_FLAG_FRAGMENTED);
437 /* FIXME name hash */
439 meta1.checksum = exfat_calc_checksum(&meta1, &meta2, node->name);
441 exfat_write_raw(&meta1, sizeof(meta1), meta1_offset, ef->fd);
442 exfat_write_raw(&meta2, sizeof(meta2), meta2_offset, ef->fd);
444 node->flags &= ~EXFAT_ATTRIB_DIRTY;
447 static void erase_entry(struct exfat* ef, struct exfat_node* node)
449 cluster_t cluster = node->entry_cluster;
450 off_t offset = node->entry_offset;
451 int name_entries = DIV_ROUND_UP(utf16_length(node->name), EXFAT_ENAME_MAX);
454 entry_type = EXFAT_ENTRY_FILE & ~EXFAT_ENTRY_VALID;
455 exfat_write_raw(&entry_type, 1, exfat_c2o(ef, cluster) + offset, ef->fd);
457 next_entry(ef, node->parent, &cluster, &offset);
458 entry_type = EXFAT_ENTRY_FILE_INFO & ~EXFAT_ENTRY_VALID;
459 exfat_write_raw(&entry_type, 1, exfat_c2o(ef, cluster) + offset, ef->fd);
461 while (name_entries--)
463 next_entry(ef, node->parent, &cluster, &offset);
464 entry_type = EXFAT_ENTRY_FILE_NAME & ~EXFAT_ENTRY_VALID;
465 exfat_write_raw(&entry_type, 1, exfat_c2o(ef, cluster) + offset,
470 static void delete(struct exfat* ef, struct exfat_node* node)
472 erase_entry(ef, node);
474 node->prev->next = node->next;
475 else /* this is the first node in the list */
476 node->parent->child = node->next;
478 node->next->prev = node->prev;
482 /* file clusters will be freed when node reference counter becomes 0 */
483 node->flags |= EXFAT_ATTRIB_UNLINKED;
486 int exfat_unlink(struct exfat* ef, struct exfat_node* node)
488 if (node->flags & EXFAT_ATTRIB_DIR)
494 int exfat_rmdir(struct exfat* ef, struct exfat_node* node)
496 if (!(node->flags & EXFAT_ATTRIB_DIR))
498 /* check that directory is empty */
499 exfat_cache_directory(ef, node);