#/**
#         ogr CreatePartitions int_ndisk str_parttype:int_partsize ...
#@brief   Define el conjunto de particiones de un disco.
#@param   int_ndisk      nº de orden del disco
#@param   str_parttype   mnemónico del tipo de partición
#@param   int_partsize   tamaño de la partición (en KB)
#@return  (nada, por determinar)
#@exception OG_ERR_FORMAT     formato incorrecto.
#@exception OG_ERR_NOTFOUND   disco o particion no detectado (no es un dispositivo).
#@exception OG_ERR_OUTOFLIMIT valor fuera de rango.
#@exception OG_ERR_PARTITION  particion desconocida o no accesible.
#@attention El nº de partición se indica por el orden de los párametros \c parttype:partsize
#@attention Pueden definirse particiones vacías de tipo \c EMPTY
#@attention No puede definirse partición de cache y no se modifica si existe.
#@note    Requisitos: sfdisk, parted, partprobe, awk
#@todo    Definir atributos (arranque, oculta) y tamaños en MB, GB, etc.
#@version 0.9 - Primera versión para OpenGnSys
#@author  Ramon Gomez, ETSII Universidad de Sevilla
#@date    2009/09/09
#@version 0.91 - Corrección del redondeo del tamaño del disco.
#@author  Ramon Gomez, ETSII Universidad de Sevilla
#@date    2010/03/09
#*/ ##
# Variables locales.
local DISK PART SECTORS CYLS START SIZE TYPE CACHEPART CACHESIZE EXTSTART EXTSIZE tmpsfdisk
# Si se solicita, mostrar ayuda.
if [ "$*" == "help" ]; then
    ogr Help "$FUNCNAME" "$FUNCNAME int_ndisk str_parttype:int_partsize ..." \
           "$FUNCNAME 1 NTFS:10000000 EXT3:5000000 LINUX-SWAP:1000000"
    return
fi
# Error si no se reciben menos de 2 parámetros.
[ $# -ge 2 ] || ogr RaiseError $OG_ERR_FORMAT || return $?

# Nº total de sectores, para evitar desbordamiento
DISK=$(ogr DiskToDev "$1") || return $?
SECTORS=$(awk -v D=${DISK#/dev/} '{if ($4==D) {print $3*2}}' /proc/partitions)
CYLS=$(sfdisk -g $DISK | cut -f2 -d" ")
SECTORS=$[SECTORS/CYLS*CYLS-1]
# Se recalcula el nº de sectores del disco 1, si existe partición de caché.
CACHEPART=$(ogr FindCacheSize 2>/dev/null)
[ "$1" == "${CACHEPART% *}" ] && CACHESIZE=$(ogr GetCacheSize 2>/dev/null)
[ -n "$CACHESIZE" ] && SECTORS=$[SECTORS-$CACHESIZE*2]
ENDPART3=$(sfdisk -uS -l $DISK | awk -v P="${DISK}3" '{if ($1==P) print $3}')
# Sector de inicio de la particon (la 1ª empieza en el sector 63).
START=63
PART=1

# Desmontar todos los sistemas de archivos del disco.
ogr UnmountAll $1 2>/dev/null
shift
# Fichero temporal de entrada para "sfdisk"
tmpsfdisk=/tmp/sfdisk$$
trap "rm -f $tmpsfdisk" 1 2 3 9 15
echo "unit: sectors" >$tmpsfdisk
echo                >>$tmpsfdisk

# Generar fichero de entrada para "sfdisk" con las particiones.
while [ $# -gt 0 ]; do
    # Conservar los datos de la partición de caché.
    if [ "$1 $PART" == "$CACHEPART" -a -n "$CACHESIZE" ]; then
        echo "$DISK$PART : start=$[SECTORS+1], size=$CACHESIZE, Id=$(ogr TypeToId CACHE)" >>$tmpsfdisk
        PART=$[PART+1]
    fi
    # Leer formato de cada parámetro - Tipo:Tamaño
    TYPE="${1%%:*}"
    [ "$TYPE" != "CACHE" ] || ogr RaiseError $OG_ERR_FORMAT "$TYPE" || return $?
    SIZE="${1#*:}"
    # Convertir en sectores de 512 B.
    SIZE=$(echo $SIZE|awk '{print $0*2}')      # (solución error de sintaxis)
    [ $SIZE != 0 ] || ogr RaiseError $OG_ERR_FORMAT || return $?
    # Obtener identificador de tipo de partición.
    ID=$(ogr TypeToId "$TYPE")
    [ -n "$ID" ] || ogr RaiseError $OG_ERR_PARTITION "$TYPE" || return $?
    # Comprobar si la partición es extendida.
    if [ $TYPE == "EXTENDED" ]; then
        [ $PART -le 4 ] || ogr RaiseError $OG_ERR_OUTOFLIMIT "$MSG_PARTITION $PART: $TYPE" || return $?
        EXTSTART=$START
        EXTSIZE=$SIZE
    fi
    # Incluir particiones lógicas dentro de la partición extendida.
    if [ $PART = 5 ]; then
        [ -n "$EXTSTART" ] || ogr RaiseError $OG_ERR_FORMAT "$MSG_NOEXTENDED" || return $?
        START=$EXTSTART
        SECTORS=$[EXTSTART+EXTSIZE]
    fi
    # Generar datos para la partición.
    echo "$DISK$PART : start=$START, size=$SIZE, Id=$ID" >>$tmpsfdisk
    # Error si se supera el nº total de sectores.
    START=$[START+SIZE]
    [ $START -le $SECTORS ] || ogr RaiseError $OG_ERR_OUTOFLIMIT "$[START/2] > $[SECTORS/2]" || return $?
    PART=$[PART+1]
    shift
done
# Si no se indican las 4 particiones primarias, definirlas como vacías.
while [ $PART -le 4 ]; do
    if [ "$1 $PART" == "$CACHEPART" -a -n "$CACHESIZE" ]; then
        echo "$DISK$PART : start=$[SECTORS+1], size=$CACHESIZE, Id=$(ogr TypeToId CACHE)" >>$tmpsfdisk
    else
        echo "$DISK$PART : start=0, size=0, Id=0" >>$tmpsfdisk
    fi
    PART=$[PART+1]
done
# Si se define partición extendida sin lógicas, crear particion 5 vacía.
if [ $PART = 5 -a -n "$EXTSTART" ]; then
    echo "${DISK}5 : start=$EXTSTART, size=$EXTSIZE, Id=0" >>$tmpsfdisk
fi

# Si la tabla de particiones no es valida, volver a generarla.
[ $(parted -s $DISK print >/dev/null) ] || fdisk $DISK <<< "w"
# Definir particiones y notificar al kernel.
sfdisk -f $DISK < $tmpsfdisk 2>/dev/null && partprobe
rm -f $tmpsfdisk
