Subversion Repositories HelenOS

Compare Revisions

No changes between revisions

Ignore whitespace Rev 3887 → Rev 3888

/tags/0.4.0/tools/xtui.py
0,0 → 1,260
#
# Copyright (c) 2009 Martin Decky
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
#
# - Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# - Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
# - The name of the author may not be used to endorse or promote products
# derived from this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
"""
Text User Interface wrapper
"""
 
import sys
import os
 
def call_dlg(dlgcmd, *args, **kw):
"Wrapper for calling 'dialog' program"
indesc, outdesc = os.pipe()
pid = os.fork()
if (not pid):
os.close(2)
os.dup(outdesc)
os.close(indesc)
dlgargs = [dlgcmd]
for key, val in kw.items():
dlgargs.append('--' + key)
dlgargs.append(val)
dlgargs += args
os.execlp(dlgcmd, *dlgargs)
os.close(outdesc)
try:
errout = os.fdopen(indesc, 'r')
data = errout.read()
errout.close()
pid, status = os.wait()
except:
# Reset terminal
os.system('reset')
raise
if (not os.WIFEXITED(status)):
# Reset terminal
os.system('reset')
raise EOFError
status = os.WEXITSTATUS(status)
if (status == 255):
raise EOFError
return (status, data)
 
try:
import snack
newt = True
dialog = False
except ImportError:
newt = False
dlgcmd = os.environ.get('DIALOG', 'dialog')
if (call_dlg(dlgcmd, '--print-maxsize')[0] != 0):
dialog = False
else:
dialog = True
 
width_extra = 13
height_extra = 11
 
def width_fix(screen, width):
"Correct width to screen size"
if (width + width_extra > screen.width):
width = screen.width - width_extra
if (width <= 0):
width = screen.width
return width
 
def height_fix(screen, height):
"Correct height to screen size"
if (height + height_extra > screen.height):
height = screen.height - height_extra
if (height <= 0):
height = screen.height
return height
 
def screen_init():
"Initialize the screen"
if (newt):
return snack.SnackScreen()
return None
 
def screen_done(screen):
"Cleanup the screen"
if (newt):
screen.finish()
 
def choice_window(screen, title, text, options, position):
"Create options menu"
maxopt = 0
for option in options:
length = len(option)
if (length > maxopt):
maxopt = length
width = maxopt
height = len(options)
if (newt):
width = width_fix(screen, width + width_extra)
height = height_fix(screen, height)
if (height > 3):
large = True
else:
large = False
buttonbar = snack.ButtonBar(screen, ('Done', 'Cancel'))
textbox = snack.TextboxReflowed(width, text)
listbox = snack.Listbox(height, scroll = large, returnExit = 1)
cnt = 0
for option in options:
listbox.append(option, cnt)
cnt += 1
if (position != None):
listbox.setCurrent(position)
grid = snack.GridForm(screen, title, 1, 3)
grid.add(textbox, 0, 0)
grid.add(listbox, 0, 1, padding = (0, 1, 0, 1))
grid.add(buttonbar, 0, 2, growx = 1)
retval = grid.runOnce()
return (buttonbar.buttonPressed(retval), listbox.current())
elif (dialog):
if (width < 35):
width = 35
args = []
cnt = 0
for option in options:
args.append(str(cnt + 1))
args.append(option)
cnt += 1
kw = {}
if (position != None):
kw['default-item'] = str(position + 1)
status, data = call_dlg(dlgcmd, '--title', title, '--extra-button', '--extra-label', 'Done', '--menu', text, str(height + height_extra), str(width + width_extra), str(cnt), *args, **kw)
if (status == 1):
return ('cancel', None)
try:
choice = int(data) - 1
except ValueError:
return ('cancel', None)
if (status == 0):
return (None, choice)
return ('done', choice)
sys.stdout.write("\n *** %s *** \n%s\n\n" % (title, text))
maxcnt = len(str(len(options)))
cnt = 0
for option in options:
sys.stdout.write("%*s. %s\n" % (maxcnt, cnt + 1, option))
cnt += 1
sys.stdout.write("\n%*s. Done\n" % (maxcnt, '0'))
sys.stdout.write("%*s. Quit\n\n" % (maxcnt, 'q'))
while True:
if (position != None):
sys.stdout.write("Selection[%s]: " % str(position + 1))
else:
sys.stdout.write("Selection: ")
inp = sys.stdin.readline()
if (not inp):
raise EOFError
if (not inp.strip()):
if (position != None):
return (None, position)
continue
if (inp.strip() == 'q'):
return ('cancel', None)
try:
choice = int(inp.strip())
except ValueError:
continue
if (choice == 0):
return ('done', 0)
if (choice < 1) or (choice > len(options)):
continue
return (None, choice - 1)
 
