aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorSean Whitton <spwhitton@spwhitton.name>2021-05-03 17:23:21 -0700
committerSean Whitton <spwhitton@spwhitton.name>2021-05-06 12:23:51 -0700
commit9e5770606c30cb8b763a572aba59fac42484898c (patch)
treeea0ebc36d84deadd2e80a08e99107f9819b32e67 /src
parent0dba628638acd2aa5d990cd1edd41ac689f808c8 (diff)
downloadconsfigurator-9e5770606c30cb8b763a572aba59fac42484898c.tar.gz
factor out FILE:UPDATE-UNIX-TABLE
Signed-off-by: Sean Whitton <spwhitton@spwhitton.name>
Diffstat (limited to 'src')
-rw-r--r--src/package.lisp3
-rw-r--r--src/property/file.lisp32
-rw-r--r--src/property/fstab.lisp29
3 files changed, 35 insertions, 29 deletions
diff --git a/src/package.lisp b/src/package.lisp
index de9eb85..edd90ca 100644
--- a/src/package.lisp
+++ b/src/package.lisp
@@ -260,7 +260,8 @@
#:regex-replaced-lines
#:directory-exists
#:symlinked
- #:is-copy-of))
+ #:is-copy-of
+ #:update-unix-table))
(defpackage :consfigurator.property.os
(:use #:cl #:consfigurator)
diff --git a/src/property/file.lisp b/src/property/file.lisp
index 71372d8..dd4ae89 100644
--- a/src/property/file.lisp
+++ b/src/property/file.lisp
@@ -409,3 +409,35 @@ removed, and semicolon comment chars will be replaced with '#'."
finally (return
(nconc new-lines
(sort accum #'string< :key #'cadr)))))))))))
+
+(defun update-unix-table (file source target entries &key (no-source "none"))
+ "Ensure that the UNIX table at FILE (e.g. /etc/fstab) contains each of
+ENTRIES, using a simple merge procedure: existing lines of the file with the
+same value for the TARGETth field are updated to match the corresponding
+members of ENTRIES, except that if the SOURCEth field of the existing entry is
+not NO-SOURCE and the corresponding member of ENTRIES is STRING= to either
+NO-SOURCE or \"PLACEHOLDER\", use the existing field value."
+ (let ((unknown (list no-source "PLACEHOLDER"))
+ (pending (make-hash-table :test #'equal)))
+ (flet ((fields (entry)
+ (remove "" (split-string entry) :test #'string=)))
+ (dolist (entry entries)
+ (setf (gethash (nth target (fields entry)) pending) entry))
+ (map-file-lines
+ file
+ (lambda (lines)
+ (loop for line in lines
+ for line-fields = (fields line)
+ for line-source = (nth source line-fields)
+ and line-target = (nth target line-fields)
+ for entry = (when-let* ((entry (gethash line-target pending))
+ (fields (fields entry)))
+ (and (member (nth source fields)
+ unknown :test #'string=)
+ (not (string= line-source no-source))
+ (setf (nth source fields) line-source)
+ (format nil "~{~A~^ ~}" fields)))
+ if entry
+ collect it into accum and do (remhash line-target pending)
+ else collect line into accum
+ finally (return (nconc accum (hash-table-values pending)))))))))
diff --git a/src/property/fstab.lisp b/src/property/fstab.lisp
index f89365d..7be61a4 100644
--- a/src/property/fstab.lisp
+++ b/src/property/fstab.lisp
@@ -64,12 +64,6 @@ Other properties might fill it in."
;;;; Properties
-(defun entry->source (entry)
- (car (split-string entry)))
-
-(defun entry->mountpoint (entry)
- (cadr (remove "" (split-string entry) :test #'string=)))
-
(defprop entries :posix (&rest entries)
"Ensure that /etc/fstab contains each of ENTRIES, using a simple merge
procedure: existing lines of the fstab with the same mount point as any of
@@ -81,28 +75,7 @@ This makes it easy to update mount options without having to specify the
partition or filesystem UUID in your consfig."
(:desc (format nil "fstab entries for ~{~A~^, ~}"
(mapcar #'entry->mountpoint entries)))
- (:apply
- (file:map-file-lines
- #P"/etc/fstab"
- (lambda (lines)
- (let ((pending (make-hash-table :test #'equal)))
- (dolist (entry entries)
- (setf (gethash (entry->mountpoint entry) pending) entry))
- (loop for line in lines
- for line-source = (entry->source line)
- and line-mountpoint = (entry->mountpoint line)
- for entry = (let ((entry (gethash line-mountpoint pending)))
- (if (and (member (entry->source entry)
- '("none" "PLACEHOLDER")
- :test #'string=)
- (not (string= line-source "none")))
- (format nil "~A ~{~A~^ ~}"
- line-source (cdr (split-string entry)))
- entry))
- if entry
- collect it into accum and do (remhash line-mountpoint pending)
- else collect line into accum
- finally (return (nconc accum (hash-table-values pending)))))))))
+ (:apply (file:update-unix-table #P"/etc/fstab" 0 1 entries)))
(defprop entries-for-volumes :posix ()
"Add or update entries in /etc/fstab for the host's volumes, as specified with