mirror of
https://review.haiku-os.org/haiku
synced 2025-01-31 18:56:49 +01:00
exfat: fix problems with hrev46820
* Set the size of the volume name member var to B_FILE_NAME_LENGTH which is the max width of a volume name according to the BeBook and the Support Kit code. We'll deal with trying to stuff the volume name back into the exfat volume label later. * Rename volume_name() to get_volume_name() * Pass the name string length into get_volume_name() and use it to avoid buffer overrun. * Fill name with a blank string if volume has no label. * Don't memset the name with zeros before doing the conversion from Unicode to UTF-8, the conversion function will make sure the result is NUL-terminated if it returns B_OK. * Also check the return value of the Unicode conversion function and return an error if it fails. * Add get_default_volume_name() method to Utility.cpp which is used to fill out the default volume name in the case volume name is blank. e.g. 32GiB ExFAT Volume. This now applies to both the volume name and mount point. * Use non-metric prefixes for default volume name, e.g. MiB, GiB, TiB * For an unset volume name fill the volume name with an empty string. * Remove the leading underscore from _name and _partition parameters * Replace size constants with sizeof() calls * Remove Axel from the copyright statement in Utility.cpp, he had nothing to do with it, add Jérôme (aka korli) because he wrote the code for get_default_volume_name() (was in Volumes.cpp) * Remove some trailing spaces from encodings.cpp Thanks Axel.
This commit is contained in:
parent
88e24cf64f
commit
dae266a8a4
@ -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);
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -17,6 +17,8 @@
|
||||
#include <lock.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <StorageDefs.h>
|
||||
|
||||
#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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -24,6 +24,7 @@
|
||||
#include <fs_info.h>
|
||||
#include <io_requests.h>
|
||||
#include <NodeMonitor.h>
|
||||
#include <StorageDefs.h>
|
||||
#include <util/AutoLock.h>
|
||||
|
||||
#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;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user