From 0a7a8b470671035ad0c2d8dc0d7714d06921273d Mon Sep 17 00:00:00 2001 From: Sven Hoexter Date: Tue, 23 May 2023 13:59:09 +0200 Subject: [PATCH] New upstream version 1.2.1 --- Makefile.in | 2 +- NEWS | 7 ++++++ configure | 20 ++++++++--------- exfat2img/exfat2img.c | 2 +- fsck/fsck.c | 50 ++++++++++++++++++++++++++++++++++++++---- fsck/repair.c | 1 + fsck/repair.h | 2 +- include/exfat_dir.h | 1 + include/libexfat.h.rej | 9 -------- include/version.h | 2 +- include/version.h.rej | 9 -------- lib/exfat_dir.c | 7 +++--- lib/libexfat.c | 4 ++-- manpages/fsck.exfat.8 | 2 +- 14 files changed, 76 insertions(+), 42 deletions(-) delete mode 100644 include/libexfat.h.rej delete mode 100644 include/version.h.rej diff --git a/Makefile.in b/Makefile.in index 76de3b7..e1c0b64 100644 --- a/Makefile.in +++ b/Makefile.in @@ -198,7 +198,7 @@ am__DIST_COMMON = $(dist_man8_MANS) $(srcdir)/Makefile.in \ $(top_srcdir)/build-aux/install-sh \ $(top_srcdir)/build-aux/ltmain.sh \ $(top_srcdir)/build-aux/missing COPYING NEWS build-aux/compile \ - build-aux/config.guess build-aux/config.sub build-aux/depcomp \ + build-aux/config.guess build-aux/config.sub \ build-aux/install-sh build-aux/ltmain.sh build-aux/missing DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) distdir = $(PACKAGE)-$(VERSION) diff --git a/NEWS b/NEWS index f845397..f371d62 100644 --- a/NEWS +++ b/NEWS @@ -1,3 +1,10 @@ +exfatprogs 1.2.1 - released 2023-05-17 +====================================== + +CHANGES : + * fsck.exfat: Repair zero size directory. + * fsck.exfat: Four small clean-ups. + exfatprogs 1.2.0 - released 2022-10-28 ====================================== diff --git a/configure b/configure index 436be7a..c2938e9 100755 --- a/configure +++ b/configure @@ -1,6 +1,6 @@ #! /bin/sh # Guess values for system-dependent variables and create Makefiles. -# Generated by GNU Autoconf 2.69 for exfatprogs 1.2.0. +# Generated by GNU Autoconf 2.69 for exfatprogs 1.2.1. # # Report bugs to . # @@ -590,8 +590,8 @@ MAKEFLAGS= # Identity of this package. PACKAGE_NAME='exfatprogs' PACKAGE_TARNAME='exfatprogs' -PACKAGE_VERSION='1.2.0' -PACKAGE_STRING='exfatprogs 1.2.0' +PACKAGE_VERSION='1.2.1' +PACKAGE_STRING='exfatprogs 1.2.1' PACKAGE_BUGREPORT='linkinjeon@kernel.org' PACKAGE_URL='https://github.com/exfatprogs/exfatprogs' @@ -1325,7 +1325,7 @@ if test "$ac_init_help" = "long"; then # Omit some internal or obsolete options to make the list less imposing. # This message is too long to be a string in the A/UX 3.1 sh. cat <<_ACEOF -\`configure' configures exfatprogs 1.2.0 to adapt to many kinds of systems. +\`configure' configures exfatprogs 1.2.1 to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... @@ -1396,7 +1396,7 @@ fi if test -n "$ac_init_help"; then case $ac_init_help in - short | recursive ) echo "Configuration of exfatprogs 1.2.0:";; + short | recursive ) echo "Configuration of exfatprogs 1.2.1:";; esac cat <<\_ACEOF @@ -1508,7 +1508,7 @@ fi test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF -exfatprogs configure 1.2.0 +exfatprogs configure 1.2.1 generated by GNU Autoconf 2.69 Copyright (C) 2012 Free Software Foundation, Inc. @@ -1786,7 +1786,7 @@ cat >config.log <<_ACEOF This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. -It was created by exfatprogs $as_me 1.2.0, which was +It was created by exfatprogs $as_me 1.2.1, which was generated by GNU Autoconf 2.69. Invocation command line was $ $0 $@ @@ -2654,7 +2654,7 @@ fi # Define the identity of the package. PACKAGE='exfatprogs' - VERSION='1.2.0' + VERSION='1.2.1' cat >>confdefs.h <<_ACEOF @@ -13256,7 +13256,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # report actual input values of CONFIG_FILES etc. instead of their # values after options handling. ac_log=" -This file was extended by exfatprogs $as_me 1.2.0, which was +This file was extended by exfatprogs $as_me 1.2.1, which was generated by GNU Autoconf 2.69. Invocation command line was CONFIG_FILES = $CONFIG_FILES @@ -13323,7 +13323,7 @@ _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" ac_cs_version="\\ -exfatprogs config.status 1.2.0 +exfatprogs config.status 1.2.1 configured by $0, generated by GNU Autoconf 2.69, with options \\"\$ac_cs_config\\" diff --git a/exfat2img/exfat2img.c b/exfat2img/exfat2img.c index 81e86d2..be1f0f3 100644 --- a/exfat2img/exfat2img.c +++ b/exfat2img/exfat2img.c @@ -754,7 +754,7 @@ static ssize_t read_stream(int fd, void *buf, size_t len) } else if (ret == 0) { return 0; } - buf += (size_t)ret; + buf = (char *)buf + (size_t)ret; read_len += (size_t)ret; } return read_len; diff --git a/fsck/fsck.c b/fsck/fsck.c index 219d723..cd9ee9a 100644 --- a/fsck/fsck.c +++ b/fsck/fsck.c @@ -103,21 +103,31 @@ static void usage(char *name) }) static int check_clus_chain(struct exfat_de_iter *de_iter, - struct exfat_inode *node) + struct exfat_inode *node) { struct exfat *exfat = de_iter->exfat; struct exfat_dentry *stream_de; - clus_t clus, prev, next; + clus_t clus, prev, next, new_clus; uint64_t count, max_count; + int err; clus = node->first_clus; prev = EXFAT_EOF_CLUSTER; count = 0; max_count = DIV_ROUND_UP(node->size, exfat->clus_size); - if (node->size == 0 && node->first_clus == EXFAT_FREE_CLUSTER) + if (node->size == 0 && node->first_clus == EXFAT_FREE_CLUSTER) { + /* locate a cluster for the empty dir if the dir starts with EXFAT_FREE_CLUSTER */ + if (node->attr & ATTR_SUBDIR) { + if (repair_file_ask(de_iter, node, + ER_DE_FIRST_CLUS, + "size %#" PRIx64 ", but the first cluster %#x", + node->size, node->first_clus)) + goto allocate_cluster; + return -EINVAL; + } return 0; - + } /* the first cluster is wrong */ if ((node->size == 0 && node->first_clus != EXFAT_FREE_CLUSTER) || (node->size > 0 && !exfat_heap_clus(exfat, node->first_clus))) { @@ -215,6 +225,38 @@ static int check_clus_chain(struct exfat_de_iter *de_iter, } return 0; +allocate_cluster: + exfat_de_iter_get_dirty(de_iter, 1, &stream_de); + err = exfat_find_free_cluster(exfat, exfat->start_clu, &new_clus); + if (err) { + exfat->start_clu = EXFAT_FIRST_CLUSTER; + exfat_err("failed to find a free cluster\n"); + return -ENOSPC; + } + exfat->start_clu = new_clus; + + if (exfat_set_fat(exfat, new_clus, EXFAT_EOF_CLUSTER)) + return -EIO; + + /* zero out the new cluster */ + if (exfat_write(exfat->blk_dev->dev_fd, exfat->zero_cluster, + exfat->clus_size, exfat_c2o(exfat, new_clus)) != + (ssize_t)exfat->clus_size) { + exfat_err("failed to fill new cluster with zeroes\n"); + return -EIO; + } + + /* modify the number of cluster form 0 to 1 */ + count = 1; + stream_de->stream_start_clu = cpu_to_le32(new_clus); + stream_de->stream_size = cpu_to_le64(count * exfat->clus_size); + stream_de->stream_valid_size = cpu_to_le64(count * exfat->clus_size); + stream_de->dentry.stream.flags |= EXFAT_SF_CONTIGUOUS; + node->first_clus = new_clus; + node->size = count * exfat->clus_size; + node->is_contiguous = true; + exfat_bitmap_set(exfat->alloc_bitmap, new_clus); + return 1; truncate_file: node->size = count * exfat->clus_size; if (!exfat_heap_clus(exfat, prev)) diff --git a/fsck/repair.c b/fsck/repair.c index 92b1c3f..ab46f85 100644 --- a/fsck/repair.c +++ b/fsck/repair.c @@ -61,6 +61,7 @@ static struct exfat_repair_problem problems[] = { {ER_FILE_LARGER_SIZE, ERF_PREEN_YES, ERP_TRUNCATE, 0, 0, 0}, {ER_FILE_DUPLICATED_CLUS, ERF_PREEN_YES, ERP_TRUNCATE, 0, 0, 0}, {ER_FILE_ZERO_NOFAT, ERF_PREEN_YES, ERP_FIX, 0, 0, 0}, + {ER_DE_FIRST_CLUS, ERF_PREEN_YES, ERP_FIX, 0, 0, 0} }; static struct exfat_repair_problem *find_problem(er_problem_code_t prcode) diff --git a/fsck/repair.h b/fsck/repair.h index dc3cc50..ea89747 100644 --- a/fsck/repair.h +++ b/fsck/repair.h @@ -23,7 +23,7 @@ #define ER_FILE_LARGER_SIZE 0x00002005 #define ER_FILE_DUPLICATED_CLUS 0x00002006 #define ER_FILE_ZERO_NOFAT 0x00002007 - +#define ER_DE_FIRST_CLUS 0x00002008 typedef unsigned int er_problem_code_t; struct exfat_fsck; diff --git a/include/exfat_dir.h b/include/exfat_dir.h index 3bc5b51..12e1546 100644 --- a/include/exfat_dir.h +++ b/include/exfat_dir.h @@ -75,6 +75,7 @@ int exfat_update_file_dentry_set(struct exfat *exfat, int exfat_build_file_dentry_set(struct exfat *exfat, const char *name, unsigned short attr, struct exfat_dentry **dentry_set, int *dentry_count); +int exfat_find_free_cluster(struct exfat *exfat, clus_t start, clus_t *new_clu); int exfat_add_dentry_set(struct exfat *exfat, struct exfat_dentry_loc *loc, struct exfat_dentry *dset, int dcount, bool need_next_loc); diff --git a/include/libexfat.h.rej b/include/libexfat.h.rej deleted file mode 100644 index 63c0a8b..0000000 --- a/include/libexfat.h.rej +++ /dev/null @@ -1,9 +0,0 @@ -diff a/include/libexfat.h b/include/libexfat.h (rejected hunks) -@@ -35,6 +35,7 @@ - #define VOLUME_LABEL_BUFFER_SIZE (VOLUME_LABEL_MAX_LEN*MB_LEN_MAX+1) - - /* Upcase tabel macro */ -+#define EXFAT_UPCASE_TABLE_CHARS (0x10000) - #define EXFAT_UPCASE_TABLE_SIZE (5836) - - /* Flags for tune.exfat and exfatlabel */ diff --git a/include/version.h b/include/version.h index b0348d6..f0b250c 100644 --- a/include/version.h +++ b/include/version.h @@ -5,6 +5,6 @@ #ifndef _VERSION_H -#define EXFAT_PROGS_VERSION "1.2.0" +#define EXFAT_PROGS_VERSION "1.2.1" #endif /* !_VERSION_H */ diff --git a/include/version.h.rej b/include/version.h.rej deleted file mode 100644 index e7c2573..0000000 --- a/include/version.h.rej +++ /dev/null @@ -1,9 +0,0 @@ -diff a/include/version.h b/include/version.h (rejected hunks) -@@ -6,6 +6,6 @@ - #ifndef _VERSION_H - - #define EXFAT_PROGS_VERSION "1.1.2" --#define WEBOS_EXFAT_PROGS_VERSION "webos-1.1.2-8" -+#define WEBOS_EXFAT_PROGS_VERSION "webos-1.1.2-9" - - #endif /* !_VERSION_H */ diff --git a/lib/exfat_dir.c b/lib/exfat_dir.c index 499b672..7c145f4 100644 --- a/lib/exfat_dir.c +++ b/lib/exfat_dir.c @@ -35,10 +35,11 @@ static ssize_t write_block(struct exfat_de_iter *iter, unsigned int block) unsigned int i; desc = &iter->buffer_desc[block & 0x01]; - device_offset = exfat_c2o(exfat, desc->p_clus) + desc->offset; for (i = 0; i < iter->read_size / iter->write_size; i++) { if (desc->dirty[i]) { + device_offset = exfat_c2o(exfat, desc->p_clus) + + desc->offset; if (exfat_write(exfat->blk_dev->dev_fd, desc->buffer + i * iter->write_size, iter->write_size, @@ -677,7 +678,7 @@ int exfat_update_file_dentry_set(struct exfat *exfat, return 0; } -static int find_free_cluster(struct exfat *exfat, +int exfat_find_free_cluster(struct exfat *exfat, clus_t start, clus_t *new_clu) { clus_t end = le32_to_cpu(exfat->bs->bsx.clu_count) + @@ -804,7 +805,7 @@ static int exfat_alloc_cluster(struct exfat *exfat, struct exfat_inode *inode, if ((need_dset && !inode->dentry_set) || inode->is_contiguous) return -EINVAL; - err = find_free_cluster(exfat, exfat->start_clu, new_clu); + err = exfat_find_free_cluster(exfat, exfat->start_clu, new_clu); if (err) { exfat->start_clu = EXFAT_FIRST_CLUSTER; exfat_err("failed to find an free cluster\n"); diff --git a/lib/libexfat.c b/lib/libexfat.c index d7c1df1..4fd4ac6 100644 --- a/lib/libexfat.c +++ b/lib/libexfat.c @@ -15,6 +15,7 @@ #include #include #include +#include #include "exfat_ondisk.h" #include "libexfat.h" @@ -748,8 +749,7 @@ off_t exfat_s2o(struct exfat *exfat, off_t sect) off_t exfat_c2o(struct exfat *exfat, unsigned int clus) { - if (clus < EXFAT_FIRST_CLUSTER) - return ~0L; + assert(clus >= EXFAT_FIRST_CLUSTER); return exfat_s2o(exfat, le32_to_cpu(exfat->bs->bsx.clu_offset) + ((off_t)(clus - EXFAT_FIRST_CLUSTER) << diff --git a/manpages/fsck.exfat.8 b/manpages/fsck.exfat.8 index 3b247d5..5faecf0 100644 --- a/manpages/fsck.exfat.8 +++ b/manpages/fsck.exfat.8 @@ -42,7 +42,7 @@ Files share the same cluster. Cluster chains for files except one are broken. .IP - Start cluster number is invalid. The cluster number and file size are changed to 0. .IP - -Checksum value of direcotry entry set is invalid. Directory entry set is deleted. +Checksum value of directory entry set is invalid. Directory entry set is deleted. .IP - Bad hash value of a file name. The hash value is changed properly. .IP - -- 2.39.2