[603] in Info-AFS_Redistribution

home help back first fref pref prev next nref lref last post

pckg

daemon@ATHENA.MIT.EDU (Daniel Edward Lovinger)
Wed Feb 12 18:16:44 1992

Date: Wed, 12 Feb 1992 16:52:28 -0500 (EST)
From: Daniel Edward Lovinger <dl2n+@andrew.cmu.edu>
To: Info-AFS@transarc.com

	Pckg is a perl script that generates a package description for
a tree of files - most notably an OS tree (what we use it for here).
It'll also do the right thing if you point it at /dev or similar.

	Some may remember a while back I posted a pair of scripts
pckg-tree and dev-tree. Please kill them. I wrote 'em before I learned
Perl and it shows ... pckg does everything they did and more. In
particular:

	* will resolve symbolic links inside of a tree properly (it
	must be able to figure out the OS tree root to be useful - see
	the comments)

	* will resolve hard links in the OS tree into symbolic links
	for package

	* gets major/minor right on systems that use a longword for 
	devices (like AIX)

	* uses cached stat information (_)

	* is waaay faster (I calculated a 30x speedup)

	Reference: it did our entire SunOS 4.1.1a tree from AFS w/
nothing particular in the cache (~150 megs) in 21 minutes flat on a
Sparc IPX. Fast.

	Let me know if you find it useful ...

      Dan Lovinger     Computing & Communications      Carnegie Mellon U.
    Internet: dl2n+@andrew.cmu.edu   Bitnet: dl2n+%andrew.cmu.edu@carnegie
   "... and in the stillness, they heard the cry of the golden banana ..."

