#!/usr/bin/env python

#
#     rootstrap - Quickly and easily build Linux filesystem images
#     Copyright (C) 2002 Matt Zimmerman <mdz@debian.org>
#
#     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 2 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, write to the Free Software
#     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
#

import os
import sys
import getopt
import ConfigParser

def usage(exitcode):
    sys.stderr.write("Usage: rootstrap [options] <output image file>\n")
    sys.exit(exitcode)

config = ConfigParser.ConfigParser()
config.readfp(open('/etc/rootstrap/rootstrap.conf'))
config.read(('rootstrap.conf',))

try:
    (optlist,args) = getopt.getopt(sys.argv[1:], 's:u:o:',
                                   ['image-size=', 'umlargs='])
except getopt.GetoptError:
    usage(1)

if len(args) < 1:
    usage(1)

# So that we can find tune2fs, resize2fs and such
os.environ['PATH'] += ':/sbin:/usr/sbin'

imagefile = args[0]
imagesize = config.getint('global', 'initialsize')
log = sys.stdout
umlargs = ['linux']

netif = config.get('network', 'interface')
if netif != None:
    hostaddr = config.get('network', 'host')
    transport = config.get('network', 'transport')
    umlargs.append('%s=%s,,,%s' % (netif,transport,hostaddr))

for opt,arg in optlist:
    if opt in ('-s', '--image-size'):
        imagesize = int(arg)
    elif opt in ('-o',):
        log = open(arg,"w")
        os.dup2(log.fileno(), sys.stdout.fileno())
        
    elif opt in ('u', '--umlargs'):
        umlargs.append(arg)

umlargs.extend(['con0=fd:0,fd:1',
                'con=pty',
                'ubd0=/',
                'ubd1=' + imagefile,
                'init=/usr/lib/rootstrap/builder',
                'devfs=mount',
                'rsworkdir=' + os.getcwd()])
if config.has_option('global', 'umlargs'):
    umlargs.extend(config.get('global', 'umlargs').split())

try:
    os.remove(imagefile)
except:
    pass

image = open(imagefile,'w')
image.truncate(imagesize * 1048576)
image.close()

if os.spawnvpe(os.P_WAIT,umlargs[0], umlargs, os.environ) != 0:
    sys.stderr.write("UML exited with non-zero status, aborting\n")
    sys.exit(1)

if config.has_option('global', 'freespace'):
    freespace_wanted = config.getint('global', 'freespace')
    if freespace_wanted != 0:
        tune2fs = os.popen('tune2fs -l ' + imagefile)
        freeblocks_natural = -1
        block_size = -1
        for line in tune2fs.readlines():
            if line.find(':') == -1:
                continue
            label, value = line.split(':', 1)
            if label == 'Block count':
                size_natural = int(value)
            elif label == 'Free blocks':
                freeblocks_natural = int(value)
            elif label == 'Block size':
                block_size = int(value)
                
        tune2fs.close()
                
        if block_size == -1:
            sys.stderr.write("Warning: Unable to determine block size, not resizing\n")
        else:
            print "Resizing filesystem..."
            if freeblocks_natural == -1:
                sys.stderr.write("Warning: Unable to determine free space, not resizing\n")
            else:
                freeblocks_wanted = freespace_wanted * block_size
                if freeblocks_natural != freeblocks_wanted:
                    size_wanted = size_natural - freeblocks_natural + freeblocks_wanted
                    resize2fs = os.popen('resize2fs -f %s %s 2>&1' % (imagefile, size_wanted))
                    sys.stdout.write(resize2fs.read())
                    image = open(imagefile, 'r+')
                    image.truncate(size_wanted * block_size)
                    image.close()
