#! /bin/sh
# BLURB gpl
#
#                            Coda File System
#                               Release 6
#
#           Copyright (c) 1987-2016 Carnegie Mellon University
#                   Additional copyrights listed below
#
# This  code  is  distributed "AS IS" without warranty of any kind under
# the terms of the GNU General Public Licence Version 2, as shown in the
# file  LICENSE.  The  technical and financial  contributors to Coda are
# listed in the file CREDITS.
#
#                         Additional copyrights
#                            none currently
#
#*/

prefix=/usr
exec_prefix=${prefix}

PATH=$PATH:$prefix/sbin
export PATH

# load the server configuration file
vicedir=/vice
. "$(${exec_prefix}/sbin/codaconfedit server.conf)"

if [ ! -f "$vicedir/hostname" ] || [ ! -f "$vicedir/db/scm" ] ; then
   echo "Coda server configuration error.  Could not find needed files."
   exit 1
fi

# Ensure that this is the SCM
scm=$(cat "$vicedir/db/scm")
if [ "$(cat "$vicedir/hostname")" != "$scm" ]; then
	echo "This must be run from the scm ($scm)"
	exit 1
fi

# Parse arguments
if  [ $# -lt 2 ]; then
	echo "bad args:  createvol_rep <volname> <server>[/<partition>] [<server>[/<partition>]]* [groupid]"
	exit 1
fi

# Initialize local variables
SERVERS=
NSERVERS=0
MAXSERVERS=8

# deal with Parameters
VOLNAME="$1"

# The maximum volume name length is really 32 characters, but we have to allow
# for the trailing \0 and we append '.N' to the individual replica names.
MAXVOLNAMELEN=29
VOLNAMELENGTH=${#VOLNAME}

if [ "$VOLNAMELENGTH" -gt "$MAXVOLNAMELEN" ]; then
    echo "Volume name \"$VOLNAME\" too long."
    echo "  it should be at most $MAXVOLNAMELEN characters"
    exit 1
fi

# Hmm, we sometimes need to use the volumename in regular expressions
# As a result we can't use a lot of special characters, but having at
# least '/' would be nice.
_VOLNAME=$(echo "$VOLNAME" | sed 's&/&\\\/&g')

#
# Create these files if they don't already exist.

# VRList was moved from vice/vol to vice/db in Coda 5.3.11
if [ ! -f "$vicedir/db/VRList" ] && [ -f "$vicedir/vol/VRList" ] ; then
  echo "Moving $vicedir/vol/VRList to $vicedir/db"
  cp "$vicedir/vol/VRList" "$vicedir/db/VRList" && rm $vicedir/vol/VRList
  # Need to replicate VRList and maxgroupid too
  echo VRList >> "$vicedir/db/files"
  echo maxgroupid >> "$vicedir/db/files"
fi
touch "$vicedir/db/VRList"

# Dump the VRDB from RVM into a temporary VRList list
rm -f "$vicedir/db/VRList.new"
volutil -h "$scm" dumpvrdb "$vicedir/db/VRList.new" 2>/dev/null
if [ $? -ne 0 ]; then
    echo "Failed to dump the current VRDB into $vicedir/db/VRList.new"
    exit 1
fi

if [ "$VOLNAME" = "$(awk "\$1 ~ /^${_VOLNAME}\$/ { print \$1 }" "$vicedir/db/VRList.new")" ]; then
	echo "Volume $VOLNAME already exists in $vicedir/db/VRList"
	exit 1
fi

while [ $# -gt 1 ]; do
	shift
	PRE=$(echo "$1" | sed 's/\(..\).*/\1/')
	if [ "$PRE" = "7f" ] || [ "$PRE" = "7F" ] ; then
	    GROUPID="$1"
	    break
	fi
	SERVER=$(echo "$1" | sed 's/\([^\/]*\).*/\1/')
	PART=$(echo "$1" | sed 's/[^\/]*\(.*\)/\1/')

	# Validate the server
	grep "$SERVER" "$vicedir/db/servers" > /dev/null
	if [ $? -ne 0 ];  then
		echo "Server $SERVER not in servers file"
		exit 1
	fi

	volutil -h "$SERVER" getvolumelist "/tmp/vollist.$$" 2>/dev/null

	# Validate the <volname> parameter
	egrep '^[WRB]'"${_VOLNAME}"' ' "/tmp/vollist.$$" >/dev/null
	if [ $? -eq 0 ] ; then
	    echo "$VOLNAME already exists as a non replicated volume on $SERVER"
	    exit 1
	fi

	egrep '^[WRB]'"${_VOLNAME}"'\.[0-7] ' "/tmp/vollist.$$" >/dev/null
	if [ $? -eq 0 ] ; then
	    echo "$VOLNAME already exists as a replica on $SERVER"
	    exit 1
	fi

	grep "^P" "/tmp/vollist.$$" | sed 's/^P\(.*\) H.*/\1/' > "/tmp/part.$$"
	np=$(cat "/tmp/part.$$" | wc -w)
	if [ "$np" -eq 0 ]; then
	    echo "Found no partitions for server $SERVER."
	    exit 1
	fi
        if [ -z "$PART" ]; then
	    if [ "$np" -gt 1 ]; then
		echo "Found 2 or more partitions for server $SERVER."
                echo "You must specify a partition."
		exit 1
	    fi
	    PART=$(cat "/tmp/part.$$")
	fi
	grep "^$PART\$" "/tmp/part.$$" >/dev/null
	if [ $? -ne 0 ] ; then
	    echo "Partition $PART not found on server $SERVER."
	    exit 1
	fi
	rm -f "/tmp/vollist.$$" "/tmp/part.$$"

	NSERVERS=$((NSERVERS + 1))
	SERVERS="$SERVERS $SERVER"
	PARTS="$PARTS $PART"
done

if [ $NSERVERS -eq 0 ] || [ $NSERVERS -gt $MAXSERVERS ]; then
    echo "Specify 1 - $MAXSERVERS servers"
    exit 1
fi

# Allocate a new groupid if necessary
if  [ -z "$GROUPID" ]; then
# New location for maxgroupid -- move it.
        if  [ -f "$vicedir/vol/maxgroupid" ]; then
		mv "$vicedir/vol/maxgroupid" "$vicedir/db/maxgroupid"
	fi
	if  [ -f $vicedir/db/maxgroupid ]; then
		MAXGROUPID=$(cat "$vicedir/db/maxgroupid")
		GROUPID=$(printf %x "$MAXGROUPID")
		MAXGROUPID=$((MAXGROUPID + 1))
		echo "$MAXGROUPID" > "$vicedir/db/maxgroupid"
	else
		echo "$vicedir/db/maxgroupid not found"
		exit 1
	fi
fi

echo "Replicated volumeid is $GROUPID"

# strip leading whitespace
PARTS=${PARTS#* }

# Create the new volumes
N=0
ENTRY="$VOLNAME $GROUPID $NSERVERS"
for SERVER in $SERVERS ; do
        PART=${PARTS%% *}
	PARTS=${PARTS#* }

	echo "creating volume $VOLNAME.$N on $SERVER (partition $PART)"
	volutil -h "$SERVER" create_rep "$PART" "$VOLNAME.$N" "$GROUPID" > "/tmp/out.$$"
	if [ $? -ne 0 ]; then
		echo "Failure to make volume on $SERVER!. Abort.".
		exit 1
	fi

	# grab the volume number.
	volnum=$(cut -d' ' -f2 "/tmp/out.$$")
	ENTRY="$ENTRY $volnum"
	N=$((N + 1))
done
rm -f "/tmp/out.$$"

# HACK, disable resolution on singly replicated volumes. The server should
# really be doing this.
if [ $NSERVERS -eq 1 ] ; then
    volutil -h $SERVERS setlogparms "$volnum" reson 0
fi

# Rebuild the VLDB
bldvldb.sh $SERVERS

# Update the VRList and rebuild the VRDB
# We already got the replica id's.
# add nulentries
while [ $N -lt 8 ] ; do
        ENTRY="$ENTRY 0"
	N=$((N + 1))
done

echo "<echo $ENTRY >> $vicedir/db/VRList.new>"
echo "$ENTRY" >> "$vicedir/db/VRList.new"
volutil makevrdb "$vicedir/db/VRList.new"

if [ $? -ne 0 ]; then
    echo "Failed to create a new VRDB file from $vicedir/db/VRList.new"
    exit 1
fi

# All seemed to have gone well. Make a backup of the old VRList and move the
# new VRList in it's place.
mv $vicedir/db/VRList $vicedir/db/VRList.old
mv $vicedir/db/VRList.new $vicedir/db/VRList

# locally trigger reading of the new VRList file (or VRDB on older servers)
volutil updatedb
