diff --git a/gnu/system/file-systems.scm b/gnu/system/file-systems.scm index 4cc1221eb8..fa56853fd1 100644 --- a/gnu/system/file-systems.scm +++ b/gnu/system/file-systems.scm @@ -1,5 +1,5 @@ ;;; GNU Guix --- Functional package management for GNU -;;; Copyright © 2013, 2014, 2015, 2016 Ludovic Courtès +;;; Copyright © 2013, 2014, 2015, 2016, 2017 Ludovic Courtès ;;; ;;; This file is part of GNU Guix. ;;; @@ -95,11 +95,39 @@ (dependencies file-system-dependencies ; list of (default '()))) ; or -(define-inlinable (file-system-needed-for-boot? fs) - "Return true if FS has the 'needed-for-boot?' flag set, or if it's the root -file system." +(define %not-slash + (char-set-complement (char-set #\/))) + +(define (file-prefix? file1 file2) + "Return #t if FILE1 denotes the name of a file that is a parent of FILE2, +where both FILE1 and FILE2 are absolute file name. For example: + + (file-prefix? \"/gnu\" \"/gnu/store\") + => #t + + (file-prefix? \"/gn\" \"/gnu/store\") + => #f +" + (and (string-prefix? "/" file1) + (string-prefix? "/" file2) + (let loop ((file1 (string-tokenize file1 %not-slash)) + (file2 (string-tokenize file2 %not-slash))) + (match file1 + (() + #t) + ((head1 tail1 ...) + (match file2 + ((head2 tail2 ...) + (and (string=? head1 head2) (loop tail1 tail2))) + (() + #f))))))) + +(define (file-system-needed-for-boot? fs) + "Return true if FS has the 'needed-for-boot?' flag set, or if it holds the +store--e.g., if FS is the root file system." (or (%file-system-needed-for-boot? fs) - (string=? "/" (file-system-mount-point fs)))) + (and (file-prefix? (file-system-mount-point fs) (%store-prefix)) + (not (memq 'bind-mount (file-system-flags fs)))))) (define (file-system->spec fs) "Return a list corresponding to file-system FS that can be passed to the diff --git a/gnu/tests/install.scm b/gnu/tests/install.scm index ae54154c5c..4e8d594054 100644 --- a/gnu/tests/install.scm +++ b/gnu/tests/install.scm @@ -1,5 +1,5 @@ ;;; GNU Guix --- Functional package management for GNU -;;; Copyright © 2016 Ludovic Courtès +;;; Copyright © 2016, 2017 Ludovic Courtès ;;; ;;; This file is part of GNU Guix. ;;; @@ -257,8 +257,7 @@ build (current-guix) and then store a couple of full system images.") (device "store-fs") (title 'label) (mount-point "/gnu") - (type "ext4") - (needed-for-boot? #t)) ;definitely! + (type "ext4")) %base-file-systems)) (users %base-user-accounts) (services (cons (service marionette-service-type diff --git a/tests/file-systems.scm b/tests/file-systems.scm index aed27e89c2..fd1599e132 100644 --- a/tests/file-systems.scm +++ b/tests/file-systems.scm @@ -1,5 +1,5 @@ ;;; GNU Guix --- Functional package management for GNU -;;; Copyright © 2015 Ludovic Courtès +;;; Copyright © 2015, 2017 Ludovic Courtès ;;; ;;; This file is part of GNU Guix. ;;; @@ -17,6 +17,7 @@ ;;; along with GNU Guix. If not, see . (define-module (test-file-systems) + #:use-module (guix store) #:use-module (gnu system file-systems) #:use-module (srfi srfi-64) #:use-module (rnrs bytevectors)) @@ -50,4 +51,25 @@ (string-contains message "invalid UUID") (equal? form '(uuid "foobar")))))) +(test-assert "file-system-needed-for-boot?" + (let-syntax ((dummy-fs (syntax-rules () + ((_ directory) + (file-system + (device "foo") + (mount-point directory) + (type "ext4")))))) + (parameterize ((%store-prefix "/gnu/guix/store")) + (and (file-system-needed-for-boot? (dummy-fs "/")) + (file-system-needed-for-boot? (dummy-fs "/gnu")) + (file-system-needed-for-boot? (dummy-fs "/gnu/guix")) + (file-system-needed-for-boot? (dummy-fs "/gnu/guix/store")) + (not (file-system-needed-for-boot? + (dummy-fs "/gnu/guix/store/foo"))) + (not (file-system-needed-for-boot? (dummy-fs "/gn"))) + (not (file-system-needed-for-boot? + (file-system + (inherit (dummy-fs (%store-prefix))) + (device "/foo") + (flags '(bind-mount read-only))))))))) + (test-end)