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 void opendir(const struct exfat_node* dir, struct iterator* it)
58 if (!(dir->flags & EXFAT_ATTRIB_DIR))
59 exfat_bug("`%s' is not a directory", dir->name);
60 it->cluster = dir->start_cluster;
62 it->contiguous = IS_CONTIGUOUS(*dir);
66 static void closedir(struct iterator* it)
75 static int fetch_next_entry(struct exfat* ef, const struct exfat_node* parent,
78 /* move iterator to the next entry in the directory */
79 it->offset += sizeof(struct exfat_entry);
80 /* fetch the next cluster if needed */
81 if ((it->offset & (CLUSTER_SIZE(*ef->sb) - 1)) == 0)
83 it->cluster = exfat_next_cluster(ef, parent, it->cluster);
84 if (CLUSTER_INVALID(it->cluster))
86 exfat_error("invalid cluster while reading directory");
89 exfat_read_raw(it->chunk, CLUSTER_SIZE(*ef->sb),
90 exfat_c2o(ef, it->cluster), ef->fd);
96 * Reads one entry in directory at position pointed by iterator and fills
99 static int readdir(struct exfat* ef, const struct exfat_node* parent,
100 struct exfat_node** node, struct iterator* it)
102 const struct exfat_entry* entry;
103 const struct exfat_file* file;
104 const struct exfat_file_info* file_info;
105 const struct exfat_file_name* file_name;
106 const struct exfat_upcase* upcase;
107 const struct exfat_bitmap* bitmap;
108 const struct exfat_label* label;
109 uint8_t continuations = 0;
110 le16_t* namep = NULL;
111 uint16_t reference_checksum = 0;
112 uint16_t actual_checksum = 0;
116 if (it->chunk == NULL)
118 it->chunk = malloc(CLUSTER_SIZE(*ef->sb));
119 if (it->chunk == NULL)
121 exfat_error("out of memory");
124 exfat_read_raw(it->chunk, CLUSTER_SIZE(*ef->sb),
125 exfat_c2o(ef, it->cluster), ef->fd);
130 /* every directory (even empty one) occupies at least one cluster and
131 must contain EOD entry */
132 entry = (const struct exfat_entry*)
133 (it->chunk + it->offset % CLUSTER_SIZE(*ef->sb));
137 case EXFAT_ENTRY_EOD:
138 if (continuations != 0)
140 exfat_error("expected %hhu continuations before EOD",
144 return -ENOENT; /* that's OK, means end of directory */
146 case EXFAT_ENTRY_FILE:
147 if (continuations != 0)
149 exfat_error("expected %hhu continuations before new entry",
153 file = (const struct exfat_file*) entry;
154 continuations = file->continuations;
155 /* each file entry must have at least 2 continuations:
157 if (continuations < 2)
159 exfat_error("too few continuations (%hhu)", continuations);
162 reference_checksum = le16_to_cpu(file->checksum);
163 actual_checksum = exfat_start_checksum(file);
164 *node = malloc(sizeof(struct exfat_node));
167 exfat_error("failed to allocate node");
170 memset(*node, 0, sizeof(struct exfat_node));
171 /* new node has zero reference counter */
172 (*node)->entry_cluster = it->cluster;
173 (*node)->entry_offset = it->offset % CLUSTER_SIZE(*ef->sb);
174 (*node)->flags = le16_to_cpu(file->attrib);
175 (*node)->mtime = exfat_exfat2unix(file->mdate, file->mtime);
176 (*node)->atime = exfat_exfat2unix(file->adate, file->atime);
177 namep = (*node)->name;
180 case EXFAT_ENTRY_FILE_INFO:
181 if (continuations < 2)
183 exfat_error("unexpected continuation (%hhu)",
187 file_info = (const struct exfat_file_info*) entry;
188 actual_checksum = exfat_add_checksum(entry, actual_checksum);
189 (*node)->size = le64_to_cpu(file_info->size);
190 /* directories must be aligned on at cluster boundary */
191 if (((*node)->flags & EXFAT_ATTRIB_DIR) &&
192 (*node)->size % CLUSTER_SIZE(*ef->sb) != 0)
194 char buffer[EXFAT_NAME_MAX + 1];
196 exfat_get_name(*node, buffer, EXFAT_NAME_MAX);
197 exfat_error("directory `%s' has invalid size %"PRIu64" bytes",
198 buffer, (*node)->size);
201 (*node)->start_cluster = le32_to_cpu(file_info->start_cluster);
202 (*node)->fptr_cluster = (*node)->start_cluster;
203 if (file_info->flag == EXFAT_FLAG_CONTIGUOUS)
204 (*node)->flags |= EXFAT_ATTRIB_CONTIGUOUS;
208 case EXFAT_ENTRY_FILE_NAME:
209 if (continuations == 0)
211 exfat_error("unexpected continuation");
214 file_name = (const struct exfat_file_name*) entry;
215 actual_checksum = exfat_add_checksum(entry, actual_checksum);
217 memcpy(namep, file_name->name, EXFAT_ENAME_MAX * sizeof(le16_t));
218 namep += EXFAT_ENAME_MAX;
219 if (--continuations == 0)
221 if (actual_checksum != reference_checksum)
223 exfat_error("invalid checksum (0x%hx != 0x%hx)",
224 actual_checksum, reference_checksum);
227 if (fetch_next_entry(ef, parent, it) != 0)
229 return 0; /* entry completed */
233 case EXFAT_ENTRY_UPCASE:
234 if (ef->upcase != NULL)
236 upcase = (const struct exfat_upcase*) entry;
237 if (CLUSTER_INVALID(le32_to_cpu(upcase->start_cluster)))
239 exfat_error("invalid cluster in upcase table");
242 if (le64_to_cpu(upcase->size) == 0 ||
243 le64_to_cpu(upcase->size) > 0xffff * sizeof(uint16_t) ||
244 le64_to_cpu(upcase->size) % sizeof(uint16_t) != 0)
246 exfat_error("bad upcase table size (%"PRIu64" bytes)",
247 le64_to_cpu(upcase->size));
250 ef->upcase = malloc(le64_to_cpu(upcase->size));
251 if (ef->upcase == NULL)
253 exfat_error("failed to allocate upcase table (%"PRIu64" bytes)",
254 le64_to_cpu(upcase->size));
257 ef->upcase_chars = le64_to_cpu(upcase->size) / sizeof(le16_t);
259 exfat_read_raw(ef->upcase, le64_to_cpu(upcase->size),
260 exfat_c2o(ef, le32_to_cpu(upcase->start_cluster)), ef->fd);
263 case EXFAT_ENTRY_BITMAP:
264 bitmap = (const struct exfat_bitmap*) entry;
265 if (CLUSTER_INVALID(le32_to_cpu(bitmap->start_cluster)))
267 exfat_error("invalid cluster in clusters bitmap");
270 ef->cmap.size = le32_to_cpu(ef->sb->cluster_count) -
271 EXFAT_FIRST_DATA_CLUSTER;
272 if (le64_to_cpu(bitmap->size) != (ef->cmap.size + 7) / 8)
274 exfat_error("invalid bitmap size: %"PRIu64" (expected %u)",
275 le64_to_cpu(bitmap->size), (ef->cmap.size + 7) / 8);
278 ef->cmap.start_cluster = le32_to_cpu(bitmap->start_cluster);
279 /* FIXME bitmap can be rather big, up to 512 MB */
280 ef->cmap.chunk_size = ef->cmap.size;
281 ef->cmap.chunk = malloc(le64_to_cpu(bitmap->size));
282 if (ef->cmap.chunk == NULL)
284 exfat_error("failed to allocate clusters map chunk "
285 "(%"PRIu64" bytes)", le64_to_cpu(bitmap->size));
289 exfat_read_raw(ef->cmap.chunk, le64_to_cpu(bitmap->size),
290 exfat_c2o(ef, ef->cmap.start_cluster), ef->fd);
293 case EXFAT_ENTRY_LABEL:
294 label = (const struct exfat_label*) entry;
295 if (label->length > EXFAT_ENAME_MAX)
297 exfat_error("too long label (%hhu chars)", label->length);
303 if (entry->type & EXFAT_ENTRY_VALID)
305 exfat_error("unknown entry type 0x%hhu", entry->type);
311 if (fetch_next_entry(ef, parent, it) != 0)
314 /* we never reach here */
322 int exfat_cache_directory(struct exfat* ef, struct exfat_node* dir)
326 struct exfat_node* node;
327 struct exfat_node* current = NULL;
329 if (dir->flags & EXFAT_ATTRIB_CACHED)
330 return 0; /* already cached */
333 while ((rc = readdir(ef, dir, &node, &it)) == 0)
338 current->next = node;
339 node->prev = current;
351 for (current = dir->child; current; current = node)
353 node = current->next;
360 dir->flags |= EXFAT_ATTRIB_CACHED;
364 static void reset_cache(struct exfat* ef, struct exfat_node* node)
366 struct exfat_node* child;
367 struct exfat_node* next;
369 for (child = node->child; child; child = next)
371 reset_cache(ef, child);
375 if (node->references != 0)
377 char buffer[EXFAT_NAME_MAX + 1];
378 exfat_get_name(node, buffer, EXFAT_NAME_MAX);
379 exfat_warn("non-zero reference counter (%d) for `%s'",
380 node->references, buffer);
382 while (node->references--)
383 exfat_put_node(ef, node);
385 node->flags &= ~EXFAT_ATTRIB_CACHED;
388 void exfat_reset_cache(struct exfat* ef)
390 reset_cache(ef, ef->root);
393 void next_entry(struct exfat* ef, const struct exfat_node* parent,
394 cluster_t* cluster, off_t* offset)
396 if (*offset + sizeof(struct exfat_entry) == CLUSTER_SIZE(*ef->sb))
398 /* next cluster cannot be invalid */
399 *cluster = exfat_next_cluster(ef, parent, *cluster);
403 *offset += sizeof(struct exfat_entry);
407 void exfat_flush_node(struct exfat* ef, struct exfat_node* node)
411 off_t meta1_offset, meta2_offset;
412 struct exfat_file meta1;
413 struct exfat_file_info meta2;
415 if (node->parent == NULL)
416 return; /* do not flush unlinked node */
418 cluster = node->entry_cluster;
419 offset = node->entry_offset;
420 meta1_offset = exfat_c2o(ef, cluster) + offset;
421 next_entry(ef, node->parent, &cluster, &offset);
422 meta2_offset = exfat_c2o(ef, cluster) + offset;
424 exfat_read_raw(&meta1, sizeof(meta1), meta1_offset, ef->fd);
425 if (meta1.type != EXFAT_ENTRY_FILE)
426 exfat_bug("invalid type of meta1: 0x%hhx", meta1.type);
427 meta1.attrib = cpu_to_le16(node->flags);
428 exfat_unix2exfat(node->mtime, &meta1.mdate, &meta1.mtime);
429 exfat_unix2exfat(node->atime, &meta1.adate, &meta1.atime);
431 exfat_read_raw(&meta2, sizeof(meta2), meta2_offset, ef->fd);
432 if (meta2.type != EXFAT_ENTRY_FILE_INFO)
433 exfat_bug("invalid type of meta2: 0x%hhx", meta2.type);
434 meta2.size = cpu_to_le64(node->size);
435 meta2.start_cluster = cpu_to_le32(node->start_cluster);
436 meta2.flag = (IS_CONTIGUOUS(*node) ?
437 EXFAT_FLAG_CONTIGUOUS : EXFAT_FLAG_FRAGMENTED);
438 /* FIXME name hash */
440 meta1.checksum = exfat_calc_checksum(&meta1, &meta2, node->name);
442 exfat_write_raw(&meta1, sizeof(meta1), meta1_offset, ef->fd);
443 exfat_write_raw(&meta2, sizeof(meta2), meta2_offset, ef->fd);
445 node->flags &= ~EXFAT_ATTRIB_DIRTY;
448 static void erase_entry(struct exfat* ef, struct exfat_node* node)
450 cluster_t cluster = node->entry_cluster;
451 off_t offset = node->entry_offset;
452 int name_entries = DIV_ROUND_UP(utf16_length(node->name), EXFAT_ENAME_MAX);
455 entry_type = EXFAT_ENTRY_FILE & ~EXFAT_ENTRY_VALID;
456 exfat_write_raw(&entry_type, 1, exfat_c2o(ef, cluster) + offset, ef->fd);
458 next_entry(ef, node->parent, &cluster, &offset);
459 entry_type = EXFAT_ENTRY_FILE_INFO & ~EXFAT_ENTRY_VALID;
460 exfat_write_raw(&entry_type, 1, exfat_c2o(ef, cluster) + offset, ef->fd);
462 while (name_entries--)
464 next_entry(ef, node->parent, &cluster, &offset);
465 entry_type = EXFAT_ENTRY_FILE_NAME & ~EXFAT_ENTRY_VALID;
466 exfat_write_raw(&entry_type, 1, exfat_c2o(ef, cluster) + offset,
471 static void delete(struct exfat* ef, struct exfat_node* node)
473 erase_entry(ef, node);
475 node->prev->next = node->next;
476 else /* this is the first node in the list */
477 node->parent->child = node->next;
479 node->next->prev = node->prev;
483 /* file clusters will be freed when node reference counter becomes 0 */
484 node->flags |= EXFAT_ATTRIB_UNLINKED;
487 int exfat_unlink(struct exfat* ef, struct exfat_node* node)
489 if (node->flags & EXFAT_ATTRIB_DIR)
495 int exfat_rmdir(struct exfat* ef, struct exfat_node* node)
497 if (!(node->flags & EXFAT_ATTRIB_DIR))
499 /* check that directory is empty */
500 exfat_cache_directory(ef, node);