gnu: Depend on 'gettext-minimal' rather than 'gettext' when appropriate.
[jackhill/guix/guix.git] / gnu / system / image.scm
CommitLineData
f19cf27c
MO
1;;; GNU Guix --- Functional package management for GNU
2;;; Copyright © 2020 Mathieu Othacehe <m.othacehe@gmail.com>
7ca533c7 3;;; Copyright © 2020 Jan (janneke) Nieuwenhuizen <janneke@gnu.org>
f19cf27c
MO
4;;;
5;;; This file is part of GNU Guix.
6;;;
7;;; GNU Guix is free software; you can redistribute it and/or modify it
8;;; under the terms of the GNU General Public License as published by
9;;; the Free Software Foundation; either version 3 of the License, or (at
10;;; your option) any later version.
11;;;
12;;; GNU Guix is distributed in the hope that it will be useful, but
13;;; WITHOUT ANY WARRANTY; without even the implied warranty of
14;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15;;; GNU General Public License for more details.
16;;;
17;;; You should have received a copy of the GNU General Public License
18;;; along with GNU Guix. If not, see <http://www.gnu.org/licenses/>.
19
20(define-module (gnu system image)
10b135ce
MO
21 #:use-module (guix diagnostics)
22 #:use-module (guix discovery)
f19cf27c
MO
23 #:use-module (guix gexp)
24 #:use-module (guix modules)
25 #:use-module (guix monads)
26 #:use-module (guix records)
27 #:use-module (guix store)
28 #:use-module (guix ui)
29 #:use-module (guix utils)
30 #:use-module ((guix self) #:select (make-config.scm))
31 #:use-module (gnu bootloader)
32 #:use-module (gnu bootloader grub)
33 #:use-module (gnu image)
34 #:use-module (gnu services)
35 #:use-module (gnu services base)
36 #:use-module (gnu system)
37 #:use-module (gnu system file-systems)
38 #:use-module (gnu system uuid)
39 #:use-module (gnu system vm)
40 #:use-module (guix packages)
41 #:use-module (gnu packages base)
42 #:use-module (gnu packages bootloaders)
43 #:use-module (gnu packages cdrom)
44 #:use-module (gnu packages disk)
45 #:use-module (gnu packages gawk)
46 #:use-module (gnu packages genimage)
47 #:use-module (gnu packages guile)
48 #:autoload (gnu packages gnupg) (guile-gcrypt)
c77b9285 49 #:use-module (gnu packages hurd)
f19cf27c
MO
50 #:use-module (gnu packages linux)
51 #:use-module (gnu packages mtools)
f441e3e8 52 #:use-module (gnu packages virtualization)
f19cf27c
MO
53 #:use-module ((srfi srfi-1) #:prefix srfi-1:)
54 #:use-module (srfi srfi-11)
55 #:use-module (srfi srfi-26)
281869e6 56 #:use-module (srfi srfi-34)
f19cf27c
MO
57 #:use-module (srfi srfi-35)
58 #:use-module (rnrs bytevectors)
f441e3e8 59 #:use-module (ice-9 format)
f19cf27c 60 #:use-module (ice-9 match)
b904b59c
MO
61 #:export (root-offset
62 root-label
63
64 esp-partition
f19cf27c
MO
65 root-partition
66
67 efi-disk-image
68 iso9660-image
c0458011 69 arm32-disk-image
599954c1 70 arm64-disk-image
f19cf27c 71
10b135ce
MO
72 image-with-os
73 raw-image-type
23ad7e92 74 qcow2-image-type
10b135ce
MO
75 iso-image-type
76 uncompressed-iso-image-type
c0458011 77 arm32-image-type
599954c1 78 arm64-image-type
10b135ce
MO
79
80 image-with-label
036f23f0 81 system-image
10b135ce
MO
82
83 %image-types
84 lookup-image-type-by-name))
f19cf27c
MO
85
86\f
87;;;
88;;; Images definitions.
89;;;
90
b7b45372
MO
91;; This is the offset before the first partition. GRUB will install itself in
92;; this post-MBR gap.
93(define root-offset (* 512 2048))
94
95;; Generic root partition label.
96(define root-label "Guix_image")
97
f19cf27c
MO
98(define esp-partition
99 (partition
100 (size (* 40 (expt 2 20)))
b7b45372 101 (offset root-offset)
f19cf27c
MO
102 (label "GNU-ESP") ;cosmetic only
103 ;; Use "vfat" here since this property is used when mounting. The actual
104 ;; FAT-ness is based on file system size (16 in this case).
105 (file-system "vfat")
106 (flags '(esp))
107 (initializer (gexp initialize-efi-partition))))
108
109(define root-partition
110 (partition
111 (size 'guess)
b7b45372 112 (label root-label)
f19cf27c
MO
113 (file-system "ext4")
114 (flags '(boot))
115 (initializer (gexp initialize-root-partition))))
116
117(define efi-disk-image
118 (image
119 (format 'disk-image)
120 (partitions (list esp-partition root-partition))))
121
122(define iso9660-image
123 (image
124 (format 'iso9660)
125 (partitions
126 (list (partition
127 (size 'guess)
128 (label "GUIX_IMAGE")
f56144e1 129 (flags '(boot)))))))
f19cf27c 130
c0458011 131(define arm32-disk-image
599954c1
MO
132 (image
133 (format 'disk-image)
c0458011 134 (target "arm-linux-gnueabihf")
599954c1
MO
135 (partitions
136 (list (partition
137 (inherit root-partition)
138 (offset root-offset))))
139 ;; FIXME: Deleting and creating "/var/run" and "/tmp" on the overlayfs
140 ;; fails.
141 (volatile-root? #f)))
142
c0458011
MO
143(define arm64-disk-image
144 (image
145 (inherit arm32-disk-image)
146 (target "aarch64-linux-gnu")))
147
f19cf27c 148\f
10b135ce
MO
149;;;
150;;; Images types.
151;;;
152
153(define-syntax-rule (image-with-os base-image os)
154 "Return an image inheriting from BASE-IMAGE, with the operating-system field
155set to the given OS."
156 (image
157 (inherit base-image)
158 (operating-system os)))
159
160(define raw-image-type
161 (image-type
162 (name 'raw)
163 (constructor (cut image-with-os efi-disk-image <>))))
164
23ad7e92
MO
165(define qcow2-image-type
166 (image-type
167 (name 'qcow2)
168 (constructor (cut image-with-os
169 (image
170 (inherit efi-disk-image)
171 (name 'image.qcow2)
172 (format 'compressed-qcow2))
173 <>))))
174
10b135ce
MO
175(define iso-image-type
176 (image-type
177 (name 'iso9660)
178 (constructor (cut image-with-os iso9660-image <>))))
179
180(define uncompressed-iso-image-type
181 (image-type
182 (name 'uncompressed-iso9660)
183 (constructor (cut image-with-os
184 (image
185 (inherit iso9660-image)
186 (compression? #f))
187 <>))))
188
c0458011
MO
189(define arm32-image-type
190 (image-type
191 (name 'arm32-raw)
192 (constructor (cut image-with-os arm32-disk-image <>))))
193
599954c1
MO
194(define arm64-image-type
195 (image-type
c0458011 196 (name 'arm64-raw)
599954c1
MO
197 (constructor (cut image-with-os arm64-disk-image <>))))
198
10b135ce 199\f
f19cf27c
MO
200;;
201;; Helpers.
202;;
203
204(define not-config?
205 ;; Select (guix …) and (gnu …) modules, except (guix config).
206 (match-lambda
207 (('guix 'config) #f)
208 (('guix rest ...) #t)
209 (('gnu rest ...) #t)
210 (rest #f)))
211
212(define (partition->gexp partition)
213 "Turn PARTITION, a <partition> object, into a list-valued gexp suitable for
214'make-partition-image'."
215 #~'(#$@(list (partition-size partition))
216 #$(partition-file-system partition)
bd3716f6 217 #$(partition-file-system-options partition)
f19cf27c
MO
218 #$(partition-label partition)
219 #$(and=> (partition-uuid partition)
220 uuid-bytevector)))
221
222(define gcrypt-sqlite3&co
223 ;; Guile-Gcrypt, Guile-SQLite3, and their propagated inputs.
224 (srfi-1:append-map
225 (lambda (package)
226 (cons package
227 (match (package-transitive-propagated-inputs package)
228 (((labels packages) ...)
229 packages))))
dac7dd1b 230 (list guile-gcrypt guile-sqlite3)))
f19cf27c
MO
231
232(define-syntax-rule (with-imported-modules* gexp* ...)
233 (with-extensions gcrypt-sqlite3&co
234 (with-imported-modules `(,@(source-module-closure
235 '((gnu build vm)
236 (gnu build image)
b97b423e 237 (gnu build bootloader)
b37c5441 238 (gnu build hurd-boot)
c77b9285 239 (gnu build linux-boot)
f19cf27c
MO
240 (guix store database))
241 #:select? not-config?)
242 ((guix config) => ,(make-config.scm)))
243 #~(begin
244 (use-modules (gnu build vm)
245 (gnu build image)
b97b423e 246 (gnu build bootloader)
b37c5441 247 (gnu build hurd-boot)
c77b9285 248 (gnu build linux-boot)
f19cf27c
MO
249 (guix store database)
250 (guix build utils))
251 gexp* ...))))
252
7feefb3b
MO
253(define (root-partition? partition)
254 "Return true if PARTITION is the root partition, false otherwise."
255 (member 'boot (partition-flags partition)))
256
257(define (find-root-partition image)
258 "Return the root partition of the given IMAGE."
259 (srfi-1:find root-partition? (image-partitions image)))
260
261(define (root-partition-index image)
262 "Return the index of the root partition of the given IMAGE."
263 (1+ (srfi-1:list-index root-partition? (image-partitions image))))
264
f19cf27c
MO
265\f
266;;
267;; Disk image.
268;;
269
270(define* (system-disk-image image
271 #:key
272 (name "disk-image")
273 bootcfg
274 bootloader
275 register-closures?
276 (inputs '()))
277 "Return as a file-like object, the disk-image described by IMAGE. Said
278image can be copied on a USB stick as is. BOOTLOADER is the bootloader that
279will be installed and configured according to BOOTCFG parameter.
280
281Raw images of the IMAGE partitions are first created. Then, genimage is used
282to assemble the partition images into a disk-image without resorting to a
283virtual machine.
284
285INPUTS is a list of inputs (as for packages). When REGISTER-CLOSURES? is
286true, register INPUTS in the store database of the image so that Guix can be
287used in the image."
288
289 (define genimage-name "image")
290
291 (define (image->genimage-cfg image)
292 ;; Return as a file-like object, the genimage configuration file
293 ;; describing the given IMAGE.
294 (define (format->image-type format)
295 ;; Return the genimage format corresponding to FORMAT. For now, only
296 ;; the hdimage format (raw disk-image) is supported.
f441e3e8
MO
297 (cond
298 ((memq format '(disk-image compressed-qcow2)) "hdimage")
f19cf27c
MO
299 (else
300 (raise (condition
301 (&message
302 (message
303 (format #f (G_ "Unsupported image type ~a~%.") format))))))))
304
305 (define (partition->dos-type partition)
306 ;; Return the MBR partition type corresponding to the given PARTITION.
307 ;; See: https://en.wikipedia.org/wiki/Partition_type.
308 (let ((flags (partition-flags partition)))
309 (cond
310 ((member 'esp flags) "0xEF")
311 (else "0x83"))))
312
313 (define (partition-image partition)
314 ;; Return as a file-like object, an image of the given PARTITION. A
315 ;; directory, filled by calling the PARTITION initializer procedure, is
316 ;; first created within the store. Then, an image of this directory is
317 ;; created using tools such as 'mke2fs' or 'mkdosfs', depending on the
318 ;; partition file-system type.
319 (let* ((os (image-operating-system image))
320 (schema (local-file (search-path %load-path
321 "guix/store/schema.sql")))
322 (graph (match inputs
323 (((names . _) ...)
324 names)))
7f75a7ec
MO
325 (type (partition-file-system partition))
326 (image-builder
f19cf27c 327 (with-imported-modules*
7f75a7ec 328 (let ((initializer #$(partition-initializer partition))
fd45ecb5 329 (inputs '#+(list e2fsprogs fakeroot dosfstools mtools))
7f75a7ec 330 (image-root "tmp-root"))
f19cf27c
MO
331 (sql-schema #$schema)
332
7f75a7ec
MO
333 (set-path-environment-variable "PATH" '("bin" "sbin") inputs)
334
f19cf27c
MO
335 ;; Allow non-ASCII file names--e.g., 'nss-certs'--to be
336 ;; decoded.
337 (setenv "GUIX_LOCPATH"
338 #+(file-append glibc-utf8-locales "/lib/locale"))
339 (setlocale LC_ALL "en_US.utf8")
340
7f75a7ec 341 (initializer image-root
f19cf27c
MO
342 #:references-graphs '#$graph
343 #:deduplicate? #f
344 #:system-directory #$os
05f37c16 345 #:grub-efi #+grub-efi
f19cf27c 346 #:bootloader-package
9c1adb24
MO
347 #+(bootloader-package bootloader)
348 #:bootloader-installer
349 #+(bootloader-installer bootloader)
f19cf27c
MO
350 #:bootcfg #$bootcfg
351 #:bootcfg-location
7f75a7ec 352 #$(bootloader-configuration-file bootloader))
f19cf27c
MO
353 (make-partition-image #$(partition->gexp partition)
354 #$output
7f75a7ec
MO
355 image-root)))))
356 (computed-file "partition.img" image-builder
6d6e74ea 357 #:options `(#:references-graphs ,inputs))))
f19cf27c
MO
358
359 (define (partition->config partition)
360 ;; Return the genimage partition configuration for PARTITION.
361 (let ((label (partition-label partition))
362 (dos-type (partition->dos-type partition))
1b4fa785
MO
363 (image (partition-image partition))
364 (offset (partition-offset partition)))
f19cf27c 365 #~(format #f "~/partition ~a {
7d4ecda6
MO
366~/~/partition-type = ~a
367~/~/image = \"~a\"
368~/~/offset = \"~a\"
369~/}"
1b4fa785
MO
370 #$label
371 #$dos-type
372 #$image
1dd7b87f 373 #$offset)))
f19cf27c
MO
374
375 (let* ((format (image-format image))
376 (image-type (format->image-type format))
377 (partitions (image-partitions image))
378 (partitions-config (map partition->config partitions))
379 (builder
380 #~(begin
381 (let ((format (@ (ice-9 format) format)))
382 (call-with-output-file #$output
383 (lambda (port)
384 (format port
385 "\
386image ~a {
387~/~a {}
388~{~a~^~%~}
389}~%" #$genimage-name #$image-type (list #$@partitions-config))))))))
390 (computed-file "genimage.cfg" builder)))
391
f27bec10
MO
392 (let* ((image-name (image-name image))
393 (name (if image-name
394 (symbol->string image-name)
395 name))
f441e3e8 396 (format (image-format image))
5980ec8a 397 (substitutable? (image-substitutable? image))
f19cf27c
MO
398 (builder
399 (with-imported-modules*
f441e3e8 400 (let ((inputs '#+(list genimage coreutils findutils qemu-minimal))
7feefb3b 401 (bootloader-installer
f441e3e8
MO
402 #+(bootloader-disk-image-installer bootloader))
403 (out-image (string-append "images/" #$genimage-name)))
f19cf27c 404 (set-path-environment-variable "PATH" '("bin" "sbin") inputs)
f441e3e8 405 (genimage #$(image->genimage-cfg image))
7feefb3b
MO
406 ;; Install the bootloader directly on the disk-image.
407 (when bootloader-installer
408 (bootloader-installer
409 #+(bootloader-package bootloader)
410 #$(root-partition-index image)
f441e3e8
MO
411 out-image))
412 (convert-disk-image out-image '#$format #$output)))))
413 (computed-file name builder
6d6e74ea 414 #:options `(#:substitutable? ,substitutable?))))
f19cf27c
MO
415
416\f
417;;
418;; ISO9660 image.
419;;
420
421(define (has-guix-service-type? os)
422 "Return true if OS contains a service of the type GUIX-SERVICE-TYPE."
423 (not (not (srfi-1:find (lambda (service)
424 (eq? (service-kind service) guix-service-type))
425 (operating-system-services os)))))
426
427(define* (system-iso9660-image image
428 #:key
0996fcc6 429 (name "image.iso")
f19cf27c
MO
430 bootcfg
431 bootloader
432 register-closures?
433 (inputs '())
434 (grub-mkrescue-environment '()))
435 "Return as a file-like object a bootable, stand-alone iso9660 image.
436
437INPUTS is a list of inputs (as for packages). When REGISTER-CLOSURES? is
438true, register INPUTS in the store database of the image so that Guix can be
439used in the image. "
440 (define root-label
441 (match (image-partitions image)
442 ((partition)
443 (partition-label partition))))
444
445 (define root-uuid
446 (match (image-partitions image)
447 ((partition)
448 (uuid-bytevector (partition-uuid partition)))))
449
450 (let* ((os (image-operating-system image))
451 (bootloader (bootloader-package bootloader))
452 (compression? (image-compression? image))
453 (substitutable? (image-substitutable? image))
454 (schema (local-file (search-path %load-path
455 "guix/store/schema.sql")))
456 (graph (match inputs
457 (((names . _) ...)
458 names)))
f19cf27c
MO
459 (builder
460 (with-imported-modules*
461 (let* ((inputs '#$(list parted e2fsprogs dosfstools xorriso
1cb9effc
MO
462 sed grep coreutils findutils gawk))
463 (image-root "tmp-root"))
464 (sql-schema #$schema)
465
466 ;; Allow non-ASCII file names--e.g., 'nss-certs'--to be decoded.
467 (setenv "GUIX_LOCPATH"
468 #+(file-append glibc-utf8-locales "/lib/locale"))
469
470 (setlocale LC_ALL "en_US.utf8")
471
f19cf27c 472 (set-path-environment-variable "PATH" '("bin" "sbin") inputs)
1cb9effc
MO
473
474 (initialize-root-partition image-root
475 #:references-graphs '#$graph
476 #:deduplicate? #f
477 #:system-directory #$os)
f19cf27c
MO
478 (make-iso9660-image #$xorriso
479 '#$grub-mkrescue-environment
480 #$bootloader
481 #$bootcfg
482 #$os
1cb9effc 483 image-root
f19cf27c
MO
484 #$output
485 #:references-graphs '#$graph
486 #:register-closures? #$register-closures?
487 #:compression? #$compression?
488 #:volume-id #$root-label
489 #:volume-uuid #$root-uuid)))))
490 (computed-file name builder
6d6e74ea 491 #:options `(#:references-graphs ,inputs
f19cf27c
MO
492 #:substitutable? ,substitutable?))))
493
036f23f0
JL
494(define (image-with-label base-image label)
495 "The volume ID of an ISO is the label of the first partition. This procedure
496returns an image record where the first partition's label is set to <label>."
497 (image
498 (inherit base-image)
499 (partitions
500 (match (image-partitions base-image)
501 ((boot others ...)
502 (cons
503 (partition
504 (inherit boot)
505 (label label))
506 others))))))
507
f19cf27c
MO
508\f
509;;
510;; Image creation.
511;;
512
f19cf27c
MO
513(define (image->root-file-system image)
514 "Return the IMAGE root partition file-system type."
515 (let ((format (image-format image)))
516 (if (eq? format 'iso9660)
517 "iso9660"
518 (partition-file-system (find-root-partition image)))))
519
520(define (root-size image)
521 "Return the root partition size of IMAGE."
522 (let* ((image-size (image-size image))
523 (root-partition (find-root-partition image))
524 (root-size (partition-size root-partition)))
525 (cond
526 ((and (eq? root-size 'guess) image-size)
527 image-size)
528 (else root-size))))
529
10b135ce 530(define* (image-with-os* base-image os)
f19cf27c
MO
531 "Return an image based on BASE-IMAGE but with the operating-system field set
532to OS. Also set the UUID and the size of the root partition."
533 (define root-file-system
534 (srfi-1:find
535 (lambda (fs)
536 (string=? (file-system-mount-point fs) "/"))
537 (operating-system-file-systems os)))
538
74938105
MO
539 (image
540 (inherit base-image)
541 (operating-system os)
542 (partitions
543 (map (lambda (p)
544 (if (root-partition? p)
545 (partition
546 (inherit p)
547 (uuid (file-system-device root-file-system))
548 (size (root-size base-image)))
549 p))
550 (image-partitions base-image)))))
f19cf27c
MO
551
552(define (operating-system-for-image image)
553 "Return an operating-system based on the one specified in IMAGE, but
554suitable for image creation. Assign an UUID to the root file-system, so that
555it can be used for bootloading."
556 (define volatile-root? (image-volatile-root? image))
557
558 (define (root-uuid os)
559 ;; UUID of the root file system, computed in a deterministic fashion.
560 ;; This is what we use to locate the root file system so it has to be
561 ;; different from the user's own file system UUIDs.
562 (let ((type (if (eq? (image-format image) 'iso9660)
563 'iso9660
564 'dce)))
565 (operating-system-uuid os type)))
566
567 (let* ((root-file-system-type (image->root-file-system image))
568 (base-os (image-operating-system image))
569 (file-systems-to-keep
570 (srfi-1:remove
571 (lambda (fs)
572 (string=? (file-system-mount-point fs) "/"))
573 (operating-system-file-systems base-os)))
574 (format (image-format image))
575 (os
576 (operating-system
577 (inherit base-os)
578 (initrd (lambda (file-systems . rest)
579 (apply (operating-system-initrd base-os)
580 file-systems
581 #:volatile-root? volatile-root?
582 rest)))
583 (bootloader (if (eq? format 'iso9660)
584 (bootloader-configuration
585 (inherit
586 (operating-system-bootloader base-os))
587 (bootloader grub-mkrescue-bootloader))
588 (operating-system-bootloader base-os)))
589 (file-systems (cons (file-system
590 (mount-point "/")
591 (device "/dev/placeholder")
592 (type root-file-system-type))
593 file-systems-to-keep))))
594 (uuid (root-uuid os)))
595 (operating-system
596 (inherit os)
597 (file-systems (cons (file-system
598 (mount-point "/")
599 (device uuid)
600 (type root-file-system-type))
601 file-systems-to-keep)))))
602
e3f0155c 603(define* (system-image image)
f19cf27c
MO
604 "Return the derivation of IMAGE. It can be a raw disk-image or an ISO9660
605image, depending on IMAGE format."
606 (define substitutable? (image-substitutable? image))
c9f6e2e5
MO
607 (define target (image-target image))
608
609 (with-parameters ((%current-target-system target))
610 (let* ((os (operating-system-for-image image))
10b135ce 611 (image* (image-with-os* image os))
f441e3e8 612 (image-format (image-format image))
c9f6e2e5
MO
613 (register-closures? (has-guix-service-type? os))
614 (bootcfg (operating-system-bootcfg os))
615 (bootloader (bootloader-configuration-bootloader
616 (operating-system-bootloader os))))
f441e3e8
MO
617 (cond
618 ((memq image-format '(disk-image compressed-qcow2))
f292d471
MO
619 (system-disk-image image*
620 #:bootcfg bootcfg
621 #:bootloader bootloader
622 #:register-closures? register-closures?
623 #:inputs `(("system" ,os)
624 ("bootcfg" ,bootcfg))))
f441e3e8 625 ((memq image-format '(iso9660))
f292d471
MO
626 (system-iso9660-image
627 image*
628 #:bootcfg bootcfg
629 #:bootloader bootloader
630 #:register-closures? register-closures?
631 #:inputs `(("system" ,os)
632 ("bootcfg" ,bootcfg))
633 ;; Make sure to use a mode that does no imply
634 ;; HFS+ tree creation that may fail with:
635 ;;
636 ;; "libisofs: FAILURE : Too much files to mangle,
637 ;; cannot guarantee unique file names"
638 ;;
639 ;; This happens if some limits are exceeded, see:
640 ;; https://lists.gnu.org/archive/html/grub-devel/2020-06/msg00048.html
641 #:grub-mkrescue-environment
642 '(("MKRESCUE_SED_MODE" . "mbr_only"))))))))
f19cf27c 643
10b135ce
MO
644\f
645;;
646;; Image detection.
647;;
648
649(define (image-modules)
650 "Return the list of image modules."
651 (cons (resolve-interface '(gnu system image))
652 (all-modules (map (lambda (entry)
653 `(,entry . "gnu/system/images/"))
654 %load-path)
655 #:warn warn-about-load-error)))
656
657(define %image-types
658 ;; The list of publically-known image types.
659 (delay (fold-module-public-variables (lambda (obj result)
660 (if (image-type? obj)
661 (cons obj result)
662 result))
663 '()
664 (image-modules))))
665
666(define (lookup-image-type-by-name name)
667 "Return the image type called NAME."
668 (or (srfi-1:find (lambda (image-type)
669 (eq? name (image-type-name image-type)))
670 (force %image-types))
671 (raise
281869e6 672 (formatted-message (G_ "~a: no such image type") name))))
f19cf27c
MO
673
674;;; image.scm ends here