;;; GNU Guix --- Functional package management for GNU ;;; Copyright © 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019 Ludovic Courtès ;;; Copyright © 2013 Andreas Enge ;;; Copyright © 2013 Nikita Karetnikov ;;; Copyright © 2015, 2018 Mark H Weaver ;;; Copyright © 2018 Arun Isaac ;;; Copyright © 2018, 2019 Ricardo Wurmus ;;; ;;; 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 (guix build service-utils) #:use-module (ice-9 match) #:use-module (guix build utils) #:export (mkdir-p/perms)) ;; Based upon mkdir-p from (guix build utils) (define (verify-not-symbolic dir) "Verify DIR or its ancestors aren't symbolic links." (define absolute? (string-prefix? "/" dir)) (define not-slash (char-set-complement (char-set #\/))) (define (verify-component path) (when (eq? 'symlink (stat:type (lstat path))) (throw 'XXX-TODO-does-someone-have-an-idea? path))) (let loop ((components (string-tokenize dir not-slash)) (root (if absolute? "" "."))) (match components ((head tail ...) (let ((path (string-append root "/" head))) (catch 'system-error (lambda () (verify-component path) (loop tail path)) (lambda args (if (= ENOENT (system-error-errno args)) #t (apply throw args)))))) (() #t)))) (define (mkdir-p/perms directory owner bits) "Create the directory DIRECTORY and all its ancestors. Verify no component of DIRECTORY is a symbolic link. Warning: this is currently suspect to a TOCTOU race!" (verify-not-symbolic directory) (mkdir-p directory) (chown directory (passwd:uid owner) (passwd:gid owner)) (chmod directory bits))