exfat: use diff structs 4 vol labels and filenames

... and rename the structs to reflect this.

* Volume labels contain up to 11 uint16s (11 2-byte UTF-16 characters).
* Filenames are packed into 1 to 17 structs of 15 uint16s each (for a total
  of 255 2-byte UTF-16 characters).
* Use 2 different packed structs in the exfat_entry union (same bytes, accessed
  with different structs) to access these 2 things.
* Remove a check that assumed the length returned the number of 2-byte UTF-16
  characters, i.e. the number of uint16s the string uses. It doesn't, it
  returns the number of characters contained in the string which might be 2 or
  4-bytes wide. We're doing the conversion wrong for 4-byte UTF-16 characters
  anyway, more on that later.
This commit is contained in:
John Scipione
2014-02-11 13:26:55 -05:00
parent 675878fcfe
commit 5b10d763d0
3 changed files with 12 additions and 13 deletions
@@ -208,9 +208,9 @@ DirectoryIterator::_GetNext(uchar* name, size_t* _nameLength, ino_t* _id,
visitor->VisitFileInfo(fCurrent); visitor->VisitFileInfo(fCurrent);
} else if (fCurrent->type == EXFAT_ENTRY_TYPE_FILENAME) { } else if (fCurrent->type == EXFAT_ENTRY_TYPE_FILENAME) {
TRACE("DirectoryIterator::_GetNext() Filename\n"); TRACE("DirectoryIterator::_GetNext() Filename\n");
memcpy((uint8*)name + nameIndex, fCurrent->label.name, memcpy((uint8*)name + nameIndex, fCurrent->file_name.name,
sizeof(fCurrent->label.name)); sizeof(fCurrent->file_name.name));
nameIndex += sizeof(fCurrent->label.name); nameIndex += sizeof(fCurrent->file_name.name);
name[nameIndex] = '\0'; name[nameIndex] = '\0';
chunkCount--; chunkCount--;
if (visitor != NULL) if (visitor != NULL)
@@ -30,14 +30,9 @@ get_volume_name(struct exfat_entry* entry, char* name, size_t length)
if (entry->type == EXFAT_ENTRY_TYPE_NOT_IN_USE) if (entry->type == EXFAT_ENTRY_TYPE_NOT_IN_USE)
name = ""; name = "";
else if (entry->type == EXFAT_ENTRY_TYPE_LABEL) { else if (entry->type == EXFAT_ENTRY_TYPE_LABEL) {
// UCS-2 can encode codepoints in the range U+0000 to U+FFFF status_t result
// UTF-8 needs at most 3 bytes to encode values in this range = unicode_to_utf8((const uchar*)entry->volume_label.name,
size_t utf8NameLength = entry->label.length * 3; entry->volume_label.length * 2, (uint8*)name, &length);
if (length < utf8NameLength)
return B_NAME_TOO_LONG;
status_t result = unicode_to_utf8((const uchar*)entry->label.name,
entry->label.length * 2, (uint8*)name, &utf8NameLength);
if (result != B_OK) if (result != B_OK)
return result; return result;
} else } else
@@ -104,14 +104,14 @@ struct exfat_entry {
uint8 length; uint8 length;
uint16 name[11]; uint16 name[11];
uint8 reserved[8]; uint8 reserved[8];
} _PACKED label; } _PACKED volume_label;
struct { struct {
uint8 chunkCount; uint8 chunkCount;
uint16 checksum; uint16 checksum;
uint16 flags; uint16 flags;
uint8 guid[16]; uint8 guid[16];
uint8 reserved[10]; uint8 reserved[10];
} _PACKED guid; } _PACKED volume_guid;
struct { struct {
uint8 reserved[3]; uint8 reserved[3];
uint32 checksum; uint32 checksum;
@@ -171,6 +171,10 @@ struct exfat_entry {
uint64 Size() const uint64 Size() const
{ return B_LENDIAN_TO_HOST_INT64(size1); } { return B_LENDIAN_TO_HOST_INT64(size1); }
} _PACKED file_info; } _PACKED file_info;
struct {
uint8 flags;
uint16 name[15];
} _PACKED file_name;
}; };
} _PACKED; } _PACKED;