#! /bin/sh
# This is a shell archive.  Remove anything before this line, then unpack
# it by saving it into a file and typing "sh file".  To overwrite existing
# files, type "sh file -c".  You can also feed this as standard input via
# unshar, or by typing "sh <file", e.g..  If this archive is complete, you
# will see the following message at the end:
#		"End of archive 1 (of 1)."
# Contents:  pckg
# Wrapped by dl2n@freehold.andrew.cmu.edu on Wed Feb 12 16:49:40 1992
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f pckg -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"pckg\"
else
echo shar: Extracting \"pckg\" \(5157 characters\)
sed "s/^X//" >pckg <<'END_OF_pckg'
X#!/usr/local/bin/perl
X
X# pckg - generate a package description of a filesystem tree
X#
X# requires Perl 4.x (possibly 4.10 or greater)
X#
X# usage:
X#	pckg [directory]
X#
X# local andrew.cmu.edu caveats:
X#
X#	We have the convention of an OS tree, which is an image
X#	of the vendor supplied OS from / on down. It resides on
X#	AFS, and via package we can selectively link or copy
X#	files across. This script is designed to create a complete
X#	package description for an OS tree, which can then be edited
X#	down for local purposes.
X#
X#	Here, we mount OS trees as
X#
X#	/afs/andrew.cmu.edu/@sys/os
X#
X#	pckg will attempt to discover where the root of the OS tree that you
X#	point it at is. If you do not use .../os, you will need to modify how 
X#	it pulls apart $ARGV[0] to get it right for your purposes. If it does
X#	not think you've pointed it at an OS tree, it will just generate. This
X#	is useful for creating package descriptions for /dev ala
X#
X#	pckg /dev
X#
X#	We also have the convention of the mpp macro ${machine} which will
X#	resolve to the start of the appropriate OS tree. Again, you may
X#	want to change it for local use. Another convention is that we
X#	tend to map most ownerships down to root/wheel. If pckg cannot
X#	figure out who owns the file (in the case that some vendor shipped
X#	things owned by some bizzare userid), it will render the user down
X#	to root and groups down to wheel. This may not suit all, but is
X#	easy to change in the code.
X#
X#	Obplug: please look around /afs/andrew.cmu.edu/wsadmin/lib to see how
X#	we do things after six years of dealing with package. It may provide
X#	some ideas. wsadmin/public/src/public.proto is used by mpp (ignore
X#	the public.@sys files)
X#
X# general notes:
X#	since package cannot handle hard links, pckg will turn them into
X#	symbolic ones on the fly.
X
X# TODO
X#	pretty output? mondo difficult in finite horizontal space
X#	lookup table of type/owner/group/perm for ${magicmode}
X#	be able to specify a trim table so /usr/man isn't traversed, etc.
X
X# force flushes
Xselect(STDOUT);
X$| = 1;
X
X($os_tree, $start_dir) = $ARGV[0] =~ /(.*os)(.*$)/;
X
Xif (! defined $os_tree) {
X	$os_tree = "";
X	$start_dir = $ARGV[0];
X}
X
X&traverse($start_dir);
X
Xsub traverse {
X	local($dir)=@_;
X	local($d);
X	local(%inoar) = ();
X	local(@dircache) = ();
X
X	$rdir= $os_tree . $dir;
X
X	opendir(DIR, $rdir);
X	local(@dir) = readdir(DIR);
X	closedir(DIR);
X
X	foreach $d (@dir) {
X		next if ($d eq "." || $d eq "..");
X
X		$file = "$dir/$d";
X		$rfile = "$os_tree$file";
X
X		($mydev, $ino, $mode, $nlink, $uid, $gid, $rdev, $size,
X			$atime, $mtime,	$ctime, $blksize, $blocks) 
X			= lstat($rfile);
X
X		# optimization!
X		if ($uid == 0) {
X			$oname = "root";
X		} else {
X			($oname) = getpwuid($uid);	# sloooow
X		}
X		($gname) = getgrgid($gid);
X		$mode = $mode & 0007777;
X
X		# just in case, handle unknown users/groups
X		$oname = "root" if ($oname eq "");
X
X		#or common translations
X		$gname = "wheel" if ($gname eq "" || $gname eq "staff");
X
X		# symlinks
X		if (-l _)
X		{
X			$link = readlink($rfile);
X
X			@linkar = split(/\//, $link);
X
X			# don't do anything with an absolute link
X			if ($linkar[0] ne "") {
X				$up = 0;
X				# rip off "." and ".." counting ".."s in $up
X				while (1) {
X					# link to ./something - rip off ./
X					if ($linkar[0] eq ".") {
X						shift(@linkar);
X						next;
X					}
X					if ($linkar[0] eq "..") {
X						shift(@linkar);
X						$up++;
X						next;
X					}
X					#drop out when we have no .|..
X					last;
X				}
X				
X				@dirar = split(/\//, $dir);
X				while ($up--) {
X					#rip from bottom this time
X					pop(@dirar);
X				}
X
X				$link = join('/', @dirar, @linkar);
X				if ($#dirar == -1) {
X					#link went above /. odd, but legal
X					$link = "/$link";
X				}
X			}
X			printf("LA\t%s\t\t%s", $file, $link);
X			printf("\t%s %s %o\n", $oname, $gname, $mode);
X			next;
X		}
X
X		# device entry
X		if (-b _ || -c _) {
X			# some systems use longwords - detect
X			if ($rdev & 0xffff0000) {
X				$major_dev = ($rdev >> 16) & 0x0000ffff;
X				$minor_dev = ($rdev) & 0x0000ffff;
X			} else {
X				$major_dev = ($rdev >> 8) & 0x000000ff;
X				$minor_dev = ($rdev) & 0x000000ff;
X			}
X
X			if (-b _) {
X				print("B\t");
X			} else {
X				print("C\t");
X			}
X
X			printf("%s\t%d\t%d\t%s %s %o\n", $rfile, 
X						$major_dev, $minor_dev, 
X						 $oname, $gname, $mode);
X			next;
X		}
X
X		# make hard links into symbolic links 
X		# (package can't do hard links - sigh)
X		if (defined $inoar{$ino}) {
X			printf("LA\t%s\t\t%s", $file, $inoar{$ino});
X			printf("\t%s %s %o\n", $oname, $gname, $mode);
X			next;
X		} 
X
X		# cache directory entries do we don't get huge %inoar wastage
X		if (-d _) 
X		{
X			push(@dircache, join('\\', $file, $oname, 
X						   $gname, $mode));
X			next;
X		}
X		
X		# has hard links to it
X		if ($nlink > 1) {
X			$inoar{$ino} = $file;
X		}
X
X		# normal files
X		if (-f _)
X		{
X			printf("F\t%s\t\t%s", $file, '${machine}');
X			printf("\t%s %s %o\n", $oname, $gname, $mode); 
X			next;
X		} 
X	}
X
X	# clear inode array
X	%inoar = ();
X
X	# now traverse directories
X	for (@dircache) {
X		($file, $oname, $gname, $mode) = split(/\\/);
X		printf("DR\t%s\t\t\t\t%s %s %o\n",$file,$oname,$gname,$mode);
X		&traverse($file);
X	}
X
X	# clear directory cache
X	@dircache = ();
X}
X
END_OF_pckg
if test 5157 -ne `wc -c <pckg`; then
    echo shar: \"pckg\" unpacked with wrong size!
fi
chmod +x pckg
# end of overwriting check
fi
echo shar: End of archive 1 \(of 1\).
cp /dev/null ark1isdone
MISSING=""
for I in 1 ; do
    if test ! -f ark${I}isdone ; then
	MISSING="${MISSING} ${I}"
    fi
done
if test "${MISSING}" = "" ; then
    echo You have unpacked all 1 archives.
    rm -f ark[1-9]isdone
else
    echo You still need to unpack the following archives:
    echo "        " ${MISSING}
fi
##  End of shell archive.
exit 0

home help back first fref pref prev next nref lref last post