# shfs-helper: get 3
LC_TIME=C
export LC_TIME
# SHELL_MAX_BYTES, when above zero, caps both the announced size and what is
# sent, so a preview does not drag a whole file across the wire. The count is
# taken from the file itself, never from a pipe: the announced size and the
# bytes that follow it must agree or the channel goes out of step.
shell_get_perl ()
{
FILENAME=$1
OFFSET=$2
MAXB=$3
perl -e '
use strict;
use POSIX;
use Fcntl;
my $filename = $ARGV[0];
my $pos = $ARGV[1];
my $max = $ARGV[2];
my $content;
my ($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$size,$atime,$mtime,$ctime,$blksize,$blocks) = lstat("$filename");
my $n;
my $left;
if (-f $filename && open IFILE,$filename) {
    if ($size<$pos) {
        $size=0;
    } else {
        $size-=$pos;
    }
    if ($max>0 && $size>$max) {
        $size=$max;
    }
    printf("$size\n");
    printf("### 100\n");
    seek (IFILE, $pos, 0);
    $left=$size;
    while ($left>0 && ($n = read(IFILE,$content,$blksize<$left ? $blksize : $left)) != 0) {
        print $content;
        $left-=$n;
    }
    close IFILE;
    printf("### 200\n");
} else {
    printf("### 500\n");
}
exit 0
' "${FILENAME}" $OFFSET $MAXB
}

shell_get_tail ()
{
FILENAME=$1
OFFSET=$2
MAXB=$3
LC_TIME=C
export LC_TIME
if dd if="${FILENAME}" of=/dev/null bs=1 count=1 2>/dev/null ; then
    file_size=`ls -ln "${FILENAME}" 2>/dev/null | (
       read p l u g s r
       echo $s
    )`
    if [ $OFFSET -gt 0 ]; then
        file_size=`expr $file_size - $OFFSET`
    fi
    if [ $file_size -lt 0 ]; then
        file_size=0
    fi
    if [ $MAXB -gt 0 ] && [ $file_size -gt $MAXB ]; then
        file_size=$MAXB
    fi
    echo $file_size
    echo "### 100"
    if [ $file_size -eq 0 ]; then
        :
    elif [ $MAXB -gt 0 ] && [ $OFFSET -eq 0 ]; then
        dd if="${FILENAME}" bs=$file_size count=1 2>/dev/null
    elif [ $MAXB -gt 0 ]; then
        dd if="${FILENAME}" bs=1 skip=$OFFSET count=$file_size 2>/dev/null
    elif [ $OFFSET -gt 0 ]; then
        tail -c +`expr $OFFSET + 1` "${FILENAME}"
    else
        cat "${FILENAME}"
    fi
    echo "### 200"
else
    echo "### 500"
fi
}

shell_get_dd ()
{
FILENAME=$1
OFFSET=$2
MAXB=$3
LC_TIME=C
export LC_TIME
if dd if="${FILENAME}" of=/dev/null bs=1 count=1 2>/dev/null ; then
    file_size=`ls -ln "${FILENAME}" 2>/dev/null | (
       read p l u g s r
       echo $s
    )`
    file_size=`expr $file_size - $OFFSET`
    if [ $file_size -lt 0 ]; then
        file_size=0
    fi
    if [ $MAXB -gt 0 ] && [ $file_size -gt $MAXB ]; then
        file_size=$MAXB
    fi
    echo $file_size
    echo "### 100"
    if [ $file_size -eq 0 ]; then
        :
    elif [ $MAXB -gt 0 ] && [ $OFFSET -eq 0 ]; then
        dd if="${FILENAME}" bs=$file_size count=1 2>/dev/null
    elif [ $MAXB -gt 0 ]; then
        dd if="${FILENAME}" bs=1 skip=$OFFSET count=$file_size 2>/dev/null
    elif [ $OFFSET -gt 0 ]; then
        dd skip=$OFFSET ibs=1 if="${FILENAME}" 2>/dev/null
    else
        cat "${FILENAME}"
    fi
    echo "### 200"
else
    echo "### 500"
fi
}

if [ -z "${SHELL_MAX_BYTES}" ]; then
    SHELL_MAX_BYTES=0
fi

if [ -n "${SHELL_HAVE_PERL}" ]; then
    shell_get_perl "/${SHELL_FILENAME}" ${SHELL_START_OFFSET} ${SHELL_MAX_BYTES}
elif [ -n "${SHELL_HAVE_TAIL}" ]; then
    shell_get_tail "/${SHELL_FILENAME}" ${SHELL_START_OFFSET} ${SHELL_MAX_BYTES}
else
    shell_get_dd "/${SHELL_FILENAME}" ${SHELL_START_OFFSET} ${SHELL_MAX_BYTES}
fi
