Script 'mail_helper' called by obssrc
Hello community,

here is the log from the commit of package f3 for openSUSE:Factory checked in 
at 2025-03-27 22:34:50
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/f3 (Old)
 and      /work/SRC/openSUSE:Factory/.f3.new.2696 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "f3"

Thu Mar 27 22:34:50 2025 rev:10 rq:1264690 version:9.0

Changes:
--------
--- /work/SRC/openSUSE:Factory/f3/f3.changes    2020-11-23 10:26:08.781068789 
+0100
+++ /work/SRC/openSUSE:Factory/.f3.new.2696/f3.changes  2025-03-27 
22:35:30.712579925 +0100
@@ -1,0 +2,11 @@
+Thu Mar 27 13:28:40 UTC 2025 - Johannes Kastl 
<[email protected]>
+
+- update to version 9.0:
+    * f3read/f3write: Avoid the execution stack to list files
+    * f3read/f3write: Add dynamic buffers
+    * f3read/f3write: chroot(2) to source/target dir if allowed
+    * Portability improvements for Ubuntu, ARM, OpenBSD, and Apple
+    * Automated test of the code with GitHub Actions
+    * Improved documentation
+
+-------------------------------------------------------------------

Old:
----
  f3-8.0.tar.gz

New:
----
  f3-9.0.tar.gz

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

Other differences:
------------------
++++++ f3.spec ++++++
--- /var/tmp/diff_new_pack.mP3agz/_old  2025-03-27 22:35:31.164598635 +0100
+++ /var/tmp/diff_new_pack.mP3agz/_new  2025-03-27 22:35:31.164598635 +0100
@@ -1,7 +1,7 @@
 #
 # spec file for package f3
 #
-# Copyright (c) 2020 SUSE LLC
+# Copyright (c) 2025 SUSE LLC
 #
 # 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:           f3
-Version:        8.0
+Version:        9.0
 Release:        0
 Summary:        Fight Flash Fraud / Fight Fake Flash
 License:        GPL-3.0-only

++++++ f3-8.0.tar.gz -> f3-9.0.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/f3-8.0/.github/workflows/test.yml 
new/f3-9.0/.github/workflows/test.yml
--- old/f3-8.0/.github/workflows/test.yml       1970-01-01 01:00:00.000000000 
+0100
+++ new/f3-9.0/.github/workflows/test.yml       2025-03-27 14:18:19.000000000 
+0100
@@ -0,0 +1,130 @@
+---
+name: Test
+
+on:
+  push:
+    branches:
+      - master
+  pull_request: {}
+
+jobs:
+  Linux:
+    strategy:
+      fail-fast: false
+      matrix:
+        volume:
+          - /tmp
+          - .
+          - relative-path
+          - /
+        asroot:
+          - name: ''
+            sudo: ''
+          - name: ' as root'
+            sudo: 'sudo '
+
+    name: Linux ${{ matrix.volume }}${{ matrix.asroot.name }}
+    runs-on: ubuntu-22.04
+
+    steps:
+      - uses: actions/checkout@v3
+      - run: sudo apt-get install -y libparted-dev libudev-dev
+      - run: make all extra
+
+      - if: matrix.volume == 'relative-path'
+        run: mkdir relative-path
+
+      - if: matrix.volume == '/'
+        run: sudo chmod a+w /
+
+      - run: ./f3write -V
+      - run: ./f3write --help
+      - run: ${{ matrix.asroot.sudo }}./f3write -s 2 -e 4 -w 50000 ${{ 
matrix.volume }}
+
+      - run: stat ${{ matrix.volume }}/2.h2w
+      - run: stat ${{ matrix.volume }}/3.h2w
+      - run: stat ${{ matrix.volume }}/4.h2w
+
+      - run: ./f3read -V
+      - run: ./f3read --help
+      - run: ${{ matrix.asroot.sudo }}./f3read -s 2 -e 4 -r 50000 ${{ 
matrix.volume }}
+
+  MacOS:
+    strategy:
+      fail-fast: false
+      matrix:
+        volume:
+          - /tmp
+          - .
+          - relative-path
+          # MacOS denies `sudo chmod a+w /`
+          #- /
+        asroot:
+          - name: ''
+            sudo: ''
+          - name: ' as root'
+            sudo: 'sudo '
+
+    name: MacOS ${{ matrix.volume }}${{ matrix.asroot.name }}
+    runs-on: macos-12
+
+    steps:
+      - uses: actions/checkout@v3
+      - run: brew install argp-standalone
+      - run: make
+
+      - if: matrix.volume == 'relative-path'
+        run: mkdir relative-path
+
+      - run: ./f3write -V
+      - run: ./f3write --help
+      - run: ${{ matrix.asroot.sudo }}./f3write -s 2 -e 4 -w 50000 ${{ 
matrix.volume }}
+
+      - run: stat ${{ matrix.volume }}/2.h2w
+      - run: stat ${{ matrix.volume }}/3.h2w
+      - run: stat ${{ matrix.volume }}/4.h2w
+
+      - run: ./f3read -V
+      - run: ./f3read --help
+      - run: ${{ matrix.asroot.sudo }}./f3read -s 2 -e 4 -r 50000 ${{ 
matrix.volume }}
+
+  Cygwin:
+    strategy:
+      fail-fast: false
+      matrix:
+        volume:
+          - cygwin: /cygdrive/c
+            windows: 'C:'
+          - cygwin: .
+            windows: .
+          - cygwin: relative-path
+            windows: relative-path
+          - cygwin: /
+            windows: 'C:\cygwin'
+
+    name: Cygwin ${{ matrix.volume.cygwin }}
+    runs-on: windows-2022
+
+    steps:
+      - uses: actions/checkout@v3
+
+      - uses: cygwin/cygwin-install-action@v2
+        with:
+          packages: gcc-core libargp-devel make
+
+      - run: "$Env:LDFLAGS = '-Wl,--stack,4000000'; make"
+
+      - if: matrix.volume.windows == 'relative-path'
+        run: New-Item -ItemType Directory -Path relative-path
+
+      - run: '& .\f3write.exe -V'
+      - run: '& .\f3write.exe --help'
+      - run: '& .\f3write.exe -s 2 -e 4 -w 50000 ${{ matrix.volume.cygwin }}'
+
+      - run: 'Get-Item ${{ matrix.volume.windows }}\2.h2w'
+      - run: 'Get-Item ${{ matrix.volume.windows }}\3.h2w'
+      - run: 'Get-Item ${{ matrix.volume.windows }}\4.h2w'
+
+      - run: '& .\f3read.exe -V'
+      - run: '& .\f3read.exe --help'
+      - run: '& .\f3read.exe -s 2 -e 4 -r 50000 ${{ matrix.volume.cygwin }}'
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/f3-8.0/Dockerfile new/f3-9.0/Dockerfile
--- old/f3-8.0/Dockerfile       2020-10-29 14:25:47.000000000 +0100
+++ new/f3-9.0/Dockerfile       2025-03-27 14:18:19.000000000 +0100
@@ -1,14 +1,14 @@
-FROM ubuntu:18.04
+FROM ubuntu:22.04
 
 RUN apt-get update && \
     apt-get install -y --no-install-recommends \
