5 # The contents of this file are subject to the terms of the
6 # Common Development and Distribution License (the "License").
7 # You may not use this file except in compliance with the License.
9 # You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 # or http://www.opensolaris.org/os/licensing.
11 # See the License for the specific language governing permissions
12 # and limitations under the License.
14 # When distributing Covered Code, include this CDDL HEADER in each
15 # file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 # If applicable, add the following below this CDDL HEADER, with the
17 # fields enclosed by brackets "[]" replaced with your own identifying
18 # information: Portions Copyright [yyyy] [name of copyright owner]
22 # Copyright 2010 Sun Microsystems, Inc. All rights reserved.
23 # Use is subject to license terms.
26 # This is a clean script for removable disks
28 # Following is the syntax for calling the script:
29 # scriptname [-s|-f|-i|-I] devicename [-A|-D] username zonename zonepath
31 # -s for standard cleanup by a user
32 # -f for forced cleanup by an administrator
33 # -i for boot-time initialization (when the system is booted with -r)
34 # -I to suppress error/warning messages; the script is run in the '-i'
37 # $1: devicename - device to be allocated/deallocated, e.g., sr0
39 # $2: -A if cleanup is for allocation, or -D if cleanup is for deallocation.
41 # $3: username - run the script as this user, rather than as the caller.
43 # $4: zonename - zone in which device to be allocated/deallocated
45 # $5: zonepath - root path of zonename
47 # A clean script for a removable media device should prompt the user to
48 # insert correctly labeled media at allocation time, and ensure that the
49 # media is ejected at deallocation time.
51 # Unless the clean script is being called for boot-time
52 # initialization, it may communicate with the user via stdin and
53 # stdout. To communicate with the user via CDE dialogs, create a
54 # script or link with the same name, but with ".windowing" appended.
55 # For example, if the clean script specified in device_allocate is
56 # /etc/security/xyz_clean, that script must use stdin/stdout. If a
57 # script named /etc/security/xyz_clean.windowing exists, it must use
58 # dialogs. To present dialogs to the user, the dtksh script
59 # /etc/security/lib/wdwmsg may be used.
61 # This particular script, disk_clean, will work using stdin/stdout, or
62 # using dialogs. A symbolic link disk_clean.windowing points to
66 # ####################################################
67 # ################ Local Functions #################
68 # ####################################################
71 # Set up for windowing and non-windowing messages
75 if [ `basename $0` != `basename $0 .windowing` ]; then
77 case $VOLUME_MEDIATYPE in
78 cdrom
) TITLE
="CD-ROM";;
79 rmdisk
) TITLE
="Removable Disk";;
80 floppy
) TITLE
="Floppy";;
84 if [ "$MODE" = "allocate" ]; then
85 TITLE
="$TITLE Allocation"
87 TITLE
="$TITLE Deallocation"
95 # Display a message for the user. For windowing, user must press OK button
96 # to continue. For non-windowing, no response is required.
99 if [ "$WINDOWING" = "yes" ]; then
100 $WDWMSG "$*" "$TITLE" OK
101 elif [ "$silent" != "y" ]; then
102 echo "$*" > /dev
/${MSGDEV}
107 if [ "$WINDOWING" = "yes" ]; then
108 $WDWMSG "$*" "$TITLE" READY
110 form
=`gettext "Media in %s is ready. Please store safely."`
111 printf "${form}\n" $PROG $DEVICE > /dev
/{MSGDEV
}
116 if [ "$WINDOWING" = "yes" ]; then
117 $WDWMSG "$*" "$TITLE" ERROR
119 form
=`gettext "%s: Error cleaning up device %s."`
120 printf "${form}\n" $PROG $DEVICE > /dev
/${MSGDEV}
125 # Ask the user an OK/Cancel question. Return 0 for OK, 1 for Cancel.
128 if [ "$WINDOWING" = "yes" ]; then
129 $WDWMSG "$*" "$TITLE" OK Cancel
130 elif [ "$silent" != "y" ]; then
131 get_reply
"$* (y to continue, n to cancel) \c" y n
136 # Ask the user an Yes/No question. Return 0 for Yes, 1 for No
139 if [ "$WINDOWING" = "yes" ]; then
140 $WDWMSG "$*" "$TITLE" Yes No
141 elif [ "$silent" != "y" ]; then
142 get_reply
"$* (y/n) \c" y n
147 # Display an error message, put the device in the error state, and exit.
150 if [ "$silent" != "y" ]; then
152 "\n\nDevice has been placed in allocation error state." \
153 "\nPlease inform system administrator."
159 # get_reply prompt choice ...
165 echo $prompt > /dev
/tty
170 if [ "$choice" = "$reply" ]
181 # Find the first disk slice containing a file system
185 # The list of files in device_maps(4) is in an unspecified order.
186 # To speed up the fstyp(1M) scanning below in most cases, perform
187 # the search for filesystems as follows:
188 # 1) Select only block device files of the form "/dev/dsk/*".
189 # 2) Sort the list of files in an order more likely to yield
190 # matches: first the fdisk(1M) partitions ("/dev/dsk/cNtNdNpN")
191 # then the format(1M) slices ("/dev/dsk/cNtNdNsN"), in ascending
192 # numeric order within each group.
193 DEVall
="`echo $FILES | \
194 /usr/bin/tr ' ' '\n' | \
195 /usr/bin/sed '/^\/dev\/dsk\//!d; s/\([sp]\)\([0-9]*\)$/ \1 \2/;' | \
196 /usr/bin/sort -t ' ' -k 2,2d -k 3,3n | \
198 for DEVn
in $DEVall ; do
199 fstyp_output
="`/usr/sbin/fstyp -a $DEVn 2>&1`"
202 gen_volume_label
="`echo "$fstyp_output" | \
203 sed -n '/^gen_volume_label: .\(.*\).$/s//\1/p'`"
204 if [ "$gen_volume_label" != "" ]; then
205 FSNAME
="`echo $gen_volume_label | \
206 /usr/xpg4/bin/tr '[:upper:] ' '[:lower:]_'`"
208 # For consistency, hsfs filesystems detected at
209 # /dev/dsk/*p0 are mounted as /dev/dsk/*s2
210 FSTYPE
=`echo "$fstyp_output" | /usr/bin/head -1`
211 if [ "$FSTYPE" = hsfs
-a \
212 `/usr/bin/expr $FSPATH : '.*p0'` -gt 0 ]; then
213 FSPATH
=`echo $FSPATH | /usr/bin/sed 's/p0$/s2/'`
221 # Find all mountpoints in use for a set of device special files.
222 # Usage: findmounts devpath ...
226 nawk
-f - -v vold_root
="$VOLD_ROOT" -v devs
="$*" /etc
/mnttab
<<\
229 split(devs
, devlist
, " ");
230 for (devN
in devlist
) {
232 realdevlist
[dev
] = 1;
233 sub
(/.
*\
//, "", dev
);
234 sub
(/s
[0-9]$
/, "", dev
);
235 if (vold_root
!= "") {
236 vold_dir
[vold_root
"/dev/dsk/" dev
] = 1;
237 vold_dir
[vold_root
"/dev/rdsk/" dev
] = 1;
243 for (dev
in realdevlist
) {
249 for (dev
in vold_dir
) {
250 if (substr
($1, 1, length
(dev
)) == dev
) {
261 # Ask the user to make sure the disk is properly labeled.
262 # Ask if the disk should be mounted.
266 if [ $VOLUME_MEDIATYPE = floppy
]; then
267 # Determine if media is in drive
268 eject_msg
="`eject -q $DEVFILE 2>&1`"
270 case $eject_status in
271 1) # Media is not in drive
272 okcancel
"Insert disk in $DEVICE."
278 "Error checking for media in drive.";;
281 okcancel
"Insert disk in $DEVICE."
287 yesno
"Do you want $DEVICE mounted?"
292 if [ $VOLUME_MEDIATYPE = cdrom
-o $VOLUME_MEDIATYPE = rmdisk
]; then
293 # Get the device path and volume name of a partition
295 if [ "$FSPATH" != "" ]; then
298 if [ "$FSNAME" != "" ]; then
304 # Give ourself write permission on device file so file system gets
305 # mounted read/write if possible.
306 # rmmount only cares about permissions not user...
307 chown
$VOLUME_USER $VOLUME_PATH
308 chmod 700 $VOLUME_PATH
310 # Do the actual mount. VOLUME_* environment variables are inputs to
312 rmmount_msg
="`/usr/sbin/rmmount 2>&1`"
314 if [ $rmmount_status -eq 0 ]; then
315 EXIT_STATUS
=$CLEAN_MOUNT
316 elif [ $rmmount_status -gt 0 -a $VOLUME_MEDIATYPE != cdrom
]; then
317 # Try again in readonly mode. cdrom is always mounted ro, so
318 # no need to try again.
319 echo "Read-write mount of $DEVICE failed. Mounting read-only."
320 VOLUME_ACTION
=remount
; export VOLUME_ACTION
321 VOLUME_MOUNT_MODE
=ro
; export VOLUME_MOUNT_MODE
323 if [ $?
-eq 0 ]; then
324 EXIT_STATUS
=$CLEAN_MOUNT
328 # Set permissions on directory used by vold, sdtvolcheck, etc.
329 if [ -d /tmp
/.removable
]; then
330 chown root
/tmp
/.removable
331 chmod 777 /tmp
/.removable
338 if [ $VOLUME_MEDIATYPE = cdrom
-o $VOLUME_MEDIATYPE = rmdisk
]; then
339 if [ -h /$VOLUME_MEDIATYPE/$DEVICE ]; then
340 # Get the device path and volume name of a partition
341 VOLUME_PATH
=`ls -l /$VOLUME_MEDIATYPE/$DEVICE|\
343 VOLUME_DEVICE
=`mount -p|grep $VOLUME_PATH|\
348 if [ -d "$VOLUME_PATH" ]; then
350 # Do the actual unmount.
351 # VOLUME_* environment variables are inputs to rmmount.
352 rmmount_msg
="`/usr/sbin/rmmount 2>&1`"
355 # Remove symbolic links to mount point
356 for name
in /$VOLUME_MEDIATYPE/*; do
357 if [ -h $name ]; then
358 target
=`ls -l $name | awk '{ print $NF; }'`
359 target_dir
=`dirname $target`
360 target_device
=`echo $target_dir | \
361 sed -e 's/^.*-\(.*\)$/\1/'`
362 if [ "$target_device" = "$DEVICE" ]; then
371 case $rmmount_status in
373 error_exit
$DEVICE "Error unmounting $DEVICE" "$rmmount_msg";;
376 if [ "$FLAG" = "f" ] ; then
377 eject_msg
="`eject -f $DEVICE 2>&1`"
379 eject_msg
="`eject $DEVICE 2>&1`"
382 case $eject_status in
383 0|
1|
4) # Media has been ejected
384 case $VOLUME_MEDIATYPE in
386 msg
"Please remove the disk from $DEVICE.";;
388 3) # Media didn't eject
389 msg
$DEVICE "Error ejecting disk from $DEVICE" \
400 eject_msg
="`eject -f $DEVICE 2>&1`"
403 case $eject_status in
404 0) # Media has been ejected
405 if [ "$silent" != "y" ]; then
409 1) # Media not ejected
410 if [ "$silent" != "y" ]; then
415 if [ "$silent" != "y" ]; then
418 msg
$DEVICE "Error ejecting disk from $DEVICE" \
425 # ####################################################
426 # ################ Begin main program ################
427 # ####################################################
429 trap "" INT TERM QUIT TSTP ABRT
431 PATH
="/usr/bin:/usr/sbin"
434 WDWMSG
="/etc/security/lib/wdwmsg"
436 USAGE
="Usage: disk_clean [-s|-f|-i|-I] devicename -[A|D] [username] [zonename] [zonepath]"
442 # Parse the command line arguments
462 shift `expr $OPTIND - 1`
466 if [ "$2" = "-A" ]; then
468 elif [ "$2" = "-D" ]; then
472 #get the device_maps information
473 MAP
=`/usr/sbin/list_devices -s -l $DEVICE`
474 FILES
=`echo $MAP | cut -f4 -d:` # e.g., /dev/dsk/c0t6d0s0 /dev/dsk/c0t6d0s1 ...
475 DEVFILE
=`echo $FILES | cut -f1 -d" "` # e.g., "/dev/dsk/c0t6d0s0"
477 # Set VOLUME_ variables that are inputs to rmmount
479 VOLUME_DEVICE
=`echo $FILES | cut -f2 -d" "` # e.g., "/dev/dsk/c0t6d0s1"
480 MEDIATYPE
=`echo $MAP | cut -f3 -d: | cut -f2 -d" "`
481 # e.g., "cdrom" or "floppy"
482 if [ "$MEDIATYPE" = "sr" ]; then
483 VOLUME_MEDIATYPE
="cdrom"
484 elif [ "$MEDIATYPE" = "fd" ]; then
485 VOLUME_MEDIATYPE
="floppy"
486 elif [ "$MEDIATYPE" = "rmdisk" ]; then
487 VOLUME_MEDIATYPE
="rmdisk"
490 VOLUME_PATH
=$DEVFILE # e.g., "/dev/dsk/c0t6d0s0"
491 if [ "$MACH" = "i386" ] && [ "$MEDIATYPE" = "rmdisk" ]; then
492 VOLUME_PATH
=`echo $DEVFILE | sed -e 's/s0/p0/'`
495 SYMDEV
=`echo $DEVICE | sed -e 's/_//'` # e.g., "cdrom" or "floppy"
496 SYMNUM
=`echo $SYMDEV | sed -e 's/[a-z]*//g'`
497 SYMDEV
=`echo $SYMDEV | sed -e 's/[0-9]*//g'`
498 if [ "$SYMDEV" = "sr" ]; then
499 VOLUME_SYMDEV
="cdrom"$SYMNUM
500 elif [ "$SYMDEV" = "fd" ]; then
501 VOLUME_SYMDEV
="floppy"$SYMNUM
502 elif [ "$SYMDEV" = "rmdisk" ]; then
503 VOLUME_SYMDEV
="rmdisk"$SYMNUM
505 VOLUME_SYMDEV
=$SYMDEV$SYMNUM
512 if [ "$MODE" = "allocate" ]; then
513 if [ -n "$3" ]; then # e.g., "joeuser"
516 VOLUME_USER
=`/usr/xpg4/bin/id -u -nr`
519 # If there's a directory for the device under /<mediatype>, get the
520 # user name from there, to use in cleaning up that directory. Otherwise,
521 # the user name isn't actually used in deallocation.
522 if [ -d ${VOLUME_ZONE_PATH}/${VOLUME_MEDIATYPE}/*-${DEVICE} ]; then
523 VOLUME_USER
=`ls -ld ${VOLUME_ZONE_PATH}/${VOLUME_MEDIATYPE}/*-${DEVICE} | awk '/^d/{print $3}'`
528 VOLUME_USER
=`/usr/xpg4/bin/id -u -nr`
533 VOLUME_NAME
=unnamed_
${VOLUME_MEDIATYPE}
534 # e.g., "joeuser-cdrom0/unnamed_cdrom"
536 if [ "$VOLUME_MEDIATYPE" = "rmdisk" ]; then
542 export VOLUME_ACTION VOLUME_DEVICE VOLUME_MEDIATYPE VOLUME_NAME VOLUME_PCFS_ID
543 export VOLUME_PATH VOLUME_SYMDEV VOLUME_USER VOLUME_ZONE_NAME VOLUME_ZONE_PATH
545 USERDIR
=${VOLUME_USER}-${DEVICE} # e.g., "joeusr-cdrom0"
549 if [ "$MODE" = "allocate" ]; then
553 if [ "$FLAG" = "i" ] ; then