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-03-11 20:50:30
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/exfatprogs (Old)
 and      /work/SRC/openSUSE:Factory/.exfatprogs.new.8177 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "exfatprogs"

Wed Mar 11 20:50:30 2026 rev:23 rq:1338190 version:1.3.2

Changes:
--------
--- /work/SRC/openSUSE:Factory/exfatprogs/exfatprogs.changes    2026-01-21 
14:11:46.224866956 +0100
+++ /work/SRC/openSUSE:Factory/.exfatprogs.new.8177/exfatprogs.changes  
2026-03-11 20:51:21.780195359 +0100
@@ -1,0 +2,21 @@
+Wed Mar 11 05:32:16 UTC 2026 - Michael Vetter <[email protected]>
+
+- Update to 1.3.2:
+  Features:
+  * fsck.exfat: add an option to show a progress bar
+    while checking a filesystem.
+  Changes:
+  * mkfs.exfat: discard blocks prior to write outs by
+    default.
+  * mkfs.exfat: add a read-after-write verification for
+    the volume boot record.
+  * exfatprogs: adjust utility exit codes and add log
+    messages for malloc() failures.
+  Bug fixes:
+  * dump.exfat: handle paths including '.', '..', and
+    repeated '/'.
+  * fsck.exfat: convert 0x80 entries into deleted file
+    entries to avoid bogus dentry errors.
+  * fsck.exfat: fix an uninitialized variable warning.
+
+-------------------------------------------------------------------

Old:
----
  1.3.1.tar.gz

New:
----
  1.3.2.tar.gz

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ exfatprogs.spec ++++++
--- /var/tmp/diff_new_pack.MhuKtw/_old  2026-03-11 20:51:22.432222348 +0100
+++ /var/tmp/diff_new_pack.MhuKtw/_new  2026-03-11 20:51:22.432222348 +0100
@@ -17,7 +17,7 @@
 
 
 Name:           exfatprogs
-Version:        1.3.1
+Version:        1.3.2
 Release:        0
 Summary:        Utilities for exFAT file system maintenance
 License:        GPL-2.0-or-later

++++++ 1.3.1.tar.gz -> 1.3.2.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/exfatprogs-1.3.1/.github/workflows/c-cpp.yml 
new/exfatprogs-1.3.2/.github/workflows/c-cpp.yml
--- old/exfatprogs-1.3.1/.github/workflows/c-cpp.yml    2025-12-15 
04:54:48.000000000 +0100
+++ new/exfatprogs-1.3.2/.github/workflows/c-cpp.yml    2026-03-10 
02:29:29.000000000 +0100
@@ -23,7 +23,7 @@
              linux-headers-$(uname -r) xz-utils \
              gcc-mips-linux-gnu qemu-system-mips \
              qemu-user
-        git clone https://github.com/namjaejeon/linux-exfat-oot
+        sudo apt-get install -y linux-modules-extra-$(uname -r)
         export LD_LIBRARY_PATH=/usr/local/lib:$LD_LIBRARY_PATH
         export PATH=/usr/local/lib:$PATH
     - name: build test & install exfatprogs
@@ -46,12 +46,8 @@
         sudo -E ./test_fsck.sh
     - name: create file/director test
       run: |
-        cd linux-exfat-oot
-        make > /dev/null
-        sudo make install > /dev/null
         sudo modprobe exfat
         sudo mkdir -p /mnt/test
-        cd ..
         truncate -s 10G test.img
         sudo losetup /dev/loop22 test.img
         sudo mkfs.exfat /dev/loop22
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/exfatprogs-1.3.1/NEWS new/exfatprogs-1.3.2/NEWS
--- old/exfatprogs-1.3.1/NEWS   2025-12-15 04:54:48.000000000 +0100
+++ new/exfatprogs-1.3.2/NEWS   2026-03-10 02:29:29.000000000 +0100
@@ -1,3 +1,25 @@
+exfatprogs 1.3.2 - release 2026-03-09
+===================================
+
+NEW FEATURES :
+ * fsck.exfat: add an option to show a progress bar
+   while checking a filesystem.
+
+CHANGES :
+ * mkfs.exfat: discard blocks prior to write outs by
+   default.
+ * mkfs.exfat: add a read-after-write verification for
+   the volume boot record.
+ * exfatprogs: adjust utility exit codes and add log
+   messages for malloc() failures.
+
+BUG FIXES :
+ * dump.exfat: handle paths including '.', '..', and
+   repeated '/'.
+ * fsck.exfat: convert 0x80 entries into deleted file
+   entries to avoid bogus dentry errors.
+ * fsck.exfat: fix an uninitialized variable warning.
+
 exfatprogs 1.3.1 - released 2025-12-15
 =====================================
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/exfatprogs-1.3.1/defrag/defrag.c 
new/exfatprogs-1.3.2/defrag/defrag.c
--- old/exfatprogs-1.3.1/defrag/defrag.c        2025-12-15 04:54:48.000000000 
+0100
+++ new/exfatprogs-1.3.2/defrag/defrag.c        2026-03-10 02:29:29.000000000 
+0100
@@ -167,7 +167,7 @@
                boot_calc_checksum(buf, bd->sector_size, is_boot_sec, 
&checksum);
        }
 
-       ret = exfat_write_checksum_sector(bd, checksum, is_backup);
+       ret = exfat_write_checksum_sector(bd, NULL, checksum, is_backup);
 
 free_buf:
        free(buf);
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/exfatprogs-1.3.1/dump/dump.c 
new/exfatprogs-1.3.2/dump/dump.c
--- old/exfatprogs-1.3.1/dump/dump.c    2025-12-15 04:54:48.000000000 +0100
+++ new/exfatprogs-1.3.2/dump/dump.c    2026-03-10 02:29:29.000000000 +0100
@@ -240,6 +240,17 @@
        return 0;
 }
 