def error_dialog(screen, title, msg):
"Print error dialog"
width = len(msg)
if (newt):
width = width_fix(screen, width)
buttonbar = snack.ButtonBar(screen, ['Ok'])
textbox = snack.TextboxReflowed(width, msg)
grid = snack.GridForm(screen, title, 1, 2)
grid.add(textbox, 0, 0, padding = (0, 0, 0, 1))
grid.add(buttonbar, 0, 1, growx = 1)
grid.runOnce()
elif (dialog):
call_dlg(dlgcmd, '--title', title, '--msgbox', msg, '6', str(width + width_extra))
sys.stdout.write("\n%s: %s\n" % (title, msg))
/tags/0.4.0/tools/config.py
0,0 → 1,353
#!/usr/bin/env python
#
# Copyright (c) 2006 Ondrej Palkovsky
# Copyright (c) 2009 Martin Decky
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
#
# - Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# - Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
# - The name of the author may not be used to endorse or promote products
# derived from this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
"""
HelenOS configuration system
"""
import sys
import os
import re
import commands
import xtui
 
INPUT = sys.argv[1]
OUTPUT = 'Makefile.config'
 
def read_defaults(fname, defaults):
"Read saved values from last configuration run"
inf = file(fname,'r')
for line in inf:
res = re.match(r'^(?:#!# )?([^#]\w*)\s*=\s*(.*?)\s*$', line)
if (res):
defaults[res.group(1)] = res.group(2)
inf.close()
 
def check_condition(text, defaults, ask_names):
"Check for condition"
ctype = 'cnf'
if ((')|' in text) or ('|(' in text)):
ctype = 'dnf'
if (ctype == 'cnf'):
conds = text.split('&')
else:
conds = text.split('|')
for cond in conds:
if (cond.startswith('(')) and (cond.endswith(')')):
cond = cond[1:-1]
inside = check_inside(cond, defaults, ctype)
if (ctype == 'cnf') and (not inside):
return False
if (ctype == 'dnf') and (inside):
return True
if (ctype == 'cnf'):
return True
return False
 
def check_inside(text, defaults, ctype):
"Check that the condition specified on input line is True (only CNF is supported)"
if (ctype == 'cnf'):
conds = text.split('|')
else:
conds = text.split('&')
for cond in conds:
res = re.match(r'^(.*?)(!?=)(.*)$', cond)
if (not res):
raise RuntimeError("Invalid condition: %s" % cond)
condname = res.group(1)
oper = res.group(2)
condval = res.group(3)
if (not defaults.has_key(condname)):
varval = ''
else:
varval = defaults[condname]
if (ctype == 'cnf'):
if (oper == '=') and (condval == varval):
return True
if (oper == '!=') and (condval != varval):
return True
else:
if (oper == '=') and (condval != varval):
return False
if (oper == '!=') and (condval == varval):
return False
if (ctype == 'cnf'):
return False
return True
 
def parse_config(fname, ask_names):
"Parse configuration file"
inf = file(fname, 'r')
name = ''
choices = []
for line in inf:
if (line.startswith('!')):
# Ask a question
res = re.search(r'!\s*(?:\[(.*?)\])?\s*([^\s]+)\s*\((.*)\)\s*$', line)
if (not res):
raise RuntimeError("Weird line: %s" % line)
cond = res.group(1)
varname = res.group(2)
vartype = res.group(3)
ask_names.append((varname, vartype, name, choices, cond))
name = ''
choices = []
continue
if (line.startswith('@')):
# Add new line into the 'choices' array
res = re.match(r'@\s*(?:\[(.*?)\])?\s*"(.*?)"\s*(.*)$', line)
if not res:
raise RuntimeError("Bad line: %s" % line)
choices.append((res.group(2), res.group(3)))
continue
if (line.startswith('%')):
# Name of the option
name = line[1:].strip()
continue
if ((line.startswith('#')) or (line == '\n')):
# Comment or empty line
continue
raise RuntimeError("Unknown syntax: %s" % line)
inf.close()
 
