aboutsummaryrefslogtreecommitdiff
;;; GNU Guix --- Functional package management for GNU
;;; Copyright © 2016-2020, 2022-2023 Ludovic Courtès <ludo@gnu.org>
;;; Copyright © 2017 Mathieu Othacehe <m.othacehe@gmail.com>
;;; Copyright © 2017 Tobias Geerinckx-Rice <me@tobias.gr>
;;; Copyright © 2021 Maxime Devos <maximedevos@telenet.be>
;;;
;;; 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 <http://www.gnu.org/licenses/>.

(define-module (gnu tests)
  #:use-module (guix gexp)
  #:use-module (guix diagnostics)
  #:use-module (guix records)
  #:use-module ((guix ui) #:select (warn-about-load-error))
  #:use-module (gnu bootloader)
  #:use-module (gnu bootloader grub)
  #:use-module (gnu system)
  #:use-module (gnu system file-systems)
  #:use-module (gnu system shadow)
  #:use-module (gnu services)
  #:use-module (gnu services base)
  #:use-module (gnu services shepherd)
  #:use-module (guix discovery)
  #:use-module (guix monads)
  #:use-module ((guix store) #:select (%store-monad))
  #:use-module ((guix utils)
                #:select (%current-system %current-target-system))
  #:use-module (srfi srfi-1)
  #:use-module (srfi srfi-9 gnu)
  #:use-module (ice-9 match)
  #:export (marionette-configuration
            marionette-configuration?
            marionette-configuration-device
            marionette-configuration-imported-modules
            marionette-configuration-requirements

            marionette-service-type
            marionette-operating-system
            define-os-with-source

            %simple-os
            simple-operating-system

            system-test
            system-test?
            system-test-name
            system-test-value
            system-test-description
            system-test-location

            fold-system-tests
            all-system-tests))

;;; Commentary:
;;;
;;; This module provides the infrastructure to run operating system tests.
;;; The most important part of that is tools to instrument the OS under test,
;;; essentially allowing it to run in a virtual machine controlled by the host
;;; system--hence the name "marionette".
;;;
;;; Code:

