From 11e19555e5693b420f32ab5cc002764ef906ad16 Mon Sep 17 00:00:00 2001 From: Ludovic Courtès Date: Thu, 22 Oct 2020 23:28:31 +0200 Subject: file-systems: Allow swap space lookup by UUID/label. * gnu/build/file-systems.scm (%linux-swap-magic, %page-size): New variables. (linux-swap-superblock?, read-linux-swap-superblock) (linux-swap-superblock-uuid, linux-swap-superblock-volume-name): New procedures. (%partition-label-readers, %partition-uuid-readers): Add them. --- gnu/build/file-systems.scm | 46 +++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 45 insertions(+), 1 deletion(-) (limited to 'gnu/build') diff --git a/gnu/build/file-systems.scm b/gnu/build/file-systems.scm index 734d648575..8ec8eac896 100644 --- a/gnu/build/file-systems.scm +++ b/gnu/build/file-systems.scm @@ -1,5 +1,5 @@ ;;; GNU Guix --- Functional package management for GNU -;;; Copyright © 2014, 2015, 2016, 2017, 2018 Ludovic Courtès +;;; Copyright © 2014, 2015, 2016, 2017, 2018, 2020 Ludovic Courtès ;;; Copyright © 2016, 2017 David Craven ;;; Copyright © 2017 Mathieu Othacehe ;;; Copyright © 2019 Guillaume Le Vaillant @@ -179,6 +179,46 @@ (define (check-ext2-file-system device) (2 'reboot-required) (_ 'fatal-error))) + +;;; +;;; Linux swap. +;;; + +;; Linux "swap space" is not a file system but it has a UUID and volume name, +;; like actual file systems, and we want to be able to look up swap partitions +;; by UUID and by label. + +(define %linux-swap-magic + (string->utf8 "SWAPSPACE2")) + +;; Like 'PAGE_SIZE' in Linux, arch/x86/include/asm/page.h. +;; XXX: This is always 4K on x86_64, i386, and ARMv7. However, on AArch64, +;; this is determined by 'CONFIG_ARM64_PAGE_SHIFT' in the kernel, which is 12 +;; by default (4K) but can be 14 or 16. +(define %page-size 4096) + +(define (linux-swap-superblock? sblock) + "Return #t when SBLOCK is an linux-swap superblock." + (and (= (bytevector-length sblock) %page-size) + (bytevector=? (sub-bytevector sblock (- %page-size 10) 10) + %linux-swap-magic))) + +(define (read-linux-swap-superblock device) + "Return the raw contents of DEVICE's linux-swap superblock as a bytevector, or #f +if DEVICE does not contain an linux-swap file system." + (read-superblock device 0 %page-size linux-swap-superblock?)) + +;; See 'union swap_header' in 'include/linux/swap.h'. + +(define (linux-swap-superblock-uuid sblock) + "Return the UUID of Linux-swap superblock SBLOCK as a 16-byte bytevector." + (sub-bytevector sblock (+ 1024 4 4 4) 16)) + +(define (linux-swap-superblock-volume-name sblock) + "Return the label of Linux-swap superblock SBLOCK as a string." + (null-terminated-latin1->string + (sub-bytevector sblock (+ 1024 4 4 4 16) 16))) + ;;; ;;; Btrfs file systems. @@ -596,6 +636,8 @@ (define %partition-label-readers iso9660-superblock-volume-name) (partition-field-reader read-ext2-superblock ext2-superblock-volume-name) + (partition-field-reader read-linux-swap-superblock + linux-swap-superblock-volume-name) (partition-field-reader read-btrfs-superblock btrfs-superblock-volume-name) (partition-field-reader read-fat32-superblock @@ -612,6 +654,8 @@ (define %partition-uuid-readers iso9660-superblock-uuid) (partition-field-reader read-ext2-superblock ext2-superblock-uuid) + (partition-field-reader read-linux-swap-superblock + linux-swap-superblock-uuid) (partition-field-reader read-btrfs-superblock btrfs-superblock-uuid) (partition-field-reader read-fat32-superblock -- cgit v1.2.3 From a38d861e571c952f78ca588b50bdcc4adcb0c88c Mon Sep 17 00:00:00 2001 From: Mathieu Othacehe Date: Wed, 21 Oct 2020 10:42:50 +0200 Subject: system: reconfigure: Use the disk-installer if provided. Fixes: . * gnu/build/bootloader.scm (write-file-on-device): Pass 'no-fail flag instead of 'no-create. Use a latin-1 transcoder. * guix/scripts/system/reconfigure.scm (install-bootloader-program): Add a "disk-installer" argument and use it as a fallback. (install-bootloader): Adapt accordingly. * gnu/tests/reconfigure.scm (run-install-bootloader-test): Ditto. --- gnu/build/bootloader.scm | 7 +++++-- gnu/tests/reconfigure.scm | 4 +++- guix/scripts/system/reconfigure.scm | 17 ++++++++++++++--- 3 files changed, 22 insertions(+), 6 deletions(-) (limited to 'gnu/build') diff --git a/gnu/build/bootloader.scm b/gnu/build/bootloader.scm index 5ec839f902..3916930c89 100644 --- a/gnu/build/bootloader.scm +++ b/gnu/build/bootloader.scm @@ -38,10 +38,13 @@ (define (write-file-on-device file size device offset) (lambda (input) (let ((bv (get-bytevector-n input size))) (call-with-port + ;; Do not use "call-with-output-file" that would truncate the file. (open-file-output-port device - (file-options no-truncate no-create) + (file-options no-truncate no-fail) (buffer-mode block) - (native-transcoder)) + ;; Use the binary-friendly ISO-8859-1 + ;; encoding. + (make-transcoder (latin-1-codec))) (lambda (output) (seek output offset SEEK_SET) (put-bytevector output bv))))))) diff --git a/gnu/tests/reconfigure.scm b/gnu/tests/reconfigure.scm index 928a210a94..52beeef447 100644 --- a/gnu/tests/reconfigure.scm +++ b/gnu/tests/reconfigure.scm @@ -260,7 +260,9 @@ (define (generations-in-grub-cfg marionette) ;; test suite, the bootloader installer script is omitted. 'grub-install' ;; would attempt to write directly to the virtual disk if the ;; installation script were run. - (test (install-bootloader-program #f #f bootcfg bootcfg-file #f "/"))))) + (test + (install-bootloader-program #f #f #f bootcfg bootcfg-file #f "/"))))) + (define %test-switch-to-system (system-test diff --git a/guix/scripts/system/reconfigure.scm b/guix/scripts/system/reconfigure.scm index d89caf80fc..5581e12892 100644 --- a/guix/scripts/system/reconfigure.scm +++ b/guix/scripts/system/reconfigure.scm @@ -204,7 +204,8 @@ (define target-services ;;; Bootloader configuration. ;;; -(define (install-bootloader-program installer bootloader-package bootcfg +(define (install-bootloader-program installer disk-installer + bootloader-package bootcfg bootcfg-file device target) "Return an executable store item that, upon being evaluated, will install BOOTCFG to BOOTCFG-FILE, a target file name, on DEVICE, a file system device, @@ -246,10 +247,17 @@ (define (install-bootloader-program installer bootloader-package bootcfg ;; a broken installation. (switch-symlinks new-gc-root #$bootcfg) (install-boot-config #$bootcfg #$bootcfg-file #$target) - (when #$installer + (when (or #$installer #$disk-installer) (catch #t (lambda () - (#$installer #$bootloader-package #$device #$target)) + ;; The bootloader might not support installation on a + ;; mounted directory using the BOOTLOADER-INSTALLER + ;; procedure. In that case, fallback to installing the + ;; bootloader directly on DEVICE using the + ;; BOOTLOADER-DISK-IMAGE-INSTALLER procedure. + (if #$installer + (#$installer #$bootloader-package #$device #$target) + (#$disk-installer #$bootloader-package 0 #$device))) (lambda args (delete-file new-gc-root) (match args @@ -272,11 +280,14 @@ (define* (install-bootloader eval configuration bootcfg (let* ((bootloader (bootloader-configuration-bootloader configuration)) (installer (and run-installer? (bootloader-installer bootloader))) + (disk-installer (and run-installer? + (bootloader-disk-image-installer bootloader))) (package (bootloader-package bootloader)) (device (bootloader-configuration-target configuration)) (bootcfg-file (bootloader-configuration-file bootloader))) (eval #~(parameterize ((current-warning-port (%make-void-port "w"))) (primitive-load #$(install-bootloader-program installer + disk-installer package bootcfg bootcfg-file -- cgit v1.2.3 From 61d9c4458eef35a2a3fce94f113031d86b9f4d8d Mon Sep 17 00:00:00 2001 From: Ludovic Courtès Date: Thu, 5 Nov 2020 14:56:16 +0100 Subject: image: Error out when passed an unsupported partition type. * gnu/build/image.scm (make-partition-image): Use 'raise' instead of 'format' when TYPE is not supported. (convert-disk-image): Remove unneeded 'begin'. --- gnu/build/image.scm | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'gnu/build') diff --git a/gnu/build/image.scm b/gnu/build/image.scm index 8a2d0eb5fd..640a784204 100644 --- a/gnu/build/image.scm +++ b/gnu/build/image.scm @@ -118,16 +118,16 @@ (define* (make-partition-image partition-sexp target root) ((string=? type "vfat") (make-vfat-image partition target root)) (else - (format (current-error-port) - "Unsupported partition type~%."))))) + (raise (condition + (&message + (message "unsupported partition type")))))))) (define (convert-disk-image image format output) "Convert IMAGE to OUTPUT according to the given FORMAT." (case format ((compressed-qcow2) - (begin - (invoke "qemu-img" "convert" "-c" "-f" "raw" - "-O" "qcow2" image output))) + (invoke "qemu-img" "convert" "-c" "-f" "raw" + "-O" "qcow2" image output)) (else (copy-file image output)))) -- cgit v1.2.3 From e6934c0429ed94c9d9e61f81520d11153bbb3f64 Mon Sep 17 00:00:00 2001 From: Ludovic Courtès Date: Thu, 5 Nov 2020 15:26:57 +0100 Subject: shepherd: Remove dependency on (guix utils). Since commit 8ce6f4dc2879919c12bc76a2f4b01200af97e019, importing this module in a gexp would pull in (guix config) from the host, thereby leading to non-reproducible derivations. Users in (gnu services ...) do not expect that so simply remove the (guix utils) dependency for now. * gnu/build/shepherd.scm (fork+exec-command/container)[strip-pid]: New procedure. Use it instead of 'strip-keyword-arguments'. --- gnu/build/shepherd.scm | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) (limited to 'gnu/build') diff --git a/gnu/build/shepherd.scm b/gnu/build/shepherd.scm index 91646288d5..d7b858dea4 100644 --- a/gnu/build/shepherd.scm +++ b/gnu/build/shepherd.scm @@ -21,7 +21,6 @@ (define-module (gnu build shepherd) #:use-module (gnu system file-systems) #:use-module (gnu build linux-container) #:use-module (guix build utils) - #:use-module (guix utils) #:use-module (srfi srfi-1) #:use-module (srfi srfi-26) #:use-module (ice-9 match) @@ -199,11 +198,24 @@ (define* (fork+exec-command/container command "This is a variant of 'fork+exec-command' procedure, that joins the namespaces of process PID beforehand. If there is no support for containers, on Hurd systems for instance, fallback to direct forking." + (define (strip-pid args) + ;; TODO: Replace with 'strip-keyword-arguments' when that no longer pulls + ;; in (guix config). + (let loop ((args args) + (result '())) + (match args + (() + (reverse result)) + ((#:pid _ . rest) + (loop rest result)) + ((head . rest) + (loop rest (cons head result)))))) + (let ((container-support? (file-exists? "/proc/self/ns")) (fork-proc (lambda () (apply fork+exec-command command - (strip-keyword-arguments '(#:pid) args))))) + (strip-pid args))))) (if container-support? (container-excursion* pid fork-proc) (fork-proc)))) -- cgit v1.2.3 From 174254749da64a92192ccfb5239867be30fed4ea Mon Sep 17 00:00:00 2001 From: Tobias Geerinckx-Rice Date: Thu, 5 Nov 2020 13:06:18 +0100 Subject: file-systems: Add support for bcachefs. * gnu/build/file-systems.scm (%bcachefs-endianness): New syntax. (bcachefs-superblock?, read-bcachefs-superblock) (bcachefs-superblock-external-uuid, bcachefs-superblock-volume-name) (check-bcachefs-file-system): New procedures. (%partition-label-readers, %partition-uuid-readers, check-file-system): Register them. --- gnu/build/file-systems.scm | 59 +++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 58 insertions(+), 1 deletion(-) (limited to 'gnu/build') diff --git a/gnu/build/file-systems.scm b/gnu/build/file-systems.scm index 8ec8eac896..b762e82ad2 100644 --- a/gnu/build/file-systems.scm +++ b/gnu/build/file-systems.scm @@ -3,7 +3,7 @@ ;;; Copyright © 2016, 2017 David Craven ;;; Copyright © 2017 Mathieu Othacehe ;;; Copyright © 2019 Guillaume Le Vaillant -;;; Copyright © 2019 Tobias Geerinckx-Rice +;;; Copyright © 2019, 2020 Tobias Geerinckx-Rice ;;; Copyright © 2019 David C. Trudgian ;;; Copyright © 2020 Maxim Cournoyer ;;; @@ -218,6 +218,58 @@ (define (linux-swap-superblock-volume-name sblock) "Return the label of Linux-swap superblock SBLOCK as a string." (null-terminated-latin1->string (sub-bytevector sblock (+ 1024 4 4 4 16) 16))) + + +;;; +;;; Bcachefs file systems. +;;; + +;; + +(define-syntax %bcachefs-endianness + ;; Endianness of bcachefs file systems. + (identifier-syntax (endianness little))) + +(define (bcachefs-superblock? sblock) + "Return #t when SBLOCK is an bcachefs superblock." + (bytevector=? (sub-bytevector sblock 24 16) + #vu8(#xc6 #x85 #x73 #xf6 #x4e #x1a #x45 #xca + #x82 #x65 #xf5 #x7f #x48 #xba #x6d #x81))) + +(define (read-bcachefs-superblock device) + "Return the raw contents of DEVICE's bcachefs superblock as a bytevector, or #f +if DEVICE does not contain a bcachefs file system." + ;; We completely ignore the back-up superblock & any checksum errors. + ;; Superblock field names, with offset & length respectively, in bytes: + ;; 0 16 bch_csum + ;; 16 8 version + ;; 24 16 magic + ;; 40 16 uuid ← ‘internal UUID’, you probably don't want this + ;; 56 16 user_uuid ← ‘external UUID’, the one by which to mount + ;; 72 32 label + ;; … there are more & the superblock is extensible, but we don't care yet. + (read-superblock device 4096 104 bcachefs-superblock?)) + +(define (bcachefs-superblock-external-uuid sblock) + "Return the external UUID of bcachefs superblock SBLOCK as a 16-byte +bytevector." + (sub-bytevector sblock 56 16)) + +(define (bcachefs-superblock-volume-name sblock) + "Return the volume name of SBLOCK as a string of at most 32 characters, or +#f if SBLOCK has no volume name." + (null-terminated-latin1->string (sub-bytevector sblock 72 32))) + +(define (check-bcachefs-file-system device) + "Return the health of a bcachefs file system on DEVICE." + (match (status:exit-val + (apply system* "bcachefs" "fsck" "-p" "-v" + ;; Make each multi-device member a separate argument. + (string-split device #\:))) + (0 'pass) + (1 'errors-corrected) + (2 'reboot-required) + (_ 'fatal-error))) ;;; @@ -638,6 +690,8 @@ (define %partition-label-readers ext2-superblock-volume-name) (partition-field-reader read-linux-swap-superblock linux-swap-superblock-volume-name) + (partition-field-reader read-bcachefs-superblock + bcachefs-superblock-volume-name) (partition-field-reader read-btrfs-superblock btrfs-superblock-volume-name) (partition-field-reader read-fat32-superblock @@ -656,6 +710,8 @@ (define %partition-uuid-readers ext2-superblock-uuid) (partition-field-reader read-linux-swap-superblock linux-swap-superblock-uuid) + (partition-field-reader read-bcachefs-superblock + bcachefs-superblock-external-uuid) (partition-field-reader read-btrfs-superblock btrfs-superblock-uuid) (partition-field-reader read-fat32-superblock @@ -763,6 +819,7 @@ (define (check-file-system device type) (define check-procedure (cond ((string-prefix? "ext" type) check-ext2-file-system) + ((string-prefix? "bcachefs" type) check-bcachefs-file-system) ((string-prefix? "btrfs" type) check-btrfs-file-system) ((string-suffix? "fat" type) check-fat-file-system) ((string-prefix? "jfs" type) check-jfs-file-system) -- cgit v1.2.3 From b9abb301d0911e33747e59bb61bb9858f0cb4a77 Mon Sep 17 00:00:00 2001 From: Tobias Geerinckx-Rice Date: Thu, 5 Nov 2020 11:03:21 +0100 Subject: linux-boot: Resume from hibernation. * gnu/build/linux-boot.scm (resume-if-hibernated): New procedure. (boot-system): Call it. --- gnu/build/linux-boot.scm | 59 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 59 insertions(+) (limited to 'gnu/build') diff --git a/gnu/build/linux-boot.scm b/gnu/build/linux-boot.scm index 32e3536039..bfaac9ec1f 100644 --- a/gnu/build/linux-boot.scm +++ b/gnu/build/linux-boot.scm @@ -1,5 +1,6 @@ ;;; GNU Guix --- Functional package management for GNU ;;; Copyright © 2013, 2014, 2015, 2016, 2017, 2018, 2019, 2020 Ludovic Courtès +;;; Copyright © 2016, 2017, 2019, 2020 Tobias Geerinckx-Rice ;;; Copyright © 2017 Mathieu Othacehe ;;; Copyright © 2019 Guillaume Le Vaillant ;;; @@ -110,6 +111,58 @@ (define (find-long-options option arguments) (substring arg (+ 1 (string-index arg #\=))))) arguments))) +(define (resume-if-hibernated device) + "Resume from hibernation if possible. This is safe ONLY if no on-disk file +systems have been mounted; calling it later risks severe file system corruption! +See in the kernel source directory. This is the +caller's responsibility, as is catching exceptions if resumption was supposed to +happen but didn't. + +Resume only from DEVICE if it's a string. If it's #f, use the kernel's default +hibernation device (CONFIG_PM_STD_PARTITION). Never return if resumption +succeeds. Return nothing otherwise. The kernel logs any details to dmesg." + + (define (string->major:minor string) + "Return a string with MAJOR:MINOR numbers of the device specified by STRING" + + ;; The "resume=" kernel command-line option always provides a string, which + ;; can represent a device, a UUID, or a label. Check for all three. + (let* ((spec (cond ((string-prefix? "/" string) string) + ((uuid string) => identity) + (else (file-system-label string)))) + ;; XXX The kernel's swsusp_resume_can_resume() waits if ‘resumewait’ + ;; is found on the command line; our canonicalize-device-spec gives + ;; up after 20 seconds. We could emulate the former by looping… + (device (canonicalize-device-spec spec)) + (rdev (stat:rdev (stat device))) + ;; For backwards compatibility, device numbering is a baroque affair. + ;; This is the full 64-bit scheme used by glibc's . + (major (logior (ash (logand #x00000000000fff00 rdev) -8) + (ash (logand #xfffff00000000000 rdev) -32))) + (minor (logior (logand #x00000000000000ff rdev) + (ash (logand #x00000ffffff00000 rdev) -12)))) + (format #f "~a:~a" major minor))) + + ;; Write the resume DEVICE to this magic file, using the MAJOR:MINOR device + ;; numbers if possible. The kernel will immediately try to resume from it. + (let ((resume "/sys/power/resume")) + (when (file-exists? resume) ; this kernel supports hibernation + ;; Honour the kernel's default device (only) if none other was given. + (let ((major:minor (if device + (or (false-if-exception (string->major:minor + device)) + ;; We can't parse it. Maybe the kernel can. + device) + (let ((default (call-with-input-file resume + read-line))) + ;; Don't waste time echoing 0:0 to /sys. + (if (string=? "0:0" default) + #f + default))))) + (when major:minor + (call-with-output-file resume ; may throw an ‘Invalid argument’ + (cut display major:minor <>))))))) ; may never return + (define* (make-disk-device-nodes base major #:optional (minor 0)) "Make the block device nodes around BASE (something like \"/root/dev/sda\") with the given MAJOR number, starting with MINOR." @@ -507,6 +560,12 @@ (define (device-string->file-system-device device-string) (load-linux-modules-from-directory linux-modules linux-module-directory) + (unless (member "noresume" args) + ;; Try to resume immediately after loading (storage) modules + ;; but before any on-disk file systems have been mounted. + (false-if-exception ; failure is not fatal + (resume-if-hibernated (find-long-option "resume" args)))) + (when keymap-file (let ((status (system* "loadkeys" keymap-file))) (unless (zero? status) -- cgit v1.2.3 From d7a295b24b8b84ca3193d30249a01f292178105a Mon Sep 17 00:00:00 2001 From: Marius Bakke Date: Sat, 31 Oct 2020 17:25:58 +0100 Subject: Add (gnu build chromium-extension). * gnu/build/chromium-extension.scm: New file. * gnu/local.mk (GNU_SYSTEM_MODULES): Adjust accordingly. --- gnu/build/chromium-extension.scm | 192 +++++++++++++++++++++++++++++++++++++++ gnu/local.mk | 1 + 2 files changed, 193 insertions(+) create mode 100644 gnu/build/chromium-extension.scm (limited to 'gnu/build') diff --git a/gnu/build/chromium-extension.scm b/gnu/build/chromium-extension.scm new file mode 100644 index 0000000000..d65df09f37 --- /dev/null +++ b/gnu/build/chromium-extension.scm @@ -0,0 +1,192 @@ +;;; GNU Guix --- Functional package management for GNU +;;; Copyright © 2020 Marius Bakke +;;; +;;; This file is part of GNU Guix. +;;; +;;; GNU Guix is free software; you can redistribute it and/or modify it +;;; under the terms of the GNU General Public License as published by +;;; the Free Software Foundation; either version 3 of the License, or (at +;;; your option) any later version. +;;; +;;; GNU Guix is distributed in the hope that it will be useful, but +;;; WITHOUT ANY WARRANTY; without even the implied warranty of +;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;;; GNU General Public License for more details. +;;; +;;; You should have received a copy of the GNU General Public License +;;; along with GNU Guix. If not, see . + +(define-module (gnu build chromium-extension) + #:use-module (gcrypt base16) + #:use-module ((gcrypt hash) #:prefix hash:) + #:use-module (ice-9 iconv) + #:use-module (guix gexp) + #:use-module (guix packages) + #:use-module (gnu packages base) + #:use-module (gnu packages check) + #:use-module (gnu packages chromium) + #:use-module (gnu packages gnupg) + #:use-module (gnu packages tls) + #:use-module (gnu packages xorg) + #:use-module (guix build-system trivial) + #:export (make-chromium-extension)) + +;;; Commentary: +;;; +;;; Tools to deal with Chromium extensions. +;;; +;;; Code: + +(define (make-signing-key seed) + "Return a derivation for a deterministic PKCS #8 private key using SEED." + + (define sha256sum + (bytevector->base16-string (hash:sha256 (string->bytevector seed "UTF-8")))) + + ;; certtool.c wants a 56 byte seed for a 2048 bit key. + (define size 2048) + (define normalized-seed (string-take sha256sum 56)) + + (computed-file (string-append seed "-signing-key.pem") + #~(system* #$(file-append gnutls "/bin/certtool") + "--generate-privkey" + "--key-type=rsa" + "--pkcs8" + ;; Use the provable FIPS-PUB186-4 algorithm for + ;; deterministic results. + "--provable" + "--password=" + "--no-text" + (string-append "--bits=" #$(number->string size)) + (string-append "--seed=" #$normalized-seed) + "--outfile" #$output) + #:local-build? #t)) + +(define* (make-crx signing-key package #:optional (package-output "out")) + "Create a signed \".crx\" file from the unpacked Chromium extension residing +in PACKAGE-OUTPUT of PACKAGE. The extension will be signed with SIGNING-KEY." + (define name (package-name package)) + (define version (package-version package)) + + (with-imported-modules '((guix build utils)) + (computed-file + (string-append name "-" version ".crx") + #~(begin + ;; This is not great. We pull Xorg and Chromium just to Zip and + ;; sign an extension. This should be implemented with something + ;; lighter. (TODO: where is the CRXv3 documentation..?) + (use-modules (guix build utils)) + (let ((chromium #$(file-append ungoogled-chromium "/bin/chromium")) + (xvfb #$(file-append xorg-server "/bin/Xvfb")) + (packdir "/tmp/extension")) + (mkdir-p (dirname packdir)) + (copy-recursively (ungexp package package-output) packdir) + (system (string-append xvfb " :1 &")) + (setenv "DISPLAY" ":1") + (sleep 2) ;give Xorg some time to initialize... + ;; Chromium stores the current time in the .crx Zip archive. + ;; Use a fixed timestamp for deterministic behavior. + ;; FIXME (core-updates): faketime is missing an absolute reference + ;; to 'date', hence the need to set PATH. + (setenv "PATH" #$(file-append coreutils "/bin")) + (invoke #$(file-append libfaketime "/bin/faketime") + "2000-01-01 00:00:00" + chromium + "--user-data-dir=/tmp/signing-profile" + (string-append "--pack-extension=" packdir) + (string-append "--pack-extension-key=" #$signing-key)) + (copy-file (string-append packdir ".crx") #$output))) + #:local-build? #t))) + +(define* (crx->chromium-json crx version) + "Return a derivation that creates a Chromium JSON settings file for the +extension given as CRX. VERSION is used to signify the CRX version, and +must match the version listed in the extension manifest.json." + ;; See chrome/browser/extensions/external_provider_impl.cc and + ;; extensions/common/extension.h for documentation on the JSON format. + (computed-file "extension.json" + #~(call-with-output-file #$output + (lambda (port) + (format port "{ + \"external_crx\": \"~a\", + \"external_version\": \"~a\" +} +" + #$crx #$version))) + #:local-build? #t)) + + +(define (signing-key->public-der key) + "Return a derivation for a file containing the public key of KEY in DER +format." + (computed-file "der" + #~(system* #$(file-append gnutls "/bin/certtool") + "--load-privkey" #$key + "--pubkey-info" + "--outfile" #$output + "--outder") + #:local-build? #t)) + +(define (chromium-json->profile-object json signing-key) + "Return a derivation that installs JSON to the directory searched by +Chromium, using a file name (aka extension ID) derived from SIGNING-KEY." + (define der (signing-key->public-der signing-key)) + + (with-extensions (list guile-gcrypt) + (with-imported-modules '((guix build utils)) + (computed-file + "chromium-extension" + #~(begin + (use-modules (guix build utils) + (gcrypt base16) + (gcrypt hash)) + (define (base16-string->chromium-base16 str) + ;; Translate STR, a hexadecimal string, to a Chromium-style + ;; representation using the letters a-p (where a=0, p=15). + (define s1 "0123456789abcdef") + (define s2 "abcdefghijklmnop") + (let loop ((chars (string->list str)) + (converted '())) + (if (null? chars) + (list->string (reverse converted)) + (loop (cdr chars) + (cons (string-ref s2 (string-index s1 (car chars))) + converted))))) + + (let* ((checksum (bytevector->base16-string (file-sha256 #$der))) + (file-name (base16-string->chromium-base16 + (string-take checksum 32))) + (extension-directory (string-append #$output + "/share/chromium/extensions"))) + (mkdir-p extension-directory) + (symlink #$json (string-append extension-directory "/" + file-name ".json")))) + #:local-build? #t)))) + +(define* (make-chromium-extension p #:optional (output "out")) + "Create a Chromium extension from package P and return a package that, +when installed, will make the extension contained in P available as a +Chromium browser extension. OUTPUT specifies which output of P to use." + (let* ((pname (package-name p)) + (version (package-version p)) + (signing-key (make-signing-key pname))) + (package + (inherit p) + (name (string-append pname "-chromium")) + (source #f) + (build-system trivial-build-system) + (native-inputs '()) + (inputs + `(("extension" ,(chromium-json->profile-object + (crx->chromium-json (make-crx signing-key p output) + version) + signing-key)))) + (propagated-inputs '()) + (outputs '("out")) + (arguments + '(#:modules ((guix build utils)) + #:builder + (begin + (use-modules (guix build utils)) + (copy-recursively (assoc-ref %build-inputs "extension") + (assoc-ref %outputs "out")))))))) diff --git a/gnu/local.mk b/gnu/local.mk index 3a8f1e30fc..9069dd8bc2 100644 --- a/gnu/local.mk +++ b/gnu/local.mk @@ -657,6 +657,7 @@ GNU_SYSTEM_MODULES = \ %D%/build/accounts.scm \ %D%/build/activation.scm \ %D%/build/bootloader.scm \ + %D%/build/chromium-extension.scm \ %D%/build/cross-toolchain.scm \ %D%/build/image.scm \ %D%/build/file-systems.scm \ -- cgit v1.2.3 From 2200bb214690ebc78b9fa42887ac9dfb8035bd4f Mon Sep 17 00:00:00 2001 From: Ludovic Courtès Date: Thu, 19 Nov 2020 22:02:16 +0100 Subject: linux-initrd: Remove unnecessary timestamp reset phase. * gnu/build/linux-initrd.scm (write-cpio-archive): Mention timestamps in docstring. (build-initrd): Remove unnecessary timestamp reset phase. --- gnu/build/linux-initrd.scm | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) (limited to 'gnu/build') diff --git a/gnu/build/linux-initrd.scm b/gnu/build/linux-initrd.scm index ea7de58553..99796adba6 100644 --- a/gnu/build/linux-initrd.scm +++ b/gnu/build/linux-initrd.scm @@ -1,5 +1,5 @@ ;;; GNU Guix --- Functional package management for GNU -;;; Copyright © 2013, 2014, 2015, 2018 Ludovic Courtès +;;; Copyright © 2013, 2014, 2015, 2018, 2020 Ludovic Courtès ;;; ;;; This file is part of GNU Guix. ;;; @@ -39,8 +39,9 @@ (define* (write-cpio-archive output directory #:key (compress? #t) (gzip "gzip")) - "Write a cpio archive containing DIRECTORY to file OUTPUT. When -COMPRESS? is true, compress it using GZIP. On success, return OUTPUT." + "Write a cpio archive containing DIRECTORY to file OUTPUT, with reset +timestamps in the archive. When COMPRESS? is true, compress it using GZIP. +On success, return OUTPUT." ;; Note: as per `ramfs-rootfs-initramfs.txt', always add directory entries ;; before the files that are inside of it: "The Linux kernel cpio @@ -141,12 +142,6 @@ (define* (build-initrd output (symlink (string-append guile "/bin/guile") "proc/self/exe") (readlink "proc/self/exe") - ;; Reset the timestamps of all the files that will make it in the initrd. - (for-each (lambda (file) - (unless (eq? 'symlink (stat:type (lstat file))) - (utime file 0 0 0 0))) - (find-files "." ".*")) - (write-cpio-archive output "." #:gzip gzip)) ;; Make sure directories are writable so we can delete files. -- cgit v1.2.3