def yes_no(default):
"Return '*' if yes, ' ' if no"
if (default == 'y'):
return '*'
return ' '
 
def subchoice(screen, name, choices, default):
"Return choice of choices"
maxkey = 0
for key, val in choices:
length = len(key)
if (length > maxkey):
maxkey = length
options = []
position = None
cnt = 0
for key, val in choices:
if ((default) and (key == default)):
position = cnt
options.append(" %-*s %s " % (maxkey, key, val))
cnt += 1
(button, value) = xtui.choice_window(screen, name, 'Choose value', options, position)
if (button == 'cancel'):
return None
return choices[value][0]
 
def check_choices(defaults, ask_names):
"Check whether all accessible variables have a default"
for varname, vartype, name, choices, cond in ask_names:
if ((cond) and (not check_condition(cond, defaults, ask_names))):
continue
if (not defaults.has_key(varname)):
return False
return True
 
def create_output(fname, defaults, ask_names):
"Create output configuration"
outf = file(fname, 'w')
outf.write('#########################################\n')
outf.write('## AUTO-GENERATED FILE, DO NOT EDIT!!! ##\n')
outf.write('#########################################\n\n')
for varname, vartype, name, choices, cond in ask_names:
if ((cond) and (not check_condition(cond, defaults, ask_names))):
continue
if (not defaults.has_key(varname)):
default = ''
else:
default = defaults[varname]
outf.write('# %s\n%s = %s\n\n' % (name, varname, default))
outf.write('REVISION = %s\n' % commands.getoutput('svnversion . 2> /dev/null'))
outf.write('TIMESTAMP = %s\n' % commands.getoutput('date "+%Y-%m-%d %H:%M:%S"'))
outf.close()
 
def main():
defaults = {}
ask_names = []
# Parse configuration file
parse_config(INPUT, ask_names)
# Read defaults from previous run
if os.path.exists(OUTPUT):
read_defaults(OUTPUT, defaults)
# Default mode: only check defaults and regenerate configuration
if ((len(sys.argv) >= 3) and (sys.argv[2] == 'default')):
if (check_choices(defaults, ask_names)):
create_output(OUTPUT, defaults, ask_names)
return 0
# Check mode: only check defaults
if ((len(sys.argv) >= 3) and (sys.argv[2] == 'check')):
if (check_choices(defaults, ask_names)):
return 0
return 1
screen = xtui.screen_init()
try:
selname = None
while True:
options = []
opt2row = {}
position = None
cnt = 0
for varname, vartype, name, choices, cond in ask_names:
if ((cond) and (not check_condition(cond, defaults, ask_names))):
continue
if (varname == selname):
position = cnt
if (not defaults.has_key(varname)):
default = None
else:
default = defaults[varname]
if (vartype == 'choice'):
# Check if the default is an acceptable value
if ((default) and (not default in [choice[0] for choice in choices])):
default = None
defaults.pop(varname)
# If there is just one option, use it
if (len(choices) == 1):
default = choices[0][0]
defaults[varname] = default
options.append(" %s [%s] --> " % (name, default))
elif (vartype == 'y/n'):
if (default == None):
default = 'y'
defaults[varname] = default
options.append(" <%s> %s " % (yes_no(default), name))
elif (vartype == 'n/y'):
if (default == None):
default = 'n'
defaults[varname] = default
options.append(" <%s> %s " % (yes_no(default), name))
else:
raise RuntimeError("Unknown variable type: %s" % vartype)
opt2row[cnt] = (varname, vartype, name, choices)
cnt += 1
(button, value) = xtui.choice_window(screen, 'HelenOS configuration', 'Choose configuration option', options, position)
if (button == 'cancel'):
return 'Configuration canceled'
if (not opt2row.has_key(value)):
raise RuntimeError("Error selecting value: %s" % value)
(selname, seltype, name, choices) = opt2row[value]
if (not defaults.has_key(selname)):
default = None
else:
default = defaults[selname]
if (button == 'done'):
if (check_choices(defaults, ask_names)):
break
else:
xtui.error_dialog(screen, 'Error', 'Some options have still undefined values.')
continue
if (seltype == 'choice'):
defaults[selname] = subchoice(screen, name, choices, default)
elif ((seltype == 'y/n') or (seltype == 'n/y')):
if (defaults[selname] == 'y'):
defaults[selname] = 'n'
else:
defaults[selname] = 'y'
finally:
xtui.screen_done(screen)
create_output(OUTPUT, defaults, ask_names)
return 0
 
