From fd70236249f38ffd8fb186398ab1defaf5e55afe Mon Sep 17 00:00:00 2001 From: relan Date: Fri, 21 Jan 2011 20:54:34 +0000 Subject: [PATCH] Add functions that get and set volume label. --- libexfat/exfat.h | 4 +++ libexfat/node.c | 74 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 78 insertions(+) diff --git a/libexfat/exfat.h b/libexfat/exfat.h index 5481917..66ed078 100644 --- a/libexfat/exfat.h +++ b/libexfat/exfat.h @@ -85,6 +85,8 @@ struct exfat int dirty; } cmap; + char label[EXFAT_ENAME_MAX * 6 + 1]; /* a character can occupy up to + 6 bytes in UTF-8 */ void* zero_block; int dmask, fmask; uid_t uid; @@ -178,6 +180,8 @@ int exfat_rename(struct exfat* ef, const char* old_path, const char* new_path); void exfat_utimes(struct exfat_node* node, const struct timespec tv[2]); void exfat_update_atime(struct exfat_node* node); void exfat_update_mtime(struct exfat_node* node); +const char* exfat_get_label(struct exfat* ef); +int exfat_set_label(struct exfat* ef, const char* label); int exfat_mount(struct exfat* ef, const char* spec, const char* options); void exfat_unmount(struct exfat* ef); diff --git a/libexfat/node.c b/libexfat/node.c index 19bee9c..965c12b 100644 --- a/libexfat/node.c +++ b/libexfat/node.c @@ -348,6 +348,9 @@ static int readdir(struct exfat* ef, const struct exfat_node* parent, exfat_error("too long label (%hhu chars)", label->length); return -EIO; } + if (utf16_to_utf8(ef->label, label->name, + sizeof(ef->label), EXFAT_ENAME_MAX) != 0) + return -EIO; break; default: @@ -937,3 +940,74 @@ void exfat_update_mtime(struct exfat_node* node) node->mtime = time(NULL); node->flags |= EXFAT_ATTRIB_DIRTY; } + +const char* exfat_get_label(struct exfat* ef) +{ + return ef->label; +} + +static int find_label(struct exfat* ef, cluster_t* cluster, off_t* offset) +{ + struct iterator it; + int rc; + const struct exfat_entry* entry; + + rc = opendir(ef, ef->root, &it); + if (rc != 0) + return rc; + + for (;;) + { + entry = (const struct exfat_entry*) + (it.chunk + it.offset % CLUSTER_SIZE(*ef->sb)); + + if (entry->type == EXFAT_ENTRY_EOD) + { + closedir(&it); + return -ENOENT; + } + if (entry->type == EXFAT_ENTRY_LABEL) + { + *cluster = it.cluster; + *offset = it.offset; + closedir(&it); + return 0; + } + + if (fetch_next_entry(ef, ef->root, &it) != 0) + { + closedir(&it); + return -EIO; + } + } +} + +int exfat_set_label(struct exfat* ef, const char* label) +{ + le16_t label_utf16[EXFAT_ENAME_MAX + 1]; + int rc; + cluster_t cluster; + off_t offset; + struct exfat_entry_label entry; + + memset(label_utf16, 0, sizeof(label_utf16)); + rc = utf8_to_utf16(label_utf16, label, EXFAT_ENAME_MAX, strlen(label)); + if (rc != 0) + return rc; + + rc = find_label(ef, &cluster, &offset); + if (rc == -ENOENT) + rc = find_slot(ef, ef->root, &cluster, &offset, 1); + if (rc != 0) + return rc; + + entry.type = EXFAT_ENTRY_LABEL; + entry.length = utf16_length(label_utf16); + memcpy(entry.name, label_utf16, sizeof(entry.name)); + if (entry.length == 0) + entry.type ^= EXFAT_ENTRY_VALID; + + exfat_write_raw(&entry, sizeof(struct exfat_entry_label), + co2o(ef, cluster, offset), ef->fd); + return 0; +} -- 2.11.0