#!/bin/sh

if [ $# -le 1 ]; then
  echo "usage: mkisofs -o image.iso -graft-points \`graftat <path on CD> <file or dir>...\` ..."
  fmt <<EOF

The option -graft-points of mkisofs is a useful feature implemented in
the most braindead way possible.  It allows to determine where in the image's
directory tree the given files end up by passing file names in the form
<graft point>=<file name>.  But the semantics differ between files and
directories: "name1/name2=source" will graft "source" as "name1/name2" if it
is a file, but will graft the contents of "source" at "name1/..." as their own
name if "source" is directory (and "name1/name2" usually will not exist at
all).  This makes the graft option annoying to use and only suitable for a very
few files if the effort is to be reasonable.

graftat accepts semantics resembling those of cp or mv and outputs graft point
descriptors suitable for mkisofs's command line.  Its first argument is the
"target directory" in the directory tree on the CD, the others are the files or
directories to be "copied" there.  It generates an expression "<path>/<file
without path>=<file>" for each file.  If <path> is the empty string, the output
is just "<file without path>=<file>", which puts the file or directory into the
CD's root directory.  If <file or dir> is a directory, a slash is inserted
before the equals sign, so that its files and subdirectories end up inside its
equivalent on the CD.

CAVEAT: As for any program being executed via command substitution, errors
occurring in graftat will not abort the mkisofs command.  It is recommended to
test the validity of graftat's arguments first, most easily done by prepending
the whole mkisofs command line by "echo" before running it for real.

EOF
  exit 1
fi

if [ "${1:0:1}" = "/" ]; then
  echo "Cannot use absolute paths as graft points." >&2
  exit 1
fi

if [ -z "$1" ]; then
  graft=
else
  graft="$1"
  while [ -z "${graft##*/}" ]; do
    graft="${graft%/}"
  done
  graft="$graft/"
fi
shift

while [ $# -gt 0 ]; do

  file="$1"
  base=${file##*/}
  while [ -n "$file" -a -z "$base" ]; do
    file="${file%/}"
    base="${file##*/}"
  done
  if [ "$base" = ".." -o "$base" = "." ]; then
    if [ "${file:0:1}" != "/" ]; then
      file="`pwd`/$file"
    fi
    newfile="${file//\/.\///}"
    while [ "$file" != "$newfile" ]; do
      file="$newfile"
      newfile="${file//\/.\///}"
    done
    file="${file%/.}"
    base="${file##*/}"
    while [ "$base" = ".." -o "$base" = "." ]; do
      post="${file#*/..}"
      file="${file%$post}"
      file="${file%\/*\/..}/"
      file="${file/#\/..\///}"
      file="${file%/}$post"
      base="${file##*/}"
    done
  fi
  if [ -z "$file" ]; then
    echo "Cannot take base name of root directory or empty file name." >&2
    exit 1
  fi
  if [ -d "$file" ]; then
    base="$base/"
  fi
  echo $graft$base=$file
  shift

done