if __name__ == '__main__':
sys.exit(main())
Property changes:
Added: svn:executable
+*
\ No newline at end of property
/tags/0.4.0/tools/mkfat.py
0,0 → 1,450
#!/usr/bin/env python
#
# Copyright (c) 2008 Martin Decky
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
#
# - Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# - Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
# - The name of the author may not be used to endorse or promote products
# derived from this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
"""
FAT creator
"""
 
import sys
import os
import random
import xstruct
import array
 
exclude_names = set(['.svn'])
 
def align_up(size, alignment):
"Return size aligned up to alignment"
if (size % alignment == 0):
return size
return (((size / alignment) + 1) * alignment)
 
def subtree_size(root, cluster_size, dirent_size):
"Recursive directory walk and calculate size"
size = 0
files = 2
for name in os.listdir(root):
canon = os.path.join(root, name)
if (os.path.isfile(canon) and (not name in exclude_names)):
size += align_up(os.path.getsize(canon), cluster_size)
files += 1
if (os.path.isdir(canon) and (not name in exclude_names)):
size += subtree_size(canon, cluster_size, dirent_size)
files += 1
return size + align_up(files * dirent_size, cluster_size)
 
def root_entries(root):
"Return number of root directory entries"
return len(os.listdir(root))
 
def write_file(path, outf, cluster_size, data_start, fat, reserved_clusters):
"Store the contents of a file"
size = os.path.getsize(path)
prev = -1
first = 0
inf = file(path, "r")
rd = 0;
while (rd < size):
empty_cluster = fat.index(0)
fat[empty_cluster] = 0xffff
if (prev != -1):
fat[prev] = empty_cluster
else:
first = empty_cluster
prev = empty_cluster
data = inf.read(cluster_size);
outf.seek(data_start + (empty_cluster - reserved_clusters) * cluster_size)
outf.write(data)
rd += len(data)
inf.close()
return first, size
 
def write_directory(directory, outf, cluster_size, data_start, fat, reserved_clusters, dirent_size, empty_cluster):
"Store the contents of a directory"
length = len(directory)
size = length * dirent_size
prev = -1
first = 0
i = 0
rd = 0;
while (rd < size):
if (prev != -1):
empty_cluster = fat.index(0)
fat[empty_cluster] = 0xffff
fat[prev] = empty_cluster
else:
first = empty_cluster
prev = empty_cluster
data = ''
data_len = 0
while ((i < length) and (data_len < cluster_size)):
if (i == 0):
directory[i].cluster = empty_cluster
data += directory[i].pack()
data_len += dirent_size
i += 1
outf.seek(data_start + (empty_cluster - reserved_clusters) * cluster_size)
outf.write(data)
rd += len(data)
return first, size
 
DIR_ENTRY = """little:
char name[8] /* file name */
char ext[3] /* file extension */
uint8_t attr /* file attributes */
padding[1] /* reserved for NT */
uint8_t ctime_fine /* create time (fine resolution) */
uint16_t ctime /* create time */
uint16_t cdate /* create date */
uint16_t adate /* access date */
padding[2] /* EA-index */
uint16_t mtime /* modification time */
uint16_t mdate /* modification date */
uint16_t cluster /* first cluster */
uint32_t size /* file size */
"""
 
DOT_DIR_ENTRY = """little:
uint8_t signature /* 0x2e signature */
char name[7] /* empty */
char ext[3] /* empty */
uint8_t attr /* file attributes */
padding[1] /* reserved for NT */
uint8_t ctime_fine /* create time (fine resolution) */
uint16_t ctime /* create time */
uint16_t cdate /* create date */
uint16_t adate /* access date */
padding[2] /* EA-index */
uint16_t mtime /* modification time */
uint16_t mdate /* modification date */
uint16_t cluster /* first cluster */
uint32_t size /* file size */
"""
 
