#! /usr/bin/awk -f
# MOUNT-RAW - mounts partitions stored in image file
# Copyright (C) 2007  Matous Jan Fialka
#
# This program is free software: you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by the Free
# Software Foundation, either version 3 of the License, or (at your option)
# any later version.
#
# This program is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
# more details.
#
# You should have received a copy of the GNU General Public License along with
# this program. If not, see .
# NOTES:
#
# Works also when POSIXLY_CORRECT exists in environment.
BEGIN {
        DEBUG = 1
        # DEBUG = 0
        FTEST = "/usr/bin/test"
        FDISK = "/sbin/fdisk"
        MOUNT = "/bin/mount"
        USAGE = USAGE "mountraw.awk "
        USAGE = USAGE "   "
        USAGE = USAGE "[  ]"
        ERROR[01] = "invalid number of arguments; at least 3 expected"
        ERROR[02] = "invalid run-time user; only root can do that"
        ERROR[03] = "target does not exist"
        ERROR[04] = "target can not be read"
        ERROR[05] = "target can not be executed"
        ERROR[06] = "target is not a directory"
        ERROR[07] = "invalid partition number given; use decimal number"
        ERROR[08] = "invalid mount options given; see mount(8) options"
        ERROR[09] = "unable to determine sector size"
        ERROR[10] = "unable to determine partition starting sector"
        ERROR[11] = "unable to perform write operations; turn off debugging"
        EMPTY = ""
}
function error(code, message)
{
        print("Error: " ERROR[code] " " message) > "/dev/stderr"
        exit(code)
}
function usage()
{
        print("Usage: " USAGE)
}
function debug(message)
{
        print("Debug: " message)
}
function teste(filename)
{
        if (system(FTEST " -e " filename " &> /dev/null"))
                error(3, filename)
        return(1)
}
function testr(filename)
{
        if (system(FTEST " -r " filename " &> /dev/null"))
                error(4, filename)
        return(1)
}
function testx(filename)
{
        if (system(FTEST " -x " filename " &> /dev/null"))
                error(4, filename)
        return(1)
}
function testd(filename)
{
        if (system(FTEST " -d " filename " &> /dev/null"))
                error(6, filename)
        return(1)
}
BEGIN {
        if (ARGC < 4) {
                usage()
                error(1, EMPTY)
        }
        if (PROCINFO["euid"] != 0)
                error(2, EMPTY)
        teste(FTEST)	# sort of tricky test of test
        testx(FTEST)
        teste(FDISK)
        testx(FDISK)
        teste(MOUNT)
        testx(MOUNT)
        testr(image_file  = ARGV[1])
        testd(mount_point = ARGV[3])
        if (ARGV[2] !~ /^[0-9]+$/)
                error(7, ENPTY)
        else
                partition_number = ARGV[2]
        if (ARGV[4] && ARGV[4] !~ /^[a-zA-Z0-9,=]+$/)
                error(8, EMPTY)
        else
                mount_options = ARGV[4]
        FDISK = FDISK " 2> /dev/null -u -l " image_file
        sector_size = starting_sector = 0
	match_sector_size = "^Units = sectors of 1 \\* [0-9]+ = [0-9]+ bytes$"
	match_starting_sector = "^" image_file partition_number "$"
        while (FDISK | getline) {
		if ((!sector_size) && $0 ~ match_sector_size) {
                        sector_size = $7
                        continue
                }
		if ((!starting_sector) && $1 ~ match_starting_sector) {
                        if ($2 ~ /^[0-9]+$/) {
                                starting_sector = $2
                                break
                        }
                        if ($2 ~ "^*$" && $3 ~ /^[0-9]+$/) {
                                starting_sector = $3
                                break
                        }
                        break
                }
        }
        close(command_fdisk)
        if (!sector_size)
                error(9, EMPTY)
        if (!starting_sector)
                error(10, EMPTY)
        offset = sprintf("%d", starting_sector * sector_size)
        MOUNT = MOUNT " -o loop,offset=" offset
        MOUNT = MOUNT (mount_options ? "," mount_options : "")
        MOUNT = MOUNT " " image_file " " mount_point
        if (DEBUG) {
                debug(MOUNT)
                error(11, EMPTY)
        }
        exit(system(MOUNT))
}