(define-record-type* <marionette-configuration>
  marionette-configuration make-marionette-configuration
  marionette-configuration?
  (device           marionette-configuration-device ;string
                    (default "/dev/virtio-ports/org.gnu.guix.port.0"))
  (imported-modules marionette-configuration-imported-modules
                    (default '()))
  (extensions       marionette-configuration-extensions
                    (default '())) ; list of packages
  (requirements     marionette-configuration-requirements ;list of symbols
                    (default '())))

;; Hack: avoid indenting code beyond column 80 in marionette-shepherd-service.
(define-syntax-rule (with-imported-modules-and-extensions imported-modules
                                                          extensions
                                                          gexp)
  (with-imported-modules imported-modules
    (with-extensions extensions
      gexp)))

(define (marionette-program device imported-modules extensions)
  "Return the program that runs the marionette REPL on DEVICE.  Ensure
IMPORTED-MODULES and EXTENSIONS are accessible from the REPL."
  (define code
    (with-imported-modules-and-extensions
        `((guix build utils)
          (guix build syscalls)
          ,@imported-modules)
        extensions
      #~(begin
          (use-modules (ice-9 match)
                       (ice-9 binary-ports))

          (define (self-quoting? x)
            (letrec-syntax ((one-of (syntax-rules ()
                                      ((_) #f)
                                      ((_ pred rest ...)
                                       (or (pred x)
                                           (one-of rest ...))))))
              (one-of symbol? string? keyword? pair? null? array?
                      number? boolean? char?)))

          (let ((repl    (open-file #$device "r+0"))
                (console (open-file "/dev/console" "r+0")))
            ;; Redirect output to the console.
            (close-fdes 1)
            (close-fdes 2)
            (dup2 (fileno console) 1)
            (dup2 (fileno console) 2)
            (close-port console)

            (display 'ready repl)
            (let loop ()
              (newline repl)

              (match (read repl)
                ((? eof-object?)
                 (primitive-exit 0))
                (expr
                 (catch #t
                   (lambda ()
                     (let ((result (primitive-eval expr)))
                       (write (if (self-quoting? result)
                                  result
                                  (object->string result))
                              repl)))
                   (lambda (key . args)
                     (print-exception (current-error-port)
                                      (stack-ref (make-stack #t) 1)
                                      key args)
                     (write #f repl)))))
              (loop))))))

  (program-file "marionette-repl.scm" code))

(define (marionette-shepherd-service config)
  "Return the Shepherd service for the marionette REPL"
  (match config
    (($ <marionette-configuration> device imported-modules extensions
                                   requirement)
     (list (shepherd-service
            (provision '(marionette))

            ;; Always depend on UDEV so that DEVICE is available.
            (requirement `(udev ,@requirement))

            (modules '((ice-9 match)
                       (srfi srfi-9 gnu)))
            (start #~(make-forkexec-constructor
                      (list #$(marionette-program device
                                                  imported-modules
                                                  extensions))))
            (stop #~(make-kill-destructor)))))))

(define marionette-service-type
  ;; This is the type of the "marionette" service, allowing a guest system to
  ;; be manipulated from the host.  This marionette REPL is essentially a
  ;; universal backdoor.
  (service-type (name 'marionette-repl)
                (extensions
                 (list (service-extension shepherd-root-service-type
                                          marionette-shepherd-service)))
                (description "The @dfn{marionette} service allows a guest
system (virtual machine) to be manipulated by the host.  It is used for system
tests.")))

(define* (marionette-operating-system os
                                      #:key
                                      (imported-modules '())
                                      (extensions '())
                                      (requirements '()))
  "Return a marionetteed variant of OS such that OS can be used as a
marionette in a virtual machine--i.e., controlled from the host system.  The
marionette service in the guest is started after the Shepherd services listed
in REQUIREMENTS.  The packages in the list EXTENSIONS are made available from
the backdoor REPL."
  (operating-system
    (inherit os)
    ;; Make sure the guest dies on error.
    (kernel-arguments (cons "panic=1"
                            (operating-system-user-kernel-arguments os)))
    ;; Make sure the guest doesn't hang in the REPL on error.
    (initrd (lambda (fs . rest)
              (apply (operating-system-initrd os) fs
                     #:on-error 'backtrace
                     rest)))
    (services (cons (service marionette-service-type
                             (marionette-configuration
                              (requirements requirements)
                              (extensions extensions)
                              (imported-modules imported-modules)))
                    (operating-system-user-services os)))))

(define-syntax define-os-with-source
  (syntax-rules (use-modules operating-system)
    "Define two variables: OS containing the given operating system, and
SOURCE containing the source to define OS as an sexp.

This is convenient when we need both the <operating-system> object so we can
instantiate it, and the source to create it so we can store in in a file in
the system under test."
    ((_ (os source)
        (use-modules modules ...)
        (operating-system fields ...))
     (begin
       (define os
         (operating-system fields ...))
       (define source
         '(begin
            (use-modules modules ...)
            (operating-system fields ...)))))))


;;;
;;; Simple operating systems.
;;;

(define %simple-os
  (operating-system
    (host-name "komputilo")
    (timezone "Europe/Berlin")
    (locale "en_US.UTF-8")

    (bootloader (bootloader-configuration
                 (bootloader grub-bootloader)
                 (targets '("/dev/sdX"))))
    (file-systems (cons (file-system
                          (device (file-system-label "my-root"))
                          (mount-point "/")
                          (type "ext4"))
                        %base-file-systems))
    (firmware '())

    (users (cons (user-account
                  (name "alice")
                  (comment "Bob's sister")
                  (group "users")
                  (supplementary-groups '("wheel" "audio" "video")))
                 %base-user-accounts))))

(define-syntax-rule (simple-operating-system user-services ...)
  "Return an operating system that includes USER-SERVICES in addition to
%BASE-SERVICES."
  (operating-system (inherit %simple-os)
                    (services (cons* user-services ... %base-services))))



;;;
;;; Tests.
;;;

(define-record-type* <system-test> system-test make-system-test
  system-test?
  (name        system-test-name)                  ;string
  (value       system-test-value)                 ;%STORE-MONAD value
  (description system-test-description)           ;string
  (location    system-test-location (innate)      ;<location>
               (default (and=> (current-source-location)
                               source-properties->location))))

(define (write-system-test test port)
  (match test
    (($ <system-test> name _ _ ($ <location> file line))
     (format port "#<system-test ~a ~a:~a ~a>"
             name file line
             (number->string (object-address test) 16)))
    (($ <system-test> name)
     (format port "#<system-test ~a ~a>" name
             (number->string (object-address test) 16)))))

(set-record-type-printer! <system-test> write-system-test)

(define-gexp-compiler (compile-system-test (test <system-test>)
                                           system target)
  "Compile TEST to a derivation."
  (mparameterize %store-monad ((%current-system system)
                               (%current-target-system target))
    (system-test-value test)))

(define (test-modules)
  "Return the list of modules that define system tests."
  (scheme-modules (dirname (search-path %load-path "guix.scm"))
                  "gnu/tests"
                  #:warn warn-about-load-error))

(define (fold-system-tests proc seed)
  "Invoke PROC on each system test, passing it the test and the previous
result."
  (fold-module-public-variables (lambda (obj result)
                                  (if (system-test? obj)
                                      (cons obj result)
                                      result))
                                '()
                                (test-modules)))

(define (all-system-tests)
  "Return the list of system tests."
  (reverse (fold-system-tests cons '())))


;; Local Variables:
;; eval: (put 'with-imported-modules-and-extensions 'scheme-indent-function 2)
;; End:

;;; tests.scm ends here
Add 'port' parameter and honor it. (process-query): Likewise. (process-substitution): Likewise. (%error-to-file-descriptor-4?, with-redirected-error-port): Remove. (%reply-file-descriptor): New variable. (guix-substitute): Remove use of 'with-redirected-error-port'. Define 'reply-port' and pass it to 'process-query' and 'process-substitution'. * nix/libstore/build.cc (SubstitutionGoal::handleChildOutput): Swap 'builderOut' and 'fromAgent'. * nix/libstore/local-store.cc (LocalStore::getLineFromSubstituter): Likewise. * tests/substitute.scm <top level>: Set '%reply-file-descriptor' rather than '%error-to-file-descriptor-4?'. Ludovic Courtès 2021-03-18daemon: Prevent privilege escalation with '--keep-failed' [security]....Fixes <https://bugs.gnu.org/47229>. Reported by Nathan Nye of WhiteBeam Security. * nix/libstore/build.cc (DerivationGoal::startBuilder): When 'useChroot' is true, add "/top" to 'tmpDir'. (DerivationGoal::deleteTmpDir): Adjust accordingly. When 'settings.keepFailed' is true, chown in two steps: first the "/top" sub-directory, and then rename "/top" to its parent. Ludovic Courtès 2020-12-19daemon: Delegate deduplication to 'guix substitute'....This removes the main source of latency between subsequent downloads. * nix/libstore/build.cc (SubstitutionGoal::tryToRun): Add a "deduplicate" key to ENV. (SubstitutionGoal::finished): Remove call to 'optimisePath'. * guix/scripts/substitute.scm (process-substitution)[destination-in-store?] [dump-file/deduplicate*]: New variables. Pass #:dump-file to 'restore-file'. * guix/scripts/substitute.scm (guix-substitute)[deduplicate?]: New variable. Pass #:deduplicate? to 'process-substitution'. * guix/serialization.scm (dump-file): Export and augment 'dump-file'. Ludovic Courtès 2020-12-19daemon: Do not reset timestamps and permissions on substituted items....'guix substitute' now takes care of it via 'restore-file'. * nix/libstore/build.cc (SubstitutionGoal::finished): Remove call to 'canonicalisePathMetaData'. Ludovic Courtès 2020-12-19daemon: Let 'guix substitute' perform hash checks....This way, the hash of the store item can be computed as it is restored, thereby avoiding an additional file tree traversal ('hashPath' call) later on in the daemon. Consequently, it should reduce latency between subsequent substitute downloads. This is a followup to 5ff521452b9ec2aae9ed8e4bb7bdc250a581f203. * guix/scripts/substitute.scm (narinfo-hash-algorithm+value): New procedure. (process-substitution): Wrap INPUT into a hash input port, 'hashed', and read from it. Compare the actual and expected hashes, and print a "hash-mismatch" status line when they differ. When they match, print not just "success" but also the nar hash and size. * nix/libstore/build.cc (class SubstitutionGoal)[expectedHashStr]: Remove. (SubstitutionGoal::finished): Tokenize 'status'. Parse it and handle "success" and "hash-mismatch" accordingly. Call 'hashPath' only when the returned hash is not SHA256. (SubstitutionGoal::handleChildOutput): Remove 'expectedHashStr' handling. * tests/substitute.scm ("substitute, invalid hash"): Rename to... ("substitute, invalid narinfo hash"): ... this. ("substitute, invalid hash"): New test. Ludovic Courtès 2020-12-08daemon: Raise an error if substituter doesn't send the expected hash....It was already impossible in practice for 'expectedHashStr' to be empty if 'status' == "success". * nix/libstore/build.cc (SubstitutionGoal::finished): Throw 'SubstError' when 'expectedHashStr' is empty. Ludovic Courtès 2020-12-08substitute: Cache and reuse connections while substituting....That way, when fetching a series of substitutes from the same server(s), the connection is reused instead of being closed/opened for each substitutes, which saves on network round trips and TLS handshakes. * guix/http-client.scm (http-fetch): Add #:keep-alive? and honor it. * guix/progress.scm (progress-report-port): Add #:close? parameter and honor it. * guix/scripts/substitute.scm (at-most): Return the tail as a second value. (fetch): Add #:port and #:keep-alive? and honor them. (%max-cached-connections): New variable. (open-connection-for-uri/cached, call-with-cached-connection): New procedures. (with-cached-connection): New macro. (process-substitution): Wrap 'fetch' call in 'with-cached-connection'. Pass #:close? to 'progress-report-port'. Ludovic Courtès 2020-12-08daemon: Run 'guix substitute --substitute' as an agent....This avoids spawning one substitute process per substitution. * nix/libstore/build.cc (class Worker)[substituter]: New field. [outPipe, logPipe, pid]: Remove. (class SubstitutionGoal)[expectedHashStr, status, substituter]: New fields. (SubstitutionGoal::timedOut): Adjust to check 'substituter'. (SubstitutionGoal::tryToRun): Remove references to 'outPipe' and 'logPipe'. Run "guix substitute --substitute" as an 'Agent'. Send the request with 'writeLine'. (SubstitutionGoal::finished): Likewise. (SubstitutionGoal::handleChildOutput): Change to fill in 'expectedHashStr' and 'status'. (SubstitutionGoal::handleEOF): Call 'wakeUp' unconditionally. (SubstitutionGoal::~SubstitutionGoal): Adjust to check 'substituter'. * guix/scripts/substitute.scm (process-substitution): Write "success\n" to stdout upon success. (%error-to-file-descriptor-4?): New variable. (guix-substitute): Set 'current-error-port' to file descriptor 4 unless (%error-to-file-descriptor-4?) is false. Remove "--substitute" arguments. Loop reading line from stdin. * tests/substitute.scm <top level>: Call '%error-to-file-descriptor-4?'. (request-substitution): New procedure. ("substitute, no signature") ("substitute, invalid hash") ("substitute, unauthorized key") ("substitute, authorized key") ("substitute, unauthorized narinfo comes first") ("substitute, unsigned narinfo comes first") ("substitute, first narinfo is unsigned and has wrong hash") ("substitute, first narinfo is unsigned and has wrong refs") ("substitute, two invalid narinfos") ("substitute, narinfo with several URLs"): Adjust to new "guix substitute --substitute" calling convention. Ludovic Courtès 2020-12-08daemon: Factorize substituter agent spawning....* nix/libstore/local-store.hh (class LocalStore)[substituter]: New method. [runningSubstituter]: Turn into a shared_ptr. * nix/libstore/local-store.cc (LocalStore::querySubstitutablePaths): Call 'substituter' instead of using inline code. (LocalStore::querySubstitutablePathInfos): Likewise. (LocalStore::substituter): New method. Ludovic Courtès 2020-12-08daemon: Use 'Agent' to spawn 'guix substitute --query'....* nix/libstore/local-store.hh (RunningSubstituter): Remove. (LocalStore)[runningSubstituter]: Change to unique_ptr<Agent>. [setSubstituterEnv, didSetSubstituterEnv]: Remove. [getLineFromSubstituter, getIntLineFromSubstituter]: Take an 'Agent'. * nix/libstore/local-store.cc (LocalStore::~LocalStore): Remove reference to 'runningSubstituter'. (LocalStore::setSubstituterEnv, LocalStore::startSubstituter): Remove. (LocalStore::getLineFromSubstituter): Adjust to 'run' being an 'Agent'. (LocalStore::querySubstitutablePaths): Spawn substituter agent if needed. Adjust to 'Agent' interface. (LocalStore::querySubstitutablePathInfos): Likewise. * nix/libstore/build.cc (SubstitutionGoal::tryToRun): Remove call to 'setSubstituterEnv' and add 'setenv' call for "_NIX_OPTIONS" instead. (SubstitutionGoal::finished): Remove 'readLine' call for 'dummy'. * guix/scripts/substitute.scm (%allow-unauthenticated-substitutes?): Remove second argument to 'make-parameter'. (process-query): Call 'warn-about-missing-authentication' when (%allow-unauthenticated-substitutes?) is #t. (guix-substitute): Wrap body in 'parameterize'. Set 'guix-warning-port' too. No longer exit when 'substitute-urls' returns the empty list. No longer print newline initially. * tests/substitute.scm (test-quit): Parameterize 'current-error-port' to account for the port changes in 'guix-substitute'. Ludovic Courtès 2020-12-01daemon: Remove unneeded forward declaration....This is a followup to ee9dff34f9317509cb2b833d07a0d5e01a36a4ae. * nix/libstore/build.cc: Remove 'struct Agent' forward declaration. Ludovic Courtès 2020-11-29daemon: Remove pre-Guix hack....* nix/libstore/build.cc (DerivationGoal::startBuilder): Remove "NIX_OUTPUT_CHECKED" hack. Ludovic Courtès 2020-10-09nix: Honor '--rounds' when also using '--check'....Fixes <https://issues.guix.gnu.org/40144>. Until now, the '--rounds' option, when also using '--check', was ignored. This change makes it possible to use both, so that an item that has already been built once can be rebuilt as many times as desired. * nix/libstore/build.cc: Remove the conditionals causing the daemon to complete a build task early when 'buildMode' is equal to 'nix::bmCheck'. Reported-by: Brice Waegeneire <brice@waegenei.re> Maxim Cournoyer 2020-10-01daemon: Try to execute derivation builders only for matching OS kernels....Fixes <https://bugs.gnu.org/43668>. Previously, guix-daemon would try to run GNU/Hurd executables on GNU/Linux. execve(2) would succeed, but the executable would immediately crash. This change prevents it from attempting to execute "i586-gnu" code on "*-linux", while preserving the binfmt_misc-friendly behavior implemented in commit 7bf2a70a4ffd976d50638d3b9f2ec409763157df. * nix/libstore/build.cc (sameOperatingSystemKernel): New function. (DerivationGoal::runChild): Call 'execve' only when 'sameOperatingSystemKernel' returns true. Ludovic Courtès 2020-09-14daemon: Spawn 'guix authenticate' once for all....Previously, we'd spawn 'guix authenticate' once for each item that has to be signed (when exporting) or authenticated (when importing). Now, we spawn it once for all and then follow a request/reply protocol. This reduces the wall-clock time of: guix archive --export -r $(guix build coreutils -d) from 30s to 2s. * guix/scripts/authenticate.scm (sign-with-key): Return the signature instead of displaying it. Raise a &formatted-message instead of calling 'leave'. (validate-signature): Likewise. (read-command): New procedure. (define-enumerate-type, reply-code): New macros. (guix-authenticate)[send-reply]: New procedure. Change to read commands from current-input-port. * nix/libstore/local-store.cc (runAuthenticationProgram): Remove. (authenticationAgent, readInteger, readAuthenticateReply): New functions. (signHash, verifySignature): Rewrite in terms of the agent. * tests/store.scm ("import not signed"): Remove 'pk' call. ("import signed by unauthorized key"): Check the error message of C. * tests/guix-authenticate.sh: Rewrite using the new protocol. fixlet Ludovic Courtès 2020-09-14daemon: Move 'Agent' to libutil....* nix/libstore/build.cc (DerivationGoal::tryBuildHook): Add "offload" to 'args' and pass settings.guixProgram as the first argument to Agent::Agent. (pathNullDevice, commonChildInit, Agent, Agent::Agent) (Agent::~Agent): Move to... * nix/libutil/util.cc: ... here. * nix/libutil/util.hh (struct Agent, commonChildInit): New declarations. Ludovic Courtès 2020-09-14daemon: Isolate signing and signature verification functions....* nix/libstore/local-store.cc (signHash, verifySignature): New functions. (LocalStore::exportPath): Use 'signHash' instead of inline code. (LocalStore::importPath): Use 'verifySignature' instead of inline code. Ludovic Courtès 2020-09-14daemon: Generalize 'HookInstance' to 'Agent'....* nix/libstore/build.cc (HookInstance): Rename to... (Agent): ... this. Rename 'toHook' and 'fromHook' similarly and update users. Change constructor to require a command and an argument list. (DerivationGoal::tryBuildHook): Pass arguments to the 'Agent' constructor. Ludovic Courtès 2020-09-11daemon: Simplify interface with 'guix authenticate'....There's no reason at this point to mimic the calling convention of the 'openssl' command. * nix/libstore/local-store.cc (LocalStore::exportPath): Add only "sign" and HASH to ARGS. Remove 'tmpDir' and 'hashFile'. (LocalStore::importPath): Add only "verify" and SIGNATURE to * guix/scripts/authenticate.scm (guix-authenticate): Adjust accordingly; remove the OpenSSL-style clauses. (read-hash-data): Remove. (sign-with-key): Replace 'port' with 'sha256' and adjust accordingly. (validate-signature): Export SIGNATURE to be a canonical sexp. * tests/guix-authenticate.sh: Adjust tests accordingly. Ludovic Courtès 2020-06-25daemon: Correctly handle EMLINK corner case when deduplicating....Suggested by Caleb Ristvedt <caleb.ristvedt@cune.org>. * nix/libstore/optimise-store.cc (LocalStore::optimisePath_): Save errno from 'rename' before calling 'unlink'. Ludovic Courtès 2020-06-24nix: Tweak .gitignore files....Remove .gitignore entries where they match source files that are tracked in Git. This is relevant to me at least, as some code searching tools use .gitignore files and will ignore matched files. Christopher Baines 2020-06-06daemon: Handle EXDEV when moving to trash directory....Fixes <https://bugs.gnu.org/41607>. Reported by Stephen Scheck <singularsyntax@gmail.com>. * nix/libstore/gc.cc (LocalStore::deletePathRecursive): When we try to move a dead directory into the trashDir using rename(2) but it returns an EXDEV error, just delete the directory instead. This can happen in a Docker container when the directory is not on the "top layer". Chris Marusich 2020-03-26daemon: Do not use clone on the Hurd....Checking for CLONE_NEWNS is only needed for using tha Linux specific clone(2), otherwise we can use fork(2). Using clone on the Hurd needs some work, only support LINUX for now. See https://lists.gnu.org/archive/html/guix-devel/2020-03/msg00190.html * nix/libstore/build.cc (CHROOT_ENABLED): Break into CHROOT_ENABLED and CLONE_ENABLED. (DerivationGoal::startBuilder): Replace CHROOT_ENABLED with __linux__. (DerivationGoal::runChild): Only define pivot_root() if SYS_pivot_root is defined. Co-authored-by: Jan Nieuwenhuizen <janneke@gnu.org> Manolis Ragkousis 2020-02-26daemon: Drop 'AT_STATX_DONT_SYNC' flag upon EINVAL....Fixes <https://bugs.gnu.org/39727>. Reported by Paul Garlick <pgarlick@tourbillion-technology.com>. * nix/libstore/gc.cc (LocalStore::removeUnusedLinks) [HAVE_STATX]: Add 'statx_flags' static variables. Clear 'AT_STATX_DONT_SYNC' flag from 'statx_flags' when 'statx' returns EINVAL. Ludovic Courtès 2020-01-12daemon: Fix the displayed GC estimated progress....* nix/libstore/gc.cc (LocalStore::deletePathRecursive): Fix computation of 'fraction'. Take 'bytesInvalidated' into account. Ludovic Courtès 2020-01-12daemon: Account for deleted store files when deduplication is on....Previously, a store item that is a regular file would not be accounted for in the 'bytesFreed' value computed by 'deletePath' because its 'st_nlink' count would always be >= 2. This commit fixes that. * nix/libutil/util.hh (deletePath): Add optional 'linkThreshold' argument. * nix/libutil/util.cc (_deletePath): Add 'linkThreshold' argument and honor it. Pass it down in recursive call. (deletePath): Add 'linkThreshold' and honor it. * nix/libstore/gc.cc (LocalStore::deleteGarbage): Pass 'linkThreshold' argument to 'deletePath', with a value of 2 when PATH is a store item and deduplication is on. Ludovic Courtès 2019-11-27daemon: GC remove-unused-links phase uses 'statx' when available....* config-daemon.ac: Check for 'statx'. * nix/libstore/gc.cc (LocalStore::removeUnusedLinks) [HAVE_STATX]: Use 'statx' instead of 'lstat'. Ludovic Courtès 2019-11-22daemon: GC displays how much it has collected....* nix/libstore/gc.cc (LocalStore::deletePathRecursive): Display the percentage reached relative to 'maxFreed', or the total amount of data deleted when 'maxFreed' is ULLONG_MAX. Ludovic Courtès 2019-11-13daemon: Don't include <linux/fs.h>....As of GNU libc 2.29, <sys/mount.h> declares all the constants and functions we need, so there's no use in including <linux/fs.h> anymore. This silences annoying warnings like this one: In file included from nix/libstore/local-store.cc:32:0: /gnu/store/…-linux-libre-headers-4.19.56/include/linux/fs.h:108:0: warning: "MS_RDONLY" redefined #define MS_RDONLY 1 /* Mount read-only */ In file included from nix/libstore/local-store.cc:28:0: /gnu/store/…-glibc-2.29/include/sys/mount.h:36:0: note: this is the location of the previous definition #define MS_RDONLY MS_RDONLY * config-daemon.ac: Remove check for <linux/fs.h>. * nix/libstore/build.cc: Remove conditional inclusion of <linux/fs.h>. * nix/libstore/local-store.cc: Remove "#if HAVE_LINUX_FS_H" and inclusion of <linux/fs.h>. Ludovic Courtès 2019-11-04daemon: Unregister build hook from the worker's children upon build failure....Fixes <https://bugs.gnu.org/38062>. This is a followup to ada9a19a2dca74feafcf24df1152abd685d4142f. * nix/libstore/build.cc (DerivationGoal::killChild): Add conditional call to 'worker.childTerminated' for 'hook->pid'. Ludovic Courtès 2019-10-16daemon: Make 'profiles/per-user' non-world-writable....Fixes <https://bugs.gnu.org/37744>. Reported at <https://www.openwall.com/lists/oss-security/2019/10/09/4>. Based on Nix commit 5a303093dcae1e5ce9212616ef18f2ca51020b0d by Eelco Dolstra <edolstra@gmail.com>. * nix/libstore/local-store.cc (LocalStore::LocalStore): Set 'perUserDir' to #o755 instead of #o1777. (LocalStore::createUser): New function. * nix/libstore/local-store.hh (LocalStore): Add it. * nix/libstore/store-api.hh (StoreAPI): Add it. * nix/nix-daemon/nix-daemon.cc (performOp): In 'wopSetOptions', add condition to handle "user-name" property and honor it. (processConnection): Add 'userId' parameter. Call 'store->createUser' when userId is not -1. * guix/profiles.scm (ensure-profile-directory): Note that this is now handled by the daemon. * guix/store.scm (current-user-name): New procedure. (set-build-options): Add #:user-name parameter and pass it to the daemon. * tests/guix-daemon.sh: Test the creation of 'profiles/per-user' when listening on a TCP socket. * tests/store.scm ("profiles/per-user exists and is not writable") ("profiles/per-user/$USER exists"): New tests. Ludovic Courtès 2019-10-16daemon: Remove traces of 'NIX_ROOT_FINDER'....This is a followup to 2e3e5d21988fc2cafb2a9eaf4b00976ea425629d. * build-aux/test-env.in: Remove mentions of 'NIX_ROOT_FINDER'. * nix/libstore/gc.cc (LocalStore::collectGarbage): Adjust comment accordingly. Ludovic Courtès