+static void exfat_free_inode_chain(struct exfat_inode *inode)
+{
+       struct exfat_inode *parent;
+
+       while (inode) {
+               parent = inode->parent;
+               exfat_free_inode(inode);
+               inode = parent;
+       }
+}
+
 /*
  * Get the first level file name from a given path
  *
@@ -253,28 +264,25 @@
  */
 static int get_name_from_path(const char *path, char *name, size_t name_size)
 {
-       int i;
-       int name_len = 0;
-       int path_len = strlen(path);
-
-       if (path_len == 0)
-               return 0;
+       const char *p = path;
+       size_t len = 0;
 
-       for (i = 0; i <= path_len && name_len + 1 < name_size; i++, path++) {
-               if (*path == '/' || *path == '\0') {
-                       if (name_len == 0)
-                               continue;
+       while (*p == '/')
+               p++;
 
-                       name[name_len] = 0;
-                       return i;
-               }
+       if (*p == '\0') {
+               name[0] = '\0';
+               return p - path;
+       }
 
-               name[name_len] = *path;
-               name_len++;
+       while (*p != '/' && *p != '\0') {
+               if (len + 1 < name_size)
+                       name[len++] = *p;
+               p++;
        }
 
-       name[0] = 0;
-       return 0;
+       name[len] = '\0';
+       return p - path;
 }
 
 /*
@@ -296,60 +304,91 @@
 {
        int len, ret;
        char name[PATH_MAX + 1];
-       struct exfat_inode *inode;
+       struct exfat_inode *cur_inode, *new_inode, *tmp;
        struct exfat_dentry *dentry_set;
        struct exfat_lookup_filter filter;
        const char *p_path = path;
 
-       inode = exfat_alloc_inode(ATTR_SUBDIR);
-       if (!inode)
+       cur_inode = exfat_alloc_inode(ATTR_SUBDIR);
+       if (!cur_inode)
                return -ENOMEM;
 
-       *inode = *exfat->root;
-       *dir_is_contiguous = inode->is_contiguous;
+       cur_inode->parent = NULL;
+       *cur_inode = *exfat->root;
+       *dir_is_contiguous = cur_inode->is_contiguous;
 
-       do {
-               if ((inode->attr & ATTR_SUBDIR) == 0 && *p_path != '\0') {
+       while (*p_path) {
+               if ((cur_inode->attr & ATTR_SUBDIR) == 0 && *p_path != '\0') {
                        ret = -ENOENT;
                        goto free_inode;
                }
 
                len = get_name_from_path(p_path, name, sizeof(name));
                p_path += len;
-               if (name[0] == '\0' || len == 0) {
-                       *new = inode;
-                       return 0;
+               if (name[0] == '\0' || len == 0)
+                       goto out;
+
+               if (strcmp(name, ".") == 0)
+                       continue;
+
+               if (strcmp(name, "..") == 0) {
+                       if (!cur_inode->parent) {
+                               ret = -EINVAL;
+                               goto free_inode;
+                       }
+                       tmp = cur_inode;
+                       cur_inode = cur_inode->parent;
+                       exfat_free_inode(tmp);
+                       continue;
+               }
+
+               new_inode = exfat_alloc_inode(ATTR_SUBDIR);
+               if (!new_inode) {
+                       ret = -ENOMEM;
+                       goto free_inode;
                }
 
-               ret = exfat_utf16_enc(name, inode->name, NAME_BUFFER_SIZE);
-               if (ret < 0)
+               new_inode->parent = cur_inode;
+
+               ret = exfat_utf16_enc(name, new_inode->name, NAME_BUFFER_SIZE);
+               if (ret < 0) {
+                       exfat_free_inode(new_inode);
                        goto free_inode;
+               }
 
-               ret = exfat_lookup_file_by_utf16name(exfat, inode, inode->name,
+               ret = exfat_lookup_file_by_utf16name(exfat, cur_inode, 
new_inode->name,
                                                     &filter);
                if (ret) {
                        if (ret == EOF)
                                ret = -ENOENT;
+                       exfat_free_inode(new_inode);
                        goto free_inode;
                }
 
+               /* fill new inode from lookup result */
                dentry_set = filter.out.dentry_set;
-               if (inode->dentry_set)
-                       free(inode->dentry_set);
-               inode->dentry_set = dentry_set;
-               inode->dev_offset = filter.out.dev_offset;
-               inode->dentry_count = filter.out.dentry_count;
-               inode->attr = dentry_set[0].file_attr;
-               inode->first_clus = le32_to_cpu(dentry_set[1].stream_start_clu);
-               *dir_is_contiguous = inode->is_contiguous;
-               inode->is_contiguous =
+               new_inode->dentry_set = dentry_set;
+               new_inode->dev_offset = filter.out.dev_offset;
+               new_inode->dentry_count = filter.out.dentry_count;
+               new_inode->attr = dentry_set[0].file_attr;
+               new_inode->first_clus = 
le32_to_cpu(dentry_set[1].stream_start_clu);
+               new_inode->is_contiguous =
                        (dentry_set[1].stream_flags & EXFAT_SF_CONTIGUOUS);
-               inode->size = le64_to_cpu(dentry_set[1].stream_size);
-       } while (1);
+               new_inode->size = le64_to_cpu(dentry_set[1].stream_size);
 
-free_inode:
-       exfat_free_inode(inode);
+               cur_inode = new_inode;
+       }
+
+out:
+       if (cur_inode->parent) {
+               *dir_is_contiguous = cur_inode->parent->is_contiguous;
+               exfat_free_inode_chain(cur_inode->parent);
+       }
+       *new = cur_inode;
+       return 0;
 
+free_inode:
+       exfat_free_inode_chain(cur_inode);
        return ret;
 }
 
@@ -950,5 +989,5 @@
        close(bd.dev_fd);
 
 out:
-       return ret;
+       return ret ? EXIT_FAILURE : EXIT_SUCCESS;
 }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/exfatprogs-1.3.1/fsck/fsck.c 
new/exfatprogs-1.3.2/fsck/fsck.c
--- old/exfatprogs-1.3.1/fsck/fsck.c    2025-12-15 04:54:48.000000000 +0100
+++ new/exfatprogs-1.3.2/fsck/fsck.c    2026-03-10 02:29:29.000000000 +0100
@@ -59,6 +59,7 @@
        {"help",        no_argument,    NULL,   'h' },
        {"?",           no_argument,    NULL,   '?' },
        {"ignore-bad-fs",       no_argument,    NULL,   'b' },
+       {"progress",    no_argument,    NULL,   'P' },
        {NULL,          0,              NULL,    0  }
 };
 
@@ -72,6 +73,7 @@
        fprintf(stderr, "\t-a                   Repair automatically\n");
        fprintf(stderr, "\t-b | --ignore-bad-fs Try to recover even if exfat is 
not found\n");
        fprintf(stderr, "\t-s | --rescue        Assign orphaned clusters to 
files\n");
+       fprintf(stderr, "\t-P | --progress      Show progress bar\n");
        fprintf(stderr, "\t-V | --version       Show version\n");
        fprintf(stderr, "\t-v | --verbose       Print debug\n");
        fprintf(stderr, "\t-h | --help          Show help\n");
@@ -167,6 +169,8 @@
                                             clus))
                                return -EINVAL;
                }
+               if (exfat_fsck.options & FSCK_OPTS_PROGRESS_BAR)
+                       progress_update(&exfat_fsck.progress_bar, 1);
 
                /* This cluster is allocated or not */
                if (exfat_get_inode_next_clus(exfat, node, clus, &next))