DOTDOT_DIR_ENTRY = """little:
uint8_t signature[2] /* 0x2e signature */
char name[6] /* empty */
char ext[3] /* empty */
uint8_t attr /* file attributes */
padding[1] /* reserved for NT */
uint8_t ctime_fine /* create time (fine resolution) */
uint16_t ctime /* create time */
uint16_t cdate /* create date */
uint16_t adate /* access date */
padding[2] /* EA-index */
uint16_t mtime /* modification time */
uint16_t mdate /* modification date */
uint16_t cluster /* first cluster */
uint32_t size /* file size */
"""
 
def mangle_fname(name):
# FIXME: filter illegal characters
parts = name.split('.')
if (len(parts) > 0):
fname = parts[0]
else:
fname = ''
return (fname + ' ').upper()[0:8]
 
def mangle_ext(name):
# FIXME: filter illegal characters
parts = name.split('.')
if (len(parts) > 1):
ext = parts[1]
else:
ext = ''
return (ext + ' ').upper()[0:3]
 
def create_dirent(name, directory, cluster, size):
dir_entry = xstruct.create(DIR_ENTRY)
dir_entry.name = mangle_fname(name)
dir_entry.ext = mangle_ext(name)
if (directory):
dir_entry.attr = 0x30
else:
dir_entry.attr = 0x20
dir_entry.ctime_fine = 0 # FIXME
dir_entry.ctime = 0 # FIXME
dir_entry.cdate = 0 # FIXME
dir_entry.adate = 0 # FIXME
dir_entry.mtime = 0 # FIXME
dir_entry.mdate = 0 # FIXME
dir_entry.cluster = cluster
if (directory):
dir_entry.size = 0
else:
dir_entry.size = size
return dir_entry
 
def create_dot_dirent(empty_cluster):
dir_entry = xstruct.create(DOT_DIR_ENTRY)
dir_entry.signature = 0x2e
dir_entry.name = ' '
dir_entry.ext = ' '
dir_entry.attr = 0x10
dir_entry.ctime_fine = 0 # FIXME
dir_entry.ctime = 0 # FIXME
dir_entry.cdate = 0 # FIXME
dir_entry.adate = 0 # FIXME
dir_entry.mtime = 0 # FIXME
dir_entry.mdate = 0 # FIXME
dir_entry.cluster = empty_cluster
dir_entry.size = 0
return dir_entry
 
def create_dotdot_dirent(parent_cluster):
dir_entry = xstruct.create(DOTDOT_DIR_ENTRY)
dir_entry.signature = [0x2e, 0x2e]
dir_entry.name = ' '
dir_entry.ext = ' '
dir_entry.attr = 0x10
dir_entry.ctime_fine = 0 # FIXME
dir_entry.ctime = 0 # FIXME
dir_entry.cdate = 0 # FIXME
dir_entry.adate = 0 # FIXME
dir_entry.mtime = 0 # FIXME
dir_entry.mdate = 0 # FIXME
dir_entry.cluster = parent_cluster
dir_entry.size = 0
return dir_entry
 
def recursion(head, root, outf, cluster_size, root_start, data_start, fat, reserved_clusters, dirent_size, parent_cluster):
"Recursive directory walk"
directory = []
if (not head):
# Directory cluster preallocation
empty_cluster = fat.index(0)
fat[empty_cluster] = 0xffff
directory.append(create_dot_dirent(empty_cluster))
directory.append(create_dotdot_dirent(parent_cluster))
else:
empty_cluster = 0
for name in os.listdir(root):
canon = os.path.join(root, name)
if (os.path.isfile(canon) and (not name in exclude_names)):
rv = write_file(canon, outf, cluster_size, data_start, fat, reserved_clusters)
directory.append(create_dirent(name, False, rv[0], rv[1]))
if (os.path.isdir(canon) and (not name in exclude_names)):
rv = recursion(False, canon, outf, cluster_size, root_start, data_start, fat, reserved_clusters, dirent_size, empty_cluster)
directory.append(create_dirent(name, True, rv[0], rv[1]))
if (head):
outf.seek(root_start)
for dir_entry in directory:
outf.write(dir_entry.pack())
else:
return write_directory(directory, outf, cluster_size, data_start, fat, reserved_clusters, dirent_size, empty_cluster)
 
