chiark / gitweb /
add ID_BUS to *_id programs
[elogind.git] / extras / cdsymlinks.sh
1 #! /bin/sh -e
2 #
3 # Map cdrom, cd-r, cdrw, dvd, dvdrw, dvdram, cdm, cdmrw, cdram
4 # to suitable devices.
5 # Prefers cd* for DVD-incapable and cdrom and dvd for read-only devices.
6 # First parameter is the kernel device name.
7 # Second parameter, if present, must be "-d" => output the full mapping.
8 #
9 # Usage:
10 # BUS="ide", KERNEL="hd[a-z]", PROGRAM="/etc/udev/cdsymlinks.sh %k", SYMLINK="%c{1} %c{2} %c{3} %c{4} %c{5} %c{6}"
11 # BUS="scsi", KERNEL="sr[0-9]*", PROGRAM="/etc/udev/cdsymlinks.sh %k", SYMLINK="%c{1} %c{2} %c{3} %c{4} %c{5} %c{6}"
12 # BUS="scsi", KERNEL="scd[0-9]*", PROGRAM="/etc/udev/cdsymlinks.sh %k", SYMLINK="%c{1} %c{2} %c{3} %c{4} %c{5} %c{6}"
13 # (this last one is "just in case")
14 #
15 # (c) 2004, 2005 Darren Salt <linux@youmustbejoking.demon.co.uk>
16 #
17 # Last modified: 2005-02-15
18
19 test -e /proc/sys/dev/cdrom/info || exit 0
20
21 # Defaults; it's better that you alter them in /etc/udev/cdsymlinks.conf
22 OUTPUT='CD CDRW DVD DVDRW DVDRAM'
23 NUMBERED_LINKS=1
24 LINK_ZERO=0
25
26 test -e /etc/udev/cdsymlinks.conf && . /etc/udev/cdsymlinks.conf
27
28 DEBUG=''
29 test "$2" = '-d' && DEBUG=1
30
31
32 # Array emulation. 'setArray FOO a b c' gives FOO=3 FOO_1=a FOO_2=b FOO_3=c
33 setArray () {
34   local _ARRAY=$1
35   local _INDEX=0
36   shift
37   while test $# -ne 0; do
38     eval ${_ARRAY}_$_INDEX="$1"
39     _INDEX=$(($_INDEX+1))
40     shift
41   done
42   eval $_ARRAY=$_INDEX
43 }
44
45 ix () { eval echo -n \$$1_$2; }
46 ixs () { eval $1_$2="$3"; }
47
48 # Args: variable, value
49 # Returns true if value is not in variable (a whitespace-separated list)
50 notin () {
51   test "$2" = '' && return 0
52   local i
53   for i in `eval echo '$'$1`; do
54     test "$i" != "$2" || return 1
55   done
56 }
57
58
59 # Scan /proc/sys/dev/cdrom/info for details on the present devices
60 setArray DEVICES `sed -re '/^drive name:/I!        d; s/.*://' /proc/sys/dev/cdrom/info`
61 setArray DVDRAMs `sed -re '/^Can write DVD-RAM:/I! d; s/.*://' /proc/sys/dev/cdrom/info`
62 setArray DVDRWs  `sed -re '/^Can write DVD-R:/I!   d; s/.*://' /proc/sys/dev/cdrom/info`
63 setArray DVDs    `sed -re '/^Can read DVD:/I!      d; s/.*://' /proc/sys/dev/cdrom/info`
64 setArray CDRWs   `sed -re '/^Can write CD-RW:/I!   d; s/.*://' /proc/sys/dev/cdrom/info`
65 setArray CDRs    `sed -re '/^Can write CD-R:/I!    d; s/.*://' /proc/sys/dev/cdrom/info`
66 setArray CDMRWs  `sed -re '/^Can write MRW:/I!     d; s/.*://' /proc/sys/dev/cdrom/info`
67 setArray CDMs    `sed -re '/^Can read MRW:/I!      d; s/.*://' /proc/sys/dev/cdrom/info`
68 setArray CDRAMs  `sed -re '/^Can write RAM:/I!     d; s/.*://' /proc/sys/dev/cdrom/info`
69
70 # How many devices do we have?
71 NumDevs=$(($DEVICES-1))
72 Count=''
73 i=-1
74 while test $i -ne $NumDevs; do
75   i=$(($i+1));
76   Count="$i${Count:+ }$Count";
77 done
78
79 # Fill in any missing capabilities information (assume not capable)
80 for i in $Count; do
81   test "`ix DVDRAMs $i`" != '' || ixs DVDRAMs $i 0
82   test "`ix DVDRWs $i`"  != '' || ixs DVDRWs $i 0
83   test "`ix DVDs $i`"    != '' || ixs DVDs $i 0
84   test "`ix CDRWs $i`"   != '' || ixs CDRWs $i 0
85   test "`ix CDRs $i`"    != '' || ixs CDRs $i 0
86   test "`ix CDMRWs $i`"  != '' || ixs CDMRWs $i 0
87   test "`ix CDMs $i`"    != '' || ixs CDMs $i 0
88   test "`ix CDRAMs $i`"  != '' || ixs CDRAMs $i 0
89 done
90
91 DVDRAM=''
92 DVDRW=''
93 DVD=''
94 CDRW=''
95 CDR=''
96 CDMRW=''
97 CDM=''
98 CDRAM=''
99 CD=''
100
101 # Calculate symlink->device mappings.
102 # We need to be careful about how we assign mappings because we want
103 # read-only devices to have /dev/cdrom and /dev/dvd.
104 # Hot-plugged CD/DVD devices may well cause this scheme some problems.
105 for i in $Count; do
106   test "`ix DVDRAMs $i`" = 1 && DVDRAM="$DVDRAM `ix DEVICES $i`"
107 done
108 for i in $Count; do
109   test "`ix DVDRWs $i`" = 1 &&  DVDRW="$DVDRW `ix DEVICES $i`"
110 done
111 for i in $Count; do
112   test "`ix DVDs $i`" = 1 &&    DVD="$DVD `ix DEVICES $i`"
113 done
114 for i in $Count; do
115   test "`ix CDRWs $i`" = 1 &&   CDRW="$CDRW `ix DEVICES $i`"
116 done
117 for i in $Count; do
118   test "`ix CDRs $i`" = 1 &&    CDR="$CDR `ix DEVICES $i`"
119 done
120 for i in $Count; do
121   test "`ix CDMRWs $i`" = 1 &&  CDMRW="$CDMRW `ix DEVICES $i`"
122 done
123 for i in $Count; do
124   test "`ix CDMs $i`" = 1 &&    CDM="$CDM `ix DEVICES $i`"
125 done
126 for i in $Count; do
127   test "`ix CDRAMs $i`" = 1 &&  CDRAM="$CDRAM `ix DEVICES $i`"
128 done
129 for i in $Count; do
130                                 CD="$CD `ix DEVICES $i`"
131 done
132
133 # Debug output
134 if test "$DEBUG" = 1; then
135   echo 'Devices:' `for i in $Count; do ix DEVICES $i; echo -n \ ; done`
136   echo 'CDROM  : (all)' $CD
137   echo 'CD-R   :' `for i in $Count; do ix CDRs    $i; echo -n \ ; done` $CDR
138   echo 'CDRW   :' `for i in $Count; do ix CDRWs   $i; echo -n \ ; done` $CDRW
139   echo 'DVD    :' `for i in $Count; do ix DVDs    $i; echo -n \ ; done` $DVD
140   echo 'DVDRW  :' `for i in $Count; do ix DVDRWs  $i; echo -n \ ; done` $DVDRW
141   echo 'DVDRAM :' `for i in $Count; do ix DVDRAMs $i; echo -n \ ; done` $DVDRAM
142   echo 'CDMRW  :' `for i in $Count; do ix CDMRWs  $i; echo -n \ ; done` $CDMRW
143   echo 'CDWMRW :' `for i in $Count; do ix CDMs    $i; echo -n \ ; done` $CDM
144   echo 'CDRAM  :' `for i in $Count; do ix CDRAMs  $i; echo -n \ ; done` $CDRAM
145 fi
146
147 # Prepare symlink names output
148 do_output () {
149   test "`eval echo '$'$3`" = '' && return
150   local i
151   local COUNT=$4
152   local DEVLS="`ls -dl \"/dev/$2\" \"/dev/$2\"[0-9]* 2>/dev/null`"
153   local PRESENT="`echo "$DEVLS" |
154     sed -re 's!^.* /dev/('$2'[[:digit:]]*) -> [^[:space:]]+$!\1!'`"
155   for i in `eval echo '$'$3`; do
156     # First, we look for existing symlinks to the target device.
157     local DEVPRESENT="`echo "$DEVLS" |
158       sed -re 's!^.* /dev/('$2'[[:digit:]]*) -> '$i'$!\1!; t X; d; :X'`"
159     if test "$DEVPRESENT" != ""; then
160       # Existing symlinks found - don't output a new one.
161       # If the target dev ($1) is the current dev ($i), we output their names.
162       test -z "$4" || return;
163       test "$1" = "$i" && echo " $DEVPRESENT" | sed -e 'N; $ s/\n/ /'
164     else
165       # If we found no existing symlinks for the target device...
166       # Find the next available (not present) symlink name.
167       # We always need to do this for reasons of output consistency: if a
168       # symlink is created by udev as a result of use of this program, we
169       # DON'T want different output!
170       until notin PRESENT "$2$COUNT"; do
171         test -z "$4" || return;
172         COUNT=$(($COUNT+1))
173       done
174       # If the target dev ($1) is the current dev ($i), we output its name.
175       if test $(($NUMBERED_LINKS)) -ne 0 || test -z "$COUNT"; then
176         test "$i" != "$1" || echo -n " $2$COUNT"
177       fi
178       # If the link isn't in our "existing links" list, add it and increment
179       # our counter.
180       if notin PRESENT "$2$COUNT"; then
181         test -z "$4" || return;
182         PRESENT="$PRESENT\n$2$COUNT"
183         COUNT=$(($COUNT+1))
184       fi
185     fi
186   done
187 }
188
189 output () {
190   do_output "$@"
191   test $(($LINK_ZERO)) -eq 0 || do_output "$@" 0
192 }
193
194 # And output it
195 notin OUTPUT CD     || echo -n "`output "$1" cdrom CD`"
196 notin OUTPUT CDR    || echo -n "`output "$1" cd-r CDR`"
197 notin OUTPUT CDRW   || echo -n "`output "$1" cdrw CDRW`"
198 notin OUTPUT DVD    || echo -n "`output "$1" dvd DVD`"
199 notin OUTPUT DVDRW  || echo -n "`output "$1" dvdrw DVDRW`"
200 notin OUTPUT DVDRAM || echo -n "`output "$1" dvdram DVDRAM`"
201 notin OUTPUT CDMRW  || echo -n "`output "$1" cdmrw CDM`"
202 notin OUTPUT CDWMRW || echo -n "`output "$1" cdwmrw CDMRW`"
203 notin OUTPUT CDRAM  || echo -n "`output "$1" cdram CDRAM`"
204 echo