@@ -245,14 +249,12 @@
                                 struct exfat_inode *node,
                                 clus_t *clus_count)
 {
-       clus_t clus, next, prev = EXFAT_EOF_CLUSTER;
+       clus_t clus = node->first_clus, next, prev = EXFAT_EOF_CLUSTER;
 
+       *clus_count = 0;
        if (!exfat_heap_clus(exfat, node->first_clus))
                goto out_trunc;
 
-       clus = node->first_clus;
-       *clus_count = 0;
-
        do {
                if (exfat_bitmap_get(exfat->alloc_bitmap, clus)) {
                        if (exfat_repair_ask(&exfat_fsck,
@@ -936,7 +938,7 @@
                        break;
                if (need_delete) {
                        exfat_de_iter_get_dirty(iter, i, &dentry);
-                       dentry->type &= EXFAT_DELETE;
+                       dentry->type = EXFAT_DELETE;
                }
        }
        *skip_dentries = i;
@@ -1424,7 +1426,7 @@
                                struct exfat_dentry *dentry;
 
                                exfat_de_iter_get_dirty(de_iter, 0, &dentry);
-                               dentry->type &= EXFAT_DELETE;
+                               dentry->type = EXFAT_DELETE;
                        }
                        break;
                }
@@ -1756,6 +1758,18 @@
                        exfat_stat.fixed_count);
 }
 
+static clus_t count_bitmap_set_bits(struct exfat *exfat)
+{
+       clus_t count = 0;
+       size_t i, bytes = exfat->disk_bitmap_size;
+
+       for (i = 0; i + sizeof(uint32_t) <= bytes; i += sizeof(uint32_t))
+               count += __builtin_popcount(*(uint32_t *)(exfat->disk_bitmap + 
i));
+       for (; i < bytes; i++)
+               count += __builtin_popcount(exfat->disk_bitmap[i]);
+       return count;
+}
+
 int main(int argc, char * const argv[])
 {
        struct fsck_user_input ui;
@@ -1764,6 +1778,7 @@
        struct exfat_inode *root;
        int c, ret, exit_code;
        bool version_only = false;
+       clus_t used_clus_count;
 
        memset(&ui, 0, sizeof(ui));
        memset(&bd, 0, sizeof(bd));
@@ -1774,7 +1789,7 @@
                exfat_err("failed to init locale/codeset\n");
 
        opterr = 0;
-       while ((c = getopt_long(argc, argv, "arynpbsVvh", opts, NULL)) != EOF) {
+       while ((c = getopt_long(argc, argv, "arynpbsPVvh", opts, NULL)) != EOF) 
{
                switch (c) {
                case 'n':
                        if (ui.options & FSCK_OPTS_REPAIR_ALL)
@@ -1803,6 +1818,9 @@
                case 's':
                        ui.options |= FSCK_OPTS_RESCUE_CLUS;
                        break;
+               case 'P':
+                       ui.options |= FSCK_OPTS_PROGRESS_BAR;
+                       break;
                case 'V':
                        version_only = true;
                        break;
@@ -1818,7 +1836,8 @@
        }
 
        show_version();
-       if (optind != argc - 1)
+       if (optind != argc - 1 ||
+           (ui.options & FSCK_OPTS_REPAIR_ASK && ui.options & 
FSCK_OPTS_PROGRESS_BAR))
                usage(argv[0]);
 
        if (version_only)
@@ -1879,6 +1898,11 @@
                goto out;
        }
 
+       if (exfat_fsck.options & FSCK_OPTS_PROGRESS_BAR) {
+               used_clus_count = count_bitmap_set_bits(exfat_fsck.exfat);
+               progress_init(&exfat_fsck.progress_bar, 0, used_clus_count, 0);
+       }
+
        exfat_debug("verifying directory entries...\n");
        ret = exfat_filesystem_check(&exfat_fsck);
        if (ret)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/exfatprogs-1.3.1/fsck/fsck.h 
new/exfatprogs-1.3.2/fsck/fsck.h
--- old/exfatprogs-1.3.1/fsck/fsck.h    2025-12-15 04:54:48.000000000 +0100
+++ new/exfatprogs-1.3.2/fsck/fsck.h    2026-03-10 02:29:29.000000000 +0100
@@ -6,6 +6,7 @@
 #define _FSCK_H
 
 #include "list.h"
+#include "utils.h"
 
 enum fsck_ui_options {
        FSCK_OPTS_REPAIR_ASK    = 0x01,
@@ -16,6 +17,7 @@
        FSCK_OPTS_REPAIR_ALL    = 0x0f,
        FSCK_OPTS_IGNORE_BAD_FS_NAME    = 0x10,
        FSCK_OPTS_RESCUE_CLUS   = 0x20,
+       FSCK_OPTS_PROGRESS_BAR  = 0x40,
 };
 
 struct exfat;
@@ -30,6 +32,7 @@
        bool                    dirty_fat:1;
 
        char *name_hash_bitmap;
+       struct progress_bar progress_bar;
 };
 
 off_t exfat_c2o(struct exfat *exfat, unsigned int clus);
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/exfatprogs-1.3.1/include/libexfat.h 
new/exfatprogs-1.3.2/include/libexfat.h
--- old/exfatprogs-1.3.1/include/libexfat.h     2025-12-15 04:54:48.000000000 
+0100
+++ new/exfatprogs-1.3.2/include/libexfat.h     2026-03-10 02:29:29.000000000 
+0100
@@ -68,6 +68,7 @@
 
 struct exfat_blk_dev {
        int dev_fd;
+       int verify_fd;
        unsigned long long offset;
        unsigned long long size;
        unsigned int sector_size;
@@ -75,6 +76,7 @@
        unsigned long long num_sectors;
        unsigned int num_clusters;
        unsigned int cluster_size;
+       bool isblk;
 };
 
 struct exfat_user_input {
@@ -86,10 +88,13 @@
        unsigned int boundary_align;
        bool pack_bitmap;
        bool quick;
+       bool verify;
+       bool discard;
        __u16 volume_label[VOLUME_LABEL_MAX_LEN];
        int volume_label_len;
        unsigned int volume_serial;
        const char *guid;
+       unsigned char *fat_table_buff;
 };
 
 struct exfat;
@@ -155,6 +160,7 @@
 ssize_t exfat_read(int fd, void *buf, size_t size, off_t offset);
 ssize_t exfat_write(int fd, void *buf, size_t size, off_t offset);
 ssize_t exfat_write_zero(int fd, size_t size, off_t offset);
+int exfat_discard_blocks(int fd, uint64_t start, uint64_t len);
 
 size_t exfat_utf16_len(const __le16 *str, size_t max_size);
 ssize_t exfat_utf16_enc(const char *in_str, __u16 *out_str, size_t out_size);
@@ -171,7 +177,8 @@
 int exfat_write_sector(struct exfat_blk_dev *bd, void *buf,
                unsigned int sec_off);
 int exfat_write_checksum_sector(struct exfat_blk_dev *bd,
-               unsigned int checksum, bool is_backup);
+       struct exfat_user_input *ui, unsigned int checksum,
+       bool is_backup);
 char *exfat_conv_volume_label(struct exfat_dentry *vol_entry);
 int exfat_show_volume_serial(int fd);
 int exfat_set_volume_serial(struct exfat_blk_dev *bd,
@@ -193,7 +200,9 @@
 int read_boot_sect(struct exfat_blk_dev *bdev, struct pbr **bs);
 int exfat_parse_ulong(const char *s, unsigned long *out);
 int exfat_check_name(__le16 *utf16_name, int len);
-
+int exfat_check_written_data(struct exfat_blk_dev *bd, const void *buf,
+                                    size_t len, off_t off,
+                                    const char *what);
 /*
  * Exfat Print
  */
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/exfatprogs-1.3.1/include/utils.h 
new/exfatprogs-1.3.2/include/utils.h
--- old/exfatprogs-1.3.1/include/utils.h        1970-01-01 01:00:00.000000000 
+0100
+++ new/exfatprogs-1.3.2/include/utils.h        2026-03-10 02:29:29.000000000 
+0100
@@ -0,0 +1,27 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ *  Copyright (C) 2026 Hyunchul Lee <[email protected]>
+ *
+ *  Portions of the progress bar code derived from ntfsprogs-plus and modified 
for exfatprogs.
+ */
+
+#ifndef _EXFAT_UTILS_H
+#define _EXFAT_UTILS_H
+
+#include <stdint.h>
+
+struct progress_bar {
+       uint32_t start;
+       uint32_t stop;
+       uint32_t current;
+       uint32_t resolution;
+#ifdef PROG_CALC_FLOAT
+       float unit;
+#else
+       uint64_t total;
+#endif
+};
+
+void progress_init(struct progress_bar *p, uint32_t start, uint32_t stop, 
uint32_t res);
+void progress_update(struct progress_bar *p, uint32_t current);
+#endif
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/exfatprogs-1.3.1/include/version.h 
new/exfatprogs-1.3.2/include/version.h
--- old/exfatprogs-1.3.1/include/version.h      2025-12-15 04:54:48.000000000 
+0100
+++ new/exfatprogs-1.3.2/include/version.h      2026-03-10 02:29:29.000000000 
+0100
@@ -5,6 +5,6 @@
 
 #ifndef _VERSION_H
 
-#define EXFAT_PROGS_VERSION "1.3.1"
+#define EXFAT_PROGS_VERSION "1.3.2"
 
 #endif /* !_VERSION_H */
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/exfatprogs-1.3.1/label/label.c 
new/exfatprogs-1.3.2/label/label.c
--- old/exfatprogs-1.3.1/label/label.c  2025-12-15 04:54:48.000000000 +0100
+++ new/exfatprogs-1.3.2/label/label.c  2026-03-10 02:29:29.000000000 +0100
@@ -127,5 +127,5 @@
 close_fd_out:
        close(bd.dev_fd);
 out:
-       return ret;
+       return ret ? EXIT_FAILURE : EXIT_SUCCESS;
 }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/exfatprogs-1.3.1/lib/Android.bp 
