---
task:
matrix:
- - name: debian
+ - name: debian-fuse2
container:
image: gcc:11-bullseye
install_script: |
env:
EXTRA_CFLAGS: -fanalyzer
+ - name: debian-fuse3
+ container:
+ image: gcc:11-bullseye
+ install_script: |
+ apt-get update
+ apt-get install -y libfuse3-dev
+ env:
+ EXTRA_CFLAGS: -fanalyzer
+
- name: macos
macos_instance:
- image: big-sur-base
+ image: ghcr.io/cirruslabs/macos-ventura-base:latest
install_script: |
brew update --preinstall
brew install automake macfuse
compile_script: |
autoreconf --install
- ./configure CFLAGS="-Wall -Wextra -Werror $EXTRA_CFLAGS"
+ ./configure CFLAGS="-Wall -Wextra -Werror \
+ -fsanitize=address,undefined \
+ $EXTRA_CFLAGS"
make -k
test_script: |
mkfs/mkexfatfs -i 12345678 foo.img
fsck/exfatfsck foo.img
echo 'f1b3a11f781533f5b69086596be38367d0ebfb77 foo.img' | shasum -c
+ label/exfatlabel foo.img ○○○○○○○○○○○○○○○
+ echo '4720462db953d5b2094c884f4b3098a138790533 foo.img' | shasum -c
# make
*.o
+/attrib/exfatattrib
/dump/dumpexfat
/fsck/exfatfsck
/fuse/mount.exfat-fuse
"-Wno-error",
"-D_FILE_OFFSET_BITS=64",
"-DPACKAGE=\"exfat\"",
- "-DVERSION=\"1.3.0\"",
+ "-DVERSION=\"1.4.0\"",
],
shared_libs: ["liblog"],
}
+1.4.0 (2023-03-02)
+
+* Added exfatattrib utility which prints or changes file attributes [Will
+Thompson].
+* Added FUSE 3 support. FUSE 2 continues to be supported.
+* Added support for timezone offsets [Nathan Hunsperger].
+* Fixed device opening error being reported as FS error.
+* Fixed possible data leakage when uninitialized clusters were allocated using
+NtSetInformationFile() call under Windows and FS was not unmounted correctly.
+* Improved compatibility with autoconf 2.70.
+* Fixed disk size reading on NetBSD [Dave Vasilevsky].
+* Fixed "automounted" option handling on FreeBSD [Iouri V. Ivliev].
+* Allowed to specify the "nonempty" mount option.
+* Fixed file data contiguity handling bug which could cause performance
+degradation [noctis].
+* Fixed possible crashes on invalid UTF-8 sequences.
+* Fixed a situation when FS could be erroneously marked as dirty (not cleanly
+unmounted).
+
1.3.0 (2018-09-15)
* exfatfsck can now repair some errors.
# Automake source.
#
# Free exFAT implementation.
-# Copyright (C) 2010-2018 Andrew Nayenko
+# Copyright (C) 2010-2023 Andrew Nayenko
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
#
-SUBDIRS = libexfat dump fsck fuse label mkfs
+SUBDIRS = libexfat attrib dump fsck fuse label mkfs
--- /dev/null
+#
+# Makefile.am (08.11.20)
+# Automake source.
+#
+# Free exFAT implementation.
+# Copyright (C) 2020 Endless OS Foundation LLC
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+
+sbin_PROGRAMS = exfatattrib
+dist_man8_MANS = exfatattrib.8
+exfatattrib_SOURCES = main.c
+exfatattrib_CPPFLAGS = -I$(top_srcdir)/libexfat
+exfatattrib_LDADD = ../libexfat/libexfat.a
--- /dev/null
+.\" Copyright (C) 2020-2023 Endless OS Foundation
+.\"
+.TH EXFATATTRIB 8 "November 2020"
+.SH NAME
+.B exfatattrib
+\- Set or display exFAT file attributes
+.SH SYNOPSIS
+.B exfatattrib
+[
+.B \-r
+|
+.B \-R
+|
+.B \-i
+|
+.B \-I
+|
+.B \-s
+|
+.B \-S
+|
+.B \-a
+|
+.B \-A
+]
+.B \-d
+.I device
+.I file
+.SH DESCRIPTION
+.B exfatattrib
+sets or displays attributes of a file on an exFAT file system.
+
+.I device
+is the path to an unmounted disk partition or disk image file containing an
+exFAT file system.
+
+.I file
+is the path of a file within that file system.
+
+If run with no command line options, the current attributes of
+.I file
+are displayed; otherwise, the specified attributes are set or cleared. It is an
+error to set and clear the same flag.
+
+.SH COMMAND LINE OPTIONS
+Command line options available:
+
+.TP
+.BI \-d " device"
+The path to an unmounted disk partition or disk image file containing an exFAT
+file system. This option is required.
+.TP
+.BI -r
+Set read\-only flag
+.TP
+.BI \-R
+Clear read\-only flag
+.TP
+.BI \-i
+Set hidden flag (mnemonic: \fBi\fRnvisible)
+.TP
+.BI \-I
+Clear hidden flag
+.TP
+.BI \-s
+Set system flag
+.TP
+.BI \-S
+Clear system flag
+.TP
+.BI \-a
+Set archive flag
+.TP
+.BI \-A
+Clear archive flag
+.TP
+.BI \-h
+Display this help message
+.TP
+.BI \-V
+Print version and copyright.
+
+.SH EXIT CODES
+Zero is returned if errors were not found. Any other code means an error.
+
+.SH AUTHOR
+Will Thompson
+
+.SH SEE ALSO
+.BR chmod(1)
--- /dev/null
+/*
+ main.c (08.11.20)
+ Prints or changes exFAT file attributes
+
+ Free exFAT implementation.
+ Copyright (C) 2020-2023 Endless OS Foundation LLC
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*/
+
+#include <exfat.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+
+static void usage(const char* prog)
+{
+ fprintf(stderr,
+ "Display current attributes:\n"
+ " %1$s -d <device> <file>\n"
+ "\n"
+ "Set attributes:\n"
+ " %1$s [FLAGS] -d <device> <file>\n"
+ "\n"
+ "Flags:\n"
+ " -r Set read-only flag\n"
+ " -R Clear read-only flag\n"
+ " -i Set hidden flag\n"
+ " -I Clear hidden flag\n"
+ " -s Set system flag\n"
+ " -S Clear system flag\n"
+ " -a Set archive flag\n"
+ " -A Clear archive flag\n"
+ "\n"
+ " -h Display this help message\n"
+ " -V Display version information\n",
+ prog);
+ exit(1);
+}
+
+static void print_attribute(uint16_t attribs, uint16_t attrib,
+ const char* label)
+{
+ printf("%9s: %s\n", label, (attribs & attrib) ? "yes" : "no");
+}
+
+static int attribute(struct exfat* ef, struct exfat_node* node,
+ uint16_t add_flags, uint16_t clear_flags)
+{
+ if ((add_flags | clear_flags) != 0)
+ {
+ uint16_t attrib = node->attrib;
+
+ attrib |= add_flags;
+ attrib &= ~clear_flags;
+
+ if (node->attrib != attrib)
+ {
+ int ret;
+
+ node->attrib = attrib;
+ node->is_dirty = true;
+
+ ret = exfat_flush_node(ef, node);
+ if (ret != 0)
+ {
+ char buffer[EXFAT_UTF8_NAME_BUFFER_MAX];
+
+ exfat_get_name(node, buffer);
+ exfat_error("failed to flush changes to '%s': %s", buffer,
+ strerror(-ret));
+ return 1;
+ }
+ }
+ }
+ else
+ {
+ print_attribute(node->attrib, EXFAT_ATTRIB_RO, "Read-only");
+ print_attribute(node->attrib, EXFAT_ATTRIB_HIDDEN, "Hidden");
+ print_attribute(node->attrib, EXFAT_ATTRIB_SYSTEM, "System");
+ print_attribute(node->attrib, EXFAT_ATTRIB_ARCH, "Archive");
+ /* read-only attributes */
+ print_attribute(node->attrib, EXFAT_ATTRIB_VOLUME, "Volume");
+ print_attribute(node->attrib, EXFAT_ATTRIB_DIR, "Directory");
+ }
+
+ return 0;
+}
+
+int main(int argc, char* argv[])
+{
+ int opt;
+ int ret;
+ const char* spec = NULL;
+ const char* options = "";
+ const char* file_path = NULL;
+ struct exfat ef;
+ struct exfat_node* node;
+ uint16_t add_flags = 0;
+ uint16_t clear_flags = 0;
+
+ while ((opt = getopt(argc, argv, "d:rRiIsSaAhV")) != -1)
+ {
+ switch (opt)
+ {
+ case 'V':
+ printf("exfatattrib %s\n", VERSION);
+ puts("Copyright (C) 2011-2023 Andrew Nayenko");
+ puts("Copyright (C) 2020-2023 Endless OS Foundation LLC");
+ return 0;
+ /*
+ The path to the unmounted exFAT partition is a (mandatory) named
+ option rather than a positional parameter. If the FUSE file system
+ ever gains an ioctl to get and set attributes, this option could be
+ made optional, and this tool taught to use the ioctl.
+ */
+ case 'd':
+ spec = optarg;
+ break;
+ case 'r':
+ add_flags |= EXFAT_ATTRIB_RO;
+ break;
+ case 'R':
+ clear_flags |= EXFAT_ATTRIB_RO;
+ break;
+ /* "-h[elp]" is taken; i is the second letter of "hidden" and
+ its synonym "invisible" */
+ case 'i':
+ add_flags |= EXFAT_ATTRIB_HIDDEN;
+ break;
+ case 'I':
+ clear_flags |= EXFAT_ATTRIB_HIDDEN;
+ break;
+ case 's':
+ add_flags |= EXFAT_ATTRIB_SYSTEM;
+ break;
+ case 'S':
+ clear_flags |= EXFAT_ATTRIB_SYSTEM;
+ break;
+ case 'a':
+ add_flags |= EXFAT_ATTRIB_ARCH;
+ break;
+ case 'A':
+ clear_flags |= EXFAT_ATTRIB_ARCH;
+ break;
+ default:
+ usage(argv[0]);
+ }
+ }
+
+ if ((add_flags & clear_flags) != 0)
+ {
+ exfat_error("can't set and clear the same flag");
+ return 1;
+ }
+
+ if (spec == NULL || argc - optind != 1)
+ usage(argv[0]);
+
+ file_path = argv[optind];
+
+ if ((add_flags | clear_flags) == 0)
+ options = "ro";
+
+ ret = exfat_mount(&ef, spec, options);
+ if (ret != 0)
+ {
+ exfat_error("failed to mount %s: %s", spec, strerror(-ret));
+ return 1;
+ }
+
+ ret = exfat_lookup(&ef, &node, file_path);
+ if (ret != 0)
+ {
+ exfat_error("failed to look up '%s': %s", file_path, strerror(-ret));
+ exfat_unmount(&ef);
+ return 1;
+ }
+
+ ret = attribute(&ef, node, add_flags, clear_flags);
+
+ exfat_put_node(&ef, node);
+ exfat_unmount(&ef);
+
+ return ret;
+}
# Autoconf source.
#
# Free exFAT implementation.
-# Copyright (C) 2010-2018 Andrew Nayenko
+# Copyright (C) 2010-2023 Andrew Nayenko
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
#
AC_INIT([Free exFAT implementation],
- [1.3.0],
+ [1.4.0],
[relan@users.noreply.github.com],
[exfat],
[https://github.com/relan/exfat])
AM_INIT_AUTOMAKE([1.11.2 -Wall -Werror foreign subdir-objects])
AC_PROG_CC
-AC_PROG_CC_C99
AC_PROG_RANLIB
AM_PROG_AR
AC_SYS_LARGEFILE
AC_DEFINE([USE_UBLIO], [1],
[Define if block devices are not supported.])
], [:])
-PKG_CHECK_MODULES([FUSE], [fuse])
+PKG_CHECK_MODULES([FUSE3], [fuse3],
+ [AC_DEFINE([FUSE_USE_VERSION], [30], [Required FUSE API version.])],
+ [PKG_CHECK_MODULES([FUSE2], [fuse >= 2.6],
+ [AC_DEFINE([FUSE_USE_VERSION], [26], [Required FUSE API version.])])])
case "$host_os" in
*-gnu)
AC_DEFINE([_XOPEN_SOURCE], [500], [Enable pread() and pwrite().])
AC_CONFIG_HEADERS([libexfat/config.h])
AC_CONFIG_FILES([
libexfat/Makefile
+ attrib/Makefile
dump/Makefile
fsck/Makefile
fuse/Makefile
# Automake source.
#
# Free exFAT implementation.
-# Copyright (C) 2011-2018 Andrew Nayenko
+# Copyright (C) 2011-2023 Andrew Nayenko
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
-.\" Copyright (C) 2011-2018 Andrew Nayenko
+.\" Copyright (C) 2011-2023 Andrew Nayenko
.\"
.TH DUMPEXFAT 8 "July 2016"
.SH NAME
Prints detailed information about exFAT volume.
Free exFAT implementation.
- Copyright (C) 2011-2018 Andrew Nayenko
+ Copyright (C) 2011-2023 Andrew Nayenko
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
break;
case 'V':
printf("dumpexfat %s\n", VERSION);
- puts("Copyright (C) 2011-2018 Andrew Nayenko");
+ puts("Copyright (C) 2011-2023 Andrew Nayenko");
return 0;
default:
usage(argv[0]);
# Automake source.
#
# Free exFAT implementation.
-# Copyright (C) 2011-2018 Andrew Nayenko
+# Copyright (C) 2011-2023 Andrew Nayenko
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
-.\" Copyright (C) 2011-2018 Andrew Nayenko
+.\" Copyright (C) 2011-2023 Andrew Nayenko
.\"
.TH EXFATFSCK 8 "September 2018"
.SH NAME
exFAT file system checker.
Free exFAT implementation.
- Copyright (C) 2011-2018 Andrew Nayenko
+ Copyright (C) 2011-2023 Andrew Nayenko
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
#include <string.h>
#include <inttypes.h>
#include <unistd.h>
+#include <errno.h>
#define exfat_debug(format, ...) do {} while (0)
free(entry_path);
}
-static void fsck(struct exfat* ef, const char* spec, const char* options)
+static bool fsck(struct exfat* ef, const char* spec, const char* options)
{
- if (exfat_mount(ef, spec, options) != 0)
+ int rc;
+
+ rc = exfat_mount(ef, spec, options);
+ if (rc == -ENODEV)
+ return false; /* failed to open the device, checking haven't started */
+ if (rc != 0)
{
fputs("File system checking stopped. ", stdout);
- return;
+ return true;
}
exfat_print_info(ef->sb, exfat_count_free_clusters(ef));
printf("Totally %"PRIu64" directories and %"PRIu64" files.\n",
directories_count, files_count);
fputs("File system checking finished. ", stdout);
+ return true;
}
static void usage(const char* prog)
options = "repair=0,ro";
break;
case 'V':
- puts("Copyright (C) 2011-2018 Andrew Nayenko");
+ puts("Copyright (C) 2011-2023 Andrew Nayenko");
return 0;
default:
usage(argv[0]);
spec = argv[optind];
printf("Checking file system on %s.\n", spec);
- fsck(&ef, spec, options);
+ if (!fsck(&ef, spec, options))
+ return 1;
if (exfat_errors != 0)
{
printf("ERRORS FOUND: %d, FIXED: %d.\n",
# Automake source.
#
# Free exFAT implementation.
-# Copyright (C) 2010-2018 Andrew Nayenko
+# Copyright (C) 2010-2023 Andrew Nayenko
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
dist_man8_MANS = mount.exfat-fuse.8
mount_exfat_fuse_SOURCES = main.c
mount_exfat_fuse_CPPFLAGS = -I$(top_srcdir)/libexfat
-mount_exfat_fuse_CFLAGS = $(FUSE_CFLAGS)
-mount_exfat_fuse_LDADD = ../libexfat/libexfat.a $(FUSE_LIBS)
+mount_exfat_fuse_CFLAGS = $(FUSE2_CFLAGS) $(FUSE3_CFLAGS)
+mount_exfat_fuse_LDADD = ../libexfat/libexfat.a $(FUSE2_LIBS) $(FUSE3_LIBS)
install-exec-hook:
ln -sf $(sbin_PROGRAMS) $(DESTDIR)$(sbindir)/mount.exfat
FUSE-based exFAT implementation. Requires FUSE 2.6 or later.
Free exFAT implementation.
- Copyright (C) 2010-2018 Andrew Nayenko
+ Copyright (C) 2010-2023 Andrew Nayenko
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
*/
#include <exfat.h>
-#define FUSE_USE_VERSION 26
#include <fuse.h>
#include <errno.h>
#include <fcntl.h>
fi->keep_cache = 1;
}
-static int fuse_exfat_getattr(const char* path, struct stat* stbuf)
+static int fuse_exfat_getattr(const char* path, struct stat* stbuf
+#if FUSE_USE_VERSION >= 30
+ , UNUSED struct fuse_file_info* fi
+#endif
+ )
{
struct exfat_node* node;
int rc;
return 0;
}
-static int fuse_exfat_truncate(const char* path, off_t size)
+static int fuse_exfat_truncate(const char* path, off_t size
+#if FUSE_USE_VERSION >= 30
+ , UNUSED struct fuse_file_info* fi
+#endif
+ )
{
struct exfat_node* node;
int rc;
static int fuse_exfat_readdir(const char* path, void* buffer,
fuse_fill_dir_t filler, UNUSED off_t offset,
- UNUSED struct fuse_file_info* fi)
+ UNUSED struct fuse_file_info* fi
+#if FUSE_USE_VERSION >= 30
+ , UNUSED enum fuse_readdir_flags flags
+#endif
+ )
{
struct exfat_node* parent;
struct exfat_node* node;
return -ENOTDIR;
}
+#if FUSE_USE_VERSION < 30
filler(buffer, ".", NULL, 0);
filler(buffer, "..", NULL, 0);
+#else
+ filler(buffer, ".", NULL, 0, 0);
+ filler(buffer, "..", NULL, 0, 0);
+#endif
rc = exfat_opendir(&ef, parent, &it);
if (rc != 0)
name, node->is_contiguous ? "contiguous" : "fragmented",
node->size, node->start_cluster);
exfat_stat(&ef, node, &stbuf);
+#if FUSE_USE_VERSION < 30
filler(buffer, name, &stbuf, 0);
+#else
+ filler(buffer, name, &stbuf, 0, 0);
+#endif
exfat_put_node(&ef, node);
}
exfat_closedir(&ef, &it);
struct exfat_node* node;
int rc;
- exfat_debug("[%s] %s", __func__, path);
+ exfat_debug("[%s] %s flags %#x%s%s%s%s%s", __func__, path, fi->flags,
+ fi->flags & O_RDONLY ? " O_RDONLY" : "",
+ fi->flags & O_WRONLY ? " O_WRONLY" : "",
+ fi->flags & O_RDWR ? " O_RDWR" : "",
+ fi->flags & O_APPEND ? " O_APPEND" : "",
+ fi->flags & O_TRUNC ? " O_TRUNC" : "");
rc = exfat_lookup(&ef, &node, path);
if (rc != 0)
return rc;
+ /* FUSE 2.x will call fuse_exfat_truncate() explicitly */
+#if FUSE_USE_VERSION >= 30
+ if (fi->flags & O_TRUNC)
+ {
+ rc = exfat_truncate(&ef, node, 0, true);
+ if (rc != 0)
+ {
+ exfat_put_node(&ef, node);
+ return rc;
+ }
+ }
+#endif
set_node(fi, node);
return 0;
}
This handler may be called by FUSE on close() syscall. FUSE also deals
with removals of open files, so we don't free clusters on close but
only on rmdir and unlink. If the FUSE implementation does not call this
- handler we will flush node on release. See fuse_exfat_relase() above.
+ handler we will flush node on release. See fuse_exfat_release() above.
*/
exfat_debug("[%s] %s", __func__, path);
return exfat_flush_node(&ef, get_node(fi));
}
static int fuse_exfat_fsync(UNUSED const char* path, UNUSED int datasync,
- UNUSED struct fuse_file_info *fi)
+ UNUSED struct fuse_file_info* fi)
{
int rc;
return exfat_mkdir(&ef, path);
}
-static int fuse_exfat_rename(const char* old_path, const char* new_path)
+static int fuse_exfat_rename(const char* old_path, const char* new_path
+#if FUSE_USE_VERSION >= 30
+ , UNUSED unsigned int flags
+#endif
+ )
{
exfat_debug("[%s] %s => %s", __func__, old_path, new_path);
return exfat_rename(&ef, old_path, new_path);
}
-static int fuse_exfat_utimens(const char* path, const struct timespec tv[2])
+static int fuse_exfat_utimens(const char* path, const struct timespec tv[2]
+#if FUSE_USE_VERSION >= 30
+ , UNUSED struct fuse_file_info* fi
+#endif
+ )
{
struct exfat_node* node;
int rc;
return rc;
}
-static int fuse_exfat_chmod(UNUSED const char* path, mode_t mode)
+static int fuse_exfat_chmod(UNUSED const char* path, mode_t mode
+#if FUSE_USE_VERSION >= 30
+ , UNUSED struct fuse_file_info* fi
+#endif
+ )
{
const mode_t VALID_MODE_MASK = S_IFREG | S_IFDIR |
S_IRWXU | S_IRWXG | S_IRWXO;
return 0;
}
-static int fuse_exfat_chown(UNUSED const char* path, uid_t uid, gid_t gid)
+static int fuse_exfat_chown(UNUSED const char* path, uid_t uid, gid_t gid
+#if FUSE_USE_VERSION >= 30
+ , UNUSED struct fuse_file_info* fi
+#endif
+ )
{
exfat_debug("[%s] %s %u:%u", __func__, path, uid, gid);
if (uid != ef.uid || gid != ef.gid)
return 0;
}
-static void* fuse_exfat_init(struct fuse_conn_info* fci)
+static void* fuse_exfat_init(
+#ifdef FUSE_CAP_BIG_WRITES
+ struct fuse_conn_info* fci
+#else
+ UNUSED struct fuse_conn_info* fci
+#endif
+#if FUSE_USE_VERSION >= 30
+ , UNUSED struct fuse_config* cfg
+#endif
+ )
{
exfat_debug("[%s]", __func__);
#ifdef FUSE_CAP_BIG_WRITES
int opt;
int rc;
- printf("FUSE exfat %s\n", VERSION);
+ printf("FUSE exfat %s (libfuse%d)\n", VERSION, FUSE_USE_VERSION / 10);
fuse_options = strdup("allow_other,"
-#if defined(__linux__) || defined(__FreeBSD__)
+#if FUSE_USE_VERSION < 30 && (defined(__linux__) || defined(__FreeBSD__))
"big_writes,"
#endif
#if defined(__linux__)
case 'V':
free(exfat_options);
free(fuse_options);
- puts("Copyright (C) 2010-2018 Andrew Nayenko");
+ puts("Copyright (C) 2010-2023 Andrew Nayenko");
return 0;
case 'v':
break;
-.\" Copyright (C) 2010-2016 Andrew Nayenko
+.\" Copyright (C) 2010-2023 Andrew Nayenko
.\"
.TH EXFAT-FUSE 8 "November 2015"
.SH NAME
# Automake source.
#
# Free exFAT implementation.
-# Copyright (C) 2011-2018 Andrew Nayenko
+# Copyright (C) 2011-2023 Andrew Nayenko
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
-.\" Copyright (C) 2011-2018 Andrew Nayenko
+.\" Copyright (C) 2011-2023 Andrew Nayenko
.\"
.TH EXFATLABEL 8 "September 2017"
.SH NAME
Prints or changes exFAT volume label.
Free exFAT implementation.
- Copyright (C) 2011-2018 Andrew Nayenko
+ Copyright (C) 2011-2023 Andrew Nayenko
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
if (strcmp(*pp, "-V") == 0)
{
printf("exfatlabel %s\n", VERSION);
- puts("Copyright (C) 2011-2018 Andrew Nayenko");
+ puts("Copyright (C) 2011-2023 Andrew Nayenko");
return 0;
}
# Automake source.
#
# Free exFAT implementation.
-# Copyright (C) 2010-2018 Andrew Nayenko
+# Copyright (C) 2010-2023 Andrew Nayenko
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
Endianness stuff. exFAT uses little-endian byte order.
Free exFAT implementation.
- Copyright (C) 2010-2018 Andrew Nayenko
+ Copyright (C) 2010-2023 Andrew Nayenko
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
exFAT file system implementation library.
Free exFAT implementation.
- Copyright (C) 2010-2018 Andrew Nayenko
+ Copyright (C) 2010-2023 Andrew Nayenko
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
if (erase)
{
- rc = erase_range(ef, node, node->size, size);
+ rc = erase_range(ef, node, node->valid_size, size);
if (rc != 0)
return rc;
+ node->valid_size = size;
+ }
+ else
+ {
+ node->valid_size = MIN(node->valid_size, size);
}
exfat_update_mtime(node);
showstopper.
Free exFAT implementation.
- Copyright (C) 2010-2018 Andrew Nayenko
+ Copyright (C) 2010-2023 Andrew Nayenko
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
implementation.
Free exFAT implementation.
- Copyright (C) 2010-2018 Andrew Nayenko
+ Copyright (C) 2010-2023 Andrew Nayenko
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
bool is_cached : 1;
bool is_dirty : 1;
bool is_unlinked : 1;
+ uint64_t valid_size;
uint64_t size;
time_t mtime, atime;
le16_t name[EXFAT_NAME_MAX + 1];
Definitions of structures and constants used in exFAT file system.
Free exFAT implementation.
- Copyright (C) 2010-2018 Andrew Nayenko
+ Copyright (C) 2010-2023 Andrew Nayenko
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
exFAT file system implementation library.
Free exFAT implementation.
- Copyright (C) 2010-2018 Andrew Nayenko
+ Copyright (C) 2010-2023 Andrew Nayenko
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
ssize_t exfat_generic_pread(const struct exfat* ef, struct exfat_node* node,
void* buffer, size_t size, off_t offset)
{
- uint64_t newsize = offset;
+ uint64_t uoffset = offset;
cluster_t cluster;
char* bufp = buffer;
off_t lsize, loffset, remainder;
if (offset < 0)
return -EINVAL;
- if (newsize >= node->size)
+ if (uoffset >= node->size)
return 0;
if (size == 0)
return 0;
- cluster = exfat_advance_cluster(ef, node, newsize / CLUSTER_SIZE(*ef->sb));
+ if (uoffset + size > node->valid_size)
+ {
+ ssize_t bytes = 0;
+
+ if (uoffset < node->valid_size)
+ {
+ bytes = exfat_generic_pread(ef, node, buffer,
+ node->valid_size - uoffset, offset);
+ if (bytes < 0 || (size_t) bytes < node->valid_size - uoffset)
+ return bytes;
+ }
+ memset(buffer + bytes, 0,
+ MIN(size - bytes, node->size - node->valid_size));
+ return MIN(size, node->size - uoffset);
+ }
+
+ cluster = exfat_advance_cluster(ef, node, uoffset / CLUSTER_SIZE(*ef->sb));
if (CLUSTER_INVALID(*ef->sb, cluster))
{
exfat_error("invalid cluster 0x%x while reading", cluster);
return -EIO;
}
- loffset = newsize % CLUSTER_SIZE(*ef->sb);
- remainder = MIN(size, node->size - newsize);
+ loffset = uoffset % CLUSTER_SIZE(*ef->sb);
+ remainder = MIN(size, node->size - uoffset);
while (remainder > 0)
{
if (CLUSTER_INVALID(*ef->sb, cluster))
}
if (!(node->attrib & EXFAT_ATTRIB_DIR) && !ef->ro && !ef->noatime)
exfat_update_atime(node);
- return MIN(size, node->size - newsize) - remainder;
+ return MIN(size, node->size - uoffset) - remainder;
}
ssize_t exfat_generic_pwrite(struct exfat* ef, struct exfat_node* node,
const void* buffer, size_t size, off_t offset)
{
- uint64_t newsize = offset;
+ uint64_t uoffset = offset;
int rc;
cluster_t cluster;
const char* bufp = buffer;
if (offset < 0)
return -EINVAL;
- if (newsize > node->size)
+ if (uoffset > node->size)
{
- rc = exfat_truncate(ef, node, newsize, true);
+ rc = exfat_truncate(ef, node, uoffset, true);
if (rc != 0)
return rc;
}
- if (newsize + size > node->size)
+ if (uoffset + size > node->size)
{
- rc = exfat_truncate(ef, node, newsize + size, false);
+ rc = exfat_truncate(ef, node, uoffset + size, false);
if (rc != 0)
return rc;
}
if (size == 0)
return 0;
- cluster = exfat_advance_cluster(ef, node, newsize / CLUSTER_SIZE(*ef->sb));
+ cluster = exfat_advance_cluster(ef, node, uoffset / CLUSTER_SIZE(*ef->sb));
if (CLUSTER_INVALID(*ef->sb, cluster))
{
exfat_error("invalid cluster 0x%x while writing", cluster);
return -EIO;
}
- loffset = newsize % CLUSTER_SIZE(*ef->sb);
+ loffset = uoffset % CLUSTER_SIZE(*ef->sb);
remainder = size;
while (remainder > 0)
{
bufp += lsize;
loffset = 0;
remainder -= lsize;
+ node->valid_size = MAX(node->valid_size, uoffset + size - remainder);
cluster = exfat_next_cluster(ef, node, cluster);
}
if (!(node->attrib & EXFAT_ATTRIB_DIR))
exFAT file system implementation library.
Free exFAT implementation.
- Copyright (C) 2010-2018 Andrew Nayenko
+ Copyright (C) 2010-2023 Andrew Nayenko
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
exFAT file system implementation library.
Free exFAT implementation.
- Copyright (C) 2010-2018 Andrew Nayenko
+ Copyright (C) 2010-2023 Andrew Nayenko
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
exFAT file system implementation library.
Free exFAT implementation.
- Copyright (C) 2010-2018 Andrew Nayenko
+ Copyright (C) 2010-2023 Andrew Nayenko
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
mode = EXFAT_MODE_RW;
ef->dev = exfat_open(spec, mode);
if (ef->dev == NULL)
- return -EIO;
+ return -ENODEV;
if (exfat_get_mode(ef->dev) == EXFAT_MODE_RO)
{
if (mode == EXFAT_MODE_ANY)
ef->root->start_cluster = le32_to_cpu(ef->sb->rootdir_cluster);
ef->root->fptr_cluster = ef->root->start_cluster;
ef->root->name[0] = cpu_to_le16('\0');
- ef->root->size = rootdir_size(ef);
+ ef->root->valid_size = ef->root->size = rootdir_size(ef);
if (ef->root->size == 0)
{
exfat_free(ef);
exFAT file system implementation library.
Free exFAT implementation.
- Copyright (C) 2010-2018 Andrew Nayenko
+ Copyright (C) 2010-2023 Andrew Nayenko
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
static void init_node_meta2(struct exfat_node* node,
const struct exfat_entry_meta2* meta2)
{
+ node->valid_size = le64_to_cpu(meta2->valid_size);
node->size = le64_to_cpu(meta2->size);
node->start_cluster = le32_to_cpu(meta2->start_cluster);
node->fptr_cluster = node->start_cluster;
}
static bool check_node(const struct exfat* ef, struct exfat_node* node,
- le16_t actual_checksum, const struct exfat_entry_meta1* meta1,
- const struct exfat_entry_meta2* meta2)
+ le16_t actual_checksum, const struct exfat_entry_meta1* meta1)
{
int cluster_size = CLUSTER_SIZE(*ef->sb);
uint64_t clusters_heap_size =
cannot be greater than file size. See SetFileValidData() function
description in MSDN.
*/
- if (le64_to_cpu(meta2->valid_size) > node->size)
+ if (node->valid_size > node->size)
{
exfat_get_name(node, buffer);
exfat_error("'%s' has valid size (%"PRIu64") greater than size "
- "(%"PRIu64")", buffer, le64_to_cpu(meta2->valid_size),
- node->size);
+ "(%"PRIu64")", buffer, node->valid_size, node->size);
ret = false;
}
init_node_meta2(node, meta2);
init_node_name(node, entries + 2, mandatory_entries - 2);
- if (!check_node(ef, node, exfat_calc_checksum(entries, n), meta1, meta2))
+ if (!check_node(ef, node, exfat_calc_checksum(entries, n), meta1))
return -EIO;
return 0;
NULL, &meta1->atime_tzo);
meta1->adate = edate;
meta1->atime = etime;
- meta2->size = meta2->valid_size = cpu_to_le64(node->size);
+ meta2->valid_size = cpu_to_le64(node->valid_size);
+ meta2->size = cpu_to_le64(node->size);
meta2->start_cluster = cpu_to_le32(node->start_cluster);
meta2->flags = EXFAT_FLAG_ALWAYS1;
/* empty files must not be marked as contiguous */
exfat_put_node(ef, existing);
if (rc != 0)
{
- /* free clusters even if something went wrong; overwise they
+ /* free clusters even if something went wrong; otherwise they
will be just lost */
exfat_cleanup_node(ef, existing);
exfat_put_node(ef, dir);
same kernel can use different libc implementations.
Free exFAT implementation.
- Copyright (C) 2010-2018 Andrew Nayenko
+ Copyright (C) 2010-2023 Andrew Nayenko
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
exFAT file system implementation library.
Free exFAT implementation.
- Copyright (C) 2010-2018 Andrew Nayenko
+ Copyright (C) 2010-2023 Andrew Nayenko
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
exFAT file system implementation library.
Free exFAT implementation.
- Copyright (C) 2010-2018 Andrew Nayenko
+ Copyright (C) 2010-2023 Andrew Nayenko
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
exFAT file system implementation library.
Free exFAT implementation.
- Copyright (C) 2010-2018 Andrew Nayenko
+ Copyright (C) 2010-2023 Andrew Nayenko
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
exFAT file system implementation library.
Free exFAT implementation.
- Copyright (C) 2010-2018 Andrew Nayenko
+ Copyright (C) 2010-2023 Andrew Nayenko
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
# Automake source.
#
# Free exFAT implementation.
-# Copyright (C) 2011-2018 Andrew Nayenko
+# Copyright (C) 2011-2023 Andrew Nayenko
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
Clusters Bitmap creation code.
Free exFAT implementation.
- Copyright (C) 2011-2018 Andrew Nayenko
+ Copyright (C) 2011-2023 Andrew Nayenko
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
Clusters Bitmap creation code.
Free exFAT implementation.
- Copyright (C) 2011-2018 Andrew Nayenko
+ Copyright (C) 2011-2023 Andrew Nayenko
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
File Allocation Table creation code.
Free exFAT implementation.
- Copyright (C) 2011-2018 Andrew Nayenko
+ Copyright (C) 2011-2023 Andrew Nayenko
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
File Allocation Table creation code.
Free exFAT implementation.
- Copyright (C) 2011-2018 Andrew Nayenko
+ Copyright (C) 2011-2023 Andrew Nayenko
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
Creates exFAT file system.
Free exFAT implementation.
- Copyright (C) 2011-2018 Andrew Nayenko
+ Copyright (C) 2011-2023 Andrew Nayenko
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
}
break;
case 'V':
- puts("Copyright (C) 2011-2018 Andrew Nayenko");
+ puts("Copyright (C) 2011-2023 Andrew Nayenko");
return 0;
default:
usage(argv[0]);
FS creation engine.
Free exFAT implementation.
- Copyright (C) 2011-2018 Andrew Nayenko
+ Copyright (C) 2011-2023 Andrew Nayenko
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
FS creation engine.
Free exFAT implementation.
- Copyright (C) 2011-2018 Andrew Nayenko
+ Copyright (C) 2011-2023 Andrew Nayenko
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
-.\" Copyright (C) 2011-2018 Andrew Nayenko
+.\" Copyright (C) 2011-2023 Andrew Nayenko
.\"
.TH MKEXFATFS 8 "January 2014"
.SH NAME
Root directory creation code.
Free exFAT implementation.
- Copyright (C) 2011-2018 Andrew Nayenko
+ Copyright (C) 2011-2023 Andrew Nayenko
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
Root directory creation code.
Free exFAT implementation.
- Copyright (C) 2011-2018 Andrew Nayenko
+ Copyright (C) 2011-2023 Andrew Nayenko
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
Upper Case Table creation code.
Free exFAT implementation.
- Copyright (C) 2011-2018 Andrew Nayenko
+ Copyright (C) 2011-2023 Andrew Nayenko
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
Upper Case Table creation code.
Free exFAT implementation.
- Copyright (C) 2011-2018 Andrew Nayenko
+ Copyright (C) 2011-2023 Andrew Nayenko
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
Upper Case Table contents.
Free exFAT implementation.
- Copyright (C) 2011-2018 Andrew Nayenko
+ Copyright (C) 2011-2023 Andrew Nayenko
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
Upper Case Table declaration.
Free exFAT implementation.
- Copyright (C) 2011-2018 Andrew Nayenko
+ Copyright (C) 2011-2023 Andrew Nayenko
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
Volume Boot Record creation code.
Free exFAT implementation.
- Copyright (C) 2011-2018 Andrew Nayenko
+ Copyright (C) 2011-2023 Andrew Nayenko
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
Volume Boot Record creation code.
Free exFAT implementation.
- Copyright (C) 2011-2018 Andrew Nayenko
+ Copyright (C) 2011-2023 Andrew Nayenko
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by