515 lines
		
	
	
		
			23 KiB
		
	
	
	
		
			Bash
		
	
	
		
			Executable File
		
	
			
		
		
	
	
			515 lines
		
	
	
		
			23 KiB
		
	
	
	
		
			Bash
		
	
	
		
			Executable File
		
	
| #!/bin/bash
 | |
| 
 | |
| #/**
 | |
| #@file    oglivecli
 | |
| #@brief   Command line tool to manage ogLive clients.
 | |
| #@usage   oglivecli Command [Options ...]
 | |
| #@param   Command:
 | |
| #@param     help                show this help
 | |
| #@param     version             show script version
 | |
| #@param     config [Parameter]  show configuration parameters
 | |
| #@param     check               check system consistency
 | |
| #@param     convert             convert old ogclient to new default ogLive client
 | |
| #@param     list                list installed ogLive clients
 | |
| #@param     show all            show JSON information about all installed ogLive clients
 | |
| #@param     show default        show JSON information about ogLive client marked as default
 | |
| #@param     show Index|Dir      show JSON information about an installed ogLive client
 | |
| #@param     search Index|Dir    show corresponding index or directory
 | |
| #@param     download            show a menu to download an ogLive ISO image from the OpenGnsys website
 | |
| #@param     download Iso        download an specific ogLive ISO image from the OpenGnsys website
 | |
| #@param     install Iso         install a new ogLive client from a downloaded ISO image
 | |
| #@param     uninstall Iso       remove ISO image and uninstall its ogLive client
 | |
| #@param     uninstall Index|Dir uninstall an ogLive client
 | |
| #@param     get-default         get index value for default ogLive client
 | |
| #@param     set-default Index   set default ogLive client
 | |
| #@param     rebuild             rebuild a lost configuration file
 | |
| #@param     assign Iso Index    assign an ISO file to a JSON entry
 | |
| #@param   Options:
 | |
| #@param     Index   a number, starting by 0
 | |
| #@param     Dir     directory (relative to installation directory)
 | |
| #@param     Iso     ISO file name (relative to download URL or download directory)
 | |
| #@warning This script needs "jq" command.
 | |
| #@version 1.1.0 - Initial version.
 | |
| #@author  Ramón M. Gómez - ETSII Univ. Sevilla
 | |
| #@date    2016-12-05
 | |
| #@version 1.1.1b - Use reduced directory names.
 | |
| #@author  Ramón M. Gómez - ETSII Univ. Sevilla
 | |
| #@date    2020-01-17
 | |
| #*/ ##
 | |
| 
 | |
| 
 | |
| # Global constants definition.
 | |
| PROG=$(basename "$(realpath "$0")")			# Program name.
 | |
| OPENGNSYS=/opt/ogboot				# OpenGnsys main directory.
 | |
| DOWNLOADDIR=$OPENGNSYS/lib				# Directory to store ogLive images.
 | |
| DOWNLOADURL="https://ognproject.evlt.uma.es/trac/downloads"	# Download URL.
 | |
| TFTPDIR=$OPENGNSYS/tftpboot				# TFTP directory.
 | |
| DEFOGLIVE="ogLive"					# Default ogLive directory.
 | |
| MINREL=20190601						# Mininum ogLive compatibility release.
 | |
| INFOFILE=$OPENGNSYS/etc/ogliveinfo.json			# Configuration file.
 | |
| 
 | |
| 
 | |
| # Global and secondary functions.
 | |
| 
 | |
| source $OPENGNSYS/lib/ogfunctions.sh || exit 1
 | |
| 
 | |
| # Create/edit JSON file about installed ogLive clients.
 | |
| function addToJson() {
 | |
|     local i DATA OGLIVEDIST="$1" OGLIVEKRNL="$2" OGLIVEARCH="$3" OGLIVEREV="$4"
 | |
|     local OGLIVEDIR=$(basename $5 2>/dev/null) OGLIVEISO=$(basename $6 2>/dev/null)
 | |
|     # JSON data for installed ogLive.
 | |
|     DATA=$(cat << EOT | jq .
 | |
| {"distribution":"$OGLIVEDIST","kernel":"$OGLIVEKRNL","architecture":"$OGLIVEARCH","revision":"$OGLIVEREV","directory":"$OGLIVEDIR","iso":"$OGLIVEISO"}
 | |
| EOT
 | |
|     )
 | |
|     # Check JSON file consistency.
 | |
|     if [ "$(jq -c keys $INFOFILE 2>/dev/null)" == '["default","oglive"]' ]; then
 | |
|         # Check if ogLive is defined into JSON file.
 | |
|         n=$(jq ".oglive | length" $INFOFILE)
 | |
|         for ((i=0; i<n; i++)); do
 | |
|             [ "$(jq ".check=$DATA | .check==.oglive[$i]" $INFOFILE)" == "true" ] && INDEX=$i
 | |
|         done
 | |
|         # Check if it needs to insert data.
 | |
|         if [ -z "$INDEX" ]; then
 | |
|             INDEX=$n
 | |
|             jq ".oglive |= (. + [$DATA])" $INFOFILE | sponge $INFOFILE
 | |
|         fi
 | |
|         # Show JSON entry.
 | |
|         jq ".oglive[$INDEX]" $INFOFILE
 | |
|     else
 | |
|         # Create new JSON file.
 | |
|         cat << EOT | jq . | tee $INFOFILE
 | |
| {"oglive":[$DATA],"default":0}
 | |
| EOT
 | |
|     fi
 | |
| }
 | |