new/exfatprogs-1.3.2/lib/Android.bp
--- old/exfatprogs-1.3.1/lib/Android.bp 2025-12-15 04:54:48.000000000 +0100
+++ new/exfatprogs-1.3.2/lib/Android.bp 2026-03-10 02:29:29.000000000 +0100
@@ -7,6 +7,7 @@
         "libexfat.c",
         "exfat_fs.c",
         "exfat_dir.c",
+        "utils.c",
     ],
     defaults: ["exfatprogs-defaults"],
 }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/exfatprogs-1.3.1/lib/Makefile.am 
new/exfatprogs-1.3.2/lib/Makefile.am
--- old/exfatprogs-1.3.1/lib/Makefile.am        2025-12-15 04:54:48.000000000 
+0100
+++ new/exfatprogs-1.3.2/lib/Makefile.am        2026-03-10 02:29:29.000000000 
+0100
@@ -1,4 +1,4 @@
 AM_CFLAGS = -Wall -include $(top_builddir)/config.h -I$(top_srcdir)/include 
-fno-common
 noinst_LIBRARIES = libexfat.a
 
-libexfat_a_SOURCES = libexfat.c exfat_fs.c exfat_dir.c
+libexfat_a_SOURCES = libexfat.c exfat_fs.c exfat_dir.c utils.c
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/exfatprogs-1.3.1/lib/libexfat.c 
new/exfatprogs-1.3.2/lib/libexfat.c
--- old/exfatprogs-1.3.1/lib/libexfat.c 2025-12-15 04:54:48.000000000 +0100
+++ new/exfatprogs-1.3.2/lib/libexfat.c 2026-03-10 02:29:29.000000000 +0100
@@ -3,6 +3,9 @@
  *   Copyright (C) 2019 Namjae Jeon <[email protected]>
  */
 
+#ifndef _GNU_SOURCE
+#define _GNU_SOURCE
+#endif
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <sys/ioctl.h>
@@ -134,6 +137,7 @@
        memset(ui, 0, sizeof(struct exfat_user_input));
        ui->writeable = true;
        ui->quick = true;
+       ui->discard = true;
 }
 
 int exfat_get_blk_dev_info(struct exfat_user_input *ui,
@@ -163,6 +167,8 @@
                char 
pathname[sizeof("/sys/dev/block/4294967295:4294967295/start")];
                FILE *fp;
 
+               bd->isblk = true;
+
                snprintf(pathname, sizeof(pathname), 
"/sys/dev/block/%u:%u/start",
                        major(st.st_rdev), minor(st.st_rdev));
                fp = fopen(pathname, "r");
@@ -206,6 +212,16 @@
 
        ret = 0;
        bd->dev_fd = fd;
+
+       if (ui->verify) {
+               bd->verify_fd = open(ui->dev_name, O_RDONLY|O_DIRECT);
+               if (bd->verify_fd < 0) {
+                       exfat_err("open %s O_DIRECT failed:%s\n", ui->dev_name,
+                               strerror(errno));
+                       close(fd);
+                       ret = -1;
+               }
+       }
 out:
        return ret;
 }
@@ -238,6 +254,15 @@
        return 0;
 }
 
