Subject: Re: UNPRIVED & DESTDIR
To: None <tech-toolchain@netbsd.org>
From: David Laight <david@l8s.co.uk>
List: tech-toolchain
Date: 05/03/2002 09:09:38
--x+6KMIRAuhnl3hBn
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline

On Fri, May 03, 2002 at 11:16:09AM +1000, Luke Mewburn wrote:
> 
> If you've built UNPRIVED into a DESTDIR, you can use something like
> the following to copy all the files under DESTDIR into / except for
> those in ./etc and ./var, retaining the privileges:
> 
> 	# cd $DESTDIR
> 	# ( cat etc/mtree/NetBSD.dist $MAKEOBJDIRPREFIX/usr/src/METALOG ) | \
> 	    sed -e "s,^.$DESTDIR,.,' | \
> 	    egrep -v '^./(etc|var)/' | \
> 	    nbpax -rwMvpe /

That won't work - the privileges are not set during an UNPRIVED
build.

You need to use the contents of the METALOG file to set them.
Also (unless it has been fixed since last time I updated my source)
you will find that all the .a libraries have the wrong permissions.
(Which stops any further builds...)

I've attached the script I used.

	David

-- 
David Laight: david@l8s.co.uk

--x+6KMIRAuhnl3hBn
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment; filename=update

#!/bin/sh

case `uname -r` in

1.5ZA )	tgt=/; src=/oldroot/usr/bsd-current;;
1.5.2 ) tgt=/mnt; src=/usr/bsd-current;;
* ) echo unknown version; exit 1;;
esac

METALOG=${1:-METALOG}

dest=$src/dest
prefix=


die()
{
    [ "$dots" -gt 1 ] && echo
    echo update failed: "$@" >&2
    exit 1
}

file_die()
{
    [ "$dots" -gt 1 ] && echo
    echo update line \($metacount\) $metaline >&2
    echo '	file '$file: "$@" >&2
    exit 2
}

note()
{
    [ "$dots" -gt 1 ] && echo
    dots=0
    echo "$@"
}