| 
 | |
| # Command functions.
 | |
| 
 | |
| # Convert default ogclient to a new ogLive format.
 | |
| function convert() {
 | |
|     local OGCLIENT=ogclient OLDINFOFILE=$OPENGNSYS/doc/veroglive.txt
 | |
|     local OGLIVEKRNL OGLIVEDIR OGLIVEISO
 | |
|     [ $# -ne 0 ] && raiseError usage
 | |
|     [ ! -w $(dirname $INFOFILE) ] && raiseError access "Configuration file."
 | |
|     [ -n "$(stat -c "%N" $TFTPDIR/ogclient | awk '$3~/'$DEFOGLIVE'/ {print}')" ] && raiseError access "ogLive is already converted."
 | |
|     pushd $TFTPDIR >/dev/null || raiseError access "Installation directory."
 | |
|     [ ! -f $OGCLIENT/ogvmlinuz ] && raiseError notfound "\"ogclient\"."
 | |
|     # Add entry to JSON file using ogclient kernel version.
 | |
|     OGLIVEKRNL=$(file -bkr $OGCLIENT/ogvmlinuz | awk '/Linux/ {for(i=1;i<=NF;i++) if($i~/version/) {v=$(i+1);sub(/-.*/,"",v);print v}}')
 | |
|     OGLIVEDIR=$DEFOGLIVE-$OGLIVEKRNL
 | |
|     [ -r $OLDINFOFILE ] && OGLIVEISO="$(head -1 $OLDINFOFILE)"
 | |
|     addToJson "$(echo $OGLIVEISO|cut -f2 -d-)" "$OGLIVEKRNL" "i386" "${OGLIVEISO##*-}" "$OGLIVEDIR" "$OGLIVEISO.iso"
 | |
|     # Rename directory, link to default and clean old files.
 | |
|     mv -v $OGCLIENT $OGLIVEDIR
 | |
|     ln -vfs $OGLIVEDIR $DEFOGLIVE
 | |
|     rm -f $OGCLIENT
 | |
|     ln -vfs $DEFOGLIVE $OGCLIENT
 | |
|     mv -v $OGCLIENT.old $OGLIVEDIR.old 2>/dev/null
 | |
|     rm -fv {ogvmlinuz,oginitrd.img}{,.sum} $OLDINFOFILE
 | |
|     popd >/dev/null
 | |
|     # Delete old config file.
 | |
|     rm -f $OLDINFOFILE
 | |
| }
 | |
| 
 | |
| # Show script configuration parameters.
 | |
| function config() {
 | |
|     local DATA
 | |
|     DATA=$(cat << EOT
 | |
| [
 | |
|   { "param": "config-file", "description": "Configuration file", "value": "$INFOFILE" },
 | |
|   { "param": "download-url", "description": "ogLive download URL", "value": "$DOWNLOADURL" },
 | |
|   { "param": "download-dir", "description": "ogLive download directory", "value": "$DOWNLOADDIR" },
 | |
|   { "param": "install-dir", "description": "ogLive installation directory", "value": "$TFTPDIR" },
 | |
|   { "param": "default-name", "description": "Default ogLive name", "value": "$DEFOGLIVE" },
 | |
|   { "param": "min-release", "description": "Minimum compatibility release", "value": "r$MINREL" }
 | |
| ]
 | |
| EOT
 | |
|     )
 | |
|     case $# in
 | |
|         0)  # Show all parameters.
 | |
|             echo "$DATA" | jq -r '.[] | .description + " (" + .param + ")," + .value' | column -ts,
 | |
|             ;;
 | |
|         1)  # Show specified parameter.
 | |
|             DATA=$(echo "$DATA" | jq -r ".[] | select(.param==\"$1\").value")
 | |
|             [ "$DATA" ] || raiseError notfound "\"$1\"."
 | |