+int exfat_discard_blocks(int fd, uint64_t start, uint64_t len)
+{
+       uint64_t range[2] = { start, len };
+
+       if (ioctl(fd, BLKDISCARD, &range) < 0)
+               return errno;
+       return 0;
+}
+
 size_t exfat_utf16_len(const __le16 *str, size_t max_size)
 {
        size_t i = 0;
@@ -410,8 +435,10 @@
        __le16 disk_label[VOLUME_LABEL_MAX_LEN];
 
        volume_label = malloc(VOLUME_LABEL_BUFFER_SIZE);
-       if (!volume_label)
+       if (!volume_label) {
+               exfat_err("Cannot allocate volume_label: out of memory\n");
                return NULL;
+       }
 
        memcpy(disk_label, vol_entry->vol_label, sizeof(disk_label));
        memset(volume_label, 0, VOLUME_LABEL_BUFFER_SIZE);
@@ -684,6 +711,45 @@
        return err;
 }
 
+int exfat_check_written_data(struct exfat_blk_dev *bd,
+                               const void *buf, size_t len,
+                               off_t off, const char *what)
+{
+       void *verify;
+       ssize_t n;
+       size_t sector = bd->sector_size;
+       int ret = 0;
+
+       ret = fsync(bd->dev_fd);
+       if (ret)
+               return ret;
+
+       off_t aligned_off = off & ~(sector - 1);
+       size_t head = off - aligned_off;
+       size_t aligned_len = ((head + len + sector - 1) / sector) * sector;
+
+       if (posix_memalign(&verify, sector, aligned_len))
+               return -ENOMEM;
+       memset(verify, 0, aligned_len);
+
+       n = exfat_read(bd->verify_fd, verify, aligned_len, aligned_off);
+       if (n != (ssize_t)aligned_len) {
+               exfat_debug("%s verify read failed (off=%llu, len=%zu)\n",
+                                       what, (unsigned long long)aligned_off,
+                                       aligned_len);
+               ret = -EIO;
+       }
+
+       if (memcmp(buf, (unsigned char *)verify + head, len) != 0) {
+               exfat_debug("%s verify mismatch (off=%llu)\n",
+                                       what, (unsigned long long)off);
+               ret = -EIO;
+       }
+
+       free(verify);
+       return ret;
+}
+
 int exfat_read_sector(struct exfat_blk_dev *bd, void *buf, unsigned int 
sec_off)
 {
        int ret;
@@ -715,7 +781,8 @@
 }
 
 int exfat_write_checksum_sector(struct exfat_blk_dev *bd,
-               unsigned int checksum, bool is_backup)
+               struct exfat_user_input *ui, unsigned int checksum,
+               bool is_backup)
 {
        __le32 *checksum_buf;
        int ret = 0;
@@ -723,8 +790,10 @@
        unsigned int sec_idx = CHECKSUM_SEC_IDX;
 
        checksum_buf = malloc(bd->sector_size);
-       if (!checksum_buf)
+       if (!checksum_buf) {
+               exfat_err("Cannot allocate checksum_buf: out of memory\n");
                return -1;
+       }
 
        if (is_backup)
                sec_idx += BACKUP_BOOT_SEC_IDX;
@@ -738,6 +807,17 @@
                goto free;
        }
 
+       if (ui && ui->verify) {
+               ret = exfat_check_written_data(bd,
+                               checksum_buf, bd->sector_size,
+                               sec_idx * bd->sector_size,
+                               "checksum sector");
+               if (ret) {
+                       exfat_err("checksum sector verification failed 
(read-back mismatch)\n");
+                       goto free;
+               }
+       }
+
 free:
        free(checksum_buf);
        return ret;
@@ -775,7 +855,8 @@
        return ret;
 }
 
-static int exfat_update_boot_checksum(struct exfat_blk_dev *bd, bool is_backup)
+static int exfat_update_boot_checksum(struct exfat_blk_dev *bd,
+       struct exfat_user_input *ui, bool is_backup)
 {
        unsigned int checksum = 0;
        int ret, sec_idx, backup_sec_idx = 0;
@@ -807,7 +888,7 @@
                        &checksum);
        }
 
-       ret = exfat_write_checksum_sector(bd, checksum, is_backup);
+       ret = exfat_write_checksum_sector(bd, ui, checksum, is_backup);
 
 free_buf:
        free(buf);
@@ -861,13 +942,13 @@
                goto free_ppbr;
        }
 
-       ret = exfat_update_boot_checksum(bd, 0);
+       ret = exfat_update_boot_checksum(bd, ui, 0);
        if (ret < 0) {
                exfat_err("main checksum update failed\n");
                goto free_ppbr;
        }
 
-       ret = exfat_update_boot_checksum(bd, 1);
+       ret = exfat_update_boot_checksum(bd, ui, 1);
        if (ret < 0)
                exfat_err("backup checksum update failed\n");
 free_ppbr:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/exfatprogs-1.3.1/lib/utils.c 
new/exfatprogs-1.3.2/lib/utils.c
--- old/exfatprogs-1.3.1/lib/utils.c    1970-01-01 01:00:00.000000000 +0100
+++ new/exfatprogs-1.3.2/lib/utils.c    2026-03-10 02:29:29.000000000 +0100
@@ -0,0 +1,66 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ *   Copyright (C) 2026 Hyunchul Lee <[email protected]>
+ *
+ *   Portions of the progress bar code derived from ntfsprogs-plus and 
modified for exfatprogs.
+ */
+
+#include <stdio.h>
+#include <inttypes.h>
+
+#include "utils.h"
+
+void progress_init(struct progress_bar *p, uint32_t start, uint32_t stop, 
uint32_t res)
+{
+       uint64_t total;
+
+       p->start = start;
+       p->stop = stop;
+       p->current = start;
+
+       total = stop - start + 1;
+       if (total <= 0)
+               total = 1;
+
+#ifdef PROG_CALC_FLOAT
+       p->unit = 100.0 / total;
+
+       if (((res * 100 * 100) / total) == 0)
+               p->resolution = (int)(total / (100 * 100.0));   // 0.01 
resolution
+       else
+               p->resolution = res;
+#else
+       p->total = total;
+
+       if (((res * 100) / p->total) == 0) {
+               p->resolution = p->total / 100;
+               if (!p->resolution)
+                       p->resolution = 1;
+       } else
+               p->resolution = res;
+#endif
+}
+
+void progress_update(struct progress_bar *p, uint32_t update)
+{
+#ifdef PROG_CALC_FLOAT
+       float percent;
+#else
+       uint32_t percent;
+#endif
+
+       p->current += update;
+       if (p->current != p->stop) {
+               if ((p->current - p->start) % p->resolution)
+                       return;
+#ifdef PROG_CALC_FLOAT
+               percent = p->unit * p->current;
+               printf("%6.2f percent completed\r", percent);
+#else
+               percent = (p->current * 100) / p->total;
+               printf("%3u percent completed\r", percent);
+#endif
+       } else
+               printf("100.00 percent completed\n");
+       fflush(stdout);
+}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/exfatprogs-1.3.1/manpages/fsck.exfat.8 
new/exfatprogs-1.3.2/manpages/fsck.exfat.8
--- old/exfatprogs-1.3.1/manpages/fsck.exfat.8  2025-12-15 04:54:48.000000000 
+0100
+++ new/exfatprogs-1.3.2/manpages/fsck.exfat.8  2026-03-10 02:29:29.000000000 
+0100
@@ -16,6 +16,8 @@
 ] [
 .B \-b
 ] [
+.B \-P
+] [
 .B \-v
 ]
 .I device
