From 729387130d5fba1d085a5f1bcccd20c712ae8f01 Mon Sep 17 00:00:00 2001 From: Sven Hoexter Date: Sat, 25 Jun 2016 14:12:02 +0200 Subject: [PATCH] Imported Upstream version 1.2.4 --- ChangeLog | 6 ++++ Makefile.am | 2 +- Makefile.in | 2 +- README | 45 +++++++++++++++++--------- configure | 20 ++++++------ configure.ac | 6 ++-- fuse/Makefile.am | 2 +- fuse/Makefile.in | 13 ++++---- fuse/main.c | 36 +++++++++++++++++++-- fuse/mount.exfat-fuse.8 | 2 +- libexfat/Makefile.am | 2 +- libexfat/Makefile.in | 2 +- libexfat/byteorder.h | 2 +- libexfat/cluster.c | 2 +- libexfat/compiler.h | 2 +- libexfat/exfat.h | 5 ++- libexfat/exfatfs.h | 4 ++- libexfat/io.c | 72 +---------------------------------------- libexfat/log.c | 2 +- libexfat/lookup.c | 7 ++-- libexfat/mount.c | 3 +- libexfat/node.c | 59 ++++++++++++++++++++++++++------- libexfat/platform.h | 2 +- libexfat/time.c | 2 +- libexfat/utf.c | 2 +- libexfat/utils.c | 5 ++- 26 files changed, 160 insertions(+), 147 deletions(-) diff --git a/ChangeLog b/ChangeLog index 05cd191..7826825 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +1.2.4 (2016-06-03) + +* Fixed wrong files names hashes when upper case table is compressed. +* Man pages are now installed by default. +* Commas and backslashes in device names are now escaped. + 1.2.3 (2015-12-19) * Fixed clusters loss when file renaming replaces target. diff --git a/Makefile.am b/Makefile.am index 4a50b0b..4a04532 100644 --- a/Makefile.am +++ b/Makefile.am @@ -3,7 +3,7 @@ # Automake source. # # Free exFAT implementation. -# Copyright (C) 2010-2015 Andrew Nayenko +# Copyright (C) 2010-2016 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 diff --git a/Makefile.in b/Makefile.in index d5593ce..55986d2 100644 --- a/Makefile.in +++ b/Makefile.in @@ -19,7 +19,7 @@ # Automake source. # # Free exFAT implementation. -# Copyright (C) 2010-2015 Andrew Nayenko +# Copyright (C) 2010-2016 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 diff --git a/README b/README index 8f2fe85..500d722 100644 --- a/README +++ b/README @@ -7,7 +7,6 @@ Supported operating systems: * GNU/Linux * Mac OS X 10.5 or later -* FreeBSD * OpenBSD Most GNU/Linux distributions already have fuse-exfat and exfat-utils in their repositories, so you can just install and use them. The next chapter describes how to compile them from source. @@ -15,40 +14,56 @@ Most GNU/Linux distributions already have fuse-exfat and exfat-utils in their re Compiling --------- -To build this project under GNU/Linux you need to install the following packages: +To build this project on GNU/Linux you need to install the following packages: -* pkg-config +* [pkg-config][7] * fuse-devel (or libfuse-dev) -* gcc -* make +* [gcc][8] +* [make][9] + +On Mac OS X: + +* pkg-config +* [OSXFUSE][10] +* [Xcode][11] (legacy versions include autotools but their versions are too old) + +On OpenBSD: + Get the source code, change directory and compile: - ./configure --prefix=/usr + ./configure make -Then install driver and utilities: +Then install driver and utilities (from root): - sudo make install + make install -You can remove them using this command: +You can remove them using this command (from root): - sudo make uninstall + make uninstall Mounting -------- -Modern GNU/Linux distributions will mount exFAT volumes automatically—util-linux-ng 2.18 (was renamed to util-linux in 2.19) is required for this. Anyway, you can mount manually (you will need root privileges): +Modern GNU/Linux distributions (with [util-linux][12] 2.18 or later) will mount exFAT volumes automatically. Anyway, you can mount manually (from root): - sudo mount.exfat-fuse /dev/sdXn /mnt/exfat + mount.exfat-fuse /dev/spec /mnt/exfat -where /dev/sdXn is the partition special file, /mnt/exfat is a mountpoint. +where /dev/spec is the [device file][13], /mnt/exfat is a mountpoint. Feedback -------- If you have any questions, issues, suggestions, bug reports, etc. please create an [issue][3]. Pull requests are also welcome! -[1]: http://en.wikipedia.org/wiki/ExFAT -[2]: http://en.wikipedia.org/wiki/Filesystem_in_Userspace +[1]: https://en.wikipedia.org/wiki/ExFAT +[2]: https://en.wikipedia.org/wiki/Filesystem_in_Userspace [3]: https://github.com/relan/exfat/issues +[7]: http://www.freedesktop.org/wiki/Software/pkg-config/ +[8]: https://gcc.gnu.org/ +[9]: https://www.gnu.org/software/make/ +[10]: https://osxfuse.github.io/ +[11]: https://en.wikipedia.org/wiki/Xcode +[12]: https://www.kernel.org/pub/linux/utils/util-linux/ +[13]: https://en.wikipedia.org/wiki/Device_file diff --git a/configure b/configure index afda1d2..d6ecc42 100755 --- a/configure +++ b/configure @@ -1,6 +1,6 @@ #! /bin/sh # Guess values for system-dependent variables and create Makefiles. -# Generated by GNU Autoconf 2.69 for Free exFAT implementation 1.2.3. +# Generated by GNU Autoconf 2.69 for Free exFAT implementation 1.2.4. # # Report bugs to . # @@ -579,8 +579,8 @@ MAKEFLAGS= # Identity of this package. PACKAGE_NAME='Free exFAT implementation' PACKAGE_TARNAME='fuse-exfat' -PACKAGE_VERSION='1.2.3' -PACKAGE_STRING='Free exFAT implementation 1.2.3' +PACKAGE_VERSION='1.2.4' +PACKAGE_STRING='Free exFAT implementation 1.2.4' PACKAGE_BUGREPORT='relan@users.noreply.github.com' PACKAGE_URL='https://github.com/relan/exfat' @@ -1238,7 +1238,7 @@ if test "$ac_init_help" = "long"; then # Omit some internal or obsolete options to make the list less imposing. # This message is too long to be a string in the A/UX 3.1 sh. cat <<_ACEOF -\`configure' configures Free exFAT implementation 1.2.3 to adapt to many kinds of systems. +\`configure' configures Free exFAT implementation 1.2.4 to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... @@ -1304,7 +1304,7 @@ fi if test -n "$ac_init_help"; then case $ac_init_help in - short | recursive ) echo "Configuration of Free exFAT implementation 1.2.3:";; + short | recursive ) echo "Configuration of Free exFAT implementation 1.2.4:";; esac cat <<\_ACEOF @@ -1403,7 +1403,7 @@ fi test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF -Free exFAT implementation configure 1.2.3 +Free exFAT implementation configure 1.2.4 generated by GNU Autoconf 2.69 Copyright (C) 2012 Free Software Foundation, Inc. @@ -1458,7 +1458,7 @@ cat >config.log <<_ACEOF This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. -It was created by Free exFAT implementation $as_me 1.2.3, which was +It was created by Free exFAT implementation $as_me 1.2.4, which was generated by GNU Autoconf 2.69. Invocation command line was $ $0 $@ @@ -2321,7 +2321,7 @@ fi # Define the identity of the package. PACKAGE='fuse-exfat' - VERSION='1.2.3' + VERSION='1.2.4' cat >>confdefs.h <<_ACEOF @@ -4839,7 +4839,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # report actual input values of CONFIG_FILES etc. instead of their # values after options handling. ac_log=" -This file was extended by Free exFAT implementation $as_me 1.2.3, which was +This file was extended by Free exFAT implementation $as_me 1.2.4, which was generated by GNU Autoconf 2.69. Invocation command line was CONFIG_FILES = $CONFIG_FILES @@ -4906,7 +4906,7 @@ _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" ac_cs_version="\\ -Free exFAT implementation config.status 1.2.3 +Free exFAT implementation config.status 1.2.4 configured by $0, generated by GNU Autoconf 2.69, with options \\"\$ac_cs_config\\" diff --git a/configure.ac b/configure.ac index 43e31e4..4395817 100644 --- a/configure.ac +++ b/configure.ac @@ -3,7 +3,7 @@ # Autoconf source. # # Free exFAT implementation. -# Copyright (C) 2010-2015 Andrew Nayenko +# Copyright (C) 2010-2016 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 @@ -21,11 +21,11 @@ # AC_INIT([Free exFAT implementation], - [1.2.3], + [1.2.4], [relan@users.noreply.github.com], [fuse-exfat], [https://github.com/relan/exfat]) -AM_INIT_AUTOMAKE([1.11.2 -Wall -Werror foreign subdir-objects no-installman]) +AM_INIT_AUTOMAKE([1.11.2 -Wall -Werror foreign subdir-objects]) AC_PROG_CC AC_PROG_CC_C99 AC_PROG_RANLIB diff --git a/fuse/Makefile.am b/fuse/Makefile.am index ce36b35..8f69cf4 100644 --- a/fuse/Makefile.am +++ b/fuse/Makefile.am @@ -3,7 +3,7 @@ # Automake source. # # Free exFAT implementation. -# Copyright (C) 2010-2015 Andrew Nayenko +# Copyright (C) 2010-2016 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 diff --git a/fuse/Makefile.in b/fuse/Makefile.in index caece23..8af7876 100644 --- a/fuse/Makefile.in +++ b/fuse/Makefile.in @@ -19,7 +19,7 @@ # Automake source. # # Free exFAT implementation. -# Copyright (C) 2010-2015 Andrew Nayenko +# Copyright (C) 2010-2016 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 @@ -119,7 +119,7 @@ mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/libexfat/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = -am__installdirs = "$(DESTDIR)$(sbindir)" +am__installdirs = "$(DESTDIR)$(sbindir)" "$(DESTDIR)$(man8dir)" PROGRAMS = $(sbin_PROGRAMS) am_mount_exfat_fuse_OBJECTS = mount_exfat_fuse-main.$(OBJEXT) mount_exfat_fuse_OBJECTS = $(am_mount_exfat_fuse_OBJECTS) @@ -433,7 +433,6 @@ mount_exfat_fuse-main.obj: main.c @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='main.c' object='mount_exfat_fuse-main.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mount_exfat_fuse_CPPFLAGS) $(CPPFLAGS) $(mount_exfat_fuse_CFLAGS) $(CFLAGS) -c -o mount_exfat_fuse-main.obj `if test -f 'main.c'; then $(CYGPATH_W) 'main.c'; else $(CYGPATH_W) '$(srcdir)/main.c'; fi` - install-man8: $(dist_man8_MANS) @$(NORMAL_INSTALL) @list1='$(dist_man8_MANS)'; \ @@ -560,9 +559,9 @@ distdir: $(DISTFILES) done check-am: all-am check: check-am -all-am: Makefile $(PROGRAMS) +all-am: Makefile $(PROGRAMS) $(MANS) installdirs: - for dir in "$(DESTDIR)$(sbindir)"; do \ + for dir in "$(DESTDIR)$(sbindir)" "$(DESTDIR)$(man8dir)"; do \ test -z "$$dir" || $(MKDIR_P) "$$dir"; \ done install: install-am @@ -617,7 +616,7 @@ info: info-am info-am: -install-data-am: +install-data-am: install-man install-dvi: install-dvi-am @@ -663,7 +662,7 @@ ps: ps-am ps-am: -uninstall-am: uninstall-sbinPROGRAMS +uninstall-am: uninstall-man uninstall-sbinPROGRAMS @$(NORMAL_INSTALL) $(MAKE) $(AM_MAKEFLAGS) uninstall-hook uninstall-man: uninstall-man8 diff --git a/fuse/main.c b/fuse/main.c index aad082b..bc0faf3 100644 --- a/fuse/main.c +++ b/fuse/main.c @@ -3,7 +3,7 @@ FUSE-based exFAT implementation. Requires FUSE 2.6 or later. Free exFAT implementation. - Copyright (C) 2010-2015 Andrew Nayenko + Copyright (C) 2010-2016 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 @@ -427,6 +427,36 @@ static char* add_option(char* options, const char* name, const char* value) return options; } +static void escape(char* escaped, const char* orig) +{ + do + { + if (*orig == ',' || *orig == '\\') + *escaped++ = '\\'; + } + while ((*escaped++ = *orig++)); +} + +static char* add_fsname_option(char* options, const char* spec) +{ + /* escaped string cannot be more than twice as big as the original one */ + char* escaped = malloc(strlen(spec) * 2 + 1); + + if (escaped == NULL) + { + free(options); + exfat_error("failed to allocate escaped string for %s", spec); + return NULL; + } + + /* on some platforms (e.g. Android, Solaris) device names can contain + commas */ + escape(escaped, spec); + options = add_option(options, "fsname", escaped); + free(escaped); + return options; +} + static char* add_user_option(char* options) { struct passwd* pw; @@ -458,7 +488,7 @@ static char* add_blksize_option(char* options, long cluster_size) static char* add_fuse_options(char* options, const char* spec) { - options = add_option(options, "fsname", spec); + options = add_fsname_option(options, spec); if (options == NULL) return NULL; options = add_user_option(options); @@ -508,7 +538,7 @@ int main(int argc, char* argv[]) break; case 'V': free(mount_options); - puts("Copyright (C) 2010-2015 Andrew Nayenko"); + puts("Copyright (C) 2010-2016 Andrew Nayenko"); return 0; case 'v': break; diff --git a/fuse/mount.exfat-fuse.8 b/fuse/mount.exfat-fuse.8 index 38586ca..602ddc9 100644 --- a/fuse/mount.exfat-fuse.8 +++ b/fuse/mount.exfat-fuse.8 @@ -1,4 +1,4 @@ -.\" Copyright (C) 2010-2015 Andrew Nayenko +.\" Copyright (C) 2010-2016 Andrew Nayenko .\" .TH EXFAT-FUSE 8 "July 2010" .SH NAME diff --git a/libexfat/Makefile.am b/libexfat/Makefile.am index f9067e9..102d89d 100644 --- a/libexfat/Makefile.am +++ b/libexfat/Makefile.am @@ -3,7 +3,7 @@ # Automake source. # # Free exFAT implementation. -# Copyright (C) 2010-2015 Andrew Nayenko +# Copyright (C) 2010-2016 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 diff --git a/libexfat/Makefile.in b/libexfat/Makefile.in index 6603fde..f10c73a 100644 --- a/libexfat/Makefile.in +++ b/libexfat/Makefile.in @@ -19,7 +19,7 @@ # Automake source. # # Free exFAT implementation. -# Copyright (C) 2010-2015 Andrew Nayenko +# Copyright (C) 2010-2016 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 diff --git a/libexfat/byteorder.h b/libexfat/byteorder.h index 472cb48..e417ad6 100644 --- a/libexfat/byteorder.h +++ b/libexfat/byteorder.h @@ -3,7 +3,7 @@ Endianness stuff. exFAT uses little-endian byte order. Free exFAT implementation. - Copyright (C) 2010-2015 Andrew Nayenko + Copyright (C) 2010-2016 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 diff --git a/libexfat/cluster.c b/libexfat/cluster.c index fc3657b..13bc6ce 100644 --- a/libexfat/cluster.c +++ b/libexfat/cluster.c @@ -3,7 +3,7 @@ exFAT file system implementation library. Free exFAT implementation. - Copyright (C) 2010-2015 Andrew Nayenko + Copyright (C) 2010-2016 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 diff --git a/libexfat/compiler.h b/libexfat/compiler.h index 1a4742e..b590d01 100644 --- a/libexfat/compiler.h +++ b/libexfat/compiler.h @@ -4,7 +4,7 @@ showstopper. Free exFAT implementation. - Copyright (C) 2010-2015 Andrew Nayenko + Copyright (C) 2010-2016 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 diff --git a/libexfat/exfat.h b/libexfat/exfat.h index 97d3692..75cb6e6 100644 --- a/libexfat/exfat.h +++ b/libexfat/exfat.h @@ -4,7 +4,7 @@ implementation. Free exFAT implementation. - Copyright (C) 2010-2015 Andrew Nayenko + Copyright (C) 2010-2016 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 @@ -97,8 +97,7 @@ struct exfat { struct exfat_dev* dev; struct exfat_super_block* sb; - le16_t* upcase; - size_t upcase_chars; + uint16_t* upcase; struct exfat_node* root; struct { diff --git a/libexfat/exfatfs.h b/libexfat/exfatfs.h index eca2cac..c155312 100644 --- a/libexfat/exfatfs.h +++ b/libexfat/exfatfs.h @@ -3,7 +3,7 @@ Definitions of structures and constants used in exFAT file system. Free exFAT implementation. - Copyright (C) 2010-2015 Andrew Nayenko + Copyright (C) 2010-2016 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 @@ -99,6 +99,8 @@ struct exfat_entry_bitmap /* allocated clusters bitmap */ PACKED; STATIC_ASSERT(sizeof(struct exfat_entry_bitmap) == 32); +#define EXFAT_UPCASE_CHARS 0x10000 + struct exfat_entry_upcase /* upper case translation table */ { uint8_t type; /* EXFAT_ENTRY_UPCASE */ diff --git a/libexfat/io.c b/libexfat/io.c index 3d7aaad..60f28e2 100644 --- a/libexfat/io.c +++ b/libexfat/io.c @@ -3,7 +3,7 @@ exFAT file system implementation library. Free exFAT implementation. - Copyright (C) 2010-2015 Andrew Nayenko + Copyright (C) 2010-2016 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 @@ -37,20 +37,12 @@ #include #endif #include -#ifdef USE_UBLIO -#include -#include -#endif struct exfat_dev { int fd; enum exfat_mode mode; off_t size; /* in bytes */ -#ifdef USE_UBLIO - off_t pos; - ublio_filehandle_t ufh; -#endif }; static int open_ro(const char* spec) @@ -82,9 +74,6 @@ struct exfat_dev* exfat_open(const char* spec, enum exfat_mode mode) { struct exfat_dev* dev; struct stat stbuf; -#ifdef USE_UBLIO - struct ublio_param up; -#endif dev = malloc(sizeof(struct exfat_dev)); if (dev == NULL) @@ -222,24 +211,6 @@ struct exfat_dev* exfat_open(const char* spec, enum exfat_mode mode) } } -#ifdef USE_UBLIO - memset(&up, 0, sizeof(struct ublio_param)); - up.up_blocksize = 256 * 1024; - up.up_items = 64; - up.up_grace = 32; - up.up_priv = &dev->fd; - - dev->pos = 0; - dev->ufh = ublio_open(&up); - if (dev->ufh == NULL) - { - close(dev->fd); - free(dev); - exfat_error("failed to initialize ublio"); - return NULL; - } -#endif - return dev; } @@ -247,13 +218,6 @@ int exfat_close(struct exfat_dev* dev) { int rc = 0; -#ifdef USE_UBLIO - if (ublio_close(dev->ufh) != 0) - { - exfat_error("failed to close ublio"); - rc = -EIO; - } -#endif if (close(dev->fd) != 0) { exfat_error("failed to close device: %s", strerror(errno)); @@ -267,13 +231,6 @@ int exfat_fsync(struct exfat_dev* dev) { int rc = 0; -#ifdef USE_UBLIO - if (ublio_fsync(dev->ufh) != 0) - { - exfat_error("ublio fsync failed"); - rc = -EIO; - } -#endif if (fsync(dev->fd) != 0) { exfat_error("fsync failed: %s", strerror(errno)); @@ -294,56 +251,29 @@ off_t exfat_get_size(const struct exfat_dev* dev) off_t exfat_seek(struct exfat_dev* dev, off_t offset, int whence) { -#ifdef USE_UBLIO - /* XXX SEEK_CUR will be handled incorrectly */ - return dev->pos = lseek(dev->fd, offset, whence); -#else return lseek(dev->fd, offset, whence); -#endif } ssize_t exfat_read(struct exfat_dev* dev, void* buffer, size_t size) { -#ifdef USE_UBLIO - ssize_t result = ublio_pread(dev->ufh, buffer, size, dev->pos); - if (result >= 0) - dev->pos += size; - return result; -#else return read(dev->fd, buffer, size); -#endif } ssize_t exfat_write(struct exfat_dev* dev, const void* buffer, size_t size) { -#ifdef USE_UBLIO - ssize_t result = ublio_pwrite(dev->ufh, buffer, size, dev->pos); - if (result >= 0) - dev->pos += size; - return result; -#else return write(dev->fd, buffer, size); -#endif } ssize_t exfat_pread(struct exfat_dev* dev, void* buffer, size_t size, off_t offset) { -#ifdef USE_UBLIO - return ublio_pread(dev->ufh, buffer, size, offset); -#else return pread(dev->fd, buffer, size, offset); -#endif } ssize_t exfat_pwrite(struct exfat_dev* dev, const void* buffer, size_t size, off_t offset) { -#ifdef USE_UBLIO - return ublio_pwrite(dev->ufh, buffer, size, offset); -#else return pwrite(dev->fd, buffer, size, offset); -#endif } ssize_t exfat_generic_pread(const struct exfat* ef, struct exfat_node* node, diff --git a/libexfat/log.c b/libexfat/log.c index fd8982b..e37b0d8 100644 --- a/libexfat/log.c +++ b/libexfat/log.c @@ -3,7 +3,7 @@ exFAT file system implementation library. Free exFAT implementation. - Copyright (C) 2010-2015 Andrew Nayenko + Copyright (C) 2010-2016 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 diff --git a/libexfat/lookup.c b/libexfat/lookup.c index d5bb389..30b6410 100644 --- a/libexfat/lookup.c +++ b/libexfat/lookup.c @@ -3,7 +3,7 @@ exFAT file system implementation library. Free exFAT implementation. - Copyright (C) 2010-2015 Andrew Nayenko + Copyright (C) 2010-2016 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 @@ -61,10 +61,7 @@ struct exfat_node* exfat_readdir(struct exfat* ef, struct exfat_iterator* it) static int compare_char(struct exfat* ef, uint16_t a, uint16_t b) { - if (a >= ef->upcase_chars || b >= ef->upcase_chars) - return (int) a - (int) b; - - return (int) le16_to_cpu(ef->upcase[a]) - (int) le16_to_cpu(ef->upcase[b]); + return (int) ef->upcase[a] - (int) ef->upcase[b]; } static int compare_name(struct exfat* ef, const le16_t* a, const le16_t* b) diff --git a/libexfat/mount.c b/libexfat/mount.c index 0d6ce9e..b1ce654 100644 --- a/libexfat/mount.c +++ b/libexfat/mount.c @@ -3,7 +3,7 @@ exFAT file system implementation library. Free exFAT implementation. - Copyright (C) 2010-2015 Andrew Nayenko + Copyright (C) 2010-2016 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 @@ -376,5 +376,4 @@ void exfat_unmount(struct exfat* ef) ef->sb = NULL; free(ef->upcase); ef->upcase = NULL; - ef->upcase_chars = 0; } diff --git a/libexfat/node.c b/libexfat/node.c index 4dd4dc6..fa04e25 100644 --- a/libexfat/node.c +++ b/libexfat/node.c @@ -3,7 +3,7 @@ exFAT file system implementation library. Free exFAT implementation. - Copyright (C) 2010-2015 Andrew Nayenko + Copyright (C) 2010-2016 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 @@ -227,6 +227,26 @@ static bool check_node(const struct exfat_node* node, uint16_t actual_checksum, return true; } +static void decompress_upcase(uint16_t* output, const le16_t* source, + size_t size) +{ + size_t si; + size_t oi; + + for (oi = 0; oi < EXFAT_UPCASE_CHARS; oi++) + output[oi] = oi; + + for (si = 0, oi = 0; si < size && oi < EXFAT_UPCASE_CHARS; si++) + { + uint16_t ch = le16_to_cpu(source[si]); + + if (ch == 0xffff && si + 1 < size) /* indicates a run */ + oi += le16_to_cpu(source[++si]); + else + output[oi++] = ch; + } +} + /* * Reads one entry in directory at position pointed by iterator and fills * node structure. @@ -247,6 +267,8 @@ static int readdir(struct exfat* ef, const struct exfat_node* parent, uint16_t reference_checksum = 0; uint16_t actual_checksum = 0; uint64_t valid_size = 0; + uint64_t upcase_size = 0; + le16_t* upcase_comp = NULL; *node = NULL; @@ -371,33 +393,48 @@ static int readdir(struct exfat* ef, const struct exfat_node* parent, le32_to_cpu(upcase->start_cluster)); goto error; } - if (le64_to_cpu(upcase->size) == 0 || - le64_to_cpu(upcase->size) > 0xffff * sizeof(uint16_t) || - le64_to_cpu(upcase->size) % sizeof(uint16_t) != 0) + upcase_size = le64_to_cpu(upcase->size); + if (upcase_size == 0 || + upcase_size > EXFAT_UPCASE_CHARS * sizeof(uint16_t) || + upcase_size % sizeof(uint16_t) != 0) { exfat_error("bad upcase table size (%"PRIu64" bytes)", - le64_to_cpu(upcase->size)); + upcase_size); goto error; } - ef->upcase = malloc(le64_to_cpu(upcase->size)); - if (ef->upcase == NULL) + upcase_comp = malloc(upcase_size); + if (upcase_comp == NULL) { exfat_error("failed to allocate upcase table (%"PRIu64" bytes)", - le64_to_cpu(upcase->size)); + upcase_size); rc = -ENOMEM; goto error; } - ef->upcase_chars = le64_to_cpu(upcase->size) / sizeof(le16_t); - if (exfat_pread(ef->dev, ef->upcase, le64_to_cpu(upcase->size), + /* read compressed upcase table */ + if (exfat_pread(ef->dev, upcase_comp, upcase_size, exfat_c2o(ef, le32_to_cpu(upcase->start_cluster))) < 0) { + free(upcase_comp); exfat_error("failed to read upper case table " "(%"PRIu64" bytes starting at cluster %#x)", - le64_to_cpu(upcase->size), + upcase_size, le32_to_cpu(upcase->start_cluster)); goto error; } + + /* decompress upcase table */ + ef->upcase = calloc(EXFAT_UPCASE_CHARS, sizeof(uint16_t)); + if (ef->upcase == NULL) + { + free(upcase_comp); + exfat_error("failed to allocate decompressed upcase table"); + rc = -ENOMEM; + goto error; + } + decompress_upcase(ef->upcase, upcase_comp, + upcase_size / sizeof(uint16_t)); + free(upcase_comp); break; case EXFAT_ENTRY_BITMAP: diff --git a/libexfat/platform.h b/libexfat/platform.h index 99fe507..4c5a0df 100644 --- a/libexfat/platform.h +++ b/libexfat/platform.h @@ -4,7 +4,7 @@ same kernel can use different libc implementations. Free exFAT implementation. - Copyright (C) 2010-2015 Andrew Nayenko + Copyright (C) 2010-2016 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 diff --git a/libexfat/time.c b/libexfat/time.c index 45c4aff..7d2becd 100644 --- a/libexfat/time.c +++ b/libexfat/time.c @@ -3,7 +3,7 @@ exFAT file system implementation library. Free exFAT implementation. - Copyright (C) 2010-2015 Andrew Nayenko + Copyright (C) 2010-2016 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 diff --git a/libexfat/utf.c b/libexfat/utf.c index 6f14882..98ae52d 100644 --- a/libexfat/utf.c +++ b/libexfat/utf.c @@ -3,7 +3,7 @@ exFAT file system implementation library. Free exFAT implementation. - Copyright (C) 2010-2015 Andrew Nayenko + Copyright (C) 2010-2016 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 diff --git a/libexfat/utils.c b/libexfat/utils.c index 388f360..0d3b809 100644 --- a/libexfat/utils.c +++ b/libexfat/utils.c @@ -3,7 +3,7 @@ exFAT file system implementation library. Free exFAT implementation. - Copyright (C) 2010-2015 Andrew Nayenko + Copyright (C) 2010-2016 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 @@ -124,8 +124,7 @@ le16_t exfat_calc_name_hash(const struct exfat* ef, const le16_t* name) uint16_t c = le16_to_cpu(name[i]); /* convert to upper case */ - if (c < ef->upcase_chars) - c = le16_to_cpu(ef->upcase[c]); + c = ef->upcase[c]; hash = ((hash << 15) | (hash >> 1)) + (c & 0xff); hash = ((hash << 15) | (hash >> 1)) + (c >> 8); -- 2.39.5