|             echo "$DATA"
 | |
|             ;;
 | |
|         *)  # Usage error.
 | |
|             raiseError usage
 | |
|             ;;
 | |
|     esac
 | |
| }
 | |
| 
 | |
| # Check consistency, showing configuration problems.
 | |
| function check() {
 | |
|     local ERR=0 AUX INST DEF
 | |
|     [ $# -ne 0 ] && raiseError usage
 | |
|     # Check for old system that needs conversion.
 | |
|     if [ -z "$(stat -c "%N" $TFTPDIR/ogclient | awk '$3~/'$DEFOGLIVE'/ {print}')" ]; then
 | |
|          echo "This server uses old ogclient, please run \"$PROG convert\" to update."
 | |
|          let ERR++
 | |
|          [ ! -f $INFOFILE ] && return $ERR
 | |
|     fi
 | |
|     # Check for other problems.
 | |
|     [ ! -f $INFOFILE ] && echo "Configuration file does not exists: $INFOFILE" && let ERR++
 | |
|     [ -f $INFOFILE -a "$(jq -c keys $INFOFILE 2>/dev/null)" != "[\"default\",\"oglive\"]" ] && echo "Format error in configuration file: $INFOFILE" && let ERR++
 | |
|     [ ! -e $TFTPDIR ] && echo "TFTP directory does not exist: $TFTPDIR." && let ERR++
 | |
|     # Check for installed ogLive clients.
 | |
|     INST=( $(find $TFTPDIR/ -type d -name "$DEFOGLIVE-*" -a ! -name "*.old" -printf "%f\n" | sort) )
 | |
|     [[ ${#INST[@]} -eq 0 ]] && echo "No ogLive clients are installed." && let ERR++
 | |
|     DEF=( $(jq -r .oglive[].directory $INFOFILE 2>/dev/null | sort) )
 | |
|     # Compare installed and defined ogLive clients.
 | |
|     AUX=$(comm -23 <(printf "%s\n" ${INST[*]}) <(printf "%s\n" ${DEF[*]}))
 | |
|     [ -n "$AUX" ] && echo "Some ogLive are installed but not defined: ${AUX//$'\n'/, }" && let ERR++
 | |
|     AUX=$(comm -13 <(printf "%s\n" ${INST[*]}) <(printf "%s\n" ${DEF[*]}))
 | |
|     [ -n "$AUX" ] && echo "Some ogLive are defined but not installed: ${AUX//$'\n'/, }" && let ERR++
 | |
|     # Compare downloaded and defined ISO images.
 | |
|     INST=( $(find $DOWNLOADDIR/ -type f -name "$DEFOGLIVE-*.iso" -printf "%f\n" | sort) )
 | |
|     DEF=( $(jq -r .oglive[].iso $INFOFILE 2>/dev/null | sort) )
 | |
|     AUX=$(comm -23 <(printf "%s\n" ${INST[*]}) <(printf "%s\n" ${DEF[*]}))
 | |
|     [ -n "$AUX" ] && echo "Some ISOs are downloaded but not defined: ${AUX//$'\n'/, }" && let ERR++
 | |
|     AUX=$(comm -13 <(printf "%s\n" ${INST[*]}) <(printf "%s\n" ${DEF[*]}))
 | |
|     [ -n "$AUX" ] && echo "Some ISOs are defined but not downloaded: ${AUX//$'\n'/, }" && let ERR++
 | |
|     # Check for new ISO files downloaded after installation.
 | |
|     AUX=$(jq -r '.oglive[] as $og | $og.iso + ":" + $og.directory' $INFOFILE 2>/dev/null | \
 | |
|             while IFS=":" read -r DEF INST; do
 | |
|                 [ $DOWNLOADDIR/$DEF -nt $TFTPDIR/$INST ] && echo "$DEF"
 | |
|             done)
 | |
|     [ -n "$AUX" ] && echo "Some ISOs are downloaded after installation: ${AUX//$'\n'/, }" && let ERR++
 | |
|     AUX=$(jq -r '.oglive[] as $og | if ($og.revision[1:9] | tonumber) < '$MINREL' then $og.directory else "" end' $INFOFILE 2>/dev/null)
 | |
|     [ -n "$AUX" ] && echo "Some installed ogLive aren't fully compatible: ${AUX//$'\n'/, }" && let ERR++
 | |
|     DEF=$(jq -r ".oglive[$(getdefault)].directory" $INFOFILE 2>/dev/null)
 | |
|     INST=$(stat -c "%N" $TFTPDIR/$DEFOGLIVE | cut -f4 -d\')
 | |
|     [ "$DEF" != "$INST" ] && echo "Default ogLive is not linked to right directory: $DEF <> $INST" && let ERR++
 | |
|     # Print result.
 | |
|     [ $ERR -eq 0 ] && echo "OK!" || echo "Problems detected: $ERR"
 | |
|     return $ERR
 | |
| }
 | |
| 
 | |
| # List installed ogLive clients.
 | |
| function list() {
 | |
|     [ $# -ne 0 ] && raiseError usage
 | |
|     [ ! -r $INFOFILE ] && raiseError access "Configuration file."
 | |
|     # List all defined indexes, directories and check if missing.
 | |
|     jq -r .oglive[].directory $INFOFILE | nl -v 0 | \
 | |
|             awk '{system("echo -n "$0"; test -d '$TFTPDIR'/"$2" || echo -n \" (missing)\"; echo")}' | column -t
 | |
| }
 | |
| 
 | |
| # Show information about an installed ogLive client.
 | |
| function show() {
 | |
|     local INDEX
 | |
|     [ $# -ne 1 ] && raiseError usage
 | |
|     [ ! -r $INFOFILE ] && raiseError access "Configuration file."
 | |
|     # Show JSON entries.
 | |
|     case "$1" in
 | |
|         default)    # Default index.
 | |
|             INDEX="[$(jq -r .default $INFOFILE)]" ;;
 | |
|         all)        # All intries.
 | |
|             ;;
 | |
|         [0-9]*)     # Index.
 | |
|             INDEX="[$1]" ;;
 | |
|         *)          # Directory.
 | |
|             INDEX="[$(search "$1" 2>/dev/null)]" || raiseError notfound "Directory \"$1\"."
 | |
|             ;;
 | |
|     esac
 | |
|     jq ".oglive$INDEX" $INFOFILE || raiseError notfound "Index \"$1\"."
 | |
| }
 | |
| 
 | |
| # Show index or directory corresponding to searching parameter.
 | |
| function search() {
 | |
|     [ $# -ne 1 ] && raiseError usage
 | |
|     [ ! -r $INFOFILE ] && raiseError access "Configuration file."
 | |
|     # Show corresponding index or directory.
 | |
|     list | awk -v d="$1" '{if ($2==d) print $1; if ($1==d) print $2}' | grep . || raiseError notfound "Index/Directory \"$1\"."
 | |
| }
 | |
| 
 | |
| # Show a menu to select and download an ogLive ISO image from the OpenGnsys website.
 | |
| function download() {
 | |
|     local OGLIVE NISOS i HTTPCODE ISOREL
 | |
| 
 | |
|     # Verificar si el directorio de descarga existe y tiene permisos de escritura.
 | |
|     [ ! -d "$DOWNLOADDIR" ] && raiseError notfound "Directorio de descarga."
 | |
|     [ ! -w "$DOWNLOADDIR" ] && raiseError access "Directorio de descarga."
 | |
| 
 | |
|     # Si no se proporciona ningún parámetro, mostrar el menú de descargas.
 | |
|     if [ -z "$1" ]; then
 | |
|         downloadMenu
 | |
|     else
 | |
|         local selected_name="$1"
 | |
| 
 | |
|         # Obtener la lista de archivos disponibles.
 | |
|         OGLIVE=( $(curl -k --silent $DOWNLOADURL | grep "$DEFOGLIVE.*iso") )
 | |
| 
 | |
|         # Buscar el archivo seleccionado por nombre.
 | |
|         OGLIVEFILE=""
 | |
|         for iso in "${OGLIVE[@]}"; do
 | |
|             if [[ "$iso" == *"$selected_name"* ]]; then
 | |
|                 OGLIVEFILE=$iso
 | |
|                 break
 | |
|             fi
 | |
|         done
 | |
| 
 | |
|         [ -n "$OGLIVEFILE" ] || raiseError download "Nombre \"$selected_name\" inválido."
 | |
| 
 | |
|         # Obtener el tamaño de descarga.
 | |
|         local SOURCELENGTH=$(curl -k --head --retry 5 --retry-delay 5 --max-time 30 "$DOWNLOADURL/$OGLIVEFILE" | awk -F: '/Content-Length:/ {print $2}')
 | |
|         [ -n "$SOURCELENGTH" ] || raiseError download "$OGLIVEFILE"
 | |
| 
 | |
|         # Descargar ogLive.
 | |
|         local TARGETFILE="$DOWNLOADDIR/$OGLIVEFILE"
 | |
|         trap "rm -f $TARGETFILE" 1 2 3 6 9 15
 | |
|         curl -k --retry 5 --retry-delay 5 "$DOWNLOADURL/$OGLIVEFILE" -o "$TARGETFILE" || raiseError download "\"$OGLIVEFILE\"."
 | |
|         install "$OGLIVEFILE"
 | |
|     fi
 | |
| }
 | |
| # Muestra un menú para seleccionar y descargar un archivo ogLive ISO del sitio web de OpenGnsys.
 | |
| function downloadMenu() {
 | |
|     
 | |
|     local OGLIVE NISOS i HTTPCODE ISOREL
 | |
|     OGLIVE=( $(curl -k --silent $DOWNLOADURL | grep "$DEFOGLIVE.*iso") )
 | |
|     NISOS=${#OGLIVE[@]}
 | |
|     echo "Descargas disponibles (+ = instalado, * = compatibilidad completa):"
 | |
|     for i in $(seq 1 $NISOS); do
 | |
|         [ -e $DOWNLOADDIR/${OGLIVE[i-1]} ] && OGLIVE[i-1]="(+) ${OGLIVE[i-1]}"
 | |
|         ISOREL=${OGLIVE[i-1]##*-r}; ISOREL=${ISOREL%%.*}
 | |
|         [ $ISOREL -ge $MINREL ] && OGLIVE[i-1]="(*) ${OGLIVE[i-1]}"
 | |
|         echo "$i) ${OGLIVE[i-1]}"
 | |
|     done
 | |
| }
 | |
| 
 | |
| # Show a menu to select and download an ogLive ISO image from the OpenGnsys website.
 | |
| function download_old() {
 | |
|     local OGLIVE NISOS i HTTPCODE TARGETFILE
 | |
|     local ISOREL
 | |
|     [ $# -gt 1 ] && raiseError usage
 | |
|     [ ! -d $DOWNLOADDIR ] && raiseError notfound "Download directory."
 | |
|     [ ! -w $DOWNLOADDIR ] && raiseError access "Download directory."
 | |
|     # Check parameter.
 | |
|     if [ -n "$1" ]; then
 | |
|         # ogLive to download.
 | |
|         OGLIVEFILE="$1"
 | |
|     else
 | |
|         # Show download menu.
 | |
|         OGLIVE=( $(curl -k --silent $DOWNLOADURL | grep "$DEFOGLIVE.*iso") )
 | |
|         NISOS=${#OGLIVE[@]}
 | |
|         echo "Available downloads (+ = installed, * = full compatibility):"
 | |
|         for i in $(seq 1 $NISOS); do
 | |
|             [ -e $DOWNLOADDIR/${OGLIVE[i-1]} ] && OGLIVE[i-1]="(+) ${OGLIVE[i-1]}"
 | |
|             ISOREL=${OGLIVE[i-1]##*-r}; ISOREL=${ISOREL%%.*}
 | |
|             [ $ISOREL -ge $MINREL ] && OGLIVE[i-1]="(*) ${OGLIVE[i-1]}"
 | |
|         done
 | |
|         select opt in "${OGLIVE[@]}"; do
 | |
|             [ -n "$opt" ] && OGLIVEFILE=${opt##* } && break
 | |
|         done
 | |
|     fi
 | |
|     # Get download size.
 | |
|     SOURCELENGTH=$(curl -k --head --retry 5 --retry-delay 5 --max-time 30 $DOWNLOADURL/$OGLIVEFILE | awk -F: '/Content-Length:/ {print $2}')
 | |
|     [ -n "$SOURCELENGTH" ] || raiseError download "$OGLIVEFILE"
 | |
|     # Download ogLive.
 | |
|     TARGETFILE=$DOWNLOADDIR/$OGLIVEFILE
 | |
|     trap "rm -f $TARGETFILE" 1 2 3 6 9 15
 | |
|     curl -k --retry 5 --retry-delay 5 --max-time 30 $DOWNLOADURL/$OGLIVEFILE -o $TARGETFILE || raiseError download "\"$OGLIVEFILE\"."
 | |
| }
 | |
| 
 | |
| # Install an ogLive client from a previously downloaded ISO image.
 | |
| function install() {
 | |
|     local OGLIVEFILE OGLIVEDIST OGLIVEREV OGLIVEKRNL OGLIVEDIR OGINITRD OGSQFS OGCLIENT=ogclient
 | |
|     local COMPRESS SAMBAPASS TMPDIR RSYNCSERV RSYNCCLNT
 | |
|     [ $# -ne 1 ] && raiseError usage
 | |
|     OGLIVEFILE=$(realpath $DOWNLOADDIR/$1)
 | |
|     # Only 1 file in pathname expansion.
 | |
|     [ $(echo $OGLIVEFILE | wc -w) -gt 1 ] && raiseError usage
 | |
|     [ ! -f $OGLIVEFILE ] && raiseError notfound "Downloaded file: \"$1\"."
 | |
|     [ ! -r $OGLIVEFILE ] && raiseError access "Downloaded file: \"$1\"."
 | |
|     [ ! -w $(dirname $INFOFILE) ] && raiseError access "Configuration directory."
 | |
|     [ ! -w $TFTPDIR ] && raiseError access "Installation directory."
 | |
|     [ -z "$(file -b $OGLIVEFILE | grep "ISO.*ogClient")" ] && raiseError access "File is not an ogLive ISO image."
 | |
|     # Working directory:
 | |
|     #   64-bit: ogLive-KernelVersion-rCodeRelease
 | |
|     #   32-bit: ogLive-KernelVersion-i386-rCodeRelease
 | |
|     OGLIVEDIST="$(echo $OGLIVEFILE|cut -f2 -d-)"
 | |
|     OGLIVEREV="${OGLIVEFILE##*-}"; OGLIVEREV="${OGLIVEREV%%.*}"
 | |
|     OGLIVEKRNL="$(echo $OGLIVEFILE|cut -f3- -d-)"; OGLIVEKRNL="${OGLIVEKRNL%-$OGLIVEREV.*}"
 | |
|     OGLIVEARCH="$(echo $OGLIVEFILE|awk -F- '{print $(NF-1)}')"
 | |
|     case "$OGLIVEARCH" in
 | |
|         i386|amd64) # Get architecture.
 | |
|             OGLIVEKRNL="${OGLIVEKRNL%-$OGLIVEARCH}" ;;
 | |
|         *)          # 32-bit by default.
 | |
|             OGLIVEARCH="i386" ;;
 | |
|     esac
 | |
|     OGLIVEDIR="$TFTPDIR/$DEFOGLIVE-${OGLIVEKRNL%%-*}-$OGLIVEARCH-$OGLIVEREV"
 | |
|     OGLIVEDIR="${OGLIVEDIR/amd64-/}"
 | |
|     # Get current or default Samba key.
 | |
|     OGINITRD=$OGLIVEDIR/oginitrd.img
 | |
|     [ ! -r $OGINITRD ] && OGINITRD=$TFTPDIR/$DEFOGLIVE/oginitrd.img
 | |
|     if [ -r $OGINITRD ]; then
 | |
|         COMPRESS=$(file -b "$OGINITRD" | awk '{print tolower($1);}')
 | |
|         SAMBAPASS=$($COMPRESS -dc $OGINITRD | \
 | |
|             cpio -i --to-stdout scripts/ogfunctions 2>&1 | \
 | |
|             sed -n '/^[ 	].*OPTIONS=/s/.*pass=\(\w*\).*/\1/p')
 | |
|     fi
 | |
|     # Make ogLive backup.
 | |
|     rm -fr ${OGLIVEDIR}.old
 | |
|     mv -fv $OGLIVEDIR ${OGLIVEDIR}.old 2>/dev/null
 | |
|     # Mount ogLive ISO image, update its files and unmount it.
 | |
|     TMPDIR=/tmp/${OGLIVEFILE%.iso}
 | |
|     mkdir -p $OGLIVEDIR $TMPDIR
 | |
|     trap "umount $TMPDIR; rm -fr $TMPDIR" 1 2 3 6 9 15
 | |
|     mount -o loop,ro $OGLIVEFILE $TMPDIR
 | |
|     cp -va $TMPDIR/ogclient/* $OGLIVEDIR || raiseError access "Cannot copy files to ogLive directory."
 | |
|     umount $TMPDIR
 | |
|     # Link to default directory if it's the first ogLive.
 | |
|     if [ ! -f $INFOFILE ]; then
 | |
|         rm -f $TFTPDIR/$DEFOGLIVE $TFTPDIR/$OGCLIENT
 | |
|         ln -vfs $(basename $OGLIVEDIR) $TFTPDIR/$DEFOGLIVE
 | |
|         ln -vfs $DEFOGLIVE $TFTPDIR/$OGCLIENT
 | |
|     fi
 | |
|     # Recover or ask for a new Samba access key.
 | |
|     if [ -n "$SAMBAPASS" ]; then
 | |
|         echo -ne "$SAMBAPASS\n$SAMBAPASS\n" | $OPENGNSYS/bin/setsmbpass "$(basename $OGLIVEDIR)"
 | |
|     else
 | |
|         $OPENGNSYS/bin/setsmbpass "$(basename $OGLIVEDIR)"
 | |
|     fi
 | |
|     # Set permissions.
 | |
|     find -L $OGLIVEDIR -type d -exec chmod 755 {} \;
 | |
|     find -L $OGLIVEDIR -type f -exec chmod 644 {} \;
 | |
|     chown -R :opengnsys $OGLIVEDIR
 | |
|     # Mount SquashFS and check Rsync version.
 | |
|     OGSQFS=$OGLIVEDIR/ogclient.sqfs
 | |
|     mount -o loop,ro $OGSQFS $TMPDIR
 | |
|     # If Rsync server version > client version, link to compiled file.
 | |
|     RSYNCSERV=$(rsync --version 2>/dev/null | awk '/protocol/ {print $6}')
 | |
|     RSYNCCLNT=$(chroot $TMPDIR /usr/bin/rsync --version 2>/dev/null | awk '/protocol/ {print $6}')
 | |
|     if [ -z "$RSYNCSERV" -o ${RSYNCSERV:-0} -gt ${RSYNCCLNT:-1} ]; then
 | |
|         [ -e $OPENGNSYS/client/bin/rsync-$RSYNCSERV ] && mv -f $OPENGNSYS/client/bin/rsync-$RSYNCSERV $OPENGNSYS/client/bin/rsync
 | |
|     else
 | |
|         # Else, rename compiled file using Rsync protocol number.
 | |
|         [ -e $OPENGNSYS/client/bin/rsync ] && mv -f $OPENGNSYS/client/bin/rsync $OPENGNSYS/client/bin/rsync-$($OPENGNSYS/client/bin/rsync --version 2>/dev/null | awk '/protocol/ {print $6}')
 | |
|     fi
 | |
|     # Unmount SquashFS.
 | |
|     umount $TMPDIR
 | |
|     rmdir $TMPDIR
 | |
|     # Update JSON file.
 | |
|     addToJson "$OGLIVEDIST" "$OGLIVEKRNL" "$OGLIVEARCH" "$OGLIVEREV" "$OGLIVEDIR" "$OGLIVEFILE"
 | |
| }
 | |
| 
 | |
| # Uninstall an ogLive client.
 | |
| function uninstall() {
 | |
|     local ISO DIR INDEX DEFINDEX
 | |
|     [ $# -ne 1 ] && raiseError usage
 | |
|     [ ! -r $INFOFILE ] && raiseError access "Configuration file."
 | |
|     [ ! -w $TFTPDIR ] && raiseError access "Installation directory."
 | |
|     # Get index and directory for the entry.
 | |
|     case "$1" in
 | |
|         */*)    # Error (access to other directory).
 | |
|             raiseError access "Cannot access outside installation directory."
 | |
|             ;;
 | |
|         *.iso)  # ISO file.
 | |
|             ISO="$1"
 | |
|             # Working directory (ogLive-Distribution-KernelVersion-CodeRevision).
 | |
|             DIR="$(echo $ISO|cut -f1,3 -d-)-${ISO##*-}"; DIR=${DIR%.*}
 | |
|             INDEX=$(search $DIR 2>/dev/null)
 | |
|             ;;
 | |
|         [0-9]*) # Index.
 | |
|             INDEX=$1; DIR=$(search $INDEX 2>/dev/null)
 | |
|             ;;
 | |
|         *)      # Directory.
 | |
|             DIR="$1"; INDEX=$(search $DIR 2>/dev/null)
 | |
|             ;;
 | |
|     esac
 | |
|     DEFINDEX=$(getdefault)
 | |
|     [[ $INDEX = $DEFINDEX ]] && raiseError access "Cannot uninstall default ogLive."
 | |
|     # Remove files and delete index entry.
 | |
|     rm -vfr ${ISO:+$DOWNLOADDIR/$ISO} ${DIR:+$TFTPDIR/$DIR}    ### Remove $TFTPDIR/$DIR.old ?
 | |
|     if [ -n "$INDEX" ]; then
 | |
|         jq "del(.oglive[$INDEX])" $INFOFILE | sponge $INFOFILE
 | |
|         # Decrement default index if needed (removed < default).
 | |
|         [[ $INDEX < $DEFINDEX ]] && jq ".default=$((DEFINDEX-1))" $INFOFILE | sponge $INFOFILE
 | |
|     fi
 | |
| }
 | |
| 
 | |
| # Get default ogLive index.
 | |
| function getdefault() {
 | |
|     [ $# -ne 0 ] && raiseError usage
 | |
|     [ ! -r $INFOFILE ] && raiseError access "Configuration file."
 | |
|     # Read default parameter.
 | |
|     jq -r .default $INFOFILE || raiseError notfound "Undefined default index."
 | |
| }
 | |
| 
 | |
| # Set default ogLive index.
 | |
| function setdefault() {
 | |
|     local INDEX OGLIVEDIR
 | |
|     [ $# -ne 1 ] && raiseError usage
 | |
|     [ ! -w $INFOFILE ] && raiseError access "Configuration file."
 | |
|     INDEX=$1
 | |
|     # Check if index entry exists.
 | |
|     jq ".oglive[$INDEX]" $INFOFILE || raiseError notfound "Index \"$INDEX\"."
 | |
|     # Get ogLive directory.
 | |
|     OGLIVEDIR=$(jq -r ".oglive[$INDEX].directory" $INFOFILE) || raiseError notfound "Directory for index \"$INDEX\"."
 | |
|     # Update default parameter.
 | |
|     jq ".default=$INDEX" $INFOFILE | sponge $INFOFILE
 | |
|     # Link to default directory.
 | |
|     rm -f $TFTPDIR/$DEFOGLIVE
 | |
|     ln -vfs $(basename $OGLIVEDIR) $TFTPDIR/$DEFOGLIVE
 | |
| }
 | |
| 
 | |
| # Rebuild a lost configuration file.
 | |
| function rebuild() {
 | |
|     local i INST NF DEF
 | |
|     [ $# -ne 0 ] && raiseError usage
 | |
|     [ -f $INFOFILE ] && raiseError access "Configuration file exists."
 | |
|     INST=$(find $TFTPDIR/ -type d -name "$DEFOGLIVE-*" -a ! -name "*.old" -printf "%f\n" | sort)
 | |
|     for i in $INST; do
 | |
|         NF=$(echo $i | awk -F- '{print NF-1}')
 | |
|         case $NF in
 | |
|             1)  addToJson "" "$(echo $i|cut -f2 -d-)" "i386" "" "$i" "" ;;
 | |
|             2)  eval addToJson $(echo $i | awk -F- '{printf "\"\" %s amd64 %s %s \"\"",$2,$3,$0}') ;;
 | |
|             3)  eval addToJson $(echo $i | awk -F- '{if ($3=="i386") printf "\"\" %s %s %s %s \"\"",$2,$3,$4,$0; else printf "%s %s i386 %s %s \"\"",$2,$3,$4,$0}') ;;
 | |
|             4)  eval addToJson $(echo $i | awk -F- '{printf "%s %s %s %s %s \"\"",$2,$3,$4,$5,$0}') ;;
 | |
|         esac
 | |
|         # Check for is default oglive.
 | |
|         [ -n "$(stat -c "%N" $TFTPDIR/$DEFOGLIVE | awk '$3~/'$i'/ {print}')" ] && DEF="$i"
 | |
|     done
 | |
|     # Set default ogLive.
 | |
|     [ -n "$DEF" ] && setdefault $(search $DEF)
 | |
| }
 | |
| 
 | |
| # Assign an ISO file to a JSON entry.
 | |
| function assign() {
 | |
| local ISOFILE DIR
 | |
|     [ $# -ne 2 ] && raiseError usage
 | |
|     [ ! -w $INFOFILE ] && raiseError access "Configuration file."
 | |
|     # Check if ISO file and index directory exist.
 | |
|     ISOFILE=$DOWNLOADFILE/$1
 | |
|     [ ! -f $DOWNLOADDIR/$ISOFILE ] && raiseError notfound "ISO file \"$1\"."
 | |
|     DIR=$(search $2 2>/dev/null)
 | |
|     [ ! -d $TFTPDIR/$DIR ] && raiseError notfound "Directory for index \"$2\"."
 | |
|     # Assign ISO file to JSON entry.
 | |
|     jq ".oglive[$2].iso=\"$1\"" $INFOFILE | sponge $INFOFILE && jq ".oglive[$2]" $INFOFILE
 | |
| }
 | |
| 
 | |
| 
 | |
| # Main progrram.
 | |
| 
 | |
| # Access control.
 | |
| [ -r $OPENGNSYS/www/controlacceso.php ] && ACCESS="web"
 | |
| [ "$USER" = "root" ] && ACCESS="root"
 | |
| [ -z "$ACCESS" ] && raiseError access "Need to be root."
 | |
| # Check dependencies.
 | |
| which sponge &>/dev/null || raiseError notfound "Need to install \"moreutils\"."
 | |
| # Commands control.
 | |
| shopt -s extglob
 | |
| case "$ACCESS" in
 | |
|     root)   CMDS='+(help|version|convert|config|check|list|show|search|download|install|uninstall|get-default|set-default|rebuild|assign)' ;;
 | |
|     web)    CMDS='+(list|show|search|get-default)' ;;
 | |
| esac
 | |
| case "$1" in
 | |
|     $CMDS)  COMMAND="${1/-/}"; shift; $COMMAND "$@" ;;
 | |
|     *)      raiseError usage ;;
 | |
| esac
 | |
| 
 | |
| exit $?
 | |
| 
 | |
| 
 |