Android-x86
Fork

  • R/O
  • HTTP
  • SSH
  • HTTPS

external-exfat: コミット

external/exfat


コミットメタ情報

リビジョン9e02a1a31fdaf75b83b6e3eeb2c4c822220610dc (tree)
日時2017-01-16 15:29:08
作者relan <relan@user...>
コミッターrelan

ログメッセージ

Generic I/O for directories: switch find_slot().

変更サマリ

差分

--- a/libexfat/node.c
+++ b/libexfat/node.c
@@ -869,57 +869,87 @@ int exfat_rmdir(struct exfat* ef, struct exfat_node* node)
869869 return delete(ef, node);
870870 }
871871
872-static int grow_directory(struct exfat* ef, struct exfat_node* dir,
873- uint64_t asize, uint32_t difference)
872+static int check_slot(struct exfat* ef, struct exfat_node* dir, off_t offset,
873+ int n)
874874 {
875- return exfat_truncate(ef, dir,
876- DIV_ROUND_UP(asize + difference, CLUSTER_SIZE(*ef->sb))
877- * CLUSTER_SIZE(*ef->sb), true);
875+ struct exfat_entry entries[n];
876+ int rc;
877+ size_t i;
878+
879+ /* Root directory contains entries, that don't have any nodes associated
880+ with them (clusters bitmap, upper case table, label). We need to be
881+ careful not to overwrite them. */
882+ if (dir != ef->root)
883+ return 0;
884+
885+ rc = read_entries(ef, dir, entries, n, offset);
886+ if (rc != 0)
887+ return rc;
888+ for (i = 0; i < n; i++)
889+ if (entries[i].type & EXFAT_ENTRY_VALID)
890+ return -EINVAL;
891+ return 0;
878892 }
879893
880894 static int find_slot(struct exfat* ef, struct exfat_node* dir,
881- cluster_t* cluster, off_t* offset, int subentries)
895+ off_t* offset, int n)
882896 {
883- struct iterator it;
884- int rc;
885- const struct exfat_entry* entry;
897+ bitmap_t* dmap;
898+ struct exfat_node* p;
899+ size_t i;
886900 int contiguous = 0;
887901
888- rc = opendir(ef, dir, &it);
889- if (rc != 0)
890- return rc;
891- for (;;)
902+ if (!dir->is_cached)
903+ exfat_bug("directory is not cached");
904+
905+ /* build a bitmap of valid entries in the directory */
906+ dmap = calloc(BMAP_SIZE(dir->size / sizeof(struct exfat_entry)),
907+ sizeof(bitmap_t));
908+ if (dmap == NULL)
892909 {
893- if (contiguous == 0)
910+ exfat_error("failed to allocate directory bitmap (%"PRIu64")",
911+ dir->size / sizeof(struct exfat_entry));
912+ return -ENOMEM;
913+ }
914+ for (p = dir->child; p != NULL; p = p->next)
915+ for (i = 0; i < 1 + p->continuations; i++)
916+ BMAP_SET(dmap, p->entry_offset / sizeof(struct exfat_entry) + i);
917+
918+ /* find a slot in the directory entries bitmap */
919+ for (i = 0; i < dir->size / sizeof(struct exfat_entry); i++)
920+ {
921+ if (BMAP_GET(dmap, i) == 0)
894922 {
895- *cluster = it.cluster;
896- *offset = it.offset;
923+ if (contiguous++ == 0)
924+ *offset = (off_t) i * sizeof(struct exfat_entry);
925+ if (contiguous == n)
926+ /* suitable slot is found, check that it's not occupied */
927+ switch (check_slot(ef, dir, *offset, n))
928+ {
929+ case 0:
930+ free(dmap);
931+ return 0;
932+ case -EIO:
933+ free(dmap);
934+ return -EIO;
935+ case -EINVAL:
936+ /* slot is occupied, continue searching */
937+ contiguous = 0;
938+ break;
939+ }
897940 }
898- entry = get_entry_ptr(ef, &it);
899- if (entry->type & EXFAT_ENTRY_VALID)
900- contiguous = 0;
901941 else
902- contiguous++;
903- if (contiguous == subentries)
904- break; /* suitable slot is found */
905- if (it.offset + sizeof(struct exfat_entry) >= dir->size)
906- {
907- rc = grow_directory(ef, dir, dir->size,
908- (subentries - contiguous) * sizeof(struct exfat_entry));
909- if (rc != 0)
910- {
911- closedir(&it);
912- return rc;
913- }
914- }
915- if (!fetch_next_entry(ef, dir, &it))
916- {
917- closedir(&it);
918- return -EIO;
919- }
942+ contiguous = 0;
920943 }
921- closedir(&it);
922- return 0;
944+ free(dmap);
945+
946+ /* no suitable slots found, extend the directory */
947+ if (contiguous == 0)
948+ *offset = dir->size;
949+ return exfat_truncate(ef, dir,
950+ ROUND_UP(dir->size + sizeof(struct exfat_entry[n - contiguous]),
951+ CLUSTER_SIZE(*ef->sb)),
952+ true);
923953 }
924954
925955 static int commit_entry(struct exfat* ef, struct exfat_node* dir,
@@ -1000,7 +1030,7 @@ static int create(struct exfat* ef, const char* path, uint16_t attrib)
10001030 return -EEXIST;
10011031 }
10021032
1003- rc = find_slot(ef, dir, &cluster, &offset,
1033+ rc = find_slot(ef, dir, &offset,
10041034 2 + DIV_ROUND_UP(utf16_length(name), EXFAT_ENAME_MAX));
10051035 if (rc != 0)
10061036 {
@@ -1182,7 +1212,7 @@ int exfat_rename(struct exfat* ef, const char* old_path, const char* new_path)
11821212 exfat_put_node(ef, existing);
11831213 }
11841214
1185- rc = find_slot(ef, dir, &cluster, &offset,
1215+ rc = find_slot(ef, dir, &offset,
11861216 2 + DIV_ROUND_UP(utf16_length(name), EXFAT_ENAME_MAX));
11871217 if (rc != 0)
11881218 {
@@ -1248,7 +1278,6 @@ int exfat_set_label(struct exfat* ef, const char* label)
12481278 {
12491279 le16_t label_utf16[EXFAT_ENAME_MAX + 1];
12501280 int rc;
1251- cluster_t cluster;
12521281 off_t offset;
12531282 struct exfat_entry_label entry;
12541283
@@ -1259,7 +1288,7 @@ int exfat_set_label(struct exfat* ef, const char* label)
12591288
12601289 rc = find_label(ef, &offset);
12611290 if (rc == -ENOENT)
1262- rc = find_slot(ef, ef->root, &cluster, &offset, 1);
1291+ rc = find_slot(ef, ef->root, &offset, 1);
12631292 if (rc != 0)
12641293 return rc;
12651294
旧リポジトリブラウザで表示