exfat: Set the mountpoint to same as volume name

Fixes #10501

* update copyright headers, attribute to Haiku, Inc. add authors
* volume_name gets filled out by a utility function in Utility.cpp
* update exfat_entry
  - rename name_label to just label
  - adjust volume_label to have 11 uint16 chars plus 8 uint8 reserved
  - add guid partition info
* Added a couple new entry type defines
* fName is 34 bytes long which fits the 11 3-byte UTF-8 chars and a \0
This commit is contained in:
John Scipione 2014-02-04 20:46:08 -05:00
parent c79381d32a
commit 762b846cf8
8 changed files with 175 additions and 33 deletions

View File

@ -208,9 +208,9 @@ DirectoryIterator::_GetNext(uchar* name, size_t* _nameLength, ino_t* _id,
visitor->VisitFileInfo(fCurrent);
} else if (fCurrent->type == EXFAT_ENTRY_TYPE_FILENAME) {
TRACE("DirectoryIterator::_GetNext() Filename\n");
memcpy((uint8*)name + nameIndex, fCurrent->name_label.name,
sizeof(fCurrent->name_label.name));
nameIndex += sizeof(fCurrent->name_label.name);
memcpy((uint8*)name + nameIndex, fCurrent->label.name,
sizeof(fCurrent->label.name));
nameIndex += sizeof(fCurrent->label.name);
name[nameIndex] = '\0';
chunkCount--;
if (visitor != NULL)

View File

@ -10,5 +10,6 @@ KernelAddon exfat :
encodings.cpp
Inode.cpp
kernel_interface.cpp
Utility.cpp
Volume.cpp
;

View File

@ -0,0 +1,50 @@
/*
* Copyright 2001-2009, Axel Dörfler, axeld@pinc-software.de.
* Copyright 2014 Haiku, Inc. All rights reserved.
*
* Distributed under the terms of the MIT License.
*
* Authors:
* Axel Dörfler, axeld@pinc-software.de
* John Scipione, jscipione@gmail.com
*/
#include "Utility.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <Errors.h>
#include "encodings.h"
status_t
volume_name(struct exfat_entry* entry, char* _name)
{
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) {
// 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)
return B_NAME_TOO_LONG;
} else
return B_NAME_NOT_FOUND;
return B_OK;
}

View File

@ -1,6 +1,12 @@
/*
* Copyright 2001-2009, Axel Dörfler, axeld@pinc-software.de.
* This file may be used under the terms of the MIT License.
* Copyright 2014 Haiku, Inc. All rights reserved.
*
* Distributed under the terms of the MIT License.
*
* Authors:
* Axel Dörfler, axeld@pinc-software.de
* John Scipione, jscipione@gmail.com
*/
#ifndef UTILITY_H
#define UTILITY_H
@ -38,4 +44,17 @@ open_mode_to_access(int openMode)
return R_OK | W_OK;
}
/*! 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.
*/
status_t volume_name(struct exfat_entry* entry, char* _name);
#endif // UTILITY_H

View File

@ -1,7 +1,14 @@
/*
* Copyright 2011, Jérôme Duval, korli@users.berlios.de.
* Copyright 2008-2010, Axel Dörfler, axeld@pinc-software.de.
* This file may be used under the terms of the MIT License.
* 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
*/
@ -11,6 +18,7 @@
#include "Volume.h"
#include <errno.h>
#include <unistd.h>
#include <new>
#include <stdio.h>
#include <stdlib.h>
@ -22,8 +30,8 @@
#include <util/AutoLock.h>
#include "CachedBlock.h"
#include "encodings.h"
#include "Inode.h"
#include "Utility.h"
//#define TRACE_EXFAT
@ -222,11 +230,12 @@ bool
LabelVisitor::VisitLabel(struct exfat_entry* entry)
{
TRACE("LabelVisitor::VisitLabel()\n");
char utfName[30];
size_t utfLength = 30;
unicode_to_utf8((const uchar*)entry->name_label.name,
entry->name_label.length * 2, (uint8*)utfName, &utfLength);
fVolume->SetName(utfName);
char name[34];
status_t result = volume_name(entry, name);
if (result != B_OK)
return false;
fVolume->SetName(name);
return true;
}

View File

