gexp: 'computed-file' always uses a native Guile.
[jackhill/guix/guix.git] / gnu / system / file-systems.scm
CommitLineData
c5df1839 1;;; GNU Guix --- Functional package management for GNU
5eb5c078 2;;; Copyright © 2013-2021 Ludovic Courtès <ludo@gnu.org>
5627bfe4 3;;; Copyright © 2020 Google LLC
2ef4d273 4;;; Copyright © 2020 Jakub Kądziołka <kuba@kadziolka.net>
7cde70c7 5;;; Copyright © 2020, 2021 Maxim Cournoyer <maxim.cournoyer@gmail.com>
60299484 6;;; Copyright © 2021 Tobias Geerinckx-Rice <me@tobias.gr>
c5df1839
LC
7;;;
8;;; This file is part of GNU Guix.
9;;;
10;;; GNU Guix is free software; you can redistribute it and/or modify it
11;;; under the terms of the GNU General Public License as published by
12;;; the Free Software Foundation; either version 3 of the License, or (at
13;;; your option) any later version.
14;;;
15;;; GNU Guix is distributed in the hope that it will be useful, but
16;;; WITHOUT ANY WARRANTY; without even the implied warranty of
17;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18;;; GNU General Public License for more details.
19;;;
20;;; You should have received a copy of the GNU General Public License
21;;; along with GNU Guix. If not, see <http://www.gnu.org/licenses/>.
22
23(define-module (gnu system file-systems)
575b4b09 24 #:use-module (ice-9 match)
9976c76a 25 #:use-module (rnrs bytevectors)
7597478e 26 #:use-module (srfi srfi-1)
b460ba79 27 #:use-module (srfi srfi-2)
a5acc17a 28 #:use-module (srfi srfi-9)
b460ba79
MC
29 #:use-module (srfi srfi-26)
30 #:use-module (srfi srfi-35)
a5acc17a 31 #:use-module (srfi srfi-9 gnu)
c5df1839 32 #:use-module (guix records)
5eb5c078
LC
33 #:use-module ((guix diagnostics)
34 #:select (source-properties->location leave &fix-hint))
7a0bf3d5 35 #:use-module (guix i18n)
9b336338 36 #:use-module (gnu system uuid)
47cef4ec
LC
37 #:re-export (uuid ;backward compatibility
38 string->uuid
f8865db6 39 uuid->string)
a48d3450 40 #:export (file-system
c5df1839
LC
41 file-system?
42 file-system-device
99e676db 43 file-system-device->string
a5acc17a 44 file-system-title ;deprecated
c5df1839
LC
45 file-system-mount-point
46 file-system-type
47 file-system-needed-for-boot?
48 file-system-flags
49 file-system-options
fa35fb58
MC
50 file-system-options->alist
51 alist->file-system-options
52
be21979d 53 file-system-mount?
7c27bd11 54 file-system-mount-may-fail?
4e469051 55 file-system-check?
60299484
TGR
56 file-system-skip-check-if-clean?
57 file-system-repair
4e469051 58 file-system-create-mount-point?
e51710d1 59 file-system-dependencies
dd41a7f8 60 file-system-location
c5df1839 61
278d486b 62 file-system-type-predicate
b460ba79
MC
63 btrfs-subvolume?
64 btrfs-store-subvolume-file-name
278d486b 65
a5acc17a
LC
66 file-system-label
67 file-system-label?
68 file-system-label->string
69
575b4b09 70 file-system->spec
5970e8e2 71 spec->file-system
d77a0bd6 72 specification->file-system-mapping
575b4b09 73
6ddb5960 74 %pseudo-file-system-types
c5df1839 75 %fuse-control-file-system
a69576ea 76 %binary-format-file-system
6bb07e91 77 %debug-file-system
f94835a9 78 %efivars-file-system
705f8b68
MW
79 %shared-memory-file-system
80 %pseudo-terminal-file-system
3c185b24 81 %tty-gid
3392ce5d 82 %immutable-store
727636aa 83 %control-groups
14454f0b 84 %elogind-file-systems
a69576ea 85
5dae0186 86 %base-file-systems
c829bc80 87 %container-file-systems
5dae0186 88
9110c2e9
DT
89 <file-system-mapping>
90 file-system-mapping
91 file-system-mapping?
92 file-system-mapping-source
93 file-system-mapping-target
94 file-system-mapping-writable?
95
d2a5e698
LC
96 file-system-mapping->bind-mount
97
7597478e
LC
98 %store-mapping
99 %network-configuration-files
133a61ae
JP
100 %network-file-mappings
101
102 swap-space
103 swap-space?
104 swap-space-target
0831dfab
JP
105 swap-space-dependencies
106 swap-space-priority
107 swap-space-discard?))
c5df1839
LC
108
109;;; Commentary:
110;;;
111;;; Declaring file systems to be mounted.
112;;;
278d486b
LC
113;;; Note: this file system is used both in the Shepherd and on the "host
114;;; side", so it must not include (gnu packages …) modules.
115;;;
c5df1839
LC
116;;; Code:
117
5eb5c078
LC
118(eval-when (expand load eval)
119 (define invalid-file-system-flags
120 ;; Note: Keep in sync with 'mount-flags->bit-mask'.
121 (let ((known-flags '(read-only
122 bind-mount no-suid no-dev no-exec
123 no-atime strict-atime lazy-time)))
124 (lambda (flags)
125 "Return the subset of FLAGS that is invalid."
126 (remove (cut memq <> known-flags) flags))))
127
128 (define (%validate-file-system-flags flags location)
129 "Raise an error if FLAGS contains invalid mount flags; otherwise return
130FLAGS."
131 (match (invalid-file-system-flags flags)
132 (() flags)
133 (invalid
134 (leave (source-properties->location location)
135 (N_ "invalid file system mount flag:~{ ~s~}~%"
136 "invalid file system mount flags:~{ ~s~}~%"
137 (length invalid))
138 invalid)))))
139
140(define-syntax validate-file-system-flags
141 (lambda (s)
142 "Validate the given file system mount flags, raising an error if invalid
143flags are found."
144 (syntax-case s (quote)
145 ((_ (quote (symbols ...))) ;validate at expansion time
146 (begin
147 (%validate-file-system-flags (syntax->datum #'(symbols ...))
148 (syntax-source s))
149 #'(quote (symbols ...))))
150 ((_ flags)
151 #`(%validate-file-system-flags flags
152 '#,(datum->syntax s (syntax-source s))))
153 (id
154 (identifier? #'id)
155 #'%validate-file-system-flags))))
156
c5df1839 157;; File system declaration.
a5acc17a 158(define-record-type* <file-system> %file-system
c5df1839
LC
159 make-file-system
160 file-system?
a5acc17a 161 (device file-system-device) ; string | <uuid> | <file-system-label>
c5df1839
LC
162 (mount-point file-system-mount-point) ; string
163 (type file-system-type) ; string
164 (flags file-system-flags ; list of symbols
5eb5c078
LC
165 (default '())
166 (sanitize validate-file-system-flags))
c5df1839
LC
167 (options file-system-options ; string or #f
168 (default #f))
be21979d
LC
169 (mount? file-system-mount? ; Boolean
170 (default #t))
7c27bd11
MO
171 (mount-may-fail? file-system-mount-may-fail? ; Boolean
172 (default #f))
4d6b879c 173 (needed-for-boot? %file-system-needed-for-boot? ; Boolean
c5df1839
LC
174 (default #f))
175 (check? file-system-check? ; Boolean
4e469051 176 (default #t))
60299484 177 (skip-check-if-clean? file-system-skip-check-if-clean? ; Boolean
69f37702 178 (default #t))
60299484
TGR
179 (repair file-system-repair ; symbol or #f
180 (default 'preen))
4e469051 181 (create-mount-point? file-system-create-mount-point? ; Boolean
e51710d1 182 (default #f))
e502bf89 183 (dependencies file-system-dependencies ; list of <file-system>
dd41a7f8
LC
184 (default '())) ; or <mapped-device>
185 (location file-system-location
186 (default (current-source-location))
187 (innate)))
c5df1839 188
a5acc17a
LC
189;; A file system label for use in the 'device' field.
190(define-record-type <file-system-label>
191 (file-system-label label)
192 file-system-label?
193 (label file-system-label->string))
194
195(set-record-type-printer! <file-system-label>
196 (lambda (obj port)
197 (format port "#<file-system-label ~s>"
198 (file-system-label->string obj))))
199
200(define-syntax report-deprecation
201 (lambda (s)
202 "Report the use of the now-deprecated 'title' field."
203 (syntax-case s ()
204 ((_ field)
205 (let* ((source (syntax-source #'field))
206 (file (and source (assq-ref source 'filename)))
207 (line (and source
208 (and=> (assq-ref source 'line) 1+)))
209 (column (and source (assq-ref source 'column))))
210 (format (current-error-port)
211 "~a:~a:~a: warning: 'title' field is deprecated~%"
212 file line column)
213 #t)))))
214
215;; Helper for 'process-file-system-declaration'.
216(define-syntax device-expression
217 (syntax-rules (quote label uuid device)
218 ((_ (quote label) dev)
219 (file-system-label dev))
220 ((_ (quote uuid) dev)
221 (if (uuid? dev) dev (uuid dev)))
222 ((_ (quote device) dev)
223 dev)
224 ((_ title dev)
225 (case title
226 ((label) (file-system-label dev))
227 ((uuid) (uuid dev))
228 (else dev)))))
229
230;; Helper to interpret the now-deprecated 'title' field. Detect forms like
231;; (title 'label), remove them, and adjust the 'device' field accordingly.
232;; TODO: Remove this once 'title' has been deprecated long enough.
233(define-syntax process-file-system-declaration
234 (syntax-rules (device title)
235 ((_ () (rest ...) #f #f) ;no 'title' and no 'device' field
236 (%file-system rest ...))
237 ((_ () (rest ...) dev #f) ;no 'title' field
238 (%file-system rest ... (device dev)))
239 ((_ () (rest ...) dev titl) ;got a 'title' field
240 (%file-system rest ...
241 (device (device-expression titl dev))))
242 ((_ ((title titl) rest ...) (previous ...) dev _)
243 (begin
244 (report-deprecation (title titl))
245 (process-file-system-declaration (rest ...)
246 (previous ...)
247 dev titl)))
248 ((_ ((device dev) rest ...) (previous ...) _ titl)
249 (process-file-system-declaration (rest ...)
250 (previous ...)
251 dev titl))
252 ((_ (field rest ...) (previous ...) dev titl)
253 (process-file-system-declaration (rest ...)
254 (previous ... field)
255 dev titl))))
256
257(define-syntax-rule (file-system fields ...)
258 (process-file-system-declaration (fields ...) () #f #f))
259
260(define (file-system-title fs) ;deprecated
261 (match (file-system-device fs)
262 ((? file-system-label?) 'label)
263 ((? uuid?) 'uuid)
264 ((? string?) 'device)))
265
ad167d02
LC
266;; Note: This module is used both on the build side and on the host side.
267;; Arrange not to pull (guix store) and (guix config) because the latter
268;; differs from user to user.
269(define (%store-prefix)
270 "Return the store prefix."
c45477d2
LC
271 ;; Note: If we have (guix store database) in the search path and we do *not*
272 ;; have (guix store) proper, 'resolve-module' returns an empty (guix store)
273 ;; with one sub-module.
274 (cond ((and=> (resolve-module '(guix store) #:ensure #f)
275 (lambda (store)
276 (module-variable store '%store-prefix)))
ad167d02 277 =>
c45477d2
LC
278 (lambda (variable)
279 ((variable-ref variable))))
ad167d02
LC
280 ((getenv "NIX_STORE")
281 => identity)
282 (else
283 "/gnu/store")))
284
38434419
LC
285(define %not-slash
286 (char-set-complement (char-set #\/)))
287
288(define (file-prefix? file1 file2)
4f3bdc8f 289 "Return #t if FILE1 denotes the name of a file that is a parent of FILE2.
7cde70c7
MC
290FILE1 and FILE2 must both be either absolute or relative file names, else #f
291is returned.
292
4f3bdc8f 293For example:
38434419
LC
294
295 (file-prefix? \"/gnu\" \"/gnu/store\")
296 => #t
297
298 (file-prefix? \"/gn\" \"/gnu/store\")
299 => #f
300"
7cde70c7
MC
301 (define (absolute? file)
302 (string-prefix? "/" file))
303
304 (if (or (every absolute? (list file1 file2))
305 (every (negate absolute?) (list file1 file2)))
306 (let loop ((file1 (string-tokenize file1 %not-slash))
307 (file2 (string-tokenize file2 %not-slash)))
308 (match file1
309 (()
310 #t)
311 ((head1 tail1 ...)
312 (match file2
313 ((head2 tail2 ...)
314 (and (string=? head1 head2) (loop tail1 tail2)))
315 (()
316 #f)))))
317 ;; FILE1 and FILE2 are a mix of absolute and relative file names.
318 #f))
4f3bdc8f
MC
319
320(define (file-name-depth file-name)
321 (length (string-tokenize file-name %not-slash)))
322
99e676db
MC
323(define* (file-system-device->string device #:key uuid-type)
324 "Return the string representations of the DEVICE field of a <file-system>
325record. When the device is a UUID, its representation is chosen depending on
326UUID-TYPE, a symbol such as 'dce or 'iso9660."
327 (match device
328 ((? file-system-label?)
329 (file-system-label->string device))
330 ((? uuid?)
331 (if uuid-type
332 (uuid->string (uuid-bytevector device) uuid-type)
333 (uuid->string device)))
334 ((? string?)
335 device)))
336
fa35fb58
MC
337(define (file-system-options->alist string)
338 "Translate the option string format of a <file-system> record into an
339association list of options or option/value pairs."
340 (if string
341 (let ((options (string-split string #\,)))
342 (map (lambda (param)
343 (let ((=index (string-index param #\=)))
344 (if =index
345 (cons (string-take param =index)
346 (string-drop param (1+ =index)))
347 param)))
348 options))
349 '()))
350
351(define (alist->file-system-options options)
352 "Return the string representation of OPTIONS, an association list. The
353string obtained can be used as the option field of a <file-system> record."
354 (if (null? options)
355 #f
356 (string-join (map (match-lambda
357 ((key . value)
358 (string-append key "=" value))
359 (key
360 key))
361 options)
362 ",")))
363
38434419
LC
364(define (file-system-needed-for-boot? fs)
365 "Return true if FS has the 'needed-for-boot?' flag set, or if it holds the
366store--e.g., if FS is the root file system."
4d6b879c 367 (or (%file-system-needed-for-boot? fs)
38434419
LC
368 (and (file-prefix? (file-system-mount-point fs) (%store-prefix))
369 (not (memq 'bind-mount (file-system-flags fs))))))
4d6b879c 370
575b4b09
DT
371(define (file-system->spec fs)
372 "Return a list corresponding to file-system FS that can be passed to the
373initrd code."
374 (match fs
7c27bd11 375 (($ <file-system> device mount-point type flags options mount?
60299484
TGR
376 mount-may-fail? needed-for-boot?
377 check? skip-check-if-clean? repair)
86c926d7 378 ;; Note: Add new fields towards the end for compatibility.
a5acc17a
LC
379 (list (cond ((uuid? device)
380 `(uuid ,(uuid-type device) ,(uuid-bytevector device)))
381 ((file-system-label? device)
382 `(file-system-label ,(file-system-label->string device)))
383 (else device))
60299484
TGR
384 mount-point type flags options mount-may-fail?
385 check? skip-check-if-clean? repair))))
575b4b09 386
5970e8e2
LC
387(define (spec->file-system sexp)
388 "Deserialize SEXP, a list, to the corresponding <file-system> object."
389 (match sexp
60299484
TGR
390 ((device mount-point type flags options mount-may-fail?
391 check? skip-check-if-clean? repair
86c926d7 392 _ ...) ;placeholder for new fields
5970e8e2 393 (file-system
9976c76a
LC
394 (device (match device
395 (('uuid (? symbol? type) (? bytevector? bv))
396 (bytevector->uuid bv type))
a5acc17a
LC
397 (('file-system-label (? string? label))
398 (file-system-label label))
9976c76a
LC
399 (_
400 device)))
5970e8e2
LC
401 (mount-point mount-point) (type type)
402 (flags flags) (options options)
7c27bd11 403 (mount-may-fail? mount-may-fail?)
60299484
TGR
404 (check? check?)
405 (skip-check-if-clean? skip-check-if-clean?)
406 (repair repair)))))
5970e8e2 407
d77a0bd6
LC
408(define (specification->file-system-mapping spec writable?)
409 "Read the SPEC and return the corresponding <file-system-mapping>. SPEC is
410a string of the form \"SOURCE\" or \"SOURCE=TARGET\". The former specifies
411that SOURCE from the host should be mounted at SOURCE in the other system.
412The latter format specifies that SOURCE from the host should be mounted at
413TARGET in the other system."
414 (let ((index (string-index spec #\=)))
415 (if index
416 (file-system-mapping
417 (source (substring spec 0 index))
418 (target (substring spec (+ 1 index)))
419 (writable? writable?))
420 (file-system-mapping
421 (source spec)
422 (target spec)
423 (writable? writable?)))))
424
661a1d79
LC
425\f
426;;;
427;;; Common file systems.
428;;;
429
6ddb5960
LC
430(define %pseudo-file-system-types
431 ;; List of know pseudo file system types. This is used when validating file
432 ;; system definitions.
df1eaffc
LC
433 '("binfmt_misc" "cgroup" "debugfs" "devpts" "devtmpfs" "efivarfs" "fusectl"
434 "hugetlbfs" "overlay" "proc" "securityfs" "sysfs" "tmpfs"))
6ddb5960 435
c5df1839
LC
436(define %fuse-control-file-system
437 ;; Control file system for Linux' file systems in user-space (FUSE).
438 (file-system
439 (device "fusectl")
440 (mount-point "/sys/fs/fuse/connections")
441 (type "fusectl")
442 (check? #f)))
443
444(define %binary-format-file-system
445 ;; Support for arbitrary executable binary format.
446 (file-system
447 (device "binfmt_misc")
448 (mount-point "/proc/sys/fs/binfmt_misc")
449 (type "binfmt_misc")
450 (check? #f)))
451
6bb07e91
MO
452(define %debug-file-system
453 (file-system
454 (type "debugfs")
455 (device "none")
456 (mount-point "/sys/kernel/debug")
457 (check? #f)
458 (create-mount-point? #t)))
459
f94835a9
MO
460(define %efivars-file-system
461 ;; Support for EFI variables file system.
462 (file-system
463 (device "efivarfs")
464 (mount-point "/sys/firmware/efi/efivars")
465 (type "efivarfs")
466 (mount-may-fail? #t)
467 (needed-for-boot? #f)
468 (check? #f)))
469
7f239fd3
LC
470(define %tty-gid
471 ;; ID of the 'tty' group. Allocate it statically to make it easy to refer
472 ;; to it from here and from the 'tty' group definitions.
c8fa3426 473 996)
7f239fd3
LC
474
475(define %pseudo-terminal-file-system
476 ;; The pseudo-terminal file system. It needs to be mounted so that
477 ;; statfs(2) returns DEVPTS_SUPER_MAGIC like libc's getpt(3) expects (and
478 ;; thus openpty(3) and its users, such as xterm.)
479 (file-system
480 (device "none")
481 (mount-point "/dev/pts")
482 (type "devpts")
483 (check? #f)
484 (needed-for-boot? #f)
485 (create-mount-point? #t)
486 (options (string-append "gid=" (number->string %tty-gid) ",mode=620"))))
a69576ea 487
db17ae5c
LC
488(define %shared-memory-file-system
489 ;; Shared memory.
490 (file-system
491 (device "tmpfs")
492 (mount-point "/dev/shm")
493 (type "tmpfs")
494 (check? #f)
495 (flags '(no-suid no-dev))
496 (options "size=50%") ;TODO: make size configurable
497 (create-mount-point? #t)))
498
3392ce5d
LC
499(define %immutable-store
500 ;; Read-only store to avoid users or daemons accidentally modifying it.
501 ;; 'guix-daemon' has provisions to remount it read-write in its own name
502 ;; space.
503 (file-system
504 (device (%store-prefix))
505 (mount-point (%store-prefix))
506 (type "none")
507 (check? #f)
b41c7beb 508 (flags '(read-only bind-mount no-atime))))
3392ce5d 509
727636aa 510(define %control-groups
b78cad85
LC
511 (let ((parent (file-system
512 (device "cgroup")
513 (mount-point "/sys/fs/cgroup")
514 (type "tmpfs")
515 (check? #f))))
516 (cons parent
517 (map (lambda (subsystem)
518 (file-system
519 (device "cgroup")
520 (mount-point (string-append "/sys/fs/cgroup/" subsystem))
521 (type "cgroup")
522 (check? #f)
523 (options subsystem)
524 (create-mount-point? #t)
525
526 ;; This must be mounted after, and unmounted before the
527 ;; parent directory.
528 (dependencies (list parent))))
529 '("cpuset" "cpu" "cpuacct" "memory" "devices" "freezer"
2ef4d273 530 "blkio" "perf_event" "pids")))))
727636aa 531
14454f0b
MW
532(define %elogind-file-systems
533 ;; We don't use systemd, but these file systems are needed for elogind,
534 ;; which was extracted from systemd.
2cf5f4c1
MO
535 (append
536 (list (file-system
537 (device "none")
538 (mount-point "/run/systemd")
539 (type "tmpfs")
540 (check? #f)
541 (flags '(no-suid no-dev no-exec))
542 (options "mode=0755")
543 (create-mount-point? #t))
544 (file-system
545 (device "none")
546 (mount-point "/run/user")
547 (type "tmpfs")
548 (check? #f)
549 (flags '(no-suid no-dev no-exec))
550 (options "mode=0755")
551 (create-mount-point? #t))
552 ;; Elogind uses cgroups to organize processes, allowing it to map PIDs
553 ;; to sessions. Elogind's cgroup hierarchy isn't associated with any
554 ;; resource controller ("subsystem").
555 (file-system
556 (device "cgroup")
557 (mount-point "/sys/fs/cgroup/elogind")
558 (type "cgroup")
559 (check? #f)
560 (options "none,name=elogind")
561 (create-mount-point? #t)
562 (dependencies (list (car %control-groups)))))
563 %control-groups))
14454f0b 564
a69576ea
LC
565(define %base-file-systems
566 ;; List of basic file systems to be mounted. Note that /proc and /sys are
567 ;; currently mounted by the initrd.
2cf5f4c1 568 (list %pseudo-terminal-file-system
6bb07e91 569 %debug-file-system
2cf5f4c1 570 %shared-memory-file-system
f94835a9 571 %efivars-file-system
2cf5f4c1 572 %immutable-store))
a69576ea 573
c829bc80
DT
574;; File systems for Linux containers differ from %base-file-systems in that
575;; they impose additional restrictions such as no-exec or need different
576;; options to function properly.
577;;
578;; The file system flags and options conform to the libcontainer
579;; specification:
580;; https://github.com/docker/libcontainer/blob/master/SPEC.md#filesystem
581(define %container-file-systems
582 (list
b57ec5f6 583 ;; Pseudo-terminal file system.
c829bc80
DT
584 (file-system
585 (device "none")
586 (mount-point "/dev/pts")
587 (type "devpts")
588 (flags '(no-exec no-suid))
589 (needed-for-boot? #t)
590 (create-mount-point? #t)
591 (check? #f)
592 (options "newinstance,ptmxmode=0666,mode=620"))
593 ;; Shared memory file system.
594 (file-system
595 (device "tmpfs")
596 (mount-point "/dev/shm")
597 (type "tmpfs")
598 (flags '(no-exec no-suid no-dev))
599 (options "mode=1777,size=65536k")
600 (needed-for-boot? #t)
601 (create-mount-point? #t)
602 (check? #f))
603 ;; Message queue file system.
604 (file-system
605 (device "mqueue")
606 (mount-point "/dev/mqueue")
607 (type "mqueue")
608 (flags '(no-exec no-suid no-dev))
609 (needed-for-boot? #t)
610 (create-mount-point? #t)
611 (check? #f))))
612
9110c2e9
DT
613\f
614;;;
615;;; Shared file systems, for VMs/containers.
616;;;
617
618;; Mapping of host file system SOURCE to mount point TARGET in the guest.
619(define-record-type* <file-system-mapping> file-system-mapping
620 make-file-system-mapping
621 file-system-mapping?
622 (source file-system-mapping-source) ;string
623 (target file-system-mapping-target) ;string
624 (writable? file-system-mapping-writable? ;Boolean
625 (default #f)))
626
d2a5e698
LC
627(define (file-system-mapping->bind-mount mapping)
628 "Return a file system that realizes MAPPING, a <file-system-mapping>, using
629a bind mount."
630 (match mapping
631 (($ <file-system-mapping> source target writable?)
632 (file-system
633 (mount-point target)
634 (device source)
635 (type "none")
636 (flags (if writable?
637 '(bind-mount)
638 '(bind-mount read-only)))
639 (check? #f)
640 (create-mount-point? #t)))))
641
9110c2e9
DT
642(define %store-mapping
643 ;; Mapping of the host's store into the guest.
644 (file-system-mapping
645 (source (%store-prefix))
646 (target (%store-prefix))
647 (writable? #f)))
648
7597478e
LC
649(define %network-configuration-files
650 ;; List of essential network configuration files.
651 '("/etc/resolv.conf"
652 "/etc/nsswitch.conf"
653 "/etc/services"
654 "/etc/hosts"))
655
656(define %network-file-mappings
657 ;; List of file mappings for essential network files.
658 (filter-map (lambda (file)
659 (file-system-mapping
660 (source file)
661 (target file)
662 ;; XXX: On some GNU/Linux systems, /etc/resolv.conf is a
663 ;; symlink to a file in a tmpfs which, for an unknown reason,
664 ;; cannot be bind mounted read-only within the container.
5627bfe4
JC
665 (writable? (string=? file "/etc/resolv.conf"))))
666 %network-configuration-files))
7597478e 667
72089954 668(define (file-system-type-predicate type)
7dbd75b3
LC
669 "Return a predicate that, when passed a file system, returns #t if that file
670system has the given TYPE."
72089954
DM
671 (lambda (fs)
672 (string=? (file-system-type fs) type)))
673
b460ba79
MC
674\f
675;;;
676;;; Btrfs specific helpers.
677;;;
678
679(define (btrfs-subvolume? fs)
680 "Predicate to check if FS, a file-system object, is a Btrfs subvolume."
681 (and-let* ((btrfs-file-system? (string= "btrfs" (file-system-type fs)))
682 (option-keys (map (match-lambda
683 ((key . value) key)
684 (key key))
685 (file-system-options->alist
686 (file-system-options fs)))))
687 (find (cut string-prefix? "subvol" <>) option-keys)))
688
689(define (btrfs-store-subvolume-file-name file-systems)
690 "Return the subvolume file name within the Btrfs top level onto which the
691store is located, else #f."
692
693 (define (prepend-slash/maybe s)
694 (if (string=? "/" (string-take s 1))
695 s
696 (string-append "/" s)))
697
b460ba79
MC
698 (and-let* ((btrfs-subvolume-fs (filter btrfs-subvolume? file-systems))
699 (btrfs-subvolume-fs*
700 (sort btrfs-subvolume-fs
701 (lambda (fs1 fs2)
702 (> (file-name-depth (file-system-mount-point fs1))
703 (file-name-depth (file-system-mount-point fs2))))))
704 (store-subvolume-fs
705 (find (lambda (fs) (file-prefix? (file-system-mount-point fs)
706 (%store-prefix)))
707 btrfs-subvolume-fs*))
708 (options (file-system-options->alist
709 (file-system-options store-subvolume-fs))))
710 ;; XXX: Deriving the subvolume name based from a subvolume ID is not
711 ;; supported, as we'd need to query the actual file system.
712 (or (and=> (assoc-ref options "subvol") prepend-slash/maybe)
b460ba79
MC
713 (raise (condition
714 (&message
715 (message "The store is on a Btrfs subvolume, but the \
7a0bf3d5
LC
716subvolume name is unknown."))
717 (&fix-hint
718 (hint
719 (G_ "Use the @code{subvol} Btrfs file system option."))))))))
b460ba79
MC
720
721
133a61ae
JP
722;;;
723;;; Swap space
724;;;
725
726(define-record-type* <swap-space> swap-space make-swap-space
727 swap-space?
728 this-swap-space
729 (target swap-space-target)
730 (dependencies swap-space-dependencies
0831dfab
JP
731 (default '()))
732 (priority swap-space-priority
733 (default #f))
734 (discard? swap-space-discard?
735 (default #f)))
133a61ae 736
c5df1839 737;;; file-systems.scm ends here