-       gcc \
-       less \
-       libparted0-dev \
-       libudev1 \
-       libudev-dev \
-       make \
-       udev
+        gcc \
+        less \
+        libparted-dev \
+        libudev1 \
+        libudev-dev \
+        make \
+        udev
 
 COPY . /f3
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/f3-8.0/LICENSE new/f3-9.0/LICENSE
--- old/f3-8.0/LICENSE  2020-10-29 14:25:47.000000000 +0100
+++ new/f3-9.0/LICENSE  2025-03-27 14:18:19.000000000 +0100
@@ -1,7 +1,7 @@
                     GNU GENERAL PUBLIC LICENSE
                        Version 3, 29 June 2007
 
- Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
+ Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
  Everyone is permitted to copy and distribute verbatim copies
  of this license document, but changing it is not allowed.
 
@@ -645,7 +645,7 @@
     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, see <http://www.gnu.org/licenses/>.
+    along with this program.  If not, see <https://www.gnu.org/licenses/>.
 
 Also add information on how to contact you by electronic and paper mail.
 
@@ -664,11 +664,11 @@
   You should also get your employer (if you work as a programmer) or school,
 if any, to sign a "copyright disclaimer" for the program, if necessary.
 For more information on this, and how to apply and follow the GNU GPL, see
-<http://www.gnu.org/licenses/>.
+<https://www.gnu.org/licenses/>.
 
   The GNU General Public License does not permit incorporating your program
 into proprietary programs.  If your program is a subroutine library, you
 may consider it more useful to permit linking proprietary applications with
 the library.  If this is what you want to do, use the GNU Lesser General
 Public License instead of this License.  But first, please read
-<http://www.gnu.org/philosophy/why-not-lgpl.html>.
+<https://www.gnu.org/licenses/why-not-lgpl.html>.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/f3-8.0/Makefile new/f3-9.0/Makefile
--- old/f3-8.0/Makefile 2020-10-29 14:25:47.000000000 +0100
+++ new/f3-9.0/Makefile 2025-03-27 14:18:19.000000000 +0100
@@ -13,6 +13,11 @@
 endif
 ifneq ($(OS), Linux)
        ARGP = /usr/local
+       ifeq ($(OS), Darwin)
+               ifneq ($(shell command -v brew),)
+                       ARGP = $(shell brew --prefix)
+               endif
+       endif
        CFLAGS += -I$(ARGP)/include
        LDFLAGS += -L$(ARGP)/lib -largp
 endif
@@ -20,6 +25,9 @@
 all: $(TARGETS)
 extra: $(EXTRA_TARGETS)
 
+docker:
+       docker build -f Dockerfile -t f3:latest .
+
 install: all
        $(INSTALL) -d $(DESTDIR)$(PREFIX)/bin
        $(INSTALL) -m755 $(TARGETS) $(DESTDIR)$(PREFIX)/bin
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/f3-8.0/README.rst new/f3-9.0/README.rst
--- old/f3-8.0/README.rst       2020-10-29 14:25:47.000000000 +0100
+++ new/f3-9.0/README.rst       2025-03-27 14:18:19.000000000 +0100
@@ -14,12 +14,16 @@
 -  `Other resources <#other-resources>`__
 
 .. _examples:
-
-.. highlight:: bash
+.. highlight:: console
 
 Examples
 ========
 
+We'll use :code:`/dev/sdX` as a placeholder here, you need to replace 
+:code:`X` with a lowercase letter so that it matches the device you
+want to use.
+:code:`lsblk` will show you an overview of your current devices.
+
 Testing performance with f3read/f3write
 ---------------------------------------
 
@@ -44,7 +48,7 @@
 on the (unmounted) block device and needs to be run as a privileged
 user::
 
-    # ./f3probe --destructive --time-ops /dev/sdb
+    # ./f3probe --destructive --time-ops /dev/sdX
 
 .. warning:: This will destroy any previously stored data on your disk!
 
@@ -54,7 +58,7 @@
 f3fix creates a partition that fits the actual size of the fake drive.
 Use f3probe's output to determine the parameters for f3fix::
 
-    # ./f3fix --last-sec=16477878 /dev/sdb
+    # ./f3fix --last-sec=16477878 /dev/sdX
 
 Installation
 ============
@@ -63,11 +67,12 @@
 --------------------
 
 The files of the stable version of F3 are
-`here <https://github.com/AltraMayor/f3/releases>`__. The
+`here <https://github.com/AltraMayor/f3/tags>`__. The
 following command uncompresses the files::
 
-    $ unzip f3-8.0.zip
+    $ unzip f3-9.0.zip
 
+.. highlight:: bash
 
 Compile stable software on Linux or FreeBSD
 -------------------------------------------
@@ -129,7 +134,7 @@
 Compiling the latest development version from the source code
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
-Most of the f3 source code builds fine using XCode, the only dependency
+Most of the f3 source code builds fine using Xcode, the only dependency
 missing is the GNU C library "argp". You can build argp from scratch, or
 use the version provided by HomeBrew and MacPorts as "argp-standalone"
 
@@ -156,7 +161,7 @@
 
        brew install argp-standalone
 
-   See http://brewformulas.org/ArgpStandalone and
+   See https://formulae.brew.sh/formula/argp-standalone and
    https://www.freshports.org/devel/argp-standalone/ for more
    information.
 
@@ -190,16 +195,28 @@
 
     docker run -it --rm --device <device> peron/f3 <f3-command> [<f3-options>] 
<device>
 
-For example, to probe a drive mounted at /dev/sdb::
+For example, to probe a drive mounted at /dev/sdX::
 
-    docker run -it --rm --device /dev/sdb peron/f3 f3probe --destructive 
--time-ops /dev/sdb
+    docker run -it --rm --device /dev/sdX peron/f3 f3probe --destructive 
--time-ops /dev/sdX
 
 Optionally, you can also build your own container *if* you don't want to use 
the
 pre-built image.  From this directory, run::
 
+    make docker
+
+or::
+
     docker build -t f3:latest .
+
+
+To run f3 commands using your newly built Docker image::
+
     docker run -it --rm --device <device> f3:latest <f3-command> 
[<f3-options>] <device>
 
+    docker run -it --rm --device /dev/sdX f3:latest f3probe --destructive 
--time-ops /dev/sdX
+    docker run -it --rm -v /path/to/mounted/device:/mnt/ f3:latest f3write 
/mnt/
+    docker run -it --rm -v /path/to/mounted/device:/mnt/ f3:latest f3read /mnt/
+
 Drive Permissions / Passthrough
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
@@ -221,7 +238,7 @@
 handle device pass-through, we can pass the device through to the VirtualBox VM
 which can then pass the device through to the Docker container.  Milad Alizadeh
 wrote up some good instructions `here
-<https://mil.ad/docker/2018/05/06/access-usb-devices-in-container-in-mac.html>`__
+<https://mil.ad/blog/2018/access-usb-devices-in-container-in-mac.html>`__
 which are geared towards USB devices, but it shouldn't be too hard to adapt to
 other drive types.  Here's what I typed into my Mac terminal (probably
 similar for Windows, but untested)::