@ -1,7 +1,14 @@
/*
* Copyright 2011, Jérôme Duval, korli@users.berlios.de.
* Copyright 2008-2010, Axel Dörfler, axeld@pinc-software.de.
* This file may be used under the terms of the MIT License.
* 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
*/
#ifndef VOLUME_H
#define VOLUME_H
@ -144,7 +151,9 @@ private:
fs_volume* fFSVolume;
int fDevice;
exfat_super_block fSuperBlock;
char fName[32];
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.
uint16 fFlags;
uint32 fBlockSize;

View File

@ -1,6 +1,12 @@
/*
* 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:
* Jérôme Duval, korli@users.berlios.de
* John Scipione, jscipione@gmail.com
*/
#ifndef EXFAT_H
#define EXFAT_H
@ -75,10 +81,12 @@ struct exfat_super_block {
#define EXFAT_SUPER_BLOCK_MAGIC "EXFAT "
#define EXFAT_ENTRY_TYPE_NOT_IN_USE 0x03
#define EXFAT_ENTRY_TYPE_BITMAP 0x81
#define EXFAT_ENTRY_TYPE_UPPERCASE 0x82
#define EXFAT_ENTRY_TYPE_LABEL 0x83
#define EXFAT_ENTRY_TYPE_FILE 0x85
#define EXFAT_ENTRY_TYPE_GUID 0xa0
#define EXFAT_ENTRY_TYPE_FILEINFO 0xc0
#define EXFAT_ENTRY_TYPE_FILENAME 0xc1
#define EXFAT_CLUSTER_END 0xffffffff
@ -94,8 +102,16 @@ struct exfat_entry {
union {
struct {
uint8 length;
char name[30];
} _PACKED name_label;
uint16 name[11];
uint8 reserved[8];
} _PACKED label;
struct {
uint8 chunkCount;
uint16 checksum;
uint16 flags;
uint8 guid[16];
uint8 reserved[10];
} _PACKED guid;
struct {
uint8 reserved[3];
uint32 checksum;

View File

@ -1,14 +1,24 @@
/*
* Copyright 2008-2010, Axel Dörfler, axeld@pinc-software.de.
* Copyright 2011, Jérôme Duval, korli@users.berlios.de.
* Copyright 2008, Axel Dörfler, axeld@pinc-software.de.
* This file may be used under the terms of the MIT License.
* 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
*/
#include <dirent.h>
#include <unistd.h>
#include <util/kernel_cpp.h>
#include <string.h>
#include <new>
#include <AutoDeleter.h>
#include <fs_cache.h>
#include <fs_info.h>
@ -36,6 +46,7 @@
struct identify_cookie {
exfat_super_block super_block;
char name[34];
};
@ -66,15 +77,45 @@ 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)
{
exfat_super_block superBlock;
struct exfat_super_block superBlock;
status_t status = Volume::Identify(fd, &superBlock);
if (status != B_OK)
return -1;
identify_cookie *cookie = new identify_cookie;
identify_cookie* cookie = new (std::nothrow)identify_cookie;
if (cookie == NULL)
return -1;
memcpy(&cookie->super_block, &superBlock, sizeof(exfat_super_block));
memset(cookie->name, 0, 34);
// zero out volume name
uint32 rootDirCluster = superBlock.RootDirCluster();
uint32 blockSize = 1 << superBlock.BlockShift();
uint32 clusterSize = blockSize << superBlock.BlocksPerClusterShift();
uint64 rootDirectoryOffset = (uint64)(EXFAT_SUPER_BLOCK_OFFSET
+ superBlock.FirstDataBlock() * blockSize
+ (rootDirCluster - 2) * clusterSize);
struct exfat_entry entry;
size_t entrySize = sizeof(struct exfat_entry);
for (uint32 i = 0; read_pos(fd, rootDirectoryOffset + i * entrySize,
&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) {
delete cookie;
return -1;
}
break;
}
}
if (cookie->name[0] == '\0') {
delete cookie;
return -1;
}
*_cookie = cookie;
return 0.8f;
@ -82,21 +123,18 @@ 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;
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();
// TODO volume name isn't in the superblock
partition->content_name = strdup(cookie->super_block.filesystem);
if (partition->content_name == NULL)
return B_NO_MEMORY;
_partition->block_size = 1 << cookie->super_block.BlockShift();
_partition->content_name = strdup(cookie->name);
return B_OK;
return _partition->content_name != NULL ? B_OK : B_NO_MEMORY;
}