Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package exfatprogs for openSUSE:Factory checked in at 2026-01-21 14:11:44 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/exfatprogs (Old) and /work/SRC/openSUSE:Factory/.exfatprogs.new.1928 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "exfatprogs" Wed Jan 21 14:11:44 2026 rev:22 rq:1328191 version:1.3.1 Changes: -------- --- /work/SRC/openSUSE:Factory/exfatprogs/exfatprogs.changes 2025-10-31 16:28:00.477757231 +0100 +++ /work/SRC/openSUSE:Factory/.exfatprogs.new.1928/exfatprogs.changes 2026-01-21 14:11:46.224866956 +0100 @@ -1,0 +2,12 @@ +Tue Jan 20 08:14:58 UTC 2026 - Michael Vetter <[email protected]> + +- Update to 1.3.1: + Features: + * fsck.exfat: support repairing the allocation bitmap size. + Changes: + * exfatprogs: temporarily disable building defrag.exfat due to reported + data loss. + Bug fixes: + * libexfat: fix a NULL pointer dereference in read_file_dentry_set(). + +------------------------------------------------------------------- Old: ---- 1.3.0.tar.gz New: ---- 1.3.1.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ exfatprogs.spec ++++++ --- /var/tmp/diff_new_pack.lRLNKG/_old 2026-01-21 14:11:47.036900763 +0100 +++ /var/tmp/diff_new_pack.lRLNKG/_new 2026-01-21 14:11:47.040900930 +0100 @@ -1,7 +1,7 @@ # # spec file for package exfatprogs # -# Copyright (c) 2025 SUSE LLC and contributors +# Copyright (c) 2026 SUSE LLC and contributors # # All modifications and additions to the file contributed by third parties # remain the property of their copyright owners, unless otherwise agreed @@ -17,7 +17,7 @@ Name: exfatprogs -Version: 1.3.0 +Version: 1.3.1 Release: 0 Summary: Utilities for exFAT file system maintenance License: GPL-2.0-or-later @@ -61,14 +61,12 @@ %license COPYING %doc README.md %{_mandir}/man8/dump.exfat.8%{?ext_man} -%{_mandir}/man8/defrag.exfat.8%{?ext_man} %{_mandir}/man8/exfatlabel.8%{?ext_man} %{_mandir}/man8/fsck.exfat.8%{?ext_man} %{_mandir}/man8/mkfs.exfat.8%{?ext_man} %{_mandir}/man8/tune.exfat.8%{?ext_man} %{_mandir}/man8/exfat2img.8%{?ext_man} %{_sbindir}/dump.exfat -%{_sbindir}/defrag.exfat %{_sbindir}/exfatlabel %{_sbindir}/fsck.exfat %{_sbindir}/mkfs.exfat ++++++ 1.3.0.tar.gz -> 1.3.1.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/exfatprogs-1.3.0/.gitignore new/exfatprogs-1.3.1/.gitignore --- old/exfatprogs-1.3.0/.gitignore 2025-10-15 05:03:42.000000000 +0200 +++ new/exfatprogs-1.3.1/.gitignore 2025-12-15 04:54:48.000000000 +0100 @@ -48,4 +48,3 @@ /label/exfatlabel /mkfs/mkfs.exfat /tune/tune.exfat -/defrag/defrag.exfat \ No newline at end of file diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/exfatprogs-1.3.0/Android.bp new/exfatprogs-1.3.1/Android.bp --- old/exfatprogs-1.3.0/Android.bp 2025-10-15 05:03:42.000000000 +0200 +++ new/exfatprogs-1.3.1/Android.bp 2025-12-15 04:54:48.000000000 +0100 @@ -10,7 +10,6 @@ "label", "dump", "exfat2img", - "defrag", ], } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/exfatprogs-1.3.0/Makefile.am new/exfatprogs-1.3.1/Makefile.am --- old/exfatprogs-1.3.0/Makefile.am 2025-10-15 05:03:42.000000000 +0200 +++ new/exfatprogs-1.3.1/Makefile.am 2025-12-15 04:54:48.000000000 +0100 @@ -2,7 +2,7 @@ ACLOCAL_AMFLAGS = -I m4 -SUBDIRS = lib mkfs fsck tune label dump exfat2img defrag +SUBDIRS = lib mkfs fsck tune label dump exfat2img # manpages dist_man8_MANS = \ @@ -11,8 +11,7 @@ manpages/mkfs.exfat.8 \ manpages/exfatlabel.8 \ manpages/dump.exfat.8 \ - manpages/exfat2img.8 \ - manpages/defrag.exfat.8 + manpages/exfat2img.8 # other stuff EXTRA_DIST = \ @@ -26,5 +25,4 @@ label/Android.bp \ dump/Android.bp \ exfat2img/Android.bp \ - defrag/Android.bp \ README.md diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/exfatprogs-1.3.0/NEWS new/exfatprogs-1.3.1/NEWS --- old/exfatprogs-1.3.0/NEWS 2025-10-15 05:03:42.000000000 +0200 +++ new/exfatprogs-1.3.1/NEWS 2025-12-15 04:54:48.000000000 +0100 @@ -1,3 +1,16 @@ +exfatprogs 1.3.1 - released 2025-12-15 +===================================== + +NEW FEATURES : + * fsck.exfat: support repairing the allocation bitmap size. + +CHANGES : + * exfatprogs: temporarily disable building defrag.exfat due to reported + data loss. + +BUG FIXES : + * libexfat: fix a NULL pointer dereference in read_file_dentry_set(). + exfatprogs 1.3.0 - released 2025-10-15 ====================================== diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/exfatprogs-1.3.0/README.md new/exfatprogs-1.3.1/README.md --- old/exfatprogs-1.3.0/README.md 2025-10-15 05:03:42.000000000 +0200 +++ new/exfatprogs-1.3.1/README.md 2025-12-15 04:54:48.000000000 +0100 @@ -96,15 +96,6 @@ Usage example: exfat2img -o sda1.dump /dev/sda1 -- defrag.exfat: - Defragment an exFAT-formatted device, or assess its fragmentation status. - -Usage examples: - 1. Defragment an exFAT-formatted device: - defrag.exfat /dev/sda1 - 2. Assess fragmentation status of an exFAT-formatted device: - defrag.exfat -a /dev/sda1 - ``` ## Benchmarks diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/exfatprogs-1.3.0/configure.ac new/exfatprogs-1.3.1/configure.ac --- old/exfatprogs-1.3.0/configure.ac 2025-10-15 05:03:42.000000000 +0200 +++ new/exfatprogs-1.3.1/configure.ac 2025-12-15 04:54:48.000000000 +0100 @@ -32,7 +32,6 @@ label/Makefile dump/Makefile exfat2img/Makefile - defrag/Makefile ]) AC_OUTPUT diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/exfatprogs-1.3.0/defrag/defrag.c new/exfatprogs-1.3.1/defrag/defrag.c --- old/exfatprogs-1.3.0/defrag/defrag.c 2025-10-15 05:03:42.000000000 +0200 +++ new/exfatprogs-1.3.1/defrag/defrag.c 2025-12-15 04:54:48.000000000 +0100 @@ -28,7 +28,7 @@ /*----------------------- Part 0: Signal Handling ---------------------*/ /* Global interrupt flag */ -static sig_atomic_t interrupt_received; +static volatile sig_atomic_t interrupt_received; /* Index at which interruption occurred */ static uint32_t interrupt_point; @@ -117,14 +117,14 @@ /* Perform read or write operation */ if (read) { rw_len = exfat_read(exfat->blk_dev->dev_fd, exfat->alloc_bitmap, - exfat->disk_bitmap_size, - exfat_c2o(exfat, exfat->disk_bitmap_clus)); + exfat->disk_bitmap_size, + exfat_c2o(exfat, exfat->disk_bitmap_clus)); if (rw_len != exfat->disk_bitmap_size) return -EIO; } else { rw_len = exfat_write(exfat->blk_dev->dev_fd, exfat->alloc_bitmap, - exfat->disk_bitmap_size, - exfat_c2o(exfat, exfat->disk_bitmap_clus)); + exfat->disk_bitmap_size, + exfat_c2o(exfat, exfat->disk_bitmap_clus)); if (rw_len != exfat->disk_bitmap_size) return -EIO; } @@ -210,7 +210,7 @@ * Sets FAT entries for a contiguous cluster chain to ensure correctness. */ static int set_physical_nodes(struct cluster_info_set *set, - uint32_t begin, uint32_t count, uint32_t data) + uint32_t begin, uint32_t count, uint32_t data) { uint32_t i; @@ -831,7 +831,8 @@ uint32_t scan_ptr = EXFAT_RESERVED_CLUSTERS, exchanged_ptr = 0; uint32_t i; - exfat_info("Defragmentation is in progress — please keep the device connected.\n"); + exfat_info("Defragmentation is in progress -- please keep the device connected.\n"); + exfat_info("WARNING: Removing or powering off the device during execution may corrupt the file system.\n"); exfat_info("If you do not want to wait, just press Ctrl+C to terminate it safely.\n"); for (i = n_clus; i < n_clus + n_file; i++) { @@ -896,7 +897,7 @@ /* 2. Assess free cluster contiguity */ last_clu = 0; for (cur_clu = EXFAT_FIRST_CLUSTER; cur_clu < exfat->clus_count + EXFAT_FIRST_CLUSTER; - cur_clu++) { + cur_clu++) { if (!exfat_bitmap_get(exfat->alloc_bitmap, cur_clu)) { num_free_clus++; if (last_clu != 0 && cur_clu != last_clu + 1) @@ -999,7 +1000,7 @@ break; default: exfat_err("Invalid command! Please refer to the help information below or consult the manual.\n"); - usage(argv[0], -1); + usage(argv[0], 2); } } @@ -1009,7 +1010,7 @@ if (optind != argc - 1) { exfat_err("Invalid command! Please refer to the help information below or consult the manual.\n"); - usage(argv[0], -1); + usage(argv[0], 2); } if ((!only_assessment) && show_fsck_warning) { @@ -1018,18 +1019,10 @@ exfat_info("Proceed without filesystem check? [y/N]: "); fflush(stdout); - while (1) { - c = fgetc(stdin); - if (c == 'Y' || c == 'y') { - exfat_info("\n"); - break; - } else if (c == 'N' || c == 'n') { - return 0; - } else if (c == '\n' || c == ' ' || c == '\t') { - continue; - } else { - exfat_info("Sorry, please enter 'Y' or 'y' or 'N' or 'n':"); - } + c = fgetc(stdin); + if (!(c == 'Y' || c == 'y')) { + exfat_info("Defrag aborted.\n"); + return 1; } } @@ -1041,7 +1034,7 @@ ui.writeable = true; if (exfat_get_blk_dev_info(&ui, &bd) < 0) { exfat_err("fail in exfat_get_blk_dev_info\n"); - ret = -1; + ret = 1; goto out; } @@ -1050,7 +1043,7 @@ defrag.exfat = exfat_alloc_exfat(&bd, NULL, NULL); if (defrag.exfat == NULL) { exfat_err("fail in exfat_alloc_exfat\n"); - ret = -1; + ret = 1; goto out; } @@ -1060,92 +1053,88 @@ set->next_clus = calloc(set->num_phys_clus, sizeof(uint32_t)); if (set->next_clus == NULL) { exfat_err("memory run out in defrag.cluster_info_set->next_clus\n"); - ret = -1; - goto fsycn_and_free; + ret = 1; + goto fsync_and_free; } defrag.tmp_clus = calloc(2, defrag.exfat->clus_size); if (defrag.tmp_clus == NULL) { exfat_err("memory run out in defrag.tmp_clus\n"); - ret = -1; - goto fsycn_and_free; + ret = 1; + goto fsync_and_free; } defrag.dentry_buffer = exfat_alloc_buffer(defrag.exfat); if (defrag.dentry_buffer == NULL) { exfat_err("memory run out in defrag.dentry_buffer\n"); - ret = -1; - goto fsycn_and_free; + ret = 1; + goto fsync_and_free; } /* Step 4: Read bitmap and FAT */ if (exfat_rw_bitmap(defrag.exfat, true) < 0) { exfat_err("fail in exfat_read_bitmap\n"); - ret = -1; - goto fsycn_and_free; + ret = 1; + goto fsync_and_free; } if (exfat_rw_FAT(defrag.exfat, set->next_clus, set->num_phys_clus, true) < 0) { exfat_err("fail in exfat_read_FAT\n"); - ret = -1; - goto fsycn_and_free; + ret = 1; + goto fsync_and_free; } /* Step 5: Traverse file tree (BFS), collect first cluster info into virtual nodes */ if (BFS_read_file_tree(&defrag) < 0) { exfat_err("fail in BFS_read_file_tree\n"); - ret = -1; - goto fsycn_and_free; + ret = 1; + goto fsync_and_free; } /* For fragmentation assessment, reaching this step is sufficient */ if (only_assessment) { exfat_defrag_assess(&defrag); - goto fsycn_and_free; + goto fsync_and_free; } /* Step 6: Allocate prev_clus array and build backward links */ set->prev_clus = calloc(set->num_phys_clus + set->num_clus_chain, sizeof(uint32_t)); if (set->prev_clus == NULL) { exfat_err("memory run out in defrag.cluster_info_set->prev_clus\n"); - ret = -1; - goto fsycn_and_free; + ret = 1; + goto fsync_and_free; } next_to_prev(set); /* Step 7: Perform defragmentation with interrupt support */ interrupt_point = 0; interrupt_received = 0; - if (signal(SIGINT, sigint_handler) == SIG_ERR || - signal(SIGTERM, sigint_handler) == SIG_ERR) { - exfat_err("fail in signal register\n"); - ret = -1; - goto fsycn_and_free; - } + signal(SIGINT, sigint_handler); + signal(SIGTERM, sigint_handler); if (exfat_defrag(&defrag) < 0) { exfat_err("fail in exfat_defrag\n"); - ret = -1; - goto fsycn_and_free; + ret = 1; + goto fsync_and_free; } /* Step 8: Rewrite first cluster and contiguous flags in directory entries */ if (BFS_write_file_tree(&defrag) < 0) { exfat_err("fail in BFS_write_file_tree\n"); - ret = -1; - goto fsycn_and_free; + ret = 1; + goto fsync_and_free; } /* Step 9: Write back updated bitmap and FAT */ if (exfat_rw_bitmap(defrag.exfat, false) < 0) { exfat_err("fail in exfat_write_bitmap\n"); - ret = -1; - goto fsycn_and_free; + ret = 1; + goto fsync_and_free; } if (exfat_rw_FAT(defrag.exfat, set->next_clus, set->num_phys_clus, false) < 0) { exfat_err("fail in exfat_write_FAT\n"); - ret = -1; - goto fsycn_and_free; + ret = 1; + goto fsync_and_free; } -fsycn_and_free: +fsync_and_free: /* Step 10: fsync and free allocated resources */ fsync(bd.dev_fd); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/exfatprogs-1.3.0/fsck/fsck.c new/exfatprogs-1.3.1/fsck/fsck.c --- old/exfatprogs-1.3.0/fsck/fsck.c 2025-10-15 05:03:42.000000000 +0200 +++ new/exfatprogs-1.3.1/fsck/fsck.c 2025-12-15 04:54:48.000000000 +0100 @@ -980,6 +980,7 @@ .in.param = NULL, }; struct exfat_dentry *dentry; + uint64_t map_size, need_map_size; int retval; retval = exfat_lookup_dentry_set(exfat, exfat->root, &filter); @@ -991,6 +992,20 @@ le32_to_cpu(dentry->bitmap_start_clu), le64_to_cpu(dentry->bitmap_size)); + /* Validate on-disk bitmap size and required size */ + map_size = le64_to_cpu(dentry->bitmap_size); + need_map_size = DIV_ROUND_UP(exfat->clus_count, 8); + if (map_size != need_map_size && + exfat_repair_ask(&exfat_fsck, ER_DE_BITMAP, + "ERROR: invalid bitmap size. %lld", map_size)) { + dentry->bitmap_size = cpu_to_le64(need_map_size); + if (pwrite(exfat->blk_dev->dev_fd, dentry, DENTRY_SIZE, + filter.out.dev_offset) != DENTRY_SIZE) { + exfat_err("failed to write bitmap dentry\n"); + return -EIO; + } + } + if (le64_to_cpu(dentry->bitmap_size) < DIV_ROUND_UP(exfat->clus_count, 8)) { exfat_err("invalid size of allocation bitmap. 0x%" PRIx64 "\n", diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/exfatprogs-1.3.0/fsck/repair.c new/exfatprogs-1.3.1/fsck/repair.c --- old/exfatprogs-1.3.0/fsck/repair.c 2025-10-15 05:03:42.000000000 +0200 +++ new/exfatprogs-1.3.1/fsck/repair.c 2025-12-15 04:54:48.000000000 +0100 @@ -50,6 +50,7 @@ {ER_DE_UNUSED, ERF_PREEN_YES, ERP_FIX, 0, 0, 0}, {ER_DE_FILE, ERF_PREEN_YES, ERP_DELETE, 0, 0, 0}, {ER_DE_UPCASE, ERF_PREEN_YES, ERP_FIX, 0, 0, 0}, + {ER_DE_BITMAP, ERF_PREEN_YES, ERP_FIX, 0, 0, 0}, {ER_DE_SECONDARY_COUNT, ERF_PREEN_YES, ERP_FIX, 0, 0, 0}, {ER_DE_STREAM, ERF_PREEN_YES, ERP_DELETE, 0, 0, 0}, {ER_DE_NAME, ERF_PREEN_YES, ERP_DELETE, 0, 0, 0}, diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/exfatprogs-1.3.0/fsck/repair.h new/exfatprogs-1.3.1/fsck/repair.h --- old/exfatprogs-1.3.0/fsck/repair.h 2025-10-15 05:03:42.000000000 +0200 +++ new/exfatprogs-1.3.1/fsck/repair.h 2025-12-15 04:54:48.000000000 +0100 @@ -22,6 +22,7 @@ #define ER_DE_DUPLICATED_NAME 0x00001034 #define ER_DE_INVALID_NAME 0x00001035 #define ER_DE_UPCASE 0x00001036 +#define ER_DE_BITMAP 0x00001037 #define ER_FILE_VALID_SIZE 0x00002001 #define ER_FILE_INVALID_CLUS 0x00002002 #define ER_FILE_FIRST_CLUS 0x00002003 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/exfatprogs-1.3.0/include/version.h new/exfatprogs-1.3.1/include/version.h --- old/exfatprogs-1.3.0/include/version.h 2025-10-15 05:03:42.000000000 +0200 +++ new/exfatprogs-1.3.1/include/version.h 2025-12-15 04:54:48.000000000 +0100 @@ -5,6 +5,6 @@ #ifndef _VERSION_H -#define EXFAT_PROGS_VERSION "1.3.0" +#define EXFAT_PROGS_VERSION "1.3.1" #endif /* !_VERSION_H */ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/exfatprogs-1.3.0/lib/exfat_dir.c new/exfatprogs-1.3.1/lib/exfat_dir.c --- old/exfatprogs-1.3.0/lib/exfat_dir.c 2025-10-15 05:03:42.000000000 +0200 +++ new/exfatprogs-1.3.1/lib/exfat_dir.c 2025-12-15 04:54:48.000000000 +0100 @@ -10,6 +10,7 @@ #include <fcntl.h> #include <string.h> #include <time.h> +#include <inttypes.h> #include "exfat_ondisk.h" #include "libexfat.h" @@ -261,7 +262,6 @@ int ith, struct exfat_dentry **dentry) { off_t next_de_file_offset; - ssize_t ret; unsigned int block; struct buffer_desc *bd; @@ -275,9 +275,12 @@ /* read next cluster if needed */ if (next_de_file_offset >= iter->next_read_offset) { - ret = read_block(iter, block); - if (ret != (ssize_t)iter->read_size) - return ret; + if (read_block(iter, block) != (ssize_t)iter->read_size) { + exfat_err("failed to read from device at offset %#" PRIx64 "\n", + exfat_de_iter_device_offset(iter)); + + return -EIO; + } iter->next_read_offset += iter->read_size; } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/exfatprogs-1.3.0/manpages/defrag.exfat.8 new/exfatprogs-1.3.1/manpages/defrag.exfat.8 --- old/exfatprogs-1.3.0/manpages/defrag.exfat.8 2025-10-15 05:03:42.000000000 +0200 +++ new/exfatprogs-1.3.1/manpages/defrag.exfat.8 2025-12-15 04:54:48.000000000 +0100 @@ -15,17 +15,17 @@ .SH DESCRIPTION .B defrag.exfat -is a utility to defragment files on an exFAT-formatted device or assess its current fragmentation status. +is a utility to defragment files on an exFAT-formatted device or assess its fragmentation status. -Defragmentation reorganizes scattered file clusters into contiguous blocks, which may improve I/O performance — especially on mechanical storage devices. - -By default, when no option is specified, the tool will prompt the user with a warning recommending to run \fBfsck.exfat\fR first to ensure filesystem consistency. +When no option is specified, the tool warns the user to run \fBfsck.exfat\fR first for filesystem consistency. This safety prompt can be bypassed using the \fB\-f\fR option. The \fB\-a\fR option enables assessment mode, which analyzes fragmentation without modifying the filesystem. -The target device must be \fIunmounted\fR before running this command. +\fBdefrag.exfat\fR provides whole-disk defragmentation based on cluster swapping, which incurs a certain amount of wear overhead on flash-based storage devices with low fragmentation levels. + +Therefore, it is recommended to use \fBdefrag.exfat\fR on mechanical hard disk drives (HDDs) or flash-based devices that exhibit a relatively high degree of fragmentation. .SH OPTIONS .TP @@ -73,6 +73,18 @@ .EE .SH NOTES -It is \fBstrongly recommended\fR to run \fBfsck.exfat\fR on the device before defragmenting to ensure filesystem integrity. +Before defragmentation: +.IP - +The target device must be \fBunmounted\fR. +.IP - +Please run \fBfsck.exfat\fR on the target device to ensure filesystem integrity. +.IP - +Considering the potential risks of defragmentation, critical data should be \fBbacked up\fR in advance. +.PP -Always backup critical data before defragmenting. +During defragmentation: +.IP - +Always keep the device \fBconnected and powered\fR. +.IP - +If the device is removed, powered off, or experiences a hardware failure, the filesystem may become corrupted. +.PP \ No newline at end of file Binary files old/exfatprogs-1.3.0/tests/bad_bitmap_size/exfat.img.tar.xz and new/exfatprogs-1.3.1/tests/bad_bitmap_size/exfat.img.tar.xz differ
