]> git.sven.stormbind.net Git - sven/exfat-utils.git/commitdiff
New upstream version 1.3.0 upstream upstream/1.3.0
authorSven Hoexter <sven@stormbind.net>
Wed, 31 Oct 2018 21:39:25 +0000 (22:39 +0100)
committerSven Hoexter <sven@stormbind.net>
Wed, 31 Oct 2018 21:39:25 +0000 (22:39 +0100)
25 files changed:
ChangeLog
Makefile.in
README
aclocal.m4
configure
configure.ac
dump/Makefile.in
dump/dumpexfat.8
fsck/Makefile.in
fsck/exfatfsck.8
fsck/main.c
label/Makefile.in
label/exfatlabel.8
libexfat/Makefile.am
libexfat/Makefile.in
libexfat/config.h.in
libexfat/exfat.h
libexfat/io.c
libexfat/log.c
libexfat/mount.c
libexfat/node.c
libexfat/platform.h
libexfat/repair.c [new file with mode: 0644]
mkfs/Makefile.in
mkfs/mkexfatfs.8

index 8bff070de12ba13b4447086b2467319b892c9b4f..9e20bf53f0c66486a286d5527ad600f9fcca24cb 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,14 @@
+1.3.0 (2018-09-15)
+
+* exfatfsck can now repair some errors.
+* Added experimental Android support for exfat-utils [liminghao, LongPingWEI,
+Pablo Mendez Hernandez, Pierre-Hugues Husson].
+* Cleaned up FUSE code preparing for FUSE 3 support.
+* Removed OpenBSD support as it does not handle -o option in fuse_main().
+* Re-introduced FreeBSD support [Oleksii Samorukov].
+* Fixed DragonFly BSD support [Tomohiro Kusumi].
+* dirent->d_type in now filled on readdir() [Mark Browning].
+
 1.2.8 (2018-02-03)
 
 * Fixed new files or directories creation in the root directory: ensure there
index 6f647c65191be0d54db2d0dd05d379905d9331df..8270c0a126c2168ee779d5387023c4402e9c8382 100644 (file)
@@ -260,10 +260,15 @@ PACKAGE_TARNAME = @PACKAGE_TARNAME@
 PACKAGE_URL = @PACKAGE_URL@
 PACKAGE_VERSION = @PACKAGE_VERSION@
 PATH_SEPARATOR = @PATH_SEPARATOR@
+PKG_CONFIG = @PKG_CONFIG@
+PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
+PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
 RANLIB = @RANLIB@
 SET_MAKE = @SET_MAKE@
 SHELL = @SHELL@
 STRIP = @STRIP@
+UBLIO_CFLAGS = @UBLIO_CFLAGS@
+UBLIO_LIBS = @UBLIO_LIBS@
 VERSION = @VERSION@
 abs_builddir = @abs_builddir@
 abs_srcdir = @abs_srcdir@
diff --git a/README b/README
index 500d72234ab2037b78c908b71f7b07ccf0bf8640..2b98bbce3c1cf7fe7298d41ed7ef881a311059f7 100644 (file)
--- a/README
+++ b/README
@@ -7,7 +7,7 @@ Supported operating systems:
 
 * GNU/Linux
 * Mac OS X 10.5 or later
-* OpenBSD
+* FreeBSD
 
 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.
 
index 8745e0ddf0cc01745bd9045e78ae1568329ad977..73c422d5b83e790484057c7864c3c22e5bfb3446 100644 (file)
@@ -20,6 +20,350 @@ You have another version of autoconf.  It may work, but is not guaranteed to.
 If you have problems, you may need to regenerate the build system entirely.
 To do so, use the procedure documented by the package, typically 'autoreconf'.])])
 
