1#!/bin/sh
2#
3# $NetBSD: 02-wedgenames,v 1.8 2021/08/08 10:48:35 martin Exp $
4#
5# Try to maintain symlinks to wedge devices
6#
7
8export LC_ALL=C
9
10event="$1"
11shift
12
13wedgedir=/dev/wedges
14
15recurse()
16{
17          test -d "$1" &&
18              ls -1af "$1" | while read n; do
19                    case $n in
20                    .|..)     ;;
21                    *)
22                              echo "$1/$n"
23                              if [ -L "$1/$n" ]; then
24                                        : #nothing
25                              elif [ -d "$1/$n" ]; then
26                                        recurse "$1/$n"
27                              fi
28                              ;;
29                    esac
30              done
31}
32
33simple_readlink()
34{
35          local x
36
37          x=$(test -e "$1" && ls -ld "$1")
38          case $x in
39          *'-> '*) echo ${x#*-> };;
40          esac
41}
42
43#ordtable=$(
44#         for n1 in 0 1 2 3 4 5 6 7 8 9 a b c d e f; do
45#         for n2 in 0 1 2 3 4 5 6 7 8 9 a b c d e f; do
46#                   echo "\$'\x$n1$n2') x=$n1$n2;;"
47#         done
48#         done
49#)
50#
51#ord()
52#{
53#         local x
54#         eval "case \$1 in $ordtable esac"
55#         echo -n $x
56#}
57
58ord()
59{
60          printf %2.2x "'$1"
61}
62
63encode()
64{
65          local a b c
66
67          a=$1
68          b=
69          while [ -n "$a" ]; do
70                    c="${a%"${a#?}"}"
71                    a=${a#?}
72                    case $c in
73                    [][:alnum:]._:\;!^$\&~\(\)[{}=,+/-])
74                              ;;
75                    *)
76                              c=%%$(ord "$c")
77                              ;;
78                    esac
79                    b=${b}${c}
80          done
81          printf %s "$b"
82}
83
84remove_wedge() {
85          recurse "$wedgedir" | while read w; do
86                    t=$(simple_readlink "$w")
87                    if [ x"$t" = x"/dev/$1" ]; then
88                              rm -f "$w"
89                              basedir=${w%/*}
90                              rmdir -p "$basedir" 2>/dev/null
91                    fi
92          done
93}
94
95wedge_label() {
96          local l
97
98          # dkctl getwedgeinfo always outputs 2 "lines", the first
99          # contains the label (and may contain embedded \n chars)
100          # the second contains the size, offset, and type, and one
101          # trailing \n (stripped by the $()) - so we can safely
102          # extract the label by deleting from the final \n in the
103          # value getwedgeinfo prints to the end
104
105          l=$(dkctl "$1" getwedgeinfo)
106          l=${l%$'\n'*}
107          case "${l}" in
108          $1' at '*': '*)
109                    l=${l#*: }
110                    ;;
111          *)
112                    l=$1
113                    ;;
114          esac
115
116          # The trailing <END> is to ensure a trailing \n in the label
117          # is not deleted by a command substitution which invokes us.
118          # That will be rmeoved by the caller.
119          printf %s "${l}<END>"
120}
121
122add_wedge() {
123          local l n
124
125          l=$(wedge_label "$1")
126          l=${l%'<END>'}
127          case "$l" in */) l="${l}Wedge";; esac
128
129          n=$(encode "${l}")
130
131          (
132                    umask 022
133
134                    test -d "$wedgedir" || mkdir -m 755 "$wedgedir"
135                    basedir="$wedgedir/$n"
136                    basedir=${basedir%/*}
137                    test -d "$basedir" || mkdir -p -m 755 "$basedir"
138                    if oldlink=$(simple_readlink "$wedgedir/$n"); then
139                              if [ x"$oldlink" != x"/dev/$1" ]; then
140                                        rm -f "$wedgedir/$n"
141                                        ln -s "/dev/$1" "$wedgedir/$n"
142                              fi
143                    else
144                              ln -s "/dev/$1" "$wedgedir/$n"
145                    fi
146          )
147}
148
149for device do
150          case $device in
151          dk*)
152                    case $event in
153                    device-attach)
154                              remove_wedge "$device"
155                              add_wedge "$device"
156                              ;;
157                    device-detach)
158                              remove_wedge "$device"
159                              ;;
160                    esac
161                    ;;
162          esac
163done
164