@@ -59,6 +61,9 @@
 .BI \-p
 Repair the filesystem without user interaction if it can be done safely.
 .TP
+.BI \-P
+Show progress bar while checking the filesystem. Cannot be used with -r option.
+.TP
 .BI \-r
 Repair the filesystem interactively.
 .TP
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/exfatprogs-1.3.1/manpages/mkfs.exfat.8 
new/exfatprogs-1.3.2/manpages/mkfs.exfat.8
--- old/exfatprogs-1.3.1/manpages/mkfs.exfat.8  2025-12-15 04:54:48.000000000 
+0100
+++ new/exfatprogs-1.3.2/manpages/mkfs.exfat.8  2026-03-10 02:29:29.000000000 
+0100
@@ -16,6 +16,8 @@
 ] [
 .B \-f
 ] [
+.B \-C
+] [
 .B \-h
 ] [
 .B \-L
@@ -103,6 +105,20 @@
 .BR \-f ", " \-\-full\-format
 Performs a full format.
 This zeros the entire disk device while creating the exFAT filesystem.
+.TE
+.TP
+.BR \-K ", " \-\-no\-discard
+Do not attempt to discard blocks.
+.TP
+.BR \-C ", " \-\-verify\-written
+Verify filesystem metadata by reading it back after writing.
+This option performs read-back verification of critical exFAT metadata
+(boot record, FAT, allocation bitmap, upcase table, and root directory)
+after each formatting stage.
+It is useful for detecting broken storage devices or devices that falsely
+report successful writes without actually persisting data.
+This option may slightly degrade formatting performance and is therefore
+disabled by default.
 .TP
 .BR \-h ", " \-\-help
 Prints the help and exit.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/exfatprogs-1.3.1/mkfs/mkfs.c 
new/exfatprogs-1.3.2/mkfs/mkfs.c
--- old/exfatprogs-1.3.1/mkfs/mkfs.c    2025-12-15 04:54:48.000000000 +0100
+++ new/exfatprogs-1.3.2/mkfs/mkfs.c    2026-03-10 02:29:29.000000000 +0100
@@ -127,6 +127,17 @@
                goto free_ppbr;
        }
 
+       if (ui->verify) {
+               ret = exfat_check_written_data(bd,
+                               ppbr, bd->sector_size,
+                               sec_idx * bd->sector_size,
+                               "boot sector");
+               if (ret) {
+                       exfat_err("boot sector verification failed (read-back 
mismatch)\n");
+                       goto free_ppbr;
+               }
+       }
+
        boot_calc_checksum((unsigned char *)ppbr, bd->sector_size,
                true, checksum);
 
@@ -136,7 +147,8 @@
 }
 
 static int exfat_write_extended_boot_sectors(struct exfat_blk_dev *bd,
-               unsigned int *checksum, bool is_backup)
+               struct exfat_user_input *ui, unsigned int *checksum,
+               bool is_backup)
 {
        char *peb;
        __le16 *peb_signature;
@@ -145,8 +157,10 @@
        unsigned int sec_idx = EXBOOT_SEC_IDX;
 
        peb = malloc(bd->sector_size);
-       if (!peb)
+       if (!peb) {
+               exfat_err("Cannot allocate peb: out of memory\n");
                return -1;
+       }
 
        if (is_backup)
                sec_idx += BACKUP_BOOT_SEC_IDX;
@@ -161,6 +175,17 @@
                        goto free_peb;
                }
 
+               if (ui->verify) {
+                       ret = exfat_check_written_data(bd,
+                                       peb, bd->sector_size,
+                                       (sec_idx - 1) * bd->sector_size,
+                                       "extended boot sector");
+                       if (ret) {
+                               exfat_err("extended boot sector verification 
failed (read-back mismatch)\n");
+                               goto free_peb;
+                       }
+               }
+
                boot_calc_checksum((unsigned char *) peb, bd->sector_size,
                        false, checksum);
        }
@@ -171,7 +196,8 @@
 }
 
 static int exfat_write_oem_sector(struct exfat_blk_dev *bd,
-               unsigned int *checksum, bool is_backup)
+               struct exfat_user_input *ui, unsigned int *checksum,
+               bool is_backup)
 {
        char *oem;
        int ret = 0;
@@ -191,6 +217,17 @@
                goto free_oem;
        }
 
+       if (ui->verify) {
+               ret = exfat_check_written_data(bd,
+                               oem, bd->sector_size,
+                               sec_idx * bd->sector_size,
+                               "oem sector");
+               if (ret) {
+                       exfat_err("oem sector verification failed (read-back 
mismatch)\n");
+                       goto free_oem;
+               }
+       }
+
        boot_calc_checksum((unsigned char *)oem, bd->sector_size, false,
                checksum);
 
@@ -202,6 +239,17 @@
                goto free_oem;
        }
 
+       if (ui->verify) {
+               ret = exfat_check_written_data(bd,
+                               oem, bd->sector_size,
+                               (sec_idx + 1) * bd->sector_size,
+                               "reserved sector");
+               if (ret) {
+                       exfat_err("reserved sector verification failed 
(read-back mismatch)\n");
+                       goto free_oem;
+               }
+       }
+
        boot_calc_checksum((unsigned char *)oem, bd->sector_size, false,
                checksum);
 
@@ -219,18 +267,18 @@
        ret = exfat_write_boot_sector(bd, ui, &checksum, is_backup);
        if (ret)
                return ret;
-       ret = exfat_write_extended_boot_sectors(bd, &checksum, is_backup);
+       ret = exfat_write_extended_boot_sectors(bd, ui, &checksum, is_backup);
        if (ret)
                return ret;
-       ret = exfat_write_oem_sector(bd, &checksum, is_backup);
+       ret = exfat_write_oem_sector(bd, ui, &checksum, is_backup);
        if (ret)
                return ret;
 
-       return exfat_write_checksum_sector(bd, checksum, is_backup);
+       return exfat_write_checksum_sector(bd, ui, checksum, is_backup);
 }
 
-static int write_fat_entry(int fd, __le32 clu,
-               unsigned long long offset)
+static int write_fat_entry(struct exfat_user_input *ui, int fd,
+               __le32 clu, unsigned long long offset)
 {
        int nbyte;
        off_t fat_entry_offset = finfo.fat_byte_off + (offset * sizeof(__le32));
@@ -242,6 +290,11 @@
                return -1;
        }
 
