me
/
guix
Archived
1
0
Fork 0

home: symlink-manager: Remove 'empty-directory?' and avoid TOCTTOU race.

This removes three 'stat' syscalls.

* gnu/home/services/symlink-manager.scm (update-symlinks-script)[empty-directory?]:
Remove.
[cleanup-symlinks]: Replace use of 'file-exists?', 'file-is-directory?',
and 'empty-directory?' by a single 'rmdir' call.
master
Ludovic Courtès 2022-02-18 17:13:00 +01:00
parent e1b38046a6
commit a81bb1e4bb
No known key found for this signature in database
GPG Key ID: 090B11993D9AEBB5
1 changed files with 18 additions and 17 deletions

View File

@ -1,6 +1,7 @@
;;; GNU Guix --- Functional package management for GNU ;;; GNU Guix --- Functional package management for GNU
;;; Copyright © 2021 Andrew Tropin <andrew@trop.in> ;;; Copyright © 2021 Andrew Tropin <andrew@trop.in>
;;; Copyright © 2021 Xinglu Chen <public@yoctocell.xyz> ;;; Copyright © 2021 Xinglu Chen <public@yoctocell.xyz>
;;; Copyright © 2022 Ludovic Courtès <ludo@gnu.org>
;;; ;;;
;;; This file is part of GNU Guix. ;;; This file is part of GNU Guix.
;;; ;;;
@ -101,9 +102,6 @@ appear only after all nested items already listed."
(define (get-backup-path path) (define (get-backup-path path)
(string-append backup-dir "/." path)) (string-append backup-dir "/." path))
(define (empty-directory? dir)
(equal? (scandir dir) '("." "..")))
(define (symlink-to-store? path) (define (symlink-to-store? path)
(and (equal? (stat:type (lstat path)) 'symlink) (and (equal? (stat:type (lstat path)) 'symlink)
(store-file-name? (readlink path)))) (store-file-name? (readlink path))))
@ -127,20 +125,23 @@ appear only after all nested items already listed."
(('dir . ".") (('dir . ".")
(display (G_ "Cleanup finished.\n\n"))) (display (G_ "Cleanup finished.\n\n")))
(('dir . path) (('dir . directory)
(if (and (let ((directory (get-target-path directory)))
(file-exists? (get-target-path path)) (catch 'system-error
(file-is-directory? (get-target-path path)) (lambda ()
(empty-directory? (get-target-path path))) (rmdir directory)
(begin (format #t (G_ "Removed ~a.\n") directory))
(format #t (G_ "Removing ~a...") (lambda args
(get-target-path path)) (let ((errno (system-error-errno args)))
(rmdir (get-target-path path)) (cond ((= ENOTEMPTY errno)
(display (G_ " done\n")))
(format (format
#t #t
(G_ "Skipping ~a (not an empty directory)... done\n") (G_ "Skipping ~a (not an empty directory)...\n")
(get-target-path path)))) directory))
((= ENOTDIR errno)
#t)
(else
(apply throw args))))))))
(('file . path) (('file . path)
(when (file-exists? (get-target-path path)) (when (file-exists? (get-target-path path))