diff --git a/CHANGELOG.md b/CHANGELOG.md
new file mode 100644
--- /dev/null
+++ b/CHANGELOG.md
@@ -0,0 +1,5 @@
+# Revision history for libfuse3
+
+## 0.1.0.0 -- 2020-08-27
+
+* First version. Released on an unsuspecting world.
diff --git a/LICENSE b/LICENSE
new file mode 100644
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,20 @@
+Copyright (c) 2020 yohashi
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be included
+in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
diff --git a/LICENSE-HFuse b/LICENSE-HFuse
new file mode 100644
--- /dev/null
+++ b/LICENSE-HFuse
@@ -0,0 +1,26 @@
+Copyright (c) Jérémy Bobbio
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+1. Redistributions of source code must retain the above copyright
+   notice, this list of conditions and the following disclaimer.
+2. Redistributions in binary form must reproduce the above copyright
+   notice, this list of conditions and the following disclaimer in the
+   documentation and/or other materials provided with the distribution.
+3. Neither the name of the University nor the names of its contributors
+   may be used to endorse or promote products derived from this software
+   without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+SUCH DAMAGE.
diff --git a/README.md b/README.md
new file mode 100644
--- /dev/null
+++ b/README.md
@@ -0,0 +1,51 @@
+# libfuse3: A Haskell binding to libfuse-3.x
+
+![GitHub Actions](https://github.com/matil019/haskell-libfuse3/workflows/Haskell%20CI/badge.svg?branch=master)
+
+## Important notes
+
+- Executables using `libfuse3` should be compiled with the threaded runtime (`-threaded`).
+- Developed and tested on Linux only. Not tested on other UNIXes such as BSD and MacOS because I don't own them / machines to run them on.
+
+## Building from HEAD
+
+This packages uses the `./configure` script, but it is not checked into the git repository. To build the source checked out from git, you must generate it from `configure.ac` before invoking any of the `cabal` commands:
+
+```
+autoreconf -fiv
+# cabal v2-build, etc.
+```
+
+You may have to install `autotools` or something like that with your system package manager.
+
+## Examples
+
+There are two examples, `null` and `passthrough` in the `example` directory. These are the ports of the examples in the official libfuse. They should be good start points for writing your filesystems.
+
+Enable the cabal flag to build them:
+
+```
+cabal v2-configure --flags=examples
+```
+
+## Known issues and limitations
+
+- Can't stop the process and unmount with signals. You have to use `fusermount -u` to unmount.
+- Not all Haskell-friendly bindings to the FUSE operations are implemented yet, including but not limited to:
+  - `struct fuse_conn_info`. The availability of filesystem capabilities such as `FUSE_CAP_HANDLE_KILLPRIV` can't be checked.
+  - Setting the fields of `struct fuse_file_info` from the certain fuse operations.
+- Look for the `TODO` comments in the source tree for more specific topics.
+
+If you are able to implement any of these, that would be very appreciated! Please open a PR to contribute.
+
+## Related works
+
+- [libfuse][libfuse]: The reference implementation, to which this package binds
+- [HFuse][HFuse]: The bindings to libfuse-2.x
+  - `libfuse3` is based on `HFuse` (with massive rewrites).
+  - `libfuse3` has more complete API and exposes internal (and unstable) API to allow workarounds.
+- [fuse-rs][fuse-rs]: The Rust implementation of FUSE. Unlike this package, `fuse-rs` implements the FUSE protocol itself (i.e. replaces `libfuse`). See [its README](https://github.com/zargony/fuse-rs) for overview.
+
+[libfuse]: https://github.com/libfuse/libfuse
+[HFuse]: https://github.com/m15k/hfuse
+[fuse-rs]: https://github.com/zargony/fuse-rs
diff --git a/Setup.hs b/Setup.hs
new file mode 100644
--- /dev/null
+++ b/Setup.hs
@@ -0,0 +1,2 @@
+import Distribution.Simple
+main = defaultMain
diff --git a/configure b/configure
new file mode 100644
--- /dev/null
+++ b/configure
@@ -0,0 +1,4108 @@
+#! /bin/sh
+# Guess values for system-dependent variables and create Makefiles.
+# Generated by GNU Autoconf 2.69 for Haskell libfuse3 package 0.1.0.0.
+#
+#
+# Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc.
+#
+#
+# This configure script is free software; the Free Software Foundation
+# gives unlimited permission to copy, distribute and modify it.
+## -------------------- ##
+## M4sh Initialization. ##
+## -------------------- ##
+
+# Be more Bourne compatible
+DUALCASE=1; export DUALCASE # for MKS sh
+if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then :
+  emulate sh
+  NULLCMD=:
+  # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which
+  # is contrary to our usage.  Disable this feature.
+  alias -g '${1+"$@"}'='"$@"'
+  setopt NO_GLOB_SUBST
+else
+  case `(set -o) 2>/dev/null` in #(
+  *posix*) :
+    set -o posix ;; #(
+  *) :
+     ;;
+esac
+fi
+
+
+as_nl='
+'
+export as_nl
+# Printing a long string crashes Solaris 7 /usr/bin/printf.
+as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\'
+as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo
+as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo
+# Prefer a ksh shell builtin over an external printf program on Solaris,
+# but without wasting forks for bash or zsh.
+if test -z "$BASH_VERSION$ZSH_VERSION" \
+    && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then
+  as_echo='print -r --'
+  as_echo_n='print -rn --'
+elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then
+  as_echo='printf %s\n'
+  as_echo_n='printf %s'
+else
+  if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then
+    as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"'
+    as_echo_n='/usr/ucb/echo -n'
+  else
+    as_echo_body='eval expr "X$1" : "X\\(.*\\)"'
+    as_echo_n_body='eval
+      arg=$1;
+      case $arg in #(
+      *"$as_nl"*)
+	expr "X$arg" : "X\\(.*\\)$as_nl";
+	arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;;
+      esac;
+      expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl"
+    '
+    export as_echo_n_body
+    as_echo_n='sh -c $as_echo_n_body as_echo'
+  fi
+  export as_echo_body
+  as_echo='sh -c $as_echo_body as_echo'
+fi
+
+# The user is always right.
+if test "${PATH_SEPARATOR+set}" != set; then
+  PATH_SEPARATOR=:
+  (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && {
+    (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 ||
+      PATH_SEPARATOR=';'
+  }
+fi
+
+
+# IFS
+# We need space, tab and new line, in precisely that order.  Quoting is
+# there to prevent editors from complaining about space-tab.
+# (If _AS_PATH_WALK were called with IFS unset, it would disable word
+# splitting by setting IFS to empty value.)
+IFS=" ""	$as_nl"
+
+# Find who we are.  Look in the path if we contain no directory separator.
+as_myself=
+case $0 in #((
+  *[\\/]* ) as_myself=$0 ;;
+  *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break
+  done
+IFS=$as_save_IFS
+
+     ;;
+esac
+# We did not find ourselves, most probably we were run as `sh COMMAND'
+# in which case we are not to be found in the path.
+if test "x$as_myself" = x; then
+  as_myself=$0
+fi
+if test ! -f "$as_myself"; then
+  $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2
+  exit 1
+fi
+
+# Unset variables that we do not need and which cause bugs (e.g. in
+# pre-3.0 UWIN ksh).  But do not cause bugs in bash 2.01; the "|| exit 1"
+# suppresses any "Segmentation fault" message there.  '((' could
+# trigger a bug in pdksh 5.2.14.
+for as_var in BASH_ENV ENV MAIL MAILPATH
+do eval test x\${$as_var+set} = xset \
+  && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || :
+done
+PS1='$ '
+PS2='> '
+PS4='+ '
+
+# NLS nuisances.
+LC_ALL=C
+export LC_ALL
+LANGUAGE=C
+export LANGUAGE
+
+# CDPATH.
+(unset CDPATH) >/dev/null 2>&1 && unset CDPATH
+
+# Use a proper internal environment variable to ensure we don't fall
+  # into an infinite loop, continuously re-executing ourselves.
+  if test x"${_as_can_reexec}" != xno && test "x$CONFIG_SHELL" != x; then
+    _as_can_reexec=no; export _as_can_reexec;
+    # We cannot yet assume a decent shell, so we have to provide a
+# neutralization value for shells without unset; and this also
+# works around shells that cannot unset nonexistent variables.
+# Preserve -v and -x to the replacement shell.
+BASH_ENV=/dev/null
+ENV=/dev/null
+(unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV
+case $- in # ((((
+  *v*x* | *x*v* ) as_opts=-vx ;;
+  *v* ) as_opts=-v ;;
+  *x* ) as_opts=-x ;;
+  * ) as_opts= ;;
+esac
+exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"}
+# Admittedly, this is quite paranoid, since all the known shells bail
+# out after a failed `exec'.
+$as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2
+as_fn_exit 255
+  fi
+  # We don't want this to propagate to other subprocesses.
+          { _as_can_reexec=; unset _as_can_reexec;}
+if test "x$CONFIG_SHELL" = x; then
+  as_bourne_compatible="if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then :
+  emulate sh
+  NULLCMD=:
+  # Pre-4.2 versions of Zsh do word splitting on \${1+\"\$@\"}, which
+  # is contrary to our usage.  Disable this feature.
+  alias -g '\${1+\"\$@\"}'='\"\$@\"'
+  setopt NO_GLOB_SUBST
+else
+  case \`(set -o) 2>/dev/null\` in #(
+  *posix*) :
+    set -o posix ;; #(
+  *) :
+     ;;
+esac
+fi
+"
+  as_required="as_fn_return () { (exit \$1); }
+as_fn_success () { as_fn_return 0; }
+as_fn_failure () { as_fn_return 1; }
+as_fn_ret_success () { return 0; }
+as_fn_ret_failure () { return 1; }
+
+exitcode=0
+as_fn_success || { exitcode=1; echo as_fn_success failed.; }
+as_fn_failure && { exitcode=1; echo as_fn_failure succeeded.; }
+as_fn_ret_success || { exitcode=1; echo as_fn_ret_success failed.; }
+as_fn_ret_failure && { exitcode=1; echo as_fn_ret_failure succeeded.; }
+if ( set x; as_fn_ret_success y && test x = \"\$1\" ); then :
+
+else
+  exitcode=1; echo positional parameters were not saved.
+fi
+test x\$exitcode = x0 || exit 1
+test -x / || exit 1"
+  as_suggested="  as_lineno_1=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_1a=\$LINENO
+  as_lineno_2=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_2a=\$LINENO
+  eval 'test \"x\$as_lineno_1'\$as_run'\" != \"x\$as_lineno_2'\$as_run'\" &&
+  test \"x\`expr \$as_lineno_1'\$as_run' + 1\`\" = \"x\$as_lineno_2'\$as_run'\"' || exit 1"
+  if (eval "$as_required") 2>/dev/null; then :
+  as_have_required=yes
+else
+  as_have_required=no
+fi
+  if test x$as_have_required = xyes && (eval "$as_suggested") 2>/dev/null; then :
+
+else
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+as_found=false
+for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  as_found=:
+  case $as_dir in #(
+	 /*)
+	   for as_base in sh bash ksh sh5; do
+	     # Try only shells that exist, to save several forks.
+	     as_shell=$as_dir/$as_base
+	     if { test -f "$as_shell" || test -f "$as_shell.exe"; } &&
+		    { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$as_shell"; } 2>/dev/null; then :
+  CONFIG_SHELL=$as_shell as_have_required=yes
+		   if { $as_echo "$as_bourne_compatible""$as_suggested" | as_run=a "$as_shell"; } 2>/dev/null; then :
+  break 2
+fi
+fi
+	   done;;
+       esac
+  as_found=false
+done
+$as_found || { if { test -f "$SHELL" || test -f "$SHELL.exe"; } &&
+	      { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$SHELL"; } 2>/dev/null; then :
+  CONFIG_SHELL=$SHELL as_have_required=yes
+fi; }
+IFS=$as_save_IFS
+
+
+      if test "x$CONFIG_SHELL" != x; then :
+  export CONFIG_SHELL
+             # We cannot yet assume a decent shell, so we have to provide a
+# neutralization value for shells without unset; and this also
+# works around shells that cannot unset nonexistent variables.
+# Preserve -v and -x to the replacement shell.
+BASH_ENV=/dev/null
+ENV=/dev/null
+(unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV
+case $- in # ((((
+  *v*x* | *x*v* ) as_opts=-vx ;;
+  *v* ) as_opts=-v ;;
+  *x* ) as_opts=-x ;;
+  * ) as_opts= ;;
+esac
+exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"}
+# Admittedly, this is quite paranoid, since all the known shells bail
+# out after a failed `exec'.
+$as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2
+exit 255
+fi
+
+    if test x$as_have_required = xno; then :
+  $as_echo "$0: This script requires a shell more modern than all"
+  $as_echo "$0: the shells that I found on your system."
+  if test x${ZSH_VERSION+set} = xset ; then
+    $as_echo "$0: In particular, zsh $ZSH_VERSION has bugs and should"
+    $as_echo "$0: be upgraded to zsh 4.3.4 or later."
+  else
+    $as_echo "$0: Please tell bug-autoconf@gnu.org about your system,
+$0: including any error possibly output before this
+$0: message. Then install a modern shell, or manually run
+$0: the script under such a shell if you do have one."
+  fi
+  exit 1
+fi
+fi
+fi
+SHELL=${CONFIG_SHELL-/bin/sh}
+export SHELL
+# Unset more variables known to interfere with behavior of common tools.
+CLICOLOR_FORCE= GREP_OPTIONS=
+unset CLICOLOR_FORCE GREP_OPTIONS
+
+## --------------------- ##
+## M4sh Shell Functions. ##
+## --------------------- ##
+# as_fn_unset VAR
+# ---------------
+# Portably unset VAR.
+as_fn_unset ()
+{
+  { eval $1=; unset $1;}
+}
+as_unset=as_fn_unset
+
+# as_fn_set_status STATUS
+# -----------------------
+# Set $? to STATUS, without forking.
+as_fn_set_status ()
+{
+  return $1
+} # as_fn_set_status
+
+# as_fn_exit STATUS
+# -----------------
+# Exit the shell with STATUS, even in a "trap 0" or "set -e" context.
+as_fn_exit ()
+{
+  set +e
+  as_fn_set_status $1
+  exit $1
+} # as_fn_exit
+
+# as_fn_mkdir_p
+# -------------
+# Create "$as_dir" as a directory, including parents if necessary.
+as_fn_mkdir_p ()
+{
+
+  case $as_dir in #(
+  -*) as_dir=./$as_dir;;
+  esac
+  test -d "$as_dir" || eval $as_mkdir_p || {
+    as_dirs=
+    while :; do
+      case $as_dir in #(
+      *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'(
+      *) as_qdir=$as_dir;;
+      esac
+      as_dirs="'$as_qdir' $as_dirs"
+      as_dir=`$as_dirname -- "$as_dir" ||
+$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+	 X"$as_dir" : 'X\(//\)[^/]' \| \
+	 X"$as_dir" : 'X\(//\)$' \| \
+	 X"$as_dir" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X"$as_dir" |
+    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\/\)[^/].*/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\/\)$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\).*/{
+	    s//\1/
+	    q
+	  }
+	  s/.*/./; q'`
+      test -d "$as_dir" && break
+    done
+    test -z "$as_dirs" || eval "mkdir $as_dirs"
+  } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir"
+
+
+} # as_fn_mkdir_p
+
+# as_fn_executable_p FILE
+# -----------------------
+# Test if FILE is an executable regular file.
+as_fn_executable_p ()
+{
+  test -f "$1" && test -x "$1"
+} # as_fn_executable_p
+# as_fn_append VAR VALUE
+# ----------------------
+# Append the text in VALUE to the end of the definition contained in VAR. Take
+# advantage of any shell optimizations that allow amortized linear growth over
+# repeated appends, instead of the typical quadratic growth present in naive
+# implementations.
+if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then :
+  eval 'as_fn_append ()
+  {
+    eval $1+=\$2
+  }'
+else
+  as_fn_append ()
+  {
+    eval $1=\$$1\$2
+  }
+fi # as_fn_append
+
+# as_fn_arith ARG...
+# ------------------
+# Perform arithmetic evaluation on the ARGs, and store the result in the
+# global $as_val. Take advantage of shells that can avoid forks. The arguments
+# must be portable across $(()) and expr.
+if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then :
+  eval 'as_fn_arith ()
+  {
+    as_val=$(( $* ))
+  }'
+else
+  as_fn_arith ()
+  {
+    as_val=`expr "$@" || test $? -eq 1`
+  }
+fi # as_fn_arith
+
+
+# as_fn_error STATUS ERROR [LINENO LOG_FD]
+# ----------------------------------------
+# Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are
+# provided, also output the error to LOG_FD, referencing LINENO. Then exit the
+# script with STATUS, using 1 if that was 0.
+as_fn_error ()
+{
+  as_status=$1; test $as_status -eq 0 && as_status=1
+  if test "$4"; then
+    as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+    $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4
+  fi
+  $as_echo "$as_me: error: $2" >&2
+  as_fn_exit $as_status
+} # as_fn_error
+
+if expr a : '\(a\)' >/dev/null 2>&1 &&
+   test "X`expr 00001 : '.*\(...\)'`" = X001; then
+  as_expr=expr
+else
+  as_expr=false
+fi
+
+if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then
+  as_basename=basename
+else
+  as_basename=false
+fi
+
+if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then
+  as_dirname=dirname
+else
+  as_dirname=false
+fi
+
+as_me=`$as_basename -- "$0" ||
+$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \
+	 X"$0" : 'X\(//\)$' \| \
+	 X"$0" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X/"$0" |
+    sed '/^.*\/\([^/][^/]*\)\/*$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\/\(\/\/\)$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\/\(\/\).*/{
+	    s//\1/
+	    q
+	  }
+	  s/.*/./; q'`
+
+# Avoid depending upon Character Ranges.
+as_cr_letters='abcdefghijklmnopqrstuvwxyz'
+as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
+as_cr_Letters=$as_cr_letters$as_cr_LETTERS
+as_cr_digits='0123456789'
+as_cr_alnum=$as_cr_Letters$as_cr_digits
+
+
+  as_lineno_1=$LINENO as_lineno_1a=$LINENO
+  as_lineno_2=$LINENO as_lineno_2a=$LINENO
+  eval 'test "x$as_lineno_1'$as_run'" != "x$as_lineno_2'$as_run'" &&
+  test "x`expr $as_lineno_1'$as_run' + 1`" = "x$as_lineno_2'$as_run'"' || {
+  # Blame Lee E. McMahon (1931-1989) for sed's syntax.  :-)
+  sed -n '
+    p
+    /[$]LINENO/=
+  ' <$as_myself |
+    sed '
+      s/[$]LINENO.*/&-/
+      t lineno
+      b
+      :lineno
+      N
+      :loop
+      s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/
+      t loop
+      s/-\n.*//
+    ' >$as_me.lineno &&
+  chmod +x "$as_me.lineno" ||
+    { $as_echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2; as_fn_exit 1; }
+
+  # If we had to re-execute with $CONFIG_SHELL, we're ensured to have
+  # already done that, so ensure we don't try to do so again and fall
+  # in an infinite loop.  This has already happened in practice.
+  _as_can_reexec=no; export _as_can_reexec
+  # Don't try to exec as it changes $[0], causing all sort of problems
+  # (the dirname of $[0] is not the place where we might find the
+  # original and so on.  Autoconf is especially sensitive to this).
+  . "./$as_me.lineno"
+  # Exit status is that of the last command.
+  exit
+}
+
+ECHO_C= ECHO_N= ECHO_T=
+case `echo -n x` in #(((((
+-n*)
+  case `echo 'xy\c'` in
+  *c*) ECHO_T='	';;	# ECHO_T is single tab character.
+  xy)  ECHO_C='\c';;
+  *)   echo `echo ksh88 bug on AIX 6.1` > /dev/null
+       ECHO_T='	';;
+  esac;;
+*)
+  ECHO_N='-n';;
+esac
+
+rm -f conf$$ conf$$.exe conf$$.file
+if test -d conf$$.dir; then
+  rm -f conf$$.dir/conf$$.file
+else
+  rm -f conf$$.dir
+  mkdir conf$$.dir 2>/dev/null
+fi
+if (echo >conf$$.file) 2>/dev/null; then
+  if ln -s conf$$.file conf$$ 2>/dev/null; then
+    as_ln_s='ln -s'
+    # ... but there are two gotchas:
+    # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail.
+    # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable.
+    # In both cases, we have to default to `cp -pR'.
+    ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe ||
+      as_ln_s='cp -pR'
+  elif ln conf$$.file conf$$ 2>/dev/null; then
+    as_ln_s=ln
+  else
+    as_ln_s='cp -pR'
+  fi
+else
+  as_ln_s='cp -pR'
+fi
+rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file
+rmdir conf$$.dir 2>/dev/null
+
+if mkdir -p . 2>/dev/null; then
+  as_mkdir_p='mkdir -p "$as_dir"'
+else
+  test -d ./-p && rmdir ./-p
+  as_mkdir_p=false
+fi
+
+as_test_x='test -x'
+as_executable_p=as_fn_executable_p
+
+# Sed expression to map a string onto a valid CPP name.
+as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'"
+
+# Sed expression to map a string onto a valid variable name.
+as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'"
+
+
+test -n "$DJDIR" || exec 7<&0 </dev/null
+exec 6>&1
+
+# Name of the host.
+# hostname on some systems (SVR3.2, old GNU/Linux) returns a bogus exit status,
+# so uname gets run too.
+ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q`
+
+#
+# Initializations.
+#
+ac_default_prefix=/usr/local
+ac_clean_files=
+ac_config_libobj_dir=.
+LIBOBJS=
+cross_compiling=no
+subdirs=
+MFLAGS=
+MAKEFLAGS=
+
+# Identity of this package.
+PACKAGE_NAME='Haskell libfuse3 package'
+PACKAGE_TARNAME='haskell-libfuse3-package'
+PACKAGE_VERSION='0.1.0.0'
+PACKAGE_STRING='Haskell libfuse3 package 0.1.0.0'
+PACKAGE_BUGREPORT=''
+PACKAGE_URL=''
+
+ac_unique_file="libfuse3.cabal"
+ac_subst_vars='LTLIBOBJS
+LIBOBJS
+OBJEXT
+EXEEXT
+ac_ct_CC
+CPPFLAGS
+LDFLAGS
+CFLAGS
+CC
+FUSEVER
+FUSE3_LIBS
+FUSE3_CFLAGS
+PKG_CONFIG_LIBDIR
+PKG_CONFIG_PATH
+PKG_CONFIG
+target_alias
+host_alias
+build_alias
+LIBS
+ECHO_T
+ECHO_N
+ECHO_C
+DEFS
+mandir
+localedir
+libdir
+psdir
+pdfdir
+dvidir
+htmldir
+infodir
+docdir
+oldincludedir
+includedir
+localstatedir
+sharedstatedir
+sysconfdir
+datadir
+datarootdir
+libexecdir
+sbindir
+bindir
+program_transform_name
+prefix
+exec_prefix
+PACKAGE_URL
+PACKAGE_BUGREPORT
+PACKAGE_STRING
+PACKAGE_VERSION
+PACKAGE_TARNAME
+PACKAGE_NAME
+PATH_SEPARATOR
+SHELL'
+ac_subst_files=''
+ac_user_opts='
+enable_option_checking
+'
+      ac_precious_vars='build_alias
+host_alias
+target_alias
+PKG_CONFIG
+PKG_CONFIG_PATH
+PKG_CONFIG_LIBDIR
+FUSE3_CFLAGS
+FUSE3_LIBS
+CC
+CFLAGS
+LDFLAGS
+LIBS
+CPPFLAGS'
+
+
+# Initialize some variables set by options.
+ac_init_help=
+ac_init_version=false
+ac_unrecognized_opts=
+ac_unrecognized_sep=
+# The variables have the same names as the options, with
+# dashes changed to underlines.
+cache_file=/dev/null
+exec_prefix=NONE
+no_create=
+no_recursion=
+prefix=NONE
+program_prefix=NONE
+program_suffix=NONE
+program_transform_name=s,x,x,
+silent=
+site=
+srcdir=
+verbose=
+x_includes=NONE
+x_libraries=NONE
+
+# Installation directory options.
+# These are left unexpanded so users can "make install exec_prefix=/foo"
+# and all the variables that are supposed to be based on exec_prefix
+# by default will actually change.
+# Use braces instead of parens because sh, perl, etc. also accept them.
+# (The list follows the same order as the GNU Coding Standards.)
+bindir='${exec_prefix}/bin'
+sbindir='${exec_prefix}/sbin'
+libexecdir='${exec_prefix}/libexec'
+datarootdir='${prefix}/share'
+datadir='${datarootdir}'
+sysconfdir='${prefix}/etc'
+sharedstatedir='${prefix}/com'
+localstatedir='${prefix}/var'
+includedir='${prefix}/include'
+oldincludedir='/usr/include'
+docdir='${datarootdir}/doc/${PACKAGE_TARNAME}'
+infodir='${datarootdir}/info'
+htmldir='${docdir}'
+dvidir='${docdir}'
+pdfdir='${docdir}'
+psdir='${docdir}'
+libdir='${exec_prefix}/lib'
+localedir='${datarootdir}/locale'
+mandir='${datarootdir}/man'
+
+ac_prev=
+ac_dashdash=
+for ac_option
+do
+  # If the previous option needs an argument, assign it.
+  if test -n "$ac_prev"; then
+    eval $ac_prev=\$ac_option
+    ac_prev=
+    continue
+  fi
+
+  case $ac_option in
+  *=?*) ac_optarg=`expr "X$ac_option" : '[^=]*=\(.*\)'` ;;
+  *=)   ac_optarg= ;;
+  *)    ac_optarg=yes ;;
+  esac
+
+  # Accept the important Cygnus configure options, so we can diagnose typos.
+
+  case $ac_dashdash$ac_option in
+  --)
+    ac_dashdash=yes ;;
+
+  -bindir | --bindir | --bindi | --bind | --bin | --bi)
+    ac_prev=bindir ;;
+  -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*)
+    bindir=$ac_optarg ;;
+
+  -build | --build | --buil | --bui | --bu)
+    ac_prev=build_alias ;;
+  -build=* | --build=* | --buil=* | --bui=* | --bu=*)
+    build_alias=$ac_optarg ;;
+
+  -cache-file | --cache-file | --cache-fil | --cache-fi \
+  | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c)
+    ac_prev=cache_file ;;
+  -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \
+  | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*)
+    cache_file=$ac_optarg ;;
+
+  --config-cache | -C)
+    cache_file=config.cache ;;
+
+  -datadir | --datadir | --datadi | --datad)
+    ac_prev=datadir ;;
+  -datadir=* | --datadir=* | --datadi=* | --datad=*)
+    datadir=$ac_optarg ;;
+
+  -datarootdir | --datarootdir | --datarootdi | --datarootd | --dataroot \
+  | --dataroo | --dataro | --datar)
+    ac_prev=datarootdir ;;
+  -datarootdir=* | --datarootdir=* | --datarootdi=* | --datarootd=* \
+  | --dataroot=* | --dataroo=* | --dataro=* | --datar=*)
+    datarootdir=$ac_optarg ;;
+
+  -disable-* | --disable-*)
+    ac_useropt=`expr "x$ac_option" : 'x-*disable-\(.*\)'`
+    # Reject names that are not valid shell variable names.
+    expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
+      as_fn_error $? "invalid feature name: $ac_useropt"
+    ac_useropt_orig=$ac_useropt
+    ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
+    case $ac_user_opts in
+      *"
+"enable_$ac_useropt"
+"*) ;;
+      *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--disable-$ac_useropt_orig"
+	 ac_unrecognized_sep=', ';;
+    esac
+    eval enable_$ac_useropt=no ;;
+
+  -docdir | --docdir | --docdi | --doc | --do)
+    ac_prev=docdir ;;
+  -docdir=* | --docdir=* | --docdi=* | --doc=* | --do=*)
+    docdir=$ac_optarg ;;
+
+  -dvidir | --dvidir | --dvidi | --dvid | --dvi | --dv)
+    ac_prev=dvidir ;;
+  -dvidir=* | --dvidir=* | --dvidi=* | --dvid=* | --dvi=* | --dv=*)
+    dvidir=$ac_optarg ;;
+
+  -enable-* | --enable-*)
+    ac_useropt=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'`
+    # Reject names that are not valid shell variable names.
+    expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
+      as_fn_error $? "invalid feature name: $ac_useropt"
+    ac_useropt_orig=$ac_useropt
+    ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
+    case $ac_user_opts in
+      *"
+"enable_$ac_useropt"
+"*) ;;
+      *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--enable-$ac_useropt_orig"
+	 ac_unrecognized_sep=', ';;
+    esac
+    eval enable_$ac_useropt=\$ac_optarg ;;
+
+  -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \
+  | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \
+  | --exec | --exe | --ex)
+    ac_prev=exec_prefix ;;
+  -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \
+  | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \
+  | --exec=* | --exe=* | --ex=*)
+    exec_prefix=$ac_optarg ;;
+
+  -gas | --gas | --ga | --g)
+    # Obsolete; use --with-gas.
+    with_gas=yes ;;
+
+  -help | --help | --hel | --he | -h)
+    ac_init_help=long ;;
+  -help=r* | --help=r* | --hel=r* | --he=r* | -hr*)
+    ac_init_help=recursive ;;
+  -help=s* | --help=s* | --hel=s* | --he=s* | -hs*)
+    ac_init_help=short ;;
+
+  -host | --host | --hos | --ho)
+    ac_prev=host_alias ;;
+  -host=* | --host=* | --hos=* | --ho=*)
+    host_alias=$ac_optarg ;;
+
+  -htmldir | --htmldir | --htmldi | --htmld | --html | --htm | --ht)
+    ac_prev=htmldir ;;
+  -htmldir=* | --htmldir=* | --htmldi=* | --htmld=* | --html=* | --htm=* \
+  | --ht=*)
+    htmldir=$ac_optarg ;;
+
+  -includedir | --includedir | --includedi | --included | --include \
+  | --includ | --inclu | --incl | --inc)
+    ac_prev=includedir ;;
+  -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \
+  | --includ=* | --inclu=* | --incl=* | --inc=*)
+    includedir=$ac_optarg ;;
+
+  -infodir | --infodir | --infodi | --infod | --info | --inf)
+    ac_prev=infodir ;;
+  -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*)
+    infodir=$ac_optarg ;;
+
+  -libdir | --libdir | --libdi | --libd)
+    ac_prev=libdir ;;
+  -libdir=* | --libdir=* | --libdi=* | --libd=*)
+    libdir=$ac_optarg ;;
+
+  -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \
+  | --libexe | --libex | --libe)
+    ac_prev=libexecdir ;;
+  -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \
+  | --libexe=* | --libex=* | --libe=*)
+    libexecdir=$ac_optarg ;;
+
+  -localedir | --localedir | --localedi | --localed | --locale)
+    ac_prev=localedir ;;
+  -localedir=* | --localedir=* | --localedi=* | --localed=* | --locale=*)
+    localedir=$ac_optarg ;;
+
+  -localstatedir | --localstatedir | --localstatedi | --localstated \
+  | --localstate | --localstat | --localsta | --localst | --locals)
+    ac_prev=localstatedir ;;
+  -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \
+  | --localstate=* | --localstat=* | --localsta=* | --localst=* | --locals=*)
+    localstatedir=$ac_optarg ;;
+
+  -mandir | --mandir | --mandi | --mand | --man | --ma | --m)
+    ac_prev=mandir ;;
+  -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*)
+    mandir=$ac_optarg ;;
+
+  -nfp | --nfp | --nf)
+    # Obsolete; use --without-fp.
+    with_fp=no ;;
+
+  -no-create | --no-create | --no-creat | --no-crea | --no-cre \
+  | --no-cr | --no-c | -n)
+    no_create=yes ;;
+
+  -no-recursion | --no-recursion | --no-recursio | --no-recursi \
+  | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r)
+    no_recursion=yes ;;
+
+  -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \
+  | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \
+  | --oldin | --oldi | --old | --ol | --o)
+    ac_prev=oldincludedir ;;
+  -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \
+  | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \
+  | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*)
+    oldincludedir=$ac_optarg ;;
+
+  -prefix | --prefix | --prefi | --pref | --pre | --pr | --p)
+    ac_prev=prefix ;;
+  -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*)
+    prefix=$ac_optarg ;;
+
+  -program-prefix | --program-prefix | --program-prefi | --program-pref \
+  | --program-pre | --program-pr | --program-p)
+    ac_prev=program_prefix ;;
+  -program-prefix=* | --program-prefix=* | --program-prefi=* \
+  | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*)
+    program_prefix=$ac_optarg ;;
+
+  -program-suffix | --program-suffix | --program-suffi | --program-suff \
+  | --program-suf | --program-su | --program-s)
+    ac_prev=program_suffix ;;
+  -program-suffix=* | --program-suffix=* | --program-suffi=* \
+  | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*)
+    program_suffix=$ac_optarg ;;
+
+  -program-transform-name | --program-transform-name \
+  | --program-transform-nam | --program-transform-na \
+  | --program-transform-n | --program-transform- \
+  | --program-transform | --program-transfor \
+  | --program-transfo | --program-transf \
+  | --program-trans | --program-tran \
+  | --progr-tra | --program-tr | --program-t)
+    ac_prev=program_transform_name ;;
+  -program-transform-name=* | --program-transform-name=* \
+  | --program-transform-nam=* | --program-transform-na=* \
+  | --program-transform-n=* | --program-transform-=* \
+  | --program-transform=* | --program-transfor=* \
+  | --program-transfo=* | --program-transf=* \
+  | --program-trans=* | --program-tran=* \
+  | --progr-tra=* | --program-tr=* | --program-t=*)
+    program_transform_name=$ac_optarg ;;
+
+  -pdfdir | --pdfdir | --pdfdi | --pdfd | --pdf | --pd)
+    ac_prev=pdfdir ;;
+  -pdfdir=* | --pdfdir=* | --pdfdi=* | --pdfd=* | --pdf=* | --pd=*)
+    pdfdir=$ac_optarg ;;
+
+  -psdir | --psdir | --psdi | --psd | --ps)
+    ac_prev=psdir ;;
+  -psdir=* | --psdir=* | --psdi=* | --psd=* | --ps=*)
+    psdir=$ac_optarg ;;
+
+  -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+  | -silent | --silent | --silen | --sile | --sil)
+    silent=yes ;;
+
+  -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb)
+    ac_prev=sbindir ;;
+  -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \
+  | --sbi=* | --sb=*)
+    sbindir=$ac_optarg ;;
+
+  -sharedstatedir | --sharedstatedir | --sharedstatedi \
+  | --sharedstated | --sharedstate | --sharedstat | --sharedsta \
+  | --sharedst | --shareds | --shared | --share | --shar \
+  | --sha | --sh)
+    ac_prev=sharedstatedir ;;
+  -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \
+  | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \
+  | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \
+  | --sha=* | --sh=*)
+    sharedstatedir=$ac_optarg ;;
+
+  -site | --site | --sit)
+    ac_prev=site ;;
+  -site=* | --site=* | --sit=*)
+    site=$ac_optarg ;;
+
+  -srcdir | --srcdir | --srcdi | --srcd | --src | --sr)
+    ac_prev=srcdir ;;
+  -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*)
+    srcdir=$ac_optarg ;;
+
+  -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \
+  | --syscon | --sysco | --sysc | --sys | --sy)
+    ac_prev=sysconfdir ;;
+  -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \
+  | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*)
+    sysconfdir=$ac_optarg ;;
+
+  -target | --target | --targe | --targ | --tar | --ta | --t)
+    ac_prev=target_alias ;;
+  -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*)
+    target_alias=$ac_optarg ;;
+
+  -v | -verbose | --verbose | --verbos | --verbo | --verb)
+    verbose=yes ;;
+
+  -version | --version | --versio | --versi | --vers | -V)
+    ac_init_version=: ;;
+
+  -with-* | --with-*)
+    ac_useropt=`expr "x$ac_option" : 'x-*with-\([^=]*\)'`
+    # Reject names that are not valid shell variable names.
+    expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
+      as_fn_error $? "invalid package name: $ac_useropt"
+    ac_useropt_orig=$ac_useropt
+    ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
+    case $ac_user_opts in
+      *"
+"with_$ac_useropt"
+"*) ;;
+      *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--with-$ac_useropt_orig"
+	 ac_unrecognized_sep=', ';;
+    esac
+    eval with_$ac_useropt=\$ac_optarg ;;
+
+  -without-* | --without-*)
+    ac_useropt=`expr "x$ac_option" : 'x-*without-\(.*\)'`
+    # Reject names that are not valid shell variable names.
+    expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
+      as_fn_error $? "invalid package name: $ac_useropt"
+    ac_useropt_orig=$ac_useropt
+    ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
+    case $ac_user_opts in
+      *"
+"with_$ac_useropt"
+"*) ;;
+      *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--without-$ac_useropt_orig"
+	 ac_unrecognized_sep=', ';;
+    esac
+    eval with_$ac_useropt=no ;;
+
+  --x)
+    # Obsolete; use --with-x.
+    with_x=yes ;;
+
+  -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \
+  | --x-incl | --x-inc | --x-in | --x-i)
+    ac_prev=x_includes ;;
+  -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \
+  | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*)
+    x_includes=$ac_optarg ;;
+
+  -x-libraries | --x-libraries | --x-librarie | --x-librari \
+  | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l)
+    ac_prev=x_libraries ;;
+  -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \
+  | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*)
+    x_libraries=$ac_optarg ;;
+
+  -*) as_fn_error $? "unrecognized option: \`$ac_option'
+Try \`$0 --help' for more information"
+    ;;
+
+  *=*)
+    ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='`
+    # Reject names that are not valid shell variable names.
+    case $ac_envvar in #(
+      '' | [0-9]* | *[!_$as_cr_alnum]* )
+      as_fn_error $? "invalid variable name: \`$ac_envvar'" ;;
+    esac
+    eval $ac_envvar=\$ac_optarg
+    export $ac_envvar ;;
+
+  *)
+    # FIXME: should be removed in autoconf 3.0.
+    $as_echo "$as_me: WARNING: you should use --build, --host, --target" >&2
+    expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null &&
+      $as_echo "$as_me: WARNING: invalid host type: $ac_option" >&2
+    : "${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option}"
+    ;;
+
+  esac
+done
+
+if test -n "$ac_prev"; then
+  ac_option=--`echo $ac_prev | sed 's/_/-/g'`
+  as_fn_error $? "missing argument to $ac_option"
+fi
+
+if test -n "$ac_unrecognized_opts"; then
+  case $enable_option_checking in
+    no) ;;
+    fatal) as_fn_error $? "unrecognized options: $ac_unrecognized_opts" ;;
+    *)     $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2 ;;
+  esac
+fi
+
+# Check all directory arguments for consistency.
+for ac_var in	exec_prefix prefix bindir sbindir libexecdir datarootdir \
+		datadir sysconfdir sharedstatedir localstatedir includedir \
+		oldincludedir docdir infodir htmldir dvidir pdfdir psdir \
+		libdir localedir mandir
+do
+  eval ac_val=\$$ac_var
+  # Remove trailing slashes.
+  case $ac_val in
+    */ )
+      ac_val=`expr "X$ac_val" : 'X\(.*[^/]\)' \| "X$ac_val" : 'X\(.*\)'`
+      eval $ac_var=\$ac_val;;
+  esac
+  # Be sure to have absolute directory names.
+  case $ac_val in
+    [\\/$]* | ?:[\\/]* )  continue;;
+    NONE | '' ) case $ac_var in *prefix ) continue;; esac;;
+  esac
+  as_fn_error $? "expected an absolute directory name for --$ac_var: $ac_val"
+done
+
+# There might be people who depend on the old broken behavior: `$host'
+# used to hold the argument of --host etc.
+# FIXME: To remove some day.
+build=$build_alias
+host=$host_alias
+target=$target_alias
+
+# FIXME: To remove some day.
+if test "x$host_alias" != x; then
+  if test "x$build_alias" = x; then
+    cross_compiling=maybe
+  elif test "x$build_alias" != "x$host_alias"; then
+    cross_compiling=yes
+  fi
+fi
+
+ac_tool_prefix=
+test -n "$host_alias" && ac_tool_prefix=$host_alias-
+
+test "$silent" = yes && exec 6>/dev/null
+
+
+ac_pwd=`pwd` && test -n "$ac_pwd" &&
+ac_ls_di=`ls -di .` &&
+ac_pwd_ls_di=`cd "$ac_pwd" && ls -di .` ||
+  as_fn_error $? "working directory cannot be determined"
+test "X$ac_ls_di" = "X$ac_pwd_ls_di" ||
+  as_fn_error $? "pwd does not report name of working directory"
+
+
+# Find the source files, if location was not specified.
+if test -z "$srcdir"; then
+  ac_srcdir_defaulted=yes
+  # Try the directory containing this script, then the parent directory.
+  ac_confdir=`$as_dirname -- "$as_myself" ||
+$as_expr X"$as_myself" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+	 X"$as_myself" : 'X\(//\)[^/]' \| \
+	 X"$as_myself" : 'X\(//\)$' \| \
+	 X"$as_myself" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X"$as_myself" |
+    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\/\)[^/].*/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\/\)$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\).*/{
+	    s//\1/
+	    q
+	  }
+	  s/.*/./; q'`
+  srcdir=$ac_confdir
+  if test ! -r "$srcdir/$ac_unique_file"; then
+    srcdir=..
+  fi
+else
+  ac_srcdir_defaulted=no
+fi
+if test ! -r "$srcdir/$ac_unique_file"; then
+  test "$ac_srcdir_defaulted" = yes && srcdir="$ac_confdir or .."
+  as_fn_error $? "cannot find sources ($ac_unique_file) in $srcdir"
+fi
+ac_msg="sources are in $srcdir, but \`cd $srcdir' does not work"
+ac_abs_confdir=`(
+	cd "$srcdir" && test -r "./$ac_unique_file" || as_fn_error $? "$ac_msg"
+	pwd)`
+# When building in place, set srcdir=.
+if test "$ac_abs_confdir" = "$ac_pwd"; then
+  srcdir=.
+fi
+# Remove unnecessary trailing slashes from srcdir.
+# Double slashes in file names in object file debugging info
+# mess up M-x gdb in Emacs.
+case $srcdir in
+*/) srcdir=`expr "X$srcdir" : 'X\(.*[^/]\)' \| "X$srcdir" : 'X\(.*\)'`;;
+esac
+for ac_var in $ac_precious_vars; do
+  eval ac_env_${ac_var}_set=\${${ac_var}+set}
+  eval ac_env_${ac_var}_value=\$${ac_var}
+  eval ac_cv_env_${ac_var}_set=\${${ac_var}+set}
+  eval ac_cv_env_${ac_var}_value=\$${ac_var}
+done
+
+#
+# Report the --help message.
+#
+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 Haskell libfuse3 package 0.1.0.0 to adapt to many kinds of systems.
+
+Usage: $0 [OPTION]... [VAR=VALUE]...
+
+To assign environment variables (e.g., CC, CFLAGS...), specify them as
+VAR=VALUE.  See below for descriptions of some of the useful variables.
+
+Defaults for the options are specified in brackets.
+
+Configuration:
+  -h, --help              display this help and exit
+      --help=short        display options specific to this package
+      --help=recursive    display the short help of all the included packages
+  -V, --version           display version information and exit
+  -q, --quiet, --silent   do not print \`checking ...' messages
+      --cache-file=FILE   cache test results in FILE [disabled]
+  -C, --config-cache      alias for \`--cache-file=config.cache'
+  -n, --no-create         do not create output files
+      --srcdir=DIR        find the sources in DIR [configure dir or \`..']
+
+Installation directories:
+  --prefix=PREFIX         install architecture-independent files in PREFIX
+                          [$ac_default_prefix]
+  --exec-prefix=EPREFIX   install architecture-dependent files in EPREFIX
+                          [PREFIX]
+
+By default, \`make install' will install all the files in
+\`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc.  You can specify
+an installation prefix other than \`$ac_default_prefix' using \`--prefix',
+for instance \`--prefix=\$HOME'.
+
+For better control, use the options below.
+
+Fine tuning of the installation directories:
+  --bindir=DIR            user executables [EPREFIX/bin]
+  --sbindir=DIR           system admin executables [EPREFIX/sbin]
+  --libexecdir=DIR        program executables [EPREFIX/libexec]
+  --sysconfdir=DIR        read-only single-machine data [PREFIX/etc]
+  --sharedstatedir=DIR    modifiable architecture-independent data [PREFIX/com]
+  --localstatedir=DIR     modifiable single-machine data [PREFIX/var]
+  --libdir=DIR            object code libraries [EPREFIX/lib]
+  --includedir=DIR        C header files [PREFIX/include]
+  --oldincludedir=DIR     C header files for non-gcc [/usr/include]
+  --datarootdir=DIR       read-only arch.-independent data root [PREFIX/share]
+  --datadir=DIR           read-only architecture-independent data [DATAROOTDIR]
+  --infodir=DIR           info documentation [DATAROOTDIR/info]
+  --localedir=DIR         locale-dependent data [DATAROOTDIR/locale]
+  --mandir=DIR            man documentation [DATAROOTDIR/man]
+  --docdir=DIR            documentation root
+                          [DATAROOTDIR/doc/haskell-libfuse3-package]
+  --htmldir=DIR           html documentation [DOCDIR]
+  --dvidir=DIR            dvi documentation [DOCDIR]
+  --pdfdir=DIR            pdf documentation [DOCDIR]
+  --psdir=DIR             ps documentation [DOCDIR]
+_ACEOF
+
+  cat <<\_ACEOF
+_ACEOF
+fi
+
+if test -n "$ac_init_help"; then
+  case $ac_init_help in
+     short | recursive ) echo "Configuration of Haskell libfuse3 package 0.1.0.0:";;
+   esac
+  cat <<\_ACEOF
+
+Some influential environment variables:
+  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
+  FUSE3_CFLAGS
+              C compiler flags for FUSE3, overriding pkg-config
+  FUSE3_LIBS  linker flags for FUSE3, overriding pkg-config
+  CC          C compiler command
+  CFLAGS      C compiler flags
+  LDFLAGS     linker flags, e.g. -L<lib dir> if you have libraries in a
+              nonstandard directory <lib dir>
+  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>
+
+Use these variables to override the choices made by `configure' or to help
+it to find libraries and programs with nonstandard names/locations.
+
+Report bugs to the package provider.
+_ACEOF
+ac_status=$?
+fi
+
+if test "$ac_init_help" = "recursive"; then
+  # If there are subdirs, report their specific --help.
+  for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue
+    test -d "$ac_dir" ||
+      { cd "$srcdir" && ac_pwd=`pwd` && srcdir=. && test -d "$ac_dir"; } ||
+      continue
+    ac_builddir=.
+
+case "$ac_dir" in
+.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;;
+*)
+  ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'`
+  # A ".." for each directory in $ac_dir_suffix.
+  ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'`
+  case $ac_top_builddir_sub in
+  "") ac_top_builddir_sub=. ac_top_build_prefix= ;;
+  *)  ac_top_build_prefix=$ac_top_builddir_sub/ ;;
+  esac ;;
+esac
+ac_abs_top_builddir=$ac_pwd
+ac_abs_builddir=$ac_pwd$ac_dir_suffix
+# for backward compatibility:
+ac_top_builddir=$ac_top_build_prefix
+
+case $srcdir in
+  .)  # We are building in place.
+    ac_srcdir=.
+    ac_top_srcdir=$ac_top_builddir_sub
+    ac_abs_top_srcdir=$ac_pwd ;;
+  [\\/]* | ?:[\\/]* )  # Absolute name.
+    ac_srcdir=$srcdir$ac_dir_suffix;
+    ac_top_srcdir=$srcdir
+    ac_abs_top_srcdir=$srcdir ;;
+  *) # Relative name.
+    ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix
+    ac_top_srcdir=$ac_top_build_prefix$srcdir
+    ac_abs_top_srcdir=$ac_pwd/$srcdir ;;
+esac
+ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix
+
+    cd "$ac_dir" || { ac_status=$?; continue; }
+    # Check for guested configure.
+    if test -f "$ac_srcdir/configure.gnu"; then
+      echo &&
+      $SHELL "$ac_srcdir/configure.gnu" --help=recursive
+    elif test -f "$ac_srcdir/configure"; then
+      echo &&
+      $SHELL "$ac_srcdir/configure" --help=recursive
+    else
+      $as_echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2
+    fi || ac_status=$?
+    cd "$ac_pwd" || { ac_status=$?; break; }
+  done
+fi
+
+test -n "$ac_init_help" && exit $ac_status
+if $ac_init_version; then
+  cat <<\_ACEOF
+Haskell libfuse3 package configure 0.1.0.0
+generated by GNU Autoconf 2.69
+
+Copyright (C) 2012 Free Software Foundation, Inc.
+This configure script is free software; the Free Software Foundation
+gives unlimited permission to copy, distribute and modify it.
+_ACEOF
+  exit
+fi
+
+## ------------------------ ##
+## Autoconf initialization. ##
+## ------------------------ ##
+
+# ac_fn_c_try_compile LINENO
+# --------------------------
+# Try to compile conftest.$ac_ext, and return whether this succeeded.
+ac_fn_c_try_compile ()
+{
+  as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+  rm -f conftest.$ac_objext
+  if { { ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+  (eval "$ac_compile") 2>conftest.err
+  ac_status=$?
+  if test -s conftest.err; then
+    grep -v '^ *+' conftest.err >conftest.er1
+    cat conftest.er1 >&5
+    mv -f conftest.er1 conftest.err
+  fi
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then :
+  ac_retval=0
+else
+  $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	ac_retval=1
+fi
+  eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+  as_fn_set_status $ac_retval
+
+} # ac_fn_c_try_compile
+
+# ac_fn_c_check_member LINENO AGGR MEMBER VAR INCLUDES
+# ----------------------------------------------------
+# Tries to find if the field MEMBER exists in type AGGR, after including
+# INCLUDES, setting cache variable VAR accordingly.
+ac_fn_c_check_member ()
+{
+  as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2.$3" >&5
+$as_echo_n "checking for $2.$3... " >&6; }
+if eval \${$4+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+$5
+int
+main ()
+{
+static $2 ac_aggr;
+if (ac_aggr.$3)
+return 0;
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  eval "$4=yes"
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+$5
+int
+main ()
+{
+static $2 ac_aggr;
+if (sizeof ac_aggr.$3)
+return 0;
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  eval "$4=yes"
+else
+  eval "$4=no"
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+eval ac_res=\$$4
+	       { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+  eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+
+} # ac_fn_c_check_member
+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 Haskell libfuse3 package $as_me 0.1.0.0, which was
+generated by GNU Autoconf 2.69.  Invocation command line was
+
+  $ $0 $@
+
+_ACEOF
+exec 5>>config.log
+{
+cat <<_ASUNAME
+## --------- ##
+## Platform. ##
+## --------- ##
+
+hostname = `(hostname || uname -n) 2>/dev/null | sed 1q`
+uname -m = `(uname -m) 2>/dev/null || echo unknown`
+uname -r = `(uname -r) 2>/dev/null || echo unknown`
+uname -s = `(uname -s) 2>/dev/null || echo unknown`
+uname -v = `(uname -v) 2>/dev/null || echo unknown`
+
+/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown`
+/bin/uname -X     = `(/bin/uname -X) 2>/dev/null     || echo unknown`
+
+/bin/arch              = `(/bin/arch) 2>/dev/null              || echo unknown`
+/usr/bin/arch -k       = `(/usr/bin/arch -k) 2>/dev/null       || echo unknown`
+/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown`
+/usr/bin/hostinfo      = `(/usr/bin/hostinfo) 2>/dev/null      || echo unknown`
+/bin/machine           = `(/bin/machine) 2>/dev/null           || echo unknown`
+/usr/bin/oslevel       = `(/usr/bin/oslevel) 2>/dev/null       || echo unknown`
+/bin/universe          = `(/bin/universe) 2>/dev/null          || echo unknown`
+
+_ASUNAME
+
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    $as_echo "PATH: $as_dir"
+  done
+IFS=$as_save_IFS
+
+} >&5
+
+cat >&5 <<_ACEOF
+
+
+## ----------- ##
+## Core tests. ##
+## ----------- ##
+
+_ACEOF
+
+
+# Keep a trace of the command line.
+# Strip out --no-create and --no-recursion so they do not pile up.
+# Strip out --silent because we don't want to record it for future runs.
+# Also quote any args containing shell meta-characters.
+# Make two passes to allow for proper duplicate-argument suppression.
+ac_configure_args=
+ac_configure_args0=
+ac_configure_args1=
+ac_must_keep_next=false
+for ac_pass in 1 2
+do
+  for ac_arg
+  do
+    case $ac_arg in
+    -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;;
+    -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+    | -silent | --silent | --silen | --sile | --sil)
+      continue ;;
+    *\'*)
+      ac_arg=`$as_echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;;
+    esac
+    case $ac_pass in
+    1) as_fn_append ac_configure_args0 " '$ac_arg'" ;;
+    2)
+      as_fn_append ac_configure_args1 " '$ac_arg'"
+      if test $ac_must_keep_next = true; then
+	ac_must_keep_next=false # Got value, back to normal.
+      else
+	case $ac_arg in
+	  *=* | --config-cache | -C | -disable-* | --disable-* \
+	  | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \
+	  | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \
+	  | -with-* | --with-* | -without-* | --without-* | --x)
+	    case "$ac_configure_args0 " in
+	      "$ac_configure_args1"*" '$ac_arg' "* ) continue ;;
+	    esac
+	    ;;
+	  -* ) ac_must_keep_next=true ;;
+	esac
+      fi
+      as_fn_append ac_configure_args " '$ac_arg'"
+      ;;
+    esac
+  done
+done
+{ ac_configure_args0=; unset ac_configure_args0;}
+{ ac_configure_args1=; unset ac_configure_args1;}
+
+# When interrupted or exit'd, cleanup temporary files, and complete
+# config.log.  We remove comments because anyway the quotes in there
+# would cause problems or look ugly.
+# WARNING: Use '\'' to represent an apostrophe within the trap.
+# WARNING: Do not start the trap code with a newline, due to a FreeBSD 4.0 bug.
+trap 'exit_status=$?
+  # Save into config.log some information that might help in debugging.
+  {
+    echo
+
+    $as_echo "## ---------------- ##
+## Cache variables. ##
+## ---------------- ##"
+    echo
+    # The following way of writing the cache mishandles newlines in values,
+(
+  for ac_var in `(set) 2>&1 | sed -n '\''s/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'\''`; do
+    eval ac_val=\$$ac_var
+    case $ac_val in #(
+    *${as_nl}*)
+      case $ac_var in #(
+      *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5
+$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;;
+      esac
+      case $ac_var in #(
+      _ | IFS | as_nl) ;; #(
+      BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #(
+      *) { eval $ac_var=; unset $ac_var;} ;;
+      esac ;;
+    esac
+  done
+  (set) 2>&1 |
+    case $as_nl`(ac_space='\'' '\''; set) 2>&1` in #(
+    *${as_nl}ac_space=\ *)
+      sed -n \
+	"s/'\''/'\''\\\\'\'''\''/g;
+	  s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\''\\2'\''/p"
+      ;; #(
+    *)
+      sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p"
+      ;;
+    esac |
+    sort
+)
+    echo
+
+    $as_echo "## ----------------- ##
+## Output variables. ##
+## ----------------- ##"
+    echo
+    for ac_var in $ac_subst_vars
+    do
+      eval ac_val=\$$ac_var
+      case $ac_val in
+      *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;;
+      esac
+      $as_echo "$ac_var='\''$ac_val'\''"
+    done | sort
+    echo
+
+    if test -n "$ac_subst_files"; then
+      $as_echo "## ------------------- ##
+## File substitutions. ##
+## ------------------- ##"
+      echo
+      for ac_var in $ac_subst_files
+      do
+	eval ac_val=\$$ac_var
+	case $ac_val in
+	*\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;;
+	esac
+	$as_echo "$ac_var='\''$ac_val'\''"
+      done | sort
+      echo
+    fi
+
+    if test -s confdefs.h; then
+      $as_echo "## ----------- ##
+## confdefs.h. ##
+## ----------- ##"
+      echo
+      cat confdefs.h
+      echo
+    fi
+    test "$ac_signal" != 0 &&
+      $as_echo "$as_me: caught signal $ac_signal"
+    $as_echo "$as_me: exit $exit_status"
+  } >&5
+  rm -f core *.core core.conftest.* &&
+    rm -f -r conftest* confdefs* conf$$* $ac_clean_files &&
+    exit $exit_status
+' 0
+for ac_signal in 1 2 13 15; do
+  trap 'ac_signal='$ac_signal'; as_fn_exit 1' $ac_signal
+done
+ac_signal=0
+
+# confdefs.h avoids OS command line length limits that DEFS can exceed.
+rm -f -r conftest* confdefs.h
+
+$as_echo "/* confdefs.h */" > confdefs.h
+
+# Predefined preprocessor variables.
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_NAME "$PACKAGE_NAME"
+_ACEOF
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_TARNAME "$PACKAGE_TARNAME"
+_ACEOF
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_VERSION "$PACKAGE_VERSION"
+_ACEOF
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_STRING "$PACKAGE_STRING"
+_ACEOF
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT"
+_ACEOF
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_URL "$PACKAGE_URL"
+_ACEOF
+
+
+# Let the site file select an alternate cache file if it wants to.
+# Prefer an explicitly selected file to automatically selected ones.
+ac_site_file1=NONE
+ac_site_file2=NONE
+if test -n "$CONFIG_SITE"; then
+  # We do not want a PATH search for config.site.
+  case $CONFIG_SITE in #((
+    -*)  ac_site_file1=./$CONFIG_SITE;;
+    */*) ac_site_file1=$CONFIG_SITE;;
+    *)   ac_site_file1=./$CONFIG_SITE;;
+  esac
+elif test "x$prefix" != xNONE; then
+  ac_site_file1=$prefix/share/config.site
+  ac_site_file2=$prefix/etc/config.site
+else
+  ac_site_file1=$ac_default_prefix/share/config.site
+  ac_site_file2=$ac_default_prefix/etc/config.site
+fi
+for ac_site_file in "$ac_site_file1" "$ac_site_file2"
+do
+  test "x$ac_site_file" = xNONE && continue
+  if test /dev/null != "$ac_site_file" && test -r "$ac_site_file"; then
+    { $as_echo "$as_me:${as_lineno-$LINENO}: loading site script $ac_site_file" >&5
+$as_echo "$as_me: loading site script $ac_site_file" >&6;}
+    sed 's/^/| /' "$ac_site_file" >&5
+    . "$ac_site_file" \
+      || { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "failed to load site script $ac_site_file
+See \`config.log' for more details" "$LINENO" 5; }
+  fi
+done
+
+if test -r "$cache_file"; then
+  # Some versions of bash will fail to source /dev/null (special files
+  # actually), so we avoid doing that.  DJGPP emulates it as a regular file.
+  if test /dev/null != "$cache_file" && test -f "$cache_file"; then
+    { $as_echo "$as_me:${as_lineno-$LINENO}: loading cache $cache_file" >&5
+$as_echo "$as_me: loading cache $cache_file" >&6;}
+    case $cache_file in
+      [\\/]* | ?:[\\/]* ) . "$cache_file";;
+      *)                      . "./$cache_file";;
+    esac
+  fi
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: creating cache $cache_file" >&5
+$as_echo "$as_me: creating cache $cache_file" >&6;}
+  >$cache_file
+fi
+
+# Check that the precious variables saved in the cache have kept the same
+# value.
+ac_cache_corrupted=false
+for ac_var in $ac_precious_vars; do
+  eval ac_old_set=\$ac_cv_env_${ac_var}_set
+  eval ac_new_set=\$ac_env_${ac_var}_set
+  eval ac_old_val=\$ac_cv_env_${ac_var}_value
+  eval ac_new_val=\$ac_env_${ac_var}_value
+  case $ac_old_set,$ac_new_set in
+    set,)
+      { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5
+$as_echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;}
+      ac_cache_corrupted=: ;;
+    ,set)
+      { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was not set in the previous run" >&5
+$as_echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;}
+      ac_cache_corrupted=: ;;
+    ,);;
+    *)
+      if test "x$ac_old_val" != "x$ac_new_val"; then
+	# differences in whitespace do not lead to failure.
+	ac_old_val_w=`echo x $ac_old_val`
+	ac_new_val_w=`echo x $ac_new_val`
+	if test "$ac_old_val_w" != "$ac_new_val_w"; then
+	  { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' has changed since the previous run:" >&5
+$as_echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;}
+	  ac_cache_corrupted=:
+	else
+	  { $as_echo "$as_me:${as_lineno-$LINENO}: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&5
+$as_echo "$as_me: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&2;}
+	  eval $ac_var=\$ac_old_val
+	fi
+	{ $as_echo "$as_me:${as_lineno-$LINENO}:   former value:  \`$ac_old_val'" >&5
+$as_echo "$as_me:   former value:  \`$ac_old_val'" >&2;}
+	{ $as_echo "$as_me:${as_lineno-$LINENO}:   current value: \`$ac_new_val'" >&5
+$as_echo "$as_me:   current value: \`$ac_new_val'" >&2;}
+      fi;;
+  esac
+  # Pass precious variables to config.status.
+  if test "$ac_new_set" = set; then
+    case $ac_new_val in
+    *\'*) ac_arg=$ac_var=`$as_echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;;
+    *) ac_arg=$ac_var=$ac_new_val ;;
+    esac
+    case " $ac_configure_args " in
+      *" '$ac_arg' "*) ;; # Avoid dups.  Use of quotes ensures accuracy.
+      *) as_fn_append ac_configure_args " '$ac_arg'" ;;
+    esac
+  fi
+done
+if $ac_cache_corrupted; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+  { $as_echo "$as_me:${as_lineno-$LINENO}: error: changes in the environment can compromise the build" >&5
+$as_echo "$as_me: error: changes in the environment can compromise the build" >&2;}
+  as_fn_error $? "run \`make distclean' and/or \`rm $cache_file' and start over" "$LINENO" 5
+fi
+## -------------------- ##
+## Main body of script. ##
+## -------------------- ##
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+
+# Safety check: Ensure that we are in the correct source directory.
+
+
+ac_config_headers="$ac_config_headers include/config.h"
+
+
+
+
+
+
+
+
+
+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 FUSE3" >&5
+$as_echo_n "checking for FUSE3... " >&6; }
+
+if test -n "$FUSE3_CFLAGS"; then
+    pkg_cv_FUSE3_CFLAGS="$FUSE3_CFLAGS"
+ elif test -n "$PKG_CONFIG"; then
+    if test -n "$PKG_CONFIG" && \
+    { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"fuse3 >= 3\""; } >&5
+  ($PKG_CONFIG --exists --print-errors "fuse3 >= 3") 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; then
+  pkg_cv_FUSE3_CFLAGS=`$PKG_CONFIG --cflags "fuse3 >= 3" 2>/dev/null`
+		      test "x$?" != "x0" && pkg_failed=yes
+else
+  pkg_failed=yes
+fi
+ else
+    pkg_failed=untried
+fi
+if test -n "$FUSE3_LIBS"; then
+    pkg_cv_FUSE3_LIBS="$FUSE3_LIBS"
+ elif test -n "$PKG_CONFIG"; then
+    if test -n "$PKG_CONFIG" && \
+    { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"fuse3 >= 3\""; } >&5
+  ($PKG_CONFIG --exists --print-errors "fuse3 >= 3") 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; then
+  pkg_cv_FUSE3_LIBS=`$PKG_CONFIG --libs "fuse3 >= 3" 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
+	        FUSE3_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "fuse3 >= 3" 2>&1`
+        else
+	        FUSE3_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "fuse3 >= 3" 2>&1`
+        fi
+	# Put the nasty error message in config.log where it belongs
+	echo "$FUSE3_PKG_ERRORS" >&5
+
+	as_fn_error $? "Package requirements (fuse3 >= 3) were not met:
+
+$FUSE3_PKG_ERRORS
+
+Consider adjusting the PKG_CONFIG_PATH environment variable if you
+installed software in a non-standard prefix.
+
+Alternatively, you may set the environment variables FUSE3_CFLAGS
+and FUSE3_LIBS to avoid the need to call pkg-config.
+See the pkg-config man page for more details." "$LINENO" 5
+elif test $pkg_failed = untried; then
+     	{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+	{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "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.
+
+Alternatively, you may set the environment variables FUSE3_CFLAGS
+and FUSE3_LIBS to avoid the need to call pkg-config.
+See the pkg-config man page for more details.
+
+To get pkg-config, see <http://pkg-config.freedesktop.org/>.
+See \`config.log' for more details" "$LINENO" 5; }
+else
+	FUSE3_CFLAGS=$pkg_cv_FUSE3_CFLAGS
+	FUSE3_LIBS=$pkg_cv_FUSE3_LIBS
+        { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+
+fi
+
+
+# The FUSE API version we use. Also output it to *.buildinfo (see AC_CONFIG_FILES) so that it is reused by cabal
+FUSEVER=31
+
+
+# Check for version-dependent fields
+old_CFLAGS="$CFLAGS"
+CFLAGS="$CFLAGS -DFUSE_USE_VERSION=$FUSEVER $FUSE3_CFLAGS"
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+if test -n "$ac_tool_prefix"; then
+  # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args.
+set dummy ${ac_tool_prefix}gcc; 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_prog_CC+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$CC"; then
+  ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+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_prog_CC="${ac_tool_prefix}gcc"
+    $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
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+$as_echo "$CC" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_CC"; then
+  ac_ct_CC=$CC
+  # Extract the first word of "gcc", so it can be a program name with args.
+set dummy gcc; 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_prog_ac_ct_CC+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$ac_ct_CC"; then
+  ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
+else
+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_prog_ac_ct_CC="gcc"
+    $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
+
+fi
+fi
+ac_ct_CC=$ac_cv_prog_ac_ct_CC
+if test -n "$ac_ct_CC"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5
+$as_echo "$ac_ct_CC" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+  if test "x$ac_ct_CC" = x; then
+    CC=""
+  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
+    CC=$ac_ct_CC
+  fi
+else
+  CC="$ac_cv_prog_CC"
+fi
+
+if test -z "$CC"; then
+          if test -n "$ac_tool_prefix"; then
+    # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args.
+set dummy ${ac_tool_prefix}cc; 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_prog_CC+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$CC"; then
+  ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+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_prog_CC="${ac_tool_prefix}cc"
+    $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
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+$as_echo "$CC" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+  fi
+fi
+if test -z "$CC"; then
+  # Extract the first word of "cc", so it can be a program name with args.
+set dummy cc; 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_prog_CC+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$CC"; then
+  ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+  ac_prog_rejected=no
+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
+    if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then
+       ac_prog_rejected=yes
+       continue
+     fi
+    ac_cv_prog_CC="cc"
+    $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
+
+if test $ac_prog_rejected = yes; then
+  # We found a bogon in the path, so make sure we never use it.
+  set dummy $ac_cv_prog_CC
+  shift
+  if test $# != 0; then
+    # We chose a different compiler from the bogus one.
+    # However, it has the same basename, so the bogon will be chosen
+    # first if we set CC to just the basename; use the full file name.
+    shift
+    ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@"
+  fi
+fi
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+$as_echo "$CC" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$CC"; then
+  if test -n "$ac_tool_prefix"; then
+  for ac_prog in cl.exe
+  do
+    # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args.
+set dummy $ac_tool_prefix$ac_prog; 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_prog_CC+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$CC"; then
+  ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+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_prog_CC="$ac_tool_prefix$ac_prog"
+    $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
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+$as_echo "$CC" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+    test -n "$CC" && break
+  done
+fi
+if test -z "$CC"; then
+  ac_ct_CC=$CC
+  for ac_prog in cl.exe
+do
+  # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; 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_prog_ac_ct_CC+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$ac_ct_CC"; then
+  ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
+else
+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_prog_ac_ct_CC="$ac_prog"
+    $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
+
+fi
+fi
+ac_ct_CC=$ac_cv_prog_ac_ct_CC
+if test -n "$ac_ct_CC"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5
+$as_echo "$ac_ct_CC" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+  test -n "$ac_ct_CC" && break
+done
+
+  if test "x$ac_ct_CC" = x; then
+    CC=""
+  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
+    CC=$ac_ct_CC
+  fi
+fi
+
+fi
+
+
+test -z "$CC" && { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "no acceptable C compiler found in \$PATH
+See \`config.log' for more details" "$LINENO" 5; }
+
+# Provide some information about the compiler.
+$as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5
+set X $ac_compile
+ac_compiler=$2
+for ac_option in --version -v -V -qversion; do
+  { { ac_try="$ac_compiler $ac_option >&5"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+  (eval "$ac_compiler $ac_option >&5") 2>conftest.err
+  ac_status=$?
+  if test -s conftest.err; then
+    sed '10a\
+... rest of stderr output deleted ...
+         10q' conftest.err >conftest.er1
+    cat conftest.er1 >&5
+  fi
+  rm -f conftest.er1 conftest.err
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }
+done
+
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+ac_clean_files_save=$ac_clean_files
+ac_clean_files="$ac_clean_files a.out a.out.dSYM a.exe b.out"
+# Try to create an executable without -o first, disregard a.out.
+# It will help us diagnose broken compilers, and finding out an intuition
+# of exeext.
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the C compiler works" >&5
+$as_echo_n "checking whether the C compiler works... " >&6; }
+ac_link_default=`$as_echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'`
+
+# The possible output files:
+ac_files="a.out conftest.exe conftest a.exe a_out.exe b.out conftest.*"
+
+ac_rmfiles=
+for ac_file in $ac_files
+do
+  case $ac_file in
+    *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;;
+    * ) ac_rmfiles="$ac_rmfiles $ac_file";;
+  esac
+done
+rm -f $ac_rmfiles
+
+if { { ac_try="$ac_link_default"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+  (eval "$ac_link_default") 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; then :
+  # Autoconf-2.13 could set the ac_cv_exeext variable to `no'.
+# So ignore a value of `no', otherwise this would lead to `EXEEXT = no'
+# in a Makefile.  We should not override ac_cv_exeext if it was cached,
+# so that the user can short-circuit this test for compilers unknown to
+# Autoconf.
+for ac_file in $ac_files ''
+do
+  test -f "$ac_file" || continue
+  case $ac_file in
+    *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj )
+	;;
+    [ab].out )
+	# We found the default executable, but exeext='' is most
+	# certainly right.
+	break;;
+    *.* )
+	if test "${ac_cv_exeext+set}" = set && test "$ac_cv_exeext" != no;
+	then :; else
+	   ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'`
+	fi
+	# We set ac_cv_exeext here because the later test for it is not
+	# safe: cross compilers may not add the suffix if given an `-o'
+	# argument, so we may need to know it at that point already.
+	# Even if this section looks crufty: it has the advantage of
+	# actually working.
+	break;;
+    * )
+	break;;
+  esac
+done
+test "$ac_cv_exeext" = no && ac_cv_exeext=
+
+else
+  ac_file=''
+fi
+if test -z "$ac_file"; then :
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+$as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error 77 "C compiler cannot create executables
+See \`config.log' for more details" "$LINENO" 5; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler default output file name" >&5
+$as_echo_n "checking for C compiler default output file name... " >&6; }
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_file" >&5
+$as_echo "$ac_file" >&6; }
+ac_exeext=$ac_cv_exeext
+
+rm -f -r a.out a.out.dSYM a.exe conftest$ac_cv_exeext b.out
+ac_clean_files=$ac_clean_files_save
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of executables" >&5
+$as_echo_n "checking for suffix of executables... " >&6; }
+if { { ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+  (eval "$ac_link") 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; then :
+  # If both `conftest.exe' and `conftest' are `present' (well, observable)
+# catch `conftest.exe'.  For instance with Cygwin, `ls conftest' will
+# work properly (i.e., refer to `conftest.exe'), while it won't with
+# `rm'.
+for ac_file in conftest.exe conftest conftest.*; do
+  test -f "$ac_file" || continue
+  case $ac_file in
+    *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;;
+    *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'`
+	  break;;
+    * ) break;;
+  esac
+done
+else
+  { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "cannot compute suffix of executables: cannot compile and link
+See \`config.log' for more details" "$LINENO" 5; }
+fi
+rm -f conftest conftest$ac_cv_exeext
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_exeext" >&5
+$as_echo "$ac_cv_exeext" >&6; }
+
+rm -f conftest.$ac_ext
+EXEEXT=$ac_cv_exeext
+ac_exeext=$EXEEXT
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <stdio.h>
+int
+main ()
+{
+FILE *f = fopen ("conftest.out", "w");
+ return ferror (f) || fclose (f) != 0;
+
+  ;
+  return 0;
+}
+_ACEOF
+ac_clean_files="$ac_clean_files conftest.out"
+# Check that the compiler produces executables we can run.  If not, either
+# the compiler is broken, or we cross compile.
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are cross compiling" >&5
+$as_echo_n "checking whether we are cross compiling... " >&6; }
+if test "$cross_compiling" != yes; then
+  { { ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+  (eval "$ac_link") 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }
+  if { ac_try='./conftest$ac_cv_exeext'
+  { { case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+  (eval "$ac_try") 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; }; then
+    cross_compiling=no
+  else
+    if test "$cross_compiling" = maybe; then
+	cross_compiling=yes
+    else
+	{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "cannot run C compiled programs.
+If you meant to cross compile, use \`--host'.
+See \`config.log' for more details" "$LINENO" 5; }
+    fi
+  fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $cross_compiling" >&5
+$as_echo "$cross_compiling" >&6; }
+
+rm -f conftest.$ac_ext conftest$ac_cv_exeext conftest.out
+ac_clean_files=$ac_clean_files_save
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of object files" >&5
+$as_echo_n "checking for suffix of object files... " >&6; }
+if ${ac_cv_objext+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.o conftest.obj
+if { { ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+  (eval "$ac_compile") 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; then :
+  for ac_file in conftest.o conftest.obj conftest.*; do
+  test -f "$ac_file" || continue;
+  case $ac_file in
+    *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM ) ;;
+    *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'`
+       break;;
+  esac
+done
+else
+  $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "cannot compute suffix of object files: cannot compile
+See \`config.log' for more details" "$LINENO" 5; }
+fi
+rm -f conftest.$ac_cv_objext conftest.$ac_ext
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_objext" >&5
+$as_echo "$ac_cv_objext" >&6; }
+OBJEXT=$ac_cv_objext
+ac_objext=$OBJEXT
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C compiler" >&5
+$as_echo_n "checking whether we are using the GNU C compiler... " >&6; }
+if ${ac_cv_c_compiler_gnu+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+#ifndef __GNUC__
+       choke me
+#endif
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  ac_compiler_gnu=yes
+else
+  ac_compiler_gnu=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ac_cv_c_compiler_gnu=$ac_compiler_gnu
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu" >&5
+$as_echo "$ac_cv_c_compiler_gnu" >&6; }
+if test $ac_compiler_gnu = yes; then
+  GCC=yes
+else
+  GCC=
+fi
+ac_test_CFLAGS=${CFLAGS+set}
+ac_save_CFLAGS=$CFLAGS
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5
+$as_echo_n "checking whether $CC accepts -g... " >&6; }
+if ${ac_cv_prog_cc_g+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_save_c_werror_flag=$ac_c_werror_flag
+   ac_c_werror_flag=yes
+   ac_cv_prog_cc_g=no
+   CFLAGS="-g"
+   cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  ac_cv_prog_cc_g=yes
+else
+  CFLAGS=""
+      cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+
+else
+  ac_c_werror_flag=$ac_save_c_werror_flag
+	 CFLAGS="-g"
+	 cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  ac_cv_prog_cc_g=yes
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+   ac_c_werror_flag=$ac_save_c_werror_flag
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_g" >&5
+$as_echo "$ac_cv_prog_cc_g" >&6; }
+if test "$ac_test_CFLAGS" = set; then
+  CFLAGS=$ac_save_CFLAGS
+elif test $ac_cv_prog_cc_g = yes; then
+  if test "$GCC" = yes; then
+    CFLAGS="-g -O2"
+  else
+    CFLAGS="-g"
+  fi
+else
+  if test "$GCC" = yes; then
+    CFLAGS="-O2"
+  else
+    CFLAGS=
+  fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C89" >&5
+$as_echo_n "checking for $CC option to accept ISO C89... " >&6; }
+if ${ac_cv_prog_cc_c89+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_cv_prog_cc_c89=no
+ac_save_CC=$CC
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <stdarg.h>
+#include <stdio.h>
+struct stat;
+/* Most of the following tests are stolen from RCS 5.7's src/conf.sh.  */
+struct buf { int x; };
+FILE * (*rcsopen) (struct buf *, struct stat *, int);
+static char *e (p, i)
+     char **p;
+     int i;
+{
+  return p[i];
+}
+static char *f (char * (*g) (char **, int), char **p, ...)
+{
+  char *s;
+  va_list v;
+  va_start (v,p);
+  s = g (p, va_arg (v,int));
+  va_end (v);
+  return s;
+}
+
+/* OSF 4.0 Compaq cc is some sort of almost-ANSI by default.  It has
+   function prototypes and stuff, but not '\xHH' hex character constants.
+   These don't provoke an error unfortunately, instead are silently treated
+   as 'x'.  The following induces an error, until -std is added to get
+   proper ANSI mode.  Curiously '\x00'!='x' always comes out true, for an
+   array size at least.  It's necessary to write '\x00'==0 to get something
+   that's true only with -std.  */
+int osf4_cc_array ['\x00' == 0 ? 1 : -1];
+
+/* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters
+   inside strings and character constants.  */
+#define FOO(x) 'x'
+int xlc6_cc_array[FOO(a) == 'x' ? 1 : -1];
+
+int test (int i, double x);
+struct s1 {int (*f) (int a);};
+struct s2 {int (*f) (double a);};
+int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int);
+int argc;
+char **argv;
+int
+main ()
+{
+return f (e, argv, 0) != argv[0]  ||  f (e, argv, 1) != argv[1];
+  ;
+  return 0;
+}
+_ACEOF
+for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \
+	-Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__"
+do
+  CC="$ac_save_CC $ac_arg"
+  if ac_fn_c_try_compile "$LINENO"; then :
+  ac_cv_prog_cc_c89=$ac_arg
+fi
+rm -f core conftest.err conftest.$ac_objext
+  test "x$ac_cv_prog_cc_c89" != "xno" && break
+done
+rm -f conftest.$ac_ext
+CC=$ac_save_CC
+
+fi
+# AC_CACHE_VAL
+case "x$ac_cv_prog_cc_c89" in
+  x)
+    { $as_echo "$as_me:${as_lineno-$LINENO}: result: none needed" >&5
+$as_echo "none needed" >&6; } ;;
+  xno)
+    { $as_echo "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5
+$as_echo "unsupported" >&6; } ;;
+  *)
+    CC="$CC $ac_cv_prog_cc_c89"
+    { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5
+$as_echo "$ac_cv_prog_cc_c89" >&6; } ;;
+esac
+if test "x$ac_cv_prog_cc_c89" != xno; then :
+
+fi
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+ac_fn_c_check_member "$LINENO" "struct fuse_operations" "lseek" "ac_cv_member_struct_fuse_operations_lseek" "#include <fuse.h>
+"
+if test "x$ac_cv_member_struct_fuse_operations_lseek" = xyes; then :
+
+fi
+
+CFLAGS="$old_CFLAGS"
+
+if test "x$ac_cv_member_struct_fuse_operations_lseek" = xyes; then
+
+$as_echo "#define FUSE_HAS_LSEEK 1" >>confdefs.h
+
+fi
+
+ac_config_files="$ac_config_files libfuse3.buildinfo"
+
+cat >confcache <<\_ACEOF
+# This file is a shell script that caches the results of configure
+# tests run on this system so they can be shared between configure
+# scripts and configure runs, see configure's option --config-cache.
+# It is not useful on other systems.  If it contains results you don't
+# want to keep, you may remove or edit it.
+#
+# config.status only pays attention to the cache file if you give it
+# the --recheck option to rerun configure.
+#
+# `ac_cv_env_foo' variables (set or unset) will be overridden when
+# loading this file, other *unset* `ac_cv_foo' will be assigned the
+# following values.
+
+_ACEOF
+
+# The following way of writing the cache mishandles newlines in values,
+# but we know of no workaround that is simple, portable, and efficient.
+# So, we kill variables containing newlines.
+# Ultrix sh set writes to stderr and can't be redirected directly,
+# and sets the high bit in the cache file unless we assign to the vars.
+(
+  for ac_var in `(set) 2>&1 | sed -n 's/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'`; do
+    eval ac_val=\$$ac_var
+    case $ac_val in #(
+    *${as_nl}*)
+      case $ac_var in #(
+      *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5
+$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;;
+      esac
+      case $ac_var in #(
+      _ | IFS | as_nl) ;; #(
+      BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #(
+      *) { eval $ac_var=; unset $ac_var;} ;;
+      esac ;;
+    esac
+  done
+
+  (set) 2>&1 |
+    case $as_nl`(ac_space=' '; set) 2>&1` in #(
+    *${as_nl}ac_space=\ *)
+      # `set' does not quote correctly, so add quotes: double-quote
+      # substitution turns \\\\ into \\, and sed turns \\ into \.
+      sed -n \
+	"s/'/'\\\\''/g;
+	  s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p"
+      ;; #(
+    *)
+      # `set' quotes correctly as required by POSIX, so do not add quotes.
+      sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p"
+      ;;
+    esac |
+    sort
+) |
+  sed '
+     /^ac_cv_env_/b end
+     t clear
+     :clear
+     s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/
+     t end
+     s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/
+     :end' >>confcache
+if diff "$cache_file" confcache >/dev/null 2>&1; then :; else
+  if test -w "$cache_file"; then
+    if test "x$cache_file" != "x/dev/null"; then
+      { $as_echo "$as_me:${as_lineno-$LINENO}: updating cache $cache_file" >&5
+$as_echo "$as_me: updating cache $cache_file" >&6;}
+      if test ! -f "$cache_file" || test -h "$cache_file"; then
+	cat confcache >"$cache_file"
+      else
+        case $cache_file in #(
+        */* | ?:*)
+	  mv -f confcache "$cache_file"$$ &&
+	  mv -f "$cache_file"$$ "$cache_file" ;; #(
+        *)
+	  mv -f confcache "$cache_file" ;;
+	esac
+      fi
+    fi
+  else
+    { $as_echo "$as_me:${as_lineno-$LINENO}: not updating unwritable cache $cache_file" >&5
+$as_echo "$as_me: not updating unwritable cache $cache_file" >&6;}
+  fi
+fi
+rm -f confcache
+
+test "x$prefix" = xNONE && prefix=$ac_default_prefix
+# Let make expand exec_prefix.
+test "x$exec_prefix" = xNONE && exec_prefix='${prefix}'
+
+DEFS=-DHAVE_CONFIG_H
+
+ac_libobjs=
+ac_ltlibobjs=
+U=
+for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue
+  # 1. Remove the extension, and $U if already installed.
+  ac_script='s/\$U\././;s/\.o$//;s/\.obj$//'
+  ac_i=`$as_echo "$ac_i" | sed "$ac_script"`
+  # 2. Prepend LIBOBJDIR.  When used with automake>=1.10 LIBOBJDIR
+  #    will be set to the directory where LIBOBJS objects are built.
+  as_fn_append ac_libobjs " \${LIBOBJDIR}$ac_i\$U.$ac_objext"
+  as_fn_append ac_ltlibobjs " \${LIBOBJDIR}$ac_i"'$U.lo'
+done
+LIBOBJS=$ac_libobjs
+
+LTLIBOBJS=$ac_ltlibobjs
+
+
+
+: "${CONFIG_STATUS=./config.status}"
+ac_write_fail=0
+ac_clean_files_save=$ac_clean_files
+ac_clean_files="$ac_clean_files $CONFIG_STATUS"
+{ $as_echo "$as_me:${as_lineno-$LINENO}: creating $CONFIG_STATUS" >&5
+$as_echo "$as_me: creating $CONFIG_STATUS" >&6;}
+as_write_fail=0
+cat >$CONFIG_STATUS <<_ASEOF || as_write_fail=1
+#! $SHELL
+# Generated by $as_me.
+# Run this file to recreate the current configuration.
+# Compiler output produced by configure, useful for debugging
+# configure, is in config.log if it exists.
+
+debug=false
+ac_cs_recheck=false
+ac_cs_silent=false
+
+SHELL=\${CONFIG_SHELL-$SHELL}
+export SHELL
+_ASEOF
+cat >>$CONFIG_STATUS <<\_ASEOF || as_write_fail=1
+## -------------------- ##
+## M4sh Initialization. ##
+## -------------------- ##
+
+# Be more Bourne compatible
+DUALCASE=1; export DUALCASE # for MKS sh
+if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then :
+  emulate sh
+  NULLCMD=:
+  # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which
+  # is contrary to our usage.  Disable this feature.
+  alias -g '${1+"$@"}'='"$@"'
+  setopt NO_GLOB_SUBST
+else
+  case `(set -o) 2>/dev/null` in #(
+  *posix*) :
+    set -o posix ;; #(
+  *) :
+     ;;
+esac
+fi
+
+
+as_nl='
+'
+export as_nl
+# Printing a long string crashes Solaris 7 /usr/bin/printf.
+as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\'
+as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo
+as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo
+# Prefer a ksh shell builtin over an external printf program on Solaris,
+# but without wasting forks for bash or zsh.
+if test -z "$BASH_VERSION$ZSH_VERSION" \
+    && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then
+  as_echo='print -r --'
+  as_echo_n='print -rn --'
+elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then
+  as_echo='printf %s\n'
+  as_echo_n='printf %s'
+else
+  if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then
+    as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"'
+    as_echo_n='/usr/ucb/echo -n'
+  else
+    as_echo_body='eval expr "X$1" : "X\\(.*\\)"'
+    as_echo_n_body='eval
+      arg=$1;
+      case $arg in #(
+      *"$as_nl"*)
+	expr "X$arg" : "X\\(.*\\)$as_nl";
+	arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;;
+      esac;
+      expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl"
+    '
+    export as_echo_n_body
+    as_echo_n='sh -c $as_echo_n_body as_echo'
+  fi
+  export as_echo_body
+  as_echo='sh -c $as_echo_body as_echo'
+fi
+
+# The user is always right.
+if test "${PATH_SEPARATOR+set}" != set; then
+  PATH_SEPARATOR=:
+  (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && {
+    (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 ||
+      PATH_SEPARATOR=';'
+  }
+fi
+
+
+# IFS
+# We need space, tab and new line, in precisely that order.  Quoting is
+# there to prevent editors from complaining about space-tab.
+# (If _AS_PATH_WALK were called with IFS unset, it would disable word
+# splitting by setting IFS to empty value.)
+IFS=" ""	$as_nl"
+
+# Find who we are.  Look in the path if we contain no directory separator.
+as_myself=
+case $0 in #((
+  *[\\/]* ) as_myself=$0 ;;
+  *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break
+  done
+IFS=$as_save_IFS
+
+     ;;
+esac
+# We did not find ourselves, most probably we were run as `sh COMMAND'
+# in which case we are not to be found in the path.
+if test "x$as_myself" = x; then
+  as_myself=$0
+fi
+if test ! -f "$as_myself"; then
+  $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2
+  exit 1
+fi
+
+# Unset variables that we do not need and which cause bugs (e.g. in
+# pre-3.0 UWIN ksh).  But do not cause bugs in bash 2.01; the "|| exit 1"
+# suppresses any "Segmentation fault" message there.  '((' could
+# trigger a bug in pdksh 5.2.14.
+for as_var in BASH_ENV ENV MAIL MAILPATH
+do eval test x\${$as_var+set} = xset \
+  && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || :
+done
+PS1='$ '
+PS2='> '
+PS4='+ '
+
+# NLS nuisances.
+LC_ALL=C
+export LC_ALL
+LANGUAGE=C
+export LANGUAGE
+
+# CDPATH.
+(unset CDPATH) >/dev/null 2>&1 && unset CDPATH
+
+
+# as_fn_error STATUS ERROR [LINENO LOG_FD]
+# ----------------------------------------
+# Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are
+# provided, also output the error to LOG_FD, referencing LINENO. Then exit the
+# script with STATUS, using 1 if that was 0.
+as_fn_error ()
+{
+  as_status=$1; test $as_status -eq 0 && as_status=1
+  if test "$4"; then
+    as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+    $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4
+  fi
+  $as_echo "$as_me: error: $2" >&2
+  as_fn_exit $as_status
+} # as_fn_error
+
+
+# as_fn_set_status STATUS
+# -----------------------
+# Set $? to STATUS, without forking.
+as_fn_set_status ()
+{
+  return $1
+} # as_fn_set_status
+
+# as_fn_exit STATUS
+# -----------------
+# Exit the shell with STATUS, even in a "trap 0" or "set -e" context.
+as_fn_exit ()
+{
+  set +e
+  as_fn_set_status $1
+  exit $1
+} # as_fn_exit
+
+# as_fn_unset VAR
+# ---------------
+# Portably unset VAR.
+as_fn_unset ()
+{
+  { eval $1=; unset $1;}
+}
+as_unset=as_fn_unset
+# as_fn_append VAR VALUE
+# ----------------------
+# Append the text in VALUE to the end of the definition contained in VAR. Take
+# advantage of any shell optimizations that allow amortized linear growth over
+# repeated appends, instead of the typical quadratic growth present in naive
+# implementations.
+if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then :
+  eval 'as_fn_append ()
+  {
+    eval $1+=\$2
+  }'
+else
+  as_fn_append ()
+  {
+    eval $1=\$$1\$2
+  }
+fi # as_fn_append
+
+# as_fn_arith ARG...
+# ------------------
+# Perform arithmetic evaluation on the ARGs, and store the result in the
+# global $as_val. Take advantage of shells that can avoid forks. The arguments
+# must be portable across $(()) and expr.
+if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then :
+  eval 'as_fn_arith ()
+  {
+    as_val=$(( $* ))
+  }'
+else
+  as_fn_arith ()
+  {
+    as_val=`expr "$@" || test $? -eq 1`
+  }
+fi # as_fn_arith
+
+
+if expr a : '\(a\)' >/dev/null 2>&1 &&
+   test "X`expr 00001 : '.*\(...\)'`" = X001; then
+  as_expr=expr
+else
+  as_expr=false
+fi
+
+if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then
+  as_basename=basename
+else
+  as_basename=false
+fi
+
+if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then
+  as_dirname=dirname
+else
+  as_dirname=false
+fi
+
+as_me=`$as_basename -- "$0" ||
+$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \
+	 X"$0" : 'X\(//\)$' \| \
+	 X"$0" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X/"$0" |
+    sed '/^.*\/\([^/][^/]*\)\/*$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\/\(\/\/\)$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\/\(\/\).*/{
+	    s//\1/
+	    q
+	  }
+	  s/.*/./; q'`
+
+# Avoid depending upon Character Ranges.
+as_cr_letters='abcdefghijklmnopqrstuvwxyz'
+as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
+as_cr_Letters=$as_cr_letters$as_cr_LETTERS
+as_cr_digits='0123456789'
+as_cr_alnum=$as_cr_Letters$as_cr_digits
+
+ECHO_C= ECHO_N= ECHO_T=
+case `echo -n x` in #(((((
+-n*)
+  case `echo 'xy\c'` in
+  *c*) ECHO_T='	';;	# ECHO_T is single tab character.
+  xy)  ECHO_C='\c';;
+  *)   echo `echo ksh88 bug on AIX 6.1` > /dev/null
+       ECHO_T='	';;
+  esac;;
+*)
+  ECHO_N='-n';;
+esac
+
+rm -f conf$$ conf$$.exe conf$$.file
+if test -d conf$$.dir; then
+  rm -f conf$$.dir/conf$$.file
+else
+  rm -f conf$$.dir
+  mkdir conf$$.dir 2>/dev/null
+fi
+if (echo >conf$$.file) 2>/dev/null; then
+  if ln -s conf$$.file conf$$ 2>/dev/null; then
+    as_ln_s='ln -s'
+    # ... but there are two gotchas:
+    # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail.
+    # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable.
+    # In both cases, we have to default to `cp -pR'.
+    ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe ||
+      as_ln_s='cp -pR'
+  elif ln conf$$.file conf$$ 2>/dev/null; then
+    as_ln_s=ln
+  else
+    as_ln_s='cp -pR'
+  fi
+else
+  as_ln_s='cp -pR'
+fi
+rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file
+rmdir conf$$.dir 2>/dev/null
+
+
+# as_fn_mkdir_p
+# -------------
+# Create "$as_dir" as a directory, including parents if necessary.
+as_fn_mkdir_p ()
+{
+
+  case $as_dir in #(
+  -*) as_dir=./$as_dir;;
+  esac
+  test -d "$as_dir" || eval $as_mkdir_p || {
+    as_dirs=
+    while :; do
+      case $as_dir in #(
+      *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'(
+      *) as_qdir=$as_dir;;
+      esac
+      as_dirs="'$as_qdir' $as_dirs"
+      as_dir=`$as_dirname -- "$as_dir" ||
+$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+	 X"$as_dir" : 'X\(//\)[^/]' \| \
+	 X"$as_dir" : 'X\(//\)$' \| \
+	 X"$as_dir" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X"$as_dir" |
+    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\/\)[^/].*/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\/\)$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\).*/{
+	    s//\1/
+	    q
+	  }
+	  s/.*/./; q'`
+      test -d "$as_dir" && break
+    done
+    test -z "$as_dirs" || eval "mkdir $as_dirs"
+  } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir"
+
+
+} # as_fn_mkdir_p
+if mkdir -p . 2>/dev/null; then
+  as_mkdir_p='mkdir -p "$as_dir"'
+else
+  test -d ./-p && rmdir ./-p
+  as_mkdir_p=false
+fi
+
+
+# as_fn_executable_p FILE
+# -----------------------
+# Test if FILE is an executable regular file.
+as_fn_executable_p ()
+{
+  test -f "$1" && test -x "$1"
+} # as_fn_executable_p
+as_test_x='test -x'
+as_executable_p=as_fn_executable_p
+
+# Sed expression to map a string onto a valid CPP name.
+as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'"
+
+# Sed expression to map a string onto a valid variable name.
+as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'"
+
+
+exec 6>&1
+## ----------------------------------- ##
+## Main body of $CONFIG_STATUS script. ##
+## ----------------------------------- ##
+_ASEOF
+test $as_write_fail = 0 && chmod +x $CONFIG_STATUS || ac_write_fail=1
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+# Save the log message, to keep $0 and so on meaningful, and to
+# report actual input values of CONFIG_FILES etc. instead of their
+# values after options handling.
+ac_log="
+This file was extended by Haskell libfuse3 package $as_me 0.1.0.0, which was
+generated by GNU Autoconf 2.69.  Invocation command line was
+
+  CONFIG_FILES    = $CONFIG_FILES
+  CONFIG_HEADERS  = $CONFIG_HEADERS
+  CONFIG_LINKS    = $CONFIG_LINKS
+  CONFIG_COMMANDS = $CONFIG_COMMANDS
+  $ $0 $@
+
+on `(hostname || uname -n) 2>/dev/null | sed 1q`
+"
+
+_ACEOF
+
+case $ac_config_files in *"
+"*) set x $ac_config_files; shift; ac_config_files=$*;;
+esac
+
+case $ac_config_headers in *"
+"*) set x $ac_config_headers; shift; ac_config_headers=$*;;
+esac
+
+
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+# Files that config.status was made for.
+config_files="$ac_config_files"
+config_headers="$ac_config_headers"
+
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+ac_cs_usage="\
+\`$as_me' instantiates files and other configuration actions
+from templates according to the current configuration.  Unless the files
+and actions are specified as TAGs, all are instantiated by default.
+
+Usage: $0 [OPTION]... [TAG]...
+
+  -h, --help       print this help, then exit
+  -V, --version    print version number and configuration settings, then exit
+      --config     print configuration, then exit
+  -q, --quiet, --silent
+                   do not print progress messages
+  -d, --debug      don't remove temporary files
+      --recheck    update $as_me by reconfiguring in the same conditions
+      --file=FILE[:TEMPLATE]
+                   instantiate the configuration file FILE
+      --header=FILE[:TEMPLATE]
+                   instantiate the configuration header FILE
+
+Configuration files:
+$config_files
+
+Configuration headers:
+$config_headers
+
+Report bugs to the package provider."
+
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
+ac_cs_version="\\
+Haskell libfuse3 package config.status 0.1.0.0
+configured by $0, generated by GNU Autoconf 2.69,
+  with options \\"\$ac_cs_config\\"
+
+Copyright (C) 2012 Free Software Foundation, Inc.
+This config.status script is free software; the Free Software Foundation
+gives unlimited permission to copy, distribute and modify it."
+
+ac_pwd='$ac_pwd'
+srcdir='$srcdir'
+test -n "\$AWK" || AWK=awk
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+# The default lists apply if the user does not specify any file.
+ac_need_defaults=:
+while test $# != 0
+do
+  case $1 in
+  --*=?*)
+    ac_option=`expr "X$1" : 'X\([^=]*\)='`
+    ac_optarg=`expr "X$1" : 'X[^=]*=\(.*\)'`
+    ac_shift=:
+    ;;
+  --*=)
+    ac_option=`expr "X$1" : 'X\([^=]*\)='`
+    ac_optarg=
+    ac_shift=:
+    ;;
+  *)
+    ac_option=$1
+    ac_optarg=$2
+    ac_shift=shift
+    ;;
+  esac
+
+  case $ac_option in
+  # Handling of the options.
+  -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r)
+    ac_cs_recheck=: ;;
+  --version | --versio | --versi | --vers | --ver | --ve | --v | -V )
+    $as_echo "$ac_cs_version"; exit ;;
+  --config | --confi | --conf | --con | --co | --c )
+    $as_echo "$ac_cs_config"; exit ;;
+  --debug | --debu | --deb | --de | --d | -d )
+    debug=: ;;
+  --file | --fil | --fi | --f )
+    $ac_shift
+    case $ac_optarg in
+    *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;;
+    '') as_fn_error $? "missing file argument" ;;
+    esac
+    as_fn_append CONFIG_FILES " '$ac_optarg'"
+    ac_need_defaults=false;;
+  --header | --heade | --head | --hea )
+    $ac_shift
+    case $ac_optarg in
+    *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;;
+    esac
+    as_fn_append CONFIG_HEADERS " '$ac_optarg'"
+    ac_need_defaults=false;;
+  --he | --h)
+    # Conflict between --help and --header
+    as_fn_error $? "ambiguous option: \`$1'
+Try \`$0 --help' for more information.";;
+  --help | --hel | -h )
+    $as_echo "$ac_cs_usage"; exit ;;
+  -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+  | -silent | --silent | --silen | --sile | --sil | --si | --s)
+    ac_cs_silent=: ;;
+
+  # This is an error.
+  -*) as_fn_error $? "unrecognized option: \`$1'
+Try \`$0 --help' for more information." ;;
+
+  *) as_fn_append ac_config_targets " $1"
+     ac_need_defaults=false ;;
+
+  esac
+  shift
+done
+
+ac_configure_extra_args=
+
+if $ac_cs_silent; then
+  exec 6>/dev/null
+  ac_configure_extra_args="$ac_configure_extra_args --silent"
+fi
+
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+if \$ac_cs_recheck; then
+  set X $SHELL '$0' $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion
+  shift
+  \$as_echo "running CONFIG_SHELL=$SHELL \$*" >&6
+  CONFIG_SHELL='$SHELL'
+  export CONFIG_SHELL
+  exec "\$@"
+fi
+
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+exec 5>>config.log
+{
+  echo
+  sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX
+## Running $as_me. ##
+_ASBOX
+  $as_echo "$ac_log"
+} >&5
+
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+
+# Handling of arguments.
+for ac_config_target in $ac_config_targets
+do
+  case $ac_config_target in
+    "include/config.h") CONFIG_HEADERS="$CONFIG_HEADERS include/config.h" ;;
+    "libfuse3.buildinfo") CONFIG_FILES="$CONFIG_FILES libfuse3.buildinfo" ;;
+
+  *) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5;;
+  esac
+done
+
+
+# If the user did not use the arguments to specify the items to instantiate,
+# then the envvar interface is used.  Set only those that are not.
+# We use the long form for the default assignment because of an extremely
+# bizarre bug on SunOS 4.1.3.
+if $ac_need_defaults; then
+  test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files
+  test "${CONFIG_HEADERS+set}" = set || CONFIG_HEADERS=$config_headers
+fi
+
+# Have a temporary directory for convenience.  Make it in the build tree
+# simply because there is no reason against having it here, and in addition,
+# creating and moving files from /tmp can sometimes cause problems.
+# Hook for its removal unless debugging.
+# Note that there is a small window in which the directory will not be cleaned:
+# after its creation but before its name has been assigned to `$tmp'.
+$debug ||
+{
+  tmp= ac_tmp=
+  trap 'exit_status=$?
+  : "${ac_tmp:=$tmp}"
+  { test ! -d "$ac_tmp" || rm -fr "$ac_tmp"; } && exit $exit_status
+' 0
+  trap 'as_fn_exit 1' 1 2 13 15
+}
+# Create a (secure) tmp directory for tmp files.
+
+{
+  tmp=`(umask 077 && mktemp -d "./confXXXXXX") 2>/dev/null` &&
+  test -d "$tmp"
+}  ||
+{
+  tmp=./conf$$-$RANDOM
+  (umask 077 && mkdir "$tmp")
+} || as_fn_error $? "cannot create a temporary directory in ." "$LINENO" 5
+ac_tmp=$tmp
+
+# Set up the scripts for CONFIG_FILES section.
+# No need to generate them if there are no CONFIG_FILES.
+# This happens for instance with `./config.status config.h'.
+if test -n "$CONFIG_FILES"; then
+
+
+ac_cr=`echo X | tr X '\015'`
+# On cygwin, bash can eat \r inside `` if the user requested igncr.
+# But we know of no other shell where ac_cr would be empty at this
+# point, so we can use a bashism as a fallback.
+if test "x$ac_cr" = x; then
+  eval ac_cr=\$\'\\r\'
+fi
+ac_cs_awk_cr=`$AWK 'BEGIN { print "a\rb" }' </dev/null 2>/dev/null`
+if test "$ac_cs_awk_cr" = "a${ac_cr}b"; then
+  ac_cs_awk_cr='\\r'
+else
+  ac_cs_awk_cr=$ac_cr
+fi
+
+echo 'BEGIN {' >"$ac_tmp/subs1.awk" &&
+_ACEOF
+
+
+{
+  echo "cat >conf$$subs.awk <<_ACEOF" &&
+  echo "$ac_subst_vars" | sed 's/.*/&!$&$ac_delim/' &&
+  echo "_ACEOF"
+} >conf$$subs.sh ||
+  as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5
+ac_delim_num=`echo "$ac_subst_vars" | grep -c '^'`
+ac_delim='%!_!# '
+for ac_last_try in false false false false false :; do
+  . ./conf$$subs.sh ||
+    as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5
+
+  ac_delim_n=`sed -n "s/.*$ac_delim\$/X/p" conf$$subs.awk | grep -c X`
+  if test $ac_delim_n = $ac_delim_num; then
+    break
+  elif $ac_last_try; then
+    as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5
+  else
+    ac_delim="$ac_delim!$ac_delim _$ac_delim!! "
+  fi
+done
+rm -f conf$$subs.sh
+
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+cat >>"\$ac_tmp/subs1.awk" <<\\_ACAWK &&
+_ACEOF
+sed -n '
+h
+s/^/S["/; s/!.*/"]=/
+p
+g
+s/^[^!]*!//
+:repl
+t repl
+s/'"$ac_delim"'$//
+t delim
+:nl
+h
+s/\(.\{148\}\)..*/\1/
+t more1
+s/["\\]/\\&/g; s/^/"/; s/$/\\n"\\/
+p
+n
+b repl
+:more1
+s/["\\]/\\&/g; s/^/"/; s/$/"\\/
+p
+g
+s/.\{148\}//
+t nl
+:delim
+h
+s/\(.\{148\}\)..*/\1/
+t more2
+s/["\\]/\\&/g; s/^/"/; s/$/"/
+p
+b
+:more2
+s/["\\]/\\&/g; s/^/"/; s/$/"\\/
+p
+g
+s/.\{148\}//
+t delim
+' <conf$$subs.awk | sed '
+/^[^""]/{
+  N
+  s/\n//
+}
+' >>$CONFIG_STATUS || ac_write_fail=1
+rm -f conf$$subs.awk
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+_ACAWK
+cat >>"\$ac_tmp/subs1.awk" <<_ACAWK &&
+  for (key in S) S_is_set[key] = 1
+  FS = ""
+
+}
+{
+  line = $ 0
+  nfields = split(line, field, "@")
+  substed = 0
+  len = length(field[1])
+  for (i = 2; i < nfields; i++) {
+    key = field[i]
+    keylen = length(key)
+    if (S_is_set[key]) {
+      value = S[key]
+      line = substr(line, 1, len) "" value "" substr(line, len + keylen + 3)
+      len += length(value) + length(field[++i])
+      substed = 1
+    } else
+      len += 1 + keylen
+  }
+
+  print line
+}
+
+_ACAWK
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+if sed "s/$ac_cr//" < /dev/null > /dev/null 2>&1; then
+  sed "s/$ac_cr\$//; s/$ac_cr/$ac_cs_awk_cr/g"
+else
+  cat
+fi < "$ac_tmp/subs1.awk" > "$ac_tmp/subs.awk" \
+  || as_fn_error $? "could not setup config files machinery" "$LINENO" 5
+_ACEOF
+
+# VPATH may cause trouble with some makes, so we remove sole $(srcdir),
+# ${srcdir} and @srcdir@ entries from VPATH if srcdir is ".", strip leading and
+# trailing colons and then remove the whole line if VPATH becomes empty
+# (actually we leave an empty line to preserve line numbers).
+if test "x$srcdir" = x.; then
+  ac_vpsub='/^[	 ]*VPATH[	 ]*=[	 ]*/{
+h
+s///
+s/^/:/
+s/[	 ]*$/:/
+s/:\$(srcdir):/:/g
+s/:\${srcdir}:/:/g
+s/:@srcdir@:/:/g
+s/^:*//
+s/:*$//
+x
+s/\(=[	 ]*\).*/\1/
+G
+s/\n//
+s/^[^=]*=[	 ]*$//
+}'
+fi
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+fi # test -n "$CONFIG_FILES"
+
+# Set up the scripts for CONFIG_HEADERS section.
+# No need to generate them if there are no CONFIG_HEADERS.
+# This happens for instance with `./config.status Makefile'.
+if test -n "$CONFIG_HEADERS"; then
+cat >"$ac_tmp/defines.awk" <<\_ACAWK ||
+BEGIN {
+_ACEOF
+
+# Transform confdefs.h into an awk script `defines.awk', embedded as
+# here-document in config.status, that substitutes the proper values into
+# config.h.in to produce config.h.
+
+# Create a delimiter string that does not exist in confdefs.h, to ease
+# handling of long lines.
+ac_delim='%!_!# '
+for ac_last_try in false false :; do
+  ac_tt=`sed -n "/$ac_delim/p" confdefs.h`
+  if test -z "$ac_tt"; then
+    break
+  elif $ac_last_try; then
+    as_fn_error $? "could not make $CONFIG_HEADERS" "$LINENO" 5
+  else
+    ac_delim="$ac_delim!$ac_delim _$ac_delim!! "
+  fi
+done
+
+# For the awk script, D is an array of macro values keyed by name,
+# likewise P contains macro parameters if any.  Preserve backslash
+# newline sequences.
+
+ac_word_re=[_$as_cr_Letters][_$as_cr_alnum]*
+sed -n '
+s/.\{148\}/&'"$ac_delim"'/g
+t rset
+:rset
+s/^[	 ]*#[	 ]*define[	 ][	 ]*/ /
+t def
+d
+:def
+s/\\$//
+t bsnl
+s/["\\]/\\&/g
+s/^ \('"$ac_word_re"'\)\(([^()]*)\)[	 ]*\(.*\)/P["\1"]="\2"\
+D["\1"]=" \3"/p
+s/^ \('"$ac_word_re"'\)[	 ]*\(.*\)/D["\1"]=" \2"/p
+d
+:bsnl
+s/["\\]/\\&/g
+s/^ \('"$ac_word_re"'\)\(([^()]*)\)[	 ]*\(.*\)/P["\1"]="\2"\
+D["\1"]=" \3\\\\\\n"\\/p
+t cont
+s/^ \('"$ac_word_re"'\)[	 ]*\(.*\)/D["\1"]=" \2\\\\\\n"\\/p
+t cont
+d
+:cont
+n
+s/.\{148\}/&'"$ac_delim"'/g
+t clear
+:clear
+s/\\$//
+t bsnlc
+s/["\\]/\\&/g; s/^/"/; s/$/"/p
+d
+:bsnlc
+s/["\\]/\\&/g; s/^/"/; s/$/\\\\\\n"\\/p
+b cont
+' <confdefs.h | sed '
+s/'"$ac_delim"'/"\\\
+"/g' >>$CONFIG_STATUS || ac_write_fail=1
+
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+  for (key in D) D_is_set[key] = 1
+  FS = ""
+}
+/^[\t ]*#[\t ]*(define|undef)[\t ]+$ac_word_re([\t (]|\$)/ {
+  line = \$ 0
+  split(line, arg, " ")
+  if (arg[1] == "#") {
+    defundef = arg[2]
+    mac1 = arg[3]
+  } else {
+    defundef = substr(arg[1], 2)
+    mac1 = arg[2]
+  }
+  split(mac1, mac2, "(") #)
+  macro = mac2[1]
+  prefix = substr(line, 1, index(line, defundef) - 1)
+  if (D_is_set[macro]) {
+    # Preserve the white space surrounding the "#".
+    print prefix "define", macro P[macro] D[macro]
+    next
+  } else {
+    # Replace #undef with comments.  This is necessary, for example,
+    # in the case of _POSIX_SOURCE, which is predefined and required
+    # on some systems where configure will not decide to define it.
+    if (defundef == "undef") {
+      print "/*", prefix defundef, macro, "*/"
+      next
+    }
+  }
+}
+{ print }
+_ACAWK
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+  as_fn_error $? "could not setup config headers machinery" "$LINENO" 5
+fi # test -n "$CONFIG_HEADERS"
+
+
+eval set X "  :F $CONFIG_FILES  :H $CONFIG_HEADERS    "
+shift
+for ac_tag
+do
+  case $ac_tag in
+  :[FHLC]) ac_mode=$ac_tag; continue;;
+  esac
+  case $ac_mode$ac_tag in
+  :[FHL]*:*);;
+  :L* | :C*:*) as_fn_error $? "invalid tag \`$ac_tag'" "$LINENO" 5;;
+  :[FH]-) ac_tag=-:-;;
+  :[FH]*) ac_tag=$ac_tag:$ac_tag.in;;
+  esac
+  ac_save_IFS=$IFS
+  IFS=:
+  set x $ac_tag
+  IFS=$ac_save_IFS
+  shift
+  ac_file=$1
+  shift
+
+  case $ac_mode in
+  :L) ac_source=$1;;
+  :[FH])
+    ac_file_inputs=
+    for ac_f
+    do
+      case $ac_f in
+      -) ac_f="$ac_tmp/stdin";;
+      *) # Look for the file first in the build tree, then in the source tree
+	 # (if the path is not absolute).  The absolute path cannot be DOS-style,
+	 # because $ac_f cannot contain `:'.
+	 test -f "$ac_f" ||
+	   case $ac_f in
+	   [\\/$]*) false;;
+	   *) test -f "$srcdir/$ac_f" && ac_f="$srcdir/$ac_f";;
+	   esac ||
+	   as_fn_error 1 "cannot find input file: \`$ac_f'" "$LINENO" 5;;
+      esac
+      case $ac_f in *\'*) ac_f=`$as_echo "$ac_f" | sed "s/'/'\\\\\\\\''/g"`;; esac
+      as_fn_append ac_file_inputs " '$ac_f'"
+    done
+
+    # Let's still pretend it is `configure' which instantiates (i.e., don't
+    # use $as_me), people would be surprised to read:
+    #    /* config.h.  Generated by config.status.  */
+    configure_input='Generated from '`
+	  $as_echo "$*" | sed 's|^[^:]*/||;s|:[^:]*/|, |g'
+	`' by configure.'
+    if test x"$ac_file" != x-; then
+      configure_input="$ac_file.  $configure_input"
+      { $as_echo "$as_me:${as_lineno-$LINENO}: creating $ac_file" >&5
+$as_echo "$as_me: creating $ac_file" >&6;}
+    fi
+    # Neutralize special characters interpreted by sed in replacement strings.
+    case $configure_input in #(
+    *\&* | *\|* | *\\* )
+       ac_sed_conf_input=`$as_echo "$configure_input" |
+       sed 's/[\\\\&|]/\\\\&/g'`;; #(
+    *) ac_sed_conf_input=$configure_input;;
+    esac
+
+    case $ac_tag in
+    *:-:* | *:-) cat >"$ac_tmp/stdin" \
+      || as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;;
+    esac
+    ;;
+  esac
+
+  ac_dir=`$as_dirname -- "$ac_file" ||
+$as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+	 X"$ac_file" : 'X\(//\)[^/]' \| \
+	 X"$ac_file" : 'X\(//\)$' \| \
+	 X"$ac_file" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X"$ac_file" |
+    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\/\)[^/].*/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\/\)$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\).*/{
+	    s//\1/
+	    q
+	  }
+	  s/.*/./; q'`
+  as_dir="$ac_dir"; as_fn_mkdir_p
+  ac_builddir=.
+
+case "$ac_dir" in
+.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;;
+*)
+  ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'`
+  # A ".." for each directory in $ac_dir_suffix.
+  ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'`
+  case $ac_top_builddir_sub in
+  "") ac_top_builddir_sub=. ac_top_build_prefix= ;;
+  *)  ac_top_build_prefix=$ac_top_builddir_sub/ ;;
+  esac ;;
+esac
+ac_abs_top_builddir=$ac_pwd
+ac_abs_builddir=$ac_pwd$ac_dir_suffix
+# for backward compatibility:
+ac_top_builddir=$ac_top_build_prefix
+
+case $srcdir in
+  .)  # We are building in place.
+    ac_srcdir=.
+    ac_top_srcdir=$ac_top_builddir_sub
+    ac_abs_top_srcdir=$ac_pwd ;;
+  [\\/]* | ?:[\\/]* )  # Absolute name.
+    ac_srcdir=$srcdir$ac_dir_suffix;
+    ac_top_srcdir=$srcdir
+    ac_abs_top_srcdir=$srcdir ;;
+  *) # Relative name.
+    ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix
+    ac_top_srcdir=$ac_top_build_prefix$srcdir
+    ac_abs_top_srcdir=$ac_pwd/$srcdir ;;
+esac
+ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix
+
+
+  case $ac_mode in
+  :F)
+  #
+  # CONFIG_FILE
+  #
+
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+# If the template does not know about datarootdir, expand it.
+# FIXME: This hack should be removed a few years after 2.60.
+ac_datarootdir_hack=; ac_datarootdir_seen=
+ac_sed_dataroot='
+/datarootdir/ {
+  p
+  q
+}
+/@datadir@/p
+/@docdir@/p
+/@infodir@/p
+/@localedir@/p
+/@mandir@/p'
+case `eval "sed -n \"\$ac_sed_dataroot\" $ac_file_inputs"` in
+*datarootdir*) ac_datarootdir_seen=yes;;
+*@datadir@*|*@docdir@*|*@infodir@*|*@localedir@*|*@mandir@*)
+  { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5
+$as_echo "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;}
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+  ac_datarootdir_hack='
+  s&@datadir@&$datadir&g
+  s&@docdir@&$docdir&g
+  s&@infodir@&$infodir&g
+  s&@localedir@&$localedir&g
+  s&@mandir@&$mandir&g
+  s&\\\${datarootdir}&$datarootdir&g' ;;
+esac
+_ACEOF
+
+# Neutralize VPATH when `$srcdir' = `.'.
+# Shell code in configure.ac might set extrasub.
+# FIXME: do we really want to maintain this feature?
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+ac_sed_extra="$ac_vpsub
+$extrasub
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+:t
+/@[a-zA-Z_][a-zA-Z_0-9]*@/!b
+s|@configure_input@|$ac_sed_conf_input|;t t
+s&@top_builddir@&$ac_top_builddir_sub&;t t
+s&@top_build_prefix@&$ac_top_build_prefix&;t t
+s&@srcdir@&$ac_srcdir&;t t
+s&@abs_srcdir@&$ac_abs_srcdir&;t t
+s&@top_srcdir@&$ac_top_srcdir&;t t
+s&@abs_top_srcdir@&$ac_abs_top_srcdir&;t t
+s&@builddir@&$ac_builddir&;t t
+s&@abs_builddir@&$ac_abs_builddir&;t t
+s&@abs_top_builddir@&$ac_abs_top_builddir&;t t
+$ac_datarootdir_hack
+"
+eval sed \"\$ac_sed_extra\" "$ac_file_inputs" | $AWK -f "$ac_tmp/subs.awk" \
+  >$ac_tmp/out || as_fn_error $? "could not create $ac_file" "$LINENO" 5
+
+test -z "$ac_datarootdir_hack$ac_datarootdir_seen" &&
+  { ac_out=`sed -n '/\${datarootdir}/p' "$ac_tmp/out"`; test -n "$ac_out"; } &&
+  { ac_out=`sed -n '/^[	 ]*datarootdir[	 ]*:*=/p' \
+      "$ac_tmp/out"`; test -z "$ac_out"; } &&
+  { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file contains a reference to the variable \`datarootdir'
+which seems to be undefined.  Please make sure it is defined" >&5
+$as_echo "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir'
+which seems to be undefined.  Please make sure it is defined" >&2;}
+
+  rm -f "$ac_tmp/stdin"
+  case $ac_file in
+  -) cat "$ac_tmp/out" && rm -f "$ac_tmp/out";;
+  *) rm -f "$ac_file" && mv "$ac_tmp/out" "$ac_file";;
+  esac \
+  || as_fn_error $? "could not create $ac_file" "$LINENO" 5
+ ;;
+  :H)
+  #
+  # CONFIG_HEADER
+  #
+  if test x"$ac_file" != x-; then
+    {
+      $as_echo "/* $configure_input  */" \
+      && eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs"
+    } >"$ac_tmp/config.h" \
+      || as_fn_error $? "could not create $ac_file" "$LINENO" 5
+    if diff "$ac_file" "$ac_tmp/config.h" >/dev/null 2>&1; then
+      { $as_echo "$as_me:${as_lineno-$LINENO}: $ac_file is unchanged" >&5
+$as_echo "$as_me: $ac_file is unchanged" >&6;}
+    else
+      rm -f "$ac_file"
+      mv "$ac_tmp/config.h" "$ac_file" \
+	|| as_fn_error $? "could not create $ac_file" "$LINENO" 5
+    fi
+  else
+    $as_echo "/* $configure_input  */" \
+      && eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs" \
+      || as_fn_error $? "could not create -" "$LINENO" 5
+  fi
+ ;;
+
+
+  esac
+
+done # for ac_tag
+
+
+as_fn_exit 0
+_ACEOF
+ac_clean_files=$ac_clean_files_save
+
+test $ac_write_fail = 0 ||
+  as_fn_error $? "write failure creating $CONFIG_STATUS" "$LINENO" 5
+
+
+# configure is writing to config.log, and then calls config.status.
+# config.status does its own redirection, appending to config.log.
+# Unfortunately, on DOS this fails, as config.log is still kept open
+# by configure, so config.status won't be able to write to it; its
+# output is simply discarded.  So we exec the FD to /dev/null,
+# effectively closing config.log, so it can be properly (re)opened and
+# appended to by config.status.  When coming back to configure, we
+# need to make the FD available again.
+if test "$no_create" != yes; then
+  ac_cs_success=:
+  ac_config_status_args=
+  test "$silent" = yes &&
+    ac_config_status_args="$ac_config_status_args --quiet"
+  exec 5>/dev/null
+  $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false
+  exec 5>>config.log
+  # Use ||, not &&, to avoid exiting from the if with $? = 1, which
+  # would make configure fail if this is the last instruction.
+  $ac_cs_success || as_fn_exit 1
+fi
+if test -n "$ac_unrecognized_opts" && test "$enable_option_checking" != no; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: unrecognized options: $ac_unrecognized_opts" >&5
+$as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2;}
+fi
+
diff --git a/configure.ac b/configure.ac
new file mode 100644
--- /dev/null
+++ b/configure.ac
@@ -0,0 +1,26 @@
+AC_INIT([Haskell libfuse3 package], [0.1.0.0])
+
+# Safety check: Ensure that we are in the correct source directory.
+AC_CONFIG_SRCDIR([libfuse3.cabal])
+
+AC_CONFIG_HEADERS([include/config.h])
+
+PKG_CHECK_MODULES([FUSE3], [fuse3 >= 3])
+AC_SUBST([FUSE3_CFLAGS])
+
+# The FUSE API version we use. Also output it to *.buildinfo (see AC_CONFIG_FILES) so that it is reused by cabal
+FUSEVER=31
+AC_SUBST([FUSEVER])
+
+# Check for version-dependent fields
+old_CFLAGS="$CFLAGS"
+CFLAGS="$CFLAGS -DFUSE_USE_VERSION=$FUSEVER $FUSE3_CFLAGS"
+AC_CHECK_MEMBER([struct fuse_operations.lseek],,,[[#include <fuse.h>]])
+CFLAGS="$old_CFLAGS"
+
+if test "x$ac_cv_member_struct_fuse_operations_lseek" = xyes; then
+  AC_DEFINE([FUSE_HAS_LSEEK], [1], [struct fuse_operations.lseek exists.])
+fi
+
+AC_CONFIG_FILES([libfuse3.buildinfo])
+AC_OUTPUT
diff --git a/example/CLoff.hsc b/example/CLoff.hsc
new file mode 100644
--- /dev/null
+++ b/example/CLoff.hsc
@@ -0,0 +1,11 @@
+{-# LANGUAGE DerivingStrategies #-}
+{-# LANGUAGE GeneralizedNewtypeDeriving #-}
+module CLoff where
+
+import Foreign (Bits, FiniteBits, Int64, Storable)
+
+#include <sys/types.h>
+
+newtype CLoff = CLoff (#type loff_t)
+  deriving (Bits, Bounded, Enum, Eq, FiniteBits, Integral, Num, Ord, Real, Storable)
+  deriving newtype (Read, Show)
diff --git a/example/null.hs b/example/null.hs
new file mode 100644
--- /dev/null
+++ b/example/null.hs
@@ -0,0 +1,74 @@
+{-# LANGUAGE DisambiguateRecordFields #-}
+{-# LANGUAGE NamedFieldPuns #-}
+-- |
+-- Copyright : (The original C)   2001-2007  Miklos Szeredi <miklos@szeredi.hu>
+--             (The Haskell port) 2020 yohashi
+-- License   : GPL-2
+--
+-- This \"filesystem\" provides only a single file. The mountpoint
+-- needs to be a file rather than a directory. All writes to the
+-- file will be discarded, and reading the file always returns \\0.
+--
+-- This is a port of the C program distributed with the official libfuse.
+-- See \"example/null.c\" in the distribution.
+module Main where
+
+import Control.Exception (SomeException)
+import Data.ByteString (ByteString)
+import Data.List (foldl')
+import Foreign.C (CInt, Errno, eIO, eNOENT, eOK)
+import System.Clock (Clock(Realtime), getTime)
+import System.IO (hPrint, stderr)
+import System.LibFuse3 (FileStat, defaultFileStat, defaultFuseOperations, fuseMain)
+import System.Posix.Files (groupReadMode, otherReadMode, ownerReadMode, ownerWriteMode, regularFileMode, unionFileModes)
+import System.Posix.Types (ByteCount, FileOffset)
+import System.Posix.User (getRealGroupID, getRealUserID)
+
+import qualified Data.ByteString as B
+import qualified System.LibFuse3 as Fuse
+
+nullGetattr :: FilePath -> IO (Either Errno FileStat)
+nullGetattr "/" = do
+  fileOwner <- getRealUserID
+  fileGroup <- getRealGroupID
+  now <- getTime Realtime
+  pure $ Right $ defaultFileStat
+    { Fuse.fileMode = foldl' unionFileModes regularFileMode [ownerReadMode, ownerWriteMode, groupReadMode, otherReadMode]
+    , Fuse.linkCount = 1
+    , Fuse.fileOwner
+    , Fuse.fileGroup
+    , Fuse.fileSize = 2 ^ (32 :: Int) -- 4G
+    , Fuse.accessTimeHiRes = now
+    , Fuse.modificationTimeHiRes = now
+    , Fuse.statusChangeTimeHiRes = now
+    }
+nullGetattr _ = pure $ Left eNOENT
+
+nullTruncate :: FilePath -> IO Errno
+nullTruncate "/" = pure eOK
+nullTruncate _   = pure eNOENT
+
+nullOpen :: FilePath -> IO (Either Errno ())
+nullOpen "/" = pure $ Right ()
+nullOpen _   = pure $ Left eNOENT
+
+nullRead :: FilePath -> ByteCount -> FileOffset -> IO (Either Errno ByteString)
+nullRead "/" size offset
+  | offset >= 2 ^ (32 :: Int) = pure $ Right mempty
+  | otherwise = pure $ Right $ B.replicate (fromIntegral size) 0
+nullRead _ _ _ = pure $ Left eNOENT
+
+nullWrite :: FilePath -> ByteString -> IO (Either Errno CInt)
+nullWrite "/" buf = pure $ Right $ fromIntegral $ B.length buf
+nullWrite _   _   = pure $ Left eNOENT
+
+main :: IO ()
+main = fuseMain ops (\e -> hPrint stderr (e :: SomeException) >> pure eIO)
+  where
+  ops = defaultFuseOperations
+    { Fuse.fuseGetattr = Just $ \fp _ -> nullGetattr fp
+    , Fuse.fuseTruncate = Just $ \fp _ _ -> nullTruncate fp
+    , Fuse.fuseOpen = Just $ \fp _ _ -> nullOpen fp
+    , Fuse.fuseRead = Just $ \fp _ sz off -> nullRead fp sz off
+    , Fuse.fuseWrite = Just $ \fp _ buf _ -> nullWrite fp buf
+    }
diff --git a/example/passthrough.hs b/example/passthrough.hs
new file mode 100644
--- /dev/null
+++ b/example/passthrough.hs
@@ -0,0 +1,226 @@
+-- |
+-- Copyright : (The original C)   2001-2007  Miklos Szeredi <miklos@szeredi.hu>
+--                                2011       Sebastian Pipping <sebastian@pipping.org>
+--             (The Haskell port) 2020 yohashi
+-- License   : GPL-2
+--
+-- This file system mirrors the existing file system hierarchy of the
+-- system, starting at the root file system. This is implemented by
+-- just "passing through" all requests to the corresponding user-space
+-- libc functions. Its performance is terrible.
+--
+-- This is a port of the C program distributed with the official libfuse.
+-- See \"example/passthrough.c\" in the distribution.
+module Main where
+
+import CLoff
+import Control.Exception (SomeException, bracket)
+import Data.ByteString (ByteString)
+import Data.Function (fix)
+import Data.Time.Clock.POSIX (POSIXTime)
+import Data.Void (Void)
+import Foreign (Ptr, allocaBytes, with)
+import Foreign.C (CInt(CInt), CSize(CSize), CUInt(CUInt), Errno(Errno), eIO, eOK, eOPNOTSUPP)
+import System.IO (SeekMode, hPrint, stderr)
+import System.LibFuse3
+import System.Linux.XAttr (lCreateXAttr, lGetXAttr, lListXAttr, lRemoveXAttr, lReplaceXAttr, lSetXAttr)
+import System.Posix.Directory (closeDirStream, createDirectory, openDirStream, readDirStream, removeDirectory)
+import System.Posix.Files (createDevice, createLink, createNamedPipe, createSymbolicLink, readSymbolicLink, removeLink, rename, setFdSize, setFileCreationMask, setFileMode, setFileSize, setSymbolicLinkOwnerAndGroup, setSymbolicLinkTimesHiRes)
+import System.Posix.IO (OpenFileFlags, OpenMode(WriteOnly), closeFd, defaultFileFlags, exclusive, fdSeek, openFd)
+import System.Posix.Types (ByteCount, COff(COff), CSsize(CSsize), DeviceID, Fd(Fd), FileMode, FileOffset, GroupID, UserID)
+
+import qualified Data.ByteString as B
+import qualified Data.ByteString.Unsafe as BU
+import qualified System.LibFuse3.FuseConfig as FuseConfig
+
+foreign import ccall "pread"
+  c_pread :: CInt -> Ptr a -> CSize -> COff -> IO CSsize
+
+foreign import ccall "pwrite"
+  c_pwrite :: CInt -> Ptr a -> CSize -> COff -> IO CSsize
+
+foreign import ccall "posix_fallocate"
+  c_posix_fallocate :: CInt -> COff -> COff -> IO CInt
+
+foreign import ccall "copy_file_range"
+  c_copy_file_range :: CInt -> Ptr CLoff -> CInt -> Ptr CLoff -> CSize -> CUInt -> IO CSsize
+
+xmpInit :: FuseConfig -> IO FuseConfig
+xmpInit cfg = pure $ cfg
+  { FuseConfig.useIno = True
+  -- Pick up changes from lower filesystem right away. This is
+  -- also necessary for better hardlink support. When the kernel
+  -- calls the unlink() handler, it does not know the inode of
+  -- the to-be-removed entry and can therefore not invalidate
+  -- the cache of the associated inode - resulting in an
+  -- incorrect st_nlink value being reported for any remaining
+  -- hardlinks to this inode.
+  , FuseConfig.entryTimeout = 0
+  , FuseConfig.attrTimeout = 0
+  , FuseConfig.negativeTimeout = 0
+  }
+
+xmpGetattr :: FilePath -> IO (Either Errno FileStat)
+xmpGetattr = tryErrno . getFileStat
+
+xmpAccess :: FilePath -> AccessMode -> IO Errno
+xmpAccess = accessErrno
+
+xmpReadlink :: FilePath -> IO (Either Errno FilePath)
+xmpReadlink = tryErrno . readSymbolicLink
+
+xmpReaddir :: FilePath -> IO (Either Errno [(String, Maybe FileStat)])
+xmpReaddir path = tryErrno
+  $ bracket (openDirStream path) closeDirStream
+  $ \dp -> fmap reverse $ flip fix []
+  $ \loop acc -> do
+    entry <- readDirStream dp
+    if null entry
+      then pure acc
+      else loop $ (entry, Nothing) : acc
+
+xmpMknod :: FilePath -> FileMode -> DeviceID -> IO Errno
+xmpMknod path mode rdev = tryErrno_ $ case fileModeToEntryType mode of
+  RegularFile -> bracket (openFd path WriteOnly (Just mode) (defaultFileFlags{exclusive=True})) closeFd (\_ -> pure ())
+  Directory -> createDirectory path mode
+  NamedPipe -> createNamedPipe path mode
+  _ -> createDevice path mode rdev
+
+xmpMkdir :: FilePath -> FileMode -> IO Errno
+xmpMkdir path mode = tryErrno_ $ createDirectory path mode
+
+xmpUnlink :: FilePath -> IO Errno
+xmpUnlink = tryErrno_ . removeLink
+
+xmpRmdir :: FilePath -> IO Errno
+xmpRmdir = tryErrno_ . removeDirectory
+
+xmpSymlink :: FilePath -> FilePath -> IO Errno
+xmpSymlink from to = tryErrno_ $ createSymbolicLink from to
+
+xmpRename :: FilePath -> FilePath -> IO Errno
+xmpRename from to = tryErrno_ $ rename from to
+
+xmpLink :: FilePath -> FilePath -> IO Errno
+xmpLink from to = tryErrno_ $ createLink from to
+
+xmpChmod :: FilePath -> FileMode -> IO Errno
+xmpChmod path mode = tryErrno_ $ setFileMode path mode
+
+xmpChown :: FilePath -> UserID -> GroupID -> IO Errno
+xmpChown path uid gid = tryErrno_ $ setSymbolicLinkOwnerAndGroup path uid gid
+
+xmpTruncate :: FilePath -> Maybe Fd -> FileOffset -> IO Errno
+xmpTruncate path mfd size = tryErrno_ $ case mfd of
+  Just fd -> setFdSize fd size
+  Nothing -> setFileSize path size
+
+xmpUtimens :: FilePath -> POSIXTime -> POSIXTime -> IO Errno
+xmpUtimens path atime mtime = tryErrno_ $ setSymbolicLinkTimesHiRes path atime mtime
+
+xmpCreate :: FilePath -> OpenMode -> FileMode -> OpenFileFlags -> IO (Either Errno Fd)
+xmpCreate path omode fmode flags = tryErrno $ openFd path omode (Just fmode) flags
+
+xmpOpen :: FilePath -> OpenMode -> OpenFileFlags -> IO (Either Errno Fd)
+xmpOpen path mode flags = tryErrno $ openFd path mode Nothing flags
+
+xmpRead :: Fd -> ByteCount -> FileOffset -> IO (Either Errno ByteString)
+xmpRead (Fd fd) size offset = tryErrno $
+  -- instead of allocaBytes + packCStringLen, a pair of mallocBytes + unsafePackMallocCString
+  -- can be used to gain a small (~1%) decrease in running time
+  allocaBytes (fromIntegral size) $ \buf -> do
+    readBytes <- c_pread fd buf size offset
+    B.packCStringLen (buf, fromIntegral readBytes)
+
+xmpWrite :: Fd -> ByteString -> FileOffset -> IO (Either Errno CInt)
+xmpWrite (Fd fd) bs offset = tryErrno $
+  BU.unsafeUseAsCStringLen bs $ \(buf, size) ->
+    -- truncate CSsize (ssize_t = 64bit) to CInt (32bit) because there is no other way
+    fromIntegral <$> c_pwrite fd buf (fromIntegral size) offset
+
+xmpStatfs :: FilePath -> IO (Either Errno FileSystemStats)
+xmpStatfs = tryErrno . getFileSystemStats
+
+xmpRelease :: Fd -> IO ()
+xmpRelease = closeFd
+
+xmpFsync :: IO Errno
+-- Just a stub. This method is optional and can safely be left unimplemented
+xmpFsync = pure eOK
+
+xmpFallocate :: Fd -> CInt -> FileOffset -> FileOffset -> IO Errno
+xmpFallocate _ mode _ _ | mode /= 0 = pure eOPNOTSUPP
+xmpFallocate (Fd fd) _ offset len =
+  -- currently `System.Posix.Fcntl.fileAllocate` is broken
+  -- (see https://github.com/haskell/unix/issues/156)
+  -- so a custom implementation is used here
+  --
+  -- posix_fallocate(3) returns error number instead of setting errno
+  Errno <$> c_posix_fallocate fd offset len
+
+xmpSetxattr :: FilePath -> String -> ByteString -> SetxattrFlag -> IO Errno
+xmpSetxattr path name value flag = tryErrno_ $ go path name value
+  where
+  go = case flag of
+    SetxattrDefault -> lSetXAttr
+    SetxattrCreate  -> lCreateXAttr
+    SetxattrReplace -> lReplaceXAttr
+
+xmpGetxattr :: FilePath -> String -> IO (Either Errno ByteString)
+xmpGetxattr path name = tryErrno $ lGetXAttr path name
+
+xmpListxattr :: FilePath -> IO (Either Errno [String])
+xmpListxattr path = tryErrno $ lListXAttr path
+
+xmpRemovexattr :: FilePath -> String -> IO Errno
+xmpRemovexattr path name = tryErrno_ $ lRemoveXAttr path name
+
+xmpCopyFileRange :: Fd -> FileOffset -> Fd -> FileOffset -> ByteCount -> CUInt -> IO (Either Errno CSsize)
+xmpCopyFileRange (Fd fdIn) offIn (Fd fdOut) offOut len flags =
+  tryErrno $
+  with (fromIntegral offIn) $ \plOffIn ->
+  with (fromIntegral offOut) $ \plOffOut -> do
+    c_copy_file_range fdIn plOffIn fdOut plOffOut len flags
+    -- the example of libfuse closes the fds but I don't think it is correct
+
+xmpLseek :: Fd -> SeekMode -> FileOffset -> IO (Either Errno FileOffset)
+xmpLseek fd mode offset = tryErrno $ fdSeek fd mode offset
+
+xmpOper :: FuseOperations Fd Void
+xmpOper = defaultFuseOperations
+  { fuseInit          = Just xmpInit
+  , fuseGetattr       = Just $ \path _ -> xmpGetattr path
+  , fuseAccess        = Just xmpAccess
+  , fuseReadlink      = Just xmpReadlink
+  , fuseReaddir       = Just $ \path _ -> xmpReaddir path
+  , fuseMknod         = Just xmpMknod
+  , fuseMkdir         = Just xmpMkdir
+  , fuseSymlink       = Just xmpSymlink
+  , fuseUnlink        = Just xmpUnlink
+  , fuseRmdir         = Just xmpRmdir
+  , fuseRename        = Just xmpRename
+  , fuseLink          = Just xmpLink
+  , fuseChmod         = Just $ \path _ mode -> xmpChmod path mode
+  , fuseChown         = Just $ \path _ uid gid -> xmpChown path uid gid
+  , fuseTruncate      = Just xmpTruncate
+  , fuseUtimens       = Just $ \path _ atime mtime -> xmpUtimens path (timeSpecToPOSIXTime atime) (timeSpecToPOSIXTime mtime)
+  , fuseOpen          = Just xmpOpen
+  , fuseCreate        = Just xmpCreate
+  , fuseRead          = Just $ \_ -> xmpRead
+  , fuseWrite         = Just $ \_ -> xmpWrite
+  , fuseStatfs        = Just xmpStatfs
+  , fuseRelease       = Just $ \_ -> xmpRelease
+  , fuseFsync         = Just $ \_ _ _ -> xmpFsync
+  , fuseFallocate     = Just $ \_ fd mode offset len -> xmpFallocate fd mode offset len
+  , fuseSetxattr      = Just xmpSetxattr
+  , fuseGetxattr      = Just xmpGetxattr
+  , fuseListxattr     = Just xmpListxattr
+  , fuseRemovexattr   = Just xmpRemovexattr
+  , fuseCopyFileRange = Just $ \_ fdIn offIn _ fdOut offOut size flags -> xmpCopyFileRange fdIn offIn fdOut offOut size (fromIntegral flags)
+  , fuseLseek         = Just $ \_ fd off mode -> xmpLseek fd mode off
+  }
+
+main :: IO ()
+main = do
+  _ <- setFileCreationMask 0
+  fuseMain xmpOper (\e -> hPrint stderr (e :: SomeException) >> pure eIO)
diff --git a/example/statjson.hs b/example/statjson.hs
new file mode 100644
--- /dev/null
+++ b/example/statjson.hs
@@ -0,0 +1,303 @@
+{-# LANGUAGE DisambiguateRecordFields #-}
+{-# LANGUAGE LambdaCase #-}
+{-# LANGUAGE NamedFieldPuns #-}
+{-# LANGUAGE OverloadedStrings #-}
+-- |
+-- Copyright: (c) 2020 yohashi
+-- License  : MIT
+--
+-- A read-only filesystem that exposes file stats in JSON files.
+--
+-- This filesystem mirrors the content of a source directory along with JSON files generated
+-- next to each file. JSON files have \".stat.json\" at the end of their names.
+--
+-- For example:
+--
+-- Source directory:
+--
+-- > a.jpg
+-- > b
+-- > b/c.txt
+--
+-- Mounted directory:
+--
+-- > rootdir.stat.json  <- struct stat of the source directory
+-- > a.jpg
+-- > a.jpg.stat.json    <- struct stat of a.jpg
+-- > b
+-- > b.stat.json        <- struct stat of b
+-- > b/c.txt
+-- > b/c.txt.stat.json  <- struct stat of b/c.txt
+--
+-- If the source directory contains files which already have \".stat.json\" at the end of
+-- their names, they are shadowed (but their own JSON files are still generated, so you'll
+-- see \".stat.json.stat.json\" files).
+--
+-- This example demonstrates the expressiveness of Haskell. It uses the \"layered\"
+-- approach. There are three parts in this program; the part that generates
+-- \"rootdir.stat.json\", another for generating \".stat.json\" for each file, and the other
+-- that provides a read-only view of the source directory. For each of the parts a set of
+-- filesystem operations is defined as a layer. Operations may process and respond to
+-- filesystem requests themselves or delegate to the next layer. Finally the layers are
+-- combined to a @FuseOperations@.
+module Main(main) where
+
+import Data.Aeson ((.=))
+import Data.Bits ((.&.), (.|.), complement)
+import Data.ByteString (ByteString)
+import Data.Void (Void)
+import Foreign (Ptr, allocaBytes)
+import Foreign.C (CInt(CInt), CSize(CSize), Errno, eIO, eNOSYS, eOPNOTSUPP)
+import Numeric (showHex)
+import System.Clock (TimeSpec(TimeSpec))
+import System.Directory (doesPathExist, listDirectory, makeAbsolute)
+import System.Environment (getArgs, withArgs)
+import System.FilePath ((<.>), dropTrailingPathSeparator, stripExtension)
+import System.LibFuse3
+import System.IO (hPrint, stderr)
+import System.Posix.IO (OpenFileFlags, OpenMode(ReadOnly), closeFd, openFd)
+import System.Posix.Files (regularFileMode, stdFileMode)
+import System.Posix.Types (COff(COff), CSsize(CSsize), ByteCount, Fd(Fd), FileOffset)
+
+import qualified Data.Aeson as Aeson
+import qualified Data.ByteString as B
+import qualified Data.ByteString.Lazy as BL
+import qualified System.Clock
+
+foreign import ccall "pread"
+  c_pread :: CInt -> Ptr a -> CSize -> COff -> IO CSsize
+
+-- | An outcome of an individual operation in a layer.
+data Outcome a
+  -- | The request is forwarded to the next layer.
+  = Delegate
+  -- | The request is handled by the operation.
+  | Respond a
+  -- | The request is handled by both the operation and the next layer, and the results are
+  -- merged by the function.
+  | Merge a (a -> a -> a)
+
+type Action a = IO (Either Errno (Outcome a))
+
+-- | A set of operations, or a layer.
+data OpsLayer fh = OpsLayer
+  { layerGetAttr  :: FilePath -> Action FileStat
+  , layerReaddir  :: FilePath -> Action [(String, Maybe FileStat)]
+  -- | `Merge` is treated as same as `Respond`
+  , layerOpen     :: FilePath -> OpenMode -> OpenFileFlags -> Action fh
+  , layerRead     :: fh -> ByteCount -> FileOffset -> IO (Either Errno ByteString)
+  , layerRelease  :: fh -> IO ()
+  }
+
+removeWriteModes :: FileStat -> FileStat
+removeWriteModes stat = stat { fileMode = go (fileMode stat) }
+  where
+  go mode = mode .&. complement 0o222
+
+-- | Provides the read-only view of the source directory.
+passthroughOps :: FilePath -> OpsLayer Fd
+passthroughOps srcDir = OpsLayer
+  -- note that we can't use (</>) to concatenate to srcDir because paths passed from libfuse start with '/'
+  -- if srcDir has a trailing slash it makes double slashes but we ignore it
+  { layerGetAttr = \path -> tryErrno . fmap Respond . fmap removeWriteModes . getFileStat . (srcDir <>) $ path
+  , layerReaddir = \path -> tryErrno $ fmap Respond $ do
+      entries <- listDirectory $ srcDir <> path
+      pure $ map (\entry -> (entry, Nothing)) entries
+  , layerOpen = \path mode flags ->
+      case mode of
+        ReadOnly -> tryErrno $ fmap Respond $ openFd (srcDir <> path) mode Nothing flags
+        _ -> pure $ Left eOPNOTSUPP
+  , layerRead = \(Fd fd) size offset -> tryErrno $
+      allocaBytes (fromIntegral size) $ \buf -> do
+        readBytes <- c_pread fd buf size offset
+        B.packCStringLen (buf, fromIntegral readBytes)
+  , layerRelease = closeFd
+  }
+
+-- | Presents the \"\/roodir.stat.json\" file whose content is the metadata of the source
+-- directory.
+generateRootStatJsonOps :: FilePath -> OpsLayer FileStat
+generateRootStatJsonOps srcDir = OpsLayer
+  { layerGetAttr = \path ->
+      if path /= "/rootdir.stat.json"
+        then pure $ Right Delegate
+        else tryErrno $ do
+          -- borrow the original file's stat for the generated JSON's one
+          srcDirStat <- getFileStat $ srcDir
+          pure $ Respond $ srcDirStat
+            { fileMode = 0o444 .|. entryTypeToFileMode RegularFile
+            , linkCount = 1
+            , fileSize = fromIntegral $ BL.length $ generateFileStatJson srcDirStat
+            }
+
+  , layerReaddir = \path -> pure $ Right $ if path /= "/"
+      then Delegate
+      else Merge [("rootdir.stat.json", Nothing)] (<>)
+
+  , layerOpen = \path mode _ -> if path /= "/rootdir.stat.json"
+      then pure $ Right Delegate
+      else case mode of
+        ReadOnly -> tryErrno $ fmap Respond $ getFileStat srcDir
+        _ -> pure $ Left eOPNOTSUPP
+
+  , layerRead = \stat size off -> pure $ Right
+      $ BL.toStrict
+      $ BL.take (fromIntegral size)
+      $ BL.drop (fromIntegral off)
+      $ generateFileStatJson stat
+
+  , layerRelease = \_ -> pure ()
+  }
+
+-- | Encodes a `FileStat` into a JSON data.
+generateFileStatJson :: FileStat -> BL.ByteString
+generateFileStatJson stat = Aeson.encode $ Aeson.object
+  [ "st_ino"    .= toInt (fileID stat)
+  , "st_mode"   .= ("0x" <> showHex (fileMode stat) "")
+  , "st_nlink"  .= toInt (linkCount stat)
+  , "st_uid"    .= toInt (fileOwner stat)
+  , "st_gid"    .= toInt (fileGroup stat)
+  , "st_rdev"   .= toInt (specialDeviceID stat)
+  , "st_size"   .= toInt (fileSize stat)
+  , "st_blocks" .= toInt (blockCount stat)
+  , "st_atim"   .= timeSpecToJson (accessTimeHiRes stat)
+  , "st_mtim"   .= timeSpecToJson (modificationTimeHiRes stat)
+  , "st_ctim"   .= timeSpecToJson (statusChangeTimeHiRes stat)
+  ]
+  where
+  toInt x = fromIntegral x :: Int
+  timeSpecToJson TimeSpec{sec, nsec} = Aeson.object [ "sec" .= sec, "nsec" .= nsec ]
+
+-- | Presents a \".stat.json\" file for each file in the source directory.
+generateFileStatJsonOps :: FilePath -> OpsLayer FileStat
+generateFileStatJsonOps srcDir = OpsLayer
+  { layerGetAttr = \path ->
+      case stripExtension ".stat.json" path of
+        Nothing -> pure $ Right Delegate
+        Just origFilePath -> tryErrno $ do
+          origFileExists <- doesPathExist $ srcDir <> origFilePath
+          if not origFileExists
+            then pure Delegate
+            else do
+              -- borrow the original file's stat for the generated JSON's one
+              origFileStat <- getFileStat $ srcDir <> origFilePath
+              pure $ Respond $ removeWriteModes $ origFileStat
+                { fileMode = regularFileMode .|. fileMode origFileStat .&. stdFileMode
+                , fileSize = fromIntegral $ BL.length $ generateFileStatJson origFileStat
+                }
+
+  , layerReaddir = \path -> tryErrno $ do
+      origEntries <- listDirectory $ srcDir <> path
+      let statJsonEntries = map (\name -> (name, Nothing)) $ map (<.> ".stat.json") origEntries
+      pure $ Merge statJsonEntries (<>)
+
+  , layerOpen = \path mode _ ->
+      case mode of
+        ReadOnly -> case stripExtension ".stat.json" path of
+          Nothing -> pure $ Right Delegate
+          Just origFilePath -> tryErrno $ do
+            origFileExists <- doesPathExist $ srcDir <> origFilePath
+            if not origFileExists
+              then pure Delegate
+              else do
+                origFileStat <- getFileStat $ srcDir <> origFilePath
+                pure $ Respond origFileStat
+        _ -> pure $ Left eOPNOTSUPP
+
+  , layerRead = \stat size off -> pure $ Right
+      $ BL.toStrict
+      $ BL.take (fromIntegral size)
+      $ BL.drop (fromIntegral off)
+      $ generateFileStatJson stat
+
+  , layerRelease = \_ -> pure ()
+  }
+
+-- poor man's ExceptT
+andThen :: IO (Either e a) -> (a -> IO (Either e b)) -> IO (Either e b)
+andThen io f = io >>= \case
+  Left e -> pure $ Left e
+  Right a -> f a
+
+-- | Chains two `Action`s into one.
+--
+-- Runs the first `Action` and then run the second if needed.
+chainActions :: Action a -> Action a -> Action a
+chainActions a1 a2 = a1 `andThen` \case
+  Respond a  -> pure $ Right $ Respond a
+  Delegate   -> a2
+  Merge a fa -> a2 >>= pure . fmap (\case
+    Delegate   -> Merge a fa
+    Respond b  -> Respond $ fa a b
+    Merge b fb -> Merge (fa a b) fb
+    )
+
+infixl 2 `chainActions`
+
+-- | Runs (possibly a chain of) `Action`(s).
+--
+-- If it returns `Merge`, it is treated as `Respond`.
+runAction :: Action a -> IO (Either Errno a)
+runAction = fmap $ \case
+  Left e -> Left e
+  Right Delegate -> Left eNOSYS
+  Right (Respond a) -> Right a
+  Right (Merge a _) -> Right a
+
+data TheHandle
+  = GenRootStatHandle FileStat
+  | GenFileStatHandle FileStat
+  | PassthroughHandle Fd
+
+-- | Merges the three layers into one, and converts it to `FuseOperations`.
+ops :: FilePath -> FuseOperations TheHandle Void
+ops srcDir = defaultFuseOperations
+  { -- return the response of the first layer to respond.
+    fuseGetattr = Just $ \path _ -> runAction $
+      layerGetAttr (generateRootStatJsonOps  srcDir) path `chainActions`
+      layerGetAttr (generateFileStatJsonOps srcDir) path `chainActions`
+      layerGetAttr (passthroughOps          srcDir) path
+  , -- return the response of the first layer to respond.
+    fuseReaddir = Just $ \path _ -> runAction $
+      layerReaddir (generateRootStatJsonOps  srcDir) path `chainActions`
+      layerReaddir (generateFileStatJsonOps srcDir) path `chainActions`
+      layerReaddir (passthroughOps          srcDir) path
+  , -- try each layers in the order and put the result into the 3-way handle.
+    -- here we treat `Merge` as if `Respond`.
+    fuseOpen = Just $ \path mode flags ->
+      layerOpen (generateRootStatJsonOps srcDir) path mode flags `andThen` \case
+        Respond x -> pure $ Right $ GenRootStatHandle x
+        Merge x _ -> pure $ Right $ GenRootStatHandle x
+        Delegate -> layerOpen (generateFileStatJsonOps srcDir) path mode flags `andThen` \case
+          Respond x -> pure $ Right $ GenFileStatHandle x
+          Merge x _ -> pure $ Right $ GenFileStatHandle x
+          Delegate -> layerOpen (passthroughOps srcDir) path mode flags `andThen` \case
+            Respond x -> pure $ Right $ PassthroughHandle x
+            Merge x _ -> pure $ Right $ PassthroughHandle x
+            Delegate -> pure $ Left eNOSYS
+  , -- branch on the 3-way handle created by fuseOpen.
+    fuseRead = Just $ \_ -> \case
+      GenRootStatHandle stat -> layerRead (generateRootStatJsonOps srcDir) stat
+      GenFileStatHandle stat -> layerRead (generateFileStatJsonOps srcDir) stat
+      PassthroughHandle fd   -> layerRead (passthroughOps srcDir) fd
+  , -- branch on the 3-way handle created by fuseOpen.
+    fuseRelease = Just $ \_ -> \case
+      GenRootStatHandle stat -> layerRelease (generateRootStatJsonOps srcDir) stat
+      GenFileStatHandle stat -> layerRelease (generateFileStatJsonOps srcDir) stat
+      PassthroughHandle fd   -> layerRelease (passthroughOps srcDir) fd
+  }
+
+-- |
+--
+-- In addition to the common commandline arguments of libfuse applications, this accepts
+-- @--source PATH@ which takes the source directory.
+main :: IO ()
+main = do
+  (srcDir', rest) <- do
+    args <- getArgs
+    case break (=="--source") args of
+      (pre, _source:path:suf) -> pure (path, pre <> suf)
+      (_, _source:[]) -> fail "`--source` option expects a path"
+      (_, []) -> fail "requires an option `--source PATH`"
+  srcDir <- dropTrailingPathSeparator <$> makeAbsolute srcDir'
+  withArgs rest $ fuseMain (ops srcDir) (\e -> hPrint stderr (e :: IOError) >> pure eIO)
diff --git a/include/config.h.in b/include/config.h.in
new file mode 100644
--- /dev/null
+++ b/include/config.h.in
@@ -0,0 +1,22 @@
+/* include/config.h.in.  Generated from configure.ac by autoheader.  */
+
+/* struct fuse_operations.lseek exists. */
+#undef FUSE_HAS_LSEEK
+
+/* Define to the address where bug reports for this package should be sent. */
+#undef PACKAGE_BUGREPORT
+
+/* Define to the full name of this package. */
+#undef PACKAGE_NAME
+
+/* Define to the full name and version of this package. */
+#undef PACKAGE_STRING
+
+/* Define to the one symbol short name of this package. */
+#undef PACKAGE_TARNAME
+
+/* Define to the home page for this package. */
+#undef PACKAGE_URL
+
+/* Define to the version of this package. */
+#undef PACKAGE_VERSION
diff --git a/libfuse3.buildinfo.in b/libfuse3.buildinfo.in
new file mode 100644
--- /dev/null
+++ b/libfuse3.buildinfo.in
@@ -0,0 +1,1 @@
+cc-options:          @DEFS@ -DFUSE_USE_VERSION=@FUSEVER@
diff --git a/libfuse3.cabal b/libfuse3.cabal
new file mode 100644
--- /dev/null
+++ b/libfuse3.cabal
@@ -0,0 +1,107 @@
+cabal-version:       >=1.10
+-- Initial package description 'libfuse3.cabal' generated by 'cabal init'.
+-- For further documentation, see http://haskell.org/cabal/users-guide/
+
+name:                libfuse3
+version:             0.1.0.0
+synopsis:            A Haskell binding for libfuse-3.x
+description:         Bindings for libfuse, the FUSE userspace reference implementation, of version 3.x. Compatible with Linux.
+-- bug-reports:
+license:             MIT
+license-file:        LICENSE
+author:              yohashi
+maintainer:          yohashi <yohashi1991@gmail.com>
+-- copyright:
+category:            System
+build-type:          Configure
+extra-source-files:
+  CHANGELOG.md
+  LICENSE-HFuse
+  README.md
+  configure
+  configure.ac
+  include/config.h.in
+  libfuse3.buildinfo.in
+
+flag examples
+  default: False
+
+source-repository head
+  type:       git
+  location:   https://github.com/matil019/haskell-libfuse3
+
+library
+  exposed-modules:     System.LibFuse3
+                       System.LibFuse3.FileStat
+                       System.LibFuse3.FileSystemStats
+                       System.LibFuse3.FuseConfig
+                       System.LibFuse3.Internal
+                       System.LibFuse3.Internal.C
+                       System.LibFuse3.Internal.Resource
+                       System.LibFuse3.Utils
+  -- other-modules:
+  -- other-extensions:
+  build-depends:       base >=4.11 && <4.15
+                     , bytestring >=0.10.8 && <0.11
+                     , clock ==0.8.*
+                     , resourcet ==1.2.*
+                     , time >=1.6 && <1.10
+                     , unix ==2.7.*
+  pkgconfig-depends:   fuse3
+  hs-source-dirs:      src
+  include-dirs:        include
+  default-language:    Haskell2010
+  ghc-options:         -Wall -fdefer-typed-holes
+
+executable null
+  if flag(examples)
+    buildable: True
+    build-depends:       libfuse3, base
+                       , bytestring
+                       , clock
+                       , unix
+  else
+    buildable: False
+  main-is:             null.hs
+  -- other-modules:
+  -- other-extensions:
+  hs-source-dirs:      example
+  default-language:    Haskell2010
+  ghc-options:         -Wall -fdefer-typed-holes -threaded
+
+executable passthrough
+  if flag(examples)
+    buildable: True
+    build-depends:       libfuse3, base
+                       , bytestring
+                       , clock
+                       , linux-xattr ==0.1.*
+                       , time
+                       , unix
+  else
+    buildable: False
+  main-is:             passthrough.hs
+  other-modules:       CLoff
+  -- other-extensions:
+  hs-source-dirs:      example
+  default-language:    Haskell2010
+  ghc-options:         -Wall -fdefer-typed-holes -threaded
+
+executable statjson
+  if flag(examples)
+    buildable: True
+    build-depends:       libfuse3, base
+                       , aeson
+                       , bytestring
+                       , clock
+                       , directory
+                       , filepath
+                       , unix
+  else
+    buildable: False
+  main-is:             statjson.hs
+  -- other-modules:
+  -- other-extensions:
+  hs-source-dirs:      example
+  default-language:    Haskell2010
+  ghc-options:         -Wall -fdefer-typed-holes -threaded
diff --git a/src/System/LibFuse3.hs b/src/System/LibFuse3.hs
new file mode 100644
--- /dev/null
+++ b/src/System/LibFuse3.hs
@@ -0,0 +1,39 @@
+-- | A Haskell binding to libfuse-3.x.
+module System.LibFuse3
+  ( FuseOperations(..)
+  , defaultFuseOperations
+
+  , FuseConfig
+
+  , AccessMode(..)
+  , access
+  , accessErrno
+
+  , EntryType(..)
+  , entryTypeToFileMode
+  , fileModeToEntryType
+
+  , SyncType(..)
+
+  , FileStat(..)
+  , defaultFileStat
+  , getFileStat
+  , getFileStatFd
+
+  , FileSystemStats
+  , getFileSystemStats
+  , getFileSystemStatsFd
+
+  , SetxattrFlag(..)
+
+  , module System.LibFuse3.Utils
+
+  , fuseMain
+  )
+  where
+
+import System.LibFuse3.FileStat
+import System.LibFuse3.FileSystemStats
+import System.LibFuse3.FuseConfig
+import System.LibFuse3.Internal
+import System.LibFuse3.Utils
diff --git a/src/System/LibFuse3/FileStat.hsc b/src/System/LibFuse3/FileStat.hsc
new file mode 100644
--- /dev/null
+++ b/src/System/LibFuse3/FileStat.hsc
@@ -0,0 +1,129 @@
+{-# LANGUAGE RecordWildCards #-}
+-- | @struct stat@ in Haskell.
+module System.LibFuse3.FileStat where
+
+#include <sys/stat.h>
+
+import Foreign (Storable, alloca, castPtr, peek, peekByteOff, pokeByteOff)
+import Foreign.C (throwErrnoIfMinus1Retry_)
+import System.Clock (TimeSpec)
+import System.Posix.Error (throwErrnoPathIfMinus1Retry_)
+import System.Posix.Internals (c_fstat, lstat, withFilePath)
+import System.Posix.Types
+  ( CBlkSize
+  , DeviceID
+  , Fd(Fd)
+  , FileID
+  , FileMode
+  , FileOffset
+  , GroupID
+  , LinkCount
+  , UserID
+  )
+
+import qualified Foreign
+
+-- | A file status a.k.a. metadata.
+--
+-- The differences from `System.Posix.Files.FileStatus` are:
+--
+--   - Is a record type with a `Storable` instance.
+--
+--   - Has an extra field `blockCount`.
+--
+--   - Provides an exact representation (`TimeSpec`) of the time fields without converting to `Date.Time.Clock.POSIX.POSIXTime`.
+--
+--       - This assumes that the @struct stat@ has @st_atim@, @st_mtim@ and @st_ctim@ fields.
+--         On Linux this requires Linux >= 2.6.
+--
+-- @Ptr FileStat@ can be cast to @Ptr `System.Posix.Internals.CStat`@ and vice versa.
+--
+-- Use `defaultFileStat` and modify its fields you are interested in.
+--
+-- The @st_ino@ field is ignored unless the @use_ino@ mount option is given.
+--
+-- The @st_dev@ and @st_blksize@ fields are ignored by libfuse, so not provided.
+data FileStat = FileStat
+  { -- | Inode number. @st_ino@
+    fileID :: FileID
+  , -- | File type and mode. @st_mode@
+    fileMode :: FileMode
+  , -- | Number of hard links. @st_nlink@
+    linkCount :: LinkCount
+  , -- | User ID of owner. @st_uid@
+    fileOwner :: UserID
+  , -- | Group ID of owner. @st_gid@
+    fileGroup :: GroupID
+  , -- | Device ID (if special file). @st_rdev@
+    specialDeviceID :: DeviceID
+  , -- | Total size, in bytes. @st_size@
+    fileSize :: FileOffset
+  , -- | Number of 512B blocks allocated. @st_blocks@
+    blockCount :: CBlkSize -- see also: https://github.com/haskell/unix/pull/78/files
+  -- these assumes Linux >= 2.6
+  , -- | Time of last access. @st_atim@
+    accessTimeHiRes :: TimeSpec
+  , -- | Time of last modification. @st_mtim@
+    modificationTimeHiRes :: TimeSpec
+  , -- | Time of last status change. @st_ctim@
+    statusChangeTimeHiRes :: TimeSpec
+  }
+  deriving (Eq, Show)
+
+-- | Targets @struct stat@.
+instance Storable FileStat where
+  sizeOf _ = #size struct stat
+
+  alignment _ = #alignment struct stat
+
+  peek ptr = do
+    fileID     <- (#peek struct stat, st_ino) ptr
+    fileMode   <- (#peek struct stat, st_mode) ptr
+    linkCount  <- (#peek struct stat, st_nlink) ptr
+    fileOwner  <- (#peek struct stat, st_uid) ptr
+    fileGroup  <- (#peek struct stat, st_gid) ptr
+    specialDeviceID <- (#peek struct stat, st_rdev) ptr
+    fileSize   <- (#peek struct stat, st_size) ptr
+    blockCount <- (#peek struct stat, st_blocks) ptr
+    accessTimeHiRes       <- (#peek struct stat, st_atim) ptr
+    modificationTimeHiRes <- (#peek struct stat, st_mtim) ptr
+    statusChangeTimeHiRes <- (#peek struct stat, st_ctim) ptr
+    pure FileStat{..}
+
+  poke ptr FileStat{..} = do
+    (#poke struct stat, st_ino)    ptr fileID
+    (#poke struct stat, st_mode)   ptr fileMode
+    (#poke struct stat, st_nlink)  ptr linkCount
+    (#poke struct stat, st_uid)    ptr fileOwner
+    (#poke struct stat, st_gid)    ptr fileGroup
+    (#poke struct stat, st_rdev)   ptr specialDeviceID
+    (#poke struct stat, st_size)   ptr fileSize
+    (#poke struct stat, st_blocks) ptr blockCount
+    (#poke struct stat, st_atim)   ptr accessTimeHiRes
+    (#poke struct stat, st_mtim)   ptr modificationTimeHiRes
+    (#poke struct stat, st_ctim)   ptr statusChangeTimeHiRes
+
+-- | The default value of `FileStat`.
+--
+-- The Haskell Equivalent of zero-setting C code @{ struct stat st; memset(&st, 0, sizeof(struct stat)); }@.
+defaultFileStat :: FileStat
+defaultFileStat = FileStat 0 0 0 0 0 0 0 0 0 0 0
+
+-- | Reads a file status of a given file.
+--
+-- Calls @lstat@.
+getFileStat :: FilePath -> IO FileStat
+getFileStat path =
+  alloca $ \buf ->
+    withFilePath path $ \cpath -> do
+      throwErrnoPathIfMinus1Retry_ "getFileStat" path (lstat cpath (castPtr buf))
+      peek buf
+
+-- | Reads a file status of a given file.
+--
+-- Calls @fstat@.
+getFileStatFd :: Fd -> IO FileStat
+getFileStatFd (Fd fd) =
+  alloca $ \buf -> do
+    throwErrnoIfMinus1Retry_ "getFileStatFd" (c_fstat fd (castPtr buf))
+    peek buf
diff --git a/src/System/LibFuse3/FileSystemStats.hsc b/src/System/LibFuse3/FileSystemStats.hsc
new file mode 100644
--- /dev/null
+++ b/src/System/LibFuse3/FileSystemStats.hsc
@@ -0,0 +1,92 @@
+{-# LANGUAGE RecordWildCards #-}
+-- | @struct statvfs@ in Haskell.
+module System.LibFuse3.FileSystemStats where
+
+#include <sys/statvfs.h>
+
+import Foreign (Ptr, Storable, alloca, peek, peekByteOff, pokeByteOff)
+import Foreign.C (CInt(CInt), CString, CULong, throwErrnoIfMinus1Retry_)
+import System.Posix.Error (throwErrnoPathIfMinus1Retry_)
+import System.Posix.Internals (withFilePath)
+import System.Posix.Types (CFsBlkCnt, CFsFilCnt, Fd(Fd))
+
+import qualified Foreign
+
+-- | Passed to `System.LibFuse3.fuseStatfs`.
+--
+-- The 'Storable' instance targets C @struct statvfs@.
+--
+-- @f_favail@, @f_fsid@ and @f_flag@ fields are ignored by libfuse, and their corresponding
+-- fields are not defined.
+data FileSystemStats = FileSystemStats
+  { -- | Filesystem block size. @f_bsize@
+    blockSize :: CULong
+  , -- | Fragment size. @f_frsize@
+    fragmentSize :: CULong
+  , -- | Size of the filesystem in @f_frsize@ units. @f_blocks@
+    blockCount :: CFsBlkCnt
+  , -- | Number of free blocks. @f_bfree@
+    blocksFree :: CFsBlkCnt
+  , -- | Number of free blocks for unprivileged users. @f_bavail@
+    blocksAvailable :: CFsBlkCnt
+  , -- | Number of inodes (file nodes). @f_files@
+    fileCount :: CFsFilCnt
+  , -- | Number of free inodes. @f_ffree@
+    filesFree :: CFsFilCnt
+  , -- | Maximum filename length. @f_namemax@
+    maxNameLength :: CULong
+  }
+  deriving (Eq, Show)
+
+instance Storable FileSystemStats where
+  sizeOf _ = #size struct statvfs
+
+  alignment _ = #alignment struct statvfs
+
+  peek ptr = do
+    blockSize       <- (#peek struct statvfs, f_bsize) ptr
+    fragmentSize    <- (#peek struct statvfs, f_frsize) ptr
+    blockCount      <- (#peek struct statvfs, f_blocks) ptr
+    blocksFree      <- (#peek struct statvfs, f_bfree) ptr
+    blocksAvailable <- (#peek struct statvfs, f_bavail) ptr
+    fileCount       <- (#peek struct statvfs, f_files) ptr
+    filesFree       <- (#peek struct statvfs, f_ffree) ptr
+    maxNameLength   <- (#peek struct statvfs, f_namemax) ptr
+    pure FileSystemStats{..}
+
+  poke ptr FileSystemStats{..} = do
+    (#poke struct statvfs, f_bsize)   ptr blockSize
+    (#poke struct statvfs, f_frsize)  ptr fragmentSize
+    (#poke struct statvfs, f_blocks)  ptr blockCount
+    (#poke struct statvfs, f_bfree)   ptr blocksFree
+    (#poke struct statvfs, f_bavail)  ptr blocksAvailable
+    (#poke struct statvfs, f_files)   ptr fileCount
+    (#poke struct statvfs, f_ffree)   ptr filesFree
+    (#poke struct statvfs, f_namemax) ptr maxNameLength
+
+-- | Gets filesystem statistics.
+--
+-- Calls @statvfs@.
+getFileSystemStats
+  :: FilePath  -- ^ A path of any file within the filesystem
+  -> IO FileSystemStats
+getFileSystemStats path =
+  alloca $ \buf ->
+  withFilePath path $ \cpath -> do
+    throwErrnoPathIfMinus1Retry_ "getFileSystemStats" path (c_statvfs cpath buf)
+    peek buf
+
+-- | Gets filesystem statistics.
+--
+-- Calls @fstatvfs@.
+getFileSystemStatsFd :: Fd -> IO FileSystemStats
+getFileSystemStatsFd fd =
+  alloca $ \buf -> do
+    throwErrnoIfMinus1Retry_ "getFileSystemStatsFd" (c_fstatvfs fd buf)
+    peek buf
+
+foreign import ccall safe "fstatvfs"
+  c_fstatvfs :: Fd -> Ptr FileSystemStats -> IO CInt
+
+foreign import ccall safe "statvfs"
+  c_statvfs :: CString -> Ptr FileSystemStats -> IO CInt
diff --git a/src/System/LibFuse3/FuseConfig.hs b/src/System/LibFuse3/FuseConfig.hs
new file mode 100644
--- /dev/null
+++ b/src/System/LibFuse3/FuseConfig.hs
@@ -0,0 +1,117 @@
+{-# LANGUAGE RecordWildCards #-}
+-- | The Haskell-friendly interface of @struct fuse_config@.
+module System.LibFuse3.FuseConfig where
+
+import Foreign.C (CDouble(CDouble), CInt(CInt), CUInt(CUInt))
+import System.Posix.Signals (Signal)
+import System.Posix.Types (CGid(CGid), CMode(CMode), CUid(CUid), FileMode, GroupID, UserID)
+
+import qualified System.LibFuse3.Internal.C as C
+
+-- | Configures the filesystem. Passed to `System.LibFuse3.fuseInit`.
+--
+-- See the module "System.LibFuse3.FuseConfig" for its fields.
+data FuseConfig = FuseConfig
+  { -- | @set_gid@
+    setGid :: Bool
+  , -- | @gid@
+    gid :: GroupID
+  , -- | @set_uid@
+    setUid :: Bool
+  , -- | @uid@
+    uid :: UserID
+  , -- | @set_mode@
+    setMode :: Bool
+  , -- | @umask@
+    umask :: FileMode
+  , -- | @entry_timeout@
+    entryTimeout :: Double
+  , -- | @negative_timeout@
+    negativeTimeout :: Double
+  , -- | @attr_timeout@
+    attrTimeout :: Double
+  , -- | @intr@
+    intr :: Bool
+  , -- | @intr_signal@
+    intrSignal :: Signal
+  , -- | @remember@
+    remember :: Int
+  , -- | @hard_remove@
+    hardRemove :: Bool
+  , -- | @use_ino@
+    useIno :: Bool
+  , -- | @readdir_ino@
+    readdirIno :: Bool
+  , -- | @direct_io@
+    directIo :: Bool
+  , -- | @kernel_cache@
+    kernelCache :: Bool
+  , -- | @auto_cache@
+    autoCache :: Bool
+  , -- | @ac_attr_timeout_set@
+    acAttrTimeoutSet :: Bool
+  , -- | @ac_attr_timeout@
+    acAttrTimeout :: Double
+  , -- | @nullpath_ok@
+    nullpathOk :: Bool
+  }
+  deriving (Eq, Show)
+
+-- | Converts to the Storable counterpart.
+toCFuseConfig :: FuseConfig -> C.FuseConfig
+toCFuseConfig FuseConfig{..} = C.FuseConfig
+  { C.setGid           = boolToCInt setGid
+  , C.gid              = CUInt $ (\(CGid x) -> x) gid
+  , C.setUid           = boolToCInt setUid
+  , C.uid              = CUInt $ (\(CUid x) -> x) uid
+  , C.setMode          = boolToCInt setMode
+  , C.umask            = CUInt $ (\(CMode x) -> x) umask
+  , C.entryTimeout     = CDouble entryTimeout
+  , C.negativeTimeout  = CDouble negativeTimeout
+  , C.attrTimeout      = CDouble attrTimeout
+  , C.intr             = boolToCInt intr
+  , C.intrSignal       = intrSignal
+  , C.remember         = fromIntegral remember
+  , C.hardRemove       = boolToCInt hardRemove
+  , C.useIno           = boolToCInt useIno
+  , C.readdirIno       = boolToCInt readdirIno
+  , C.directIo         = boolToCInt directIo
+  , C.kernelCache      = boolToCInt kernelCache
+  , C.autoCache        = boolToCInt autoCache
+  , C.acAttrTimeoutSet = boolToCInt acAttrTimeoutSet
+  , C.acAttrTimeout    = CDouble acAttrTimeout
+  , C.nullpathOk       = boolToCInt nullpathOk
+  }
+  where
+  boolToCInt b = if b then 1 else 0
+
+-- | Converts from the Storable counterpart.
+fromCFuseConfig :: C.FuseConfig -> FuseConfig
+fromCFuseConfig C.FuseConfig{..} = FuseConfig
+  { setGid           = cintToBool setGid
+  , gid              = CGid $ unCUInt gid
+  , setUid           = cintToBool setUid
+  , uid              = CUid $ unCUInt uid
+  , setMode          = cintToBool setMode
+  , umask            = CMode $ unCUInt umask
+  , entryTimeout     = unCDouble entryTimeout
+  , negativeTimeout  = unCDouble negativeTimeout
+  , attrTimeout      = unCDouble attrTimeout
+  , intr             = cintToBool intr
+  , intrSignal       = intrSignal
+  , remember         = fromIntegral $ unCInt remember
+  , hardRemove       = cintToBool hardRemove
+  , useIno           = cintToBool useIno
+  , readdirIno       = cintToBool readdirIno
+  , directIo         = cintToBool directIo
+  , kernelCache      = cintToBool kernelCache
+  , autoCache        = cintToBool autoCache
+  , acAttrTimeoutSet = cintToBool acAttrTimeoutSet
+  , acAttrTimeout    = unCDouble acAttrTimeout
+  , nullpathOk       = cintToBool nullpathOk
+  }
+  where
+  unCDouble (CDouble x) = x
+  unCInt (CInt x) = x
+  unCUInt (CUInt x) = x
+  cintToBool x = x /= 0
diff --git a/src/System/LibFuse3/Internal.hsc b/src/System/LibFuse3/Internal.hsc
new file mode 100644
--- /dev/null
+++ b/src/System/LibFuse3/Internal.hsc
@@ -0,0 +1,1036 @@
+{-# LANGUAGE LambdaCase #-}
+{-# LANGUAGE RecordWildCards #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+-- | The core stuff
+--
+-- This is an internal module. It is exposed to allow fine-tuning and workarounds but its API is not stable.
+module System.LibFuse3.Internal where
+
+import Control.Applicative ((<|>))
+import Control.Exception (Exception, bracket_, finally, handle)
+import Control.Monad (unless, void)
+import Control.Monad.IO.Class (liftIO)
+import Control.Monad.Trans.Resource (ResourceT, runResourceT)
+import Data.Bits ((.&.), (.|.))
+import Data.Foldable (traverse_)
+import Data.Maybe (fromJust)
+import Foreign
+  ( FunPtr
+  , Ptr
+  , StablePtr
+  , allocaBytes
+  , castPtrToStablePtr
+  , castStablePtrToPtr
+  , copyArray
+  , deRefStablePtr
+  , free
+  , freeHaskellFunPtr
+  , freeStablePtr
+  , maybeWith
+  , newStablePtr
+  , nullFunPtr
+  , nullPtr
+  , peek
+  , peekArray
+  , peekByteOff
+  , poke
+  , pokeByteOff
+  , with
+  )
+import Foreign.C (CInt(CInt), CString, Errno, eINVAL, eNOSYS, eOK, getErrno, peekCString, resetErrno, throwErrno, withCStringLen)
+import GHC.IO.Handle (hDuplicateTo)
+import System.Clock (TimeSpec)
+import System.Environment (getArgs, getProgName)
+import System.Exit (ExitCode(ExitFailure, ExitSuccess), exitFailure, exitSuccess, exitWith)
+import System.IO (IOMode(ReadMode, WriteMode), SeekMode(AbsoluteSeek, RelativeSeek, SeekFromEnd), stderr, stdin, stdout, withFile)
+import System.LibFuse3.FileStat (FileStat)
+import System.LibFuse3.FileSystemStats (FileSystemStats)
+import System.LibFuse3.FuseConfig (FuseConfig, fromCFuseConfig, toCFuseConfig)
+import System.LibFuse3.Internal.Resource (daemonizeResourceT, resMallocBytes, resNew, resNewArray, resNewCString, resNewFilePath)
+import System.LibFuse3.Utils (pokeCStringLen0, testBitSet, unErrno)
+import System.Posix.Directory (changeWorkingDirectory)
+import System.Posix.Files (blockSpecialMode, characterSpecialMode, directoryMode, namedPipeMode, regularFileMode, socketMode, symbolicLinkMode)
+import System.Posix.IO (OpenFileFlags(OpenFileFlags), OpenMode(ReadOnly, ReadWrite, WriteOnly))
+import System.Posix.Internals (c_access, peekFilePath, withFilePath)
+import System.Posix.Process (createSession)
+import System.Posix.Types (ByteCount, COff(COff), CSsize, DeviceID, FileMode, FileOffset, GroupID, UserID)
+import Text.Printf (hPrintf, printf)
+
+import qualified Control.Monad.Trans.Resource as Res
+import qualified Data.ByteString as B
+import qualified Data.ByteString.Unsafe as BU
+import qualified System.LibFuse3.Internal.C as C
+import qualified System.Posix.IO
+import qualified System.Posix.Signals as Signals
+
+#include <fuse.h>
+#include <fuse_lowlevel.h>
+#include <sys/xattr.h>
+
+-- | The Unix type of a node in the filesystem.
+data EntryType
+  = Unknown            -- ^ Unknown entry type
+  | NamedPipe
+  | CharacterSpecial
+  | Directory
+  | BlockSpecial
+  | RegularFile
+  | SymbolicLink
+  | Socket
+  deriving (Eq, Show)
+
+-- | Converts an 'EntryType' into the corresponding POSIX 'FileMode'.
+entryTypeToFileMode :: EntryType -> FileMode
+entryTypeToFileMode Unknown          = 0
+entryTypeToFileMode NamedPipe        = namedPipeMode
+entryTypeToFileMode CharacterSpecial = characterSpecialMode
+entryTypeToFileMode Directory        = directoryMode
+entryTypeToFileMode BlockSpecial     = blockSpecialMode
+entryTypeToFileMode RegularFile      = regularFileMode
+entryTypeToFileMode SymbolicLink     = symbolicLinkMode
+entryTypeToFileMode Socket           = socketMode
+
+-- | Decodes `EntryType` from a `FileMode`.
+fileModeToEntryType :: FileMode -> EntryType
+fileModeToEntryType mode
+  | fileType == namedPipeMode        = NamedPipe
+  | fileType == characterSpecialMode = CharacterSpecial
+  | fileType == directoryMode        = Directory
+  | fileType == blockSpecialMode     = BlockSpecial
+  | fileType == regularFileMode      = RegularFile
+  | fileType == symbolicLinkMode     = SymbolicLink
+  | fileType == socketMode           = Socket
+  | otherwise = Unknown
+  where
+  fileType = mode .&. (#const S_IFMT)
+
+-- | Passed to `fuseFsync` and `fuseFsyncdir`.
+data SyncType
+  -- | Synchronize both file content and metadata.
+  = FullSync
+  -- | Synchronize only the file content.
+  | DataSync
+  deriving (Eq, Show)
+
+-- | The query type of @access@. Passed to `fuseAccess`.
+data AccessMode
+  -- | File existence (@F_OK@)
+  = FileOK
+  -- | Reading, writing and executing permissions (@R_OK@, @W_OK@ and @X_OK@, resp.)
+  | PermOK Bool Bool Bool
+  deriving (Eq, Show)
+
+-- | Passed to `fuseSetxattr`.
+data SetxattrFlag
+  -- | Create a new attribute if it does not exist, or replace the value if it already exists (@0@)
+  = SetxattrDefault
+  -- | Perform a pure create, which fails if the named attribute exists already (@XATTR_CREATE@)
+  | SetxattrCreate
+  -- | Perform a pure replace operation, which fails if the named attribute does not already exist (@XATTR_REPLACE@)
+  | SetxattrReplace
+  deriving (Eq, Show)
+
+-- | Tests if access permissions to the file is granted or the file exists.
+--
+-- Calls @access@. Compared to `System.Posix.Files.fileAccess` and
+-- `System.Posix.Files.fileExist`, this function doesn't translate the errno and just
+-- returns @()@ to indicate success, or throws an error to indicate failure.
+access :: FilePath -> AccessMode -> IO ()
+access path mode = do
+  e <- accessErrno path mode
+  if e == eOK
+    then pure ()
+    else throwErrno "access"
+
+-- | Same as `access` but returns the `Errno` instead of throwing an exception.
+--
+-- Returns `eOK` on success.
+accessErrno :: FilePath -> AccessMode -> IO Errno
+accessErrno path mode = withFilePath path $ \cPath -> do
+  let cMode = case mode of
+        FileOK -> #const F_OK
+        PermOK r w x ->
+          (if r then (#const R_OK) else 0) .|.
+          (if w then (#const W_OK) else 0) .|.
+          (if x then (#const X_OK) else 0)
+  resetErrno
+  ret <- c_access cPath cMode
+  if ret == 0
+    then pure eOK
+    else getErrno
+
+-- memo: when adding a new field, make sure to update resCFuseOperations
+-- | The file system operations.
+--
+-- All operations are optional. Each field is named against @struct fuse_operations@ in
+-- @fuse.h@.
+--
+-- @fh@ is the file handle type returned by `fuseOpen`, and subsequently passed to all
+-- other file operations.
+--
+-- @dh@ is the directory handle type returned by `fuseOpendir`, and subsequently passed to
+-- `fuseReaddir` and `fuseReleasedir`.
+data FuseOperations fh dh = FuseOperations
+  { -- | Implements 'System.Posix.Files.getSymbolicLinkStatus' operation (POSIX @lstat(2)@).
+    --
+    -- @fh@ will always be @Nothing@ if the file is not currently open, but may also be
+    -- @Nothing@ even if it is open.
+    fuseGetattr :: Maybe (FilePath -> Maybe fh -> IO (Either Errno FileStat))
+
+  , -- | Implements 'System.Posix.Files.readSymbolicLink' operation (POSIX @readlink(2)@).
+    --
+    -- This function should not append a terminating NUL byte. The returned 'FilePath'
+    -- might be truncated depending on caller buffer size.
+    fuseReadlink :: Maybe (FilePath -> IO (Either Errno FilePath))
+
+  , -- | Implements 'System.Posix.Files.createDevice' (POSIX @mknod(2)@).
+    --
+    -- This function will also be called for regular file creation if `fuseCreate` is not defined.
+    --
+    -- `fileModeToEntryType` is handy to pattern match on the request type of the node.
+    fuseMknod :: Maybe (FilePath -> FileMode -> DeviceID -> IO Errno)
+
+  , -- | Implements 'System.Posix.Directory.createDirectory' (POSIX @mkdir(2)@).
+    fuseMkdir :: Maybe (FilePath -> FileMode -> IO Errno)
+
+  , -- | Implements 'System.Posix.Files.removeLink' (POSIX @unlink(2)@).
+    fuseUnlink :: Maybe (FilePath -> IO Errno)
+
+  , -- | Implements 'Ststen.Posix.Directory.removeDirectory' (POSIX @rmdir(2)@).
+    fuseRmdir :: Maybe (FilePath -> IO Errno)
+
+  , -- | Implements 'System.Posix.Files.createSymbolicLink' (POSIX @symlink(2)@).
+    fuseSymlink :: Maybe (FilePath -> FilePath -> IO Errno)
+
+  , -- | Implements 'System.Posix.Files.rename' (POSIX @rename(2)@).
+    fuseRename :: Maybe (FilePath -> FilePath -> IO Errno)
+
+  , -- | Implements 'System.Posix.Files.createLink' (POSIX @link(2)@).
+    fuseLink :: Maybe (FilePath -> FilePath -> IO Errno)
+
+  , -- | Implements 'System.Posix.Files.setFileMode' (POSIX @chmod(2)@).
+    --
+    -- @fh@ will always be @Nothing@ if the file is not currently open, but may also be
+    -- @Nothing@ even if it is open.
+    fuseChmod :: Maybe (FilePath -> Maybe fh -> FileMode -> IO Errno)
+
+  , -- | Implements 'System.Posix.Files.setOwnerAndGroup' (POSIX @chown(2)@).
+    --
+    -- @fh@ will always be @Nothing@ if the file is not currently open, but may also be
+    -- @Nothing@ even if it is open.
+    --
+    -- Unless @FUSE_CAP_HANDLE_KILLPRIV@ is disabled, this method is expected to reset the
+    -- setuid and setgid bits.
+    fuseChown :: Maybe (FilePath -> Maybe fh -> UserID -> GroupID -> IO Errno)
+
+  , -- | Implements 'System.Posix.Files.setFileSize' (POSIX @truncate(2)@).
+    --
+    -- @fh@ will always be @Nothing@ if the file is not currently open, but may also be
+    -- @Nothing@ even if it is open.
+    --
+    -- Unless @FUSE_CAP_HANDLE_KILLPRIV@ is disabled, this method is expected to reset the
+    -- setuid and setgid bits.
+    fuseTruncate :: Maybe (FilePath -> Maybe fh -> FileOffset -> IO Errno)
+
+  , -- | Implements 'System.Posix.Files.openFd' (POSIX @open(2)@).  On success, returns
+    -- 'Right' of a filehandle-like value that will be passed to future file operations; on
+    -- failure, returns 'Left' of the appropriate 'Errno'.
+    --
+    --   * Creation flags will be filtered out / handled by the kernel.
+    --   * Access modes should be used by this to check if the operation is permitted.
+    --   * The filesystem is expected to properly handle the @O_APPEND@ flag and ensure that
+    --     each write is appending to the end of the file.
+    --   * If this method returns @Left `eNOSYS`@ and @FUSE_CAP_NO_OPEN_SUPPORT@ is set in
+    --     @fuse_conn_info.capable@, this is treated as success and future calls to open
+    --     will also succeed without being sent to the filesystem process.
+    --
+    -- TODO allow this method to set @fuse_file_info.direct_io@ and @fuse_file_info.keep_cache@
+    fuseOpen :: Maybe (FilePath -> OpenMode -> OpenFileFlags -> IO (Either Errno fh))
+
+  , -- | Implements Unix98 @pread(2)@.
+    --
+    -- It differs from 'System.Posix.Files.fdRead' by the explicit 'FileOffset' argument.
+    fuseRead :: Maybe (FilePath -> fh -> ByteCount -> FileOffset -> IO (Either Errno B.ByteString))
+
+  , -- | Implements Unix98 @pwrite(2)@.
+    --
+    -- It differs from 'System.Posix.Files.fdWrite' by the explicit 'FileOffset' argument.
+    --
+    -- Unless @FUSE_CAP_HANDLE_KILLPRIV@ is disabled, this method is expected to reset the
+    -- setuid and setgid bits.
+    fuseWrite :: Maybe (FilePath -> fh -> B.ByteString -> FileOffset -> IO (Either Errno CInt))
+
+  , -- | Implements @statfs(2)@.
+    fuseStatfs :: Maybe (String -> IO (Either Errno FileSystemStats))
+
+  , -- | Called when @close(2)@ has been called on an open file.
+    --
+    -- Note: this does not mean that the file is released.  This function may be called more
+    -- than once for each @open(2)@.  The return value is passed on to the @close(2)@ system
+    -- call.
+    fuseFlush :: Maybe (FilePath -> fh -> IO Errno)
+
+  , -- | Called when an open file has all file descriptors closed and all memory mappings
+    -- unmapped.
+    --
+    -- For every @open@ call there will be exactly one @release@ call with the same flags.
+    -- It is possible to have a file opened more than once, in which case only the last
+    -- release will mean that no more reads or writes will happen on the file.
+    fuseRelease :: Maybe (FilePath -> fh -> IO ())
+
+  , -- | Implements @fsync(2)@.
+    fuseFsync :: Maybe (FilePath -> fh -> SyncType -> IO Errno)
+
+  , -- | Implements @setxattr(2)@.
+    --
+    -- The parameters are: path, name, value and flags.
+    fuseSetxattr :: Maybe (FilePath -> String -> B.ByteString -> SetxattrFlag -> IO Errno)
+
+  , -- | Implements @getxattr(2)@.
+    --
+    -- The parameters are path and name.
+    fuseGetxattr :: Maybe (FilePath -> String -> IO (Either Errno B.ByteString))
+
+  , -- | Implements @listxattr(2)@.
+    fuseListxattr :: Maybe (FilePath -> IO (Either Errno [String]))
+
+  , -- | Implements @removexattr(2)@.
+    fuseRemovexattr :: Maybe (FilePath -> String -> IO Errno)
+
+  , -- | Implements @opendir(3)@.
+    --
+    -- This method should check if the open operation is permitted for this directory.
+    fuseOpendir :: Maybe (FilePath -> IO (Either Errno dh))
+
+  , -- | Implements @readdir(3)@.
+    --
+    -- The entire contents of the directory should be returned as a list of tuples
+    -- (corresponding to the first mode of operation documented in @fuse.h@).
+    --
+    -- The returned list should contain entries of \".\" and \"..\".
+    --
+    -- Each element of the list is a pair of the name and the stat. The name should not
+    -- include the path to it. The implementation may return @Nothing@ as the stat; in this
+    -- case `fuseGetattr` is called instead.
+    fuseReaddir :: Maybe (FilePath -> dh -> IO (Either Errno [(String, Maybe FileStat)]))
+
+  , -- | Implements @closedir(3)@.
+    fuseReleasedir :: Maybe (FilePath -> dh -> IO Errno)
+
+  , -- | Synchronize the directory's contents; analogous to `fuseFsync`.
+    fuseFsyncdir :: Maybe (FilePath -> dh -> SyncType -> IO Errno)
+
+  , -- | Initializes the filesystem.  This is called before all other operations.
+    --
+    -- The filesystem may modify `FuseConfig` to configure the API.
+    fuseInit :: Maybe (FuseConfig -> IO FuseConfig)
+
+  , -- | Called on filesystem exit to allow cleanup.
+    fuseDestroy :: Maybe (IO ())
+
+  , -- | Implements 'System.Posix.Files.fileAccess' and 'System.Posix.Files.fileExist
+    -- (POSIX @access(2)@).
+    --
+    -- Checks file access permissions as requested by an `AccessMode`.
+    --
+    -- If the @default_permissions@ mount option is given, this method is not called. This
+    -- method is also not called under Linux kernel versions 2.4.x
+    --
+    -- TODO add notes about @default_permissions@ to other relevant handlers
+    fuseAccess :: Maybe (FilePath -> AccessMode -> IO Errno)
+
+  , -- | Implements 'System.Posix.Files.openFd' (POSIX @open(2)@). Creates and opens a regular
+    -- file.
+    --
+    -- If this is not implemented, `fuseMknod` and `fuseOpen` methods will be called instead.
+    --
+    -- See `fuseOpen` for notes on the flags.
+    fuseCreate :: Maybe (FilePath -> OpenMode -> FileMode -> OpenFileFlags -> IO (Either Errno fh))
+
+    -- TODO , fuseLock :: _
+
+  , -- | Implements @utimensat(2)@.
+    --
+    -- Changes the access and modification times of a file with nanosecond resolution.
+    --
+    -- @fh@ will always be @Nothing@ if the file is not currently open, but may also be
+    -- @Nothing@ even if it is open.
+    fuseUtimens :: Maybe (FilePath -> Maybe fh -> TimeSpec -> TimeSpec -> IO Errno)
+
+    -- TODO , fuseBmap :: _
+    -- TODO , fuseIoctl :: _
+    -- TODO , fusePoll :: _
+    -- TODO , fuseWriteBuf :: _
+    -- TODO , fuseReadBuf :: _
+    -- TODO , fuseFlock :: _
+
+  , -- | Implements 'System.Posix.Fcntl.fileAllocate' (@posix_fallocate(3)@). Allocates
+    -- space for an open file.
+    fuseFallocate :: Maybe (FilePath -> fh -> CInt -> FileOffset -> FileOffset -> IO Errno)
+
+  , -- | Implements @copy_file_range(2)@.
+    fuseCopyFileRange :: Maybe (FilePath -> fh -> FileOffset -> FilePath -> fh -> FileOffset -> ByteCount -> CInt -> IO (Either Errno CSsize))
+
+  , -- | Implements 'System.Posix.IO.fdSeek' @lseek(3)@.
+    --
+    -- /Note:/ This is silently ignored if libfuse doesn't support @lseek@ operation (requires libfuse-3.8.0).
+    fuseLseek :: Maybe (FilePath -> fh -> FileOffset -> SeekMode -> IO (Either Errno FileOffset))
+  }
+
+-- | An empty set of operations whose fields are @Nothing@.
+defaultFuseOperations :: FuseOperations fh dh
+defaultFuseOperations = FuseOperations Nothing Nothing Nothing Nothing Nothing Nothing Nothing Nothing Nothing Nothing Nothing Nothing Nothing Nothing Nothing Nothing Nothing Nothing Nothing Nothing Nothing Nothing Nothing Nothing Nothing Nothing Nothing Nothing Nothing Nothing Nothing Nothing Nothing Nothing Nothing
+
+-- | Merges two `FuseOperations` in a left-biased manner.
+mergeLFuseOperations :: FuseOperations fh dh -> FuseOperations fh dh -> FuseOperations fh dh
+mergeLFuseOperations
+  (FuseOperations a1 a2 a3 a4 a5 a6 a7 a8 a9 a10 a11 a12 a13 a14 a15 a16 a17 a18 a19 a20 a21 a22 a23 a24 a25 a26 a27 a28 a29 a30 a31 a32 a33 a34 a35)
+  (FuseOperations b1 b2 b3 b4 b5 b6 b7 b8 b9 b10 b11 b12 b13 b14 b15 b16 b17 b18 b19 b20 b21 b22 b23 b24 b25 b26 b27 b28 b29 b30 b31 b32 b33 b34 b35)
+  = FuseOperations (a1 <|> b1) (a2 <|> b2) (a3 <|> b3) (a4 <|> b4) (a5 <|> b5) (a6 <|> b6) (a7 <|> b7) (a8 <|> b8) (a9 <|> b9) (a10 <|> b10) (a11 <|> b11) (a12 <|> b12) (a13 <|> b13) (a14 <|> b14) (a15 <|> b15) (a16 <|> b16) (a17 <|> b17) (a18 <|> b18) (a19 <|> b19) (a20 <|> b20) (a21 <|> b21) (a22 <|> b22) (a23 <|> b23) (a24 <|> b24) (a25 <|> b25) (a26 <|> b26) (a27 <|> b27) (a28 <|> b28) (a29 <|> b29) (a30 <|> b30) (a31 <|> b31) (a32 <|> b32) (a33 <|> b33) (a34 <|> b34) (a35 <|> b35)
+
+-- | Allocates a @fuse_operations@ struct and pokes `FuseOperations` into it.
+--
+-- Each field of `FuseOperations` is converted into a C function pointer and is assigned
+-- to a corresponding field of @struct fuse_operations@.
+--
+-- The created `C.FuseOperations` has the following invariants:
+--
+--   - The content of @fuse_operations.fh@ is a Haskell value of type @StablePtr fh@ or
+--     @StablePtr dh@, depending on operations. It is created with `newFH`, accessed with
+--     `getFH` and released with `delFH`.
+--
+--   - Every methods handle Haskell exception with the supplied error handler.
+--
+--   - NULL filepaths (passed from libfuse if `FuseConfig.nullpathOk` is set) are
+--     translated to empty strings.
+resCFuseOperations
+  :: forall fh dh e
+   . Exception e
+  => FuseOperations fh dh           -- ^ A set of file system operations.
+  -> (e -> IO Errno)                -- ^ An error handler that converts a Haskell exception to @errno@.
+  -> ResourceT IO (Ptr C.FuseOperations)
+resCFuseOperations ops handler = do
+  fuseGetattr       <- resC C.mkGetattr       wrapGetattr       (fuseGetattr ops)
+  fuseReadlink      <- resC C.mkReadlink      wrapReadlink      (fuseReadlink ops)
+  fuseMknod         <- resC C.mkMknod         wrapMknod         (fuseMknod ops)
+  fuseMkdir         <- resC C.mkMkdir         wrapMkdir         (fuseMkdir ops)
+  fuseUnlink        <- resC C.mkUnlink        wrapUnlink        (fuseUnlink ops)
+  fuseRmdir         <- resC C.mkRmdir         wrapRmdir         (fuseRmdir ops)
+  fuseSymlink       <- resC C.mkSymlink       wrapSymlink       (fuseSymlink ops)
+  fuseRename        <- resC C.mkRename        wrapRename        (fuseRename ops)
+  fuseLink          <- resC C.mkLink          wrapLink          (fuseLink ops)
+  fuseChmod         <- resC C.mkChmod         wrapChmod         (fuseChmod ops)
+  fuseChown         <- resC C.mkChown         wrapChown         (fuseChown ops)
+  fuseTruncate      <- resC C.mkTruncate      wrapTruncate      (fuseTruncate ops)
+  fuseOpen          <- resC C.mkOpen          wrapOpen          (fuseOpen ops)
+  fuseRead          <- resC C.mkRead          wrapRead          (fuseRead ops)
+  fuseWrite         <- resC C.mkWrite         wrapWrite         (fuseWrite ops)
+  fuseStatfs        <- resC C.mkStatfs        wrapStatfs        (fuseStatfs ops)
+  fuseFlush         <- resC C.mkFlush         wrapFlush         (fuseFlush ops)
+  fuseRelease       <- resC C.mkRelease       wrapRelease       (fuseRelease ops)
+  fuseFsync         <- resC C.mkFsync         wrapFsync         (fuseFsync ops)
+  fuseSetxattr      <- resC C.mkSetxattr      wrapSetxattr      (fuseSetxattr ops)
+  fuseGetxattr      <- resC C.mkGetxattr      wrapGetxattr      (fuseGetxattr ops)
+  fuseListxattr     <- resC C.mkListxattr     wrapListxattr     (fuseListxattr ops)
+  fuseRemovexattr   <- resC C.mkRemovexattr   wrapRemovexattr   (fuseRemovexattr ops)
+  fuseOpendir       <- resC C.mkOpendir       wrapOpendir       (fuseOpendir ops)
+  fuseReaddir       <- resC C.mkReaddir       wrapReaddir       (fuseReaddir ops)
+  fuseReleasedir    <- resC C.mkReleasedir    wrapReleasedir    (fuseReleasedir ops)
+  fuseFsyncdir      <- resC C.mkFsyncdir      wrapFsyncdir      (fuseFsyncdir ops)
+  fuseInit          <- resC C.mkInit          wrapInit          (fuseInit ops)
+  fuseDestroy       <- resC C.mkDestroy       wrapDestroy       (fuseDestroy ops)
+  fuseAccess        <- resC C.mkAccess        wrapAccess        (fuseAccess ops)
+  fuseCreate        <- resC C.mkCreate        wrapCreate        (fuseCreate ops)
+  fuseUtimens       <- resC C.mkUtimens       wrapUtimens       (fuseUtimens ops)
+  fuseFallocate     <- resC C.mkFallocate     wrapFallocate     (fuseFallocate ops)
+  fuseCopyFileRange <- resC C.mkCopyFileRange wrapCopyFileRange (fuseCopyFileRange ops)
+  fuseLseek         <- resC C.mkLseek         wrapLseek         (fuseLseek ops)
+  fmap snd $ resNew C.FuseOperations
+    -- not (yet) implemented methods
+    { fuseLock = nullFunPtr
+    , fuseBmap = nullFunPtr
+    , fuseIoctl = nullFunPtr
+    , fusePoll = nullFunPtr
+    , fuseWriteBuf = nullFunPtr
+    , fuseReadBuf = nullFunPtr
+    , fuseFlock = nullFunPtr
+    , ..
+    }
+  where
+  -- convert a Haskell function to C one with @wrapMeth@, get its @FunPtr@, and associate it with freeHaskellFunPtr
+  resC :: (cfunc -> IO (FunPtr cfunc)) -> (hsfunc -> cfunc) -> Maybe hsfunc -> ResourceT IO (FunPtr cfunc)
+  resC _ _ Nothing = pure nullFunPtr
+  resC mkMeth wrapMeth (Just hsfunc) = fmap snd $ Res.allocate (mkMeth $ wrapMeth hsfunc) freeHaskellFunPtr
+
+  -- return negated errno as specified by fuse.h. also handle any Haskell exceptions
+  handleAsFuseError :: IO Errno -> IO CInt
+  handleAsFuseError = handleAsFuseErrorResult . fmap Left -- assumes eOK == 0
+
+  -- return a (successful) result as positive int and a negated errno as negative int
+  handleAsFuseErrorResult :: IO (Either Errno CInt) -> IO CInt
+  handleAsFuseErrorResult = handleAsFuseErrorIntegral
+
+  handleAsFuseErrorCSsize :: IO (Either Errno CSsize) -> IO CSsize
+  handleAsFuseErrorCSsize = handleAsFuseErrorIntegral
+
+  handleAsFuseErrorCOff :: IO (Either Errno COff) -> IO COff
+  handleAsFuseErrorCOff = handleAsFuseErrorIntegral
+
+  handleAsFuseErrorIntegral :: Integral a => IO (Either Errno a) -> IO a
+  handleAsFuseErrorIntegral = fmap (either (fromIntegral . negate . unErrno) id) . handle (fmap Left . handler)
+
+  peekFilePathOrEmpty :: CString -> IO FilePath
+  peekFilePathOrEmpty pFilePath
+    | pFilePath == nullPtr = pure ""
+    | otherwise            = peekFilePath pFilePath
+
+  peekOpenFileFlagsAndMode :: Ptr C.FuseFileInfo -> IO (OpenFileFlags, OpenMode)
+  peekOpenFileFlagsAndMode pFuseFileInfo = do
+    (flags :: CInt) <- (#peek struct fuse_file_info, flags) pFuseFileInfo
+    let openFileFlags = OpenFileFlags
+          { append   = testBitSet flags (#const O_APPEND)
+          , nonBlock = testBitSet flags (#const O_NONBLOCK)
+          , trunc    = testBitSet flags (#const O_TRUNC)
+          , exclusive = False
+          , noctty    = False
+          }
+        openMode
+          | testBitSet flags (#const O_RDWR)   = ReadWrite
+          | testBitSet flags (#const O_WRONLY) = WriteOnly
+          | otherwise = ReadOnly -- O_RDONLY
+    pure (openFileFlags, openMode)
+
+  wrapGetattr :: (FilePath -> Maybe fh -> IO (Either Errno FileStat)) -> C.CGetattr
+  wrapGetattr go pFilePath pStat pFuseFileInfo = handleAsFuseError $ do
+    filePath <- peekFilePathOrEmpty pFilePath
+    mfh <- getFH pFuseFileInfo
+    go filePath mfh >>= \case
+      Left errno -> pure errno
+      Right stat -> do
+        poke pStat stat
+        pure eOK
+
+  wrapReadlink :: (FilePath -> IO (Either Errno FilePath)) -> C.CReadlink
+  wrapReadlink go pFilePath pBuf bufSize = handleAsFuseError $ do
+    filePath <- peekFilePath pFilePath
+    go filePath >>= \case
+      Left errno -> pure errno
+      Right target -> do
+        -- This will truncate target if it's longer than the buffer can hold,
+        -- as specified by fuse.h
+        pokeCStringLen0 (pBuf, (fromIntegral bufSize)) target
+        pure eOK
+
+  wrapMknod :: (FilePath -> FileMode -> DeviceID -> IO Errno) -> C.CMknod
+  wrapMknod go pFilePath mode dev = handleAsFuseError $ do
+    filePath <- peekFilePath pFilePath
+    go filePath mode dev
+
+  wrapMkdir :: (FilePath -> FileMode -> IO Errno) -> C.CMkdir
+  wrapMkdir go pFilePath mode = handleAsFuseError $ do
+    filePath <- peekFilePath pFilePath
+    go filePath mode
+
+  wrapUnlink :: (FilePath -> IO Errno) -> C.CUnlink
+  wrapUnlink go pFilePath = handleAsFuseError $ do
+    filePath <- peekFilePath pFilePath
+    go filePath
+
+  wrapRmdir :: (FilePath -> IO Errno) -> C.CRmdir
+  wrapRmdir go pFilePath = handleAsFuseError $ do
+    filePath <- peekFilePath pFilePath
+    go filePath
+
+  wrapSymlink :: (FilePath -> FilePath -> IO Errno) -> C.CSymlink
+  wrapSymlink go pSource pDestination = handleAsFuseError $ do
+    source <- peekFilePath pSource
+    destination <- peekFilePath pDestination
+    go source destination
+
+  wrapRename :: (FilePath -> FilePath -> IO Errno) -> C.CRename
+  wrapRename go pOld pNew _flags = handleAsFuseError $ do
+    -- we ignore the rename flags because #define _GNU_SOURCE is needed to use the constants
+    -- TODO return EINVAL if flags are specified?
+    old <- peekFilePath pOld
+    new <- peekFilePath pNew
+    go old new
+
+  wrapLink :: (FilePath -> FilePath -> IO Errno) -> C.CLink
+  wrapLink go pSource pDestination = handleAsFuseError $ do
+    source <- peekFilePath pSource
+    destination <- peekFilePath pDestination
+    go source destination
+
+  wrapChmod :: (FilePath -> Maybe fh -> FileMode -> IO Errno) -> C.CChmod
+  wrapChmod go pFilePath mode pFuseFileInfo = handleAsFuseError $ do
+    filePath <- peekFilePathOrEmpty pFilePath
+    mfh <- getFH pFuseFileInfo
+    go filePath mfh mode
+
+  wrapChown :: (FilePath -> Maybe fh -> UserID -> GroupID -> IO Errno) -> C.CChown
+  wrapChown go pFilePath uid gid pFuseFileInfo = handleAsFuseError $ do
+    filePath <- peekFilePathOrEmpty pFilePath
+    mfh <- getFH pFuseFileInfo
+    go filePath mfh uid gid
+
+  wrapTruncate :: (FilePath -> Maybe fh -> FileOffset -> IO Errno) -> C.CTruncate
+  wrapTruncate go pFilePath off pFuseFileInfo = handleAsFuseError $ do
+    filePath <- peekFilePathOrEmpty pFilePath
+    mfh <- getFH pFuseFileInfo
+    go filePath mfh off
+
+  wrapOpen :: (FilePath -> OpenMode -> OpenFileFlags -> IO (Either Errno fh)) -> C.COpen
+  wrapOpen go pFilePath pFuseFileInfo = handleAsFuseError $ do
+    filePath <- peekFilePath pFilePath
+    (openFileFlags, openMode) <- peekOpenFileFlagsAndMode pFuseFileInfo
+    go filePath openMode openFileFlags >>= \case
+      Left errno -> pure errno
+      Right fh -> do
+        newFH pFuseFileInfo fh
+        pure eOK
+
+  wrapRead :: (FilePath -> fh -> ByteCount -> FileOffset -> IO (Either Errno B.ByteString)) -> C.CRead
+  wrapRead go pFilePath pBuf bufSize off pFuseFileInfo = handleAsFuseErrorResult $ do
+    filePath <- peekFilePathOrEmpty pFilePath
+    fh <- getFHJust pFuseFileInfo
+    go filePath fh bufSize off >>= \case
+      Left errno -> pure $ Left errno
+      Right bytes -> BU.unsafeUseAsCStringLen bytes $ \(pBytes, bytesLen) -> do
+        let len = bytesLen `min` fromIntegral bufSize
+        copyArray pBuf pBytes len
+        pure $ Right $ fromIntegral len
+
+  wrapWrite :: (FilePath -> fh -> B.ByteString -> FileOffset -> IO (Either Errno CInt)) -> C.CWrite
+  wrapWrite go pFilePath pBuf bufSize off pFuseFileInfo = handleAsFuseErrorResult $ do
+    filePath <- peekFilePathOrEmpty pFilePath
+    fh <- getFHJust pFuseFileInfo
+    buf <- BU.unsafePackCStringLen (pBuf, fromIntegral bufSize)
+    go filePath fh buf off
+
+  wrapStatfs :: (String -> IO (Either Errno FileSystemStats)) -> C.CStatfs
+  wrapStatfs go pStr pStatVFS = handleAsFuseError $ do
+    str <- peekFilePath pStr
+    go str >>= \case
+      Left errno -> pure errno
+      Right statvfs -> do
+        poke pStatVFS statvfs
+        pure eOK
+
+  wrapFlush :: (FilePath -> fh -> IO Errno) -> C.CFlush
+  wrapFlush go pFilePath pFuseFileInfo = handleAsFuseError $ do
+    filePath <- peekFilePathOrEmpty pFilePath
+    fh <- getFHJust pFuseFileInfo
+    go filePath fh
+
+  wrapRelease :: (FilePath -> fh -> IO ()) -> C.CRelease
+  wrapRelease go pFilePath pFuseFileInfo = go' `finally` delFH pFuseFileInfo
+    where
+    go' = handleAsFuseError $ do
+      filePath <- peekFilePathOrEmpty pFilePath
+      fh <- getFHJust pFuseFileInfo
+      go filePath fh
+      pure eOK
+
+  wrapFsync :: (FilePath -> fh -> SyncType -> IO Errno) -> C.CFsync
+  wrapFsync go pFilePath isDataSync pFuseFileInfo = handleAsFuseError $ do
+    filePath <- peekFilePathOrEmpty pFilePath
+    fh <- getFHJust pFuseFileInfo
+    go filePath fh (if isDataSync /= 0 then DataSync else FullSync)
+
+  wrapSetxattr :: (FilePath -> String -> B.ByteString -> SetxattrFlag -> IO Errno) -> C.CSetxattr
+  wrapSetxattr go pFilePath pName pValue valueSize cFlags = handleAsFuseError $ do
+    filePath <- peekFilePath pFilePath
+    name <- peekCString pName
+    value <- BU.unsafePackCStringLen (pValue, fromIntegral valueSize)
+    let eflag = case cFlags of
+          0 -> Right SetxattrDefault
+          (#const XATTR_CREATE) -> Right SetxattrCreate
+          (#const XATTR_REPLACE) -> Right SetxattrReplace
+          _ -> Left eINVAL
+    either pure (go filePath name value) eflag
+
+  wrapGetxattr :: (FilePath -> String -> IO (Either Errno B.ByteString)) -> C.CGetxattr
+  wrapGetxattr go pFilePath pName pValueBuf bufSize = handleAsFuseErrorResult $ do
+    filePath <- peekFilePath pFilePath
+    name <- peekCString pName
+    go filePath name >>= \case
+      Left errno -> pure $ Left errno
+      Right bytes
+        | bufSize == 0 -> pure $ Right $ fromIntegral $ B.length bytes
+        | otherwise -> BU.unsafeUseAsCStringLen bytes $ \(pBytes, bytesLen) -> do
+            let len = bytesLen `min` fromIntegral bufSize
+            copyArray pValueBuf pBytes len
+            pure $ Right $ fromIntegral len
+
+  wrapListxattr :: (FilePath -> IO (Either Errno [String])) -> C.CListxattr
+  wrapListxattr go pFilePath pBuf bufSize = handleAsFuseErrorResult $ do
+    filePath <- peekFilePath pFilePath
+    go filePath >>= \case
+      Left errno -> pure $ Left errno
+      Right names -> withCStringLen (concatMap (<> "\0") names) $ \(pNames, namesLen) ->
+        if bufSize == 0
+          then pure $ Right $ fromIntegral namesLen
+          else do
+            let len = namesLen `min` fromIntegral bufSize
+            copyArray pBuf pNames len
+            pure $ Right $ fromIntegral len
+
+  wrapRemovexattr :: (FilePath -> String -> IO Errno) -> C.CRemovexattr
+  wrapRemovexattr go pFilePath pName = handleAsFuseError $ do
+    filePath <- peekFilePath pFilePath
+    name <- peekCString pName
+    go filePath name
+
+  wrapOpendir :: (FilePath -> IO (Either Errno dh)) -> C.COpendir
+  wrapOpendir go pFilePath pFuseFileInfo = handleAsFuseError $ do
+    filePath <- peekFilePath pFilePath
+    go filePath >>= \case
+      Left errno -> pure errno
+      Right dh -> do
+        newFH pFuseFileInfo dh
+        pure eOK
+
+  wrapReaddir :: (FilePath -> dh -> IO (Either Errno [(String, Maybe FileStat)])) -> C.CReaddir
+  wrapReaddir go pFilePath pBuf pFillDir _off pFuseFileInfo _readdirFlags = handleAsFuseError $ do
+    filePath <- peekFilePathOrEmpty pFilePath
+    dh <- getFHJust pFuseFileInfo
+    let fillDir = peekFuseFillDir pFillDir
+        fillEntry :: (FilePath, Maybe FileStat) -> IO ()
+        fillEntry (fileName, fileStat) =
+          withFilePath fileName $ \pFileName ->
+          maybeWith with fileStat $ \pFileStat -> do
+            _ <- fillDir pBuf pFileName pFileStat 0 0
+            pure ()
+    go filePath dh >>= \case
+      Left errno -> pure errno
+      Right entries -> do
+        traverse_ fillEntry entries
+        pure eOK
+
+  wrapReleasedir :: (FilePath -> dh -> IO Errno) -> C.CReleasedir
+  wrapReleasedir go pFilePath pFuseFileInfo = go' `finally` delFH pFuseFileInfo
+    where
+    go' = handleAsFuseError $ do
+      filePath <- peekFilePathOrEmpty pFilePath
+      dh <- getFHJust pFuseFileInfo
+      go filePath dh
+
+  wrapFsyncdir :: (FilePath -> dh -> SyncType -> IO Errno) -> C.CFsyncdir
+  wrapFsyncdir go pFilePath isDataSync pFuseFileInfo = handleAsFuseError $ do
+    filePath <- peekFilePathOrEmpty pFilePath
+    dh <- getFHJust pFuseFileInfo
+    go filePath dh (if isDataSync /= 0 then DataSync else FullSync)
+
+  wrapInit :: (FuseConfig -> IO FuseConfig) -> C.CInit
+  -- TODO implement read/write of fuseConnInfo; watch out for read-only fields
+  wrapInit go _fuseConnInfo pFuseConfig = do
+    _ <- handle (void . handler) $ do
+      -- @pFuseConfig@ is filled beforehand by fuse_opt_parse in libfuse so we pass it
+      -- as-is to the callback as the default value.
+      fuseConfigOld <- fromCFuseConfig <$> peek pFuseConfig
+      fuseConfigNew <- go fuseConfigOld
+      -- The return value of the callback is poked back to @pFuseConfig@. Note that, by
+      -- doing this the fields of @fuse_config@ which we do /not/ implement are left
+      -- unchanged. This is the intended behavior.
+      poke pFuseConfig $ toCFuseConfig fuseConfigNew
+    pure nullPtr
+
+  wrapDestroy :: IO () -> C.CDestroy
+  wrapDestroy go _privateData = handle (void . handler) go
+
+  wrapAccess :: (FilePath -> AccessMode -> IO Errno) -> C.CAccess
+  wrapAccess go pFilePath mode = handleAsFuseError $ do
+    filePath <- peekFilePath pFilePath
+    go filePath accessMode
+    where
+    accessMode
+      | testBitSet mode (#const F_OK) = FileOK
+      | otherwise = PermOK
+          (testBitSet mode (#const R_OK))
+          (testBitSet mode (#const W_OK))
+          (testBitSet mode (#const X_OK))
+
+  wrapCreate :: (FilePath -> OpenMode -> FileMode -> OpenFileFlags -> IO (Either Errno fh)) -> C.CCreate
+  wrapCreate go pFilePath mode pFuseFileInfo = handleAsFuseError $ do
+    filePath <- peekFilePath pFilePath
+    (openFileFlags, openMode) <- peekOpenFileFlagsAndMode pFuseFileInfo
+    go filePath openMode mode openFileFlags >>= \case
+      Left errno -> pure errno
+      Right fh -> do
+        newFH pFuseFileInfo fh
+        pure eOK
+
+  wrapUtimens :: (FilePath -> Maybe fh -> TimeSpec -> TimeSpec -> IO Errno) -> C.CUtimens
+  wrapUtimens go pFilePath arrTs pFuseFileInfo = handleAsFuseError $ do
+    filePath <- peekFilePathOrEmpty pFilePath
+    mfh <- getFH pFuseFileInfo
+    [atime, mtime] <- peekArray 2 arrTs
+    go filePath mfh atime mtime
+
+  wrapFallocate :: (FilePath -> fh -> CInt -> FileOffset -> FileOffset -> IO Errno) -> C.CFallocate
+  wrapFallocate go pFilePath mode offset len pFuseFileInfo = handleAsFuseError $ do
+    filePath <- peekFilePath pFilePath
+    fh <- getFHJust pFuseFileInfo
+    go filePath fh mode offset len
+
+  wrapCopyFileRange :: (FilePath -> fh -> FileOffset -> FilePath -> fh -> FileOffset -> ByteCount -> CInt -> IO (Either Errno CSsize)) -> C.CCopyFileRange
+  wrapCopyFileRange go pFilePathIn pFuseFileInfoIn offsetIn pFilePathOut pFuseFileInfoOut offsetOut size flags = handleAsFuseErrorCSsize $ do
+    filePathIn <- peekFilePath pFilePathIn
+    fhIn <- getFHJust pFuseFileInfoIn
+    filePathOut <- peekFilePath pFilePathOut
+    fhOut <- getFHJust pFuseFileInfoOut
+    go filePathIn fhIn offsetIn filePathOut fhOut offsetOut size flags
+
+  wrapLseek :: (FilePath -> fh -> FileOffset -> SeekMode -> IO (Either Errno FileOffset)) -> C.CLseek
+  wrapLseek go pFilePath offset whence pFuseFileInfo = handleAsFuseErrorCOff $ do
+    filePath <- peekFilePath pFilePath
+    fh <- getFHJust pFuseFileInfo
+    let emode = case whence of
+          (#const SEEK_SET) -> Right AbsoluteSeek
+          (#const SEEK_CUR) -> Right RelativeSeek
+          (#const SEEK_END) -> Right SeekFromEnd
+          _ -> Left eINVAL
+    either (pure . Left) (go filePath fh offset) emode
+
+-- | Allocates a @fuse_args@ struct to hold commandline arguments.
+resFuseArgs :: String -> [String] -> ResourceT IO (Ptr C.FuseArgs)
+resFuseArgs prog args = do
+  let allArgs = (prog:args)
+      argc = length allArgs
+  cArgs <- traverse (fmap snd . resNewCString) allArgs
+  pArgv <- fmap snd $ resNewArray cArgs
+  -- call FUSE_ARGS_INIT instead?
+  fuseArgs <- fmap snd $ resMallocBytes (#size struct fuse_args)
+  liftIO $ do
+    (#poke struct fuse_args, argc) fuseArgs argc
+    (#poke struct fuse_args, argv) fuseArgs pArgv
+    (#poke struct fuse_args, allocated) fuseArgs (0::CInt)
+  _ <- Res.register $ C.fuse_opt_free_args fuseArgs
+  pure fuseArgs
+
+-- | Calls @fuse_parse_cmdline@ to parse the part of the commandline arguments that
+-- we care about.
+--
+-- @fuse_parse_cmdline@ will modify the `C.FuseArgs` struct passed in to remove those
+-- arguments; the `C.FuseArgs` struct containing remaining arguments must be passed to
+-- @fuse_mount@/@fuse_new@.
+--
+-- The multithreaded runtime will be used regardless of the threading flag!
+-- See the comment in @fuse_session_exit@ for why.
+fuseParseCommandLine :: Ptr C.FuseArgs -> IO (Either ExitCode FuseMainArgs)
+fuseParseCommandLine pArgs =
+  allocaBytes (#size struct fuse_cmdline_opts) $ \pOpts -> do
+    retval <- C.fuse_parse_cmdline pArgs pOpts
+    if retval /= 0
+      -- fuse_parse_cmdline prints an error message
+      then pure $ Left $ ExitFailure 1
+      else go pOpts
+  where
+  go pOpts = do
+    pMountPoint <- (#peek struct fuse_cmdline_opts, mountpoint) pOpts
+    showHelp    <- (/= (0 :: CInt)) <$> (#peek struct fuse_cmdline_opts, show_help) pOpts
+    showVersion <- (/= (0 :: CInt)) <$> (#peek struct fuse_cmdline_opts, show_version) pOpts
+    -- free fuse_cmdline_opts.mountpoint because it is allocated with realloc (see libfuse's examples)
+    let freeMountPoint = free pMountPoint
+    flip finally freeMountPoint $ case () of
+      _ | showHelp -> do
+            printf "usage: %s [options] <mountpoint>\n\n" =<< getProgName
+            C.fuse_cmdline_help
+            C.fuse_lib_help pArgs
+            pure $ Left ExitSuccess
+        | showVersion -> do
+            ver <- peekCString =<< C.fuse_pkgversion
+            printf "FUSE library version %s\n" ver
+            C.fuse_lowlevel_version
+            pure $ Left ExitSuccess
+        | pMountPoint == nullPtr -> do
+            progName <- getProgName
+            hPrintf stderr "usage: %s [options] <mountpoint>\n" progName
+            hPrintf stderr "       %s --help\n" progName
+            pure $ Left $ ExitFailure 1
+        | otherwise -> do
+            mountPoint <- peekFilePath pMountPoint
+            foreground <- (/= (0 :: CInt)) <$> (#peek struct fuse_cmdline_opts, foreground) pOpts
+            cloneFd <- (#peek struct fuse_cmdline_opts, clone_fd) pOpts
+            pure $ Right (foreground, mountPoint, cloneFd)
+
+-- | Parses the commandline arguments and exit if the args are bad or certain informational
+-- flag(s) are specified. See `fuseParseCommandLine`.
+fuseParseCommandLineOrExit :: Ptr C.FuseArgs -> IO FuseMainArgs
+fuseParseCommandLineOrExit pArgs = either exitWith pure =<< fuseParseCommandLine pArgs
+
+-- | Haskell version of @fuse_daemonize@.
+--
+-- During the fork, transfers all of the resources in `ResourceT` (and its cleanup actions)
+-- to the forked process.
+--
+-- Mimics @daemon()@'s use of @_exit()@ instead of @exit()@; we depend on this in
+-- `fuseMainReal`, because otherwise we'll unmount the filesystem when the foreground
+-- process exits.
+fuseDaemonize :: ResourceT IO a -> ResourceT IO b
+fuseDaemonize job = daemonizeResourceT $ do
+  liftIO $ do
+    _ <- createSession
+    changeWorkingDirectory "/"
+    -- need to open @/dev/null@ twice because `hDuplicateTo` can't dup a
+    -- ReadWriteMode to a ReadMode handle
+    withFile "/dev/null" WriteMode $ \devNullOut -> do
+      hDuplicateTo devNullOut stdout
+      hDuplicateTo devNullOut stderr
+    withFile "/dev/null" ReadMode $ \devNullIn -> do
+      hDuplicateTo devNullIn stdin
+  _ <- job
+  liftIO $ exitSuccess
+
+-- | @withSignalHandlers handler io@ installs signal handlers while @io@ is executed.
+withSignalHandlers :: IO () -> IO a -> IO a
+withSignalHandlers exitHandler = bracket_ setHandlers resetHandlers
+  where
+  setHandlers = do
+    let sigHandler = Signals.CatchOnce exitHandler
+    void $ Signals.installHandler Signals.sigINT  sigHandler Nothing
+    void $ Signals.installHandler Signals.sigHUP  sigHandler Nothing
+    void $ Signals.installHandler Signals.sigTERM sigHandler Nothing
+    void $ Signals.installHandler Signals.sigPIPE Signals.Ignore Nothing
+  resetHandlers = do
+    void $ Signals.installHandler Signals.sigINT  Signals.Default Nothing
+    void $ Signals.installHandler Signals.sigHUP  Signals.Default Nothing
+    void $ Signals.installHandler Signals.sigTERM Signals.Default Nothing
+    void $ Signals.installHandler Signals.sigPIPE Signals.Default Nothing
+
+-- | The parts of @fuse_parse_cmdline@ we are interested in. Passed to `fuseMainReal`.
+--
+-- @(foreground, mountpoint, clone_fd)@
+--
+-- So far, we don't interpret the value of @clone_fd@ at all so its type is `CInt`.
+type FuseMainArgs = (Bool, String, CInt)
+
+-- | Mounts the filesystem, forks (if requested), and then starts fuse.
+fuseMainReal
+  :: Ptr C.StructFuse
+  -> FuseMainArgs
+  -> ResourceT IO a
+fuseMainReal = \pFuse (foreground, mountPt, cloneFd) -> do
+  let run = if foreground
+        then \io -> liftIO $ changeWorkingDirectory "/" >> io
+        else fuseDaemonize . liftIO
+  cMountPt <- fmap snd $ resNewFilePath mountPt
+  mountResult <- snd <$> Res.allocate (C.fuse_mount pFuse cMountPt) (\_ -> C.fuse_unmount pFuse)
+  if mountResult == 0
+    then run $ procMain pFuse cloneFd
+    else liftIO $ fail "fuse_mount failed"
+  where
+  -- here, we're finally inside the daemon process, we can run the main loop
+  procMain pFuse cloneFd = do
+    session <- C.fuse_get_session pFuse
+    -- TODO calling fuse_session_exit doesn't stop fuse_loop_mt_31!
+    -- @fusermount -u@ successfully kills the process but SIGINT doesn't
+    -- TODO try non-multithreaded loop
+    withSignalHandlers (C.fuse_session_exit session) $ do
+      retVal <- C.fuse_loop_mt_31 pFuse cloneFd
+      if retVal == 0
+        then exitSuccess
+        else exitFailure
+
+-- | Parses the commandline arguments and runs fuse.
+fuseRun :: Exception e => String -> [String] -> FuseOperations fh dh -> (e -> IO Errno) -> IO a
+fuseRun prog args ops handler = runResourceT $ do
+  pArgs <- resFuseArgs prog args
+  mainArgs <- liftIO $ fuseParseCommandLineOrExit pArgs
+  pOp <- resCFuseOperations ops handler
+  pFuse <- fmap snd $ Res.allocate
+    (C.fuse_new pArgs pOp (#size struct fuse_operations) nullPtr)
+    (\p -> unless (p == nullPtr) $ C.fuse_destroy p)
+  if pFuse == nullPtr
+    then liftIO exitFailure -- fuse_new prints an error message
+    else fuseMainReal pFuse mainArgs
+
+-- | Main function of FUSE.
+--
+-- This is all that has to be called from the @main@ function. On top of
+-- the `FuseOperations` record with filesystem implementation, you must give
+-- an exception handler converting Haskell exceptions to `Errno`.
+--
+-- This function does the following:
+--
+--   * parses command line options
+--
+--   * passes all options after @--@ to the fusermount program
+--
+--   * mounts the filesystem by calling @fusermount@
+--
+--   * installs signal handlers
+--
+--   * registers an exit handler to unmount the filesystem on program exit
+--
+--   * registers the operations
+--
+--   * calls FUSE event loop
+fuseMain :: Exception e => FuseOperations fh dh -> (e -> IO Errno) -> IO ()
+fuseMain ops handler = do
+  -- this used to be implemented using libfuse's fuse_main. Doing this will fork()
+  -- from C behind the GHC runtime's back, which deadlocks in GHC 6.8.
+  -- Instead, we reimplement fuse_main in Haskell using the forkProcess and the
+  -- lower-level fuse_new/fuse_loop_mt API.
+  prog <- getProgName
+  args <- getArgs
+  fuseRun prog args ops handler
+
+-- | Gets a file handle from `C.FuseFileInfo` which is embedded with `newFH`.
+--
+-- If either the @Ptr `C.FuseFileInfo`@ itself or its @fh@ field is NULL, returns @Nothing@.
+getFH :: Ptr C.FuseFileInfo -> IO (Maybe fh)
+getFH pFuseFileInfo
+  | pFuseFileInfo == nullPtr = pure Nothing
+  | otherwise = do
+    sptr <- (#peek struct fuse_file_info, fh) pFuseFileInfo
+    -- Note that this implementation relies on the fact that @fuse_file_info.fh@ is
+    -- @NULL@-initialized before @fuse_operations.open@ and @.opendir@, and remains @NULL@
+    -- if they are unimplemented. It's a hack but we check this because because if we
+    -- didn't, we'll hit undefined behavior.
+    if sptr == nullPtr
+      then pure Nothing
+      else fmap Just $ deRefStablePtr $ castPtrToStablePtr sptr
+
+-- | Gets a file handle from `C.FuseFileInfo`.
+--
+-- @
+-- getFHJust = fmap fromJust . `getFH`
+-- @
+--
+-- This means you must make sure that `getFH` returns @Just@ or you'll get a Haskell
+-- exception. /However/, it's deliberately made lazy so that calling `getFHJust` itself
+-- won't throw but trying to use the returned value will.
+--
+-- This function is implemented this way in order to take care of rare(?) cases in which
+-- `fuseRead`\/`fuseReaddir` is implemented but not `fuseOpen`\/`fuseOpendir` resp. In
+-- such a case, `newFH` would not be called but only `getFH` would be. Without some
+-- protection, we would be dereferencing a non-initialized `StablePtr`, which is
+-- /undefined behavior/. Throwing a Haskell exception in a pure code is much better than
+-- UB. See the comment in the source of `getFH` if you are interested in more explanation.
+getFHJust :: Ptr C.FuseFileInfo -> IO fh
+getFHJust = fmap fromJust . getFH
+
+-- | Embeds a file handle into `C.FuseFileInfo`. It should be freed with `delFH` when no
+-- longer required.
+newFH :: Ptr C.FuseFileInfo -> fh -> IO ()
+newFH pFuseFileInfo fh = do
+  sptr <- newStablePtr fh
+  (#poke struct fuse_file_info, fh) pFuseFileInfo $ castStablePtrToPtr sptr
+
+-- | Frees a file handle in `C.FuseFileInfo` which is embedded with `newFH`.
+delFH :: Ptr C.FuseFileInfo -> IO ()
+delFH pFuseFileInfo = do
+  sptr <- (#peek struct fuse_file_info, fh) pFuseFileInfo
+  -- if sptr is NULL, it should mean newFH have not called. See getFH and getFHJust for
+  -- more info
+  unless (sptr == nullPtr) $
+    freeStablePtr $ castPtrToStablePtr sptr
+
+-- | Materializes the callback of @readdir@ to marshal `fuseReaddir`.
+foreign import ccall "dynamic"
+  peekFuseFillDir :: FunPtr C.FuseFillDir -> C.FuseFillDir
+
+-- | the dummy to please both ghc and haddock; don't use
+_dummy :: StablePtr a -> b
+_dummy _ = undefined eNOSYS
diff --git a/src/System/LibFuse3/Internal/C.hsc b/src/System/LibFuse3/Internal/C.hsc
new file mode 100644
--- /dev/null
+++ b/src/System/LibFuse3/Internal/C.hsc
@@ -0,0 +1,543 @@
+{-# LANGUAGE RecordWildCards #-}
+-- | C land.
+--
+-- This is an internal module. It is exposed to allow fine-tuning and workarounds but its API is not stable.
+module System.LibFuse3.Internal.C where
+
+import Data.Word (Word32, Word64)
+import Foreign (FunPtr, Ptr, Storable, nullFunPtr, peekByteOff, pokeByteOff)
+import Foreign.C (CDouble, CInt(CInt), CSize(CSize), CString, CUInt(CUInt))
+import System.Clock (TimeSpec)
+import System.LibFuse3.FileStat (FileStat)
+import System.LibFuse3.FileSystemStats (FileSystemStats)
+import System.Posix.Types (CDev(CDev), CGid(CGid), CMode(CMode), COff(COff), CSsize(CSsize), CUid(CUid))
+
+import qualified Foreign
+import qualified System.Posix.Internals as Posix
+
+#include <fuse.h>
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+-- | @struct fuse_args@
+data FuseArgs
+
+-- | @struct fuse_buf@
+data FuseBuf
+
+-- | @struct fuse_bufvec@
+data FuseBufvec
+
+-- | @struct fuse_cmdline_opts@
+data FuseCmdlineOpts
+
+-- | The direct, storable representation of @struct fuse_config@.
+--
+-- Not to be confused with the high-level `System.LibFuse3.Internal.FuseConfig`.
+data FuseConfig = FuseConfig
+  { -- | @set_gid@
+    setGid :: CInt
+  , -- | @gid@
+    gid :: CUInt
+  , -- | @set_uid@
+    setUid :: CInt
+  , -- | @uid@
+    uid :: CUInt
+  , -- | @set_mode@
+    setMode :: CInt
+  , -- | @umask@
+    umask :: CUInt
+  , -- | @entry_timeout@
+    entryTimeout :: CDouble
+  , -- | @negative_timeout@
+    negativeTimeout :: CDouble
+  , -- | @attr_timeout@
+    attrTimeout :: CDouble
+  , -- | @intr@
+    intr :: CInt
+  , -- | @intr_signal@
+    intrSignal :: CInt
+  , -- | @remember@
+    remember :: CInt
+  , -- | @hard_remove@
+    hardRemove :: CInt
+  , -- | @use_ino@
+    useIno :: CInt
+  , -- | @readdir_ino@
+    readdirIno :: CInt
+  , -- | @direct_io@
+    directIo :: CInt
+  , -- | @kernel_cache@
+    kernelCache :: CInt
+  , -- | @auto_cache@
+    autoCache :: CInt
+  , -- | @ac_attr_timeout_set@
+    acAttrTimeoutSet :: CInt
+  , -- | @ac_attr_timeout@
+    acAttrTimeout :: CDouble
+  , -- | @nullpath_ok@
+    nullpathOk :: CInt
+  }
+  deriving (Eq, Show)
+
+-- | Targets @struct fuse_config@.
+instance Storable FuseConfig where
+  sizeOf _ = #size struct fuse_config
+
+  alignment _ = #alignment struct fuse_config
+
+  peek ptr = do
+    setGid           <- (#peek struct fuse_config, set_gid)             ptr
+    gid              <- (#peek struct fuse_config, gid)                 ptr
+    setUid           <- (#peek struct fuse_config, set_uid)             ptr
+    uid              <- (#peek struct fuse_config, uid)                 ptr
+    setMode          <- (#peek struct fuse_config, set_mode)            ptr
+    umask            <- (#peek struct fuse_config, umask)               ptr
+    entryTimeout     <- (#peek struct fuse_config, entry_timeout)       ptr
+    negativeTimeout  <- (#peek struct fuse_config, negative_timeout)    ptr
+    attrTimeout      <- (#peek struct fuse_config, attr_timeout)        ptr
+    intr             <- (#peek struct fuse_config, intr)                ptr
+    intrSignal       <- (#peek struct fuse_config, intr_signal)         ptr
+    remember         <- (#peek struct fuse_config, remember)            ptr
+    hardRemove       <- (#peek struct fuse_config, hard_remove)         ptr
+    useIno           <- (#peek struct fuse_config, use_ino)             ptr
+    readdirIno       <- (#peek struct fuse_config, readdir_ino)         ptr
+    directIo         <- (#peek struct fuse_config, direct_io)           ptr
+    kernelCache      <- (#peek struct fuse_config, kernel_cache)        ptr
+    autoCache        <- (#peek struct fuse_config, auto_cache)          ptr
+    acAttrTimeoutSet <- (#peek struct fuse_config, ac_attr_timeout_set) ptr
+    acAttrTimeout    <- (#peek struct fuse_config, ac_attr_timeout)     ptr
+    nullpathOk       <- (#peek struct fuse_config, nullpath_ok)         ptr
+    pure FuseConfig{..}
+
+  poke ptr FuseConfig{..} = do
+    (#poke struct fuse_config, set_gid)             ptr setGid
+    (#poke struct fuse_config, gid)                 ptr gid
+    (#poke struct fuse_config, set_uid)             ptr setUid
+    (#poke struct fuse_config, uid)                 ptr uid
+    (#poke struct fuse_config, set_mode)            ptr setMode
+    (#poke struct fuse_config, umask)               ptr umask
+    (#poke struct fuse_config, entry_timeout)       ptr entryTimeout
+    (#poke struct fuse_config, negative_timeout)    ptr negativeTimeout
+    (#poke struct fuse_config, attr_timeout)        ptr attrTimeout
+    (#poke struct fuse_config, intr)                ptr intr
+    (#poke struct fuse_config, intr_signal)         ptr intrSignal
+    (#poke struct fuse_config, remember)            ptr remember
+    (#poke struct fuse_config, hard_remove)         ptr hardRemove
+    (#poke struct fuse_config, use_ino)             ptr useIno
+    (#poke struct fuse_config, readdir_ino)         ptr readdirIno
+    (#poke struct fuse_config, direct_io)           ptr directIo
+    (#poke struct fuse_config, kernel_cache)        ptr kernelCache
+    (#poke struct fuse_config, auto_cache)          ptr autoCache
+    (#poke struct fuse_config, ac_attr_timeout_set) ptr acAttrTimeoutSet
+    (#poke struct fuse_config, ac_attr_timeout)     ptr acAttrTimeout
+    (#poke struct fuse_config, nullpath_ok)         ptr nullpathOk
+
+-- | @struct fuse_conn_info@
+data FuseConnInfo
+
+-- | @struct fuse_file_info@
+data FuseFileInfo
+
+-- | @typedef fuse_fill_dir_t@
+type FuseFillDir = Ptr FuseFillDirBuf -> CString -> Ptr FileStat -> COff -> FuseFillDirFlags -> IO CInt
+
+-- | @Ptr FuseFillDirBuf = void *@, used in `FuseFillDir`.
+data FuseFillDirBuf
+
+-- | @enum fuse_fill_dir_flags@
+type FuseFillDirFlags = #type enum fuse_fill_dir_flags
+
+-- | The direct, storable representation of @struct fuse_operations@.
+--
+-- All operations are optional. NULL indicates undefined operation. You may modify some
+-- of the fields to fine-tune the behavior.
+--
+-- Not to be confused with Haskell-friendly `System.LibFuse3.Internal.FuseOperations`.
+-- Also not to be confused with libfuse's low-level API @struct fuse_lowlevel_ops@.
+data FuseOperations = FuseOperations
+  { fuseGetattr       :: FunPtr CGetattr
+  , fuseReadlink      :: FunPtr CReadlink
+  , fuseMknod         :: FunPtr CMknod
+  , fuseMkdir         :: FunPtr CMkdir
+  , fuseUnlink        :: FunPtr CUnlink
+  , fuseRmdir         :: FunPtr CRmdir
+  , fuseSymlink       :: FunPtr CSymlink
+  , fuseRename        :: FunPtr CRename
+  , fuseLink          :: FunPtr CLink
+  , fuseChmod         :: FunPtr CChmod
+  , fuseChown         :: FunPtr CChown
+  , fuseTruncate      :: FunPtr CTruncate
+  , fuseOpen          :: FunPtr COpen
+  , fuseRead          :: FunPtr CRead
+  , fuseWrite         :: FunPtr CWrite
+  , fuseStatfs        :: FunPtr CStatfs
+  , fuseFlush         :: FunPtr CFlush
+  , fuseRelease       :: FunPtr CRelease
+  , fuseFsync         :: FunPtr CFsync
+  , fuseSetxattr      :: FunPtr CSetxattr
+  , fuseGetxattr      :: FunPtr CGetxattr
+  , fuseListxattr     :: FunPtr CListxattr
+  , fuseRemovexattr   :: FunPtr CRemovexattr
+  , fuseOpendir       :: FunPtr COpendir
+  , fuseReaddir       :: FunPtr CReaddir
+  , fuseReleasedir    :: FunPtr CReleasedir
+  , fuseFsyncdir      :: FunPtr CFsyncdir
+  , fuseInit          :: FunPtr CInit
+  , fuseDestroy       :: FunPtr CDestroy
+  , fuseAccess        :: FunPtr CAccess
+  , fuseCreate        :: FunPtr CCreate
+  , fuseLock          :: FunPtr CLock
+  , fuseUtimens       :: FunPtr CUtimens
+  , fuseBmap          :: FunPtr CBmap
+  , fuseIoctl         :: FunPtr CIoctl
+  , fusePoll          :: FunPtr CPoll
+  , fuseWriteBuf      :: FunPtr CWriteBuf
+  , fuseReadBuf       :: FunPtr CReadBuf
+  , fuseFlock         :: FunPtr CFlock
+  , fuseFallocate     :: FunPtr CFallocate
+  , fuseCopyFileRange :: FunPtr CCopyFileRange
+  , fuseLseek         :: FunPtr CLseek
+  }
+
+instance Storable FuseOperations where
+  sizeOf _ = #size struct fuse_operations
+
+  alignment _ = #alignment struct fuse_operations
+
+  peek ptr = do
+    fuseGetattr       <- (#peek struct fuse_operations, getattr)         ptr
+    fuseReadlink      <- (#peek struct fuse_operations, readlink)        ptr
+    fuseMknod         <- (#peek struct fuse_operations, mknod)           ptr
+    fuseMkdir         <- (#peek struct fuse_operations, mkdir)           ptr
+    fuseUnlink        <- (#peek struct fuse_operations, unlink)          ptr
+    fuseRmdir         <- (#peek struct fuse_operations, rmdir)           ptr
+    fuseSymlink       <- (#peek struct fuse_operations, symlink)         ptr
+    fuseRename        <- (#peek struct fuse_operations, rename)          ptr
+    fuseLink          <- (#peek struct fuse_operations, link)            ptr
+    fuseChmod         <- (#peek struct fuse_operations, chmod)           ptr
+    fuseChown         <- (#peek struct fuse_operations, chown)           ptr
+    fuseTruncate      <- (#peek struct fuse_operations, truncate)        ptr
+    fuseOpen          <- (#peek struct fuse_operations, open)            ptr
+    fuseRead          <- (#peek struct fuse_operations, read)            ptr
+    fuseWrite         <- (#peek struct fuse_operations, write)           ptr
+    fuseStatfs        <- (#peek struct fuse_operations, statfs)          ptr
+    fuseFlush         <- (#peek struct fuse_operations, flush)           ptr
+    fuseRelease       <- (#peek struct fuse_operations, release)         ptr
+    fuseFsync         <- (#peek struct fuse_operations, fsync)           ptr
+    fuseSetxattr      <- (#peek struct fuse_operations, setxattr)        ptr
+    fuseGetxattr      <- (#peek struct fuse_operations, getxattr)        ptr
+    fuseListxattr     <- (#peek struct fuse_operations, listxattr)       ptr
+    fuseRemovexattr   <- (#peek struct fuse_operations, removexattr)     ptr
+    fuseOpendir       <- (#peek struct fuse_operations, opendir)         ptr
+    fuseReaddir       <- (#peek struct fuse_operations, readdir)         ptr
+    fuseReleasedir    <- (#peek struct fuse_operations, releasedir)      ptr
+    fuseFsyncdir      <- (#peek struct fuse_operations, fsyncdir)        ptr
+    fuseInit          <- (#peek struct fuse_operations, init)            ptr
+    fuseDestroy       <- (#peek struct fuse_operations, destroy)         ptr
+    fuseAccess        <- (#peek struct fuse_operations, access)          ptr
+    fuseCreate        <- (#peek struct fuse_operations, create)          ptr
+    fuseLock          <- (#peek struct fuse_operations, lock)            ptr
+    fuseUtimens       <- (#peek struct fuse_operations, utimens)         ptr
+    fuseBmap          <- (#peek struct fuse_operations, bmap)            ptr
+    fuseIoctl         <- (#peek struct fuse_operations, ioctl)           ptr
+    fusePoll          <- (#peek struct fuse_operations, poll)            ptr
+    fuseWriteBuf      <- (#peek struct fuse_operations, write_buf)       ptr
+    fuseReadBuf       <- (#peek struct fuse_operations, read_buf)        ptr
+    fuseFlock         <- (#peek struct fuse_operations, flock)           ptr
+    fuseFallocate     <- (#peek struct fuse_operations, fallocate)       ptr
+    fuseCopyFileRange <- (#peek struct fuse_operations, copy_file_range) ptr
+#ifdef FUSE_HAS_LSEEK
+    fuseLseek         <- (#peek struct fuse_operations, lseek)           ptr
+#else
+    let fuseLseek = nullFunPtr
+#endif
+    pure FuseOperations{..}
+
+  poke ptr FuseOperations{..} = do
+    (#poke struct fuse_operations, getattr)         ptr fuseGetattr
+    (#poke struct fuse_operations, readlink)        ptr fuseReadlink
+    (#poke struct fuse_operations, mknod)           ptr fuseMknod
+    (#poke struct fuse_operations, mkdir)           ptr fuseMkdir
+    (#poke struct fuse_operations, unlink)          ptr fuseUnlink
+    (#poke struct fuse_operations, rmdir)           ptr fuseRmdir
+    (#poke struct fuse_operations, symlink)         ptr fuseSymlink
+    (#poke struct fuse_operations, rename)          ptr fuseRename
+    (#poke struct fuse_operations, link)            ptr fuseLink
+    (#poke struct fuse_operations, chmod)           ptr fuseChmod
+    (#poke struct fuse_operations, chown)           ptr fuseChown
+    (#poke struct fuse_operations, truncate)        ptr fuseTruncate
+    (#poke struct fuse_operations, open)            ptr fuseOpen
+    (#poke struct fuse_operations, read)            ptr fuseRead
+    (#poke struct fuse_operations, write)           ptr fuseWrite
+    (#poke struct fuse_operations, statfs)          ptr fuseStatfs
+    (#poke struct fuse_operations, flush)           ptr fuseFlush
+    (#poke struct fuse_operations, release)         ptr fuseRelease
+    (#poke struct fuse_operations, fsync)           ptr fuseFsync
+    (#poke struct fuse_operations, setxattr)        ptr fuseSetxattr
+    (#poke struct fuse_operations, getxattr)        ptr fuseGetxattr
+    (#poke struct fuse_operations, listxattr)       ptr fuseListxattr
+    (#poke struct fuse_operations, removexattr)     ptr fuseRemovexattr
+    (#poke struct fuse_operations, opendir)         ptr fuseOpendir
+    (#poke struct fuse_operations, readdir)         ptr fuseReaddir
+    (#poke struct fuse_operations, releasedir)      ptr fuseReleasedir
+    (#poke struct fuse_operations, fsyncdir)        ptr fuseFsyncdir
+    (#poke struct fuse_operations, init)            ptr fuseInit
+    (#poke struct fuse_operations, destroy)         ptr fuseDestroy
+    (#poke struct fuse_operations, access)          ptr fuseAccess
+    (#poke struct fuse_operations, create)          ptr fuseCreate
+    (#poke struct fuse_operations, lock)            ptr fuseLock
+    (#poke struct fuse_operations, utimens)         ptr fuseUtimens
+    (#poke struct fuse_operations, bmap)            ptr fuseBmap
+    (#poke struct fuse_operations, ioctl)           ptr fuseIoctl
+    (#poke struct fuse_operations, poll)            ptr fusePoll
+    (#poke struct fuse_operations, write_buf)       ptr fuseWriteBuf
+    (#poke struct fuse_operations, read_buf)        ptr fuseReadBuf
+    (#poke struct fuse_operations, flock)           ptr fuseFlock
+    (#poke struct fuse_operations, fallocate)       ptr fuseFallocate
+    (#poke struct fuse_operations, copy_file_range) ptr fuseCopyFileRange
+#ifdef FUSE_HAS_LSEEK
+    (#poke struct fuse_operations, lseek)           ptr fuseLseek
+#endif
+
+-- | An empty set of operations whose fields are @nullFunPtr@.
+defaultFuseOperations :: FuseOperations
+defaultFuseOperations = FuseOperations nullFunPtr nullFunPtr nullFunPtr nullFunPtr nullFunPtr nullFunPtr nullFunPtr nullFunPtr nullFunPtr nullFunPtr nullFunPtr nullFunPtr nullFunPtr nullFunPtr nullFunPtr nullFunPtr nullFunPtr nullFunPtr nullFunPtr nullFunPtr nullFunPtr nullFunPtr nullFunPtr nullFunPtr nullFunPtr nullFunPtr nullFunPtr nullFunPtr nullFunPtr nullFunPtr nullFunPtr nullFunPtr nullFunPtr nullFunPtr nullFunPtr nullFunPtr nullFunPtr nullFunPtr nullFunPtr nullFunPtr nullFunPtr nullFunPtr
+
+-- | Merges two `FuseOperations` in a left-biased manner.
+mergeLFuseOperations :: FuseOperations -> FuseOperations -> FuseOperations
+mergeLFuseOperations
+  (FuseOperations a1 a2 a3 a4 a5 a6 a7 a8 a9 a10 a11 a12 a13 a14 a15 a16 a17 a18 a19 a20 a21 a22 a23 a24 a25 a26 a27 a28 a29 a30 a31 a32 a33 a34 a35 a36 a37 a38 a39 a40 a41 a42)
+  (FuseOperations b1 b2 b3 b4 b5 b6 b7 b8 b9 b10 b11 b12 b13 b14 b15 b16 b17 b18 b19 b20 b21 b22 b23 b24 b25 b26 b27 b28 b29 b30 b31 b32 b33 b34 b35 b36 b37 b38 b39 b40 b41 b42)
+  = FuseOperations (a1 `mergeL` b1) (a2 `mergeL` b2) (a3 `mergeL` b3) (a4 `mergeL` b4) (a5 `mergeL` b5) (a6 `mergeL` b6) (a7 `mergeL` b7) (a8 `mergeL` b8) (a9 `mergeL` b9) (a10 `mergeL` b10) (a11 `mergeL` b11) (a12 `mergeL` b12) (a13 `mergeL` b13) (a14 `mergeL` b14) (a15 `mergeL` b15) (a16 `mergeL` b16) (a17 `mergeL` b17) (a18 `mergeL` b18) (a19 `mergeL` b19) (a20 `mergeL` b20) (a21 `mergeL` b21) (a22 `mergeL` b22) (a23 `mergeL` b23) (a24 `mergeL` b24) (a25 `mergeL` b25) (a26 `mergeL` b26) (a27 `mergeL` b27) (a28 `mergeL` b28) (a29 `mergeL` b29) (a30 `mergeL` b30) (a31 `mergeL` b31) (a32 `mergeL` b32) (a33 `mergeL` b33) (a34 `mergeL` b34) (a35 `mergeL` b35) (a36 `mergeL` b36) (a37 `mergeL` b37) (a38 `mergeL` b38) (a39 `mergeL` b39) (a40 `mergeL` b40) (a41 `mergeL` b41) (a42 `mergeL` b42)
+  where
+  mergeL a b = if a == nullFunPtr then b else a
+
+-- | @struct fuse_pollhandle@
+data FusePollhandle
+
+-- | @enum fuse_readdir_flags@
+type FuseReaddirFlags = #type enum fuse_readdir_flags
+
+-- | @struct fuse_session@
+data FuseSession
+
+-- | @struct fuse@
+data StructFuse
+
+foreign import ccall safe "fuse_cmdline_help"
+  fuse_cmdline_help :: IO ()
+
+foreign import ccall safe "fuse_destroy"
+  fuse_destroy :: Ptr StructFuse -> IO ()
+
+foreign import ccall safe "fuse_get_session"
+  fuse_get_session :: Ptr StructFuse -> IO (Ptr FuseSession)
+
+foreign import ccall safe "fuse_lib_help"
+  fuse_lib_help :: Ptr FuseArgs -> IO ()
+
+foreign import ccall safe "fuse_loop_mt_31"
+  fuse_loop_mt_31 :: Ptr StructFuse -> CInt -> IO Int
+
+foreign import ccall safe "fuse_lowlevel_help"
+  fuse_lowlevel_help :: IO ()
+
+foreign import ccall safe "fuse_lowlevel_version"
+  fuse_lowlevel_version :: IO ()
+
+foreign import ccall safe "fuse_mount"
+  fuse_mount :: Ptr StructFuse -> CString -> IO CInt
+
+foreign import ccall safe "fuse_new"
+  fuse_new :: Ptr FuseArgs -> Ptr FuseOperations -> CSize -> Ptr a -> IO (Ptr StructFuse)
+
+foreign import ccall safe "fuse_opt_free_args"
+  fuse_opt_free_args :: Ptr FuseArgs -> IO ()
+
+foreign import ccall safe "fuse_parse_cmdline"
+  fuse_parse_cmdline :: Ptr FuseArgs -> Ptr FuseCmdlineOpts -> IO CInt
+
+foreign import ccall safe "fuse_pkgversion"
+  fuse_pkgversion :: IO CString
+
+foreign import ccall safe "fuse_session_exit"
+  fuse_session_exit :: Ptr FuseSession -> IO ()
+
+foreign import ccall safe "fuse_unmount"
+  fuse_unmount :: Ptr StructFuse -> IO ()
+
+type CGetattr = CString -> Ptr FileStat -> Ptr FuseFileInfo -> IO CInt
+foreign import ccall "wrapper"
+  mkGetattr :: CGetattr -> IO (FunPtr CGetattr)
+
+type CReadlink = CString -> CString -> CSize -> IO CInt
+foreign import ccall "wrapper"
+  mkReadlink :: CReadlink -> IO (FunPtr CReadlink)
+
+type CMknod = CString -> CMode -> CDev -> IO CInt
+foreign import ccall "wrapper"
+  mkMknod :: CMknod -> IO (FunPtr CMknod)
+
+type CMkdir = CString -> CMode -> IO CInt
+foreign import ccall "wrapper"
+  mkMkdir :: CMkdir -> IO (FunPtr CMkdir)
+
+type CUnlink = CString -> IO CInt
+foreign import ccall "wrapper"
+  mkUnlink :: CUnlink -> IO (FunPtr CUnlink)
+
+type CRmdir = CString -> IO CInt
+foreign import ccall "wrapper"
+  mkRmdir :: CRmdir -> IO (FunPtr CRmdir)
+
+type CSymlink = CString -> CString -> IO CInt
+foreign import ccall "wrapper"
+  mkSymlink :: CSymlink -> IO (FunPtr CSymlink)
+
+type CRename = CString -> CString -> CUInt -> IO CInt
+foreign import ccall "wrapper"
+  mkRename :: CRename -> IO (FunPtr CRename)
+
+type CLink = CString -> CString -> IO CInt
+foreign import ccall "wrapper"
+  mkLink :: CLink -> IO (FunPtr CLink)
+
+type CChmod = CString -> CMode -> Ptr FuseFileInfo -> IO CInt
+foreign import ccall "wrapper"
+  mkChmod :: CChmod -> IO (FunPtr CChmod)
+
+type CChown = CString -> CUid -> CGid -> Ptr FuseFileInfo -> IO CInt
+foreign import ccall "wrapper"
+  mkChown :: CChown -> IO (FunPtr CChown)
+
+type CTruncate = CString -> COff -> Ptr FuseFileInfo -> IO CInt
+foreign import ccall "wrapper"
+  mkTruncate :: CTruncate -> IO (FunPtr CTruncate)
+
+type COpen = CString -> Ptr FuseFileInfo -> IO CInt
+foreign import ccall "wrapper"
+  mkOpen :: COpen -> IO (FunPtr COpen)
+
+type CRead = CString -> CString -> CSize -> COff -> Ptr FuseFileInfo -> IO CInt
+foreign import ccall "wrapper"
+  mkRead :: CRead -> IO (FunPtr CRead)
+
+type CWrite = CString -> CString -> CSize -> COff -> Ptr FuseFileInfo -> IO CInt
+foreign import ccall "wrapper"
+  mkWrite :: CWrite -> IO (FunPtr CWrite)
+
+type CStatfs = CString -> Ptr FileSystemStats -> IO CInt
+foreign import ccall "wrapper"
+  mkStatfs :: CStatfs -> IO (FunPtr CStatfs)
+
+type CFlush = CString -> Ptr FuseFileInfo -> IO CInt
+foreign import ccall "wrapper"
+  mkFlush :: CFlush -> IO (FunPtr CFlush)
+
+type CRelease = CString -> Ptr FuseFileInfo -> IO CInt
+foreign import ccall "wrapper"
+  mkRelease :: CRelease -> IO (FunPtr CRelease)
+
+type CFsync = CString -> CInt -> Ptr FuseFileInfo -> IO CInt
+foreign import ccall "wrapper"
+  mkFsync :: CFsync -> IO (FunPtr CFsync)
+
+type CSetxattr = CString -> CString -> CString -> CSize -> CInt -> IO CInt
+foreign import ccall "wrapper"
+  mkSetxattr :: CSetxattr -> IO (FunPtr CSetxattr)
+
+type CGetxattr = CString -> CString -> CString -> CSize -> IO CInt
+foreign import ccall "wrapper"
+  mkGetxattr :: CGetxattr -> IO (FunPtr CGetxattr)
+
+type CListxattr = CString -> CString -> CSize -> IO CInt
+foreign import ccall "wrapper"
+  mkListxattr :: CListxattr -> IO (FunPtr CListxattr)
+
+type CRemovexattr = CString -> CString -> IO CInt
+foreign import ccall "wrapper"
+  mkRemovexattr :: CRemovexattr -> IO (FunPtr CRemovexattr)
+
+type COpendir = CString -> Ptr FuseFileInfo -> IO CInt
+foreign import ccall "wrapper"
+  mkOpendir :: COpendir -> IO (FunPtr COpendir)
+
+type CReaddir = CString -> Ptr FuseFillDirBuf -> FunPtr FuseFillDir -> COff -> Ptr FuseFileInfo -> FuseReaddirFlags -> IO CInt
+foreign import ccall "wrapper"
+  mkReaddir :: CReaddir -> IO (FunPtr CReaddir)
+
+type CReleasedir = CString -> Ptr FuseFileInfo -> IO CInt
+foreign import ccall "wrapper"
+  mkReleasedir :: CReleasedir -> IO (FunPtr CReleasedir)
+
+type CFsyncdir = CString -> CInt -> Ptr FuseFileInfo -> IO CInt
+foreign import ccall "wrapper"
+  mkFsyncdir :: CFsyncdir -> IO (FunPtr CFsyncdir)
+
+type CInit = Ptr FuseConnInfo -> Ptr FuseConfig -> IO (Ptr ())
+foreign import ccall "wrapper"
+  mkInit :: CInit -> IO (FunPtr CInit)
+
+type CDestroy = Ptr () -> IO ()
+foreign import ccall "wrapper"
+  mkDestroy :: CDestroy -> IO (FunPtr CDestroy)
+
+type CAccess = CString -> CInt -> IO CInt
+foreign import ccall "wrapper"
+  mkAccess :: CAccess -> IO (FunPtr CAccess)
+
+type CCreate = CString -> CMode -> Ptr FuseFileInfo -> IO CInt
+foreign import ccall "wrapper"
+  mkCreate :: CCreate -> IO (FunPtr CCreate)
+
+type CLock = CString -> Ptr FuseFileInfo -> CInt -> Ptr Posix.CFLock
+foreign import ccall "wrapper"
+  mkLock :: CLock -> IO (FunPtr CLock)
+
+-- actual signature:
+-- int(*utimens)(const char *, const struct timespec tv[2], struct fuse_file_info *fi)
+-- We treat @struct timespec [2]@ as if it is @struct timespec *@ because they are compatible in
+-- function parameter lists:
+-- https://en.cppreference.com/w/c/language/type#Compatible_types
+type CUtimens = CString -> Ptr TimeSpec -> Ptr FuseFileInfo -> IO CInt
+foreign import ccall "wrapper"
+  mkUtimens :: CUtimens -> IO (FunPtr CUtimens)
+
+type CBmap = CString -> CSize -> Ptr Word64 -> IO CInt
+foreign import ccall "wrapper"
+  mkBmap :: CBmap -> IO (FunPtr CBmap)
+
+type CIoctl = CString -> CUInt -> Ptr () -> Ptr FuseFileInfo -> CUInt -> Ptr () -> IO CInt
+foreign import ccall "wrapper"
+  mkIoctl :: CIoctl -> IO (FunPtr CIoctl)
+
+type CPoll = CString -> Ptr FuseFileInfo -> Ptr FusePollhandle -> Ptr CUInt -> IO CInt
+foreign import ccall "wrapper"
+  mkPoll :: CPoll -> IO (FunPtr CPoll)
+
+type CWriteBuf = CString -> Ptr FuseBufvec -> COff -> Ptr FuseFileInfo -> IO CInt
+foreign import ccall "wrapper"
+  mkWriteBuf :: CWriteBuf -> IO (FunPtr CWriteBuf)
+
+type CReadBuf = CString -> Ptr (Ptr FuseBufvec) -> CSize -> COff -> Ptr FuseFileInfo -> IO CInt
+foreign import ccall "wrapper"
+  mkReadBuf :: CReadBuf -> IO (FunPtr CReadBuf)
+
+type CFlock = CString -> Ptr FuseFileInfo -> CInt -> IO CInt
+foreign import ccall "wrapper"
+  mkFlock :: CFlock -> IO (FunPtr CFlock)
+
+type CFallocate = CString -> CInt -> COff -> COff -> Ptr FuseFileInfo -> IO CInt
+foreign import ccall "wrapper"
+  mkFallocate :: CFallocate -> IO (FunPtr CFallocate)
+
+type CCopyFileRange = CString -> Ptr FuseFileInfo -> COff -> CString -> Ptr FuseFileInfo -> COff -> CSize -> CInt -> IO CSsize
+foreign import ccall "wrapper"
+  mkCopyFileRange :: CCopyFileRange -> IO (FunPtr CCopyFileRange)
+
+type CLseek = CString -> COff -> CInt -> Ptr FuseFileInfo -> IO COff
+foreign import ccall "wrapper"
+  mkLseek :: CLseek -> IO (FunPtr CLseek)
diff --git a/src/System/LibFuse3/Internal/Resource.hs b/src/System/LibFuse3/Internal/Resource.hs
new file mode 100644
--- /dev/null
+++ b/src/System/LibFuse3/Internal/Resource.hs
@@ -0,0 +1,55 @@
+-- | Utils related to @ResourceT@
+--
+-- This is an internal module. It is exposed to allow fine-tuning and workarounds but its API is not stable.
+module System.LibFuse3.Internal.Resource where
+
+import Control.Exception (catch, mask, throwIO)
+import Control.Monad.IO.Class (liftIO)
+import Control.Monad.Trans.Resource (ReleaseKey, ResourceT, allocate, getInternalState, runInternalState)
+import Control.Monad.Trans.Resource.Internal (stateCleanupChecked)
+import Foreign (Ptr, Storable, callocBytes, free, mallocBytes, new, newArray)
+import Foreign.C (CString, newCString)
+import System.Exit (ExitCode(ExitSuccess))
+import System.Posix.Internals (newFilePath)
+import System.Posix.Process (exitImmediately, forkProcess)
+
+-- | Forks a new process and transfers the resources to it.
+--
+-- The parent process `exitImmediately`.
+daemonizeResourceT :: ResourceT IO a -> ResourceT IO b
+daemonizeResourceT res = do
+  -- We don't use resourceForkWith because we don't want to increase refcounts
+  istate <- getInternalState
+  liftIO $ do
+    _ <- forkProcess $ mask $ \restore -> do
+      _ <- restore (runInternalState res istate) `catch` \e -> do
+        stateCleanupChecked (Just e) istate
+        throwIO e
+      stateCleanupChecked Nothing istate
+    -- cleanup actions are discarded because the child will run them
+    exitImmediately ExitSuccess
+    undefined
+
+-- | `callocBytes` with `free` associated as a cleanup action.
+resCallocBytes :: Int -> ResourceT IO (ReleaseKey, Ptr a)
+resCallocBytes n = allocate (callocBytes n) free
+
+-- | `mallocBytes` with `free` associated as a cleanup action.
+resMallocBytes :: Int -> ResourceT IO (ReleaseKey, Ptr a)
+resMallocBytes n = allocate (mallocBytes n) free
+
+-- | `new` with `free` associated as a cleanup action.
+resNew :: Storable a => a -> ResourceT IO (ReleaseKey, Ptr a)
+resNew a = allocate (new a) free
+
+-- | `newCString` with `free` associated as a cleanup action.
+resNewCString :: String -> ResourceT IO (ReleaseKey, CString)
+resNewCString s = allocate (newCString s) free
+
+-- | `newFilePath` with `free` associated as a cleanup action.
+resNewFilePath :: FilePath -> ResourceT IO (ReleaseKey, CString)
+resNewFilePath path = allocate (newFilePath path) free
+
+-- | `newArray` with `free` associated as a cleanup action.
+resNewArray :: Storable a => [a] -> ResourceT IO (ReleaseKey, Ptr a)
+resNewArray as = allocate (newArray as) free
diff --git a/src/System/LibFuse3/Utils.hs b/src/System/LibFuse3/Utils.hs
new file mode 100644
--- /dev/null
+++ b/src/System/LibFuse3/Utils.hs
@@ -0,0 +1,82 @@
+-- | Miscellaneous utilities provided for convenience.
+--
+-- These can be used for general purpose and are not directly related to FUSE.
+module System.LibFuse3.Utils
+  ( -- * Bitsets
+    testBitSet
+
+  , -- * Errno
+    unErrno, ioErrorToErrno, tryErrno, tryErrno_
+
+  , -- * Marshalling strings
+    pokeCStringLen0
+
+  , -- * TimeSpec
+    timeSpecToPOSIXTime
+  )
+  where
+
+import Control.Exception (tryJust)
+import Data.Bits ((.&.), Bits)
+import Data.Ratio ((%))
+import Data.Time.Clock.POSIX (POSIXTime)
+import Foreign (copyArray, pokeElemOff)
+import Foreign.C (CInt, CStringLen, Errno(Errno), eOK, errnoToIOError, throwErrno, withCStringLen)
+import GHC.IO.Exception (IOException(IOError, ioe_errno))
+import System.Clock (TimeSpec)
+
+import qualified System.Clock as TimeSpec
+
+-- to have haddock link to proper entities
+_dummy :: dummy
+_dummy = error "dummy" errnoToIOError throwErrno
+
+-- | Unwraps the newtype `Errno`.
+unErrno :: Errno -> CInt
+unErrno (Errno errno) = errno
+
+-- | Attempts to extract an `Errno` from an t`IOError` assuming it is
+-- constructed with `errnoToIOError` (typically via `throwErrno`).
+ioErrorToErrno :: IOError -> Maybe Errno
+ioErrorToErrno IOError{ioe_errno=Just e} = Just $ Errno e
+ioErrorToErrno _ = Nothing
+
+-- | Catches an exception constructed with `errnoToIOError` and extracts `Errno` from it.
+tryErrno :: IO a -> IO (Either Errno a)
+tryErrno = tryJust ioErrorToErrno
+
+-- | Like `tryErrno` but discards the result of the original action.
+--
+-- If no exceptions, returns `eOK`.
+tryErrno_ :: IO a -> IO Errno
+tryErrno_ = fmap (either id (const eOK)) . tryErrno
+
+-- | Converts a `TimeSpec` to a `POSIXTime`.
+--
+-- This is the same conversion as the @unix@ package does (as of writing).
+timeSpecToPOSIXTime :: TimeSpec -> POSIXTime
+timeSpecToPOSIXTime ts = fromRational $ TimeSpec.toNanoSecs ts % 10^(9::Int)
+
+-- | Marshals a Haskell string into a NUL terminated C string in a locale-dependent way.
+--
+-- Does `withCStringLen` and copies it into the destination buffer.
+--
+-- The Haskell string should not contain NUL characters.
+--
+-- If the destination buffer is not long enough to hold the source string, it is truncated
+-- and a NUL byte is inserted at the end of the buffer.
+pokeCStringLen0 :: CStringLen -> String -> IO ()
+pokeCStringLen0 (pBuf, bufSize) src =
+  withCStringLen src $ \(pSrc, srcSize) -> do
+    -- withCStringLen does *not* append NUL byte at the end
+    let bufSize0 = bufSize - 1
+    copyArray pBuf pSrc (min bufSize0 srcSize)
+    pokeElemOff pBuf (min bufSize0 srcSize) 0
+
+-- | @testBitSet bits mask@ is @True@ iff all bits in @mask@ are set in @bits@.
+--
+-- @
+-- testBitSet bits mask ≡ bits .&. mask == mask
+-- @
+testBitSet :: Bits a => a -> a -> Bool
+testBitSet bits mask = bits .&. mask == mask