BOOT_SECTOR = """little:
uint8_t jmp[3] /* jump instruction */
char oem[8] /* OEM string */
uint16_t sector /* bytes per sector */
uint8_t cluster /* sectors per cluster */
uint16_t reserved /* reserved sectors */
uint8_t fats /* number of FATs */
uint16_t rootdir /* root directory entries */
uint16_t sectors /* total number of sectors */
uint8_t descriptor /* media descriptor */
uint16_t fat_sectors /* sectors per single FAT */
uint16_t track_sectors /* sectors per track */
uint16_t heads /* number of heads */
uint32_t hidden /* hidden sectors */
uint32_t sectors_big /* total number of sectors (if sectors == 0) */
/* Extended BIOS Parameter Block */
uint8_t drive /* physical drive number */
padding[1] /* reserved (current head) */
uint8_t extboot_signature /* extended boot signature */
uint32_t serial /* serial number */
char label[11] /* volume label */
char fstype[8] /* filesystem type */
padding[448] /* boot code */
uint8_t boot_signature[2] /* boot signature */
"""
 
EMPTY_SECTOR = """little:
padding[512] /* empty sector data */
"""
 
FAT_ENTRY = """little:
uint16_t next /* FAT16 entry */
"""
 
def usage(prname):
"Print usage syntax"
print prname + " <PATH> <IMAGE>"
 
def main():
if (len(sys.argv) < 3):
usage(sys.argv[0])
return
path = os.path.abspath(sys.argv[1])
if (not os.path.isdir(path)):
print "<PATH> must be a directory"
return
fat16_clusters = 4096
sector_size = 512
cluster_size = 4096
dirent_size = 32
fatent_size = 2
fat_count = 2
reserved_clusters = 2
# Make sure the filesystem is large enought for FAT16
size = subtree_size(path, cluster_size, dirent_size) + reserved_clusters * cluster_size
while (size / cluster_size < fat16_clusters):
if (cluster_size > sector_size):
cluster_size /= 2
size = subtree_size(path, cluster_size, dirent_size) + reserved_clusters * cluster_size
else:
size = fat16_clusters * cluster_size + reserved_clusters * cluster_size
root_size = align_up(root_entries(path) * dirent_size, cluster_size)
fat_size = align_up(align_up(size, cluster_size) / cluster_size * fatent_size, sector_size)
sectors = (cluster_size + fat_count * fat_size + root_size + size) / sector_size
root_start = cluster_size + fat_count * fat_size
data_start = root_start + root_size
outf = file(sys.argv[2], "w")
boot_sector = xstruct.create(BOOT_SECTOR)
boot_sector.jmp = [0xEB, 0x3C, 0x90]
boot_sector.oem = "MSDOS5.0"
boot_sector.sector = sector_size
boot_sector.cluster = cluster_size / sector_size
boot_sector.reserved = cluster_size / sector_size
boot_sector.fats = fat_count
boot_sector.rootdir = root_size / dirent_size
if (sectors <= 65535):
boot_sector.sectors = sectors
else:
boot_sector.sectors = 0
boot_sector.descriptor = 0xF8
boot_sector.fat_sectors = fat_size / sector_size
boot_sector.track_sectors = 63
boot_sector.heads = 6
boot_sector.hidden = 0
if (sectors > 65535):
boot_sector.sectors_big = sectors
else:
boot_sector.sectors_big = 0
boot_sector.drive = 0x80
boot_sector.extboot_signature = 0x29
boot_sector.serial = random.randint(0, 0x7fffffff)
boot_sector.label = "HELENOS"
boot_sector.fstype = "FAT16 "
boot_sector.boot_signature = [0x55, 0xAA]
outf.write(boot_sector.pack())
empty_sector = xstruct.create(EMPTY_SECTOR)
# Reserved sectors
for i in range(1, cluster_size / sector_size):
outf.write(empty_sector.pack())
# FAT tables
for i in range(0, fat_count):
for j in range(0, fat_size / sector_size):
outf.write(empty_sector.pack())
# Root directory
for i in range(0, root_size / sector_size):
outf.write(empty_sector.pack())
# Data
for i in range(0, size / sector_size):
outf.write(empty_sector.pack())
fat = array.array('L', [0] * (fat_size / fatent_size))
fat[0] = 0xfff8
fat[1] = 0xffff
recursion(True, path, outf, cluster_size, root_start, data_start, fat, reserved_clusters, dirent_size, 0)
# Store FAT
fat_entry = xstruct.create(FAT_ENTRY)
for i in range(0, fat_count):
outf.seek(cluster_size + i * fat_size)
for j in range(0, fat_size / fatent_size):
fat_entry.next = fat[j]
outf.write(fat_entry.pack())
outf.close()
if __name__ == '__main__':
main()
Property changes:
Added: svn:executable
+*
\ No newline at end of property
/tags/0.4.0/tools/mktmpfs.py
0,0 → 1,138
#!/usr/bin/env python
#
# Copyright (c) 2008 Martin Decky
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
#
# - Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# - Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
# - The name of the author may not be used to endorse or promote products
# derived from this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
"""
TMPFS creator
"""
 
