#!/bin/sh
# Filename:      grml-bind
# Purpose:       Program to copy config files and mount them back for editing
# Authors:       grml-team (grml.org), (c) Michael Gebetsroither <gebi@grml.org>
# Bug-Reports:   see http://grml.org/bugs/
# License:       This file is licensed under the GPL v2.
# Latest change: Thu Feb 10 06:25:01 CET 2005 [gebi]
################################################################################


###
### __INCLUDES
###
. /etc/grml/sh-lib
#. /etc/grml/sysexits-sh



###
### __VARIABLES
###

# real vars (script defaults)
target_="/ramdisk/grml-bind"
runsFromHd && target_="/tmp/grml-bind"   # where to save the file
file_ro_=""   # secured input filename (source)
target_path_="" #secured path to target + filename

# command parameter vars
verbose_=0
remove_mapping_=0   # user wants to remove the mapping
create_mapping=0    # user wants to create the mapping



###
### __FUNCTIONS
###

# print program usage
function printUsage
{
cat << EOF
Usage: "grml-bind" [OPTIONS] <file you want to edit>

grml-bind is a program to prepare a file on a read-only fs for writing
It copies the file to a ramdisk and mount --bind it back.
Very usefull for knoppix-like distributions.

OPTIONS:
   -c     create the file-mapping
   -r     remove the file-mapping
   -v     verbose (show what is going on, v++)
   -h     this help text
   ()     create the file-mapping

EOF
}


# function to create the mapping
function createMapping
{
  isExistent "$file_ro_" die
  isNotExistent "$target_path_" die

  # --preserve=mode,ownership,timestamps can be a problem for normal user
  # but neverless mount --bind requires extended privilegs, so who cares?
  execute "cp -rL \"$file_ro_\" \"$target_\"" warn \
    "Problms copying data to ramdisk"

  # mount--bind the file from ramdisk back over the r/o file
  execute "mount --bind \"$target_path_\" \"$file_ro_\"" warn || \
    execute "rm -r \"$target_path_\"" die
  
  exit 0
}


# remove the mapping
function removeMapping
{
  isExistent "$target_path_" die \
    "You have not edited this file yet: \"$target_path_\""

  execute "umount \"$file_ro_\"" warn
  execute "rm -r \"$target_path_\"" die

  exit 0
}


###
### __START
###

# parse commandline
while getopts vrhc opt_ ; do
  case "$opt_" in
    r) remove_mapping_=1 ;;
    c) create_mapping=1 ;;
    h) printUsage; exit ;;
    v) let verbose_=$verbose_+1 ;;
    ?) printUsage; exit 64 ;;
  esac
done
shift $(($OPTIND - 1))  # set ARGV to the first not parsed commandline parameter
setVerbose $verbose_


###
# Working part
###

setExitFunction "printUsage"
# hmmm user has not given us a filename/path
if [ -z "$1" ]; then
  die "you need to give me a file/path" 64
fi

# hmmm user gave us the wrong number of arguments
if [ "$#" -ne 1 ]; then
  die "wrong number of arguments" 64
fi
resetExitFunction

checkRoot die

# does our target-path exist? if not create it
if [ ! -d $target_ ]; then
  warn "target path \"$target_\" does not exist => creating"
  execute "mkdir -p $target_" die
  runsFromHd && execute "chmod 751 $target_" die
fi

# secure the input file/path
file_ro_=`secureInput "$1"`

# check if input file is a link, if yes resolve it
if [ -L $file_ro_ ]; then
  file_ro_=`execute "readlink \"$file_ro_\""`
fi

#create all possible pathformats to absolut paths
normalized_source_path_=`relToAbs "$file_ro_"`
file_ro_=$normalized_source_path_
target_path_=$target_/`execute "basename \"$normalized_source_path_\""`

# do what the user wants, maybee *g*
if [ $remove_mapping_ -eq 1 ]; then # ok, the user wants to remove his mapping
  removeMapping
else # no, user wants to create the mapping
  createMapping
fi

# END OF FILE ################################################################################
