diff --git a/src/add-ons/kernel/file_systems/exfat/Utility.cpp b/src/add-ons/kernel/file_systems/exfat/Utility.cpp index d89adcfc27..9a301ebfeb 100644 --- a/src/add-ons/kernel/file_systems/exfat/Utility.cpp +++ b/src/add-ons/kernel/file_systems/exfat/Utility.cpp @@ -1,11 +1,11 @@ /* - * Copyright 2001-2009, Axel Dörfler, axeld@pinc-software.de. + * Copyright 2011, Jérôme Duval, korli@users.berlios.de. * Copyright 2014 Haiku, Inc. All rights reserved. * * Distributed under the terms of the MIT License. * * Authors: - * Axel Dörfler, axeld@pinc-software.de + * Jérôme Duval, korli@users.berlios.de * John Scipione, jscipione@gmail.com */ @@ -22,29 +22,47 @@ status_t -volume_name(struct exfat_entry* entry, char* _name) +get_volume_name(struct exfat_entry* entry, char* name, size_t length) { - if (entry == NULL || _name == NULL) + if (entry == NULL || name == NULL) return B_BAD_VALUE; - if (entry->type == EXFAT_ENTRY_TYPE_NOT_IN_USE) { - const char* untitled = "Untitled"; - size_t length = strlen(untitled); - strncpy(_name, untitled, length); - if (strlen(_name) < length) - return B_NAME_TOO_LONG; - } else if (entry->type == EXFAT_ENTRY_TYPE_LABEL) { + if (entry->type == EXFAT_ENTRY_TYPE_NOT_IN_USE) + name = ""; + else if (entry->type == EXFAT_ENTRY_TYPE_LABEL) { // UCS-2 can encode codepoints in the range U+0000 to U+FFFF // UTF-8 needs at most 3 bytes to encode values in this range size_t utf8NameLength = entry->label.length * 3; - memset(_name, 0, utf8NameLength + 1); - // zero out the character array - unicode_to_utf8((const uchar*)entry->label.name, - entry->label.length * 2, (uint8*)_name, &utf8NameLength); - if (strlen(_name) < utf8NameLength) + 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) + return result; } else return B_NAME_NOT_FOUND; return B_OK; } + + +void +get_default_volume_name(off_t diskSize, char* name, size_t length) +{ + off_t divisor = 1ULL << 40; + char unit = 'T'; + if (diskSize < divisor) { + divisor = 1UL << 30; + unit = 'G'; + if (diskSize < divisor) { + divisor = 1UL << 20; + unit = 'M'; + } + } + + double size = double((10 * diskSize + divisor - 1) / divisor); + // %g in the kernel does not support precision... + + snprintf(name, length, "%g%ciB ExFAT Volume", size / 10, unit); +} diff --git a/src/add-ons/kernel/file_systems/exfat/Utility.h b/src/add-ons/kernel/file_systems/exfat/Utility.h index b4c9000ad7..2251f610b5 100644 --- a/src/add-ons/kernel/file_systems/exfat/Utility.h +++ b/src/add-ons/kernel/file_systems/exfat/Utility.h @@ -45,16 +45,31 @@ open_mode_to_access(int openMode) } -/*! Reads the volume name from an exfat entry and writes it to \a _name - as a UTF-8 char array. Writes "Untitled" The volume name is not set. - \returns A status code. - \retval B_OK Wrote the volume name successfully. - \retval B_BAD_VALUE \a entry or \a _name was \c NULL. - \retval B_NAME_NOT_FOUND Volume name was not found in this entry. - \retval B_NAME_TOO_LONG The passed in _name wasn't long enough to - fit the name. +/*! Reads the volume name from an exfat entry and writes it to + \a _name as a UTF-8 char array. + + Writes a blank string to \a name if the volume name is not set. + + \param entry The \a entry to look for the volume name in. + \param name The \a name array to fill out. + \param length The \a length of the name array in bytes. + + \returns A status code, \c B_OK on success or an error code otherwise. + \retval B_OK Wrote the volume name to \a name successfully. + \retval B_BAD_VALUE \a entry or \a name was \c NULL. + \retval B_NAME_NOT_FOUND Volume name was not found in this \a entry. + \retval B_NAME_TOO_LONG \a name wasn't long enough to fit the volume name. */ -status_t volume_name(struct exfat_entry* entry, char* _name); +status_t get_volume_name(struct exfat_entry* entry, char* name, size_t length); + + +/*! Writes a more or less descriptive volume name to \a name. + + \param diskSize The disk size in bytes + \param name The \a name array to fill out. + \param length The \a length of the name array in bytes. +*/ +void get_default_volume_name(off_t diskSize, char* name, size_t length); #endif // UTILITY_H diff --git a/src/add-ons/kernel/file_systems/exfat/Volume.cpp b/src/add-ons/kernel/file_systems/exfat/Volume.cpp index 7a633198ce..2868e8af6f 100644 --- a/src/add-ons/kernel/file_systems/exfat/Volume.cpp +++ b/src/add-ons/kernel/file_systems/exfat/Volume.cpp @@ -230,8 +230,8 @@ bool LabelVisitor::VisitLabel(struct exfat_entry* entry) { TRACE("LabelVisitor::VisitLabel()\n"); - char name[34]; - status_t result = volume_name(entry, name); + char name[B_FILE_NAME_LENGTH]; + status_t result = get_volume_name(entry, name, sizeof(name)); if (result != B_OK) return false; @@ -334,13 +334,6 @@ Volume::Mount(const char* deviceName, uint32 flags) fEntriesPerBlock = (fBlockSize / sizeof(struct exfat_entry)); // check if the device size is large enough to hold the file system - off_t diskSize; - status = opener.GetSize(&diskSize); - if (status != B_OK) - return status; - if (diskSize < (off_t)fSuperBlock.NumBlocks() << fSuperBlock.BlockShift()) - return B_BAD_VALUE; - fBlockCache = opener.InitCache(fSuperBlock.NumBlocks(), fBlockSize); if (fBlockCache == NULL) return B_ERROR; @@ -371,23 +364,9 @@ Volume::Mount(const char* deviceName, uint32 flags) iterator.Iterate(visitor); if (fName[0] == '\0') { - // generate a more or less descriptive volume name - off_t divisor = 1ULL << 40; - char unit = 'T'; - if (diskSize < divisor) { - divisor = 1UL << 30; - unit = 'G'; - if (diskSize < divisor) { - divisor = 1UL << 20; - unit = 'M'; - } - } - - double size = double((10 * diskSize + divisor - 1) / divisor); - // %g in the kernel does not support precision... - - snprintf(fName, sizeof(fName), "%g %cB ExFAT Volume", - size / 10, unit); + off_t deviceSize = (off_t)fSuperBlock.NumBlocks() + << fSuperBlock.BlockShift(); + get_default_volume_name(deviceSize, fName, sizeof(fName)); } return B_OK; diff --git a/src/add-ons/kernel/file_systems/exfat/Volume.h b/src/add-ons/kernel/file_systems/exfat/Volume.h index f6298852c4..8a546274f6 100644 --- a/src/add-ons/kernel/file_systems/exfat/Volume.h +++ b/src/add-ons/kernel/file_systems/exfat/Volume.h @@ -17,6 +17,8 @@ #include #include +#include + #include "exfat.h" #include "SplayTree.h" @@ -151,9 +153,7 @@ private: fs_volume* fFSVolume; int fDevice; exfat_super_block fSuperBlock; - char fName[34]; - // Max number of bytes needed is (11 * 3) + 1 for the \0, - // that is 11 UCS-2 characters converted to UTF-8. + char fName[B_FILE_NAME_LENGTH]; uint16 fFlags; uint32 fBlockSize; diff --git a/src/add-ons/kernel/file_systems/exfat/encodings.cpp b/src/add-ons/kernel/file_systems/exfat/encodings.cpp index 0393fab255..ac844dfc43 100644 --- a/src/add-ons/kernel/file_systems/exfat/encodings.cpp +++ b/src/add-ons/kernel/file_systems/exfat/encodings.cpp @@ -134,7 +134,7 @@ _lendian_unicode_to_utf8( *srcLen = srcCount; *dstLen = dstCount; dst[dstCount] = '\0'; - + return status; } @@ -174,7 +174,7 @@ _utf8_to_lendian_unicode( dst[dstCount++] = unicode >> 8; srcCount += UTF8 - ((uchar *)(src + srcCount)); - status = B_OK; + status = B_OK; } *srcLen = srcCount; @@ -217,4 +217,3 @@ status_t utf8_to_unicode(const char *utf8, uchar *uni, size_t *unilen) return result; } - diff --git a/src/add-ons/kernel/file_systems/exfat/kernel_interface.cpp b/src/add-ons/kernel/file_systems/exfat/kernel_interface.cpp index 112918db40..bda5b1ce8a 100644 --- a/src/add-ons/kernel/file_systems/exfat/kernel_interface.cpp +++ b/src/add-ons/kernel/file_systems/exfat/kernel_interface.cpp @@ -24,6 +24,7 @@ #include #include #include +#include #include #include "DirectoryIterator.h" @@ -46,7 +47,7 @@ struct identify_cookie { exfat_super_block super_block; - char name[34]; + char name[B_FILE_NAME_LENGTH]; }; @@ -77,7 +78,7 @@ iterative_io_finished_hook(void* cookie, io_request* request, status_t status, static float -exfat_identify_partition(int fd, partition_data* _partition, void** _cookie) +exfat_identify_partition(int fd, partition_data* partition, void** _cookie) { struct exfat_super_block superBlock; status_t status = Volume::Identify(fd, &superBlock); @@ -89,7 +90,7 @@ exfat_identify_partition(int fd, partition_data* _partition, void** _cookie) return -1; memcpy(&cookie->super_block, &superBlock, sizeof(exfat_super_block)); - memset(cookie->name, 0, 34); + memset(cookie->name, 0, sizeof(cookie->name)); // zero out volume name uint32 rootDirCluster = superBlock.RootDirCluster(); @@ -104,7 +105,8 @@ exfat_identify_partition(int fd, partition_data* _partition, void** _cookie) &entry, entrySize) == (ssize_t)entrySize; i++) { if (entry.type == EXFAT_ENTRY_TYPE_NOT_IN_USE || entry.type == EXFAT_ENTRY_TYPE_LABEL) { - if (volume_name(&entry, cookie->name) != B_OK) { + if (get_volume_name(&entry, cookie->name, sizeof(cookie->name)) + != B_OK) { delete cookie; return -1; } @@ -113,8 +115,8 @@ exfat_identify_partition(int fd, partition_data* _partition, void** _cookie) } if (cookie->name[0] == '\0') { - delete cookie; - return -1; + off_t deviceSize = (off_t)superBlock.NumBlocks() << superBlock.BlockShift(); + get_default_volume_name(deviceSize, cookie->name, sizeof(cookie->name)); } *_cookie = cookie; @@ -123,23 +125,23 @@ exfat_identify_partition(int fd, partition_data* _partition, void** _cookie) static status_t -exfat_scan_partition(int fd, partition_data* _partition, void* _cookie) +exfat_scan_partition(int fd, partition_data* partition, void* _cookie) { identify_cookie* cookie = (identify_cookie*)_cookie; - _partition->status = B_PARTITION_VALID; - _partition->flags |= B_PARTITION_FILE_SYSTEM; - _partition->content_size = cookie->super_block.NumBlocks() + partition->status = B_PARTITION_VALID; + partition->flags |= B_PARTITION_FILE_SYSTEM; + partition->content_size = cookie->super_block.NumBlocks() << cookie->super_block.BlockShift(); - _partition->block_size = 1 << cookie->super_block.BlockShift(); - _partition->content_name = strdup(cookie->name); + partition->block_size = 1 << cookie->super_block.BlockShift(); + partition->content_name = strdup(cookie->name); - return _partition->content_name != NULL ? B_OK : B_NO_MEMORY; + return partition->content_name != NULL ? B_OK : B_NO_MEMORY; } static void -exfat_free_identify_partition_cookie(partition_data* _partition, void* _cookie) +exfat_free_identify_partition_cookie(partition_data* partition, void* _cookie) { delete (identify_cookie*)_cookie; }