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);
50 static void opendir(const struct exfat_node* dir, struct iterator* it)
52 if (!(dir->flags & EXFAT_ATTRIB_DIR))
53 exfat_bug("`%s' is not a directory", dir->name);
54 it->cluster = dir->start_cluster;
56 it->contiguous = IS_CONTIGUOUS(*dir);
60 static void closedir(struct iterator* it)
69 static int fetch_next_entry(struct exfat* ef, const struct exfat_node* parent,
72 /* move iterator to the next entry in the directory */
73 it->offset += sizeof(struct exfat_entry);
74 /* fetch the next cluster if needed */
75 if ((it->offset & (CLUSTER_SIZE(*ef->sb) - 1)) == 0)
77 it->cluster = exfat_next_cluster(ef, parent, it->cluster);
78 if (CLUSTER_INVALID(it->cluster))
80 exfat_error("invalid cluster while reading directory");
83 exfat_read_raw(it->chunk, CLUSTER_SIZE(*ef->sb),
84 exfat_c2o(ef, it->cluster), ef->fd);
90 * Reads one entry in directory at position pointed by iterator and fills
93 static int readdir(struct exfat* ef, const struct exfat_node* parent,
94 struct exfat_node** node, struct iterator* it)
96 const struct exfat_entry* entry;
97 const struct exfat_file* file;
98 const struct exfat_file_info* file_info;
99 const struct exfat_file_name* file_name;
100 const struct exfat_upcase* upcase;
101 const struct exfat_bitmap* bitmap;
102 const struct exfat_label* label;
103 uint8_t continuations = 0;
104 le16_t* namep = NULL;
105 uint16_t reference_checksum = 0;
106 uint16_t actual_checksum = 0;
110 if (it->chunk == NULL)
112 it->chunk = malloc(CLUSTER_SIZE(*ef->sb));
113 if (it->chunk == NULL)
115 exfat_error("out of memory");
118 exfat_read_raw(it->chunk, CLUSTER_SIZE(*ef->sb),
119 exfat_c2o(ef, it->cluster), ef->fd);
124 /* every directory (even empty one) occupies at least one cluster and
125 must contain EOD entry */
126 entry = (const struct exfat_entry*)
127 (it->chunk + it->offset % CLUSTER_SIZE(*ef->sb));
131 case EXFAT_ENTRY_EOD:
132 if (continuations != 0)
134 exfat_error("expected %hhu continuations before EOD",
138 return -ENOENT; /* that's OK, means end of directory */
140 case EXFAT_ENTRY_FILE:
141 if (continuations != 0)
143 exfat_error("expected %hhu continuations before new entry",
147 file = (const struct exfat_file*) entry;
148 continuations = file->continuations;
149 /* each file entry must have at least 2 continuations:
151 if (continuations < 2)
153 exfat_error("too few continuations (%hhu)", continuations);
156 reference_checksum = le16_to_cpu(file->checksum);
157 actual_checksum = exfat_start_checksum(file);
158 *node = malloc(sizeof(struct exfat_node));
161 exfat_error("failed to allocate node");
164 memset(*node, 0, sizeof(struct exfat_node));
165 /* new node has zero reference counter */
166 (*node)->entry_cluster = it->cluster;
167 (*node)->entry_offset = it->offset % CLUSTER_SIZE(*ef->sb);
168 (*node)->flags = le16_to_cpu(file->attrib);
169 (*node)->mtime = exfat_exfat2unix(file->mdate, file->mtime);
170 (*node)->atime = exfat_exfat2unix(file->adate, file->atime);
171 namep = (*node)->name;
174 case EXFAT_ENTRY_FILE_INFO:
175 if (continuations < 2)
177 exfat_error("unexpected continuation (%hhu)",
181 file_info = (const struct exfat_file_info*) entry;
182 actual_checksum = exfat_add_checksum(entry, actual_checksum);
183 (*node)->size = le64_to_cpu(file_info->size);
184 /* directories must be aligned on at cluster boundary */
185 if (((*node)->flags & EXFAT_ATTRIB_DIR) &&
186 (*node)->size % CLUSTER_SIZE(*ef->sb) != 0)
188 char buffer[EXFAT_NAME_MAX + 1];
190 exfat_get_name(*node, buffer, EXFAT_NAME_MAX);
191 exfat_error("directory `%s' has invalid size %"PRIu64" bytes",
192 buffer, (*node)->size);
195 (*node)->start_cluster = le32_to_cpu(file_info->start_cluster);
196 (*node)->fptr_cluster = (*node)->start_cluster;
197 if (file_info->flag == EXFAT_FLAG_CONTIGUOUS)
198 (*node)->flags |= EXFAT_ATTRIB_CONTIGUOUS;
202 case EXFAT_ENTRY_FILE_NAME:
203 if (continuations == 0)
205 exfat_error("unexpected continuation");
208 file_name = (const struct exfat_file_name*) entry;
209 actual_checksum = exfat_add_checksum(entry, actual_checksum);
211 memcpy(namep, file_name->name, EXFAT_ENAME_MAX * sizeof(le16_t));
212 namep += EXFAT_ENAME_MAX;
213 if (--continuations == 0)
215 if (actual_checksum != reference_checksum)
217 exfat_error("invalid checksum (0x%hx != 0x%hx)",
218 actual_checksum, reference_checksum);
221 if (fetch_next_entry(ef, parent, it) != 0)
223 return 0; /* entry completed */
227 case EXFAT_ENTRY_UPCASE:
228 if (ef->upcase != NULL)
230 upcase = (const struct exfat_upcase*) entry;
231 if (CLUSTER_INVALID(le32_to_cpu(upcase->start_cluster)))
233 exfat_error("invalid cluster in upcase table");
236 if (le64_to_cpu(upcase->size) == 0 ||
237 le64_to_cpu(upcase->size) > 0xffff * sizeof(uint16_t) ||
238 le64_to_cpu(upcase->size) % sizeof(uint16_t) != 0)
240 exfat_error("bad upcase table size (%"PRIu64" bytes)",
241 le64_to_cpu(upcase->size));
244 ef->upcase = malloc(le64_to_cpu(upcase->size));
245 if (ef->upcase == NULL)
247 exfat_error("failed to allocate upcase table (%"PRIu64" bytes)",
248 le64_to_cpu(upcase->size));
251 ef->upcase_chars = le64_to_cpu(upcase->size) / sizeof(le16_t);
253 exfat_read_raw(ef->upcase, le64_to_cpu(upcase->size),
254 exfat_c2o(ef, le32_to_cpu(upcase->start_cluster)), ef->fd);
257 case EXFAT_ENTRY_BITMAP:
258 bitmap = (const struct exfat_bitmap*) entry;
259 if (CLUSTER_INVALID(le32_to_cpu(bitmap->start_cluster)))
261 exfat_error("invalid cluster in clusters bitmap");
264 ef->cmap.size = le32_to_cpu(ef->sb->cluster_count) -
265 EXFAT_FIRST_DATA_CLUSTER;
266 if (le64_to_cpu(bitmap->size) != (ef->cmap.size + 7) / 8)
268 exfat_error("invalid bitmap size: %"PRIu64" (expected %u)",
269 le64_to_cpu(bitmap->size), (ef->cmap.size + 7) / 8);
272 ef->cmap.start_cluster = le32_to_cpu(bitmap->start_cluster);
273 /* FIXME bitmap can be rather big, up to 512 MB */
274 ef->cmap.chunk_size = ef->cmap.size;
275 ef->cmap.chunk = malloc(le64_to_cpu(bitmap->size));
276 if (ef->cmap.chunk == NULL)
278 exfat_error("failed to allocate clusters map chunk "
279 "(%"PRIu64" bytes)", le64_to_cpu(bitmap->size));
283 exfat_read_raw(ef->cmap.chunk, le64_to_cpu(bitmap->size),
284 exfat_c2o(ef, ef->cmap.start_cluster), ef->fd);
287 case EXFAT_ENTRY_LABEL:
288 label = (const struct exfat_label*) entry;
289 if (label->length > EXFAT_ENAME_MAX)
291 exfat_error("too long label (%hhu chars)", label->length);
297 if (entry->type & EXFAT_ENTRY_VALID)
299 exfat_error("unknown entry type 0x%hhu", entry->type);
305 if (fetch_next_entry(ef, parent, it) != 0)
308 /* we never reach here */
316 int exfat_cache_directory(struct exfat* ef, struct exfat_node* dir)
320 struct exfat_node* node;
321 struct exfat_node* current = NULL;
323 if (dir->flags & EXFAT_ATTRIB_CACHED)
324 return 0; /* already cached */
327 while ((rc = readdir(ef, dir, &node, &it)) == 0)
332 current->next = node;
333 node->prev = current;
345 for (current = dir->child; current; current = node)
347 node = current->next;
354 dir->flags |= EXFAT_ATTRIB_CACHED;
358 static void reset_cache(struct exfat* ef, struct exfat_node* node)
360 struct exfat_node* child;
361 struct exfat_node* next;
363 for (child = node->child; child; child = next)
365 reset_cache(ef, child);
369 if (node->references != 0)
371 char buffer[EXFAT_NAME_MAX + 1];
372 exfat_get_name(node, buffer, EXFAT_NAME_MAX);
373 exfat_warn("non-zero reference counter (%d) for `%s'",
374 node->references, buffer);
376 while (node->references--)
377 exfat_put_node(ef, node);
379 node->flags &= ~EXFAT_ATTRIB_CACHED;
382 void exfat_reset_cache(struct exfat* ef)
384 reset_cache(ef, ef->root);
387 void exfat_flush_node(struct exfat* ef, struct exfat_node* node)
389 off_t meta1_offset, meta2_offset;
390 struct exfat_file meta1;
391 struct exfat_file_info meta2;
395 meta1_offset = exfat_c2o(ef, node->entry_cluster) + node->entry_offset;
396 if (node->entry_offset + sizeof(struct exfat_entry)
397 == CLUSTER_SIZE(*ef->sb))
398 /* next cluster cannot be invalid */
399 meta2_offset = exfat_c2o(ef,
400 exfat_next_cluster(ef, node, node->entry_cluster));
402 meta2_offset = meta1_offset + sizeof(struct exfat_entry);
404 exfat_read_raw(&meta1, sizeof(meta1), meta1_offset, ef->fd);
405 if (meta1.type != EXFAT_ENTRY_FILE)
406 exfat_bug("invalid type of meta1: 0x%hhx", meta1.type);
407 meta1.attrib = cpu_to_le16(node->flags);
408 exfat_unix2exfat(node->mtime, &meta1.mdate, &meta1.mtime);
409 exfat_unix2exfat(node->atime, &meta1.adate, &meta1.atime);
411 exfat_read_raw(&meta2, sizeof(meta2), meta2_offset, ef->fd);
412 if (meta2.type != EXFAT_ENTRY_FILE_INFO)
413 exfat_bug("invalid type of meta2: 0x%hhx", meta2.type);
414 meta2.size = cpu_to_le64(node->size);
415 meta2.start_cluster = cpu_to_le32(node->start_cluster);
416 meta2.flag = (IS_CONTIGUOUS(*node) ?
417 EXFAT_FLAG_CONTIGUOUS : EXFAT_FLAG_FRAGMENTED);
418 /* FIXME name hash */
420 checksum = exfat_start_checksum(&meta1);
421 checksum = exfat_add_checksum(&meta2, checksum);
422 for (i = 1; i < meta1.continuations; i++)
424 struct exfat_file_name name = {EXFAT_ENTRY_FILE_NAME, 0};
425 memcpy(name.name, node->name + (i - 1) * EXFAT_ENAME_MAX,
426 EXFAT_ENAME_MAX * sizeof(le16_t));
427 checksum = exfat_add_checksum(&name, checksum);
429 meta1.checksum = cpu_to_le16(checksum);
431 exfat_write_raw(&meta1, sizeof(meta1), meta1_offset, ef->fd);
432 exfat_write_raw(&meta2, sizeof(meta2), meta2_offset, ef->fd);
434 node->flags &= ~EXFAT_ATTRIB_DIRTY;