+       if (ui->verify) {
+               memcpy(ui->fat_table_buff + offset * sizeof(__le32),
+                       (__u8 *)&clu, sizeof(__le32));
+       }
+
        return 0;
 }
 
@@ -254,12 +307,12 @@
        count = clu + round_up(length, ui->cluster_size) / ui->cluster_size;
 
        for (; clu < count - 1; clu++) {
-               ret = write_fat_entry(fd, cpu_to_le32(clu + 1), clu);
+               ret = write_fat_entry(ui, fd, cpu_to_le32(clu + 1), clu);
                if (ret)
                        return ret;
        }
 
-       ret = write_fat_entry(fd, cpu_to_le32(EXFAT_EOF_CLUSTER), clu);
+       ret = write_fat_entry(ui, fd, cpu_to_le32(EXFAT_EOF_CLUSTER), clu);
        if (ret)
                return ret;
 
@@ -270,52 +323,87 @@
                struct exfat_user_input *ui)
 {
        int ret, clu;
+       unsigned int fat_table_entries = 0;
+
+       if (ui->verify) {
+               fat_table_entries =
+                       EXFAT_FIRST_CLUSTER +
+                       DIV_ROUND_UP(finfo.bitmap_byte_len, ui->cluster_size) +
+                       DIV_ROUND_UP(finfo.ut_byte_len, ui->cluster_size) +
+                       DIV_ROUND_UP(finfo.root_byte_len, ui->cluster_size);
+
+               ui->fat_table_buff = calloc(fat_table_entries, sizeof(__le32));
+               if (!ui->fat_table_buff)
+                       return -ENOMEM;
+       }
 
        /* fat entry 0 should be media type field(0xF8) */
-       ret = write_fat_entry(bd->dev_fd, cpu_to_le32(0xfffffff8), 0);
+       ret = write_fat_entry(ui, bd->dev_fd, cpu_to_le32(0xfffffff8), 0);
        if (ret) {
                exfat_err("fat 0 entry write failed\n");
-               return ret;
+               goto free_fat_table_buff;
        }
 
        /* fat entry 1 is historical precedence(0xFFFFFFFF) */
-       ret = write_fat_entry(bd->dev_fd, cpu_to_le32(0xffffffff), 1);
+       ret = write_fat_entry(ui, bd->dev_fd, cpu_to_le32(0xffffffff), 1);
        if (ret) {
                exfat_err("fat 1 entry write failed\n");
-               return ret;
+               goto free_fat_table_buff;
        }
 
        /* write bitmap entries */
        clu = write_fat_entries(ui, bd->dev_fd, EXFAT_FIRST_CLUSTER,
                finfo.bitmap_byte_len);
-       if (clu < 0)
-               return ret;
+       if (clu < 0) {
+               ret = clu;
+               goto free_fat_table_buff;
+       }
 
        /* write upcase table entries */
        clu = write_fat_entries(ui, bd->dev_fd, clu + 1, finfo.ut_byte_len);
-       if (clu < 0)
-               return ret;
+       if (clu < 0) {
+               ret = clu;
+               goto free_fat_table_buff;
+       }
 
        /* write root directory entries */
        clu = write_fat_entries(ui, bd->dev_fd, clu + 1, finfo.root_byte_len);
-       if (clu < 0)
-               return ret;
+       if (clu < 0) {
+               ret = clu;
+               goto free_fat_table_buff;
+       }
 
        finfo.used_clu_cnt = clu + 1 - EXFAT_FIRST_CLUSTER;
        exfat_debug("Total used cluster count : %d\n", finfo.used_clu_cnt);
 
+       if (ui->verify) {
+               ret = exfat_check_written_data(bd,
+                               ui->fat_table_buff, fat_table_entries * 
sizeof(__le32),
+                               finfo.fat_byte_off,
+                               "fat table");
+               if (ret)
+                       exfat_err("fat table verification failed (read-back 
mismatch)\n");
+       }
+
+free_fat_table_buff:
+       if (ui->verify)
+               free(ui->fat_table_buff);
        return ret;
 }
 
-static int exfat_create_bitmap(struct exfat_blk_dev *bd)
+static int exfat_create_bitmap(struct exfat_blk_dev *bd,
+               struct exfat_user_input *ui)
 {
        char *bitmap;
        unsigned int full_bytes, rem_bits, zero_offset;
        unsigned int nbytes;
+       int ret = 0;
 
        bitmap = malloc(finfo.bitmap_byte_len);
-       if (!bitmap)
+       if (!bitmap) {
+               exfat_err("Cannot allocate bitmap: out of memory\n");
                return -1;
+       }
 
        full_bytes = finfo.used_clu_cnt / 8;
        rem_bits = finfo.used_clu_cnt % 8;
@@ -340,6 +428,18 @@
                return -1;
        }
 
+       if (ui->verify) {
+               ret = exfat_check_written_data(bd,
+                               bitmap, finfo.bitmap_byte_len,
+                               finfo.bitmap_byte_off,
+                               "bitmap");
+               if (ret) {
+                       exfat_err("bitmap verification failed (read-back 
mismatch)\n");
+                       free(bitmap);
+                       return ret;
+               }
+       }
+
        free(bitmap);
        return 0;
 }
@@ -396,6 +496,17 @@
                return -1;
        }
 
+       if (ui->verify) {
+               ret = exfat_check_written_data(bd,
+                               ed, dentries_len,
+                               finfo.root_byte_off,
+                               "root directory");
+               if (ret) {
+                       exfat_err("root directory verification failed 
(read-back mismatch)\n");
+                       return ret;
+               }
+
+       }
        return 0;
 }
 
@@ -409,6 +520,8 @@
                "\t-b | --boundary-align=size(or suffixed by 'K' or 'M')  
Specify boundary alignment\n"
                "\t     --pack-bitmap                                     Move 
bitmap into FAT segment\n"
                "\t-f | --full-format                                     Full 
format\n"
+               "\t-C | --check-written                                   
Verify written filesystem metadata by read-back\n"
+               "\t-K | --no-discard                                      Do 
not discard blocks\n"
                "\t-V | --version                                         Show 
version\n"
                "\t-q | --quiet                                           Print 
only errors\n"
                "\t-v | --verbose                                         Print 
debug\n"
@@ -428,6 +541,8 @@
        {"boundary-align",      required_argument,      NULL,   'b' },
        {"pack-bitmap",         no_argument,            NULL,   PACK_BITMAP },
        {"full-format",         no_argument,            NULL,   'f' },
+       {"check-written",       no_argument,            NULL,   'C' },
+       {"no-discard",          no_argument,            NULL,   'K' },
        {"version",             no_argument,            NULL,   'V' },
        {"quiet",               no_argument,            NULL,   'q' },
        {"verbose",             no_argument,            NULL,   'v' },