@@ -258,12 +275,12 @@
 mount point for a USB drive.  Now you should be able to run the command from
 Quick Start::
 
-    docker run --rm -it --device /dev/sdb peron/f3 f3probe --destructive 
--time-ops /dev/sdb
+    docker run --rm -it --device /dev/sdX peron/f3 f3probe --destructive 
--time-ops /dev/sdX
 
 You may find it useful to enter a bash prompt in the Docker container to poke
 around the filesystem::
 
-    docker run --rm -it --device /dev/sdb peron/f3 bash
+    docker run --rm -it --device /dev/sdX peron/f3 bash
 
 so that you can run commands like :code:`ls /dev/*`.
 
@@ -277,7 +294,10 @@
 requires version 0 of the library libparted to compile. On Ubuntu, you
 can install these libraries with the following command::
 
-    sudo apt-get install libudev1 libudev-dev libparted0-dev
+    sudo apt-get install libudev1 libudev-dev libparted-dev
+
+If you are running a version of Ubuntu before 20.04.1, replace the package 
`libparted-dev`
+on the command line above with `libparted0-dev`.
 
 On Fedora, you can install these libraries with the following command::
 
@@ -318,37 +338,53 @@
 QT. F3 QT supports ``f3write``, ``f3read``, ``f3probe``, and ``f3fix``. Author:
 Tianze.
 
-Please support the above project by testing it and giving feedback to their
-authors. This will make their code improve as it has improved mine.
+`F3XSwift <https://github.com/vrunkel/F3XSwift>`__ is a Mac GUI. F3XSwift 
supports ``f3write`` and ``f3read``. Author:
+Volker Runkel.
+
+Please support the above projects by testing them and giving feedback to their
+authors. This will improve their code as it has improved mine.
 
 Files
 -----
 
-::
+- ``changelog`` - Change log for package maintainers
+- ``f3read.1`` - Man page for f3read and f3write
 
-    changelog   - Change log for package maintainers
-    f3read.1    - Man page for f3read and f3write
-                In order to read this manual page, run `man ./f3read.1`
-                To install the page, run
-                `install --owner=root --group=root --mode=644 f3read.1 
/usr/share/man/man1`
-    LICENSE     - License (GPLv3)
-    Makefile    - make(1) file
-    README      - This file
-    *.h and *.c - C code of F3
+  In order to read this manual page, run ``man ./f3read.1``.
+  To install the page, run
+  ``install --owner=root --group=root --mode=644 f3read.1 
/usr/share/man/man1``.
+
+- ``LICENSE`` - License (GPLv3)
+- ``Makefile`` - make(1) file
+- ``README`` - This file
+- ``*.h`` and ``*.c`` - C code of F3
 
 Bash scripts
 ------------
 
 Although the simple scripts listed in this section are ready for use,
 they are really meant to help you to write your own scripts. So you can
-personalize F3 to your specific needs::
+personalize F3 to your specific needs:
 
-    f3write.h2w - Script to create files exactly like H2testw.
-        Use example: `f3write.h2w /media/michel/5EBD-5C80/`
+- ``f3write.h2w`` - Script to create files exactly like H2testw.
 
-    log-f3wr    - Script that runs f3write and f3read, and records
-                  their output into a log file.
-        Use example: `log-f3wr log-filename /media/michel/5EBD-5C80/`
+  Use example: ``f3write.h2w /media/michel/5EBD-5C80/``.
+
+- ``log-f3wr`` - Script that runs f3write and f3read, and records
+  their output into a log file.
+
+  Use example: ``log-f3wr log-filename /media/michel/5EBD-5C80/``.
 
 Please notice that all scripts and use examples above assume that
 f3write, f3read, and the scripts are in the same folder.
+
+Flakyflash
+----------
+
+If your flash isn't fraudulent (or you've run f3fix to "fix" it) but
+you're still seeing some sporadic data corruption, then you may have
+"flaky flash." If your flash is formatted using the FAT file system,
+then you can use `Flakyflash <https://github.com/whitslack/flakyflash>`__
+to find the flaky data clusters and mark them as bad in the FAT. This
+may allow you to get a little more use out of your flash, but you
+should still consider it as failing and replace it ASAP.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/f3-8.0/changelog new/f3-9.0/changelog
--- old/f3-8.0/changelog        2020-10-29 14:25:47.000000000 +0100
+++ new/f3-9.0/changelog        2025-03-27 14:18:19.000000000 +0100
@@ -1,16 +1,25 @@
+Version 9.0 - Mar 27, 2025
+
+    * f3read/f3write: Avoid the execution stack to list files
+    * f3read/f3write: Add dynamic buffers
+    * f3read/f3write: chroot(2) to source/target dir if allowed
+    * Portability improvements for Ubuntu, ARM, OpenBSD, and Apple
+    * Automated test of the code with GitHub Actions
+    * Improved documentation
+
 Version 8.0 - Oct 29, 2020
 
     * f3read: add parameter --max-read-rate
     * f3read: report speed, percentage, remaining time like f3write
     * f3write: improve speed measurement (commit 791acdc32627...)
