The branch main has been updated by imp:

URL: 
https://cgit.FreeBSD.org/src/commit/?id=bec5a3c046ba2bd970679a31f7227f260bef4935

commit bec5a3c046ba2bd970679a31f7227f260bef4935
Author:     Warner Losh <i...@freebsd.org>
AuthorDate: 2025-01-14 17:32:01 +0000
Commit:     Warner Losh <i...@freebsd.org>
CommitDate: 2025-01-14 17:52:54 +0000

    nextboot: Smarter warning about deleting nextboot
    
    Read only filesystems always error when trying to remove something
    with EROFS. However, that's true even if the file isn't there. The
    code assumed it would always get a ENOENT if the file wasn't there,
    but produced a gross message on read only systems. This message was
    harmless, but annoying. Instead, stat the file first and return if
    it's already not there.
    
    Some readings of POSIX require that the ENOENT error take precidence
    over the EROFS error. Linux made this change years ago, and we should
    too. POSIX.1-2024 isn't explicit, but does say for unlink() does say
    "[EROFS] The directory entry to be unlinked is part of a read-only file
    system" and "[ENOENT] A component of path does not name an existing
    file" implying that EROFS should only be returned for an existing
    file. FreeBSD doesn't implement this, so this workaround is
    necessary. Ideally, we'd fix this in the kernel in the future.
    
    Sponsored by: Netflix
    Discussed with: jrtc23
    Differential Revision:  https://reviews.freebsd.org/D48425
---
 sbin/reboot/reboot.c | 17 ++++++++++++++++-
 1 file changed, 16 insertions(+), 1 deletion(-)

diff --git a/sbin/reboot/reboot.c b/sbin/reboot/reboot.c
index c6b0e0980c88..9825d4f96319 100644
--- a/sbin/reboot/reboot.c
+++ b/sbin/reboot/reboot.c
@@ -308,7 +308,22 @@ main(int argc, char *argv[])
                errx(1, "-r and -k cannot be used together, there is no next 
kernel");
 
        if (Dflag) {
-               if (unlink(PATH_NEXTBOOT) != 0 && errno != ENOENT)
+               struct stat sb;
+
+               /*
+                * Break the rule about stat then doing
+                * something. When we're booting, there's no
+                * race. When we're a read-only root, though, the
+                * read-only error takes priority over the file not
+                * there error in unlink. So stat it first and exit
+                * with success if it isn't there. Otherwise, let
+                * unlink sort error reporting. POSIX-1.2024 suggests
+                * ENOENT should be preferred to EROFS for unlink,
+                * but FreeBSD historically has preferred EROFS.
+                */
+               if (stat(PATH_NEXTBOOT, &sb) != 0 && errno == ENOENT)
+                       exit(0);
+               if (unlink(PATH_NEXTBOOT) != 0)
                        warn("unlink " PATH_NEXTBOOT);
                exit(0);
        }

Reply via email to