import sys
import os
import xstruct
 
exclude_names = set(['.svn'])
 
HEADER = """little:
char tag[5] /* 'TMPFS' */
"""
 
DENTRY_NONE = """little:
uint8_t kind /* NONE */
uint32_t fname_len /* 0 */
"""
 
DENTRY_FILE = """little:
uint8_t kind /* FILE */
uint32_t fname_len /* filename length */
char fname[%d] /* filename */
uint32_t flen /* file length */
"""
 
DENTRY_DIRECTORY = """little:
uint8_t kind /* DIRECTORY */
uint32_t fname_len /* filename length */
char fname[%d] /* filename */
"""
 
TMPFS_NONE = 0
TMPFS_FILE = 1
TMPFS_DIRECTORY = 2
 
def usage(prname):
"Print usage syntax"
print prname + " <PATH> <IMAGE>"
 
def recursion(root, outf):
"Recursive directory walk"
for name in os.listdir(root):
canon = os.path.join(root, name)
if (os.path.isfile(canon) and (not name in exclude_names)):
size = os.path.getsize(canon)
dentry = xstruct.create(DENTRY_FILE % len(name))
dentry.kind = TMPFS_FILE
dentry.fname_len = len(name)
dentry.fname = name
dentry.flen = size
outf.write(dentry.pack())
inf = file(canon, "r")
rd = 0;
while (rd < size):
data = inf.read(4096);
outf.write(data)
rd += len(data)
inf.close()
if (os.path.isdir(canon) and (not name in exclude_names)):
dentry = xstruct.create(DENTRY_DIRECTORY % len(name))
dentry.kind = TMPFS_DIRECTORY
dentry.fname_len = len(name)
dentry.fname = name
outf.write(dentry.pack())
recursion(canon, outf)
dentry = xstruct.create(DENTRY_NONE)
dentry.kind = TMPFS_NONE
dentry.fname_len = 0
outf.write(dentry.pack())
 
def main():
if (len(sys.argv) < 3):
usage(sys.argv[0])
return
path = os.path.abspath(sys.argv[1])
if (not os.path.isdir(path)):
print "<PATH> must be a directory"
return
outf = file(sys.argv[2], "w")
header = xstruct.create(HEADER)
header.tag = "TMPFS"
outf.write(header.pack())
recursion(path, outf)
dentry = xstruct.create(DENTRY_NONE)
dentry.kind = TMPFS_NONE
dentry.fname_len = 0
outf.write(dentry.pack())
outf.close()
if __name__ == '__main__':
main()
Property changes:
Added: svn:executable
+*
\ No newline at end of property
/tags/0.4.0/tools/xstruct.py
0,0 → 1,110
#
# Copyright (c) 2008 Martin Decky
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
#
# - Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# - Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
# - The name of the author may not be used to endorse or promote products
# derived from this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
"""
Convert descriptive structure definitions to structure object
"""
 
import struct
 
class Struct:
def size(self):
return struct.calcsize(self._format_)
def pack(self):
args = []
for variable in self._args_:
if (isinstance(self.__dict__[variable], list)):
for item in self.__dict__[variable]:
args.append(item)
else:
args.append(self.__dict__[variable])
return struct.pack(self._format_, *args)
 
