[bug#77201,v2] guix: substitute-key-authorization: Fix case when acl symlink is broken

Message ID bb8060e580fe7e60e3f7edd067d0f35648576e71.1745827664.git.rutherther@ditigal.xyz
State New
Headers
Series [bug#77201,v2] guix: substitute-key-authorization: Fix case when acl symlink is broken |

Commit Message

Rutherther April 28, 2025, 8:07 a.m. UTC
  One possible solution for an issue when /etc/guix/acl file exists, but points
to a non-existent location. This can for example happen if one is
reinitializing the system, and remove only /gnu/store and /var/guix, keep the
rest okay. This is a major advantage of guix as compared to other distros that
usually need you to reinitialize the whole root partition. But this will leave
the user with acl file pointing to non-existent location. The file-exists?
procedure will return #f for broken symbolic links.

I think that another reason one would get this issue is, if one was booted in
a live iso, chrooted, fixing their system. They would switch generations to
one with different acl file, delete other generations gc rooting the original
acl file and then gc. One could do this approach for example when recovering
from file corruptions in the store, to get rid of the unsubstitutable paths
that can't be repaired with guix gc --verify.

This fixes the issue by looking for type of a file through lstat, instead of
relying on file-exists?. If the symlink is a broken symlink, it is
removed. Other than that the old behavior is kept:
- If regular file, back it up
- If symlink pointing to the store, remove it
- If symlink not pointing to the store, back it up

* gnu/services/base.scm (substitute-key-authorization): Check if acl file is a
(broken) symbolic link

Change-Id: I2f8170606b2f4afeea48f04acfd738b04cafc7cf
---
 gnu/services/base.scm | 19 ++++++++++++-------
 1 file changed, 12 insertions(+), 7 deletions(-)


base-commit: 56999614a45449c4b93c8614540210b609c2b356
  

Patch

diff --git a/gnu/services/base.scm b/gnu/services/base.scm
index 8c6563c99d..02b4274e9d 100644
--- a/gnu/services/base.scm
+++ b/gnu/services/base.scm
@@ -1841,17 +1841,22 @@  (define (substitute-key-authorization keys guix)
 
   (with-imported-modules '((guix build utils))
     #~(begin
-        (use-modules (guix build utils))
+        (use-modules (guix build utils)
+                     (ice-9 match))
         (define acl-file #$%acl-file)
         ;; If the ACL already exists, move it out of the way.  Create a backup
         ;; if it's a regular file: it's likely that the user manually updated
         ;; it with 'guix archive --authorize'.
-        (if (file-exists? acl-file)
-            (if (and (symbolic-link? acl-file)
-                     (store-file-name? (readlink acl-file)))
-                (delete-file acl-file)
-                (rename-file acl-file (string-append acl-file ".bak")))
-            (mkdir-p (dirname acl-file)))
+        (match (and=> (false-if-exception (lstat acl-file)) stat:type)
+          (#f #f) ;file doesn't exist
+          ('symlink ;delete symlink pointing to store; backup otherwise.
+           (if (or (store-file-name? (readlink acl-file)) ;store symlink
+                   (not (file-exists? acl-file))) ;broken symlink
+               (delete-file acl-file)
+               (rename-file acl-file (string-append acl-file ".bak"))))
+          (_ ;backup
+           (rename-file acl-file (string-append acl-file ".bak"))))
+        (mkdir-p (dirname acl-file))
 
         ;; Installed the declared ACL.
         (symlink #+default-acl acl-file))))