#!/bin/sh
# http://www.berklix.com/~jhs//bin/.sh/new_cd	By jhs@@@berklix.com
#	Symbolic linked: new_cdi -> new_cd.
# echo "Should add code for sighup handler to unmount & deconfig"
# Run this as uid=root.
# Syntax:
#	new_cd  [cd_mount_dir  [output_dir]]
#	new_cdi [cd_image_file [output_dir]]
# Later I could develop a variant to read eg \
#	FreeBSD-9.2-RELEASE-i386-memstick.img

if [ "`basename $0`" = "new_cd" ]; then
	source_default="/cdrom"
	echo -n "Analysing pre-mounted CDROM or DVD directory,"
	echo	" default: $source_default"
	source_name="input_directory"
else	# }{	"new_cdi"	# From a CDROM or DVD image file on hard disk.
	source_default="cd.iso"
	echo "Will analyse a CDROM image."
	source_name="input_image"
fi	# }

target_default="/pub/cd/new"
cwd=`pwd`
if [ "$#" = "0" ]; then
	echo "Syntax: `basename $0` [$source_name [output_directory]]"
	echo "	Will continue with these defaults:"
	echo "	Default $source_name:		$source_default"
	echo "	Default output_directory:	$target_default"
fi	# }

if [ "x.$1" = "x." ]; then
	source_path=$source_default
	echo "Default $source_name: $source_path"
else	# }{
	source_path="$1"
	if [ "`basename $0`" = "new_cd" ]; then
		# EG /host/bla/cdrom or /host/wind/usr1/cd/7/R/cdrom/disc1
	else	# }{	"new_cdi"
		# EG /public/freebsd/ref/3.3-RELEASE/cd/vsl/1.iso
	fi	# }
fi	# }

echo "Input: $source_path"	# Ensure it exists.
if [ "`basename $0`" = "new_cd" ]; then
	(cd $source_path || exit 1 ; ls -la )
else	# }{	"new_cdi"
	ls -l $source_path || exit 1
fi	# }

if [ "x.$2" = "x." ]; then
	target=$target_default
else	# }{
	target=$2
	# EG /pub/FreeBSD/cd/7.2-RELEASE/i386/1
fi	# }

rel=`uname -r |sed 's/-RELEASE//' |awk -F . '{printf "%s\n",$1}'`

# No rm -f $target/*	as killer if $target does not evaluate!
if [ ! -d $target ]; then
	echo "mkdir target: $target"
	mkdir $target
fi
echo "Output Directory: $target"
(cd $target || exit 1) # ensure accesible.

# Convert possible relative $target to absolute
cd $cwd ; cd $target ; target=`pwd`

cd $cwd
if [ "`basename $0`" = "new_cd" ]; then
	echo "Changing directory to $source_path"
	cd $source_path || exit 1
else	# }{	"new_cdi"
	echo "Mounting $source_path on /mnt"
	if [ "$rel" = "4" ]; then
		echo "WARNING "
		echo "vnconfig has no syntax to support automatic allocation of unit"
		echo "number. If you want to force this script to continue, comment out"
		echo "the next exit.  Realise that would be dangerous."
		exit
		unit="0" 
		# Assign unit zero & hope nothing else is using it.
		echo "30 seconds to hit Control C"
		sleep 30
		doit="vnconfig -v /dev/vn${unit}c $source_path"
		#	-v is needed to get the unit number.
		#	No command to show Nodes before allocate"
		echo "Allocate command: $doit"
		rslt=`$doit`
		echo "Debug rslt: ${rslt}"
		#	Typical output:
		#		"/dev/vn0c: 0 bytes on B130-E150.iso"
		#	No command to show Nodes after allocate"
		unit=`echo $rslt | sed -e sx/dev/vnxx | sed -e 'sxc: 0 bytes on 'xx | sed -e sx${source_path}xx `
		echo "Node unit ${unit}"
		#	No command to show Node specific"
		doit="mount -t cd9660 -r /dev/vn${unit}c /mnt"
		echo "Mount command: $doit" ; $doit
	else	# }{ $rel = 5-12
		echo -n "Nodes before allocate: "
		# ---
		echo "`mdconfig -l`."
		# 12.2-RELEASE fails with:
		#	mdconfig: DIOCGMEDIASIZE(/dev/devstat): 
		#	  Operation not supported by device
		# ---
		# But this next 12.2-RELEASE succeeds:
		doit="mdconfig -a -o readonly -t vnode -f $source_path"
		echo "Allocate command: $doit"
		rslt=`$doit`
		echo "Nodes after allocate: `mdconfig -l`."
		unit=`echo $rslt|sed -e s/md//`
		echo "Node unit ${unit}"
		echo "Node info: `mdconfig -l -u ${unit}`"
		doit="mount -t cd9660 -r /dev/md${unit} /mnt"
		echo "Mount command: $doit" ; $doit
	fi	# }
	echo "Changing directory to /mnt"
	cd /mnt || exit 1
fi	# }

echo "ls -la $target"
ls -la $target

# Do du first, in case we're in a rush to know what's where.
echo "Creating $target/du"
du -k								> $target/du

# Microsoft CDs often have space in filenames.
# Even Joerg Braun''s Live NetBSD CD has names with spaces, EG
#	home/user/.kde/share/kde/applnk/Graphics/dia 0.8.desktop
# so I use "find -print0" and "xargs -0"
# sort0="| sort"	# fails with : "ls: <NEWLINE>: No such file or directory"
sort0=" "

echo "Creating $target/dirs"
find . -type d -print | sort					> $target/dirs

echo "Creating $target/files"
find . -type f -print | sort					> $target/files

echo "Creating $target/ls-l"
find . -type f -print0 $sort0 | xargs -0 ls -l			> $target/ls-l

echo "Creating $target/syms"
# There are no symbolic links on MS far as I know, but have `short cuts'.
find . -type l -print0 $sort0 | xargs -0 ls -l			> $target/syms

echo "Creating $target/devs"
# There are no block or char devices or sockets on MS far as I know,
find . \( -type b -o -type c -o -type p -o -type s \) -print0 $sort0 | \
	xargs -0 ls -l						> $target/devs

echo "Creating $target/md5"
# Last, time consuming, especially retries on media errors
## find . -type f -print0 $sort0 | xargs -0 md5			> $target/md5
# If there are read errors, md5 says Invalid argument, dd shows errors too,
# but cp $1 /dev/null does Not show errors !

cd $target ; gzip -f *	# -f added in case this gets called twice by
			# the Makefile that builds CDs.

# JJLATER add correct syntax for if euid=0
	echo "You might want to chown these:"
	ls -la
	# fi

# Note if you run this script again some months later, the content of the
#	ls-l file will not compare equal, as of course the ls command displays
#	dates differently depending upon the time differential between
#	file date & current date.

if [ "`basename $0`" = "new_cd" ]; then
	# No need to unmount as we never mounted it.
else	# }{	"new_cdi"
	cd /
	umount /mnt
	if [ "$rel" = "4" ]; then
		doit="vnconfig -u /dev/vn${unit}c"
		echo "$doit" ; $doit
	else	# }{ 5 or 6
		echo "Nodes before de-allocation: `mdconfig -l`."
		doit="mdconfig -d -u ${unit}"
		echo "De-allocation command: $doit" 
		$doit
		echo "Nodes after de-allocation: `mdconfig -l`."
	fi	# }
fi	# }