update()
{
    local src tgt tgt_file tgt_dir tmp wd inode refcnt file

    src=$1
    tgt=$2

    note updating file $tgt

    tgt_file=${tgt##*/}
    tgt_dir=${tgt%/$tgt_file}
    tmp=$tgt_dir/_up_x

    [ -w $tgt_dir ]
    wd=$?
    [ $wd = 1 ] && chmod u+w $tgt_dir

    set -- - $(ls -iln $tgt)
    inode=$2
    refcnt=$4

    while [ -f $tmp ]
    do
	note existing file $tmp
	tmp=${tmp}x
    done
    cp -p $src $tmp || file_die copy to temp $tmp
    mv -f $tmp $tgt || {
	rm -r $tmp
	file_die failed to move in new file....
    }

    [ "$refcnt" -gt 1 ] && {
	ls -i $tgt_dir | grep "^ *$inode\>" | while read inode file
	do
	    ln -f $tgt $tgt_dir/$file || file_die cannot replace link $tgt_dir/$file
	done
    }

    [ $wd = 1 ] && chmod u-w $tgt_dir
}

get_mode()
{
    local ls_out

    # get existing permissions
    ls_out="$(ls -ild $file)"
    set -- - $ls_out
    ls_inode=$2
    ls_mode=${3#?}
    ls_type=${3%$ls_mode}
    ls_ref=$4
    ls_user=$5
    ls_group=$6
    ls_size=$7
    ls_file=${11}
    [ x"${12}" = 'x->' ] && ls_link=${13} || ls_link=
    [ "$ls_file" = "$file" ] || file_die ls output name mismatch $ls_out
}

[ -f $METALOG ] || die no METALOG file

[ -d "$dest" ] || die cant find \"$dest\" directory

ls_mode_0444=r--r--r--
ls_mode_0550=r-xr-x---
ls_mode_02550=r-xr-s---
ls_mode_04554=r-sr-xr--
ls_mode_0555=r-xr-xr-x
ls_mode_02555=r-xr-sr-x
ls_mode_04555=r-sr-xr-x
ls_mode_06555=r-sr-sr-x
ls_mode_0600=rw-------
ls_mode_0640=rw-r-----
ls_mode_0644=rw-r--r--
ls_mode_0660=rw-rw----
ls_mode_0664=rw-rw-r--
ls_mode_0755=rwxr-xr-x

exec <$METALOG

cd $tgt || die cant cd to $tgt
metacount=0

# First line of file is that of 'root' - use it as such!
[ -z "$prefix" ] && {
    read prefix type mode uname gname
    [ "$type" = "type=dir" ] || die unexpected first line in metalog file
    prefix=${prefix#.}
    metacount=1
}

dots=0
oifs="$IFS"
while
    metacount=$(($metacount + 1))
    IFS=
    read -r metaline
do
    IFS="$oifs"

    [ -z "$metaline" ] && continue
    case "$metaline" in
    \#* ) continue;;
    esac

    [ "$dots" = 1 ] && echo -n $(($metacount - 1)) .
    [ "$dots" != 0 ] && echo -n .
    dots=$(($dots + 1))
    [ "$dots" = 70 ] && {
	echo
	dots=0
    }

    set -- - $metaline
    file=$2
    shift 2
    options="$*"

    # strip prefix name from filename
    [ -n "$prefix" ] && {
	f1=${file#.$prefix}
	[ "$f1" = "$file" ] && file_die doesnt start with $prefix
	file=.$f1
    }

    opt_type=
    opt_mode=
    opt_uname=
    opt_gname=
    opt_time=
    opt_link=
    for o in $options
    do
	IFS='='
	set -- - $o
	IFS="$oifs"
	case "$2" in
	type ) opt_type="$3";;
	mode ) opt_mode="$3"
		;;
	uname ) opt_uname="$3";;
	gname ) opt_gname="$3";;
	time ) opt_time="$3";;
	link ) opt_link="${3#$prefix}";;
	* )
	    file_die unknown option $2;;
	esac
    done

    [ "$opt_type" = link -o "$opt_type" = hlink ] && {
	[ -z "$opt_link" ] && file_die missing link= param
	# ignore mode of links for now - not usually set...
	opt_mode=
    }

    # canned translations for modes
    opt_ls_mode=
    [ -n "$opt_mode" ] && {
	eval opt_ls_mode=\$ls_mode_$opt_mode
	[ -z "$opt_ls_mode" ] && file_die has unknown mode $opt_mode
    }

    # if nothing exists, create it
    [ -h "$file" -o -e "$file" ] || {
	note $file "($opt_type)" doesn\'t exist
	case "$opt_type" in
	dir) mkdir -p $file || file_die cannot mkdir $file;;
	link ) ln -s $opt_link $file || file_die cannot symlink $file;;
	hlink ) ln $opt_link $file || file_die cannot hard link $file;;
	file ) cp -p $dest/$file $file || file_die cannot copy $file;;
	* ) file_die dont know how to create a $opt_type;;
	esac
	chown -h $opt_uname:$opt_group $file || file_die chown failed
	get_mode
    }

    get_mode

    # verify file type
    case "$opt_type" in
    dir)    [ "$ls_type" = d ] || file_die expected a directory;;
    file )  [ "$ls_type" = '-' ] || file_die expected a file
	    [ -f "$dest/$file" ] || file_die missing from $dest
	    [ "$dest/$file" -nt $file ] && {
		cmp -s $dest/$file $file && touch $file || {
		    update $dest/$file $file
		    chown -h $opt_uname:$opt_group $file || file_die chown failed
		    get_mode
		}
	    }
	    ;;
    link )  [ "$ls_type" = l ] || file_die expected a sym link
	    [ "$ls_link" = "$opt_link" ] || {
		note fix symlink $file to $opt_link "(was $ls_link)"
		ln -fs $opt_link $file || file_die cannot symlink $file
	    };;
    hlink ) opt_link=.$opt_link
	    [ -f "$opt_link" ] || file_die hard link tgt $opt_link missing
	    [ "$file" -ef "$opt_link" ] || {
		note $opt_link not correct file
		[ -f "$opt_link" ] || file_die target of hard link isn\'t reqular
		note replacing link: $opt_link $file
		ln -f $opt_link $file || file_die cannot recreate link
		get_mode
	    };;
    * ) file_die unknown type $opt_type;;
    esac

    # fix owner
    [ \( -n "$opt_uname" -a "$opt_uname" != "$ls_user" \) -o \( \
	     -n "$opt_pname" -a "$opt_pname" != "$ls_group" \) ] && {
	note chown -h $opt_uname:$opt_gname $file
	chown -h $opt_uname:$opt_group $file || file_die chown failed
    }

    # end mode
    [ -n "$opt_ls_mode" -a "$opt_ls_mode" != "$ls_mode" ]  && {
	note chmod $opt_mode $file
	chmod $opt_mode $file || file_die chmod $opt_mode failed
    }

done

IFS="$oifs"
[ "$dots" -gt 1 ] && echo

--x+6KMIRAuhnl3hBn--