X-Git-Url: http://git.osdn.net/view?a=blobdiff_plain;f=libexfat%2Fnode.c;h=44f4ae320009015b83c2677a2abf03f0b599ea09;hb=cf962cdfdd7fe80ae8dac93d689c90cc55350a2a;hp=a1f9b1770af1d4f1bc865577175b2d1671166c93;hpb=13f2af30a74201d3ced2bba2ef6feebeed09c962;p=android-x86%2Fexternal-exfat.git diff --git a/libexfat/node.c b/libexfat/node.c index a1f9b17..44f4ae3 100644 --- a/libexfat/node.c +++ b/libexfat/node.c @@ -222,6 +222,7 @@ static void init_node_meta1(struct exfat_node* node, const struct exfat_entry_meta1* meta1) { node->attrib = le16_to_cpu(meta1->attrib); + node->continuations = meta1->continuations; node->mtime = exfat_exfat2unix(meta1->mdate, meta1->mtime, meta1->mtime_cs); /* there is no centiseconds field for atime */ @@ -780,42 +781,36 @@ int exfat_flush_node(struct exfat* ef, struct exfat_node* node) return exfat_flush(ef); } -static bool erase_entry(struct exfat* ef, struct exfat_node* node) +static int erase_entries(struct exfat* ef, struct exfat_node* dir, int n, + off_t offset) { - cluster_t cluster = node->entry_cluster; - off_t offset = node->entry_offset; - int name_entries = DIV_ROUND_UP(utf16_length(node->name), EXFAT_ENAME_MAX); - uint8_t entry_type; + struct exfat_entry entries[n]; + int rc; + int i; - entry_type = EXFAT_ENTRY_FILE & ~EXFAT_ENTRY_VALID; - if (exfat_pwrite(ef->dev, &entry_type, 1, co2o(ef, cluster, offset)) < 0) - { - exfat_error("failed to erase meta1 entry"); - return false; - } + rc = read_entries(ef, dir, entries, n, offset); + if (rc != 0) + return rc; + for (i = 0; i < n; i++) + entries[i].type &= ~EXFAT_ENTRY_VALID; + return write_entries(ef, dir, entries, n, offset); +} - if (!next_entry(ef, node->parent, &cluster, &offset)) - return false; - entry_type = EXFAT_ENTRY_FILE_INFO & ~EXFAT_ENTRY_VALID; - if (exfat_pwrite(ef->dev, &entry_type, 1, co2o(ef, cluster, offset)) < 0) - { - exfat_error("failed to erase meta2 entry"); - return false; - } +static int erase_node(struct exfat* ef, struct exfat_node* node) +{ + int rc; - while (name_entries--) + exfat_get_node(node->parent); + rc = erase_entries(ef, node->parent, 1 + node->continuations, + node->entry_offset); + if (rc != 0) { - if (!next_entry(ef, node->parent, &cluster, &offset)) - return false; - entry_type = EXFAT_ENTRY_FILE_NAME & ~EXFAT_ENTRY_VALID; - if (exfat_pwrite(ef->dev, &entry_type, 1, - co2o(ef, cluster, offset)) < 0) - { - exfat_error("failed to erase name entry"); - return false; - } + exfat_put_node(ef, node->parent); + return rc; } - return true; + rc = exfat_flush_node(ef, node->parent); + exfat_put_node(ef, node->parent); + return rc; } static int shrink_directory(struct exfat* ef, struct exfat_node* dir, @@ -870,12 +865,12 @@ static int delete(struct exfat* ef, struct exfat_node* node) int rc; exfat_get_node(parent); - if (!erase_entry(ef, node)) + rc = erase_node(ef, node); + if (rc != 0) { exfat_put_node(ef, parent); - return -EIO; + return rc; } - exfat_update_mtime(parent); tree_detach(node); rc = shrink_directory(ef, parent, deleted_offset); node->is_unlinked = true; @@ -885,6 +880,7 @@ static int delete(struct exfat* ef, struct exfat_node* node) exfat_put_node(ef, parent); return rc; } + exfat_update_mtime(parent); rc = exfat_flush_node(ef, parent); exfat_put_node(ef, parent); return rc; @@ -969,73 +965,58 @@ static int commit_entry(struct exfat* ef, struct exfat_node* dir, const le16_t* name, cluster_t cluster, off_t offset, uint16_t attrib) { struct exfat_node* node; - struct exfat_entry_meta1 meta1; - struct exfat_entry_meta2 meta2; const size_t name_length = utf16_length(name); const int name_entries = DIV_ROUND_UP(name_length, EXFAT_ENAME_MAX); + struct exfat_entry entries[2 + name_entries]; + struct exfat_entry_meta1* meta1 = (struct exfat_entry_meta1*) &entries[0]; + struct exfat_entry_meta2* meta2 = (struct exfat_entry_meta2*) &entries[1]; int i; + int rc; - node = allocate_node(); - if (node == NULL) - return -ENOMEM; - node->entry_cluster = cluster; - node->entry_offset = offset; - memcpy(node->name, name, name_length * sizeof(le16_t)); + memset(entries, 0, sizeof(struct exfat_entry[2])); - memset(&meta1, 0, sizeof(meta1)); - meta1.type = EXFAT_ENTRY_FILE; - meta1.continuations = 1 + name_entries; - meta1.attrib = cpu_to_le16(attrib); - exfat_unix2exfat(time(NULL), &meta1.crdate, &meta1.crtime, - &meta1.crtime_cs); - meta1.adate = meta1.mdate = meta1.crdate; - meta1.atime = meta1.mtime = meta1.crtime; - meta1.mtime_cs = meta1.crtime_cs; /* there is no atime_cs */ - - memset(&meta2, 0, sizeof(meta2)); - meta2.type = EXFAT_ENTRY_FILE_INFO; - meta2.flags = EXFAT_FLAG_ALWAYS1; - meta2.name_length = name_length; - meta2.name_hash = exfat_calc_name_hash(ef, node->name, name_length); - meta2.start_cluster = cpu_to_le32(EXFAT_CLUSTER_FREE); + meta1->type = EXFAT_ENTRY_FILE; + meta1->continuations = 1 + name_entries; + meta1->attrib = cpu_to_le16(attrib); + exfat_unix2exfat(time(NULL), &meta1->crdate, &meta1->crtime, + &meta1->crtime_cs); + meta1->adate = meta1->mdate = meta1->crdate; + meta1->atime = meta1->mtime = meta1->crtime; + meta1->mtime_cs = meta1->crtime_cs; /* there is no atime_cs */ - meta1.checksum = exfat_calc_checksum(&meta1, &meta2, node->name); + meta2->type = EXFAT_ENTRY_FILE_INFO; + meta2->flags = EXFAT_FLAG_ALWAYS1; + meta2->name_length = name_length; + meta2->name_hash = exfat_calc_name_hash(ef, name, name_length); + meta2->start_cluster = cpu_to_le32(EXFAT_CLUSTER_FREE); + + meta1->checksum = exfat_calc_checksum(meta1, meta2, name); - if (exfat_pwrite(ef->dev, &meta1, sizeof(meta1), - co2o(ef, cluster, offset)) < 0) - { - exfat_error("failed to write meta1 entry"); - return -EIO; - } - if (!next_entry(ef, dir, &cluster, &offset)) - return -EIO; - if (exfat_pwrite(ef->dev, &meta2, sizeof(meta2), - co2o(ef, cluster, offset)) < 0) - { - exfat_error("failed to write meta2 entry"); - return -EIO; - } for (i = 0; i < name_entries; i++) { - struct exfat_entry_name name_entry = {EXFAT_ENTRY_FILE_NAME, 0}; - memcpy(name_entry.name, node->name + i * EXFAT_ENAME_MAX, - MIN(EXFAT_ENAME_MAX, EXFAT_NAME_MAX - i * EXFAT_ENAME_MAX) * - sizeof(le16_t)); - if (!next_entry(ef, dir, &cluster, &offset)) - return -EIO; - if (exfat_pwrite(ef->dev, &name_entry, sizeof(name_entry), - co2o(ef, cluster, offset)) < 0) - { - exfat_error("failed to write name entry"); - return -EIO; - } + struct exfat_entry_name* name_entry; + + name_entry = (struct exfat_entry_name*) &entries[2 + i]; + name_entry->type = EXFAT_ENTRY_FILE_NAME; + name_entry->__unknown = 0; + memcpy(name_entry->name, name + i * EXFAT_ENAME_MAX, + EXFAT_ENAME_MAX * sizeof(le16_t)); } - init_node_meta1(node, &meta1); - init_node_meta2(node, &meta2); + rc = write_entries(ef, dir, entries, 2 + name_entries, offset); + if (rc != 0) + return rc; + + node = allocate_node(); + if (node == NULL) + return -ENOMEM; + node->entry_cluster = cluster; + node->entry_offset = offset; + memcpy(node->name, name, name_length * sizeof(le16_t)); + init_node_meta1(node, meta1); + init_node_meta2(node, meta2); tree_attach(dir, node); - exfat_update_mtime(dir); return 0; } @@ -1071,6 +1052,7 @@ static int create(struct exfat* ef, const char* path, uint16_t attrib) exfat_put_node(ef, dir); return rc; } + exfat_update_mtime(dir); rc = exfat_flush_node(ef, dir); exfat_put_node(ef, dir); return rc; @@ -1121,6 +1103,7 @@ static int rename_entry(struct exfat* ef, struct exfat_node* dir, off_t old_offset = node->entry_offset; const size_t name_length = utf16_length(name); const int name_entries = DIV_ROUND_UP(name_length, EXFAT_ENAME_MAX); + int rc; int i; if (exfat_pread(ef->dev, &meta1, sizeof(meta1), @@ -1142,11 +1125,13 @@ static int rename_entry(struct exfat* ef, struct exfat_node* dir, meta2.name_length = name_length; meta1.checksum = exfat_calc_checksum(&meta1, &meta2, name); - if (!erase_entry(ef, node)) - return -EIO; + rc = erase_node(ef, node); + if (rc != 0) + return rc; node->entry_cluster = new_cluster; node->entry_offset = new_offset; + node->continuations = 1 + name_entries; if (exfat_pwrite(ef->dev, &meta1, sizeof(meta1), co2o(ef, new_cluster, new_offset)) < 0) @@ -1300,36 +1285,19 @@ const char* exfat_get_label(struct exfat* ef) return ef->label; } -static int find_label(struct exfat* ef, cluster_t* cluster, off_t* offset) +static int find_label(struct exfat* ef, off_t* offset) { - struct iterator it; + struct exfat_entry entry; int rc; - rc = opendir(ef, ef->root, &it); - if (rc != 0) - return rc; - - for (;;) + for (*offset = 0; ; *offset += sizeof(entry)) { - if (it.offset >= ef->root->size) - { - closedir(&it); - return -ENOENT; - } + rc = read_entries(ef, ef->root, &entry, 1, *offset); + if (rc != 0) + return rc; - if (get_entry_ptr(ef, &it)->type == EXFAT_ENTRY_LABEL) - { - *cluster = it.cluster; - *offset = it.offset; - closedir(&it); + if (entry.type == EXFAT_ENTRY_LABEL) return 0; - } - - if (!fetch_next_entry(ef, ef->root, &it)) - { - closedir(&it); - return -EIO; - } } } @@ -1346,7 +1314,7 @@ int exfat_set_label(struct exfat* ef, const char* label) if (rc != 0) return rc; - rc = find_label(ef, &cluster, &offset); + rc = find_label(ef, &offset); if (rc == -ENOENT) rc = find_slot(ef, ef->root, &cluster, &offset, 1); if (rc != 0) @@ -1358,12 +1326,10 @@ int exfat_set_label(struct exfat* ef, const char* label) if (entry.length == 0) entry.type ^= EXFAT_ENTRY_VALID; - if (exfat_pwrite(ef->dev, &entry, sizeof(struct exfat_entry_label), - co2o(ef, cluster, offset)) < 0) - { - exfat_error("failed to write label entry"); - return -EIO; - } + rc = write_entries(ef, ef->root, (struct exfat_entry*) &entry, 1, offset); + if (rc != 0) + return rc; + strcpy(ef->label, label); return 0; }