OSDN Git Service

Move nodes tree manipulation code into separate functions.
[android-x86/external-exfat.git] / libexfat / node.c
1 /*
2  *  node.c
3  *  exFAT file system implementation library.
4  *
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.
8  */
9
10 #include "exfat.h"
11 #include <errno.h>
12 #include <string.h>
13 #include <inttypes.h>
14
15 /* on-disk nodes iterator */
16 struct iterator
17 {
18         cluster_t cluster;
19         off_t offset;
20         int contiguous;
21         char* chunk;
22 };
23
24 struct exfat_node* exfat_get_node(struct exfat_node* node)
25 {
26         /* if we switch to multi-threaded mode we will need atomic
27            increment here and atomic decrement in exfat_put_node() */
28         node->references++;
29         return node;
30 }
31
32 void exfat_put_node(struct exfat* ef, struct exfat_node* node)
33 {
34         if (--node->references < 0)
35         {
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);
39         }
40
41         if (node->references == 0)
42         {
43                 if (node->flags & EXFAT_ATTRIB_DIRTY)
44                         exfat_flush_node(ef, node);
45                 if (node->flags & EXFAT_ATTRIB_UNLINKED)
46                 {
47                         /* free all clusters and node structure itself */
48                         exfat_truncate(ef, node, 0);
49                         free(node);
50                 }
51                 if (ef->cmap.dirty)
52                         exfat_flush_cmap(ef);
53         }
54 }
55
56 static int opendir(struct exfat* ef, const struct exfat_node* dir,
57                 struct iterator* it)
58 {
59         if (!(dir->flags & EXFAT_ATTRIB_DIR))
60                 exfat_bug("not a directory");
61         it->cluster = dir->start_cluster;
62         it->offset = 0;
63         it->contiguous = IS_CONTIGUOUS(*dir);
64         it->chunk = malloc(CLUSTER_SIZE(*ef->sb));
65         if (it->chunk == NULL)
66         {
67                 exfat_error("out of memory");
68                 return -ENOMEM;
69         }
70         exfat_read_raw(it->chunk, CLUSTER_SIZE(*ef->sb),
71                         exfat_c2o(ef, it->cluster), ef->fd);
72         return 0;
73 }
74
75 static void closedir(struct iterator* it)
76 {
77         it->cluster = 0;
78         it->offset = 0;
79         it->contiguous = 0;
80         free(it->chunk);
81         it->chunk = NULL;
82 }
83
84 static int fetch_next_entry(struct exfat* ef, const struct exfat_node* parent,
85                 struct iterator* it)
86 {
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)
91         {
92                 it->cluster = exfat_next_cluster(ef, parent, it->cluster);
93                 if (CLUSTER_INVALID(it->cluster))
94                 {
95                         exfat_error("invalid cluster while reading directory");
96                         return 1;
97                 }
98                 exfat_read_raw(it->chunk, CLUSTER_SIZE(*ef->sb),
99                                 exfat_c2o(ef, it->cluster), ef->fd);
100         }
101         return 0;
102 }
103
104 static struct exfat_node* allocate_node(void)
105 {
106         struct exfat_node* node = malloc(sizeof(struct exfat_node));
107         if (node == NULL)
108         {
109                 exfat_error("failed to allocate node");
110                 return NULL;
111         }
112         memset(node, 0, sizeof(struct exfat_node));
113         return node;
114 }
115
116 static void init_node_meta1(struct exfat_node* node,
117                 const struct exfat_file* meta1)
118 {
119         node->flags = le16_to_cpu(meta1->attrib);
120         node->mtime = exfat_exfat2unix(meta1->mdate, meta1->mtime);
121         node->atime = exfat_exfat2unix(meta1->adate, meta1->atime);
122 }
123
124 static void init_node_meta2(struct exfat_node* node,
125                 const struct exfat_file_info* meta2)
126 {
127         node->size = le64_to_cpu(meta2->size);
128         node->start_cluster = le32_to_cpu(meta2->start_cluster);
129         node->fptr_cluster = node->start_cluster;
130         if (meta2->flag == EXFAT_FLAG_CONTIGUOUS)
131                 node->flags |= EXFAT_ATTRIB_CONTIGUOUS;
132 }
133
134 /*
135  * Reads one entry in directory at position pointed by iterator and fills
136  * node structure.
137  */
138 static int readdir(struct exfat* ef, const struct exfat_node* parent,
139                 struct exfat_node** node, struct iterator* it)
140 {
141         const struct exfat_entry* entry;
142         const struct exfat_file* file;
143         const struct exfat_file_info* file_info;
144         const struct exfat_file_name* file_name;
145         const struct exfat_upcase* upcase;
146         const struct exfat_bitmap* bitmap;
147         const struct exfat_label* label;
148         uint8_t continuations = 0;
149         le16_t* namep = NULL;
150         uint16_t reference_checksum = 0;
151         uint16_t actual_checksum = 0;
152
153         *node = NULL;
154
155         for (;;)
156         {
157                 /* every directory (even empty one) occupies at least one cluster and
158                    must contain EOD entry */
159                 entry = (const struct exfat_entry*)
160                                 (it->chunk + it->offset % CLUSTER_SIZE(*ef->sb));
161
162                 switch (entry->type)
163                 {
164                 case EXFAT_ENTRY_EOD:
165                         if (continuations != 0)
166                         {
167                                 exfat_error("expected %hhu continuations before EOD",
168                                                 continuations);
169                                 goto error;
170                         }
171                         return -ENOENT; /* that's OK, means end of directory */
172
173                 case EXFAT_ENTRY_FILE:
174                         if (continuations != 0)
175                         {
176                                 exfat_error("expected %hhu continuations before new entry",
177                                                 continuations);
178                                 goto error;
179                         }
180                         file = (const struct exfat_file*) entry;
181                         continuations = file->continuations;
182                         /* each file entry must have at least 2 continuations:
183                            info and name */
184                         if (continuations < 2)
185                         {
186                                 exfat_error("too few continuations (%hhu)", continuations);
187                                 return -EIO;
188                         }
189                         reference_checksum = le16_to_cpu(file->checksum);
190                         actual_checksum = exfat_start_checksum(file);
191                         *node = allocate_node();
192                         if (*node == NULL)
193                                 return -ENOMEM;
194                         /* new node has zero reference counter */
195                         (*node)->entry_cluster = it->cluster;
196                         (*node)->entry_offset = it->offset % CLUSTER_SIZE(*ef->sb);
197                         init_node_meta1(*node, file);
198                         namep = (*node)->name;
199                         break;
200
201                 case EXFAT_ENTRY_FILE_INFO:
202                         if (continuations < 2)
203                         {
204                                 exfat_error("unexpected continuation (%hhu)",
205                                                 continuations);
206                                 goto error;
207                         }
208                         file_info = (const struct exfat_file_info*) entry;
209                         init_node_meta2(*node, file_info);
210                         actual_checksum = exfat_add_checksum(entry, actual_checksum);
211                         /* There are two fields that contain file size. Maybe they plan
212                            to add compression support in the future and one of those
213                            fields is visible (uncompressed) size and the other is real
214                            (compressed) size. Anyway, currently it looks like exFAT does
215                            not support compression and both fields must be equal. */
216                         if (le64_to_cpu(file_info->real_size) != (*node)->size)
217                         {
218                                 exfat_error("real size does not equal to size "
219                                                 "(%"PRIu64" != %"PRIu64")",
220                                                 le64_to_cpu(file_info->real_size), (*node)->size);
221                                 goto error;
222                         }
223                         /* directories must be aligned on at cluster boundary */
224                         if (((*node)->flags & EXFAT_ATTRIB_DIR) &&
225                                 (*node)->size % CLUSTER_SIZE(*ef->sb) != 0)
226                         {
227                                 char buffer[EXFAT_NAME_MAX + 1];
228
229                                 exfat_get_name(*node, buffer, EXFAT_NAME_MAX);
230                                 exfat_error("directory `%s' has invalid size %"PRIu64" bytes",
231                                                 buffer, (*node)->size);
232                                 goto error;
233                         }
234                         --continuations;
235                         break;
236
237                 case EXFAT_ENTRY_FILE_NAME:
238                         if (continuations == 0)
239                         {
240                                 exfat_error("unexpected continuation");
241                                 goto error;
242                         }
243                         file_name = (const struct exfat_file_name*) entry;
244                         actual_checksum = exfat_add_checksum(entry, actual_checksum);
245
246                         memcpy(namep, file_name->name, EXFAT_ENAME_MAX * sizeof(le16_t));
247                         namep += EXFAT_ENAME_MAX;
248                         if (--continuations == 0)
249                         {
250                                 if (actual_checksum != reference_checksum)
251                                 {
252                                         exfat_error("invalid checksum (0x%hx != 0x%hx)",
253                                                         actual_checksum, reference_checksum);
254                                         return -EIO;
255                                 }
256                                 if (fetch_next_entry(ef, parent, it) != 0)
257                                         goto error;
258                                 return 0; /* entry completed */
259                         }
260                         break;
261
262                 case EXFAT_ENTRY_UPCASE:
263                         if (ef->upcase != NULL)
264                                 break;
265                         upcase = (const struct exfat_upcase*) entry;
266                         if (CLUSTER_INVALID(le32_to_cpu(upcase->start_cluster)))
267                         {
268                                 exfat_error("invalid cluster in upcase table");
269                                 return -EIO;
270                         }
271                         if (le64_to_cpu(upcase->size) == 0 ||
272                                 le64_to_cpu(upcase->size) > 0xffff * sizeof(uint16_t) ||
273                                 le64_to_cpu(upcase->size) % sizeof(uint16_t) != 0)
274                         {
275                                 exfat_error("bad upcase table size (%"PRIu64" bytes)",
276                                                 le64_to_cpu(upcase->size));
277                                 return -EIO;
278                         }
279                         ef->upcase = malloc(le64_to_cpu(upcase->size));
280                         if (ef->upcase == NULL)
281                         {
282                                 exfat_error("failed to allocate upcase table (%"PRIu64" bytes)",
283                                                 le64_to_cpu(upcase->size));
284                                 return -ENOMEM;
285                         }
286                         ef->upcase_chars = le64_to_cpu(upcase->size) / sizeof(le16_t);
287
288                         exfat_read_raw(ef->upcase, le64_to_cpu(upcase->size),
289                                         exfat_c2o(ef, le32_to_cpu(upcase->start_cluster)), ef->fd);
290                         break;
291
292                 case EXFAT_ENTRY_BITMAP:
293                         bitmap = (const struct exfat_bitmap*) entry;
294                         if (CLUSTER_INVALID(le32_to_cpu(bitmap->start_cluster)))
295                         {
296                                 exfat_error("invalid cluster in clusters bitmap");
297                                 return -EIO;
298                         }
299                         ef->cmap.size = le32_to_cpu(ef->sb->cluster_count) -
300                                 EXFAT_FIRST_DATA_CLUSTER;
301                         if (le64_to_cpu(bitmap->size) != (ef->cmap.size + 7) / 8)
302                         {
303                                 exfat_error("invalid bitmap size: %"PRIu64" (expected %u)",
304                                                 le64_to_cpu(bitmap->size), (ef->cmap.size + 7) / 8);
305                                 return -EIO;
306                         }
307                         ef->cmap.start_cluster = le32_to_cpu(bitmap->start_cluster);
308                         /* FIXME bitmap can be rather big, up to 512 MB */
309                         ef->cmap.chunk_size = ef->cmap.size;
310                         ef->cmap.chunk = malloc(le64_to_cpu(bitmap->size));
311                         if (ef->cmap.chunk == NULL)
312                         {
313                                 exfat_error("failed to allocate clusters map chunk "
314                                                 "(%"PRIu64" bytes)", le64_to_cpu(bitmap->size));
315                                 return -ENOMEM;
316                         }
317
318                         exfat_read_raw(ef->cmap.chunk, le64_to_cpu(bitmap->size),
319                                         exfat_c2o(ef, ef->cmap.start_cluster), ef->fd);
320                         break;
321
322                 case EXFAT_ENTRY_LABEL:
323                         label = (const struct exfat_label*) entry;
324                         if (label->length > EXFAT_ENAME_MAX)
325                         {
326                                 exfat_error("too long label (%hhu chars)", label->length);
327                                 return -EIO;
328                         }
329                         break;
330
331                 default:
332                         if (entry->type & EXFAT_ENTRY_VALID)
333                         {
334                                 exfat_error("unknown entry type 0x%hhu", entry->type);
335                                 goto error;
336                         }
337                         break;
338                 }
339
340                 if (fetch_next_entry(ef, parent, it) != 0)
341                         goto error;
342         }
343         /* we never reach here */
344
345 error:
346         free(*node);
347         *node = NULL;
348         return -EIO;
349 }
350
351 int exfat_cache_directory(struct exfat* ef, struct exfat_node* dir)
352 {
353         struct iterator it;
354         int rc;
355         struct exfat_node* node;
356         struct exfat_node* current = NULL;
357
358         if (dir->flags & EXFAT_ATTRIB_CACHED)
359                 return 0; /* already cached */
360
361         rc = opendir(ef, dir, &it);
362         if (rc != 0)
363                 return rc;
364         while ((rc = readdir(ef, dir, &node, &it)) == 0)
365         {
366                 node->parent = dir;
367                 if (current != NULL)
368                 {
369                         current->next = node;
370                         node->prev = current;
371                 }
372                 else
373                         dir->child = node;
374
375                 current = node;
376         }
377         closedir(&it);
378
379         if (rc != -ENOENT)
380         {
381                 /* rollback */
382                 for (current = dir->child; current; current = node)
383                 {
384                         node = current->next;
385                         free(current);
386                 }
387                 dir->child = NULL;
388                 return rc;
389         }
390
391         dir->flags |= EXFAT_ATTRIB_CACHED;
392         return 0;
393 }
394
395 static void reset_cache(struct exfat* ef, struct exfat_node* node)
396 {
397         struct exfat_node* child;
398         struct exfat_node* next;
399
400         for (child = node->child; child; child = next)
401         {
402                 reset_cache(ef, child);
403                 next = child->next;
404                 free(child);
405         }
406         if (node->references != 0)
407         {
408                 char buffer[EXFAT_NAME_MAX + 1];
409                 exfat_get_name(node, buffer, EXFAT_NAME_MAX);
410                 exfat_warn("non-zero reference counter (%d) for `%s'",
411                                 node->references, buffer);
412         }
413         while (node->references--)
414                 exfat_put_node(ef, node);
415         node->child = NULL;
416         node->flags &= ~EXFAT_ATTRIB_CACHED;
417 }
418
419 void exfat_reset_cache(struct exfat* ef)
420 {
421         reset_cache(ef, ef->root);
422 }
423
424 void next_entry(struct exfat* ef, const struct exfat_node* parent,
425                 cluster_t* cluster, off_t* offset)
426 {
427         if (*offset + sizeof(struct exfat_entry) == CLUSTER_SIZE(*ef->sb))
428         {
429                 /* next cluster cannot be invalid */
430                 *cluster = exfat_next_cluster(ef, parent, *cluster);
431                 *offset = 0;
432         }
433         else
434                 *offset += sizeof(struct exfat_entry);
435
436 }
437
438 void exfat_flush_node(struct exfat* ef, struct exfat_node* node)
439 {
440         cluster_t cluster;
441         off_t offset;
442         off_t meta1_offset, meta2_offset;
443         struct exfat_file meta1;
444         struct exfat_file_info meta2;
445
446         if (ef->ro)
447                 exfat_bug("unable to flush node to read-only FS");
448
449         if (node->parent == NULL)
450                 return; /* do not flush unlinked node */
451
452         cluster = node->entry_cluster;
453         offset = node->entry_offset;
454         meta1_offset = exfat_c2o(ef, cluster) + offset;
455         next_entry(ef, node->parent, &cluster, &offset);
456         meta2_offset = exfat_c2o(ef, cluster) + offset;
457
458         exfat_read_raw(&meta1, sizeof(meta1), meta1_offset, ef->fd);
459         if (meta1.type != EXFAT_ENTRY_FILE)
460                 exfat_bug("invalid type of meta1: 0x%hhx", meta1.type);
461         meta1.attrib = cpu_to_le16(node->flags);
462         exfat_unix2exfat(node->mtime, &meta1.mdate, &meta1.mtime);
463         exfat_unix2exfat(node->atime, &meta1.adate, &meta1.atime);
464
465         exfat_read_raw(&meta2, sizeof(meta2), meta2_offset, ef->fd);
466         if (meta2.type != EXFAT_ENTRY_FILE_INFO)
467                 exfat_bug("invalid type of meta2: 0x%hhx", meta2.type);
468         meta2.size = meta2.real_size = cpu_to_le64(node->size);
469         meta2.start_cluster = cpu_to_le32(node->start_cluster);
470         /* empty files must be marked as fragmented */
471         if (node->size != 0 && IS_CONTIGUOUS(*node))
472                 meta2.flag = EXFAT_FLAG_CONTIGUOUS;
473         else
474                 meta2.flag = EXFAT_FLAG_FRAGMENTED;
475         /* name hash remains unchanged, no need to recalculate it */
476
477         meta1.checksum = exfat_calc_checksum(&meta1, &meta2, node->name);
478
479         exfat_write_raw(&meta1, sizeof(meta1), meta1_offset, ef->fd);
480         exfat_write_raw(&meta2, sizeof(meta2), meta2_offset, ef->fd);
481
482         node->flags &= ~EXFAT_ATTRIB_DIRTY;
483 }
484
485 static void erase_entry(struct exfat* ef, struct exfat_node* node)
486 {
487         cluster_t cluster = node->entry_cluster;
488         off_t offset = node->entry_offset;
489         int name_entries = DIV_ROUND_UP(utf16_length(node->name), EXFAT_ENAME_MAX);
490         uint8_t entry_type;
491
492         entry_type = EXFAT_ENTRY_FILE & ~EXFAT_ENTRY_VALID;
493         exfat_write_raw(&entry_type, 1, exfat_c2o(ef, cluster) + offset, ef->fd);
494
495         next_entry(ef, node->parent, &cluster, &offset);
496         entry_type = EXFAT_ENTRY_FILE_INFO & ~EXFAT_ENTRY_VALID;
497         exfat_write_raw(&entry_type, 1, exfat_c2o(ef, cluster) + offset, ef->fd);
498
499         while (name_entries--)
500         {
501                 next_entry(ef, node->parent, &cluster, &offset);
502                 entry_type = EXFAT_ENTRY_FILE_NAME & ~EXFAT_ENTRY_VALID;
503                 exfat_write_raw(&entry_type, 1, exfat_c2o(ef, cluster) + offset,
504                                 ef->fd);
505         }
506 }
507
508 static void tree_detach(struct exfat_node* node)
509 {
510         if (node->prev)
511                 node->prev->next = node->next;
512         else /* this is the first node in the list */
513                 node->parent->child = node->next;
514         if (node->next)
515                 node->next->prev = node->prev;
516         node->parent = NULL;
517         node->prev = NULL;
518         node->next = NULL;
519 }
520
521 static void tree_attach(struct exfat_node* dir, struct exfat_node* node)
522 {
523         node->parent = dir;
524         if (dir->child)
525         {
526                 dir->child->prev = node;
527                 node->next = dir->child;
528         }
529         dir->child = node;
530 }
531
532 static void delete(struct exfat* ef, struct exfat_node* node)
533 {
534         erase_entry(ef, node);
535         exfat_update_mtime(node->parent);
536         tree_detach(node);
537         /* file clusters will be freed when node reference counter becomes 0 */
538         node->flags |= EXFAT_ATTRIB_UNLINKED;
539 }
540
541 int exfat_unlink(struct exfat* ef, struct exfat_node* node)
542 {
543         if (node->flags & EXFAT_ATTRIB_DIR)
544                 return -EISDIR;
545         delete(ef, node);
546         return 0;
547 }
548
549 int exfat_rmdir(struct exfat* ef, struct exfat_node* node)
550 {
551         if (!(node->flags & EXFAT_ATTRIB_DIR))
552                 return -ENOTDIR;
553         /* check that directory is empty */
554         exfat_cache_directory(ef, node);
555         if (node->child)
556                 return -ENOTEMPTY;
557         delete(ef, node);
558         return 0;
559 }
560
561 static int grow_directory(struct exfat* ef, struct exfat_node* dir,
562                 uint64_t asize, uint32_t difference)
563 {
564         return exfat_truncate(ef, dir,
565                         DIV_ROUND_UP(asize + difference, CLUSTER_SIZE(*ef->sb))
566                                 * CLUSTER_SIZE(*ef->sb));
567 }
568
569 static void write_eod(struct exfat* ef, struct exfat_node* dir,
570                 cluster_t cluster, off_t offset, int seek)
571 {
572         struct exfat_entry eod;
573
574         while (seek--)
575                 next_entry(ef, dir, &cluster, &offset);
576         memset(&eod, 0, sizeof(struct exfat_entry));
577         exfat_write_raw(&eod, sizeof(struct exfat_entry),
578                         exfat_c2o(ef, cluster) + offset, ef->fd);
579 }
580
581 static int find_slot(struct exfat* ef, struct exfat_node* dir,
582                 cluster_t* cluster, off_t* offset, int subentries)
583 {
584         struct iterator it;
585         int rc;
586         const struct exfat_entry* entry;
587         int contiguous = 0;
588
589         rc = opendir(ef, dir, &it);
590         if (rc != 0)
591                 return rc;
592         for (;;)
593         {
594                 if (contiguous == 0)
595                 {
596                         *cluster = it.cluster;
597                         *offset = it.offset % CLUSTER_SIZE(*ef->sb);
598                 }
599                 entry = (const struct exfat_entry*)
600                                 (it.chunk + it.offset % CLUSTER_SIZE(*ef->sb));
601                 if (entry->type == EXFAT_ENTRY_EOD)
602                 {
603                         rc = grow_directory(ef, dir,
604                                         it.offset + sizeof(struct exfat_entry), /* actual size */
605                                         (subentries - contiguous) * sizeof(struct exfat_entry));
606                         if (rc != 0)
607                         {
608                                 closedir(&it);
609                                 return rc;
610                         }
611                         write_eod(ef, dir, *cluster, *offset, subentries - contiguous);
612                         break;
613                 }
614                 if (entry->type & EXFAT_ENTRY_VALID)
615                         contiguous = 0;
616                 else
617                         contiguous++;
618                 if (contiguous == subentries)
619                         break;  /* suitable slot it found */
620                 if (fetch_next_entry(ef, dir, &it) != 0)
621                 {
622                         closedir(&it);
623                         return -EIO;
624                 }
625         }
626         closedir(&it);
627         return 0;
628 }
629
630 static int write_entry(struct exfat* ef, struct exfat_node* dir,
631                 const le16_t* name, cluster_t cluster, off_t offset, uint16_t attrib)
632 {
633         struct exfat_node* node;
634         struct exfat_file meta1;
635         struct exfat_file_info meta2;
636         const size_t name_length = utf16_length(name);
637         const int name_entries = DIV_ROUND_UP(name_length, EXFAT_ENAME_MAX);
638         int i;
639
640         node = allocate_node();
641         if (node == NULL)
642                 return -ENOMEM;
643         node->entry_cluster = cluster;
644         node->entry_offset = offset;
645         memcpy(node->name, name, name_length * sizeof(le16_t));
646
647         memset(&meta1, 0, sizeof(meta1));
648         meta1.type = EXFAT_ENTRY_FILE;
649         meta1.continuations = 1 + name_entries;
650         meta1.attrib = cpu_to_le16(attrib);
651         exfat_unix2exfat(time(NULL), &meta1.crdate, &meta1.crtime);
652         meta1.adate = meta1.mdate = meta1.crdate;
653         meta1.atime = meta1.mtime = meta1.crtime;
654         /* crtime_cs and mtime_cs contain addition to the time in centiseconds;
655            just ignore those fields because we operate with 2 sec resolution */
656
657         memset(&meta2, 0, sizeof(meta2));
658         meta2.type = EXFAT_ENTRY_FILE_INFO;
659         meta2.flag = EXFAT_FLAG_FRAGMENTED;
660         meta2.name_length = name_length;
661         meta2.name_hash = exfat_calc_name_hash(ef, node->name);
662         meta2.start_cluster = cpu_to_le32(EXFAT_CLUSTER_FREE);
663
664         meta1.checksum = exfat_calc_checksum(&meta1, &meta2, node->name);
665
666         exfat_write_raw(&meta1, sizeof(meta1), exfat_c2o(ef, cluster) + offset,
667                         ef->fd);
668         next_entry(ef, dir, &cluster, &offset);
669         exfat_write_raw(&meta2, sizeof(meta2), exfat_c2o(ef, cluster) + offset,
670                         ef->fd);
671         for (i = 0; i < name_entries; i++)
672         {
673                 struct exfat_file_name name_entry = {EXFAT_ENTRY_FILE_NAME, 0};
674                 memcpy(name_entry.name, node->name + i * EXFAT_ENAME_MAX,
675                                 EXFAT_ENAME_MAX * sizeof(le16_t));
676                 next_entry(ef, dir, &cluster, &offset);
677                 exfat_write_raw(&name_entry, sizeof(name_entry),
678                                 exfat_c2o(ef, cluster) + offset, ef->fd);
679         }
680
681         init_node_meta1(node, &meta1);
682         init_node_meta2(node, &meta2);
683
684         tree_attach(dir, node);
685         exfat_update_mtime(dir);
686         return 0;
687 }
688
689 static int create(struct exfat* ef, const char* path, uint16_t attrib)
690 {
691         struct exfat_node* dir;
692         cluster_t cluster = EXFAT_CLUSTER_BAD;
693         off_t offset = -1;
694         le16_t name[EXFAT_NAME_MAX + 1];
695         int rc;
696
697         /* FIXME filter name characters */
698
699         rc = exfat_split(ef, &dir, name, path);
700         if (rc != 0)
701                 return rc;
702
703         rc = find_slot(ef, dir, &cluster, &offset,
704                         2 + DIV_ROUND_UP(utf16_length(name), EXFAT_ENAME_MAX));
705         if (rc != 0)
706         {
707                 exfat_put_node(ef, dir);
708                 return rc;
709         }
710         rc = write_entry(ef, dir, name, cluster, offset, attrib);
711         exfat_put_node(ef, dir);
712         return rc;
713 }
714
715 int exfat_mknod(struct exfat* ef, const char* path)
716 {
717         return create(ef, path, EXFAT_ATTRIB_ARCH);
718 }
719
720 int exfat_mkdir(struct exfat* ef, const char* path)
721 {
722         int rc;
723         struct exfat_node* node;
724
725         rc = create(ef, path, EXFAT_ATTRIB_ARCH | EXFAT_ATTRIB_DIR);
726         if (rc != 0)
727                 return rc;
728         rc = exfat_lookup(ef, &node, path);
729         if (rc != 0)
730                 return 0;
731         /* directories always have at least one cluster */
732         rc = exfat_truncate(ef, node, CLUSTER_SIZE(*ef->sb));
733         if (rc != 0)
734         {
735                 delete(ef, node);
736                 exfat_put_node(ef, node);
737                 return rc;
738         }
739         exfat_put_node(ef, node);
740         return 0;
741 }
742
743 void exfat_utimes(struct exfat_node* node, const struct timespec tv[2])
744 {
745         node->atime = tv[0].tv_sec;
746         node->mtime = tv[1].tv_sec;
747         node->flags |= EXFAT_ATTRIB_DIRTY;
748 }
749
750 void exfat_update_atime(struct exfat_node* node)
751 {
752         node->atime = time(NULL);
753         node->flags |= EXFAT_ATTRIB_DIRTY;
754 }
755
756 void exfat_update_mtime(struct exfat_node* node)
757 {
758         node->mtime = time(NULL);
759         node->flags |= EXFAT_ATTRIB_DIRTY;
760 }