gnu: python-3.4: Update to 3.4.5.
[jackhill/guix/guix.git] / gnu / build / install.scm
CommitLineData
5ce3defe 1;;; GNU Guix --- Functional package management for GNU
334bda9a 2;;; Copyright © 2013, 2014, 2015, 2016 Ludovic Courtès <ludo@gnu.org>
5ce3defe
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
548f7a8f 19(define-module (gnu build install)
5ce3defe 20 #:use-module (guix build utils)
9d3fb6c7 21 #:use-module (guix build store-copy)
b4140694 22 #:use-module (srfi srfi-26)
5ce3defe
LC
23 #:use-module (ice-9 match)
24 #:export (install-grub
b4140694 25 populate-root-file-system
5ce3defe 26 reset-timestamps
9d3fb6c7
LC
27 register-closure
28 populate-single-profile-directory))
5ce3defe
LC
29
30;;; Commentary:
31;;;
32;;; This module supports the installation of the GNU system on a hard disk.
33;;; It is meant to be used both in a build environment (in derivations that
34;;; build VM images), and on the bare metal (when really installing the
35;;; system.)
36;;;
37;;; Code:
38
39(define* (install-grub grub.cfg device mount-point)
40 "Install GRUB with GRUB.CFG on DEVICE, which is assumed to be mounted on
6412e58a
LC
41MOUNT-POINT.
42
43Note that the caller must make sure that GRUB.CFG is registered as a GC root
44so that the fonts, background images, etc. referred to by GRUB.CFG are not
45GC'd."
6ffd11f1
LC
46 (let* ((target (string-append mount-point "/boot/grub/grub.cfg"))
47 (pivot (string-append target ".new")))
48 (mkdir-p (dirname target))
49
6412e58a
LC
50 ;; Copy GRUB.CFG instead of just symlinking it, because symlinks won't
51 ;; work when /boot is on a separate partition. Do that atomically.
52 (copy-file grub.cfg pivot)
6ffd11f1
LC
53 (rename-file pivot target)
54
641f9a2a
LC
55 (unless (zero? (system* "grub-install" "--no-floppy"
56 "--boot-directory"
57 (string-append mount-point "/boot")
58 device))
59 (error "failed to install GRUB"))))
5ce3defe
LC
60
61(define (evaluate-populate-directive directive target)
62 "Evaluate DIRECTIVE, an sexp describing a file or directory to create under
63directory TARGET."
b4140694 64 (let loop ((directive directive))
a4888e2e
LC
65 (catch 'system-error
66 (lambda ()
67 (match directive
68 (('directory name)
69 (mkdir-p (string-append target name)))
70 (('directory name uid gid)
71 (let ((dir (string-append target name)))
72 (mkdir-p dir)
73 (chown dir uid gid)))
74 (('directory name uid gid mode)
75 (loop `(directory ,name ,uid ,gid))
76 (chmod (string-append target name) mode))
77 ((new '-> old)
78 (let try ()
79 (catch 'system-error
80 (lambda ()
81 (symlink old (string-append target new)))
82 (lambda args
83 ;; When doing 'guix system init' on the current '/', some
84 ;; symlinks may already exists. Override them.
85 (if (= EEXIST (system-error-errno args))
86 (begin
87 (delete-file (string-append target new))
88 (try))
89 (apply throw args))))))))
90 (lambda args
91 ;; Usually we can only get here when installing to an existing root,
92 ;; as with 'guix system init foo.scm /'.
93 (format (current-error-port)
94 "error: failed to evaluate directive: ~s~%"
95 directive)
96 (apply throw args)))))
b4140694
LC
97
98(define (directives store)
99 "Return a list of directives to populate the root file system that will host
100STORE."
e97c5be9
LC
101 `(;; Note: the store's GID is fixed precisely so we can set it here rather
102 ;; than at activation time.
66c2703f 103 (directory ,store 0 30000 #o1775)
185f6691 104
b4140694 105 (directory "/etc")
171a0a13 106 (directory "/var/log") ; for shepherd
b4140694 107 (directory "/var/guix/gcroots")
517830cc 108 (directory "/var/empty") ; for no-login accounts
3485716f 109 (directory "/var/db") ; for dhclient, etc.
4b2615e1 110 (directory "/var/run")
b4140694 111 (directory "/run")
3485716f 112 (directory "/mnt")
f2c403ea
LC
113 (directory "/var/guix/profiles/per-user/root" 0 0)
114
115 ;; Link to the initial system generation.
116 ("/var/guix/profiles/system" -> "system-1-link")
117
b4140694
LC
118 ("/var/guix/gcroots/booted-system" -> "/run/booted-system")
119 ("/var/guix/gcroots/current-system" -> "/run/current-system")
f2c403ea 120
334bda9a
LC
121 ;; XXX: 'guix-register' creates this symlink with a wrong target, so
122 ;; create it upfront to be sure.
123 ("/var/guix/gcroots/profiles" -> "/var/guix/profiles")
124
b4140694 125 (directory "/bin")
b4140694 126 (directory "/tmp" 0 0 #o1777) ; sticky bit
f73b8e3d 127 (directory "/var/tmp" 0 0 #o1777)
d9c41939 128 (directory "/var/lock" 0 0 #o1777)
b4140694
LC
129
130 (directory "/root" 0 0) ; an exception
131 (directory "/home" 0 0)))
132
f2c403ea 133(define (populate-root-file-system system target)
b4140694 134 "Make the essential non-store files and directories on TARGET. This
f2c403ea 135includes /etc, /var, /run, /bin/sh, etc., and all the symlinks to SYSTEM."
b4140694 136 (for-each (cut evaluate-populate-directive <> target)
f2c403ea
LC
137 (directives (%store-directory)))
138
139 ;; Add system generation 1.
aea9b232
LC
140 (let ((generation-1 (string-append target
141 "/var/guix/profiles/system-1-link")))
142 (let try ()
143 (catch 'system-error
144 (lambda ()
145 (symlink system generation-1))
146 (lambda args
147 ;; If GENERATION-1 already exists, overwrite it.
148 (if (= EEXIST (system-error-errno args))
149 (begin
150 (delete-file generation-1)
151 (try))
152 (apply throw args)))))))
5ce3defe
LC
153
154(define (reset-timestamps directory)
155 "Reset the timestamps of all the files under DIRECTORY, so that they appear
156as created and modified at the Epoch."
157 (display "clearing file timestamps...\n")
158 (for-each (lambda (file)
159 (let ((s (lstat file)))
160 ;; XXX: Guile uses libc's 'utime' function (not 'futime'), so
161 ;; the timestamp of symlinks cannot be changed, and there are
162 ;; symlinks here pointing to /gnu/store, which is the host,
163 ;; read-only store.
164 (unless (eq? (stat:type s) 'symlink)
165 (utime file 0 0 0 0))))
e1a56158 166 (find-files directory #:directories? #t)))
5ce3defe 167
08fa7613
LC
168(define* (register-closure store closure
169 #:key (deduplicate? #t))
5ce3defe
LC
170 "Register CLOSURE in STORE, where STORE is the directory name of the target
171store and CLOSURE is the name of a file containing a reference graph as used
08fa7613
LC
172by 'guix-register'. As a side effect, this resets timestamps on store files
173and, if DEDUPLICATE? is true, deduplicates files common to CLOSURE and the
174rest of STORE."
175 (let ((status (apply system* "guix-register" "--prefix" store
176 (append (if deduplicate? '() '("--no-deduplication"))
177 (list closure)))))
5ce3defe
LC
178 (unless (zero? status)
179 (error "failed to register store items" closure))))
180
9d3fb6c7 181(define* (populate-single-profile-directory directory
08fa7613
LC
182 #:key profile closure
183 deduplicate?)
9d3fb6c7
LC
184 "Populate DIRECTORY with a store containing PROFILE, whose closure is given
185in the file called CLOSURE (as generated by #:references-graphs.) DIRECTORY
186is initialized to contain a single profile under /root pointing to PROFILE.
08fa7613
LC
187DEDUPLICATE? determines whether to deduplicate files in the store.
188
9d3fb6c7
LC
189This is used to create the self-contained Guix tarball."
190 (define (scope file)
191 (string-append directory "/" file))
192
193 (define %root-profile
194 "/var/guix/profiles/per-user/root")
195
196 (define (mkdir-p* dir)
197 (mkdir-p (scope dir)))
198
199 (define (symlink* old new)
200 (symlink old (scope new)))
201
202 ;; Populate the store.
203 (populate-store (list closure) directory)
08fa7613
LC
204 (register-closure (canonicalize-path directory) closure
205 #:deduplicate? deduplicate?)
9d3fb6c7
LC
206
207 ;; XXX: 'guix-register' registers profiles as GC roots but the symlink
208 ;; target uses $TMPDIR. Fix that.
209 (delete-file (scope "/var/guix/gcroots/profiles"))
210 (symlink* "/var/guix/profiles"
211 "/var/guix/gcroots/profiles")
212
213 ;; Make root's profile, which makes it a GC root.
214 (mkdir-p* %root-profile)
215 (symlink* profile
216 (string-append %root-profile "/guix-profile-1-link"))
217 (symlink* (string-append %root-profile "/guix-profile-1-link")
218 (string-append %root-profile "/guix-profile"))
219
220 (mkdir-p* "/root")
221 (symlink* (string-append %root-profile "/guix-profile")
222 "/root/.guix-profile"))
223
5ce3defe 224;;; install.scm ends here