def create(definition):
"Create structure object"
tokens = definition.split(None)
# Initial byte order tag
format = {
"little:": lambda: "<",
"big:": lambda: ">",
"network:": lambda: "!"
}[tokens[0]]()
inst = Struct()
args = []
# Member tags
comment = False
variable = None
for token in tokens[1:]:
if (comment):
if (token == "*/"):
comment = False
continue
if (token == "/*"):
comment = True
continue
if (variable != None):
subtokens = token.split("[")
if (len(subtokens) > 1):
format += "%d" % int(subtokens[1].split("]")[0])
format += variable
inst.__dict__[subtokens[0]] = None
args.append(subtokens[0])
variable = None
continue
if (token[0:8] == "padding["):
size = token[8:].split("]")[0]
format += "%dx" % int(size)
continue
variable = {
"char": lambda: "s",
"uint8_t": lambda: "B",
"uint16_t": lambda: "H",
"uint32_t": lambda: "L",
"uint64_t": lambda: "Q",
"int8_t": lambda: "b",
"int16_t": lambda: "h",
"int32_t": lambda: "l",
"int64_t": lambda: "q"
}[token]()
inst.__dict__['_format_'] = format
inst.__dict__['_args_'] = args
return inst
/tags/0.4.0/tools/mkhord.py
0,0 → 1,104
#!/usr/bin/env python
#
# Copyright (c) 2008 Martin Decky
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
#
# - Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# - Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
# - The name of the author may not be used to endorse or promote products
# derived from this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
"""
HORD encapsulator
"""
 
import sys
import os
import xstruct
 
HEADER = """little:
char tag[4] /* 'HORD' */
uint8_t version /* version */
uint8_t encoding /* encoding */
uint32_t header_size /* header size */
uint64_t payload_size /* payload size */
"""
 
HORD_LSB = 1
 
def align_up(size, alignment):
"Align upwards to a given alignment"
return (((size) + ((alignment) - 1)) & ~((alignment) - 1))
 
def usage(prname):
"Print usage syntax"
print prname + " <ALIGNMENT> <FS_IMAGE> <HORD_IMAGE>"
 
def main():
if (len(sys.argv) < 4):
usage(sys.argv[0])
return
if (not sys.argv[1].isdigit()):
print "<ALIGNMENT> must be a number"
return
align = int(sys.argv[1], 0)
if (align <= 0):
print "<ALIGNMENT> must be positive"
return
fs_image = os.path.abspath(sys.argv[2])
if (not os.path.isfile(fs_image)):
print "<FS_IMAGE> must be a file"
return
inf = file(fs_image, "rb")
outf = file(sys.argv[3], "wb")
header = xstruct.create(HEADER)
header_size = header.size()
payload_size = os.path.getsize(fs_image)
header_size_aligned = align_up(header_size, align)
payload_size_aligned = align_up(payload_size, align)
header.tag = "HORD"
header.version = 1
header.encoding = HORD_LSB
header.header_size = header_size_aligned
header.payload_size = payload_size_aligned
outf.write(header.pack())
outf.write(xstruct.create("little: padding[%d]" % (header_size_aligned - header_size)).pack())
outf.write(inf.read())
padding = payload_size_aligned - payload_size
if (padding > 0):
outf.write(xstruct.create("little: padding[%d]" % padding).pack())
inf.close()
outf.close()
 
if __name__ == '__main__':
main()
Property changes:
Added: svn:executable
+*
\ No newline at end of property
/tags/0.4.0/tools/fix_symlinks.sh
0,0 → 1,24
#!/bin/bash
 
# by Alf
# This script solves malfunction of symlinks in cygwin
#
# Download sources from repository and than run this script to correct symlinks
# to be able compile project
 
 
if uname | grep 'CYGWIN' > /dev/null; then
echo "Good ... you have cygwin"
else
echo "Wrong. This script is only for cygwin"
exit
fi
for linkName in `find . ! -iwholename '.*svn*' ! -type d -print`; do
if head -n 1 $linkName | grep '^link' > /dev/null; then
linkTarget=`head -n 1 $linkName | sed 's/^link //'`
echo $linkName " -> " $linkTarget
rm $linkName
ln -s "$linkTarget" "$linkName"
fi
done