keys.delete-keeper: Only do one pass through the file system.
[distorted-keys] / keys.delete-keeper
index 778f696..edcb718 100755 (executable)
@@ -45,8 +45,11 @@ if [ ! -d $keeper ]; then
 fi
 
 ## Make sure that there aren't recovery keys which would be orphaned by
-## deleting this keeper set.
-unset deps
+## deleting this keeper set.  Also, build a data structure of recovery keys
+## and their instances: `$recov' is a space-separated list of recovery key
+## labels, and for each such label R, `$ri_R' is a space-separated list of
+## its instances.
+unset deps; recov=" "
 if [ -d $KEYS/recov ]; then
   cd $KEYS/recov
 
@@ -55,11 +58,18 @@ if [ -d $KEYS/recov ]; then
     r=${r#./}; r=${r%/current}
     if ! expr >/dev/null "Q$r" : "Q$R_LABEL"; then continue; fi
 
+    ## Add the key to our list.
+    recov="$recov$r "
+
     ## Now work through the instances.
+    ii=""
     for ri in $r/*; do
       i=${ri##*/}
       case "$i" in *[!0-9]*) continue ;; esac
 
+      ## Add the instance to our list.
+      ii="$ii $i"
+
       ## For each recovery key, make sure that: either it doesn't depend on
       ## this keeper set, or it also depends on at least one other set.  If
       ## not, add it to the `deps' list.
@@ -70,6 +80,9 @@ if [ -d $KEYS/recov ]; then
       done
       case $this,$others in t,nil) deps="$deps $ri" ;; esac
     done
+
+    ## Record the list of instances.
+    eval "ri_$r=\$ii"
   done
 fi
 
@@ -83,33 +96,23 @@ case "${deps+t}" in
 esac
 
 ## Disentangle the dependent recovery keys from this keeper set.
-if [ -d $KEYS/recov ]; then
-  cd $KEYS/recov
-
-  ## Work through the recovery keys again.
-  for r in $(find . -type l -name current -print); do
-    r=${r#./}; r=${r%/current}
-    if ! expr >/dev/null "Q$r" : "Q$R_LABEL"; then continue; fi
-
-    ## Remove the keeper data from the key's instances.
-    for ri in $i/*; do
-      i=${ri##*/}
-      case "$i" in *[!0-9]*) continue ;; esac
-      rm -f $ri/$keeper.*
-    done
-
-    ## Work through the current keepers, and remove our keeper's name from
-    ## the list.
-    changep=nil
-    while read k rest; do
-      case $k in $keeper) changep=t ;; *) echo "$k $rest" ;; esac
-    done <$r/keepers >$r/keepers.new
-    case $changep in
-      t) mv $r/keepers.new $r/keepers ;;
-      nil) rm $r/keepers.new ;;
-    esac
-  done
-fi
+for r in $recov; do
+
+  ## Remove the keeper data from the key's instances.
+  eval "ii=\$ri_$r"
+  for i in $ii; do rm -f $r/$i/$keeper.*; done
+
+  ## Work through the current keepers, and remove our keeper's name from the
+  ## list.
+  changep=nil
+  while read k rest; do
+    case $k in $keeper) changep=t ;; *) echo "$k $rest" ;; esac
+  done <$r/keepers >$r/keepers.new
+  case $changep in
+    t) mv $r/keepers.new $r/keepers ;;
+    nil) rm $r/keepers.new ;;
+  esac
+done
 
 ## Finally, actually delete the keeper keys.
 cd $KEYS/keeper