+# pkg.m4 - Macros to locate and utilise pkg-config.   -*- Autoconf -*-
+# serial 11 (pkg-config-0.29.1)
+
+dnl Copyright © 2004 Scott James Remnant <scott@netsplit.com>.
+dnl Copyright © 2012-2015 Dan Nicholson <dbn.lists@gmail.com>
+dnl
+dnl This program is free software; you can redistribute it and/or modify
+dnl it under the terms of the GNU General Public License as published by
+dnl the Free Software Foundation; either version 2 of the License, or
+dnl (at your option) any later version.
+dnl
+dnl This program is distributed in the hope that it will be useful, but
+dnl WITHOUT ANY WARRANTY; without even the implied warranty of
+dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+dnl General Public License for more details.
+dnl
+dnl You should have received a copy of the GNU General Public License
+dnl along with this program; if not, write to the Free Software
+dnl Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+dnl 02111-1307, USA.
+dnl
+dnl As a special exception to the GNU General Public License, if you
+dnl distribute this file as part of a program that contains a
+dnl configuration script generated by Autoconf, you may include it under
+dnl the same distribution terms that you use for the rest of that
+dnl program.
+
+dnl PKG_PREREQ(MIN-VERSION)
+dnl -----------------------
+dnl Since: 0.29
+dnl
+dnl Verify that the version of the pkg-config macros are at least
+dnl MIN-VERSION. Unlike PKG_PROG_PKG_CONFIG, which checks the user's
+dnl installed version of pkg-config, this checks the developer's version
+dnl of pkg.m4 when generating configure.
+dnl
+dnl To ensure that this macro is defined, also add:
+dnl m4_ifndef([PKG_PREREQ],
+dnl     [m4_fatal([must install pkg-config 0.29 or later before running autoconf/autogen])])
+dnl
+dnl See the "Since" comment for each macro you use to see what version
+dnl of the macros you require.
+m4_defun([PKG_PREREQ],
+[m4_define([PKG_MACROS_VERSION], [0.29.1])
+m4_if(m4_version_compare(PKG_MACROS_VERSION, [$1]), -1,
+    [m4_fatal([pkg.m4 version $1 or higher is required but ]PKG_MACROS_VERSION[ found])])
+])dnl PKG_PREREQ
+
+dnl PKG_PROG_PKG_CONFIG([MIN-VERSION])
+dnl ----------------------------------
+dnl Since: 0.16
+dnl
+dnl Search for the pkg-config tool and set the PKG_CONFIG variable to
+dnl first found in the path. Checks that the version of pkg-config found
+dnl is at least MIN-VERSION. If MIN-VERSION is not specified, 0.9.0 is
+dnl used since that's the first version where most current features of
+dnl pkg-config existed.
+AC_DEFUN([PKG_PROG_PKG_CONFIG],
+[m4_pattern_forbid([^_?PKG_[A-Z_]+$])
+m4_pattern_allow([^PKG_CONFIG(_(PATH|LIBDIR|SYSROOT_DIR|ALLOW_SYSTEM_(CFLAGS|LIBS)))?$])
+m4_pattern_allow([^PKG_CONFIG_(DISABLE_UNINSTALLED|TOP_BUILD_DIR|DEBUG_SPEW)$])
+AC_ARG_VAR([PKG_CONFIG], [path to pkg-config utility])
+AC_ARG_VAR([PKG_CONFIG_PATH], [directories to add to pkg-config's search path])
+AC_ARG_VAR([PKG_CONFIG_LIBDIR], [path overriding pkg-config's built-in search path])
+
+if test "x$ac_cv_env_PKG_CONFIG_set" != "xset"; then
+       AC_PATH_TOOL([PKG_CONFIG], [pkg-config])
+fi
+if test -n "$PKG_CONFIG"; then
+       _pkg_min_version=m4_default([$1], [0.9.0])
+       AC_MSG_CHECKING([pkg-config is at least version $_pkg_min_version])
+       if $PKG_CONFIG --atleast-pkgconfig-version $_pkg_min_version; then
+               AC_MSG_RESULT([yes])
+       else
+               AC_MSG_RESULT([no])
+               PKG_CONFIG=""
+       fi
+fi[]dnl
+])dnl PKG_PROG_PKG_CONFIG
+
+dnl PKG_CHECK_EXISTS(MODULES, [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND])
+dnl -------------------------------------------------------------------
+dnl Since: 0.18
+dnl
+dnl Check to see whether a particular set of modules exists. Similar to
+dnl PKG_CHECK_MODULES(), but does not set variables or print errors.
+dnl
+dnl Please remember that m4 expands AC_REQUIRE([PKG_PROG_PKG_CONFIG])
+dnl only at the first occurence in configure.ac, so if the first place
+dnl it's called might be skipped (such as if it is within an "if", you
+dnl have to call PKG_CHECK_EXISTS manually
+AC_DEFUN([PKG_CHECK_EXISTS],
+[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl
+if test -n "$PKG_CONFIG" && \
+    AC_RUN_LOG([$PKG_CONFIG --exists --print-errors "$1"]); then
+  m4_default([$2], [:])
+m4_ifvaln([$3], [else
+  $3])dnl
+fi])
+
+dnl _PKG_CONFIG([VARIABLE], [COMMAND], [MODULES])
+dnl ---------------------------------------------
+dnl Internal wrapper calling pkg-config via PKG_CONFIG and setting
+dnl pkg_failed based on the result.
+m4_define([_PKG_CONFIG],
+[if test -n "$$1"; then
+    pkg_cv_[]$1="$$1"
+ elif test -n "$PKG_CONFIG"; then
+    PKG_CHECK_EXISTS([$3],
+                     [pkg_cv_[]$1=`$PKG_CONFIG --[]$2 "$3" 2>/dev/null`
+                     test "x$?" != "x0" && pkg_failed=yes ],
+                    [pkg_failed=yes])
+ else
+    pkg_failed=untried
+fi[]dnl
+])dnl _PKG_CONFIG
+
+dnl _PKG_SHORT_ERRORS_SUPPORTED
+dnl ---------------------------
+dnl Internal check to see if pkg-config supports short errors.
+AC_DEFUN([_PKG_SHORT_ERRORS_SUPPORTED],
+[AC_REQUIRE([PKG_PROG_PKG_CONFIG])
+if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then
+        _pkg_short_errors_supported=yes
+else
+        _pkg_short_errors_supported=no
+fi[]dnl
+])dnl _PKG_SHORT_ERRORS_SUPPORTED
+
+
+dnl PKG_CHECK_MODULES(VARIABLE-PREFIX, MODULES, [ACTION-IF-FOUND],
+dnl   [ACTION-IF-NOT-FOUND])
+dnl --------------------------------------------------------------
+dnl Since: 0.4.0
+dnl
+dnl Note that if there is a possibility the first call to
+dnl PKG_CHECK_MODULES might not happen, you should be sure to include an
+dnl explicit call to PKG_PROG_PKG_CONFIG in your configure.ac
+AC_DEFUN([PKG_CHECK_MODULES],
+[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl
+AC_ARG_VAR([$1][_CFLAGS], [C compiler flags for $1, overriding pkg-config])dnl
+AC_ARG_VAR([$1][_LIBS], [linker flags for $1, overriding pkg-config])dnl
+
+pkg_failed=no
+AC_MSG_CHECKING([for $1])
+
+_PKG_CONFIG([$1][_CFLAGS], [cflags], [$2])
+_PKG_CONFIG([$1][_LIBS], [libs], [$2])
+
+m4_define([_PKG_TEXT], [Alternatively, you may set the environment variables $1[]_CFLAGS
+and $1[]_LIBS to avoid the need to call pkg-config.
+See the pkg-config man page for more details.])
+
+if test $pkg_failed = yes; then
+       AC_MSG_RESULT([no])
+        _PKG_SHORT_ERRORS_SUPPORTED
+        if test $_pkg_short_errors_supported = yes; then
+               $1[]_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "$2" 2>&1`
+        else 
+               $1[]_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "$2" 2>&1`
+        fi
+       # Put the nasty error message in config.log where it belongs
+       echo "$$1[]_PKG_ERRORS" >&AS_MESSAGE_LOG_FD
+
+       m4_default([$4], [AC_MSG_ERROR(
+[Package requirements ($2) were not met:
+
+$$1_PKG_ERRORS
+
+Consider adjusting the PKG_CONFIG_PATH environment variable if you
+installed software in a non-standard prefix.
+
+_PKG_TEXT])[]dnl
+        ])
+elif test $pkg_failed = untried; then
+       AC_MSG_RESULT([no])
+       m4_default([$4], [AC_MSG_FAILURE(
+[The pkg-config script could not be found or is too old.  Make sure it
+is in your PATH or set the PKG_CONFIG environment variable to the full
+path to pkg-config.
+
+_PKG_TEXT
+
+To get pkg-config, see <http://pkg-config.freedesktop.org/>.])[]dnl
+        ])
+else
+       $1[]_CFLAGS=$pkg_cv_[]$1[]_CFLAGS
+       $1[]_LIBS=$pkg_cv_[]$1[]_LIBS
+        AC_MSG_RESULT([yes])
+       $3
+fi[]dnl
+])dnl PKG_CHECK_MODULES
+
+
+dnl PKG_CHECK_MODULES_STATIC(VARIABLE-PREFIX, MODULES, [ACTION-IF-FOUND],
+dnl   [ACTION-IF-NOT-FOUND])
+dnl ---------------------------------------------------------------------
+dnl Since: 0.29
+dnl
+dnl Checks for existence of MODULES and gathers its build flags with
+dnl static libraries enabled. Sets VARIABLE-PREFIX_CFLAGS from --cflags
+dnl and VARIABLE-PREFIX_LIBS from --libs.
+dnl
+dnl Note that if there is a possibility the first call to
+dnl PKG_CHECK_MODULES_STATIC might not happen, you should be sure to
+dnl include an explicit call to PKG_PROG_PKG_CONFIG in your
+dnl configure.ac.
+AC_DEFUN([PKG_CHECK_MODULES_STATIC],
+[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl
+_save_PKG_CONFIG=$PKG_CONFIG
+PKG_CONFIG="$PKG_CONFIG --static"
+PKG_CHECK_MODULES($@)
+PKG_CONFIG=$_save_PKG_CONFIG[]dnl
+])dnl PKG_CHECK_MODULES_STATIC
+
+
+dnl PKG_INSTALLDIR([DIRECTORY])
+dnl -------------------------
+dnl Since: 0.27
+dnl
+dnl Substitutes the variable pkgconfigdir as the location where a module
+dnl should install pkg-config .pc files. By default the directory is
+dnl $libdir/pkgconfig, but the default can be changed by passing
+dnl DIRECTORY. The user can override through the --with-pkgconfigdir
+dnl parameter.
+AC_DEFUN([PKG_INSTALLDIR],
+[m4_pushdef([pkg_default], [m4_default([$1], ['${libdir}/pkgconfig'])])
+m4_pushdef([pkg_description],
+    [pkg-config installation directory @<:@]pkg_default[@:>@])
+AC_ARG_WITH([pkgconfigdir],
+    [AS_HELP_STRING([--with-pkgconfigdir], pkg_description)],,
+    [with_pkgconfigdir=]pkg_default)
+AC_SUBST([pkgconfigdir], [$with_pkgconfigdir])
+m4_popdef([pkg_default])
+m4_popdef([pkg_description])
+])dnl PKG_INSTALLDIR
+
+
+dnl PKG_NOARCH_INSTALLDIR([DIRECTORY])
+dnl --------------------------------
+dnl Since: 0.27
+dnl
+dnl Substitutes the variable noarch_pkgconfigdir as the location where a
+dnl module should install arch-independent pkg-config .pc files. By
+dnl default the directory is $datadir/pkgconfig, but the default can be
+dnl changed by passing DIRECTORY. The user can override through the
+dnl --with-noarch-pkgconfigdir parameter.
+AC_DEFUN([PKG_NOARCH_INSTALLDIR],
+[m4_pushdef([pkg_default], [m4_default([$1], ['${datadir}/pkgconfig'])])
+m4_pushdef([pkg_description],
+    [pkg-config arch-independent installation directory @<:@]pkg_default[@:>@])
+AC_ARG_WITH([noarch-pkgconfigdir],
+    [AS_HELP_STRING([--with-noarch-pkgconfigdir], pkg_description)],,
+    [with_noarch_pkgconfigdir=]pkg_default)
+AC_SUBST([noarch_pkgconfigdir], [$with_noarch_pkgconfigdir])
+m4_popdef([pkg_default])
+m4_popdef([pkg_description])
+])dnl PKG_NOARCH_INSTALLDIR
+
+
+dnl PKG_CHECK_VAR(VARIABLE, MODULE, CONFIG-VARIABLE,
+dnl [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND])
+dnl -------------------------------------------
+dnl Since: 0.28
+dnl
+dnl Retrieves the value of the pkg-config variable for the given module.
+AC_DEFUN([PKG_CHECK_VAR],
+[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl
+AC_ARG_VAR([$1], [value of $3 for $2, overriding pkg-config])dnl
+
+_PKG_CONFIG([$1], [variable="][$3]["], [$2])
+AS_VAR_COPY([$1], [pkg_cv_][$1])
+
+AS_VAR_IF([$1], [""], [$5], [$4])dnl
+])dnl PKG_CHECK_VAR
+
+dnl PKG_WITH_MODULES(VARIABLE-PREFIX, MODULES,
+dnl   [ACTION-IF-FOUND],[ACTION-IF-NOT-FOUND],
+dnl   [DESCRIPTION], [DEFAULT])
+dnl ------------------------------------------
+dnl
+dnl Prepare a "--with-" configure option using the lowercase
+dnl [VARIABLE-PREFIX] name, merging the behaviour of AC_ARG_WITH and
+dnl PKG_CHECK_MODULES in a single macro.
+AC_DEFUN([PKG_WITH_MODULES],
+[
+m4_pushdef([with_arg], m4_tolower([$1]))
+
+m4_pushdef([description],
+           [m4_default([$5], [build with ]with_arg[ support])])
+
+m4_pushdef([def_arg], [m4_default([$6], [auto])])
+m4_pushdef([def_action_if_found], [AS_TR_SH([with_]with_arg)=yes])
+m4_pushdef([def_action_if_not_found], [AS_TR_SH([with_]with_arg)=no])
+
+m4_case(def_arg,
+            [yes],[m4_pushdef([with_without], [--without-]with_arg)],
+            [m4_pushdef([with_without],[--with-]with_arg)])
+
+AC_ARG_WITH(with_arg,
+     AS_HELP_STRING(with_without, description[ @<:@default=]def_arg[@:>@]),,
+    [AS_TR_SH([with_]with_arg)=def_arg])
+
+AS_CASE([$AS_TR_SH([with_]with_arg)],
+            [yes],[PKG_CHECK_MODULES([$1],[$2],$3,$4)],
+            [auto],[PKG_CHECK_MODULES([$1],[$2],
+                                        [m4_n([def_action_if_found]) $3],
+                                        [m4_n([def_action_if_not_found]) $4])])
+
+m4_popdef([with_arg])
+m4_popdef([description])
+m4_popdef([def_arg])
+
+])dnl PKG_WITH_MODULES
+
+dnl PKG_HAVE_WITH_MODULES(VARIABLE-PREFIX, MODULES,
+dnl   [DESCRIPTION], [DEFAULT])
+dnl -----------------------------------------------
+dnl
+dnl Convenience macro to trigger AM_CONDITIONAL after PKG_WITH_MODULES
+dnl check._[VARIABLE-PREFIX] is exported as make variable.
+AC_DEFUN([PKG_HAVE_WITH_MODULES],
+[
+PKG_WITH_MODULES([$1],[$2],,,[$3],[$4])
+
+AM_CONDITIONAL([HAVE_][$1],
+               [test "$AS_TR_SH([with_]m4_tolower([$1]))" = "yes"])
+])dnl PKG_HAVE_WITH_MODULES
+
+dnl PKG_HAVE_DEFINE_WITH_MODULES(VARIABLE-PREFIX, MODULES,
+dnl   [DESCRIPTION], [DEFAULT])
+dnl ------------------------------------------------------
+dnl
+dnl Convenience macro to run AM_CONDITIONAL and AC_DEFINE after
+dnl PKG_WITH_MODULES check. HAVE_[VARIABLE-PREFIX] is exported as make
+dnl and preprocessor variable.
+AC_DEFUN([PKG_HAVE_DEFINE_WITH_MODULES],
+[
+PKG_HAVE_WITH_MODULES([$1],[$2],[$3],[$4])
+
+AS_IF([test "$AS_TR_SH([with_]m4_tolower([$1]))" = "yes"],
+        [AC_DEFINE([HAVE_][$1], 1, [Enable ]m4_tolower([$1])[ support])])
+])dnl PKG_HAVE_DEFINE_WITH_MODULES
+
 # Copyright (C) 2002-2017 Free Software Foundation, Inc.
 #
 # This file is free software; the Free Software Foundation
index 5f0c1a91356c4c1a7f2061bc8a0d1ca23719c780..36cf8ef22e89d2500e12d5ee737a6861d18d7699 100755 (executable)
--- 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.8.
+# Generated by GNU Autoconf 2.69 for Free exFAT implementation 1.3.0.
 #
 # Report bugs to <relan@users.noreply.github.com>.
 #
@@ -579,8 +579,8 @@ MAKEFLAGS=
 # Identity of this package.
 PACKAGE_NAME='Free exFAT implementation'
 PACKAGE_TARNAME='exfat-utils'
-PACKAGE_VERSION='1.2.8'
-PACKAGE_STRING='Free exFAT implementation 1.2.8'
+PACKAGE_VERSION='1.3.0'
+PACKAGE_STRING='Free exFAT implementation 1.3.0'
 PACKAGE_BUGREPORT='relan@users.noreply.github.com'
 PACKAGE_URL='https://github.com/relan/exfat'
 
@@ -588,6 +588,11 @@ ac_subst_vars='am__EXEEXT_FALSE
 am__EXEEXT_TRUE
 LTLIBOBJS
 LIBOBJS
+UBLIO_LIBS
+UBLIO_CFLAGS
+PKG_CONFIG_LIBDIR
+PKG_CONFIG_PATH
+PKG_CONFIG
 ac_ct_AR
 AR
 RANLIB
@@ -687,7 +692,12 @@ CC
 CFLAGS
 LDFLAGS
 LIBS
-CPPFLAGS'
+CPPFLAGS
+PKG_CONFIG
+PKG_CONFIG_PATH
+PKG_CONFIG_LIBDIR
+UBLIO_CFLAGS
+UBLIO_LIBS'
 
 
 # Initialize some variables set by options.
@@ -1228,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.8 to adapt to many kinds of systems.
+\`configure' configures Free exFAT implementation 1.3.0 to adapt to many kinds of systems.
 
 Usage: $0 [OPTION]... [VAR=VALUE]...
 
@@ -1294,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.8:";;
+     short | recursive ) echo "Configuration of Free exFAT implementation 1.3.0:";;
    esac
   cat <<\_ACEOF
 
@@ -1318,6 +1328,14 @@ Some influential environment variables:
   LIBS        libraries to pass to the linker, e.g. -l<library>
   CPPFLAGS    (Objective) C/C++ preprocessor flags, e.g. -I<include dir> if
               you have headers in a nonstandard directory <include dir>
+  PKG_CONFIG  path to pkg-config utility
+  PKG_CONFIG_PATH
+              directories to add to pkg-config's search path
+  PKG_CONFIG_LIBDIR
+              path overriding pkg-config's built-in search path
+  UBLIO_CFLAGS
+              C compiler flags for UBLIO, overriding pkg-config
+  UBLIO_LIBS  linker flags for UBLIO, overriding pkg-config
 
 Use these variables to override the choices made by `configure' or to help
 it to find libraries and programs with nonstandard names/locations.
@@ -1386,7 +1404,7 @@ fi
 test -n "$ac_init_help" && exit $ac_status
 if $ac_init_version; then
   cat <<\_ACEOF
-Free exFAT implementation configure 1.2.8
+Free exFAT implementation configure 1.3.0
 generated by GNU Autoconf 2.69
 
 Copyright (C) 2012 Free Software Foundation, Inc.
@@ -1441,7 +1459,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.8, which was
+It was created by Free exFAT implementation $as_me 1.3.0, which was
 generated by GNU Autoconf 2.69.  Invocation command line was
 
   $ $0 $@
@@ -2304,7 +2322,7 @@ fi
 
 # Define the identity of the package.
  PACKAGE='exfat-utils'
- VERSION='1.2.8'
+ VERSION='1.3.0'
 
 
 cat >>confdefs.h <<_ACEOF
@@ -4077,6 +4095,203 @@ rm -rf conftest*
 
 fi
 
+
+
+
+
+
+
+
+if test "x$ac_cv_env_PKG_CONFIG_set" != "xset"; then
+       if test -n "$ac_tool_prefix"; then
+  # Extract the first word of "${ac_tool_prefix}pkg-config", so it can be a program name with args.
+set dummy ${ac_tool_prefix}pkg-config; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_path_PKG_CONFIG+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  case $PKG_CONFIG in
+  [\\/]* | ?:[\\/]*)
+  ac_cv_path_PKG_CONFIG="$PKG_CONFIG" # Let the user override the test with a path.
+  ;;
+  *)
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_path_PKG_CONFIG="$as_dir/$ac_word$ac_exec_ext"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+  ;;
+esac
+fi
+PKG_CONFIG=$ac_cv_path_PKG_CONFIG
+if test -n "$PKG_CONFIG"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $PKG_CONFIG" >&5
+$as_echo "$PKG_CONFIG" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_path_PKG_CONFIG"; then
+  ac_pt_PKG_CONFIG=$PKG_CONFIG
+  # Extract the first word of "pkg-config", so it can be a program name with args.
+set dummy pkg-config; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_path_ac_pt_PKG_CONFIG+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  case $ac_pt_PKG_CONFIG in
+  [\\/]* | ?:[\\/]*)
+  ac_cv_path_ac_pt_PKG_CONFIG="$ac_pt_PKG_CONFIG" # Let the user override the test with a path.
+  ;;
+  *)
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_path_ac_pt_PKG_CONFIG="$as_dir/$ac_word$ac_exec_ext"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+  ;;
+esac
+fi
+ac_pt_PKG_CONFIG=$ac_cv_path_ac_pt_PKG_CONFIG
+if test -n "$ac_pt_PKG_CONFIG"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_pt_PKG_CONFIG" >&5
+$as_echo "$ac_pt_PKG_CONFIG" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+  if test "x$ac_pt_PKG_CONFIG" = x; then
+    PKG_CONFIG=""
+  else
+    case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+    PKG_CONFIG=$ac_pt_PKG_CONFIG
+  fi
+else
+  PKG_CONFIG="$ac_cv_path_PKG_CONFIG"
+fi
+
+fi
+if test -n "$PKG_CONFIG"; then
+       _pkg_min_version=0.9.0
+       { $as_echo "$as_me:${as_lineno-$LINENO}: checking pkg-config is at least version $_pkg_min_version" >&5
+$as_echo_n "checking pkg-config is at least version $_pkg_min_version... " >&6; }
+       if $PKG_CONFIG --atleast-pkgconfig-version $_pkg_min_version; then
+               { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+       else
+               { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+               PKG_CONFIG=""
+       fi
+fi
+
+pkg_failed=no
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for UBLIO" >&5
+$as_echo_n "checking for UBLIO... " >&6; }
+
+if test -n "$UBLIO_CFLAGS"; then
+    pkg_cv_UBLIO_CFLAGS="$UBLIO_CFLAGS"
+ elif test -n "$PKG_CONFIG"; then
+    if test -n "$PKG_CONFIG" && \
+    { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libublio\""; } >&5
+  ($PKG_CONFIG --exists --print-errors "libublio") 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; then
+  pkg_cv_UBLIO_CFLAGS=`$PKG_CONFIG --cflags "libublio" 2>/dev/null`
+                     test "x$?" != "x0" && pkg_failed=yes
+else
+  pkg_failed=yes
+fi
+ else
+    pkg_failed=untried
+fi
+if test -n "$UBLIO_LIBS"; then
+    pkg_cv_UBLIO_LIBS="$UBLIO_LIBS"
+ elif test -n "$PKG_CONFIG"; then
+    if test -n "$PKG_CONFIG" && \
+    { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libublio\""; } >&5
+  ($PKG_CONFIG --exists --print-errors "libublio") 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; then
+  pkg_cv_UBLIO_LIBS=`$PKG_CONFIG --libs "libublio" 2>/dev/null`
+                     test "x$?" != "x0" && pkg_failed=yes
+else
+  pkg_failed=yes
+fi
+ else
+    pkg_failed=untried
+fi
+
+
+
+if test $pkg_failed = yes; then
+       { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+
+if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then
+        _pkg_short_errors_supported=yes
+else
+        _pkg_short_errors_supported=no
+fi
+        if test $_pkg_short_errors_supported = yes; then
+               UBLIO_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "libublio" 2>&1`
+        else
+               UBLIO_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "libublio" 2>&1`
+        fi
+       # Put the nasty error message in config.log where it belongs
+       echo "$UBLIO_PKG_ERRORS" >&5
+
+       :
+elif test $pkg_failed = untried; then
+       { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+       :
+else
+       UBLIO_CFLAGS=$pkg_cv_UBLIO_CFLAGS
+       UBLIO_LIBS=$pkg_cv_UBLIO_LIBS
+        { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+
+  CFLAGS="$CFLAGS $UBLIO_CFLAGS"
+  LIBS="$LIBS $UBLIO_LIBS"
+
+$as_echo "#define USE_UBLIO 1" >>confdefs.h
+
+
+fi
 ac_config_headers="$ac_config_headers libexfat/config.h"
 
 ac_config_files="$ac_config_files libexfat/Makefile dump/Makefile fsck/Makefile label/Makefile mkfs/Makefile Makefile"
@@ -4611,7 +4826,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.8, which was
+This file was extended by Free exFAT implementation $as_me 1.3.0, which was
 generated by GNU Autoconf 2.69.  Invocation command line was
 
   CONFIG_FILES    = $CONFIG_FILES
@@ -4678,7 +4893,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.8
+Free exFAT implementation config.status 1.3.0
 configured by $0, generated by GNU Autoconf 2.69,
   with options \\"\$ac_cs_config\\"
 
index 8bcb12850833120889b3c7b941fc71b3c6251b7c..6a517ea4b5b542ceacf890c92249d3bfb7d51689 100644 (file)
@@ -21,7 +21,7 @@
 #
 
 AC_INIT([Free exFAT implementation],
-       [1.2.8],
+       [1.3.0],
        [relan@users.noreply.github.com],
        [exfat-utils],
        [https://github.com/relan/exfat])
@@ -31,6 +31,12 @@ AC_PROG_CC_C99
 AC_PROG_RANLIB
 AM_PROG_AR
 AC_SYS_LARGEFILE
+PKG_CHECK_MODULES([UBLIO], [libublio], [
+  CFLAGS="$CFLAGS $UBLIO_CFLAGS"
+  LIBS="$LIBS $UBLIO_LIBS"
+  AC_DEFINE([USE_UBLIO], [1],
+    [Define if block devices are not supported.])
+], [:])
 AC_CONFIG_HEADERS([libexfat/config.h])
 AC_CONFIG_FILES([
        libexfat/Makefile
index a4f5a6c30c5e48fdcacdf80198586f64f84898d8..8d5600407adb72cff141e29b998f6feefca7dc70 100644 (file)
@@ -254,10 +254,15 @@ PACKAGE_TARNAME = @PACKAGE_TARNAME@
 PACKAGE_URL = @PACKAGE_URL@
 PACKAGE_VERSION = @PACKAGE_VERSION@
 PATH_SEPARATOR = @PATH_SEPARATOR@
+PKG_CONFIG = @PKG_CONFIG@
+PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
+PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
 RANLIB = @RANLIB@
 SET_MAKE = @SET_MAKE@
 SHELL = @SHELL@
 STRIP = @STRIP@
+UBLIO_CFLAGS = @UBLIO_CFLAGS@
+UBLIO_LIBS = @UBLIO_LIBS@
 VERSION = @VERSION@
 abs_builddir = @abs_builddir@
 abs_srcdir = @abs_srcdir@
index 9408a62837bbc4bf4b3e891dd9bd7960e90aff7f..06022a5ddb470a8f2b6092156989c7056ece26f1 100644 (file)
@@ -1,6 +1,6 @@
-.\" Copyright (C) 2011-2016  Andrew Nayenko
+.\" Copyright (C) 2011-2018  Andrew Nayenko
 .\"
-.TH DUMPEXFAT 8 "February 2011"
+.TH DUMPEXFAT 8 "July 2016"
 .SH NAME
 .B dumpexfat
 \- dump exFAT file system
index ab380291ad39bae1c7b0ecc972fe8189f1680c28..f70f6641984f8886a6a1f5fe8a9a2d3ab5588178 100644 (file)
@@ -254,10 +254,15 @@ PACKAGE_TARNAME = @PACKAGE_TARNAME@
 PACKAGE_URL = @PACKAGE_URL@
 PACKAGE_VERSION = @PACKAGE_VERSION@
 PATH_SEPARATOR = @PATH_SEPARATOR@
+PKG_CONFIG = @PKG_CONFIG@
+PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
+PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
 RANLIB = @RANLIB@
 SET_MAKE = @SET_MAKE@
 SHELL = @SHELL@
 STRIP = @STRIP@
+UBLIO_CFLAGS = @UBLIO_CFLAGS@
+UBLIO_LIBS = @UBLIO_LIBS@
 VERSION = @VERSION@
 abs_builddir = @abs_builddir@
 abs_srcdir = @abs_srcdir@
index b0a788ab7827c92e3afec8aec3fa41429ee762ce..a641b6ca91c6dd957fd52c0ef90a3b16719688a7 100644 (file)
@@ -1,26 +1,49 @@
-.\" Copyright (C) 2011-2016  Andrew Nayenko
+.\" Copyright (C) 2011-2018  Andrew Nayenko
 .\"
-.TH EXFATFSCK 8 "February 2011"
+.TH EXFATFSCK 8 "September 2018"
 .SH NAME
 .B exfatfsck
 \- check an exFAT file system
 .SH SYNOPSIS
 .B exfatfsck
 [
-.B \-V
+.B \-a
+|
+.B \-n
+|
+.B \-p
+|
+.B \-y
 ]
 .I device
+.br
+.B exfatfsck
+[
+.B \-V
+]
 
 .SH DESCRIPTION
 .B exfatfsck
-checks an exFAT file system for errors. Note that it cannot repair corrupted
-FS, it just reports found errors.
+checks an exFAT file system for errors. It can repair some of them.
 
 .SH COMMAND LINE OPTIONS
 Command line options available:
 .TP
+.BI \-a
+Automatically repair the file system. No user intervention required.
+.TP
+.BI \-n
+No-operation mode: non-interactively check for errors, but don't write
+anything to the file system.
+.TP
+.BI \-p
+Same as \fB\-a\fR for compatibility with other *fsck.
+.TP
 .BI \-V
 Print version and copyright.
+.TP
+.BI \-y
+Same as \fB\-a\fR for compatibility with other *fsck.
 
 .SH EXIT CODES
 Zero is returned if errors were not found. Any other code means an error.
index 1eb4c1e9bede3b65bb245568e8316930b4039d8e..af40c76ad2b098cf113356b732fea4025ccee89b 100644 (file)
@@ -114,37 +114,65 @@ static void dirck(struct exfat* ef, const char* path)
                        files_count++;
                        nodeck(ef, node);
                }
+               exfat_flush_node(ef, node);
                exfat_put_node(ef, node);
        }
        exfat_closedir(ef, &it);
+       exfat_flush_node(ef, parent);
        exfat_put_node(ef, parent);
        free(entry_path);
 }
 
-static void fsck(struct exfat* ef)
+static void fsck(struct exfat* ef, const char* spec, const char* options)
 {
+       if (exfat_mount(ef, spec, options) != 0)
+       {
+               fputs("File system checking stopped. ", stdout);
+               return;
+       }
+
        exfat_print_info(ef->sb, exfat_count_free_clusters(ef));
        dirck(ef, "");
+       exfat_unmount(ef);
+
+       printf("Totally %"PRIu64" directories and %"PRIu64" files.\n",
+                       directories_count, files_count);
+       fputs("File system checking finished. ", stdout);
 }
 
 static void usage(const char* prog)
 {
-       fprintf(stderr, "Usage: %s [-V] <device>\n", prog);
+       fprintf(stderr, "Usage: %s [-a | -n | -p | -y] <device>\n", prog);
+       fprintf(stderr, "       %s -V\n", prog);
        exit(1);
 }
 
 int main(int argc, char* argv[])
 {
        int opt;
+       const char* options;
        const char* spec = NULL;
        struct exfat ef;
 
        printf("exfatfsck %s\n", VERSION);
 
-       while ((opt = getopt(argc, argv, "V")) != -1)
+       if (isatty(STDIN_FILENO))
+               options = "repair=1";
+       else
+               options = "repair=0";
+
+       while ((opt = getopt(argc, argv, "anpVy")) != -1)
        {
                switch (opt)
                {
+               case 'a':
+               case 'p':
+               case 'y':
+                       options = "repair=2";
+                       break;
+               case 'n':
+                       options = "repair=0,ro";
+                       break;
                case 'V':
                        puts("Copyright (C) 2011-2018  Andrew Nayenko");
                        return 0;
@@ -157,19 +185,12 @@ int main(int argc, char* argv[])
                usage(argv[0]);
        spec = argv[optind];
 
-       if (exfat_mount(&ef, spec, "ro") != 0)
-               return 1;
-
        printf("Checking file system on %s.\n", spec);
-       fsck(&ef);
-       exfat_unmount(&ef);
-       printf("Totally %"PRIu64" directories and %"PRIu64" files.\n",
-                       directories_count, files_count);
-
-       fputs("File system checking finished. ", stdout);
+       fsck(&ef, spec, options);
        if (exfat_errors != 0)
        {
-               printf("ERRORS FOUND: %d.\n", exfat_errors);
+               printf("ERRORS FOUND: %d, FIXED: %d.\n",
+                               exfat_errors, exfat_errors_fixed);
                return 1;
        }
        puts("No errors found.");
index 63cccc6cfc3da7a3afc9acf8c6eaa9333db96d98..745bf23853f5287322c6c6aae6fa4df8b3c32e59 100644 (file)
@@ -254,10 +254,15 @@ PACKAGE_TARNAME = @PACKAGE_TARNAME@
 PACKAGE_URL = @PACKAGE_URL@
 PACKAGE_VERSION = @PACKAGE_VERSION@
 PATH_SEPARATOR = @PATH_SEPARATOR@
+PKG_CONFIG = @PKG_CONFIG@
+PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
+PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
 RANLIB = @RANLIB@
 SET_MAKE = @SET_MAKE@
 SHELL = @SHELL@
 STRIP = @STRIP@
+UBLIO_CFLAGS = @UBLIO_CFLAGS@
+UBLIO_LIBS = @UBLIO_LIBS@
 VERSION = @VERSION@
 abs_builddir = @abs_builddir@
 abs_srcdir = @abs_srcdir@
index a7b1292ce0d3dce8983477e3164f10196b790592..4f55510b67b8e59396b7cf988f5935c20b2f820e 100644 (file)
@@ -1,6 +1,6 @@
-.\" Copyright (C) 2011-2016  Andrew Nayenko
+.\" Copyright (C) 2011-2018  Andrew Nayenko
 .\"
-.TH EXFATLABEL 8 "February 2011"
+.TH EXFATLABEL 8 "September 2017"
 .SH NAME
 .B exfatlabel
 \- get or set an exFAT file system label
index 4ec9df5c93fe89a27263e3ed2e959995bd734a55..d639e13b799b2d2b0599044fa0a97b5a9baea191 100644 (file)
@@ -33,6 +33,7 @@ libexfat_a_SOURCES = \
        mount.c \
        node.c \
        platform.h \
+       repair.c \
        time.c \
        utf.c \
        utils.c
index 47bfa2ff697e77bc4f8464f8123de7c5781004de..891447a928e89cc4fa20b4879ff1c43c263e92b2 100644 (file)
@@ -127,8 +127,8 @@ am__v_AR_1 =
 libexfat_a_AR = $(AR) $(ARFLAGS)
 libexfat_a_LIBADD =
 am_libexfat_a_OBJECTS = cluster.$(OBJEXT) io.$(OBJEXT) log.$(OBJEXT) \
-       lookup.$(OBJEXT) mount.$(OBJEXT) node.$(OBJEXT) time.$(OBJEXT) \
-       utf.$(OBJEXT) utils.$(OBJEXT)
+       lookup.$(OBJEXT) mount.$(OBJEXT) node.$(OBJEXT) \
+       repair.$(OBJEXT) time.$(OBJEXT) utf.$(OBJEXT) utils.$(OBJEXT)
 libexfat_a_OBJECTS = $(am_libexfat_a_OBJECTS)
 AM_V_P = $(am__v_P_@AM_V@)
 am__v_P_ = $(am__v_P_@AM_DEFAULT_V@)
@@ -227,10 +227,15 @@ PACKAGE_TARNAME = @PACKAGE_TARNAME@
 PACKAGE_URL = @PACKAGE_URL@
 PACKAGE_VERSION = @PACKAGE_VERSION@
 PATH_SEPARATOR = @PATH_SEPARATOR@
+PKG_CONFIG = @PKG_CONFIG@
+PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
+PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
 RANLIB = @RANLIB@
 SET_MAKE = @SET_MAKE@
 SHELL = @SHELL@
 STRIP = @STRIP@
+UBLIO_CFLAGS = @UBLIO_CFLAGS@
+UBLIO_LIBS = @UBLIO_LIBS@
 VERSION = @VERSION@
 abs_builddir = @abs_builddir@
 abs_srcdir = @abs_srcdir@
@@ -288,6 +293,7 @@ libexfat_a_SOURCES = \
        mount.c \
        node.c \
        platform.h \
+       repair.c \
        time.c \
        utf.c \
        utils.c
@@ -362,6 +368,7 @@ distclean-compile:
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lookup.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mount.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/node.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/repair.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/time.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/utf.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/utils.Po@am__quote@
index d096cd307d649e5ab2b147dc931acd6c2dc6136e..c3312ab6a2a7f4820d72486dc3925e7968cee670 100644 (file)
@@ -21,6 +21,9 @@
 /* Define to the version of this package. */
 #undef PACKAGE_VERSION
 
+/* Define if block devices are not supported. */
+#undef USE_UBLIO
+
 /* Version number of package */
 #undef VERSION
 
index e0d33e24ddb109783b235f65c882f591fd781a93..2342be4f531a5b0c489e81ee0710186b6a00dab2 100644 (file)
 #ifndef EXFAT_H_INCLUDED
 #define EXFAT_H_INCLUDED
 
+#ifndef ANDROID
+/* Android.bp is used instead of autotools when targeting Android */
 #include "config.h"
+#endif
 #include "compiler.h"
 #include "exfatfs.h"
 #include <stdio.h>
@@ -61,6 +64,9 @@
 #define BMAP_CLR(bitmap, index) \
        ((bitmap)[BMAP_BLOCK(index)] &= ~BMAP_MASK(index))
 
+#define EXFAT_REPAIR(hook, ef, ...) \
+       (exfat_ask_to_fix(ef) && exfat_fix_ ## hook(ef, __VA_ARGS__))
+
 /* The size of off_t type must be 64 bits. File systems larger than 2 GB will
    be corrupted with 32-bit off_t. */
 STATIC_ASSERT(sizeof(off_t) == 8);
@@ -119,6 +125,7 @@ struct exfat
        gid_t gid;
        int ro;
        bool noatime;
+       enum { EXFAT_REPAIR_NO, EXFAT_REPAIR_ASK, EXFAT_REPAIR_YES } repair;
 };
 
 /* in-core nodes iterator */
@@ -135,6 +142,7 @@ struct exfat_human_bytes
 };
 
 extern int exfat_errors;
+extern int exfat_errors_fixed;
 
 void exfat_bug(const char* format, ...) PRINTF NORETURN;
 void exfat_error(const char* format, ...) PRINTF;
@@ -225,4 +233,12 @@ void exfat_unix2exfat(time_t unix_time, le16_t* date, le16_t* time,
                uint8_t* centisec);
 void exfat_tzset(void);
 
+bool exfat_ask_to_fix(const struct exfat* ef);
+bool exfat_fix_invalid_vbr_checksum(const struct exfat* ef, void* sector,
+               uint32_t vbr_checksum);
+bool exfat_fix_invalid_node_checksum(const struct exfat* ef,
+               struct exfat_node* node);
+bool exfat_fix_unknown_entry(struct exfat* ef, struct exfat_node* dir,
+               const struct exfat_entry* entry, off_t offset);
+
 #endif /* ifndef EXFAT_H_INCLUDED */
index bae0cf15a1412dfdac2c67b4085d35aa56361bc6..bc92c7cf9eab396eb465b93400cff7fc448a778b 100644 (file)
 #elif __linux__
 #include <sys/mount.h>
 #endif
+#ifdef USE_UBLIO
+#include <sys/uio.h>
+#include <ublio.h>
+#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 bool is_open(int fd)
@@ -80,6 +88,9 @@ 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
 
        /* The system allocates file descriptors sequentially. If we have been
           started with stdin (0), stdout (1) or stderr (2) closed, the system
@@ -235,6 +246,24 @@ 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;
 }
 
@@ -242,6 +271,13 @@ 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));
@@ -255,6 +291,13 @@ 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));
@@ -275,29 +318,56 @@ 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,
index d62bf757128eea39d5a1f53f3b6d3da1c28561f4..f29f74b1d68c22f7702532a5bb933ea8709edc3b 100644 (file)
 
 #include "exfat.h"
 #include <stdarg.h>
+#ifdef __ANDROID__
+#include <android/log.h>
+#else
 #include <syslog.h>
+#endif
 #include <unistd.h>
 
 int exfat_errors;
@@ -43,8 +47,12 @@ void exfat_bug(const char* format, ...)
        va_end(ap);
        fputs(".\n", stderr);
 
+#ifdef __ANDROID__
+       __android_log_vprint(ANDROID_LOG_FATAL, PACKAGE, format, aq);
+#else
        if (!isatty(STDERR_FILENO))
                vsyslog(LOG_CRIT, format, aq);
+#endif
        va_end(aq);
 
        abort();
@@ -67,8 +75,12 @@ void exfat_error(const char* format, ...)
        va_end(ap);
        fputs(".\n", stderr);
 
+#ifdef __ANDROID__
+       __android_log_vprint(ANDROID_LOG_ERROR, PACKAGE, format, aq);
+#else
        if (!isatty(STDERR_FILENO))
                vsyslog(LOG_ERR, format, aq);
+#endif
        va_end(aq);
 }
 
@@ -89,8 +101,12 @@ void exfat_warn(const char* format, ...)
        va_end(ap);
        fputs(".\n", stderr);
 
+#ifdef __ANDROID__
+       __android_log_vprint(ANDROID_LOG_WARN, PACKAGE, format, aq);
+#else
        if (!isatty(STDERR_FILENO))
                vsyslog(LOG_WARNING, format, aq);
+#endif
        va_end(aq);
 }
 
index 3b18b122e43ea087ebf401b014d3bf3f509ccc29..4284aee676fd43105363eafd4bc7e5063f4fb45e 100644 (file)
@@ -103,15 +103,28 @@ static void parse_options(struct exfat* ef, const char* options)
        ef->gid = get_int_option(options, "gid", 10, getegid());
 
        ef->noatime = match_option(options, "noatime");
+
+       switch (get_int_option(options, "repair", 10, 0))
+       {
+       case 1:
+               ef->repair = EXFAT_REPAIR_ASK;
+               break;
+       case 2:
+               ef->repair = EXFAT_REPAIR_YES;
+               break;
+       default:
+               ef->repair = EXFAT_REPAIR_NO;
+               break;
+       }
 }
 
-static bool verify_vbr_checksum(struct exfat_dev* dev, void* sector,
-               off_t sector_size)
+static bool verify_vbr_checksum(const struct exfat* ef, void* sector)
 {
+       off_t sector_size = SECTOR_SIZE(*ef->sb);
        uint32_t vbr_checksum;
        int i;
 
-       if (exfat_pread(dev, sector, sector_size, 0) < 0)
+       if (exfat_pread(ef->dev, sector, sector_size, 0) < 0)
        {
                exfat_error("failed to read boot sector");
                return false;
@@ -119,7 +132,7 @@ static bool verify_vbr_checksum(struct exfat_dev* dev, void* sector,
        vbr_checksum = exfat_vbr_start_checksum(sector, sector_size);
        for (i = 1; i < 11; i++)
        {
-               if (exfat_pread(dev, sector, sector_size, i * sector_size) < 0)
+               if (exfat_pread(ef->dev, sector, sector_size, i * sector_size) < 0)
                {
                        exfat_error("failed to read VBR sector");
                        return false;
@@ -127,7 +140,7 @@ static bool verify_vbr_checksum(struct exfat_dev* dev, void* sector,
                vbr_checksum = exfat_vbr_add_checksum(sector, sector_size,
                                vbr_checksum);
        }
-       if (exfat_pread(dev, sector, sector_size, i * sector_size) < 0)
+       if (exfat_pread(ef->dev, sector, sector_size, i * sector_size) < 0)
        {
                exfat_error("failed to read VBR checksum sector");
                return false;
@@ -137,7 +150,8 @@ static bool verify_vbr_checksum(struct exfat_dev* dev, void* sector,
                {
                        exfat_error("invalid VBR checksum 0x%x (expected 0x%x)",
                                        le32_to_cpu(((const le32_t*) sector)[i]), vbr_checksum);
-                       return false;
+                       if (!EXFAT_REPAIR(invalid_vbr_checksum, ef, sector, vbr_checksum))
+                               return false;
                }
        return true;
 }
@@ -252,7 +266,7 @@ int exfat_mount(struct exfat* ef, const char* spec, const char* options)
                return -ENOMEM;
        }
        /* use zero_cluster as a temporary buffer for VBR checksum verification */
-       if (!verify_vbr_checksum(ef->dev, ef->zero_cluster, SECTOR_SIZE(*ef->sb)))
+       if (!verify_vbr_checksum(ef, ef->zero_cluster))
        {
                exfat_free(ef);
                return -EIO;
index 1ccb1c9eda0d41ddb70f64496563cd9f5e3a1472..ab1d7d6d04c7d36831c34c20dda7b0c5a4fade6e 100644 (file)
@@ -223,7 +223,8 @@ static bool check_node(const struct exfat* ef, struct exfat_node* node,
                exfat_get_name(node, buffer);
                exfat_error("'%s' has invalid checksum (%#hx != %#hx)", buffer,
                                le16_to_cpu(actual_checksum), le16_to_cpu(meta1->checksum));
-               ret = false;
+               if (!EXFAT_REPAIR(invalid_node_checksum, ef, node))
+                       ret = false;
        }
 
        /*
@@ -516,7 +517,8 @@ static int readdir(struct exfat* ef, struct exfat_node* parent,
                                break; /* deleted entry, ignore it */
 
                        exfat_error("unknown entry type %#hhx", entry.type);
-                       return -EIO;
+                       if (!EXFAT_REPAIR(unknown_entry, ef, parent, &entry, *offset))
+                               return -EIO;
                }
                *offset += sizeof(entry);
        }
index e10c46bb6363a791dd6b643157e633c97e4ce738..9ab3155d36bafc823f60a93d00679e1fa8a686c5 100644 (file)
@@ -46,7 +46,7 @@
 #define EXFAT_LITTLE_ENDIAN LITTLE_ENDIAN
 #define EXFAT_BIG_ENDIAN BIG_ENDIAN
 
-#elif defined(__FreeBSD__) || defined(__DragonFlyBSD__) || defined(__NetBSD__) || defined(__OpenBSD__)
+#elif defined(__FreeBSD__) || defined(__DragonFly__) || defined(__NetBSD__) || defined(__OpenBSD__)
 
 #include <sys/endian.h>
 #define exfat_bswap16(x) bswap16(x)
diff --git a/libexfat/repair.c b/libexfat/repair.c
new file mode 100644 (file)
index 0000000..237ab3a
--- /dev/null
@@ -0,0 +1,102 @@
+/*
+       repair.c (09.03.17)
+       exFAT file system implementation library.
+
+       Free exFAT implementation.
+       Copyright (C) 2010-2018  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.
+*/
+
+#include "exfat.h"
+#include <strings.h>
+
+int exfat_errors_fixed;
+
+bool exfat_ask_to_fix(const struct exfat* ef)
+{
+       const char* question = "Fix (Y/N)?";
+       char answer[8];
+       bool yeah, nope;
+
+       switch (ef->repair)
+       {
+       case EXFAT_REPAIR_NO:
+               return false;
+       case EXFAT_REPAIR_YES:
+               printf("%s %s", question, "Y\n");
+               return true;
+       case EXFAT_REPAIR_ASK:
+               do
+               {
+                       printf("%s ", question);
+                       fflush(stdout);
+                       if (fgets(answer, sizeof(answer), stdin))
+                       {
+                               yeah = strcasecmp(answer, "Y\n") == 0;
+                               nope = strcasecmp(answer, "N\n") == 0;
+                       }
+                       else
+                       {
+                               yeah = false;
+                               nope = true;
+                       }
+               }
+               while (!yeah && !nope);
+               return yeah;
+       }
+       exfat_bug("invalid repair option value: %d", ef->repair);
+}
+
+bool exfat_fix_invalid_vbr_checksum(const struct exfat* ef, void* sector,
+               uint32_t vbr_checksum)
+{
+       size_t i;
+       off_t sector_size = SECTOR_SIZE(*ef->sb);
+
+       for (i = 0; i < sector_size / sizeof(vbr_checksum); i++)
+               ((le32_t*) sector)[i] = cpu_to_le32(vbr_checksum);
+       if (exfat_pwrite(ef->dev, sector, sector_size, 11 * sector_size) < 0)
+       {
+               exfat_error("failed to write correct VBR checksum");
+               return false;
+       }
+       exfat_errors_fixed++;
+       return true;
+}
+
+bool exfat_fix_invalid_node_checksum(const struct exfat* ef,
+               struct exfat_node* node)
+{
+       /* checksum will be rewritten by exfat_flush_node() */
+       node->is_dirty = true;
+
+       exfat_errors_fixed++;
+       return true;
+}
+
+bool exfat_fix_unknown_entry(struct exfat* ef, struct exfat_node* dir,
+               const struct exfat_entry* entry, off_t offset)
+{
+       struct exfat_entry deleted = *entry;
+
+       deleted.type &= ~EXFAT_ENTRY_VALID;
+       if (exfat_generic_pwrite(ef, dir, &deleted, sizeof(struct exfat_entry),
+                       offset) != sizeof(struct exfat_entry))
+               return false;
+
+       exfat_errors_fixed++;
+       return true;
+}
index 71a5be168ec527d6223176bf42bf2a469c4f212a..db22f1c489b85596639768840da3c4c8c202ddb6 100644 (file)
@@ -257,10 +257,15 @@ PACKAGE_TARNAME = @PACKAGE_TARNAME@
 PACKAGE_URL = @PACKAGE_URL@
 PACKAGE_VERSION = @PACKAGE_VERSION@
 PATH_SEPARATOR = @PATH_SEPARATOR@
+PKG_CONFIG = @PKG_CONFIG@
+PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
+PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
 RANLIB = @RANLIB@
 SET_MAKE = @SET_MAKE@
 SHELL = @SHELL@
 STRIP = @STRIP@
+UBLIO_CFLAGS = @UBLIO_CFLAGS@
+UBLIO_LIBS = @UBLIO_LIBS@
 VERSION = @VERSION@
 abs_builddir = @abs_builddir@
 abs_srcdir = @abs_srcdir@
index 74e0bfed308dec8864d02a3a06055f9ff7ea5ad3..6d3c6534465d0aa423431e5a07d37e7e77689f14 100644 (file)
@@ -1,6 +1,6 @@
-.\" Copyright (C) 2011-2016  Andrew Nayenko
+.\" Copyright (C) 2011-2018  Andrew Nayenko
 .\"
-.TH MKEXFATFS 8 "January 2011"
+.TH MKEXFATFS 8 "January 2014"
 .SH NAME
 .B mkexfatfs
 \- create an exFAT file system