summaryrefslogtreecommitdiff
path: root/gnu/system/shadow.scm
diff options
context:
space:
mode:
authorLeo Prikler <leo.prikler@student.tugraz.at>2021-01-01 12:10:01 +0100
committerLeo Prikler <leo.prikler@student.tugraz.at>2021-01-11 16:03:47 +0100
commita3002104a84c60556b6616d100cb98019e48759d (patch)
tree76dc17a0d054a66c70a300a97bf5fd92687ff20a /gnu/system/shadow.scm
parent8152fd1af551f4bcec2ef59243264c10ff48daea (diff)
system: Assert, that user and group names are unique.
*gnu/system/shadow.scm (find-duplicates): New variable. (assert-unique-account-names, assert-unique-group-names): New variables. (account-activation): Use them here.
Diffstat (limited to 'gnu/system/shadow.scm')
-rw-r--r--gnu/system/shadow.scm44
1 files changed, 44 insertions, 0 deletions
diff --git a/gnu/system/shadow.scm b/gnu/system/shadow.scm
index a69339bc074..183b2cd387e 100644
--- a/gnu/system/shadow.scm
+++ b/gnu/system/shadow.scm
@@ -20,6 +20,7 @@
20;;; along with GNU Guix. If not, see <http://www.gnu.org/licenses/>. 20;;; along with GNU Guix. If not, see <http://www.gnu.org/licenses/>.
21 21
22(define-module (gnu system shadow) 22(define-module (gnu system shadow)
23 #:use-module ((guix diagnostics) #:select (formatted-message))
23 #:use-module (guix records) 24 #:use-module (guix records)
24 #:use-module (guix gexp) 25 #:use-module (guix gexp)
25 #:use-module (guix store) 26 #:use-module (guix store)
@@ -34,6 +35,7 @@
34 #:use-module ((gnu packages admin) 35 #:use-module ((gnu packages admin)
35 #:select (shadow)) 36 #:select (shadow))
36 #:use-module (gnu packages bash) 37 #:use-module (gnu packages bash)
38 #:use-module (ice-9 match)
37 #:use-module (srfi srfi-1) 39 #:use-module (srfi srfi-1)
38 #:use-module (srfi srfi-26) 40 #:use-module (srfi srfi-26)
39 #:use-module (srfi srfi-34) 41 #:use-module (srfi srfi-34)
@@ -222,6 +224,46 @@ for a colorful Guile experience.\\n\\n\"))))\n"))
222 (rename-file ".nanorc" ".config/nano/nanorc")) 224 (rename-file ".nanorc" ".config/nano/nanorc"))
223 #t)))) 225 #t))))
224 226
227(define (find-duplicates list)
228 "Find duplicate entries in @var{list}.
229Two entries are considered duplicates, if they are @code{equal?} to each other.
230This implementation is made asymptotically faster than @code{delete-duplicates}
231through the internal use of hash tables."
232 (let loop ((list list)
233 ;; We actually modify table in-place, but still allocate it here
234 ;; so that we only need one level of indentation.
235 (table (make-hash-table)))
236 (match list
237 (()
238 (hash-fold (lambda (key value seed)
239 (if (> value 1)
240 (cons key seed)
241 seed))
242 '()
243 table))
244 ((first . rest)
245 (hash-set! table first
246 (1+ (hash-ref table first 0)))
247 (loop rest table)))))
248
249(define (assert-unique-account-names users)
250 (match (find-duplicates (map user-account-name users))
251 (() *unspecified*)
252 (duplicates
253 (raise
254 (formatted-message
255 (G_ "the following accounts appear more than once:~{ ~a~}")
256 duplicates)))))
257
258(define (assert-unique-group-names groups)
259 (match (find-duplicates (map user-group-name groups))
260 (() *unspecified*)
261 (duplicates
262 (raise
263 (formatted-message
264 (G_ "the following groups appear more than once:~{ ~a~}")
265 duplicates)))))
266
225(define (assert-valid-users/groups users groups) 267(define (assert-valid-users/groups users groups)
226 "Raise an error if USERS refer to groups not listed in GROUPS." 268 "Raise an error if USERS refer to groups not listed in GROUPS."
227 (let ((groups (list->set (map user-group-name groups)))) 269 (let ((groups (list->set (map user-group-name groups))))
@@ -292,6 +334,8 @@ group."
292 (define group-specs 334 (define group-specs
293 (map user-group->gexp groups)) 335 (map user-group->gexp groups))
294 336
337 (assert-unique-account-names accounts)
338 (assert-unique-group-names groups)
295 (assert-valid-users/groups accounts groups) 339 (assert-valid-users/groups accounts groups)
296 340
297 ;; Add users and user groups. 341 ;; Add users and user groups.