-    * f3probe: handle rare assetion failure (issue #82 ENODATA)
+    * f3probe: handle rare assertion failure (issue #82 ENODATA)
 
 Version 7.2 - Jun 19, 2019
 
     * f3write: keep up with extremely fast NVM drives (issue #117)
     * f3write: improve measurement of write speed (issue #102)
-    * f3write: handle rare assetion failure (issue #111)
-    * f3probe: handle rare assetion failure (issue #82)
+    * f3write: handle rare assertion failure (issue #111)
+    * f3probe: handle rare assertion failure (issue #82)
 
 Version 7.1 - Jul 27, 2018
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/f3-8.0/doc/conf.py new/f3-9.0/doc/conf.py
--- old/f3-8.0/doc/conf.py      2020-10-29 14:25:47.000000000 +0100
+++ new/f3-9.0/doc/conf.py      2025-03-27 14:18:19.000000000 +0100
@@ -58,9 +58,9 @@
 # built documents.
 #
 # The short X.Y version.
-version = '8.0'
+version = '9.0'
 # The full version, including alpha/beta/rc tags.
-release = '8.0'
+release = '9.0'
 
 # The language for content autogenerated by Sphinx. Refer to documentation
 # for a list of supported languages.
@@ -105,6 +105,9 @@
 # The name of the Pygments (syntax highlighting) style to use.
 pygments_style = 'sphinx'
 
+# Disable default code block language being set to Python.
+highlight_language = 'none'
+
 # A list of ignored prefixes for module index sorting.
 # modindex_common_prefix = []
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/f3-8.0/doc/contribute.rst 
new/f3-9.0/doc/contribute.rst
--- old/f3-8.0/doc/contribute.rst       2020-10-29 14:25:47.000000000 +0100
+++ new/f3-9.0/doc/contribute.rst       2025-03-27 14:18:19.000000000 +0100
@@ -11,7 +11,7 @@
 How can you help?
 
 -  If F3 has helped you, consider signaling this to other users staring
-   F3 on GitHub. The larger the number of stars a project has, the more
+   F3 on `GitHub <https://github.com/AltraMayor/f3>`__. The larger the number 
of stars a project has, the more
    confident new users are to try it out.
 -  If you know a journalist, or are one, suggest to him or her writing
    an article about fake flash. The media has not been covering this
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/f3-8.0/doc/index.rst new/f3-9.0/doc/index.rst
--- old/f3-8.0/doc/index.rst    2020-10-29 14:25:47.000000000 +0100
+++ new/f3-9.0/doc/index.rst    2025-03-27 14:18:19.000000000 +0100
@@ -22,4 +22,3 @@
 * :ref:`genindex`
 * :ref:`modindex`
 * :ref:`search`
-
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/f3-8.0/doc/usage.rst new/f3-9.0/doc/usage.rst
--- old/f3-8.0/doc/usage.rst    2020-10-29 14:25:47.000000000 +0100
+++ new/f3-9.0/doc/usage.rst    2025-03-27 14:18:19.000000000 +0100
@@ -2,6 +2,7 @@
 =====
 
 .. contents::
+.. highlight:: console
 
 How to use f3write and f3read
 -----------------------------
@@ -91,7 +92,7 @@
         Slightly changed: 0.00 Byte (0 sectors)
              Overwritten: 0.00 Byte (0 sectors)
     Average Reading speed: 9.54 MB/s
-      
+
 
 This report shows that my flash card is pretty much garbage since it can
 only hold 1.02GB. ``f3write`` only writes to free space, and will not
@@ -107,7 +108,7 @@
 sector should be and in which position in that file the sector should
 be. Thus, if a sector is well formed, or with a few bits flipped, but
 read in an unexpected position, ``f3read`` counts it as overwritten.
-Slightly changed sectors, are sectors at right position with a fews bits
+Slightly changed sectors, are sectors at right position with a few bits
 flipped.
 
 Notice that ``f3write`` doesn't overwrite sectors by itself, it's done
@@ -206,7 +207,7 @@
         Slightly changed: 0.00 Byte (0 sectors)
              Overwritten: 0.00 Byte (0 sectors)
     Average Reading speed: 9.42 MB/s
-      
+
 
 Since ``f3write`` and ``f3read`` are independent, ``f3read`` can be used
 as many times as one wants, although ``f3write`` is needed only once.
@@ -214,8 +215,8 @@
 files are still available.
 
 As a final remark, if you want to run ``f3write`` and ``f3read`` with a
-single command, check out the shell script
-```log-f3wr`` <https://github.com/AltraMayor/f3/blob/master/log-f3wr>`__.
+single command, check out the ``log-f3wr`` shell script
+`here <https://github.com/AltraMayor/f3/blob/master/log-f3wr>`__.
 This script runs ``f3write`` and ``f3read``, and records their output
 into a log file. Use example:
 ``log-f3wr log-filename /media/michel/5EBD-5C80/``
@@ -256,22 +257,22 @@
 
     $ ./f3write --end-at=16 /media/michel/DISK_IMG/ && ./f3read 
/media/michel/DISK_IMG/
     Free space: 124.97 GB
-    Creating file 1.h2w ... OK!                               
-    Creating file 2.h2w ... OK!                           
-    Creating file 3.h2w ... OK!                           
-    Creating file 4.h2w ... OK!                           
-    Creating file 5.h2w ... OK!                           
-    Creating file 6.h2w ... OK!                           
-    Creating file 7.h2w ... OK!                         
-    Creating file 8.h2w ... OK!                         
-    Creating file 9.h2w ... OK!                         
-    Creating file 10.h2w ... OK!                         
-    Creating file 11.h2w ... OK!                         
-    Creating file 12.h2w ... OK!                         
-    Creating file 13.h2w ... OK!                         
-    Creating file 14.h2w ... OK!                         
-    Creating file 15.h2w ... OK!                         
-    Creating file 16.h2w ... OK!                        
+    Creating file 1.h2w ... OK!
+    Creating file 2.h2w ... OK!
+    Creating file 3.h2w ... OK!
+    Creating file 4.h2w ... OK!
+    Creating file 5.h2w ... OK!
+    Creating file 6.h2w ... OK!
+    Creating file 7.h2w ... OK!
+    Creating file 8.h2w ... OK!
+    Creating file 9.h2w ... OK!
+    Creating file 10.h2w ... OK!
+    Creating file 11.h2w ... OK!
+    Creating file 12.h2w ... OK!
+    Creating file 13.h2w ... OK!
+    Creating file 14.h2w ... OK!
+    Creating file 15.h2w ... OK!
+    Creating file 16.h2w ... OK!
     Free space: 108.97 GB
     Average writing speed: 2.87 MB/s
                       SECTORS      ok/corrupted/changed/overwritten
@@ -298,7 +299,7 @@
         Slightly changed: 0.00 Byte (0 sectors)
              Overwritten: 0.00 Byte (0 sectors)
     Average reading speed: 12.73 MB/s
-      
+
 
 After disconnecting the drive and connecting it back, ``f3read``
 produced the following output:
@@ -330,7 +331,7 @@
         Slightly changed: 0.00 Byte (0 sectors)
              Overwritten: 0.00 Byte (0 sectors)
     Average reading speed: 12.50 MB/s
-      
+
 
 Notice that file 16.h2w, that last file ``f3write`` wrote, has no longer
 good sectors. What happened is that the last sectors of 16.h2w were in
@@ -365,7 +366,7 @@
     Creating file 14.h2w ... OK!
     Free space: 755.80 MB
     Average writing speed: 13.77 MB/s
-      
+
 
 This happened because ext2 and some other file systems reserve space for
 special purposes. So they don't allow ``f3write`` to use that reserved
@@ -467,11 +468,11 @@
 ::
 
     $ truncate --size=/1M /media/michel/6135-3363/30.h2w
-      
+
 
 If you want to exchange files with H2testw users often, check out the
-shell script
-```f3write.h2w`` <https://github.com/AltraMayor/f3/blob/master/f3write.h2w>`__.
+``f3write.h2w`` shell script
+`here <https://github.com/AltraMayor/f3/blob/master/f3write.h2w>`__.
 This script calls ``truncate`` after ``f3write`` runs successfully.
 
 f3probe - the fastest drive test
@@ -575,15 +576,15 @@
 
 ::
 
-    $ lsblk 
+    $ lsblk
     NAME   MAJ:MIN RM   SIZE RO TYPE MOUNTPOINT
-    sda      8:0    0 232.9G  0 disk 
+    sda      8:0    0 232.9G  0 disk
     +-sda1   8:1    0   218G  0 part /
-    +-sda2   8:2    0     1K  0 part 
+    +-sda2   8:2    0     1K  0 part
     +-sda5   8:5    0    15G  0 part [SWAP]
-    sdb      8:16   1  15.3G  0 disk 
+    sdb      8:16   1  15.3G  0 disk
     +-sdb1   8:17   1  15.3G  0 part /media/michel/A902-D705
-    sr0     11:0    1  1024M  0 rom  
+    sr0     11:0    1  1024M  0 rom
 
 If you get confused between "sdb" and "sdb1", don't worry, ``f3probe``
 will report the mistake and point out the proper one. However, I cannot
@@ -597,8 +598,8 @@
 ::
 
     $ sudo ./f3probe --destructive --time-ops /dev/sdb
-    [sudo] password for michel: 
-    F3 probe 8.0
+    [sudo] password for michel:
+    F3 probe 9.0
     Copyright (C) 2010 Digirati Internet LTDA.
     This is free software; see the source for copying conditions.
 
@@ -672,8 +673,8 @@
 ::
 
     $ sudo ./f3probe --time-ops /dev/sdc
-    [sudo] password for michel: 
-    F3 probe 8.0
+    [sudo] password for michel:
+    F3 probe 9.0
     Copyright (C) 2010 Digirati Internet LTDA.
     This is free software; see the source for copying conditions.
 
@@ -733,7 +734,7 @@
 ::
 
     $ sudo ./f3fix --last-sec=16477878 /dev/sdb
-    F3 fix 8.0
+    F3 fix 9.0
     Copyright (C) 2010 Digirati Internet LTDA.
     This is free software; see the source for copying conditions.
 
@@ -757,14 +758,14 @@
 
     $ ./f3write /media/michel/8A34-CED2/
     Free space: 7.84 GB
-    Creating file 1.h2w ... OK!                         
-    Creating file 2.h2w ... OK!                         
-    Creating file 3.h2w ... OK!                         
-    Creating file 4.h2w ... OK!                         
-    Creating file 5.h2w ... OK!                         
-    Creating file 6.h2w ... OK!                         
-    Creating file 7.h2w ... OK!                        
-    Creating file 8.h2w ... OK!                        
+    Creating file 1.h2w ... OK!
+    Creating file 2.h2w ... OK!
+    Creating file 3.h2w ... OK!
+    Creating file 4.h2w ... OK!
+    Creating file 5.h2w ... OK!
+    Creating file 6.h2w ... OK!
+    Creating file 7.h2w ... OK!
+    Creating file 8.h2w ... OK!
     Free space: 0.00 Byte
     Average writing speed: 4.64 MB/s
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/f3-8.0/f3probe.c new/f3-9.0/f3probe.c
--- old/f3-8.0/f3probe.c        2020-10-29 14:25:47.000000000 +0100
+++ new/f3-9.0/f3probe.c        2025-03-27 14:18:19.000000000 +0100
@@ -230,7 +230,7 @@
        /* Extreme case for memory usage (limbo drive). */
        {(1ULL<<20)+512,1ULL << 40,     40,     9,      -1,     false},
 
-       /* Geomerty of a real limbo drive with 256MB of strict cache. */
+       /* Geometry of a real limbo drive with 256MB of strict cache. */
        {7600799744ULL, 67108864000ULL, 36,     9,      19,     true},
 
        /* The drive before with a non-strict cache. */
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/f3-8.0/f3read.1 new/f3-9.0/f3read.1
--- old/f3-8.0/f3read.1 2020-10-29 14:25:47.000000000 +0100
+++ new/f3-9.0/f3read.1 2025-03-27 14:18:19.000000000 +0100
@@ -1,5 +1,5 @@
 .\"Text automatically generated by txt2man
-.TH F3 "1"  "October 2020" "F3 8.0" "test real flash memory capacity"
+.TH F3 "1"  "October 2020" "F3 9.0" "test real flash memory capacity"
 .SH NAME
 \fBf3write, f3read \fP- test real flash memory capacity
 .SH SYNOPSIS
@@ -47,7 +47,7 @@
 .SH SEE ALSO
 For detailed information about the F3 tools, see:
 .PP
-http://oss.digirati.com.br/f3/
+https://fight-flash-fraud.readthedocs.io/en/stable/
 .SH AUTHOR
 F3 was written by Michel Machado <[email protected]>.
 This manual page was first written by Joao Eriberto Mota Filho 
<[email protected]>.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/f3-8.0/f3read.c new/f3-9.0/f3read.c
--- old/f3-8.0/f3read.c 2020-10-29 14:25:47.000000000 +0100
+++ new/f3-9.0/f3read.c 2025-03-27 14:18:19.000000000 +0100
@@ -191,15 +191,16 @@
        return done;
 }
 
-static ssize_t check_chunk(int fd, uint64_t *p_expected_offset,
-       uint64_t chunk_size, struct file_stats *stats)
+static ssize_t check_chunk(struct dynamic_buffer *dbuf, int fd,
+       uint64_t *p_expected_offset, uint64_t chunk_size,
+       struct file_stats *stats)
 {
-       char buf[MAX_BUFFER_SIZE];
+       char *buf = dbuf_get_buf(dbuf, chunk_size);
+       size_t len = dbuf_get_len(dbuf);
        ssize_t tot_bytes_read = 0;
 
        while (chunk_size > 0) {
-               size_t turn_size = chunk_size <= MAX_BUFFER_SIZE
-                       ? chunk_size : MAX_BUFFER_SIZE;
+               size_t turn_size = chunk_size <= len ? chunk_size : len;
                ssize_t bytes_read = read_all(fd, buf, turn_size);
 
                if (bytes_read < 0) {
@@ -235,6 +236,7 @@
        int fd, saved_errno;
        ssize_t bytes_read;
        uint64_t expected_offset;
+       struct dynamic_buffer dbuf;
 
        zero_fstats(stats);
 
@@ -257,17 +259,26 @@
         * even when testing small memory cards without a remount, and
         * we should have a better reading-speed measurement.
         */
-       assert(!fdatasync(fd));
+       if (fdatasync(fd) < 0) {
+               int saved_errno = errno;
+               /* The issue https://github.com/AltraMayor/f3/issues/211
+                * motivated the warning below.
+                */
+               printf("\nWARNING:\nThe operating system returned errno=%i for 
fdatasync(): %s\nThis error is unexpected and you may find more information on 
the log of the kernel (e.g. command dmesg(1) on Linux).\n\n",
+                       saved_errno, strerror(saved_errno));
+               exit(saved_errno);
+       }
        assert(!posix_fadvise(fd, 0, 0, POSIX_FADV_DONTNEED));
 
        /* Help the kernel to help us. */
        assert(!posix_fadvise(fd, 0, 0, POSIX_FADV_SEQUENTIAL));
 
+       dbuf_init(&dbuf);
        saved_errno = 0;
        expected_offset = (uint64_t)number * GIGABYTES;
        start_measurement(fw);
        while (true) {
-               bytes_read = check_chunk(fd, &expected_offset,
+               bytes_read = check_chunk(&dbuf, fd, &expected_offset,
                        get_rem_chunk_size(fw), stats);
                if (bytes_read == 0)
                        break;
@@ -297,6 +308,7 @@
        }
        printf("\n");
 
+       dbuf_free(&dbuf);
        close(fd);
        free(full_fn);
 }
@@ -404,7 +416,7 @@
        if (has_enough_measurements(&fw)) {
                pr_avg_speed(get_avg_speed(&fw));
        } else {
-               /* If the drive is too fast for the measuments above,
+               /* If the drive is too fast for the measurements above,
                 * try a coarse approximation of the reading speed.
                 */
                int64_t total_time_ms = delay_ms(&t1, &t2);
@@ -426,7 +438,7 @@
                .start_at       = 0,
                .end_at         = LONG_MAX - 1,
                .max_read_rate  = 0,
-               /* If stdout isn't a terminal, supress progress. */
+               /* If stdout isn't a terminal, suppress progress. */
                .show_progress  = isatty(STDOUT_FILENO),
        };
 
@@ -434,6 +446,8 @@
        argp_parse(&argp, argc, argv, 0, NULL, &args);
        print_header(stdout, "read");
 
+       adjust_dev_path(&args.dev_path);
+
        files = ls_my_files(args.dev_path, args.start_at, args.end_at);
 
        iterate_files(args.dev_path, files, args.start_at, args.end_at,
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/f3-8.0/f3write.c new/f3-9.0/f3write.c
--- old/f3-8.0/f3write.c        2020-10-29 14:25:47.000000000 +0100
+++ new/f3-9.0/f3write.c        2025-03-27 14:18:19.000000000 +0100
@@ -150,13 +150,14 @@
        return 0;
 }
 
-static int write_chunk(int fd, size_t chunk_size, uint64_t *poffset)
+static int write_chunk(struct dynamic_buffer *dbuf, int fd, size_t chunk_size,
+       uint64_t *poffset)
 {
-       char buf[MAX_BUFFER_SIZE];
+       char *buf = dbuf_get_buf(dbuf, chunk_size);
+       size_t len = dbuf_get_len(dbuf);
 
        while (chunk_size > 0) {
-               size_t turn_size = chunk_size <= MAX_BUFFER_SIZE
-                       ? chunk_size : MAX_BUFFER_SIZE;
+               size_t turn_size = chunk_size <= len ? chunk_size : len;
                int ret;
                chunk_size -= turn_size;
                *poffset = fill_buffer(buf, turn_size, *poffset);
@@ -177,6 +178,7 @@
        int fd, saved_errno;
        size_t remaining;
        uint64_t offset;
+       struct dynamic_buffer dbuf;
 
        assert(size > 0);
        assert(size % fw->block_size == 0);
@@ -198,6 +200,7 @@
        assert(fd >= 0);
 
        /* Write content. */
+       dbuf_init(&dbuf);
        saved_errno = 0;
        offset = (uint64_t)number * GIGABYTES;
        remaining = size;
@@ -206,7 +209,7 @@
                uint64_t write_size = get_rem_chunk_size(fw);
                if (write_size > remaining)
                        write_size = remaining;
-               saved_errno = write_chunk(fd, write_size, &offset);
+               saved_errno = write_chunk(&dbuf, fd, write_size, &offset);
                if (saved_errno)
                        break;
                remaining -= write_size;
@@ -220,6 +223,7 @@
                if (!saved_errno)
                        saved_errno = errno;
        }
+       dbuf_free(&dbuf);
        close(fd);
        free(full_fn);
 
@@ -320,7 +324,7 @@
        if (has_enough_measurements(&fw)) {
                pr_avg_speed(get_avg_speed(&fw));
        } else {
-               /* If the drive is too fast for the measuments above,
+               /* If the drive is too fast for the measurements above,
                 * try a coarse approximation of the writing speed.
                 */
                int64_t total_time_ms = delay_ms(&t1, &t2);
@@ -360,7 +364,7 @@
                .start_at       = 0,
                .end_at         = LONG_MAX - 1,
                .max_write_rate = 0,
-               /* If stdout isn't a terminal, supress progress. */
+               /* If stdout isn't a terminal, suppress progress. */
                .show_progress  = isatty(STDOUT_FILENO),
        };
 
@@ -368,6 +372,8 @@
        argp_parse(&argp, argc, argv, 0, NULL, &args);
        print_header(stdout, "write");
 
+       adjust_dev_path(&args.dev_path);
+
        unlink_old_files(args.dev_path, args.start_at, args.end_at);
 
        return fill_fs(args.dev_path, args.start_at, args.end_at,
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/f3-8.0/f3write.h2w new/f3-9.0/f3write.h2w
--- old/f3-8.0/f3write.h2w      2020-10-29 14:25:47.000000000 +0100
+++ new/f3-9.0/f3write.h2w      2025-03-27 14:18:19.000000000 +0100
@@ -1,4 +1,4 @@
-#!/bin/bash
+#!/usr/bin/env bash
 
 $(dirname $0)/f3write "$@" || exit 1
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/f3-8.0/libdevs.c new/f3-9.0/libdevs.c
--- old/f3-8.0/libdevs.c        2020-10-29 14:25:47.000000000 +0100
+++ new/f3-9.0/libdevs.c        2025-03-27 14:18:19.000000000 +0100
@@ -580,13 +580,13 @@
                action = udev_device_get_action(dev);
                new_size_byte = get_udev_dev_size_byte(dev);
                if (!strcmp(action, "add")) {
-                       /* Deal with the case in wich the user pulls
+                       /* Deal with the case in which the user pulls
                         * the USB device.
                         *
                         * DO NOTHING.
                         */
                } else if (!strcmp(action, "change")) {
-                       /* Deal with the case in wich the user pulls
+                       /* Deal with the case in which the user pulls
                         * the memory card from the card reader.
                         */
 
@@ -712,7 +712,7 @@
        bdev->fd = bdev_open(bdev->filename);
        if (bdev->fd < 0) {
                rc = - errno;
-               warn("Can't REopen device `%s'", bdev->filename);
+               warn("Can't reopen device `%s'", bdev->filename);
                goto usb_dev;
        }
 
@@ -808,7 +808,7 @@
        bdev->fd = bdev_open(bdev->filename);
        if (bdev->fd < 0) {
                int rc = - errno;
-               warn("Can't REopen device `%s'", bdev->filename);
+               warn("Can't reopen device `%s'", bdev->filename);
                return rc;
        }
        return 0;
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/f3-8.0/libdevs.h new/f3-9.0/libdevs.h
--- old/f3-8.0/libdevs.h        2020-10-29 14:25:47.000000000 +0100
+++ new/f3-9.0/libdevs.h        2025-03-27 14:18:19.000000000 +0100
@@ -60,7 +60,7 @@
  * batch writes or reads.
  *
  * It must be a power of 2 greater than, or equal to 2^20.
- * The current vaule is 1MB.
+ * The current value is 1MB.
  */
 #define BIG_BLOCK_SIZE_BYTE (1 << 20)
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/f3-8.0/libflow.c new/f3-9.0/libflow.c
--- old/f3-8.0/libflow.c        2020-10-29 14:25:47.000000000 +0100
+++ new/f3-9.0/libflow.c        2025-03-27 14:18:19.000000000 +0100
@@ -184,16 +184,16 @@
 }
 
 static inline int is_rate_above(const struct flow *fw,
-       long delay, double inst_speed)
+       uint64_t delay, double inst_speed)
 {
        /* We use logical or here to enforce the lowest limit. */
        return delay > fw->delay_ms || inst_speed > fw->max_process_rate;
 }
 
 static inline int is_rate_below(const struct flow *fw,
-       long delay, double inst_speed)
+       uint64_t delay, double inst_speed)
 {
-       /* We use logical and here to enforce both limist. */
+       /* We use logical and here to enforce both limits. */
        return delay <= fw->delay_ms && inst_speed < fw->max_process_rate;
 }
 
@@ -216,7 +216,7 @@
 {
        ldiv_t result = ldiv(processed, fw->block_size);
        struct timeval t2;
-       int64_t delay;
+       uint64_t delay;
        double bytes_k, inst_speed;
 
        assert(result.rem == 0);
@@ -366,3 +366,45 @@
        }
        return ret;
 }
+
+static inline void __dbuf_free(struct dynamic_buffer *dbuf)
+{
+       if (dbuf->buf != dbuf->backup_buf)
+               free(dbuf->buf);
+}
+
+void dbuf_free(struct dynamic_buffer *dbuf)
+{
+       __dbuf_free(dbuf);
+       dbuf->buf = NULL;
+       dbuf->len = 0;
+       dbuf->max_buf = true;
+}
+
+char *dbuf_get_buf(struct dynamic_buffer *dbuf, size_t size)
+{
+       /* If enough buffer, or it's already the largest buffer, return it. */
+       if (size <= dbuf->len || dbuf->max_buf)
+               return dbuf->buf;
+
+       /*
+        * Allocate a new buffer.
+        */
+
+       __dbuf_free(dbuf);
+       do {
+               dbuf->buf = malloc(size);
+               if (dbuf->buf != NULL) {
+                       dbuf->len = size;
+                       return dbuf->buf;
+               } else {
+                       dbuf->max_buf = true;
+               }
+               size /= 2;
+       } while (size > sizeof(dbuf->backup_buf));
+
+       /* A larger buffer is not available; failsafe. */
+       dbuf->buf = dbuf->backup_buf;
+       dbuf->len = sizeof(dbuf->backup_buf);
+       return dbuf->buf;
+}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/f3-8.0/libflow.h new/f3-9.0/libflow.h
--- old/f3-8.0/libflow.h        2020-10-29 14:25:47.000000000 +0100
+++ new/f3-9.0/libflow.h        2025-03-27 14:18:19.000000000 +0100
@@ -2,6 +2,7 @@
 #define HEADER_LIBFLOW_H
 
 #include <stdint.h>
+#include <stdbool.h>
 
 struct flow;
 
@@ -16,7 +17,7 @@
        int             progress;
        /* Block size in bytes. */
        int             block_size;
-       /* Delay intended between measurements in miliseconds. */
+       /* Delay intended between measurements in milliseconds. */
        unsigned int    delay_ms;
        /* Increment to apply to @blocks_per_delay. */
        int64_t         step;
@@ -90,6 +91,31 @@
        return (fw->blocks_per_delay - fw->processed_blocks) * fw->block_size;
 }
 
-#define MAX_BUFFER_SIZE        (1<<21) /* 2MB */
+struct dynamic_buffer {
+       char   *buf;
+       size_t len;
+       bool   max_buf;
+       char   backup_buf[1 << 21]; /* 2MB */
+};
+
+static inline void dbuf_init(struct dynamic_buffer *dbuf)
+{
+       dbuf->buf = dbuf->backup_buf;
+       dbuf->len = sizeof(dbuf->backup_buf);
+       dbuf->max_buf = false;
+}
+
+void dbuf_free(struct dynamic_buffer *dbuf);
+
+/*
+ * Although the returned buffer may be smaller than @size,
+ * this function never returns NULL.
+ */
+char *dbuf_get_buf(struct dynamic_buffer *dbuf, size_t size);
+
+static inline size_t dbuf_get_len(const struct dynamic_buffer *dbuf)
+{
+       return dbuf->len;
+}
 
 #endif /* HEADER_LIBFLOW_H */
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/f3-8.0/libprobe.c new/f3-9.0/libprobe.c
--- old/f3-8.0/libprobe.c       2020-10-29 14:25:47.000000000 +0100
+++ new/f3-9.0/libprobe.c       2025-03-27 14:18:19.000000000 +0100
@@ -159,7 +159,7 @@
 
        assert(n_blocks >= 1);
 
-       /* Find coeficients of function a*idx + b where idx <= max_idx. */
+       /* Find coefficients of function a*idx + b where idx <= max_idx. */
        assert(left_pos < right_pos);
        assert(right_pos - left_pos >= 2);
        *pb = left_pos + 1;
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/f3-8.0/libutils.c new/f3-9.0/libutils.c
--- old/f3-8.0/libutils.c       2020-10-29 14:25:47.000000000 +0100
+++ new/f3-9.0/libutils.c       2025-03-27 14:18:19.000000000 +0100
@@ -209,7 +209,7 @@
 
        /* The offset is known by drives,
         * so one doesn't have to encrypt it.
-        * Plese don't add @salt here!
+        * Please don't add @salt here!
         */
        int64_array[0] = offset;
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/f3-8.0/log-f3wr new/f3-9.0/log-f3wr
--- old/f3-8.0/log-f3wr 2020-10-29 14:25:47.000000000 +0100
+++ new/f3-9.0/log-f3wr 2025-03-27 14:18:19.000000000 +0100
@@ -1,4 +1,4 @@
-#!/bin/bash
+#!/usr/bin/env bash
 LOG=$1
 $(dirname $0)/f3write "${@:2}" 2>&1 | tee -a "${LOG}" && \
 echo -e "\n\n" >> "${LOG}" && \
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/f3-8.0/utils.c new/f3-9.0/utils.c
--- old/f3-8.0/utils.c  2020-10-29 14:25:47.000000000 +0100
+++ new/f3-9.0/utils.c  2025-03-27 14:18:19.000000000 +0100
@@ -10,6 +10,7 @@
 
 #include <stdio.h>
 #include <stdlib.h>
+#include <stdbool.h>
 #include <string.h>
 #include <ctype.h>
 #include <assert.h>
@@ -17,10 +18,25 @@
 #include <dirent.h>
 #include <errno.h>
 #include <err.h>
+#include <unistd.h>
 
 #include "version.h"
 #include "utils.h"
 
+void adjust_dev_path(const char **dev_path)
+{
+       if (chdir(*dev_path)) {
+               err(errno, "Can't change working directory to %s at %s()", 
*dev_path, __func__);
+       }
+       *dev_path = ".";
+
+       if (!chroot(*dev_path)) {
+               assert(!chdir("/"));
+       } else if (errno != EPERM) {
+               err(errno, "Can't change root directory to %s at %s()", 
*dev_path, __func__);
+       }
+}
+
 const char *adjust_unit(double *ptr_bytes)
 {
        const char *units[] = { "Byte", "KB", "MB", "GB", "TB", "PB", "EB" };
@@ -76,40 +92,77 @@
        return num - 1;
 }
 
-/* Don't call this function directly, use ls_my_files() instead. */
-static long *__ls_my_files(DIR *dir, long start_at, long end_at,
-       int *pcount, int *pindex)
+static inline bool include_this_file(const char *filename,
+       long start_at, long end_at, long *number)
+{
+       if (!is_my_file(filename))
+               return false;
+
+       *number = number_from_filename(filename);
+
+       return start_at <= *number && *number <= end_at;
+}
+
+static long count_files(const char *path, long start_at, long end_at)
 {
+       DIR *dir = opendir(path);
        struct dirent *entry;
-       const char *filename;
-       long number, *ret;
-       int my_index;
+       long dummy, total = 0;
+
+       if (!dir)
+               err(errno, "Can't open path %s at %s()", path, __func__);
 
        entry = readdir(dir);
-       if (!entry) {
-               ret = malloc(sizeof(long) * (*pcount + 1));
-               assert(ret);
-               *pindex = *pcount - 1;
-               ret[*pcount] = -1;
-               closedir(dir);
-               return ret;
+       while (entry) {
+               if (include_this_file(entry->d_name, start_at, end_at, &dummy))
+                       total++;
+               entry = readdir(dir);
        }
+       closedir(dir);
 
-       filename = entry->d_name;
-       if (!is_my_file(filename))
-               return __ls_my_files(dir, start_at, end_at, pcount, pindex);
+       return total;
+}
+
+/* Don't call this function directly, use ls_my_files() instead. */
+static long *__ls_my_files(const char *path, long start_at, long end_at,
+       long *pcount)
+{
+       long total_files = count_files(path, start_at, end_at);
+       DIR *dir;
+       struct dirent *entry;
+       long *ret, index;
+
+       assert(total_files >= 0);
+       ret = malloc(sizeof(*ret) * (total_files + 1));
+       assert(ret);
+
+       dir = opendir(path);
+       if (!dir)
+               err(errno, "Can't open path %s at %s()", path, __func__);
+
+       entry = readdir(dir);
+       index = 0;
+       while (entry) {
+               long number;
+               if (include_this_file(entry->d_name, start_at, end_at,
+                               &number)) {
+                       if (index >= total_files) {
+                               /* The folder @path received more files
+                                * before we finished scanning it.
+                                */
+                               closedir(dir);
+                               free(ret);
+                               return NULL;
+                       }
+                       ret[index++] = number;
+               }
 
-       /* Cache @number because @entry may go away. */
-       number = number_from_filename(filename);
+               entry = readdir(dir);
+       }
+       closedir(dir);
 
-       /* Ignore files before @start_at and after @end_at. */
-       if (number < start_at || end_at < number)
-               return __ls_my_files(dir, start_at, end_at, pcount, pindex);
-
-       (*pcount)++;
-       ret = __ls_my_files(dir, start_at, end_at, pcount, &my_index);
-       ret[my_index] = number;
-       *pindex = my_index - 1;
+       ret[index] = -1;
+       *pcount = index;
        return ret;
 }
 
@@ -121,17 +174,12 @@
 
 const long *ls_my_files(const char *path, long start_at, long end_at)
 {
-       DIR *dir = opendir(path);
-       int my_count;
-       int my_index;
-       long *ret;
+       long *ret, my_count;
 
-       if (!dir)
-               err(errno, "Can't open path %s", path);
+       do {
+               ret = __ls_my_files(path, start_at, end_at, &my_count);
+       } while (!ret);
 
-       my_count = 0;
-       ret = __ls_my_files(dir, start_at, end_at, &my_count, &my_index);
-       assert(my_index == -1);
        qsort(ret, my_count, sizeof(*ret), cmpintp);
        return ret;
 }
@@ -179,14 +227,16 @@
        }
 }
 
-#include <unistd.h> /* For usleep(). */
+#endif /* Apple Macintosh */
+
+#if (__APPLE__ && __MACH__) || defined(__OpenBSD__)
 
 void msleep(double wait_ms)
 {
        assert(!usleep(wait_ms * 1000));
 }
 
-#else
+#else  /* Apple Macintosh / OpenBSD */
 
 #include <time.h> /* For clock_gettime() and clock_nanosleep(). */
 
@@ -221,4 +271,4 @@
        assert(ret == 0);
 }
 
-#endif
+#endif /* Apple Macintosh / OpenBSD */
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/f3-8.0/utils.h new/f3-9.0/utils.h
--- old/f3-8.0/utils.h  2020-10-29 14:25:47.000000000 +0100
+++ new/f3-9.0/utils.h  2025-03-27 14:18:19.000000000 +0100
@@ -9,6 +9,8 @@
 #define SECTOR_SIZE (512)
 #define GIGABYTES   (1024 * 1024 * 1024)
 
+void adjust_dev_path(const char **dev_path);
+
 const char *adjust_unit(double *ptr_bytes);
 
 /* Return true if @filename matches the regex /^[0-9]+\.h2w$/ */
@@ -55,4 +57,20 @@
 #define fdatasync(fd) fsync(fd)
 #endif
 
+#ifdef __OpenBSD__
+
+#define POSIX_FADV_SEQUENTIAL  2 /* Expect sequential page references. */
+#define POSIX_FADV_DONTNEED    4 /* Don't need these pages.            */
+
+/*
+ * OpenBSD doesn't have posix_fadvise() (...).
+ * There is some code [in F3] to emulate posix_fadvise for MacOS
+ * but it uses various fcntl(2) commands that we don't have [in OpenBSD].
+ *
+ *  -- Stuart Henderson, OpenBSD developer
+ */
+#define posix_fadvise(fd, offset, len, advice) (0)
+
+#endif /* OpenBSD */
+
 #endif /* HEADER_UTILS_H */
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/f3-8.0/version.h new/f3-9.0/version.h
--- old/f3-8.0/version.h        2020-10-29 14:25:47.000000000 +0100
+++ new/f3-9.0/version.h        2025-03-27 14:18:19.000000000 +0100
@@ -1,6 +1,6 @@
 #ifndef HEADER_VERSION_H
 #define HEADER_VERSION_H
 
-#define F3_STR_VERSION "8.0"
+#define F3_STR_VERSION "9.0"
 
 #endif /* HEADER_VERSION_H */

Reply via email to