From 31d7c977e0842d1a2ff53ec8ec4450db7137da6e Mon Sep 17 00:00:00 2001 From: Guilherme Janczak Date: Tue, 17 Sep 2024 09:55:53 +0000 Subject: [PATCH] Make code endianness-agnostic Also fixes compilation on OpenBSD because OpenBSD's endian.h header was used incorrectly, now the header isn't used on any platform. Tested by mounting and accessing an exfat USB drive on my OpenBSD 7.5 amd64 desktop (64-bit little-endian) and a NetBSD 10.0 Nintendo Wii (big-endian 32-bit). --- configure.ac | 1 + libexfat/byteorder.h | 81 +++++++++++++++++++++++++------------------- libexfat/platform.h | 73 --------------------------------------- 3 files changed, 48 insertions(+), 107 deletions(-) delete mode 100644 libexfat/platform.h diff --git a/configure.ac b/configure.ac index 45d01c3b..25c27b96 100644 --- a/configure.ac +++ b/configure.ac @@ -47,6 +47,7 @@ case "$host_os" in AC_DEFINE([_DEFAULT_SOURCE], [], [Enable vsyslog().]) ;; esac +AC_C_BIGENDIAN(,, [AC_MSG_ERROR([Unknown endianness])]) AC_CONFIG_HEADERS([libexfat/config.h]) AC_CONFIG_FILES([ libexfat/Makefile diff --git a/libexfat/byteorder.h b/libexfat/byteorder.h index 98b93c70..412d11f8 100644 --- a/libexfat/byteorder.h +++ b/libexfat/byteorder.h @@ -23,46 +23,59 @@ #ifndef BYTEORDER_H_INCLUDED #define BYTEORDER_H_INCLUDED -#include "platform.h" +#include "config.h" #include #include +#ifdef WORDS_BIGENDIAN +typedef unsigned char bitmap_t; +#else +typedef size_t bitmap_t; +#endif + typedef struct { uint16_t __u16; } le16_t; typedef struct { uint32_t __u32; } le32_t; typedef struct { uint64_t __u64; } le64_t; -#if EXFAT_BYTE_ORDER == EXFAT_LITTLE_ENDIAN - -static inline uint16_t le16_to_cpu(le16_t v) { return v.__u16; } -static inline uint32_t le32_to_cpu(le32_t v) { return v.__u32; } -static inline uint64_t le64_to_cpu(le64_t v) { return v.__u64; } - -static inline le16_t cpu_to_le16(uint16_t v) { le16_t t = {v}; return t; } -static inline le32_t cpu_to_le32(uint32_t v) { le32_t t = {v}; return t; } -static inline le64_t cpu_to_le64(uint64_t v) { le64_t t = {v}; return t; } - -typedef size_t bitmap_t; - -#elif EXFAT_BYTE_ORDER == EXFAT_BIG_ENDIAN - -static inline uint16_t le16_to_cpu(le16_t v) - { return exfat_bswap16(v.__u16); } -static inline uint32_t le32_to_cpu(le32_t v) - { return exfat_bswap32(v.__u32); } -static inline uint64_t le64_to_cpu(le64_t v) - { return exfat_bswap64(v.__u64); } - -static inline le16_t cpu_to_le16(uint16_t v) - { le16_t t = {exfat_bswap16(v)}; return t; } -static inline le32_t cpu_to_le32(uint32_t v) - { le32_t t = {exfat_bswap32(v)}; return t; } -static inline le64_t cpu_to_le64(uint64_t v) - { le64_t t = {exfat_bswap64(v)}; return t; } - -typedef unsigned char bitmap_t; - -#else -#error Wow! You have a PDP machine?! -#endif +static inline uint16_t le16_to_cpu(le16_t v) { + unsigned char *p = (unsigned char *)&v; + return p[0] | p[1] << 8; +} + +static inline uint32_t le32_to_cpu(le32_t v) { + unsigned char *p = (unsigned char *)&v; + return p[0] | p[1] << 8 | p[2] << 16 | (uint32_t)p[3] << 24; +} +static inline uint64_t le64_to_cpu(le64_t v) { + unsigned char *p = (unsigned char *)&v; + uint64_t rval = 0; + + rval |= (uint64_t)p[0] | (uint64_t)p[1] << 8; + rval |= (uint64_t)p[2] << 16 | (uint64_t)p[3] << 24; + rval |= (uint64_t)p[4] << 32 | (uint64_t)p[5] << 40; + rval |= (uint64_t)p[6] << 48 | (uint64_t)p[7] << 56; + return rval; +} + +static inline le16_t cpu_to_le16(uint16_t v) { + le16_t t; + unsigned char *p = (unsigned char *)&t; + p[0] = v ; p[1] = v >> 8; + return t; +} +static inline le32_t cpu_to_le32(uint32_t v) { + le32_t t; + unsigned char *p = (unsigned char *)&t; + p[0] = v ; p[1] = v >>= 8; p[2] = v >>= 8; p[3] = v >> 8; + return t; +} + +static inline le64_t cpu_to_le64(uint64_t v) { + le64_t t; + unsigned char *p = (unsigned char *)&t; + p[0] = v ; p[1] = v >>= 8; p[2] = v >>= 8; p[3] = v >>= 8; + p[4] = v >>= 8; p[5] = v >>= 8; p[6] = v >>= 8; p[7] = v >> 8; + return t; +} #endif /* ifndef BYTEORDER_H_INCLUDED */ diff --git a/libexfat/platform.h b/libexfat/platform.h deleted file mode 100644 index 9bd125a1..00000000 --- a/libexfat/platform.h +++ /dev/null @@ -1,73 +0,0 @@ -/* - platform.h (14.05.13) - OS-specific code (libc-specific in fact). Note that systems with the - same kernel can use different libc implementations. - - Free exFAT implementation. - Copyright (C) 2010-2023 Andrew Nayenko - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along - with this program; if not, write to the Free Software Foundation, Inc., - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -*/ - -#ifndef PLATFORM_H_INCLUDED -#define PLATFORM_H_INCLUDED - -#if defined(__linux__) || defined(__GLIBC__) || defined(__GNU__) - -#include -#include -#define exfat_bswap16(x) bswap_16(x) -#define exfat_bswap32(x) bswap_32(x) -#define exfat_bswap64(x) bswap_64(x) -#define EXFAT_BYTE_ORDER __BYTE_ORDER -#define EXFAT_LITTLE_ENDIAN __LITTLE_ENDIAN -#define EXFAT_BIG_ENDIAN __BIG_ENDIAN - -#elif defined(__APPLE__) - -#include -#include -#define exfat_bswap16(x) OSSwapInt16(x) -#define exfat_bswap32(x) OSSwapInt32(x) -#define exfat_bswap64(x) OSSwapInt64(x) -#define EXFAT_BYTE_ORDER BYTE_ORDER -#define EXFAT_LITTLE_ENDIAN LITTLE_ENDIAN -#define EXFAT_BIG_ENDIAN BIG_ENDIAN - -#elif defined(__FreeBSD__) || defined(__DragonFly__) || defined(__NetBSD__) || defined(__OpenBSD__) - -#include -#define exfat_bswap16(x) bswap16(x) -#define exfat_bswap32(x) bswap32(x) -#define exfat_bswap64(x) bswap64(x) -#define EXFAT_BYTE_ORDER _BYTE_ORDER -#define EXFAT_LITTLE_ENDIAN _LITTLE_ENDIAN -#define EXFAT_BIG_ENDIAN _BIG_ENDIAN - -#elif defined(__sun) - -#include -#define exfat_bswap16(x) bswap_16(x) -#define exfat_bswap32(x) bswap_32(x) -#define exfat_bswap64(x) bswap_64(x) -#define EXFAT_BYTE_ORDER __BYTE_ORDER -#define EXFAT_LITTLE_ENDIAN __LITTLE_ENDIAN -#define EXFAT_BIG_ENDIAN __BIG_ENDIAN - -#else -#error Unknown platform -#endif - -#endif /* ifndef PLATFORM_H_INCLUDED */