#! /usr/bin/ksh
##########################################################################
# Title      :	update.ksh - update files based on the modification time
# Author     :	Heiner Steven <heiner.steven@odn.de>
# Date       :	1996-05-24
# Requires   :	ksh
# Category   :	File Utilities
# SCCS-Id.   :	@(#) update	2.2 18/05/17
##########################################################################
# Description
#
##########################################################################

PN=${0##*/}			# Program name
VER='2.2'

CpFlags=p

function Usage
{
    print -u2 "$PN - update files based on the modification time, $VER
usage: $PN [-efv] file [file ...] directory
    or $PN [-efv] file file
    or $PN [-efrv] {file|directory} [...] directory
    -e:  only update already existing files
    -f:  force overwriting read-only files
    -r:  copy recursively
    -v:  verbose operation"
    exit 1
}

function msg { print -u2 -- "$PN:" "$@"; }
function fatal { msg "$@"; exit 1; }

set -u	# DEBUG

Recurse=false
Verbose=false
AddFiles=true
while getopts :efhrv Opt
do
    case "$Opt" in
    	(e)	AddFiles=false;;
    	(f)	CpFlags=${CpFlags}f;;
	(r)	Recurse=true;;
	(v)	Verbose=true;;
	(h)	Usage;;
	(*)	Usage;;
    esac
done
shift OPTIND-1

(( $# < 2 )) && Usage

eval dst=\${$#}

# There is one special case where
#   (1)	exactly two arguments are specified, and
#   (2)	both are files

FileCopy=false
[[ -f $dst ]] && (($# == 2)) && FileCopy=true

if [[ -d $dst ]] || $FileCopy
then					# Copy files to a directory
    integer newcnt=0 oldcnt=0

    while [ $# -gt 1 ]
    do
	srcpath=$1; shift

	[[ $srcpath == $dst ]] && continue
	[[ $srcpath -ef $dst ]] && continue

	if [[ -d $srcpath ]]
	then
	    if ! $Recurse
	    then
	    	msg "omitting directory \"$srcpath\""
	    	continue
	    fi

	    # Recurse into the subdirectory, using the positional argument
	    # list as a stack:
	    set -- "$srcpath"/* "$@"
	    #echo >&2 "DEBUG: recurse into $srcpath ($# stack elements)"
	    continue
	fi

	# We will only process ordinary files. No devices, no pipes.
	[[ -f $srcpath ]] || continue

	# Process a file. Note that the source file name may have a
	# directory part, which we will re-create in the destination
	# directory.

	srcfile=$srcpath
	srcbase=${srcfile##*/}		# Remove directory part

	if $FileCopy
	then
	    dstdir=$dst
	    dstfile=$dst
	else
	    if [[ $srcfile == */* ]]
	    then
		dir=${srcfile%/*}
		dstdir=$dst/$dir
		[[ -e $dstdir ]] || mkdir -p "$dstdir" || exit
	    else
		dstdir=$dst
	    fi
	    dstfile=$dstdir/$srcbase
	fi

	# Compare "srcfile" with "dstfile"

	if [[ -e $dstfile ]]
	then
	    if [[ $srcfile -nt $dstfile ]]
	    then
		copy=true
	    else
		copy=false
		$Verbose && msg "existing \"$dstfile\" is same age or newer"
		((oldcnt=$oldcnt+1))
	    fi
	else
	    if $AddFiles || $FileCopy
	    then
		copy=true
	    else
		copy=false
		$Verbose &&
		    msg "does not exist in target directory: \"$srcfile\""
	    fi
	fi

	$copy || continue

	$Verbose && echo "$dstfile"
	cp -$CpFlags "$srcfile" "$dstdir" &&
	    ((newcnt=$newcnt+1))
    done

    msg "$newcnt file(s) updated, $oldcnt kept"

else
    fatal "no directory: $dst"
fi
