file-systems: 'mount-file-system' now takes a <file-system> object.
[jackhill/guix/guix.git] / gnu / system / file-systems.scm
CommitLineData
c5df1839 1;;; GNU Guix --- Functional package management for GNU
38434419 2;;; Copyright © 2013, 2014, 2015, 2016, 2017 Ludovic Courtès <ludo@gnu.org>
c5df1839
LC
3;;;
4;;; This file is part of GNU Guix.
5;;;
6;;; GNU Guix is free software; you can redistribute it and/or modify it
7;;; under the terms of the GNU General Public License as published by
8;;; the Free Software Foundation; either version 3 of the License, or (at
9;;; your option) any later version.
10;;;
11;;; GNU Guix is distributed in the hope that it will be useful, but
12;;; WITHOUT ANY WARRANTY; without even the implied warranty of
13;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14;;; GNU General Public License for more details.
15;;;
16;;; You should have received a copy of the GNU General Public License
17;;; along with GNU Guix. If not, see <http://www.gnu.org/licenses/>.
18
19(define-module (gnu system file-systems)
575b4b09 20 #:use-module (ice-9 match)
7597478e 21 #:use-module (srfi srfi-1)
c5df1839 22 #:use-module (guix records)
9b336338 23 #:use-module (gnu system uuid)
47cef4ec
LC
24 #:re-export (uuid ;backward compatibility
25 string->uuid
f8865db6 26 uuid->string)
c5df1839
LC
27 #:export (<file-system>
28 file-system
29 file-system?
30 file-system-device
d4c87617 31 file-system-title
c5df1839
LC
32 file-system-mount-point
33 file-system-type
34 file-system-needed-for-boot?
35 file-system-flags
36 file-system-options
be21979d 37 file-system-mount?
4e469051
LC
38 file-system-check?
39 file-system-create-mount-point?
e51710d1 40 file-system-dependencies
dd41a7f8 41 file-system-location
c5df1839 42
278d486b
LC
43 file-system-type-predicate
44
575b4b09 45 file-system->spec
5970e8e2 46 spec->file-system
d77a0bd6 47 specification->file-system-mapping
575b4b09 48
c5df1839 49 %fuse-control-file-system
a69576ea 50 %binary-format-file-system
705f8b68
MW
51 %shared-memory-file-system
52 %pseudo-terminal-file-system
3c185b24 53 %tty-gid
3392ce5d 54 %immutable-store
727636aa 55 %control-groups
14454f0b 56 %elogind-file-systems
a69576ea 57
5dae0186 58 %base-file-systems
c829bc80 59 %container-file-systems
5dae0186 60
9110c2e9
DT
61 <file-system-mapping>
62 file-system-mapping
63 file-system-mapping?
64 file-system-mapping-source
65 file-system-mapping-target
66 file-system-mapping-writable?
67
d2a5e698
LC
68 file-system-mapping->bind-mount
69
7597478e
LC
70 %store-mapping
71 %network-configuration-files
72 %network-file-mappings))
c5df1839
LC
73
74;;; Commentary:
75;;;
76;;; Declaring file systems to be mounted.
77;;;
278d486b
LC
78;;; Note: this file system is used both in the Shepherd and on the "host
79;;; side", so it must not include (gnu packages …) modules.
80;;;
c5df1839
LC
81;;; Code:
82
83;; File system declaration.
84(define-record-type* <file-system> file-system
85 make-file-system
86 file-system?
87 (device file-system-device) ; string
d4c87617
LC
88 (title file-system-title ; 'device | 'label | 'uuid
89 (default 'device))
c5df1839
LC
90 (mount-point file-system-mount-point) ; string
91 (type file-system-type) ; string
92 (flags file-system-flags ; list of symbols
93 (default '()))
94 (options file-system-options ; string or #f
95 (default #f))
be21979d
LC
96 (mount? file-system-mount? ; Boolean
97 (default #t))
4d6b879c 98 (needed-for-boot? %file-system-needed-for-boot? ; Boolean
c5df1839
LC
99 (default #f))
100 (check? file-system-check? ; Boolean
4e469051
LC
101 (default #t))
102 (create-mount-point? file-system-create-mount-point? ; Boolean
e51710d1 103 (default #f))
e502bf89 104 (dependencies file-system-dependencies ; list of <file-system>
dd41a7f8
LC
105 (default '())) ; or <mapped-device>
106 (location file-system-location
107 (default (current-source-location))
108 (innate)))
c5df1839 109
ad167d02
LC
110;; Note: This module is used both on the build side and on the host side.
111;; Arrange not to pull (guix store) and (guix config) because the latter
112;; differs from user to user.
113(define (%store-prefix)
114 "Return the store prefix."
115 (cond ((resolve-module '(guix store) #:ensure #f)
116 =>
117 (lambda (store)
118 ((module-ref store '%store-prefix))))
119 ((getenv "NIX_STORE")
120 => identity)
121 (else
122 "/gnu/store")))
123
38434419
LC
124(define %not-slash
125 (char-set-complement (char-set #\/)))
126
127(define (file-prefix? file1 file2)
128 "Return #t if FILE1 denotes the name of a file that is a parent of FILE2,
129where both FILE1 and FILE2 are absolute file name. For example:
130
131 (file-prefix? \"/gnu\" \"/gnu/store\")
132 => #t
133
134 (file-prefix? \"/gn\" \"/gnu/store\")
135 => #f
136"
137 (and (string-prefix? "/" file1)
138 (string-prefix? "/" file2)
139 (let loop ((file1 (string-tokenize file1 %not-slash))
140 (file2 (string-tokenize file2 %not-slash)))
141 (match file1
142 (()
143 #t)
144 ((head1 tail1 ...)
145 (match file2
146 ((head2 tail2 ...)
147 (and (string=? head1 head2) (loop tail1 tail2)))
148 (()
149 #f)))))))
150
151(define (file-system-needed-for-boot? fs)
152 "Return true if FS has the 'needed-for-boot?' flag set, or if it holds the
153store--e.g., if FS is the root file system."
4d6b879c 154 (or (%file-system-needed-for-boot? fs)
38434419
LC
155 (and (file-prefix? (file-system-mount-point fs) (%store-prefix))
156 (not (memq 'bind-mount (file-system-flags fs))))))
4d6b879c 157
575b4b09
DT
158(define (file-system->spec fs)
159 "Return a list corresponding to file-system FS that can be passed to the
160initrd code."
161 (match fs
be21979d 162 (($ <file-system> device title mount-point type flags options _ _ check?)
9b336338
LC
163 (list (if (uuid? device)
164 (uuid-bytevector device)
165 device)
166 title mount-point type flags options check?))))
575b4b09 167
5970e8e2
LC
168(define (spec->file-system sexp)
169 "Deserialize SEXP, a list, to the corresponding <file-system> object."
170 (match sexp
171 ((device title mount-point type flags options check?)
172 (file-system
173 (device device) (title title)
174 (mount-point mount-point) (type type)
175 (flags flags) (options options)
176 (check? check?)))))
177
d77a0bd6
LC
178(define (specification->file-system-mapping spec writable?)
179 "Read the SPEC and return the corresponding <file-system-mapping>. SPEC is
180a string of the form \"SOURCE\" or \"SOURCE=TARGET\". The former specifies
181that SOURCE from the host should be mounted at SOURCE in the other system.
182The latter format specifies that SOURCE from the host should be mounted at
183TARGET in the other system."
184 (let ((index (string-index spec #\=)))
185 (if index
186 (file-system-mapping
187 (source (substring spec 0 index))
188 (target (substring spec (+ 1 index)))
189 (writable? writable?))
190 (file-system-mapping
191 (source spec)
192 (target spec)
193 (writable? writable?)))))
194
661a1d79
LC
195\f
196;;;
197;;; Common file systems.
198;;;
199
c5df1839
LC
200(define %fuse-control-file-system
201 ;; Control file system for Linux' file systems in user-space (FUSE).
202 (file-system
203 (device "fusectl")
204 (mount-point "/sys/fs/fuse/connections")
205 (type "fusectl")
206 (check? #f)))
207
208(define %binary-format-file-system
209 ;; Support for arbitrary executable binary format.
210 (file-system
211 (device "binfmt_misc")
212 (mount-point "/proc/sys/fs/binfmt_misc")
213 (type "binfmt_misc")
214 (check? #f)))
215
7f239fd3
LC
216(define %tty-gid
217 ;; ID of the 'tty' group. Allocate it statically to make it easy to refer
218 ;; to it from here and from the 'tty' group definitions.
c8fa3426 219 996)
7f239fd3
LC
220
221(define %pseudo-terminal-file-system
222 ;; The pseudo-terminal file system. It needs to be mounted so that
223 ;; statfs(2) returns DEVPTS_SUPER_MAGIC like libc's getpt(3) expects (and
224 ;; thus openpty(3) and its users, such as xterm.)
225 (file-system
226 (device "none")
227 (mount-point "/dev/pts")
228 (type "devpts")
229 (check? #f)
230 (needed-for-boot? #f)
231 (create-mount-point? #t)
232 (options (string-append "gid=" (number->string %tty-gid) ",mode=620"))))
a69576ea 233
db17ae5c
LC
234(define %shared-memory-file-system
235 ;; Shared memory.
236 (file-system
237 (device "tmpfs")
238 (mount-point "/dev/shm")
239 (type "tmpfs")
240 (check? #f)
241 (flags '(no-suid no-dev))
242 (options "size=50%") ;TODO: make size configurable
243 (create-mount-point? #t)))
244
3392ce5d
LC
245(define %immutable-store
246 ;; Read-only store to avoid users or daemons accidentally modifying it.
247 ;; 'guix-daemon' has provisions to remount it read-write in its own name
248 ;; space.
249 (file-system
250 (device (%store-prefix))
251 (mount-point (%store-prefix))
252 (type "none")
253 (check? #f)
254 (flags '(read-only bind-mount))))
255
727636aa 256(define %control-groups
b78cad85
LC
257 (let ((parent (file-system
258 (device "cgroup")
259 (mount-point "/sys/fs/cgroup")
260 (type "tmpfs")
261 (check? #f))))
262 (cons parent
263 (map (lambda (subsystem)
264 (file-system
265 (device "cgroup")
266 (mount-point (string-append "/sys/fs/cgroup/" subsystem))
267 (type "cgroup")
268 (check? #f)
269 (options subsystem)
270 (create-mount-point? #t)
271
272 ;; This must be mounted after, and unmounted before the
273 ;; parent directory.
274 (dependencies (list parent))))
275 '("cpuset" "cpu" "cpuacct" "memory" "devices" "freezer"
276 "blkio" "perf_event" "hugetlb")))))
727636aa 277
14454f0b
MW
278(define %elogind-file-systems
279 ;; We don't use systemd, but these file systems are needed for elogind,
280 ;; which was extracted from systemd.
281 (list (file-system
282 (device "none")
283 (mount-point "/run/systemd")
284 (type "tmpfs")
285 (check? #f)
286 (flags '(no-suid no-dev no-exec))
287 (options "mode=0755")
288 (create-mount-point? #t))
289 (file-system
290 (device "none")
291 (mount-point "/run/user")
292 (type "tmpfs")
293 (check? #f)
294 (flags '(no-suid no-dev no-exec))
295 (options "mode=0755")
a7e50a2a
AW
296 (create-mount-point? #t))
297 ;; Elogind uses cgroups to organize processes, allowing it to map PIDs
298 ;; to sessions. Elogind's cgroup hierarchy isn't associated with any
299 ;; resource controller ("subsystem").
300 (file-system
301 (device "cgroup")
302 (mount-point "/sys/fs/cgroup/elogind")
303 (type "cgroup")
304 (check? #f)
305 (options "none,name=elogind")
306 (create-mount-point? #t)
307 (dependencies (list (car %control-groups))))))
14454f0b 308
a69576ea
LC
309(define %base-file-systems
310 ;; List of basic file systems to be mounted. Note that /proc and /sys are
311 ;; currently mounted by the initrd.
cc0e575a 312 (append (list %pseudo-terminal-file-system
727636aa
DT
313 %shared-memory-file-system
314 %immutable-store)
315 %control-groups))
a69576ea 316
c829bc80
DT
317;; File systems for Linux containers differ from %base-file-systems in that
318;; they impose additional restrictions such as no-exec or need different
319;; options to function properly.
320;;
321;; The file system flags and options conform to the libcontainer
322;; specification:
323;; https://github.com/docker/libcontainer/blob/master/SPEC.md#filesystem
324(define %container-file-systems
325 (list
b57ec5f6 326 ;; Pseudo-terminal file system.
c829bc80
DT
327 (file-system
328 (device "none")
329 (mount-point "/dev/pts")
330 (type "devpts")
331 (flags '(no-exec no-suid))
332 (needed-for-boot? #t)
333 (create-mount-point? #t)
334 (check? #f)
335 (options "newinstance,ptmxmode=0666,mode=620"))
336 ;; Shared memory file system.
337 (file-system
338 (device "tmpfs")
339 (mount-point "/dev/shm")
340 (type "tmpfs")
341 (flags '(no-exec no-suid no-dev))
342 (options "mode=1777,size=65536k")
343 (needed-for-boot? #t)
344 (create-mount-point? #t)
345 (check? #f))
346 ;; Message queue file system.
347 (file-system
348 (device "mqueue")
349 (mount-point "/dev/mqueue")
350 (type "mqueue")
351 (flags '(no-exec no-suid no-dev))
352 (needed-for-boot? #t)
353 (create-mount-point? #t)
354 (check? #f))))
355
9110c2e9
DT
356\f
357;;;
358;;; Shared file systems, for VMs/containers.
359;;;
360
361;; Mapping of host file system SOURCE to mount point TARGET in the guest.
362(define-record-type* <file-system-mapping> file-system-mapping
363 make-file-system-mapping
364 file-system-mapping?
365 (source file-system-mapping-source) ;string
366 (target file-system-mapping-target) ;string
367 (writable? file-system-mapping-writable? ;Boolean
368 (default #f)))
369
d2a5e698
LC
370(define (file-system-mapping->bind-mount mapping)
371 "Return a file system that realizes MAPPING, a <file-system-mapping>, using
372a bind mount."
373 (match mapping
374 (($ <file-system-mapping> source target writable?)
375 (file-system
376 (mount-point target)
377 (device source)
378 (type "none")
379 (flags (if writable?
380 '(bind-mount)
381 '(bind-mount read-only)))
382 (check? #f)
383 (create-mount-point? #t)))))
384
9110c2e9
DT
385(define %store-mapping
386 ;; Mapping of the host's store into the guest.
387 (file-system-mapping
388 (source (%store-prefix))
389 (target (%store-prefix))
390 (writable? #f)))
391
7597478e
LC
392(define %network-configuration-files
393 ;; List of essential network configuration files.
394 '("/etc/resolv.conf"
395 "/etc/nsswitch.conf"
396 "/etc/services"
397 "/etc/hosts"))
398
399(define %network-file-mappings
400 ;; List of file mappings for essential network files.
401 (filter-map (lambda (file)
402 (file-system-mapping
403 (source file)
404 (target file)
405 ;; XXX: On some GNU/Linux systems, /etc/resolv.conf is a
406 ;; symlink to a file in a tmpfs which, for an unknown reason,
407 ;; cannot be bind mounted read-only within the container.
408 (writable? (string=? file "/etc/resolv.conf"))))
409 %network-configuration-files))
410
72089954 411(define (file-system-type-predicate type)
7dbd75b3
LC
412 "Return a predicate that, when passed a file system, returns #t if that file
413system has the given TYPE."
72089954
DM
414 (lambda (fs)
415 (string=? (file-system-type fs) type)))
416
c5df1839 417;;; file-systems.scm ends here