@@ -553,6 +668,56 @@
        return 0;
 }
 
+static void exfat_discard_dev(struct exfat_blk_dev *bd,
+               struct exfat_user_input *ui)
+{
+       uint64_t offset = 0;
+       uint64_t tmp_step;
+       int err;
+       /* Discard the device 2G at a time */
+       const uint64_t step = 2ULL << 30;
+       const uint64_t count = bd->num_sectors * bd->sector_size;
+
+       if (!ui->discard || !bd->isblk) {
+               exfat_debug("no-discard requested or the device is a file\n");
+               return;
+       }
+
+       /*
+        * The block discarding happens in smaller batches so it can be
+        * interrupted prematurely
+        */
+       while (offset < count) {
+               tmp_step = count - offset;
+               if (step < tmp_step)
+                       tmp_step = step;
+
+               err = exfat_discard_blocks(bd->dev_fd, offset, tmp_step);
+               /*
+                * We intentionally ignore errors from the discard ioctl. It is
+                * not necessary for the mkfs functionality but just an
+                * optimization. However we should stop on error.
+                */
+               if (err == 0) {
+                       if (offset == 0) {
+                               exfat_info("Discarding blocks: ");
+                               exfat_debug("BLKDISCARD: ");
+                       }
+                       exfat_debug("%"PRIu64"-%"PRIu64" ", offset, offset + 
tmp_step);
+                       fflush(stdout);
+               } else {
+                       exfat_debug("BLKDISCARD: %s\n", strerror(err));
+                       if (offset > 0)
+                               exfat_info("\n");
+                       return;
+               }
+
+               offset += tmp_step;
+       }
+       if (offset > 0)
+               exfat_info("done\n");
+}
+
 static int make_exfat(struct exfat_blk_dev *bd, struct exfat_user_input *ui)
 {
        int ret;
@@ -580,13 +745,13 @@
                return ret;
 
        exfat_info("Allocation bitmap creation: ");
-       ret = exfat_create_bitmap(bd);
+       ret = exfat_create_bitmap(bd, ui);
        exfat_info("%s\n", ret ? "failed" : "done");
        if (ret)
                return ret;
 
        exfat_info("Upcase table creation: ");
-       ret = exfat_create_upcase_table(bd);
+       ret = exfat_create_upcase_table(bd, ui);
        exfat_info("%s\n", ret ? "failed" : "done");
        if (ret)
                return ret;
@@ -640,7 +805,7 @@
                exfat_err("failed to init locale/codeset\n");
 
        opterr = 0;
-       while ((c = getopt_long(argc, argv, "n:L:U:s:c:b:fVqvh", opts, NULL)) 
!= EOF)
+       while ((c = getopt_long(argc, argv, "n:L:U:s:c:b:fCKVqvh", opts, NULL)) 
!= EOF)
                switch (c) {
                /*
                 * Make 'n' option fallthrough to 'L' option for for backward
@@ -709,6 +874,12 @@
                case 'f':
                        ui.quick = false;
                        break;
+               case 'C':
+                       ui.verify = true;
+                       break;
+               case 'K':
+                       ui.discard = false;
+                       break;
                case 'V':
                        version_only = true;
                        break;
@@ -753,6 +924,12 @@
        if (ret)
                goto close;
 
+       exfat_discard_dev(&bd, &ui);
+       /*
+        * Zeroing out still needs to be conducted as per JESD84-B51 6.6.9:
+        * "content of an explicitly erased memory range shall be ‘0’ or ‘1’
+        * depending on different memory technology,"
+        */
        ret = exfat_zero_out_disk(&bd, &ui);
        if (ret)
                goto close;
@@ -765,10 +942,12 @@
        ret = fsync(bd.dev_fd);
 close:
        close(bd.dev_fd);
+       if (ui.verify)
+               close(bd.verify_fd);
 out:
        if (!ret)
                exfat_info("\nexFAT format complete!\n");
        else
                exfat_err("\nexFAT format fail!\n");
-       return ret;
+       return ret ? EXIT_FAILURE : EXIT_SUCCESS;
 }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/exfatprogs-1.3.1/mkfs/mkfs.h 
new/exfatprogs-1.3.2/mkfs/mkfs.h
--- old/exfatprogs-1.3.1/mkfs/mkfs.h    2025-12-15 04:54:48.000000000 +0100
+++ new/exfatprogs-1.3.2/mkfs/mkfs.h    2026-03-10 02:29:29.000000000 +0100
@@ -27,6 +27,6 @@
 
 extern struct exfat_mkfs_info finfo;
 
-int exfat_create_upcase_table(struct exfat_blk_dev *bd);
+int exfat_create_upcase_table(struct exfat_blk_dev *bd, struct 
exfat_user_input *ui);
 
 #endif /* !_MKFS_H */
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/exfatprogs-1.3.1/mkfs/upcase.c 
new/exfatprogs-1.3.2/mkfs/upcase.c
--- old/exfatprogs-1.3.1/mkfs/upcase.c  2025-12-15 04:54:48.000000000 +0100
+++ new/exfatprogs-1.3.2/mkfs/upcase.c  2026-03-10 02:29:29.000000000 +0100
@@ -13,14 +13,28 @@
 #include "mkfs.h"
 #include "upcase_table.h"
 
-int exfat_create_upcase_table(struct exfat_blk_dev *bd)
+int exfat_create_upcase_table(struct exfat_blk_dev *bd,
+               struct exfat_user_input *ui)
 {
        int nbytes;
+       int ret;
 
        nbytes = pwrite(bd->dev_fd, default_upcase_table,
                        EXFAT_UPCASE_TABLE_SIZE, finfo.ut_byte_off);
        if (nbytes != EXFAT_UPCASE_TABLE_SIZE)
                return -1;
 
+       if (ui->verify) {
+               ret = exfat_check_written_data(bd,
+                               default_upcase_table,
+                               EXFAT_UPCASE_TABLE_SIZE,
+                               finfo.ut_byte_off,
+                               "upcase table");
+               if (ret) {
+                       exfat_err("upcase table verification failed (read-back 
mismatch)\n");
+                       return ret;
+               }
+       }
+
        return 0;
 }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/exfatprogs-1.3.1/tune/tune.c 
new/exfatprogs-1.3.2/tune/tune.c
--- old/exfatprogs-1.3.1/tune/tune.c    2025-12-15 04:54:48.000000000 +0100
+++ new/exfatprogs-1.3.2/tune/tune.c    2026-03-10 02:29:29.000000000 +0100
@@ -152,5 +152,5 @@
        if (exfat)
                exfat_free_exfat(exfat);
 out:
-       return ret;
+       return ret ? EXIT_FAILURE : EXIT_SUCCESS;
 }

Reply via email to