Implementation of the fs_shell for ExFAT.
Change-Id: I93533c746e7b52b2a5e46bf6209f871258d11df0 Reviewed-on: https://review.haiku-os.org/c/haiku/+/10476 Reviewed-by: Muhammad Fawad Shah <[email protected]> Reviewed-by: Raghav Sharma <[email protected]> Reviewed-by: Adrien Destugues <[email protected]>
This commit is contained in:
committed by
Adrien Destugues
parent
3fa3499c82
commit
a3da1bbe35
@@ -0,0 +1,34 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2014 Jonathan Schleifer <[email protected]>
|
||||||
|
* Copyright 2014 Haiku, Inc. All rights reserved.
|
||||||
|
*
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*
|
||||||
|
* Authors:
|
||||||
|
* Jonathan Schleifer, [email protected]
|
||||||
|
* John Scipione, [email protected]
|
||||||
|
*/
|
||||||
|
#ifndef FSSH_CONVERT_UTF_H
|
||||||
|
#define FSSH_CONVERT_UTF_H
|
||||||
|
|
||||||
|
#include "fssh_api_wrapper.h"
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C"
|
||||||
|
{
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
ssize_t utf16le_to_utf8(const uint16* source, size_t sourceCodeUnitCount,
|
||||||
|
char* target, size_t targetLength);
|
||||||
|
|
||||||
|
ssize_t utf16be_to_utf8(const uint16* source, size_t sourceCodeUnitCount,
|
||||||
|
char* target, size_t targetLength);
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#endif // CONVERT_UTF_H
|
||||||
@@ -7,7 +7,6 @@
|
|||||||
|
|
||||||
//! interface for the block cache
|
//! interface for the block cache
|
||||||
|
|
||||||
#include <fs_cache.h>
|
|
||||||
|
|
||||||
#include "Volume.h"
|
#include "Volume.h"
|
||||||
|
|
||||||
|
|||||||
@@ -11,11 +11,6 @@
|
|||||||
|
|
||||||
|
|
||||||
#include "DirectoryIterator.h"
|
#include "DirectoryIterator.h"
|
||||||
|
|
||||||
#include <stdlib.h>
|
|
||||||
|
|
||||||
#include <util/convertutf.h>
|
|
||||||
|
|
||||||
#include "Inode.h"
|
#include "Inode.h"
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -15,6 +15,7 @@
|
|||||||
#include "CachedBlock.h"
|
#include "CachedBlock.h"
|
||||||
#include "exfat.h"
|
#include "exfat.h"
|
||||||
|
|
||||||
|
|
||||||
class Inode;
|
class Inode;
|
||||||
|
|
||||||
class EntryVisitor {
|
class EntryVisitor {
|
||||||
|
|||||||
@@ -6,11 +6,6 @@
|
|||||||
|
|
||||||
|
|
||||||
#include "Inode.h"
|
#include "Inode.h"
|
||||||
|
|
||||||
#include <real_time_clock.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
|
|
||||||
#include "CachedBlock.h"
|
#include "CachedBlock.h"
|
||||||
#include "DataStream.h"
|
#include "DataStream.h"
|
||||||
#include "Utility.h"
|
#include "Utility.h"
|
||||||
@@ -223,8 +218,16 @@ void
|
|||||||
Inode::_GetTimespec(uint16 date, uint16 time, struct timespec ×pec) const
|
Inode::_GetTimespec(uint16 date, uint16 time, struct timespec ×pec) const
|
||||||
{
|
{
|
||||||
static int32 tzoffset = -1; /* in minutes */
|
static int32 tzoffset = -1; /* in minutes */
|
||||||
if (tzoffset == -1)
|
#ifdef _KERNEL_MODE
|
||||||
tzoffset = get_timezone_offset() / 60;
|
tzoffset = static_cast<int32>(get_timezone_offset());
|
||||||
|
#elif defined USER
|
||||||
|
time_t localTime;
|
||||||
|
time(&localTime);
|
||||||
|
|
||||||
|
struct tm localTm;
|
||||||
|
localtime_r(&localTime, &localTm);
|
||||||
|
tzoffset = localTm.tm_gmtoff;
|
||||||
|
#endif
|
||||||
|
|
||||||
time_t days = daze[(date >> 5) & 15] + ((date >> 9) + 10) * 365
|
time_t days = daze[(date >> 5) & 15] + ((date >> 9) + 10) * 365
|
||||||
+ leaps((date >> 9) + 10, ((date >> 5) & 15) - 1) + (date & 31) -1;
|
+ leaps((date >> 9) + 10, ((date >> 5) & 15) - 1) + (date & 31) -1;
|
||||||
|
|||||||
@@ -7,15 +7,10 @@
|
|||||||
#define INODE_H
|
#define INODE_H
|
||||||
|
|
||||||
|
|
||||||
#include <fs_cache.h>
|
|
||||||
#include <lock.h>
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
#include <util/SplayTree.h>
|
|
||||||
|
|
||||||
#include "DirectoryIterator.h"
|
#include "DirectoryIterator.h"
|
||||||
#include "exfat.h"
|
#include "exfat.h"
|
||||||
#include "Volume.h"
|
#include "Volume.h"
|
||||||
|
#include "system_dependencies.h"
|
||||||
|
|
||||||
|
|
||||||
//#define TRACE_EXFAT
|
//#define TRACE_EXFAT
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
SubDir HAIKU_TOP src add-ons kernel file_systems exfat ;
|
SubDir HAIKU_TOP src add-ons kernel file_systems exfat ;
|
||||||
|
UsePrivateKernelHeaders ;
|
||||||
|
UsePrivateHeaders kernel ;
|
||||||
UsePrivateHeaders shared storage ;
|
UsePrivateHeaders shared storage ;
|
||||||
UsePrivateHeaders file_systems ;
|
UsePrivateHeaders file_systems ;
|
||||||
UsePrivateKernelHeaders ;
|
|
||||||
|
|
||||||
KernelAddon exfat :
|
KernelAddon exfat :
|
||||||
DataStream.cpp
|
DataStream.cpp
|
||||||
|
|||||||
@@ -12,14 +12,6 @@
|
|||||||
|
|
||||||
#include "Utility.h"
|
#include "Utility.h"
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
#include <Errors.h>
|
|
||||||
|
|
||||||
#include <util/convertutf.h>
|
|
||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
get_volume_name(struct exfat_entry* entry, char* name, size_t length)
|
get_volume_name(struct exfat_entry* entry, char* name, size_t length)
|
||||||
|
|||||||
@@ -13,6 +13,7 @@
|
|||||||
|
|
||||||
|
|
||||||
#include "exfat.h"
|
#include "exfat.h"
|
||||||
|
#include "system_dependencies.h"
|
||||||
|
|
||||||
|
|
||||||
enum inode_type {
|
enum inode_type {
|
||||||
|
|||||||
@@ -16,19 +16,6 @@
|
|||||||
|
|
||||||
|
|
||||||
#include "Volume.h"
|
#include "Volume.h"
|
||||||
|
|
||||||
#include <errno.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <new>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
#include <fs_cache.h>
|
|
||||||
#include <fs_volume.h>
|
|
||||||
|
|
||||||
#include <util/AutoLock.h>
|
|
||||||
|
|
||||||
#include "CachedBlock.h"
|
#include "CachedBlock.h"
|
||||||
#include "DeviceOpener.h"
|
#include "DeviceOpener.h"
|
||||||
#include "Inode.h"
|
#include "Inode.h"
|
||||||
|
|||||||
@@ -14,13 +14,8 @@
|
|||||||
#define VOLUME_H
|
#define VOLUME_H
|
||||||
|
|
||||||
|
|
||||||
#include <lock.h>
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
#include <StorageDefs.h>
|
|
||||||
#include <util/SplayTree.h>
|
|
||||||
|
|
||||||
#include "exfat.h"
|
#include "exfat.h"
|
||||||
|
#include "system_dependencies.h"
|
||||||
|
|
||||||
|
|
||||||
struct node_key {
|
struct node_key {
|
||||||
|
|||||||
@@ -12,11 +12,7 @@
|
|||||||
#define EXFAT_H
|
#define EXFAT_H
|
||||||
|
|
||||||
|
|
||||||
#include <sys/stat.h>
|
#include "system_dependencies.h"
|
||||||
|
|
||||||
#include <ByteOrder.h>
|
|
||||||
#include <fs_interface.h>
|
|
||||||
#include <KernelExport.h>
|
|
||||||
|
|
||||||
|
|
||||||
typedef uint64 fileblock_t; // file block number
|
typedef uint64 fileblock_t; // file block number
|
||||||
|
|||||||
@@ -12,27 +12,13 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
#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>
|
|
||||||
#include <io_requests.h>
|
|
||||||
#include <NodeMonitor.h>
|
|
||||||
#include <StorageDefs.h>
|
|
||||||
#include <util/AutoLock.h>
|
|
||||||
#include <file_systems/fs_ops_support.h>
|
|
||||||
|
|
||||||
#include "DirectoryIterator.h"
|
#include "DirectoryIterator.h"
|
||||||
#include "exfat.h"
|
#include "exfat.h"
|
||||||
#include "Inode.h"
|
#include "Inode.h"
|
||||||
#include "Utility.h"
|
#include "Utility.h"
|
||||||
|
|
||||||
|
#include <file_systems/fs_ops_support.h>
|
||||||
|
|
||||||
|
|
||||||
//#define TRACE_EXFAT
|
//#define TRACE_EXFAT
|
||||||
#ifdef TRACE_EXFAT
|
#ifdef TRACE_EXFAT
|
||||||
@@ -158,6 +144,7 @@ static status_t
|
|||||||
exfat_mount(fs_volume* _volume, const char* device, uint32 flags,
|
exfat_mount(fs_volume* _volume, const char* device, uint32 flags,
|
||||||
const char* args, ino_t* _rootID)
|
const char* args, ino_t* _rootID)
|
||||||
{
|
{
|
||||||
|
TRACE("exfat_mount(): Trying to mount\n");
|
||||||
Volume* volume = new(std::nothrow) Volume(_volume);
|
Volume* volume = new(std::nothrow) Volume(_volume);
|
||||||
if (volume == NULL)
|
if (volume == NULL)
|
||||||
return B_NO_MEMORY;
|
return B_NO_MEMORY;
|
||||||
@@ -312,7 +299,7 @@ exfat_io(fs_volume* _volume, fs_vnode* _node, void* _cookie,
|
|||||||
Volume* volume = (Volume*)_volume->private_volume;
|
Volume* volume = (Volume*)_volume->private_volume;
|
||||||
Inode* inode = (Inode*)_node->private_node;
|
Inode* inode = (Inode*)_node->private_node;
|
||||||
|
|
||||||
#ifndef EXFAT_SHELL
|
#ifndef FS_SHELL
|
||||||
if (io_request_is_write(request) && volume->IsReadOnly()) {
|
if (io_request_is_write(request) && volume->IsReadOnly()) {
|
||||||
notify_io_request(request, B_READ_ONLY_DEVICE);
|
notify_io_request(request, B_READ_ONLY_DEVICE);
|
||||||
return B_READ_ONLY_DEVICE;
|
return B_READ_ONLY_DEVICE;
|
||||||
@@ -320,7 +307,7 @@ exfat_io(fs_volume* _volume, fs_vnode* _node, void* _cookie,
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (inode->FileCache() == NULL) {
|
if (inode->FileCache() == NULL) {
|
||||||
#ifndef EXFAT_SHELL
|
#ifndef FS_SHELL
|
||||||
notify_io_request(request, B_BAD_VALUE);
|
notify_io_request(request, B_BAD_VALUE);
|
||||||
#endif
|
#endif
|
||||||
return B_BAD_VALUE;
|
return B_BAD_VALUE;
|
||||||
|
|||||||
@@ -0,0 +1,64 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2018, Your Name <your@email.address>
|
||||||
|
* All rights reserved. Distributed under the terms of the MIT license.
|
||||||
|
*/
|
||||||
|
#ifndef _SYSTEM_DEPENDENCIES_H
|
||||||
|
#define _SYSTEM_DEPENDENCIES_H
|
||||||
|
|
||||||
|
#ifdef FS_SHELL
|
||||||
|
// This needs to be included before the fs_shell wrapper
|
||||||
|
|
||||||
|
#include "fssh_api_wrapper.h"
|
||||||
|
#include "fssh_auto_deleter.h"
|
||||||
|
#include "fssh_convertutf.h"
|
||||||
|
|
||||||
|
#include <util/SplayTree.h>
|
||||||
|
|
||||||
|
#else // !FS_SHELL
|
||||||
|
|
||||||
|
#include <AutoDeleter.h>
|
||||||
|
#include <util/AutoLock.h>
|
||||||
|
#include <util/convertutf.h>
|
||||||
|
#include <util/DoublyLinkedList.h>
|
||||||
|
#include <util/kernel_cpp.h>
|
||||||
|
#include <util/SinglyLinkedList.h>
|
||||||
|
#include <util/Stack.h>
|
||||||
|
#include <util/SplayTree.h>
|
||||||
|
|
||||||
|
|
||||||
|
#include <ByteOrder.h>
|
||||||
|
//#include <uuid.h>
|
||||||
|
|
||||||
|
#include <dirent.h>
|
||||||
|
#include <driver_settings.h>
|
||||||
|
#include "Debug.h"
|
||||||
|
#include <Drivers.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <Errors.h>
|
||||||
|
#include <fs_attr.h>
|
||||||
|
#include <fs_cache.h>
|
||||||
|
#include <fs_index.h>
|
||||||
|
#include <fs_info.h>
|
||||||
|
#include <fs_interface.h>
|
||||||
|
#include <fs_query.h>
|
||||||
|
#include <fs_volume.h>
|
||||||
|
#include <io_requests.h>
|
||||||
|
#include <kernel.h>
|
||||||
|
#include <KernelExport.h>
|
||||||
|
#include <lock.h>
|
||||||
|
#include <new>
|
||||||
|
#include <NodeMonitor.h>
|
||||||
|
#include <real_time_clock.h>
|
||||||
|
#include <SupportDefs.h>
|
||||||
|
#include <StorageDefs.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <tracing.h>
|
||||||
|
#include <TypeConstants.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#endif // !FS_SHELL
|
||||||
|
|
||||||
|
#endif // _SYSTEM_DEPENDENCIES
|
||||||
@@ -3,6 +3,7 @@ SubDir HAIKU_TOP src tests add-ons kernel file_systems ;
|
|||||||
HaikuSubInclude bfs ;
|
HaikuSubInclude bfs ;
|
||||||
HaikuSubInclude btrfs ;
|
HaikuSubInclude btrfs ;
|
||||||
HaikuSubInclude cdda ;
|
HaikuSubInclude cdda ;
|
||||||
|
HaikuSubInclude exfat ;
|
||||||
HaikuSubInclude iso9660 ;
|
HaikuSubInclude iso9660 ;
|
||||||
HaikuSubInclude shared ;
|
HaikuSubInclude shared ;
|
||||||
HaikuSubInclude udf ;
|
HaikuSubInclude udf ;
|
||||||
|
|||||||
@@ -0,0 +1,3 @@
|
|||||||
|
SubDir HAIKU_TOP src tests add-ons kernel file_systems exfat ;
|
||||||
|
|
||||||
|
SubInclude HAIKU_TOP src tests add-ons kernel file_systems exfat exfat_shell ;
|
||||||
@@ -0,0 +1,78 @@
|
|||||||
|
SubDir HAIKU_TOP src tests add-ons kernel file_systems exfat exfat_shell ;
|
||||||
|
|
||||||
|
SEARCH_SOURCE += [ FDirName $(HAIKU_TOP) src add-ons kernel file_systems exfat ] ;
|
||||||
|
|
||||||
|
# prevent inclusion of HaikuBuildCompatibility.h and _BSD_SOURCE headers
|
||||||
|
DEFINES += HAIKU_BUILD_COMPATIBILITY_H __STRICT_ANSI__ ;
|
||||||
|
|
||||||
|
# set some additional defines
|
||||||
|
{
|
||||||
|
local defines =
|
||||||
|
FS_SHELL
|
||||||
|
;
|
||||||
|
|
||||||
|
defines = [ FDefines $(defines) ] ;
|
||||||
|
|
||||||
|
local c++flags = ;
|
||||||
|
|
||||||
|
SubDirCcFlags $(defines) -Wno-multichar ;
|
||||||
|
SubDirC++Flags $(defines) $(c++flags) -Wno-multichar -fno-rtti ;
|
||||||
|
}
|
||||||
|
|
||||||
|
# platform specific libraries
|
||||||
|
local fsShellCommandLibs ;
|
||||||
|
if ! $(HOST_PLATFORM_HAIKU_COMPATIBLE) {
|
||||||
|
fsShellCommandLibs = $(HOST_NETWORK_LIBS) ;
|
||||||
|
}
|
||||||
|
|
||||||
|
UseHeaders [ FDirName $(HAIKU_TOP) headers build ] : true ;
|
||||||
|
UseHeaders [ FDirName $(HAIKU_TOP) headers os storage ] : true ;
|
||||||
|
|
||||||
|
if ! $(HOST_PLATFORM_HAIKU_COMPATIBLE) {
|
||||||
|
UseHeaders [ FDirName $(HAIKU_TOP) headers build os ] : true ;
|
||||||
|
UseHeaders [ FDirName $(HAIKU_TOP) headers build os support ] : true ;
|
||||||
|
}
|
||||||
|
|
||||||
|
UsePrivateKernelHeaders ;
|
||||||
|
UsePrivateHeaders shared storage fs_shell ;
|
||||||
|
UsePrivateHeaders file_systems ;
|
||||||
|
UseHeaders [ FDirName $(HAIKU_TOP) headers private ] : true ;
|
||||||
|
UseHeaders [ FDirName $(HAIKU_TOP) src tools fs_shell ] ;
|
||||||
|
UseHeaders [ FDirName $(HAIKU_TOP) src add-ons kernel file_systems shared ] : true ;
|
||||||
|
|
||||||
|
local exfatSource =
|
||||||
|
DataStream.cpp
|
||||||
|
DeviceOpener.cpp
|
||||||
|
DirectoryIterator.cpp
|
||||||
|
kernel_interface.cpp
|
||||||
|
Inode.cpp
|
||||||
|
Volume.cpp
|
||||||
|
Utility.cpp
|
||||||
|
|
||||||
|
;
|
||||||
|
|
||||||
|
BuildPlatformMergeObject <build>exfat_shell.o : $(exfatSource) ;
|
||||||
|
|
||||||
|
BuildPlatformMain <build>exfat_shell
|
||||||
|
:
|
||||||
|
:
|
||||||
|
<build>exfat_shell.o
|
||||||
|
<build>fs_shell.a $(HOST_LIBSUPC++) $(HOST_LIBSTDC++)
|
||||||
|
$(HOST_LIBROOT) $(fsShellCommandLibs)
|
||||||
|
;
|
||||||
|
|
||||||
|
BuildPlatformMain <build>exfat_fuse
|
||||||
|
:
|
||||||
|
:
|
||||||
|
<build>exfat_shell.o
|
||||||
|
<build>fuse_module.a
|
||||||
|
$(HOST_LIBSUPC++) $(HOST_LIBSTDC++)
|
||||||
|
$(HOST_STATIC_LIBROOT) $(fsShellCommandLibs) fuse
|
||||||
|
;
|
||||||
|
|
||||||
|
SEARCH on [ FGristFiles $(utilitySources) ]
|
||||||
|
+= [ FDirName $(HAIKU_TOP) src system kernel util ] ;
|
||||||
|
SEARCH on [ FGristFiles QueryParserUtils.cpp ]
|
||||||
|
+= [ FDirName $(HAIKU_TOP) src add-ons kernel file_systems shared ] ;
|
||||||
|
SEARCH on [ FGristFiles DeviceOpener.cpp ]
|
||||||
|
+= [ FDirName $(HAIKU_TOP) src add-ons kernel file_systems shared ] ;
|
||||||
@@ -35,6 +35,7 @@ local kernelEmulationSources =
|
|||||||
block_cache.cpp
|
block_cache.cpp
|
||||||
byte_order.cpp
|
byte_order.cpp
|
||||||
command_cp.cpp
|
command_cp.cpp
|
||||||
|
convertutf.cpp
|
||||||
disk_device_manager.cpp
|
disk_device_manager.cpp
|
||||||
driver_settings.cpp
|
driver_settings.cpp
|
||||||
errno.cpp
|
errno.cpp
|
||||||
|
|||||||
@@ -0,0 +1,130 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2014 Jonathan Schleifer <js@webkeks.org>
|
||||||
|
* Copyright 2014 Haiku, Inc. All rights reserved.
|
||||||
|
*
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*
|
||||||
|
* Authors:
|
||||||
|
* Jonathan Schleifer, js@webkeks.org
|
||||||
|
* John Scipione, jscipione@gmail.com
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include "fssh_convertutf.h"
|
||||||
|
|
||||||
|
|
||||||
|
static inline size_t
|
||||||
|
glyph_length(uint32 glyph)
|
||||||
|
{
|
||||||
|
if (glyph < 0x80)
|
||||||
|
return 1;
|
||||||
|
else if (glyph < 0x800)
|
||||||
|
return 2;
|
||||||
|
else if (glyph < 0x10000)
|
||||||
|
return 3;
|
||||||
|
else if (glyph < 0x110000)
|
||||||
|
return 4;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
encode_glyph(uint32 glyph, size_t glyphLength, char* buffer)
|
||||||
|
{
|
||||||
|
if (glyphLength == 1) {
|
||||||
|
*buffer = glyph;
|
||||||
|
} else if (glyphLength == 2) {
|
||||||
|
*buffer++ = 0xC0 | (glyph >> 6);
|
||||||
|
*buffer = 0x80 | (glyph & 0x3F);
|
||||||
|
} else if (glyphLength == 3) {
|
||||||
|
*buffer++ = 0xE0 | (glyph >> 12);
|
||||||
|
*buffer++ = 0x80 | (glyph >> 6 & 0x3F);
|
||||||
|
*buffer = 0x80 | (glyph & 0x3F);
|
||||||
|
} else if (glyphLength == 4) {
|
||||||
|
*buffer++ = 0xF0 | (glyph >> 18);
|
||||||
|
*buffer++ = 0x80 | (glyph >> 12 & 0x3F);
|
||||||
|
*buffer++ = 0x80 | (glyph >> 6 & 0x3F);
|
||||||
|
*buffer = 0x80 | (glyph & 0x3F);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static ssize_t
|
||||||
|
utf16_to_utf8(const uint16* source, size_t sourceCodeUnitCount, char* target,
|
||||||
|
size_t targetLength, bool isLittleEndian)
|
||||||
|
{
|
||||||
|
if (source == NULL || sourceCodeUnitCount == 0
|
||||||
|
|| target == NULL || targetLength == 0) {
|
||||||
|
return B_BAD_VALUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
ssize_t outLength = 0;
|
||||||
|
|
||||||
|
for (size_t i = 0; i < sourceCodeUnitCount; i++) {
|
||||||
|
uint32 glyph = isLittleEndian
|
||||||
|
? B_LENDIAN_TO_HOST_INT32(source[i])
|
||||||
|
: B_BENDIAN_TO_HOST_INT32(source[i]);
|
||||||
|
|
||||||
|
if ((glyph & 0xFC00) == 0xDC00) {
|
||||||
|
// missing high surrogate
|
||||||
|
return B_BAD_VALUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((glyph & 0xFC00) == 0xD800) {
|
||||||
|
if (sourceCodeUnitCount <= i + 1) {
|
||||||
|
// high surrogate at end of string
|
||||||
|
return B_BAD_VALUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32 low = isLittleEndian
|
||||||
|
? B_LENDIAN_TO_HOST_INT32(source[i + 1])
|
||||||
|
: B_BENDIAN_TO_HOST_INT32(source[i + 1]);
|
||||||
|
if ((low & 0xFC00) != 0xDC00) {
|
||||||
|
// missing low surrogate
|
||||||
|
return B_BAD_VALUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
glyph = (((glyph & 0x3FF) << 10) | (low & 0x3FF)) + 0x10000;
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t glyphLength = glyph_length(glyph);
|
||||||
|
if (glyphLength == 0)
|
||||||
|
return B_BAD_VALUE;
|
||||||
|
else if (outLength + glyphLength >= targetLength
|
||||||
|
|| outLength + glyphLength >= B_FILE_NAME_LENGTH) {
|
||||||
|
// NUL terminate the string so the caller can use the
|
||||||
|
// abbreviated version in this case. Since the length
|
||||||
|
// isn't returned the caller will need to call strlen()
|
||||||
|
// to get the length of the string.
|
||||||
|
target[outLength] = '\0';
|
||||||
|
return B_NAME_TOO_LONG;
|
||||||
|
}
|
||||||
|
|
||||||
|
encode_glyph(glyph, glyphLength, target + outLength);
|
||||||
|
outLength += glyphLength;
|
||||||
|
}
|
||||||
|
|
||||||
|
target[outLength] = '\0';
|
||||||
|
|
||||||
|
return outLength;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
ssize_t
|
||||||
|
utf16le_to_utf8(const uint16* source, size_t sourceCodeUnitCount,
|
||||||
|
char* target, size_t targetLength)
|
||||||
|
{
|
||||||
|
return utf16_to_utf8(source, sourceCodeUnitCount, target, targetLength,
|
||||||
|
true);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
ssize_t
|
||||||
|
utf16be_to_utf8(const uint16* source, size_t sourceCodeUnitCount,
|
||||||
|
char* target, size_t targetLength)
|
||||||
|
{
|
||||||
|
return utf16_to_utf8(source, sourceCodeUnitCount, target, targetLength,
|
||||||
|
false);
|
||||||
|
}
|
||||||
@@ -191,14 +191,12 @@ init_module(module *module)
|
|||||||
module->state = MODULE_INIT;
|
module->state = MODULE_INIT;
|
||||||
|
|
||||||
// init module
|
// init module
|
||||||
|
|
||||||
TRACE(("initializing module %s (at %p)... \n", module->name, module->info->std_ops));
|
TRACE(("initializing module %s (at %p)... \n", module->name, module->info->std_ops));
|
||||||
if (module->info->std_ops != NULL)
|
if (module->info->std_ops != NULL)
|
||||||
status = module->info->std_ops(FSSH_B_MODULE_INIT);
|
status = module->info->std_ops(FSSH_B_MODULE_INIT);
|
||||||
else
|
else
|
||||||
status = FSSH_B_OK;
|
status = FSSH_B_OK;
|
||||||
TRACE(("...done (%s)\n", strerror(status)));
|
TRACE(("...done (%s)\n", strerror(status)));
|
||||||
|
|
||||||
if (status >= FSSH_B_OK)
|
if (status >= FSSH_B_OK)
|
||||||
module->state = MODULE_READY;
|
module->state = MODULE_READY;
|
||||||
else {
|
else {
|
||||||
|
|||||||
Reference in New Issue
Block a user