diff --git a/headers/private/fs_shell/fssh_convertutf.h b/headers/private/fs_shell/fssh_convertutf.h new file mode 100644 index 0000000000..7fd352831c --- /dev/null +++ b/headers/private/fs_shell/fssh_convertutf.h @@ -0,0 +1,34 @@ +/* + * Copyright 2014 Jonathan Schleifer + * 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 + */ +#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 diff --git a/src/add-ons/kernel/file_systems/exfat/CachedBlock.h b/src/add-ons/kernel/file_systems/exfat/CachedBlock.h index 09fec08abb..a077be1559 100644 --- a/src/add-ons/kernel/file_systems/exfat/CachedBlock.h +++ b/src/add-ons/kernel/file_systems/exfat/CachedBlock.h @@ -7,7 +7,6 @@ //! interface for the block cache -#include #include "Volume.h" diff --git a/src/add-ons/kernel/file_systems/exfat/DirectoryIterator.cpp b/src/add-ons/kernel/file_systems/exfat/DirectoryIterator.cpp index cb97e5190f..4e174e5d8f 100644 --- a/src/add-ons/kernel/file_systems/exfat/DirectoryIterator.cpp +++ b/src/add-ons/kernel/file_systems/exfat/DirectoryIterator.cpp @@ -11,11 +11,6 @@ #include "DirectoryIterator.h" - -#include - -#include - #include "Inode.h" diff --git a/src/add-ons/kernel/file_systems/exfat/DirectoryIterator.h b/src/add-ons/kernel/file_systems/exfat/DirectoryIterator.h index daa3ea53a7..0cf80ab2dc 100644 --- a/src/add-ons/kernel/file_systems/exfat/DirectoryIterator.h +++ b/src/add-ons/kernel/file_systems/exfat/DirectoryIterator.h @@ -15,6 +15,7 @@ #include "CachedBlock.h" #include "exfat.h" + class Inode; class EntryVisitor { diff --git a/src/add-ons/kernel/file_systems/exfat/Inode.cpp b/src/add-ons/kernel/file_systems/exfat/Inode.cpp index 279d57b14c..e84e421f0b 100644 --- a/src/add-ons/kernel/file_systems/exfat/Inode.cpp +++ b/src/add-ons/kernel/file_systems/exfat/Inode.cpp @@ -6,11 +6,6 @@ #include "Inode.h" - -#include -#include -#include - #include "CachedBlock.h" #include "DataStream.h" #include "Utility.h" @@ -223,8 +218,16 @@ void Inode::_GetTimespec(uint16 date, uint16 time, struct timespec ×pec) const { static int32 tzoffset = -1; /* in minutes */ - if (tzoffset == -1) - tzoffset = get_timezone_offset() / 60; +#ifdef _KERNEL_MODE + tzoffset = static_cast(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 + leaps((date >> 9) + 10, ((date >> 5) & 15) - 1) + (date & 31) -1; diff --git a/src/add-ons/kernel/file_systems/exfat/Inode.h b/src/add-ons/kernel/file_systems/exfat/Inode.h index ee1f4ce9d2..c792905e4e 100644 --- a/src/add-ons/kernel/file_systems/exfat/Inode.h +++ b/src/add-ons/kernel/file_systems/exfat/Inode.h @@ -7,15 +7,10 @@ #define INODE_H -#include -#include -#include - -#include - #include "DirectoryIterator.h" #include "exfat.h" #include "Volume.h" +#include "system_dependencies.h" //#define TRACE_EXFAT diff --git a/src/add-ons/kernel/file_systems/exfat/Jamfile b/src/add-ons/kernel/file_systems/exfat/Jamfile index 8e5a24ca35..c0db887109 100644 --- a/src/add-ons/kernel/file_systems/exfat/Jamfile +++ b/src/add-ons/kernel/file_systems/exfat/Jamfile @@ -1,8 +1,8 @@ SubDir HAIKU_TOP src add-ons kernel file_systems exfat ; - +UsePrivateKernelHeaders ; +UsePrivateHeaders kernel ; UsePrivateHeaders shared storage ; UsePrivateHeaders file_systems ; -UsePrivateKernelHeaders ; KernelAddon exfat : DataStream.cpp diff --git a/src/add-ons/kernel/file_systems/exfat/Utility.cpp b/src/add-ons/kernel/file_systems/exfat/Utility.cpp index 28c73aa268..859fb32a12 100644 --- a/src/add-ons/kernel/file_systems/exfat/Utility.cpp +++ b/src/add-ons/kernel/file_systems/exfat/Utility.cpp @@ -12,14 +12,6 @@ #include "Utility.h" -#include -#include -#include - -#include - -#include - status_t get_volume_name(struct exfat_entry* entry, char* name, size_t length) diff --git a/src/add-ons/kernel/file_systems/exfat/Utility.h b/src/add-ons/kernel/file_systems/exfat/Utility.h index 383c3eedb6..6d0141bd8e 100644 --- a/src/add-ons/kernel/file_systems/exfat/Utility.h +++ b/src/add-ons/kernel/file_systems/exfat/Utility.h @@ -13,6 +13,7 @@ #include "exfat.h" +#include "system_dependencies.h" enum inode_type { diff --git a/src/add-ons/kernel/file_systems/exfat/Volume.cpp b/src/add-ons/kernel/file_systems/exfat/Volume.cpp index 2852252f96..81a3b770e9 100644 --- a/src/add-ons/kernel/file_systems/exfat/Volume.cpp +++ b/src/add-ons/kernel/file_systems/exfat/Volume.cpp @@ -16,19 +16,6 @@ #include "Volume.h" - -#include -#include -#include -#include -#include -#include - -#include -#include - -#include - #include "CachedBlock.h" #include "DeviceOpener.h" #include "Inode.h" diff --git a/src/add-ons/kernel/file_systems/exfat/Volume.h b/src/add-ons/kernel/file_systems/exfat/Volume.h index 1a8515b175..a7153ee77b 100644 --- a/src/add-ons/kernel/file_systems/exfat/Volume.h +++ b/src/add-ons/kernel/file_systems/exfat/Volume.h @@ -14,13 +14,8 @@ #define VOLUME_H -#include -#include - -#include -#include - #include "exfat.h" +#include "system_dependencies.h" struct node_key { diff --git a/src/add-ons/kernel/file_systems/exfat/exfat.h b/src/add-ons/kernel/file_systems/exfat/exfat.h index f34faf823e..edda407805 100644 --- a/src/add-ons/kernel/file_systems/exfat/exfat.h +++ b/src/add-ons/kernel/file_systems/exfat/exfat.h @@ -12,11 +12,7 @@ #define EXFAT_H -#include - -#include -#include -#include +#include "system_dependencies.h" typedef uint64 fileblock_t; // file block number 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 b4342612a7..ee16b1f970 100644 --- a/src/add-ons/kernel/file_systems/exfat/kernel_interface.cpp +++ b/src/add-ons/kernel/file_systems/exfat/kernel_interface.cpp @@ -12,27 +12,13 @@ */ -#include -#include -#include -#include - -#include - -#include -#include -#include -#include -#include -#include -#include -#include - #include "DirectoryIterator.h" #include "exfat.h" #include "Inode.h" #include "Utility.h" +#include + //#define TRACE_EXFAT #ifdef TRACE_EXFAT @@ -158,6 +144,7 @@ static status_t exfat_mount(fs_volume* _volume, const char* device, uint32 flags, const char* args, ino_t* _rootID) { + TRACE("exfat_mount(): Trying to mount\n"); Volume* volume = new(std::nothrow) Volume(_volume); if (volume == NULL) return B_NO_MEMORY; @@ -312,7 +299,7 @@ exfat_io(fs_volume* _volume, fs_vnode* _node, void* _cookie, Volume* volume = (Volume*)_volume->private_volume; Inode* inode = (Inode*)_node->private_node; -#ifndef EXFAT_SHELL +#ifndef FS_SHELL if (io_request_is_write(request) && volume->IsReadOnly()) { notify_io_request(request, B_READ_ONLY_DEVICE); return B_READ_ONLY_DEVICE; @@ -320,7 +307,7 @@ exfat_io(fs_volume* _volume, fs_vnode* _node, void* _cookie, #endif if (inode->FileCache() == NULL) { -#ifndef EXFAT_SHELL +#ifndef FS_SHELL notify_io_request(request, B_BAD_VALUE); #endif return B_BAD_VALUE; diff --git a/src/add-ons/kernel/file_systems/exfat/system_dependencies.h b/src/add-ons/kernel/file_systems/exfat/system_dependencies.h new file mode 100644 index 0000000000..220afbc9ba --- /dev/null +++ b/src/add-ons/kernel/file_systems/exfat/system_dependencies.h @@ -0,0 +1,64 @@ +/* + * Copyright 2018, Your Name + * 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 + +#else // !FS_SHELL + +#include +#include +#include +#include +#include +#include +#include +#include + + +#include +//#include + +#include +#include +#include "Debug.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#endif // !FS_SHELL + +#endif // _SYSTEM_DEPENDENCIES diff --git a/src/tests/add-ons/kernel/file_systems/Jamfile b/src/tests/add-ons/kernel/file_systems/Jamfile index 605f4ffcab..b7f2e5575e 100644 --- a/src/tests/add-ons/kernel/file_systems/Jamfile +++ b/src/tests/add-ons/kernel/file_systems/Jamfile @@ -3,6 +3,7 @@ SubDir HAIKU_TOP src tests add-ons kernel file_systems ; HaikuSubInclude bfs ; HaikuSubInclude btrfs ; HaikuSubInclude cdda ; +HaikuSubInclude exfat ; HaikuSubInclude iso9660 ; HaikuSubInclude shared ; HaikuSubInclude udf ; diff --git a/src/tests/add-ons/kernel/file_systems/exfat/Jamfile b/src/tests/add-ons/kernel/file_systems/exfat/Jamfile new file mode 100644 index 0000000000..32f519a4a5 --- /dev/null +++ b/src/tests/add-ons/kernel/file_systems/exfat/Jamfile @@ -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 ; diff --git a/src/tests/add-ons/kernel/file_systems/exfat/exfat_shell/Jamfile b/src/tests/add-ons/kernel/file_systems/exfat/exfat_shell/Jamfile new file mode 100644 index 0000000000..867324e14c --- /dev/null +++ b/src/tests/add-ons/kernel/file_systems/exfat/exfat_shell/Jamfile @@ -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 exfat_shell.o : $(exfatSource) ; + +BuildPlatformMain exfat_shell + : + : + exfat_shell.o + fs_shell.a $(HOST_LIBSUPC++) $(HOST_LIBSTDC++) + $(HOST_LIBROOT) $(fsShellCommandLibs) +; + +BuildPlatformMain exfat_fuse + : + : + exfat_shell.o + 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 ] ; diff --git a/src/tools/fs_shell/Jamfile b/src/tools/fs_shell/Jamfile index 0077ddab7b..c9c480ea33 100644 --- a/src/tools/fs_shell/Jamfile +++ b/src/tools/fs_shell/Jamfile @@ -35,6 +35,7 @@ local kernelEmulationSources = block_cache.cpp byte_order.cpp command_cp.cpp + convertutf.cpp disk_device_manager.cpp driver_settings.cpp errno.cpp diff --git a/src/tools/fs_shell/convertutf.cpp b/src/tools/fs_shell/convertutf.cpp new file mode 100644 index 0000000000..d7eef59508 --- /dev/null +++ b/src/tools/fs_shell/convertutf.cpp @@ -0,0 +1,130 @@ +/* + * Copyright 2014 Jonathan Schleifer + * 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); +} diff --git a/src/tools/fs_shell/module.cpp b/src/tools/fs_shell/module.cpp index a8b9bb3003..413586a449 100644 --- a/src/tools/fs_shell/module.cpp +++ b/src/tools/fs_shell/module.cpp @@ -191,14 +191,12 @@ init_module(module *module) module->state = MODULE_INIT; // init module - TRACE(("initializing module %s (at %p)... \n", module->name, module->info->std_ops)); if (module->info->std_ops != NULL) status = module->info->std_ops(FSSH_B_MODULE_INIT); else status = FSSH_B_OK; TRACE(("...done (%s)\n", strerror(status))); - if (status >= FSSH_B_OK) module->state = MODULE_READY; else {