ia64/xen-unstable

changeset 15556:42586a0f4407

merge with xen-unstable.hg
author Alex Williamson <alex.williamson@hp.com>
date Tue Jul 10 08:39:26 2007 -0600 (2007-07-10)
parents 87b0b6a08dbd 80099a459d7a
children a36c51f43fdb
files .hgignore tools/libxc/xc_domain.c tools/libxc/xenctrl.h tools/python/xen/xend/XendDomainInfo.py tools/xenstore/fake_libxc.c tools/xenstore/speedtest.c tools/xenstore/testsuite/01simple.test tools/xenstore/testsuite/02directory.test tools/xenstore/testsuite/03write.test tools/xenstore/testsuite/04rm.test tools/xenstore/testsuite/05filepermissions.test tools/xenstore/testsuite/06dirpermissions.test tools/xenstore/testsuite/07watch.test tools/xenstore/testsuite/08transaction.slowtest tools/xenstore/testsuite/08transaction.test tools/xenstore/testsuite/09domain.test tools/xenstore/testsuite/10domain-homedir.test tools/xenstore/testsuite/11domain-watch.test tools/xenstore/testsuite/12readonly.test tools/xenstore/testsuite/13watch-ack.test tools/xenstore/testsuite/14complexperms.test tools/xenstore/testsuite/test.sh tools/xenstore/testsuite/vg-suppressions tools/xenstore/xenstored_test.h tools/xenstore/xs_crashme.c tools/xenstore/xs_random.c tools/xenstore/xs_stress.c tools/xenstore/xs_test.c xen/arch/ia64/Rules.mk xen/arch/x86/genapic/es7000.h
line diff
     1.1 --- a/.hgignore	Mon Jul 09 09:22:58 2007 -0600
     1.2 +++ b/.hgignore	Tue Jul 10 08:39:26 2007 -0600
     1.3 @@ -67,6 +67,9 @@
     1.4  ^linux-[^/]*-xen0/.*$
     1.5  ^linux-[^/]*-xenU/.*$
     1.6  ^linux-[^/]*-paravirt/.*$
     1.7 +^linux-[^/]*-mm/.*$
     1.8 +^linux-[^/]*-rc/.*$
     1.9 +^linux-[^/]*-tip/.*$
    1.10  ^linux-[^/]*\.patch$
    1.11  ^mkddbxen$
    1.12  ^netbsd-[^/]*-tools/.*$
    1.13 @@ -241,6 +244,7 @@
    1.14  ^xen/arch/powerpc/dom0\.bin$
    1.15  ^xen/arch/powerpc/asm-offsets\.s$
    1.16  ^xen/arch/powerpc/firmware$
    1.17 +^xen/arch/powerpc/firmware.dbg$
    1.18  ^xen/arch/powerpc/firmware_image.bin$
    1.19  ^xen/arch/powerpc/xen\.lds$
    1.20  ^xen/arch/powerpc/\.xen-syms$
     2.1 --- a/Config.mk	Mon Jul 09 09:22:58 2007 -0600
     2.2 +++ b/Config.mk	Tue Jul 10 08:39:26 2007 -0600
     2.3 @@ -17,8 +17,9 @@ CONFIG_$(XEN_OS) := y
     2.4  SHELL     ?= /bin/sh
     2.5  
     2.6  # Tools to run on system hosting the build
     2.7 -HOSTCC     = gcc
     2.8 -HOSTCFLAGS = -Wall -Werror -Wstrict-prototypes -O2 -fomit-frame-pointer
     2.9 +HOSTCC      = gcc
    2.10 +HOSTCFLAGS  = -Wall -Werror -Wstrict-prototypes -O2 -fomit-frame-pointer
    2.11 +HOSTCFLAGS += -fno-strict-aliasing
    2.12  
    2.13  DISTDIR     ?= $(XEN_ROOT)/dist
    2.14  DESTDIR     ?= /
    2.15 @@ -58,6 +59,8 @@ else
    2.16  CFLAGS += -g
    2.17  endif
    2.18  
    2.19 +CFLAGS += -fno-strict-aliasing
    2.20 +
    2.21  CFLAGS += -std=gnu99
    2.22  
    2.23  CFLAGS += -Wall -Wstrict-prototypes
     3.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     3.2 +++ b/buildconfigs/enable-xen-config	Tue Jul 10 08:39:26 2007 -0600
     3.3 @@ -0,0 +1,36 @@
     3.4 +#!/bin/sh
     3.5 +
     3.6 +set -ex
     3.7 +
     3.8 +if [ $# -ne 1 ] ; then
     3.9 +	echo "Usage $(basename $0) <config-file>" 1>&2
    3.10 +	exit 1
    3.11 +fi
    3.12 +
    3.13 +CONFIG=$1
    3.14 +
    3.15 +setopt()
    3.16 +{
    3.17 +	OPTION=$1
    3.18 +	VALUE=$2
    3.19 +
    3.20 +	# First remove any existing instances of this option
    3.21 +	sed -e "s/^# ${OPTION} is not set$//g ; s/^^{OPTION}=.$//g" -i "${CONFIG}"
    3.22 +
    3.23 +	# Then append the new value
    3.24 +	case ${VALUE} in
    3.25 +	    y|m) echo "${OPTION}=${VALUE}" >> "${CONFIG}" ;;
    3.26 +	    n)   echo "# ${OPTION} is not set" >> "${CONFIG}" ;;
    3.27 +	    *)   echo "Invalid value ${VALUE} for ${OPTION}" 1>&2 ; exit 1 ;;
    3.28 +	esac
    3.29 +}
    3.30 +
    3.31 +setopt CONFIG_PARAVIRT y
    3.32 +setopt CONFIG_XEN y
    3.33 +setopt CONFIG_VMI y
    3.34 +setopt CONFIG_LGUEST n
    3.35 +setopt CONFIG_XEN_BLKDEV_FRONTEND y
    3.36 +setopt CONFIG_XEN_NETDEV_FRONTEND y
    3.37 +setopt CONFIG_HVC_XEN y
    3.38 +
    3.39 +exit 0
     4.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     4.2 +++ b/buildconfigs/ketchup	Tue Jul 10 08:39:26 2007 -0600
     4.3 @@ -0,0 +1,742 @@
     4.4 +#!/usr/bin/python
     4.5 +#
     4.6 +# ketchup 0.9.8
     4.7 +# http://selenic.com/ketchup/wiki
     4.8 +#
     4.9 +# Copyright 2004 Matt Mackall <mpm@selenic.com>
    4.10 +#
    4.11 +# This software may be used and distributed according to the terms
    4.12 +# of the GNU General Public License, incorporated herein by reference.
    4.13 +#
    4.14 +# Usage:
    4.15 +#
    4.16 +# in an existing kernel directory, run:
    4.17 +#
    4.18 +#  ketchup <version>
    4.19 +#
    4.20 +# where version is a complete kernel version, or a branch name to grab
    4.21 +# the latest version
    4.22 +#
    4.23 +# You can override some variables by creating a ~/.ketchuprc file.
    4.24 +# The ~/.ketchuprc is just a Python script, eg. it might look like this:
    4.25 +#
    4.26 +# kernel_url = 'http://kernel.localdomain/pub/linux/kernel'
    4.27 +# archive = os.environ["HOME"] + '/tmp/ketchup-archive'
    4.28 +# gpg = '/weird/path/to/gpg'
    4.29 +#
    4.30 +
    4.31 +import re, sys, urllib, os, getopt, glob, shutil
    4.32 +
    4.33 +def error(*args):
    4.34 +    sys.stderr.write("ketchup: ")
    4.35 +    for a in args:
    4.36 +        sys.stderr.write(str(a))
    4.37 +        sys.stderr.write("\n")
    4.38 +
    4.39 +def qprint(*args):
    4.40 +    if not options["quiet"]:
    4.41 +        sys.stdout.write(" ".join(map(str, args)))
    4.42 +        sys.stdout.write("\n")
    4.43 +
    4.44 +def lprint(*args):
    4.45 +    sys.stdout.write(" ".join(map(str, args)))
    4.46 +    sys.stdout.write("\n")
    4.47 +
    4.48 +
    4.49 +def fancyopts(args, options, state, syntax=''):
    4.50 +    long = []
    4.51 +    short = ''
    4.52 +    map = {}
    4.53 +    dt = {}
    4.54 +
    4.55 +    def help(state, opt, arg, options = options, syntax = syntax):
    4.56 +        lprint("Usage: ", syntax)
    4.57 +
    4.58 +        for s, l, d, c in options:
    4.59 +            opt = ' '
    4.60 +            if s: opt = opt + '-' + s + ' '
    4.61 +            if l: opt = opt + '--' + l + ' '
    4.62 +            if d: opt = opt + '(' + str(d) + ')'
    4.63 +            lprint(opt)
    4.64 +            if c: lprint('   %s' % c)
    4.65 +        sys.exit(0)
    4.66 +
    4.67 +    options = [('h', 'help', help, 'Show usage info')] + options
    4.68 +
    4.69 +    for s, l, d, c in options:
    4.70 +        map['-'+s] = map['--'+l]=l
    4.71 +        state[l] = d
    4.72 +        dt[l] = type(d)
    4.73 +        if not d is None and not type(d) is type(help): s, l = s + ':', l + '='
    4.74 +        if s: short = short + s
    4.75 +        if l: long.append(l)
    4.76 +
    4.77 +    if os.environ.has_key("KETCHUP_OPTS"):
    4.78 +        args = os.environ["KETCHUP_OPTS"].split() + args
    4.79 +
    4.80 +    try:
    4.81 +        opts, args = getopt.getopt(args, short, long)
    4.82 +    except getopt.GetoptError:
    4.83 +        help(state, None, args)
    4.84 +        sys.exit(-1)
    4.85 +
    4.86 +    for opt, arg in opts:
    4.87 +        if dt[map[opt]] is type(help): state[map[opt]](state,map[opt],arg)
    4.88 +        elif dt[map[opt]] is type(1): state[map[opt]] = int(arg)
    4.89 +        elif dt[map[opt]] is type(''): state[map[opt]] = arg
    4.90 +        elif dt[map[opt]] is type([]): state[map[opt]].append(arg)
    4.91 +        elif dt[map[opt]] is type(None): state[map[opt]] = 1
    4.92 +
    4.93 +    return args
    4.94 +
    4.95 +# Default values
    4.96 +kernel_url = 'http://www.kernel.org/pub/linux/kernel'
    4.97 +archive = os.environ["HOME"] + "/.ketchup"
    4.98 +rename_prefix = 'linux-'
    4.99 +rename_with_localversion = False
   4.100 +wget = "/usr/bin/wget"
   4.101 +gpg = "/usr/bin/gpg"
   4.102 +precommand = postcommand = None
   4.103 +default_tree = None
   4.104 +local_trees = {}
   4.105 +
   4.106 +# Functions to parse version strings
   4.107 +
   4.108 +def tree(ver):
   4.109 +    return float(re.match(r'(\d+\.\d+)', ver).group(1))
   4.110 +
   4.111 +def rev(ver):
   4.112 +    p = pre(ver)
   4.113 +    r = int(re.match(r'\d+\.\d+\.(\d+)', ver).group(1))
   4.114 +    if p: r = r - 1
   4.115 +    return r
   4.116 +
   4.117 +def pre(ver):
   4.118 +    try: return re.match(r'\d+\.\d+\.\d+(\.\d+)?-((rc|pre)\d+)', ver).group(2)
   4.119 +    except: return None
   4.120 +
   4.121 +def post(ver):
   4.122 +    try: return re.match(r'\d+\.\d+\.\d+\.(\d+)', ver).group(1)
   4.123 +    except: return None
   4.124 +
   4.125 +def pretype(ver):
   4.126 +    try: return re.match(r'\d+\.\d+\.\d+(\.\d+)?-((rc|pre)\d+)', ver).group(3)
   4.127 +    except: return None
   4.128 +
   4.129 +def prenum(ver):
   4.130 +    try: return int(re.match(r'\d+\.\d+\.\d+-((rc|pre)(\d+))', ver).group(3))
   4.131 +    except: return None
   4.132 +
   4.133 +def prebase(ver):
   4.134 +    return re.match(r'(\d+\.\d+\.\d+((-(rc|pre)|\.)\d+)?)', ver).group(1)
   4.135 +
   4.136 +def revbase(ver):
   4.137 +    return "%s.%s" % (tree(ver), rev(ver))
   4.138 +
   4.139 +def base(ver):
   4.140 +    v = revbase(ver)
   4.141 +    if post(ver): v += "." + post(ver)
   4.142 +    return v
   4.143 +
   4.144 +def forkname(ver):
   4.145 +    try: return re.match(r'\d+.\d+.\d+(\.\d+)?(-(rc|pre)\d+)?(-(\w+?)\d+)?',
   4.146 +                         ver).group(5)
   4.147 +    except: return None
   4.148 +
   4.149 +def forknum(ver):
   4.150 +    try: return int(
   4.151 +        re.match(r'\d+.\d+.\d+(\.\d+)?(-(rc|pre)\d+)?(-(\w+?)(\d+))?',
   4.152 +                 ver).group(6))
   4.153 +    except: return None
   4.154 +
   4.155 +def fork(ver):
   4.156 +    try: return re.match(r'\d+.\d+.\d+(\.\d+)?(-(rc|pre)\d+)?(-(\w+))?', ver).group(4)
   4.157 +    except: return None
   4.158 +
   4.159 +def get_ver(makefile):
   4.160 +    """ Read the version information from the specified makefile """
   4.161 +    part = {}
   4.162 +    parts = "VERSION PATCHLEVEL SUBLEVEL EXTRAVERSION".split(' ')
   4.163 +    m = open(makefile)
   4.164 +    for l in m.readlines():
   4.165 +        for p in parts:
   4.166 +            try: part[p] = re.match(r'%s\s*=\s*(\S+)' % p, l).group(1)
   4.167 +            except: pass
   4.168 +
   4.169 +    version = "%s.%s.%s" % tuple([part[p] for p in parts[:3]])
   4.170 +    version += part.get("EXTRAVERSION","")
   4.171 +    return version
   4.172 +
   4.173 +def get_localversion():
   4.174 +    v = ''
   4.175 +
   4.176 +    for name in glob.glob('localversion*'):
   4.177 +        try: v += open(name).readline().strip()
   4.178 +        except: pass
   4.179 +
   4.180 +    try:
   4.181 +        c = open('.config').read()
   4.182 +        v += re.search(r'^CONFIG_LOCALVERSION="(.+)"', c, re.M).group(1)
   4.183 +    except: pass
   4.184 +
   4.185 +    return v
   4.186 +
   4.187 +def compare_ver(a, b):
   4.188 +    """
   4.189 +    Compare kernel versions a and b
   4.190 +
   4.191 +    Note that -pre and -rc versions sort before the version they modify,
   4.192 +    -pre sorts before -rc, -bk, -git, and -mm, etc. sort alphabetically.
   4.193 +    """
   4.194 +    if a == b: return 0
   4.195 +
   4.196 +    c = cmp(float(tree(a)), float(tree(b)))
   4.197 +    if c: return c
   4.198 +    c = cmp(rev(a), rev(b))
   4.199 +    if c: return c
   4.200 +    c = cmp(int(post(a) or 0), int(post(b) or 0))
   4.201 +    if c: return c
   4.202 +    c = cmp(pretype(a), pretype(b)) # pre sorts before rc
   4.203 +    if c: return c
   4.204 +    c = cmp(prenum(a), prenum(b))
   4.205 +    if c: return c
   4.206 +    c = cmp(forkname(a), forkname(b))
   4.207 +    if c: return c
   4.208 +    return cmp(forknum(a), forknum(b))
   4.209 +
   4.210 +def last(url, pat="(.*/)"):
   4.211 +    for l in urllib.urlopen(url).readlines():
   4.212 +        m = re.search('(?i)<a href="%s">' % pat, l)
   4.213 +        if m: n = m.group(1)
   4.214 +    return n
   4.215 +
   4.216 +def latest_mm(url, pat):
   4.217 +    url = kernel_url + '/people/akpm/patches/2.6/'
   4.218 +    url += last(url)
   4.219 +    part = last(url)
   4.220 +    return part[:-1]
   4.221 +
   4.222 +def latest_ck(url, pat):
   4.223 +    url = "http://ck.kolivas.org/patches/2.6/pre-releases/"
   4.224 +    url += last(url)
   4.225 +    part = last(url)
   4.226 +    pre = part[:-1]
   4.227 +
   4.228 +    url = "http://ck.kolivas.org/patches/2.6/"
   4.229 +    url += last(url,"(2.6.*/)")
   4.230 +    part = last(url)
   4.231 +    rel = part[:-1]
   4.232 +
   4.233 +    l = [pre, rel]
   4.234 +    l.sort(compare_ver)
   4.235 +    return l[-1]
   4.236 +
   4.237 +def latest_dir(url, pat):
   4.238 +    """Find the latest link matching pat at url after sorting"""
   4.239 +    p = []
   4.240 +    for l in urllib.urlopen(url).readlines():
   4.241 +        m = re.search('"%s"' % pat, l)
   4.242 +        if m: p.append(m.group(1))
   4.243 +
   4.244 +    if not p: return None
   4.245 +
   4.246 +    p.sort(compare_ver)
   4.247 +    return p[-1]
   4.248 +
   4.249 +# mbligh is lazy and has a bunch of empty directories
   4.250 +def latest_mjb(url, pat):
   4.251 +    url = kernel_url + '/people/mbligh/'
   4.252 +
   4.253 +    # find the last Linus release and search backwards
   4.254 +    l = [find_ver('2.6'), find_ver("2.6-pre")]
   4.255 +    l.sort(compare_ver)
   4.256 +    linus = l[-1]
   4.257 +
   4.258 +    p = []
   4.259 +    for l in urllib.urlopen(url).readlines():
   4.260 +        m = re.search('"(2\.6\..*/)"', l)
   4.261 +        if m:
   4.262 +            v = m.group(1)
   4.263 +            if compare_ver(v, linus) <= 0:
   4.264 +                p.append(v)
   4.265 +
   4.266 +    p.sort(compare_ver)
   4.267 +    p.reverse()
   4.268 +
   4.269 +    for ver in p:
   4.270 +        mjb = latest_dir(url + ver, pat)
   4.271 +        if mjb: return mjb
   4.272 +
   4.273 +    return None
   4.274 +
   4.275 +def latest_26_tip(url, pat):
   4.276 +    l = [find_ver('2.6'), find_ver('2.6-git'), find_ver('2.6-pre')]
   4.277 +    l.sort(compare_ver)
   4.278 +    return l[-1]
   4.279 +
   4.280 +def find_info(ver):
   4.281 +    b = "%.1f" % tree(ver)
   4.282 +    f = forkname(ver)
   4.283 +    p = pre(ver)
   4.284 +
   4.285 +    s = b
   4.286 +    if f:
   4.287 +        s = "%s-%s" % (b, f)
   4.288 +    elif p:
   4.289 +        s = "%s-pre" % b
   4.290 +
   4.291 +    return version_info[s]
   4.292 +
   4.293 +def version_urls(ver):
   4.294 +    """ Return the URL for the patch associated with the specified version """
   4.295 +    i = find_info(ver)[1]
   4.296 +    if type(i) != type([]):
   4.297 +        i = [i]
   4.298 +
   4.299 +    v = {
   4.300 +        'full': ver,
   4.301 +        'tree': tree(ver),
   4.302 +        'base': base(ver),
   4.303 +        'prebase': prebase(ver)
   4.304 +        }
   4.305 +
   4.306 +    l = []
   4.307 +    for e in i:
   4.308 +        l.append(e % v)
   4.309 +
   4.310 +    return l
   4.311 +
   4.312 +def patch_path(ver):
   4.313 +    return os.path.join(archive, os.path.basename(version_urls(ver)[0]))
   4.314 +
   4.315 +def download(url, f):
   4.316 +    qprint("Downloading %s" % os.path.basename(url))
   4.317 +    if options["dry-run"]:
   4.318 +        return 1
   4.319 +
   4.320 +    if not options["wget"]:
   4.321 +        p = urllib.urlopen(url).read()
   4.322 +        if p.find("<title>404") != -1:
   4.323 +            return None
   4.324 +        open(f, 'w').write(p)
   4.325 +    else:
   4.326 +        e = os.system("%s -c -O %s %s" %
   4.327 +                      (options["wget"], f + ".partial", url))
   4.328 +        if e:
   4.329 +            return None
   4.330 +        os.rename(f + ".partial", f)
   4.331 +
   4.332 +    return 1
   4.333 +
   4.334 +def verify(url, f, sign):
   4.335 +    if options["no-gpg"] or options["dry-run"] or not options["gpg-path"]:
   4.336 +        return 1
   4.337 +
   4.338 +    sf = f + sign
   4.339 +    if not download(url + sign, sf):
   4.340 +        error("signature download failed")
   4.341 +        error("removing files...")
   4.342 +        os.unlink(f)
   4.343 +        return 0
   4.344 +
   4.345 +    qprint("Verifying signature...")
   4.346 +    r = os.system("%s --verify %s %s" % (options["gpg-path"], sf, f))
   4.347 +    if r:
   4.348 +        error("gpg returned %d" % r)
   4.349 +        error("removing files...")
   4.350 +        os.unlink(f)
   4.351 +        os.unlink(sf)
   4.352 +        return 0
   4.353 +
   4.354 +    return 1
   4.355 +
   4.356 +def trydownload(urls, f, sign):
   4.357 +    for url in urls:
   4.358 +        if download(url, f):
   4.359 +            if not sign or verify(url, f, sign):
   4.360 +                return f
   4.361 +        if url[-4:] == ".bz2":
   4.362 +            f2 = f[:-4] + ".gz"
   4.363 +            url2 = url[:-4] + ".gz"
   4.364 +            if download(url2, f2):
   4.365 +                if not sign or verify(url2, f2, sign):
   4.366 +                    return f2
   4.367 +    return None
   4.368 +
   4.369 +def get_patch(ver):
   4.370 +    """Return the path to patch for given ver, downloading if necessary"""
   4.371 +    f = patch_path(ver)
   4.372 +    if os.path.exists(f):
   4.373 +        return f
   4.374 +    if f[-4:] == ".bz2":
   4.375 +        f2 = f[:-4] + ".gz"
   4.376 +        if os.path.exists(f2):
   4.377 +            return f2
   4.378 +
   4.379 +    urls = version_urls(ver)
   4.380 +    sign = find_info(ver)[3]
   4.381 +    if sign == 1: sign = ".sign"
   4.382 +    f = trydownload(urls, f, sign)
   4.383 +    if not f:
   4.384 +        error("patch download failed")
   4.385 +        sys.exit(-1)
   4.386 +
   4.387 +    return f
   4.388 +
   4.389 +def apply_patch(ver, reverse = 0):
   4.390 +    """Find the patch to upgrade from the predecessor of ver to ver and
   4.391 +    apply or reverse it."""
   4.392 +    p = get_patch(ver)
   4.393 +    r = ""
   4.394 +    if reverse:
   4.395 +        r = " -R"
   4.396 +
   4.397 +    qprint("Applying %s%s" % (os.path.basename(p), r))
   4.398 +    if options["dry-run"]:
   4.399 +        return ver
   4.400 +
   4.401 +    def cmd(patch, reverse, dry):
   4.402 +        base = "patch -l -p1%s" % reverse
   4.403 +        if dry:
   4.404 +            base += " --dry-run"
   4.405 +
   4.406 +        if p[-4:] == ".bz2":
   4.407 +            pipe = "bzcat %s | %s" % (patch, base)
   4.408 +        elif p[-3:] == ".gz":
   4.409 +            pipe = "zcat %s | %s" % (patch, base)
   4.410 +        else:
   4.411 +            pipe = "%s < %s" % (base, patch)
   4.412 +
   4.413 +        err = os.system(pipe + " > .patchdiag")
   4.414 +        if err:
   4.415 +            sys.stderr.write(open(".patchdiag").read())
   4.416 +        os.unlink(".patchdiag")
   4.417 +        return err
   4.418 +
   4.419 +    err = cmd(p, r, 1)
   4.420 +    if err:
   4.421 +        error("patch %s failed: %d" % (p, err))
   4.422 +        sys.exit(-1)
   4.423 +
   4.424 +    err = cmd(p, r, 0)
   4.425 +    if err:
   4.426 +        error("patch %s failed while it was supposed to apply: %d" % (p, err))
   4.427 +        sys.exit(-1)
   4.428 +
   4.429 +def untar(tarfile):
   4.430 +    old = os.getcwd()
   4.431 +    os.mkdir("ketchup-tmp")
   4.432 +    os.chdir("ketchup-tmp")
   4.433 +
   4.434 +    err = os.system("bzcat %s | tar -xf -" % tarfile)
   4.435 +    if err:
   4.436 +        error("Unpacking failed: ", err)
   4.437 +        sys.exit(-1)
   4.438 +
   4.439 +    err = os.system("mv linux*/* linux*/.[^.]* ..; rmdir linux*")
   4.440 +    if err:
   4.441 +        error("Unpacking failed: ", err)
   4.442 +        sys.exit(-1)
   4.443 +
   4.444 +    os.chdir(old)
   4.445 +    shutil.rmtree("ketchup-tmp")
   4.446 +
   4.447 +def install_nearest(ver):
   4.448 +    t = tree(ver)
   4.449 +    tarballs = glob.glob(archive + "/linux-%s.*.tar.bz2" % t)
   4.450 +    list = []
   4.451 +
   4.452 +    for f in tarballs:
   4.453 +        m = re.match(r'.*/linux-(.*).tar.bz2$', f)
   4.454 +        v = m.group(1)
   4.455 +        d = abs(rev(v) - rev(ver))
   4.456 +        list.append((d, f, v))
   4.457 +    list.sort()
   4.458 +
   4.459 +    if not list or (options["full-tarball"] and list[0][0]):
   4.460 +        f = "linux-%s.tar.bz2" % ver
   4.461 +        url = "%s/v%s/%s" % (kernel_url, t, f)
   4.462 +        f = archive + "/" + f
   4.463 +
   4.464 +        sign = find_info(ver)[3]
   4.465 +        if sign == 1: sign = ".sign"
   4.466 +
   4.467 +        f = trydownload([url], f, sign)
   4.468 +        if not f:
   4.469 +            error("Tarball download failed")
   4.470 +            sys.exit(-1)
   4.471 +
   4.472 +    else:
   4.473 +        f = list[0][1]
   4.474 +        ver = list[0][2]
   4.475 +
   4.476 +    qprint("Unpacking %s" % os.path.basename(f))
   4.477 +    if options["dry-run"]: return ver
   4.478 +    untar(f)
   4.479 +
   4.480 +    return ver
   4.481 +
   4.482 +def find_ver(ver):
   4.483 +    if ver in version_info.keys():
   4.484 +        v = version_info[ver]
   4.485 +        d = v[1]
   4.486 +        if type(d) is type([]):
   4.487 +            d = d[0]
   4.488 +        for n in range(5):
   4.489 +            return v[0](os.path.dirname(d), v[2])
   4.490 +            error('retrying version lookup for %s' % ver)
   4.491 +    else:
   4.492 +        return ver
   4.493 +
   4.494 +def transform(a, b):
   4.495 +    if a == b:
   4.496 +        qprint("Nothing to do!")
   4.497 +        return
   4.498 +    if not a:
   4.499 +        a = install_nearest(base(b))
   4.500 +    t = tree(a)
   4.501 +    if t != tree(b):
   4.502 +        error("Can't patch %s to %s" % (tree(a), tree(b)))
   4.503 +        sys.exit(-1)
   4.504 +    if fork(a):
   4.505 +        apply_patch(a, 1)
   4.506 +        a = prebase(a)
   4.507 +    if prebase(a) != prebase(b):
   4.508 +        if pre(a):
   4.509 +            apply_patch(a, 1)
   4.510 +            a = base(a)
   4.511 +
   4.512 +        if post(a) and post(a) != post(b):
   4.513 +            apply_patch(prebase(a), 1)
   4.514 +
   4.515 +        ra, rb = rev(a), rev(b)
   4.516 +        if ra > rb:
   4.517 +            for r in range(ra, rb, -1):
   4.518 +                apply_patch("%s.%s" % (t, r), -1)
   4.519 +        if ra < rb:
   4.520 +            for r in range(ra + 1, rb + 1):
   4.521 +                apply_patch("%s.%s" % (t, r))
   4.522 +        a = revbase(b)
   4.523 +
   4.524 +        if post(b) and post(a) != post(b):
   4.525 +            apply_patch(prebase(b), 0)
   4.526 +            a = base(b)
   4.527 +
   4.528 +        if pre(b):
   4.529 +            apply_patch(prebase(b))
   4.530 +            a = prebase(b)
   4.531 +
   4.532 +    if fork(b):
   4.533 +        a = apply_patch(b)
   4.534 +
   4.535 +def rename_dir(v):
   4.536 +    """Rename the current directory to linux-v, where v is the function arg"""
   4.537 +    if rename_with_localversion:
   4.538 +        v += get_localversion()
   4.539 +    cwd = os.getcwd()
   4.540 +    basedir = os.path.dirname(cwd)
   4.541 +    newdir = os.path.join(basedir, rename_prefix + v)
   4.542 +    if newdir == cwd:
   4.543 +        return
   4.544 +    if os.access(newdir, os.F_OK):
   4.545 +        error("Cannot rename directory, destination exists: %s", newdir);
   4.546 +        return
   4.547 +    os.rename(cwd, newdir)
   4.548 +    qprint('Current directory renamed to %s' % newdir)
   4.549 +
   4.550 +
   4.551 +# latest lookup function, canonical urls, pattern for lookup function,
   4.552 +#  signature flag, description
   4.553 +version_info = {
   4.554 +    '2.4': (latest_dir,
   4.555 +            kernel_url + "/v2.4" + "/patch-%(base)s.bz2",
   4.556 +            r'patch-(.*?).bz2',
   4.557 +            1, "old stable kernel series"),
   4.558 +    '2.4-pre': (latest_dir,
   4.559 +                kernel_url + "/v2.4" + "/testing/patch-%(prebase)s.bz2",
   4.560 +                r'patch-(.*?).bz2',
   4.561 +                1, "old stable kernel series prereleases"),
   4.562 +    '2.6': (latest_dir,
   4.563 +            kernel_url + "/v2.6" + "/patch-%(prebase)s.bz2",
   4.564 +            r'patch-(.*?).bz2',
   4.565 +            1, "current stable kernel series"),
   4.566 +    '2.6-rc': (latest_dir,
   4.567 +                kernel_url + "/v2.6" + "/testing/patch-%(prebase)s.bz2",
   4.568 +                r'patch-(.*?).bz2',
   4.569 +                1, "current stable kernel series prereleases"),
   4.570 +    '2.6-pre': (latest_dir,
   4.571 +                kernel_url + "/v2.6" + "/testing/patch-%(prebase)s.bz2",
   4.572 +                r'patch-(.*?).bz2',
   4.573 +                1, "current stable kernel series prereleases"),
   4.574 +    '2.6-git': (latest_dir,
   4.575 +                [kernel_url + "/v2.6" + "/snapshots/patch-%(full)s.bz2",
   4.576 +                 kernel_url + "/v2.6" + "/snapshots/old/patch-%(full)s.bz2"],
   4.577 +                r'patch-(.*?).bz2',
   4.578 +                1, "current stable kernel series snapshots"),
   4.579 +    '2.6-bk': (latest_dir,
   4.580 +               [kernel_url + "/v2.6" + "/snapshots/patch-%(full)s.bz2",
   4.581 +                kernel_url + "/v2.6" + "/snapshots/old/patch-%(full)s.bz2"],
   4.582 +               r'patch-(.*?).bz2',
   4.583 +               1, "old stable kernel series snapshots"),
   4.584 +    '2.6-tip': (latest_26_tip, "", "", 1,
   4.585 +                "current stable kernel series tip"),
   4.586 +    '2.6-mm': (latest_mm,
   4.587 +               kernel_url + "/people/akpm/patches/" +
   4.588 +               "%(tree)s/%(prebase)s/%(full)s/%(full)s.bz2", "",
   4.589 +               1, "Andrew Morton's -mm development tree"),
   4.590 +    '2.6-tiny': (latest_dir,
   4.591 +                 "http://www.selenic.com/tiny/%(full)s.patch.bz2",
   4.592 +                 r'(2.6.*?).patch.bz2',
   4.593 +                 1, "Matt Mackall's -tiny tree for small systems"),
   4.594 +    '2.6-mjb': (latest_mjb,
   4.595 +                 kernel_url + "/people/mbligh/%(prebase)s/patch-%(full)s.bz2",
   4.596 +                 r'patch-(2.6.*?).bz2',
   4.597 +                 1, "Martin Bligh's random collection 'o crap"),
   4.598 +    '2.6-rt': (latest_dir,
   4.599 +               ["http://people.redhat.com/mingo/" +
   4.600 +                "realtime-preempt/patch-%(full)s",
   4.601 +                "http://people.redhat.com/mingo/" +
   4.602 +                "realtime-preempt/older/patch-%(full)s"],
   4.603 +               r'patch-(2.6.*?)',
   4.604 +               0, "Ingo Molnar's realtime-preempt kernel"),
   4.605 +    '2.6-ck': (latest_ck,
   4.606 +               ["http://ck.kolivas.org/patches/2.6/" +
   4.607 +                "%(prebase)s/%(full)s/patch-%(full)s.bz2",
   4.608 +                "http://ck.kolivas.org/patches/2.6/pre-releases/" +
   4.609 +                "%(prebase)s/%(full)s/patch-%(full)s.bz2"],
   4.610 +               "", ".sig",
   4.611 +               "Con Kolivas' patches for system responsiveness (desktop)"),
   4.612 +    '2.6-cks': (latest_dir,
   4.613 +                "http://ck.kolivas.org/patches/cks/patch-%(full)s.bz2",
   4.614 +                r'patch-(2.6.*?).bz2', ".sig",
   4.615 +                "Con Kolivas' patches for system responsiveness (server)")
   4.616 +    }
   4.617 +
   4.618 +# Override defaults with ~/.ketchuprc which is just a Python script
   4.619 +rcpath = os.path.expanduser('~/.ketchuprc')
   4.620 +if os.path.isfile(rcpath):
   4.621 +    try:
   4.622 +        execfile(rcpath)
   4.623 +    except Exception, e:
   4.624 +        sys.exit('Failed parsing %s\nError was: %s' % (rcpath, e))
   4.625 +
   4.626 +# Add local trees
   4.627 +for k,v in local_trees.items():
   4.628 +    version_info[k] = v
   4.629 +
   4.630 +# Environment variables override defaults and ketchuprc
   4.631 +kernel_url = os.environ.get("KETCHUP_URL", kernel_url)
   4.632 +archive = os.environ.get("KETCHUP_ARCH", archive)
   4.633 +
   4.634 +# And finally command line overrides everything
   4.635 +if not os.path.exists(wget): wget = ""
   4.636 +if not os.path.exists(gpg): gpg = ""
   4.637 +
   4.638 +options = {}
   4.639 +opts = [
   4.640 +    ('a', 'archive', archive, 'cache directory'),
   4.641 +    ('d', 'directory', '.', 'directory to update'),
   4.642 +    ('f', 'full-tarball', None, 'if unpacking a tarball, download the latest'),
   4.643 +    ('g', 'gpg-path', gpg, 'path for GnuPG'),
   4.644 +    ('G', 'no-gpg', None, 'disable GPG signature verification'),
   4.645 +    ('k', 'kernel-url', kernel_url, 'base url for kernel.org mirror'),
   4.646 +    ('l', 'list-trees', None, 'list supported trees'),
   4.647 +    ('m', 'show-makefile', None, 'output version in makefile <arg>'),
   4.648 +    ('n', 'dry-run', None, 'don\'t download or apply patches'),
   4.649 +    ('p', 'show-previous', None, 'output version previous to <arg>'),
   4.650 +    ('q', 'quiet', None, 'reduce output'),
   4.651 +    ('r', 'rename-directory', None, 'rename updated directory to %s<v>'
   4.652 +     % rename_prefix),
   4.653 +    ('s', 'show-latest', None, 'output the latest version of <arg>'),
   4.654 +    ('u', 'show-url', None, 'output URL for <arg>'),
   4.655 +    ('w', 'wget', wget, 'command to use for wget'),
   4.656 +    ]
   4.657 +
   4.658 +args = fancyopts(sys.argv[1:], opts, options,
   4.659 +                 'ketchup [options] [ver]')
   4.660 +
   4.661 +archive = options["archive"]
   4.662 +kernel_url = options["kernel-url"]
   4.663 +if options["no-gpg"]: options["gpg-path"] = ''
   4.664 +
   4.665 +# Process args
   4.666 +
   4.667 +if not os.path.exists(options["directory"]):
   4.668 +    qprint("Creating target directory", options["directory"])
   4.669 +    os.mkdir(options["directory"])
   4.670 +os.chdir(options["directory"])
   4.671 +
   4.672 +if os.path.isfile(".ketchuprc"):
   4.673 +    try:
   4.674 +        execfile(".ketchuprc")
   4.675 +    except Exception, e:
   4.676 +        sys.exit('Failed parsing .ketchuprc\nError was: %s' % (e))
   4.677 +
   4.678 +if options["list-trees"]:
   4.679 +    l = version_info.keys()
   4.680 +    l.sort()
   4.681 +    for tree in l:
   4.682 +	if version_info[tree][3] == 0:
   4.683 +	   lprint(tree, "(unsigned)")
   4.684 +        else:
   4.685 +	   lprint(tree, "(signed)")
   4.686 +        lprint(" " + version_info[tree][4])
   4.687 +    sys.exit(0)
   4.688 +
   4.689 +if options["show-makefile"] and len(args) < 2:
   4.690 +    if not args:
   4.691 +        lprint(get_ver("Makefile"))
   4.692 +    else:
   4.693 +        lprint(get_ver(args[0]))
   4.694 +    sys.exit(0)
   4.695 +
   4.696 +if len(args) == 0 and default_tree:
   4.697 +    qprint("Using default tree \"%s\"" % (default_tree))
   4.698 +    args.append(default_tree)
   4.699 +
   4.700 +if len(args) != 1:
   4.701 +    error("No version given on command line and no default in configuration")
   4.702 +    sys.exit(-1)
   4.703 +
   4.704 +if options["show-latest"]:
   4.705 +    lprint(find_ver(args[0]))
   4.706 +    sys.exit(0)
   4.707 +
   4.708 +if options["show-url"]:
   4.709 +    lprint(version_urls(find_ver(args[0]))[0])
   4.710 +    sys.exit(0)
   4.711 +
   4.712 +if options["show-previous"]:
   4.713 +    v = find_ver(args[0])
   4.714 +    p = prebase(v)
   4.715 +    if p == v: p = base(v)
   4.716 +    if p == v:
   4.717 +        if rev(v) > 0: p = "%.1f.%s" % (tree(v), rev(v) -1)
   4.718 +        else: p = "unknown"
   4.719 +    lprint(p)
   4.720 +    sys.exit(0)
   4.721 +
   4.722 +if not os.path.exists(options["archive"]):
   4.723 +    qprint("Creating cache directory", options["archive"])
   4.724 +    os.mkdir(options["archive"])
   4.725 +
   4.726 +if precommand and os.system(precommand):
   4.727 +    sys.exit('Precommand "%s" failed!' % precommand)
   4.728 +
   4.729 +try:
   4.730 +    a = get_ver('Makefile')
   4.731 +except:
   4.732 +    a = None
   4.733 +
   4.734 +if not a and os.listdir("."):
   4.735 +    error("Can't find kernel version for non-empty directory")
   4.736 +    sys.exit(-1)
   4.737 +
   4.738 +b = find_ver(args[0])
   4.739 +qprint("%s -> %s" % (a, b))
   4.740 +transform(a, b)
   4.741 +if options["rename-directory"] and not options["dry-run"]:
   4.742 +    rename_dir(b)
   4.743 +
   4.744 +if postcommand and os.system(postcommand):
   4.745 +    sys.exit('Postcommand "%s" failed!' % postcommand)
     5.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     5.2 +++ b/buildconfigs/mk.linux-2.6-mm	Tue Jul 10 08:39:26 2007 -0600
     5.3 @@ -0,0 +1,14 @@
     5.4 +XEN_LINUX_SOURCE ?= tarball
     5.5 +LINUX_VER ?= 2.6-mm
     5.6 +
     5.7 +XEN_LINUX_TARBALL_KETCHUP := y
     5.8 +
     5.9 +IMAGE_TARGET ?= vmlinux bzImage
    5.10 +
    5.11 +XEN_LINUX_ALLOW_INTERFACE_MISMATCH := y
    5.12 +
    5.13 +XEN_LINUX_CONFIG_UPDATE := buildconfigs/enable-xen-config
    5.14 +
    5.15 +EXTRAVERSION ?=
    5.16 +
    5.17 +include buildconfigs/mk.linux-2.6-xen
     6.1 --- a/buildconfigs/mk.linux-2.6-paravirt	Mon Jul 09 09:22:58 2007 -0600
     6.2 +++ b/buildconfigs/mk.linux-2.6-paravirt	Tue Jul 10 08:39:26 2007 -0600
     6.3 @@ -8,6 +8,8 @@ IMAGE_TARGET ?= vmlinux bzImage
     6.4  
     6.5  XEN_LINUX_ALLOW_INTERFACE_MISMATCH := y
     6.6  
     6.7 -EXTRAVERSION ?=
     6.8 +XEN_LINUX_CONFIG_UPDATE := buildconfigs/enable-xen-config
     6.9 +
    6.10 +EXTRAVERSION ?= -paravirt
    6.11  
    6.12  include buildconfigs/mk.linux-2.6-xen
     7.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     7.2 +++ b/buildconfigs/mk.linux-2.6-rc	Tue Jul 10 08:39:26 2007 -0600
     7.3 @@ -0,0 +1,14 @@
     7.4 +XEN_LINUX_SOURCE ?= tarball
     7.5 +LINUX_VER ?= 2.6-rc
     7.6 +
     7.7 +XEN_LINUX_TARBALL_KETCHUP := y
     7.8 +
     7.9 +IMAGE_TARGET ?= vmlinux bzImage
    7.10 +
    7.11 +XEN_LINUX_ALLOW_INTERFACE_MISMATCH := y
    7.12 +
    7.13 +XEN_LINUX_CONFIG_UPDATE := buildconfigs/enable-xen-config
    7.14 +
    7.15 +EXTRAVERSION ?=
    7.16 +
    7.17 +include buildconfigs/mk.linux-2.6-xen
     8.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     8.2 +++ b/buildconfigs/mk.linux-2.6-tip	Tue Jul 10 08:39:26 2007 -0600
     8.3 @@ -0,0 +1,14 @@
     8.4 +XEN_LINUX_SOURCE ?= tarball
     8.5 +LINUX_VER ?= 2.6-tip
     8.6 +
     8.7 +XEN_LINUX_TARBALL_KETCHUP := y
     8.8 +
     8.9 +IMAGE_TARGET ?= vmlinux bzImage
    8.10 +
    8.11 +XEN_LINUX_ALLOW_INTERFACE_MISMATCH := y
    8.12 +
    8.13 +XEN_LINUX_CONFIG_UPDATE := buildconfigs/enable-xen-config
    8.14 +
    8.15 +EXTRAVERSION ?=
    8.16 +
    8.17 +include buildconfigs/mk.linux-2.6-xen
     9.1 --- a/buildconfigs/mk.linux-2.6-xen	Mon Jul 09 09:22:58 2007 -0600
     9.2 +++ b/buildconfigs/mk.linux-2.6-xen	Tue Jul 10 08:39:26 2007 -0600
     9.3 @@ -74,6 +74,10 @@ endif
     9.4  	else \
     9.5            echo "No configuration method found for this kernel" ; \
     9.6  	fi
     9.7 +ifneq ($(XEN_LINUX_CONFIG_UPDATE),)
     9.8 +	echo "Updating $(CONFIG_FILE) using $(XEN_LINUX_CONFIG_UPDATE)"
     9.9 +	sh $(XEN_LINUX_CONFIG_UPDATE) $(CONFIG_FILE)
    9.10 +endif
    9.11  ifeq ($(XEN_TARGET_ARCH),x86_32)
    9.12  ifeq ($(pae),y)
    9.13  	sed -e 's!^CONFIG_HIGHMEM4G=y$$!\# CONFIG_HIGHMEM4G is not set!;s!^\# CONFIG_HIGHMEM64G is not set$$!CONFIG_HIGHMEM64G=y!' $(CONFIG_FILE) > $(CONFIG_FILE)- && mv $(CONFIG_FILE)- $(CONFIG_FILE)
    10.1 --- a/buildconfigs/src.tarball	Mon Jul 09 09:22:58 2007 -0600
    10.2 +++ b/buildconfigs/src.tarball	Tue Jul 10 08:39:26 2007 -0600
    10.3 @@ -1,8 +1,13 @@
    10.4  XEN_LINUX_MIRROR ?= http://www.kernel.org/pub/linux/kernel/v2.6/
    10.5  XEN_LINUX_TARBALL ?= linux-$(LINUX_VER)-xen.tar.bz2
    10.6  
    10.7 +# Update using ketchup instead of manipulating tarball manually.
    10.8 +XEN_LINUX_TARBALL_KETCHUP ?= n
    10.9 +
   10.10  LINUX_SRCDIR ?= linux-$(LINUX_VER)
   10.11  
   10.12 +KETCHUP ?= python buildconfigs/ketchup
   10.13 +
   10.14  vpath linux-%.tar.bz2 $(LINUX_SRC_PATH)
   10.15  
   10.16  # download a pristine Linux kernel tarball if there isn't one in LINUX_SRC_PATH
   10.17 @@ -12,6 +17,11 @@ linux-%.tar.bz2:
   10.18  
   10.19  # XXX create a pristine tree for diff -Nurp convenience
   10.20  
   10.21 +ifeq ($(XEN_LINUX_TARBALL_KETCHUP),y)
   10.22 +%/.valid-src:
   10.23 +	$(KETCHUP) -d $(@D) $(LINUX_VER)
   10.24 +	touch $@ # update timestamp to avoid rebuild
   10.25 +else
   10.26  %/.valid-src: %.tar.bz2
   10.27  	rm -rf tmp-linux-$* $(@D)
   10.28  	mkdir -p tmp-linux-$*
   10.29 @@ -19,5 +29,5 @@ linux-%.tar.bz2:
   10.30  	-@rm -f tmp-linux-$*/pax_global_header
   10.31  	mv tmp-linux-$*/* $(@D)
   10.32  	@rm -rf tmp-linux-$*
   10.33 -	touch $(@D)/.hgskip
   10.34  	touch $@ # update timestamp to avoid rebuild
   10.35 +endif
    11.1 --- a/docs/man/xm.pod.1	Mon Jul 09 09:22:58 2007 -0600
    11.2 +++ b/docs/man/xm.pod.1	Tue Jul 10 08:39:26 2007 -0600
    11.3 @@ -4,7 +4,7 @@ xm - Xen management user interface
    11.4  
    11.5  =head1 SYNOPSIS
    11.6  
    11.7 -xm <subcommand> [args]
    11.8 +B<xm> I<subcommand> [I<args>]
    11.9  
   11.10  =head1 DESCRIPTION
   11.11  
   11.12 @@ -13,46 +13,50 @@ domains. The program can be used to crea
   11.13  domains. It can also be used to list current domains, enable or pin
   11.14  VCPUs, and attach or detach virtual block devices.
   11.15  
   11.16 -The basic structure of every xm command is almost always:
   11.17 +The basic structure of every B<xm> command is almost always:
   11.18 +
   11.19 +=over 2
   11.20  
   11.21 -  xm <subcommand> <domain-id> [OPTIONS]
   11.22 +B<xm> I<subcommand> I<domain-id> [I<OPTIONS>]
   11.23  
   11.24 -Where I<subcommand> is one of the sub commands listed below, I<domain-id>
   11.25 +=back
   11.26 +
   11.27 +Where I<subcommand> is one of the subcommands listed below, I<domain-id>
   11.28  is the numeric domain id, or the domain name (which will be internally
   11.29 -translated to domain id), and I<OPTIONS> are sub command specific
   11.30 +translated to domain id), and I<OPTIONS> are subcommand specific
   11.31  options.  There are a few exceptions to this rule in the cases where
   11.32 -the sub command in question acts on all domains, the entire machine,
   11.33 -or directly on the xen hypervisor.  Those exceptions will be clear for
   11.34 -each of those sub commands.
   11.35 +the subcommand in question acts on all domains, the entire machine,
   11.36 +or directly on the Xen hypervisor.  Those exceptions will be clear for
   11.37 +each of those subcommands.
   11.38  
   11.39  =head1 NOTES
   11.40  
   11.41  All B<xm> operations rely upon the Xen control daemon, aka B<xend>.
   11.42 -For any xm commands to run xend must also be running.  For this reason
   11.43 -you should start xend as a service when your system first boots using
   11.44 -xen.
   11.45 +For any B<xm> commands to run, xend must also be running.  For this
   11.46 +reason you should start xend as a service when your system first boots
   11.47 +using Xen.
   11.48  
   11.49  Most B<xm> commands require root privileges to run due to the
   11.50  communications channels used to talk to the hypervisor.  Running as
   11.51  non root will return an error.
   11.52  
   11.53  Most B<xm> commands act asynchronously, so just because the B<xm>
   11.54 -command returned, doesn't mean the action is complete.  This is
   11.55 +command returned doesn't mean the action is complete.  This is
   11.56  important, as many operations on domains, like create and shutdown,
   11.57  can take considerable time (30 seconds or more) to bring the machine
   11.58  into a fully compliant state.  If you want to know when one of these
   11.59 -actions has finished you must poll through xm list periodically.
   11.60 +actions has finished you must poll through B<xm list> periodically.
   11.61  
   11.62  =head1 DOMAIN SUBCOMMANDS
   11.63  
   11.64 -The following sub commands manipulate domains directly, as stated
   11.65 -previously most commands take domain-id as the first parameter.
   11.66 +The following subcommands manipulate domains directly.  As stated
   11.67 +previously, most commands take I<domain-id> as the first parameter.
   11.68  
   11.69  =over 4
   11.70  
   11.71  =item B<console> I<domain-id>
   11.72  
   11.73 -Attach to domain domain-id's console.  If you've set up your Domains to
   11.74 +Attach to domain I<domain-id>'s console.  If you've set up your domains to
   11.75  have a traditional log in console this will look much like a normal
   11.76  text log in screen.
   11.77  
   11.78 @@ -63,15 +67,15 @@ The attached console will perform much l
   11.79  so running curses based interfaces over the console B<is not
   11.80  advised>.  Vi tends to get very odd when using it over this interface.
   11.81  
   11.82 -=item B<create> I<[-c]> I<configfile> I<[name=value]>..
   11.83 +=item B<create> [B<-c>] I<configfile> [I<name>=I<value>]..
   11.84  
   11.85 -The create sub command requires a configfile and can optional take a
   11.86 +The create sub command requires a config file and can optionally take a
   11.87  series of name value pairs that add to or override variables defined
   11.88  in the config file.  See L<xmdomain.cfg> for full details of that file
   11.89  format, and possible options used in either the configfile or
   11.90 -Name=Value combinations.
   11.91 +I<name>=I<value> combinations.
   11.92  
   11.93 -Configfile can either be an absolute path to a file, or a relative
   11.94 +I<configfile> can either be an absolute path to a file, or a relative
   11.95  path to a file located in /etc/xen.
   11.96  
   11.97  Create will return B<as soon> as the domain is started.  This B<does
   11.98 @@ -116,10 +120,10 @@ virtual networking.  (This example comes
   11.99  
  11.100  =item B<destroy> I<domain-id>
  11.101  
  11.102 -Immediately terminate the domain domain-id.  This doesn't give the domain
  11.103 -OS any chance to react, and it the equivalent of ripping the power
  11.104 -cord out on a physical machine.  In most cases you will want to use
  11.105 -the B<shutdown> command instead.
  11.106 +Immediately terminate the domain I<domain-id>.  This doesn't give the
  11.107 +domain OS any chance to react, and is the equivalent of ripping the
  11.108 +power cord out on a physical machine.  In most cases you will want to
  11.109 +use the B<shutdown> command instead.
  11.110  
  11.111  =item B<domid> I<domain-name>
  11.112  
  11.113 @@ -129,14 +133,14 @@ Converts a domain name to a domain id us
  11.114  
  11.115  Converts a domain id to a domain name using xend's internal mapping.
  11.116  
  11.117 -=item B<help> I<[--long]>
  11.118 +=item B<help> [B<--long>]
  11.119  
  11.120  Displays the short help message (i.e. common commands).
  11.121  
  11.122 -The I<--long> option prints out the complete set of B<xm> subcommands,
  11.123 +The B<--long> option prints out the complete set of B<xm> subcommands,
  11.124  grouped by function.
  11.125  
  11.126 -=item B<list> I<[--long | --label]> I<[domain-id, ...]>
  11.127 +=item B<list> [B<--long> | B<--label>] [I<domain-id> ...]
  11.128  
  11.129  Prints information about one or more domains.  If no domains are
  11.130  specified it prints out information about all domains.
  11.131 @@ -151,21 +155,23 @@ An example format for the list is as fol
  11.132      Mandrake10.2                167      128     1 ------     2.5
  11.133      Suse9.2                     168      100     1 ------     1.8
  11.134  
  11.135 -Name is the name of the domain.  ID the domain numeric id.  Mem is the
  11.136 -size of the memory allocated to the domain.  VCPUS is the number of
  11.137 -VCPUS allocated to domain.  State is the run state (see below).  Time
  11.138 -is the total run time of the domain as accounted for by Xen.
  11.139 +Name is the name of the domain.  ID the numeric domain id.  Mem is the
  11.140 +desired amount of memory to allocate to the domain (although it may
  11.141 +not be the currently allocated amount).  VCPUs is the number of
  11.142 +virtual CPUs allocated to the domain.  State is the run state (see
  11.143 +below).  Time is the total run time of the domain as accounted for by
  11.144 +Xen.
  11.145  
  11.146  B<STATES>
  11.147  
  11.148  =over 4
  11.149  
  11.150 -The State field lists 6 states for a Xen Domain, and which ones the
  11.151 -current Domain is in.
  11.152 +The State field lists 6 states for a Xen domain, and which ones the
  11.153 +current domain is in.
  11.154  
  11.155  =item B<r - running>
  11.156  
  11.157 -The domain is currently running on a CPU
  11.158 +The domain is currently running on a CPU.
  11.159  
  11.160  =item B<b - blocked>
  11.161  
  11.162 @@ -203,12 +209,12 @@ B<LONG OUTPUT>
  11.163  
  11.164  =over 4
  11.165  
  11.166 -If I<--long> is specified, the output for xm list is not the table
  11.167 +If B<--long> is specified, the output for B<xm list> is not the table
  11.168  view shown above, but instead is an S-Expression representing all
  11.169  information known about all domains asked for.  This is mostly only
  11.170  useful for external programs to parse the data.
  11.171  
  11.172 -B<Note:> there is no stable guarantees on the format of this data.
  11.173 +B<Note:> There is no stable guarantees on the format of this data.
  11.174  Use at your own risk.
  11.175  
  11.176  =back
  11.177 @@ -217,10 +223,10 @@ B<LABEL OUTPUT>
  11.178  
  11.179  =over 4
  11.180  
  11.181 -If I<--label> is specified, the security labels are added to the
  11.182 -output of xm list and the lines are sorted by the labels (ignoring
  11.183 -case). The I<--long> option prints the labels by default and cannot be
  11.184 -combined with I<--label>. See the ACCESS CONTROL SUBCOMMAND section of
  11.185 +If B<--label> is specified, the security labels are added to the
  11.186 +output of B<xm list> and the lines are sorted by the labels (ignoring
  11.187 +case). The B<--long> option prints the labels by default and cannot be
  11.188 +combined with B<--label>. See the ACCESS CONTROL SUBCOMMAND section of
  11.189  this man page for more information about labels.
  11.190  
  11.191  ==back
  11.192 @@ -230,7 +236,7 @@ B<NOTES>
  11.193  =over 4
  11.194  
  11.195  The Time column is deceptive.  Virtual IO (network and block devices)
  11.196 -used by Domains requires coordination by Domain0, which means that
  11.197 +used by domains requires coordination by Domain0, which means that
  11.198  Domain0 is actually charged for much of the time that a DomainU is
  11.199  doing IO.  Use of this time value to determine relative utilizations
  11.200  by domains is thus very suspect, as a high IO workload may show as
  11.201 @@ -240,11 +246,11 @@ less utilized than a high CPU workload. 
  11.202  
  11.203  =item B<mem-max> I<domain-id> I<mem>
  11.204  
  11.205 -Specify the maximum amount of memory the Domain is able to use.  Mem
  11.206 +Specify the maximum amount of memory the domain is able to use.  I<mem>
  11.207  is specified in megabytes. 
  11.208  
  11.209  The mem-max value may not correspond to the actual memory used in the
  11.210 -Domain, as it may balloon down it's memory to give more back to the OS.
  11.211 +domain, as it may balloon down its memory to give more back to the OS.
  11.212  
  11.213  =item B<mem-set> I<domain-id> I<mem>
  11.214  
  11.215 @@ -252,20 +258,20 @@ Set the domain's used memory using the b
  11.216  operation requires cooperation from the domain operating system, there
  11.217  is no guarantee that it will succeed.
  11.218  
  11.219 -B<Warning:> there is no good way to know in advance how small of a
  11.220 +B<Warning:> There is no good way to know in advance how small of a
  11.221  mem-set will make a domain unstable and cause it to crash.  Be very
  11.222  careful when using this command on running domains.
  11.223  
  11.224 -=item B<migrate> I<domain-id> I<host> I<[options]>
  11.225 +=item B<migrate> I<domain-id> I<host> [I<OPTIONS>]
  11.226  
  11.227 -Migrate a domain to another Host machine. B<Xend> must be running on
  11.228 -other host machine, it must be running the same version of xen, it
  11.229 +Migrate a domain to another host machine. Xend must be running on
  11.230 +other host machine, it must be running the same version of Xen, it
  11.231  must have the migration TCP port open and accepting connections from
  11.232  the source host, and there must be sufficient resources for the domain
  11.233  to run (memory, disk, etc).
  11.234  
  11.235 -Migration is pretty complicated, and has many security implications,
  11.236 -please read the Xen Users Guide to ensure you understand the
  11.237 +Migration is pretty complicated, and has many security implications.
  11.238 +Please read the Xen User's Guide to ensure you understand the
  11.239  ramifications and limitations on migration before attempting it in
  11.240  production.
  11.241  
  11.242 @@ -273,13 +279,13 @@ B<OPTIONS>
  11.243  
  11.244  =over 4
  11.245  
  11.246 -=item B<-l, --live>
  11.247 +=item B<-l>, B<--live>
  11.248  
  11.249  Use live migration.  This will migrate the domain between hosts
  11.250 -without shutting down the domain.  See the Xen Users Guide for more
  11.251 +without shutting down the domain.  See the Xen User's Guide for more
  11.252  information.
  11.253  
  11.254 -=item B<-r, --resource> I<Mbs>
  11.255 +=item B<-r>, B<--resource> I<Mbs>
  11.256  
  11.257  Set maximum Mbs allowed for migrating the domain.  This ensures that
  11.258  the network link is not saturated with migration traffic while
  11.259 @@ -293,7 +299,7 @@ Pause a domain.  When in a paused state 
  11.260  allocated resources such as memory, but will not be eligible for
  11.261  scheduling by the Xen hypervisor.
  11.262  
  11.263 -=item B<reboot> I<[options]> I<domain-id>
  11.264 +=item B<reboot> [I<OPTIONS>] I<domain-id>
  11.265  
  11.266  Reboot a domain.  This acts just as if the domain had the B<reboot>
  11.267  command run from the console.  The command returns as soon as it has
  11.268 @@ -301,18 +307,18 @@ executed the reboot action, which may be
  11.269  domain actually reboots.
  11.270  
  11.271  The behavior of what happens to a domain when it reboots is set by the
  11.272 -I<on_reboot> parameter of the xmdomain.cfg file when the domain was
  11.273 +B<on_reboot> parameter of the xmdomain.cfg file when the domain was
  11.274  created.
  11.275  
  11.276  B<OPTIONS>
  11.277  
  11.278  =over 4
  11.279  
  11.280 -=item B<-a, --all>
  11.281 +=item B<-a>, B<--all>
  11.282  
  11.283 -Reboot all domains
  11.284 +Reboot all domains.
  11.285  
  11.286 -=item B<-w, --wait>
  11.287 +=item B<-w>, B<--wait>
  11.288  
  11.289  Wait for reboot to complete before returning.  This may take a while,
  11.290  as all services in the domain will have to be shut down cleanly.
  11.291 @@ -321,7 +327,7 @@ as all services in the domain will have 
  11.292  
  11.293  =item B<restore> I<state-file>
  11.294  
  11.295 -Build a domain from an B<xm save> state file.  See I<save> for more info.
  11.296 +Build a domain from an B<xm save> state file.  See B<save> for more info.
  11.297  
  11.298  =item B<save> I<domain-id> I<state-file>
  11.299  
  11.300 @@ -334,16 +340,16 @@ This is roughly equivalent to doing a hi
  11.301  with all the same limitations.  Open network connections may be
  11.302  severed upon restore, as TCP timeouts may have expired.
  11.303  
  11.304 -=item B<shutdown> I<[options]> I<domain-id>
  11.305 +=item B<shutdown> [I<OPTIONS>] I<domain-id>
  11.306  
  11.307  Gracefully shuts down a domain.  This coordinates with the domain OS
  11.308  to perform graceful shutdown, so there is no guarantee that it will
  11.309  succeed, and may take a variable length of time depending on what
  11.310  services must be shutdown in the domain.  The command returns
  11.311 -immediately after signally the domain unless that I<-w> flag is used.
  11.312 +immediately after signally the domain unless that B<-w> flag is used.
  11.313  
  11.314  The behavior of what happens to a domain when it reboots is set by the
  11.315 -I<on_shutdown> parameter of the xmdomain.cfg file when the domain was
  11.316 +B<on_shutdown> parameter of the xmdomain.cfg file when the domain was
  11.317  created.
  11.318  
  11.319  B<OPTIONS>
  11.320 @@ -386,7 +392,7 @@ Attempting to set the VCPUs to a number 
  11.321  configured VCPU count is an error.  Trying to set VCPUs to < 1 will be
  11.322  quietly ignored.
  11.323  
  11.324 -=item B<vcpu-list> I<[domain-id]>
  11.325 +=item B<vcpu-list> [I<domain-id>]
  11.326  
  11.327  Lists VCPU information for a specific domain.  If no domain is
  11.328  specified, VCPU information for all domains will be provided.
  11.329 @@ -394,7 +400,7 @@ specified, VCPU information for all doma
  11.330  =item B<vcpu-pin> I<domain-id> I<vcpu> I<cpus>
  11.331  
  11.332  Pins the the VCPU to only run on the specific CPUs.  The keyword
  11.333 -I<all> can be used to apply the I<cpus> list to all VCPUs in the
  11.334 +B<all> can be used to apply the I<cpus> list to all VCPUs in the
  11.335  domain.
  11.336  
  11.337  Normally VCPUs can float between available CPUs whenever Xen deems a
  11.338 @@ -408,7 +414,7 @@ CPUs.
  11.339  
  11.340  =over 4
  11.341  
  11.342 -=item B<dmesg> I<[-c]>
  11.343 +=item B<dmesg> [B<-c>]
  11.344  
  11.345  Reads the Xen message buffer, similar to dmesg on a Linux system.  The
  11.346  buffer contains informational, warning, and error messages created
  11.347 @@ -419,7 +425,7 @@ B<OPTIONS>
  11.348  
  11.349  =over 4
  11.350  
  11.351 -=item B<-c, --clear>
  11.352 +=item B<-c>, B<--clear>
  11.353  
  11.354  Clears Xen's message buffer.
  11.355  
  11.356 @@ -431,8 +437,8 @@ Print information about the Xen host in 
  11.357  reporting a Xen bug, please provide this information as part of the
  11.358  bug report.
  11.359  
  11.360 -Sample xen domain info looks as follows (lines wrapped manually to
  11.361 -make the man page more readable):
  11.362 +Sample output looks as follows (lines wrapped manually to make the man
  11.363 +page more readable):
  11.364  
  11.365   host                   : talon
  11.366   release                : 2.6.12.6-xen0
  11.367 @@ -470,36 +476,36 @@ B<FIELDS>
  11.368  Not all fields will be explained here, but some of the less obvious
  11.369  ones deserve explanation:
  11.370  
  11.371 -=item I<hw_caps>
  11.372 +=item B<hw_caps>
  11.373  
  11.374  A vector showing what hardware capabilities are supported by your
  11.375  processor.  This is equivalent to, though more cryptic, the flags
  11.376  field in /proc/cpuinfo on a normal Linux machine.
  11.377  
  11.378 -=item I<free_memory>
  11.379 +=item B<free_memory>
  11.380  
  11.381 -Available memory (in MB) not allocated to Xen, or any other Domains.
  11.382 +Available memory (in MB) not allocated to Xen, or any other domains.
  11.383  
  11.384 -=item I<xen_caps>
  11.385 +=item B<xen_caps>
  11.386  
  11.387 -The xen version, architecture.  Architecture values can be one of:
  11.388 +The Xen version and architecture.  Architecture values can be one of:
  11.389  x86_32, x86_32p (i.e. PAE enabled), x86_64, ia64.
  11.390  
  11.391 -=item I<xen_changeset>
  11.392 +=item B<xen_changeset>
  11.393  
  11.394 -The xen mercurial changeset id.  Very useful for determining exactly
  11.395 +The Xen mercurial changeset id.  Very useful for determining exactly
  11.396  what version of code your Xen system was built from.
  11.397  
  11.398  =back
  11.399  
  11.400  =item B<log>
  11.401  
  11.402 -Print out the B<xend> log.  This log file can be found in
  11.403 +Print out the xend log.  This log file can be found in
  11.404  /var/log/xend.log.
  11.405  
  11.406  =item B<top>
  11.407  
  11.408 -Executes the xentop command, which provides real time monitoring of
  11.409 +Executes the B<xentop> command, which provides real time monitoring of
  11.410  domains.  Xentop is a curses interface, and reasonably self
  11.411  explanatory.
  11.412  
  11.413 @@ -508,13 +514,41 @@ explanatory.
  11.414  =head1 SCHEDULER SUBCOMMANDS
  11.415  
  11.416  Xen ships with a number of domain schedulers, which can be set at boot
  11.417 -time with the I<sched=> parameter on the Xen command line.  By
  11.418 -default I<sedf> is used for scheduling.
  11.419 +time with the B<sched=> parameter on the Xen command line.  By
  11.420 +default B<credit> is used for scheduling.
  11.421  
  11.422  FIXME: we really need a scheduler expert to write up this section.
  11.423  
  11.424  =over 4
  11.425  
  11.426 +=item B<sched-credit> [ B<-d> I<domain-id> [ B<-w>[B<=>I<WEIGHT>] | B<-c>[B<=>I<CAP>] ] ]
  11.427 +
  11.428 +Set credit scheduler parameters.  The credit scheduler is a
  11.429 +proportional fair share CPU scheduler built from the ground up to be
  11.430 +work conserving on SMP hosts.
  11.431 +
  11.432 +Each domain (including Domain0) is assigned a weight and a cap.
  11.433 +
  11.434 +B<PARAMETERS>
  11.435 +
  11.436 +=over 4
  11.437 +
  11.438 +=item I<WEIGHT>
  11.439 +
  11.440 +A domain with a weight of 512 will get twice as much CPU as a domain
  11.441 +with a weight of 256 on a contended host. Legal weights range from 1
  11.442 +to 65535 and the default is 256.
  11.443 +
  11.444 +=item I<CAP>
  11.445 +
  11.446 +The cap optionally fixes the maximum amount of CPU a domain will be
  11.447 +able to consume, even if the host system has idle CPU cycles. The cap
  11.448 +is expressed in percentage of one physical CPU: 100 is 1 physical CPU,
  11.449 +50 is half a CPU, 400 is 4 CPUs, etc. The default, 0, means there is
  11.450 +no upper cap.
  11.451 +
  11.452 +=back
  11.453 +
  11.454  =item B<sched-sedf> I<period> I<slice> I<latency-hint> I<extratime> I<weight>
  11.455  
  11.456  Set Simple EDF (Earliest Deadline First) scheduler parameters.  This
  11.457 @@ -546,7 +580,7 @@ Flag for allowing domain to run in extra
  11.458  
  11.459  =item I<weight>
  11.460  
  11.461 -Another way of setting cpu slice.
  11.462 +Another way of setting CPU slice.
  11.463  
  11.464  =back
  11.465  
  11.466 @@ -591,7 +625,7 @@ event.
  11.467  
  11.468  =over 4
  11.469  
  11.470 -=item B<block-attach> I<domain-id> I<be-dev> I<fe-dev> I<mode> I<[bedomain-id]>
  11.471 +=item B<block-attach> I<domain-id> I<be-dev> I<fe-dev> I<mode> [I<bedomain-id>]
  11.472  
  11.473  Create a new virtual block device.  This will trigger a hotplug event
  11.474  for the guest.
  11.475 @@ -619,7 +653,7 @@ devices, or by device id, such as 0x1400
  11.476  =item I<mode>
  11.477  
  11.478  The access mode for the device from the guest domain.  Supported modes
  11.479 -are I<w> (read/write) or I<r> (read-only).
  11.480 +are B<w> (read/write) or B<r> (read-only).
  11.481  
  11.482  =item I<bedomain-id>
  11.483  
  11.484 @@ -635,62 +669,65 @@ B<EXAMPLES>
  11.485  
  11.486  xm block-attach guestdomain file://path/to/dsl-2.0RC2.iso /dev/hdc ro
  11.487  
  11.488 -This will mount the dsl iso as /dev/hdc in the guestdomain as a read
  11.489 -only device.  This will probably not be detected as a cdrom by the
  11.490 +This will mount the dsl ISO as /dev/hdc in the guestdomain as a read
  11.491 +only device.  This will probably not be detected as a CD-ROM by the
  11.492  guest, but mounting /dev/hdc manually will work.
  11.493  
  11.494  =back
  11.495  
  11.496 -=item B<block-detach> I<domain-id> I<devid>
  11.497 +=item B<block-detach> I<domain-id> I<devid> [B<--force>]
  11.498 +
  11.499 +Detach a domain's virtual block device. I<devid> may be the symbolic
  11.500 +name or the numeric device id given to the device by domain 0.  You
  11.501 +will need to run B<xm block-list> to determine that number.
  11.502  
  11.503 -Destroy a domain's virtual block device. devid B<must> be the device
  11.504 -id given to the device by domain 0.  You will need to run I<xm
  11.505 -block-list> to determine that number.
  11.506 +Detaching the device requires the cooperation of the domain.  If the
  11.507 +domain fails to release the device (perhaps because the domain is hung
  11.508 +or is still using the device), the detach will fail.  The B<--force>
  11.509 +parameter will forcefully detach the device, but may cause IO errors
  11.510 +in the domain.
  11.511  
  11.512 -FIXME: this is currently B<broken>.  Even though a block device is
  11.513 -removed from domU, it appears to still be allocated in the domain 0.
  11.514 -
  11.515 -=item B<block-list> I<[-l|--long]> I<domain-id>
  11.516 +=item B<block-list> [B<-l>|B<--long>] I<domain-id>
  11.517  
  11.518  List virtual block devices for a domain.  The returned output is
  11.519 -formatted as a list or as an S-Expression if the '--long' option was given.
  11.520 +formatted as a list or as an S-Expression if the B<--long> option was given.
  11.521  
  11.522  =head2 NETWORK DEVICES
  11.523  
  11.524 -=item B<network-attach> I<domain-id> I<[script=scriptname]> I<[ip=ipaddr]>
  11.525 -I<[mac=macaddr]> I<[bridge=bridge-name]> I<[backend=bedomain-id]>
  11.526 +=item B<network-attach> I<domain-id> [B<script=>I<scriptname>] [B<ip=>I<ipaddr>]
  11.527 +[B<mac=>I<macaddr>] [B<bridge=>I<bridge-name>] [B<backend=>I<bedomain-id>]
  11.528  
  11.529 -Creates a new network device in the domain specified by domain-id.  It
  11.530 +Creates a new network device in the domain specified by I<domain-id>.  It
  11.531  takes the following optional options:
  11.532  
  11.533  B<OPTIONS>
  11.534  
  11.535  =over 4
  11.536  
  11.537 -=item I<script=scriptname>
  11.538 +=item B<script=>I<scriptname>
  11.539  
  11.540  Use the specified script name to bring up the network.  Defaults to
  11.541 -the default setting in xend-config.sxp for I<vif-script>.
  11.542 +the default setting in xend-config.sxp for B<vif-script>.
  11.543  
  11.544 -=item I<ip=ipaddr>
  11.545 +=item B<ip=>I<ipaddr>
  11.546  
  11.547  Passes the specified IP Address to the adapter on creation.  
  11.548  
  11.549  FIXME: this currently appears to be B<broken>.  I'm not sure under what
  11.550  circumstances this should actually work.
  11.551  
  11.552 -=item I<mac=macaddr>
  11.553 +=item B<mac=>I<macaddr>
  11.554  
  11.555  The MAC address that the domain will see on its Ethernet device.  If
  11.556  the device is not specified it will be randomly generated with the
  11.557  00:16:3e vendor id prefix.
  11.558  
  11.559 -=item I<bridge=bridge-name>
  11.560 +=item B<bridge=>I<bridge-name>
  11.561  
  11.562  The name of the bridge to attach the vif to, in case you have more
  11.563 -than one.  This defaults to 
  11.564 +than one.  This defaults to xenbr0.
  11.565  
  11.566 -=item I<backend=bedomain-id>
  11.567 +=item B<backend=>I<bedomain-id>
  11.568  
  11.569  The backend domain id.  By default this is domain 0.
  11.570  
  11.571 @@ -705,17 +742,17 @@ I<devid> is the virtual interface device
  11.572  FIXME: this is currently B<broken>.  Network devices aren't completely
  11.573  removed from domain 0.
  11.574  
  11.575 -=item B<network-list> I<[-l|--long]> I<domain-id>
  11.576 +=item B<network-list> [B<-l>|B<--long>]> I<domain-id>
  11.577  
  11.578  List virtual network interfaces for a domain.  The returned output is
  11.579 -formatted as a list or as an S-Expression if the '--long' option was given.
  11.580 +formatted as a list or as an S-Expression if the B<--long> option was given.
  11.581  
  11.582  =head2 VIRTUAL TPM DEVICES
  11.583  
  11.584 -=item B<vtpm-list> I<[-l|--long]> I<domain-id>
  11.585 +=item B<vtpm-list> [B<-l>|B<--long>] I<domain-id>
  11.586  
  11.587  Show the virtual TPM device for a domain.  The returned output is
  11.588 -formatted as a list or as an S-Expression if the '--long' option was given.
  11.589 +formatted as a list or as an S-Expression if the B<--long> option was given.
  11.590  
  11.591  =back
  11.592  
  11.593 @@ -728,7 +765,7 @@ out entirely.
  11.594  
  11.595  =over 4
  11.596  
  11.597 -=item B<vnet-list> I<[-l|--long]>
  11.598 +=item B<vnet-list> [B<-l>|B<--long>]
  11.599  
  11.600  List vnets.
  11.601  
  11.602 @@ -762,7 +799,7 @@ subcommands described below. Currently, 
  11.603  interpret labels:
  11.604  
  11.605  (1) Simple Type Enforcement: Labels are interpreted to decide access
  11.606 -of domains to comunication means and virtual or physical
  11.607 +of domains to communication means and virtual or physical
  11.608  resources. Communication between domains as well as access to
  11.609  resources are forbidden by default and can only take place if they are
  11.610  explicitly allowed by the security policy. The proper assignment of
  11.611 @@ -796,8 +833,8 @@ time with the B<cfgbootpolicy> subcomman
  11.612  =over 4
  11.613  
  11.614  I<policy> is a dot-separated list of names. The last part is the file
  11.615 -name pre-fix for the policy xml file. The preceding name parts are
  11.616 -translated into the local path pointing to the policy xml file
  11.617 +name pre-fix for the policy XML file. The preceding name parts are
  11.618 +translated into the local path pointing to the policy XML file
  11.619  relative to the global policy root directory
  11.620  (/etc/xen/acm-security/policies). For example,
  11.621  example.chwall_ste.client_v1 denotes the policy file
  11.622 @@ -823,16 +860,16 @@ I<boot title> parameter to specify a uni
  11.623  
  11.624  Prints the current security policy state information of Xen.
  11.625  
  11.626 -=item B<labels> [I<policy>] [I<type>=dom|res|any]
  11.627 +=item B<labels> [I<policy>] [B<type=dom>|B<res>|B<any>]
  11.628  
  11.629  Lists all labels of a I<type> (domain, resource, or both) that are
  11.630  defined in the I<policy>. Unless specified, the default I<policy> is
  11.631  the currently enforced access control policy. The default for I<type>
  11.632  is 'dom'. The labels are arranged in alphabetical order.
  11.633  
  11.634 -=item B<addlabel> I<label> dom I<configfile> [I<policy>]
  11.635 +=item B<addlabel> I<label> B<dom> I<configfile> [I<policy>]
  11.636  
  11.637 -=item B<addlabel> I<label> res I<resource> [I<policy>]
  11.638 +=item B<addlabel> I<label> B<res> I<resource> [I<policy>]
  11.639  
  11.640  Adds the security label with name I<label> to a domain
  11.641  I<configfile> (dom) or to the global resource label file for the
  11.642 @@ -841,17 +878,17 @@ currently enforced access control policy
  11.643  verifies that the I<policy> definition supports the specified I<label>
  11.644  name.
  11.645  
  11.646 -=item B<rmlabel> dom I<configfile>
  11.647 +=item B<rmlabel> B<dom> I<configfile>
  11.648  
  11.649 -=item B<rmlabel> res I<resource>
  11.650 +=item B<rmlabel> B<res> I<resource>
  11.651  
  11.652 -Works the same as the I<addlabel> command (above), except that this
  11.653 +Works the same as the B<addlabel> command (above), except that this
  11.654  command will remove the label from the domain I<configfile> (dom) or
  11.655  the global resource label file (res).
  11.656  
  11.657 -=item B<getlabel> dom I<configfile>
  11.658 +=item B<getlabel> B<dom> I<configfile>
  11.659  
  11.660 -=item B<getlabel> res I<resource>
  11.661 +=item B<getlabel> B<res> I<resource>
  11.662  
  11.663  Shows the label for the given I<configfile> or I<resource>
  11.664  
  11.665 @@ -881,7 +918,7 @@ Then recompile and install xen and the s
  11.666  
  11.667      cd xen_source_dir/xen; make clean; make; cp xen.gz /boot;
  11.668      cd xen_source_dir/tools/security; make install;
  11.669 -    reboot into xen
  11.670 +    reboot into Xen
  11.671  
  11.672  =back
  11.673  
  11.674 @@ -944,10 +981,10 @@ B<ATTACHING A SECURITY LABEL TO A DOMAIN
  11.675  
  11.676  =over 4
  11.677  
  11.678 -The I<addlabel> subcommand can attach a security label to a domain
  11.679 +The B<addlabel> subcommand can attach a security label to a domain
  11.680  configuration file, here a HomeBanking label. The example policy
  11.681  ensures that this domain does not share information with other
  11.682 -non-hombanking user domains (i.e., domains labeled as dom_Fun or
  11.683 +non-homebanking user domains (i.e., domains labeled as dom_Fun or
  11.684  dom_Boinc) and that it will not run simultaneously with domains
  11.685  labeled as dom_Fun.
  11.686  
  11.687 @@ -958,7 +995,7 @@ probably just a browser environment for 
  11.688      xm addlabel dom_HomeBanking dom myconfig.xm
  11.689  
  11.690  The very simple configuration file might now look as printed
  11.691 -below. The I<addlabel> subcommand added the B<access_control> entry at
  11.692 +below. The B<addlabel> subcommand added the B<access_control> entry at
  11.693  the end of the file, consisting of a label name and the policy that
  11.694  specifies this label name:
  11.695  
  11.696 @@ -986,7 +1023,7 @@ B<ATTACHING A SECURITY LABEL TO A RESOUR
  11.697  
  11.698  =over 4
  11.699  
  11.700 -The I<addlabel> subcommand can also be used to attach a security
  11.701 +The B<addlabel> subcommand can also be used to attach a security
  11.702  label to a resource. Following the home banking example from above,
  11.703  we can label a disk resource (e.g., a physical partition or a file)
  11.704  to make it accessible to the home banking domain. The example policy
  11.705 @@ -1002,7 +1039,7 @@ attaches this disk to the domain at boot
  11.706      disk = [ 'phy:hda6,sda2,w' ]
  11.707  
  11.708  Alternatively, the resource can be attached after booting the domain
  11.709 -by using the I<block-attach> subcommand.
  11.710 +by using the B<block-attach> subcommand.
  11.711  
  11.712      xm block-attach homebanking phy:hda6 sda2 w
  11.713  
  11.714 @@ -1010,7 +1047,7 @@ Note that labeled resources cannot be us
  11.715  off.  Any attempt to use labeled resources with security turned off
  11.716  will result in a failure with a corresponding error message.  The
  11.717  solution is to enable security or, if security is no longer desired,
  11.718 -to remove the resource label using the I<rmlabel> subcommand.
  11.719 +to remove the resource label using the B<rmlabel> subcommand.
  11.720  
  11.721  =back
  11.722  
  11.723 @@ -1048,7 +1085,7 @@ B<POLICY REPRESENTATIONS>
  11.724  =over 4
  11.725  
  11.726  We distinguish three representations of the Xen access control policy:
  11.727 -the I<source XML> version, its I<binary> counterpart, and a I<mapping>
  11.728 +the source XML version, its binary counterpart, and a mapping
  11.729  representation that enables the tools to deterministically translate
  11.730  back and forth between label names of the XML policy and label
  11.731  identifiers of the binary policy. All three versions must be kept
  11.732 @@ -1075,8 +1112,6 @@ their binary identifiers (ssidrefs) used
  11.733  
  11.734  =back
  11.735  
  11.736 -=head1 EXAMPLES
  11.737 -
  11.738  =head1 SEE ALSO
  11.739  
  11.740  B<xmdomain.cfg>(5), B<xentop>(1)
    12.1 --- a/tools/blktap/drivers/Makefile	Mon Jul 09 09:22:58 2007 -0600
    12.2 +++ b/tools/blktap/drivers/Makefile	Tue Jul 10 08:39:26 2007 -0600
    12.3 @@ -10,7 +10,6 @@ LIBAIO_DIR   = ../../libaio/src
    12.4  
    12.5  CFLAGS   += -Werror
    12.6  CFLAGS   += -Wno-unused
    12.7 -CFLAGS   += -fno-strict-aliasing
    12.8  CFLAGS   += -I $(XEN_LIBXC) -I $(LIBAIO_DIR)
    12.9  CFLAGS   += $(INCLUDES) -I. -I../../xenstore 
   12.10  CFLAGS   += -D_GNU_SOURCE
    13.1 --- a/tools/blktap/lib/Makefile	Mon Jul 09 09:22:58 2007 -0600
    13.2 +++ b/tools/blktap/lib/Makefile	Tue Jul 10 08:39:26 2007 -0600
    13.3 @@ -16,7 +16,7 @@ SRCS     += xenbus.c blkif.c xs_api.c
    13.4  
    13.5  CFLAGS   += -Werror
    13.6  CFLAGS   += -Wno-unused
    13.7 -CFLAGS   += -fno-strict-aliasing -fPIC
    13.8 +CFLAGS   += -fPIC
    13.9  # get asprintf():
   13.10  CFLAGS   += -D _GNU_SOURCE
   13.11  
    14.1 --- a/tools/examples/init.d/xendomains	Mon Jul 09 09:22:58 2007 -0600
    14.2 +++ b/tools/examples/init.d/xendomains	Tue Jul 10 08:39:26 2007 -0600
    14.3 @@ -221,22 +221,26 @@ start()
    14.4      if [ "$XENDOMAINS_RESTORE" = "true" ] &&
    14.5         contains_something "$XENDOMAINS_SAVE"
    14.6      then
    14.7 -	XENDOMAINS_SAVED=`/bin/ls $XENDOMAINS_SAVE/* | grep -v 'lost+found'`
    14.8  	mkdir -p $(dirname "$LOCKFILE")
    14.9  	touch $LOCKFILE
   14.10  	echo -n "Restoring Xen domains:"
   14.11  	saved_domains=`ls $XENDOMAINS_SAVE`
   14.12 -	for dom in $XENDOMAINS_SAVED; do
   14.13 -	    echo -n " ${dom##*/}"
   14.14 -	    xm restore $dom
   14.15 -	    if [ $? -ne 0 ]; then
   14.16 -		rc_failed $?
   14.17 -		echo -n '!'
   14.18 -	    else
   14.19 -		# mv $dom ${dom%/*}/.${dom##*/}
   14.20 -		rm $dom
   14.21 -	    fi
   14.22 -	done
   14.23 +        for dom in $XENDOMAINS_SAVE/*; do
   14.24 +            if [ -f $dom ] ; then
   14.25 +                HEADER=`head -c 16 $dom | head -n 1 2> /dev/null`
   14.26 +                if [ $HEADER = "LinuxGuestRecord" ]; then
   14.27 +                    echo -n " ${dom##*/}"
   14.28 +                    xm restore $dom
   14.29 +                    if [ $? -ne 0 ]; then
   14.30 +                        rc_failed $?
   14.31 +                        echo -n '!'
   14.32 +                    else
   14.33 +                        # mv $dom ${dom%/*}/.${dom##*/}
   14.34 +                        rm $dom
   14.35 +                    fi
   14.36 +                fi
   14.37 +            fi
   14.38 +        done
   14.39  	echo .
   14.40      fi
   14.41  
   14.42 @@ -260,7 +264,6 @@ start()
   14.43  	    if [ $? -eq 0 ] || is_running $dom; then
   14.44  		echo -n "(skip)"
   14.45  	    else
   14.46 -		echo "(booting)"
   14.47  		xm create --quiet --defconfig $dom
   14.48  		if [ $? -ne 0 ]; then
   14.49  		    rc_failed $?
    15.1 --- a/tools/examples/xend-config.sxp	Mon Jul 09 09:22:58 2007 -0600
    15.2 +++ b/tools/examples/xend-config.sxp	Tue Jul 10 08:39:26 2007 -0600
    15.3 @@ -191,3 +191,9 @@
    15.4  # The default password for VNC console on HVM domain.
    15.5  # Empty string is no authentication.
    15.6  (vncpasswd '')
    15.7 +
    15.8 +# The default keymap to use for the VM's virtual keyboard
    15.9 +# when not specififed in VM's configuration
   15.10 +#(keymap 'en-us')
   15.11 +
   15.12 +
    16.1 --- a/tools/firmware/etherboot/README	Mon Jul 09 09:22:58 2007 -0600
    16.2 +++ b/tools/firmware/etherboot/README	Tue Jul 10 08:39:26 2007 -0600
    16.3 @@ -1,7 +1,8 @@
    16.4  
    16.5  This is an Etherboot option ROM for the rtl8139 NIC.  It has a few
    16.6 -non-standard settings, just to do with timeouts and when to give up.
    16.7 +non-standard settings, most to do with timeouts and when to give up,
    16.8 +and for stricter DHCP spec compliance.
    16.9  
   16.10  Rom-o-matic.net will provide this image at the following URL:
   16.11  
   16.12 -http://rom-o-matic.net/5.4.2/build.php?version=5.4.2&F=ignore&nic=rtl8139%3Artl8139+--+%5B0x10ec%2C0x8139%5D&ofmt=Binary+ROM+Image%28.zrom%29&arch=i386&ASK_BOOT=-1&BOOT_FIRST=BOOT_NIC&BOOT_SECOND=BOOT_NOTHING&BOOT_THIRD=BOOT_NOTHING&BOOT_INDEX=0&STATIC_CLIENT_IP=&STATIC_SUBNET_MASK=&STATIC_SERVER_IP=&STATIC_GATEWAY_IP=&STATIC_BOOTFILE=&EXIT_ON_FILE_LOAD_ERROR=on&DHCP_CLIENT_ID=&DHCP_CLIENT_ID_LEN=&DHCP_CLIENT_ID_TYPE=&DHCP_USER_CLASS=&DHCP_USER_CLASS_LEN=&ALLOW_ONLY_ENCAPSULATED=on&DEFAULT_BOOTFILE=&CONGESTED=on&BACKOFF_LIMIT=7&TIMEOUT=180&TRY_FLOPPY_FIRST=0&EXIT_IF_NO_OFFER=on&TAGGED_IMAGE=on&ELF_IMAGE=on&PXE_IMAGE=on&DOWNLOAD_PROTO_TFTP=on&COMCONSOLE=0x3F8&CONSPEED=9600&COMPARM=0x03&PXE_EXPORT=on&CONFIG_PCI=on&CONFIG_ISA=on&BUILD_ID=&PCBIOS=on&A=Get+ROM
   16.13 +http://rom-o-matic.net/5.4.3/build.php?version=5.4.3&F=ignore&nic=rtl8139%3Artl8139+--+%5B0x10ec%2C0x8139%5D&ofmt=Binary+ROM+Image%28.zrom%29&arch=i386&ASK_BOOT=-1&BOOT_FIRST=BOOT_NIC&BOOT_SECOND=BOOT_NOTHING&BOOT_THIRD=BOOT_NOTHING&BOOT_INDEX=0&STATIC_CLIENT_IP=&STATIC_SUBNET_MASK=&STATIC_SERVER_IP=&STATIC_GATEWAY_IP=&STATIC_BOOTFILE=&EXIT_ON_FILE_LOAD_ERROR=on&DHCP_CLIENT_ID=&DHCP_CLIENT_ID_LEN=&DHCP_CLIENT_ID_TYPE=&DHCP_USER_CLASS=&DHCP_USER_CLASS_LEN=&ALLOW_ONLY_ENCAPSULATED=on&DEFAULT_BOOTFILE=&CONGESTED=on&BACKOFF_LIMIT=7&TIMEOUT=180&TRY_FLOPPY_FIRST=0&EXIT_IF_NO_OFFER=on&TAGGED_IMAGE=on&ELF_IMAGE=on&PXE_IMAGE=on&DOWNLOAD_PROTO_TFTP=on&COMCONSOLE=0x3F8&CONSPEED=9600&COMPARM=0x03&PXE_EXPORT=on&CONFIG_PCI=on&CONFIG_ISA=on&BUILD_ID=&PCBIOS=on&PXE_DHCP_STRICT=on&A=Get+ROM
    17.1 Binary file tools/firmware/etherboot/eb-rtl8139.zrom has changed
    18.1 --- a/tools/firmware/rombios/rombios.c	Mon Jul 09 09:22:58 2007 -0600
    18.2 +++ b/tools/firmware/rombios/rombios.c	Tue Jul 10 08:39:26 2007 -0600
    18.3 @@ -4675,6 +4675,10 @@ int09_function(DI, SI, BP, SP, BX, DX, C
    18.4        write_byte(0x0040, 0x18, mf2_flags);
    18.5        break;
    18.6  
    18.7 +    case 0x53: /* Del */
    18.8 +        if ((shift_flags & 0x0c) == 0x0c) /* Ctrl + Alt */
    18.9 +            machine_reset();
   18.10 +        /* Fall through */
   18.11      default:
   18.12        if (scancode & 0x80) return; /* toss key releases ... */
   18.13        if (scancode > MAX_SCAN_CODE) {
    19.1 --- a/tools/firmware/vmxassist/vm86.c	Mon Jul 09 09:22:58 2007 -0600
    19.2 +++ b/tools/firmware/vmxassist/vm86.c	Tue Jul 10 08:39:26 2007 -0600
    19.3 @@ -594,16 +594,24 @@ movr(struct regs *regs, unsigned prefix,
    19.4  		TRACE((regs, regs->eip - eip,
    19.5  			"movb %%e%s, *0x%x", rnames[r], addr));
    19.6  		write8(addr, val);
    19.7 -		break;
    19.8 +		return 1;
    19.9  
   19.10  	case 0x8A: /* addr32 mov r/m8, r8 */
   19.11  		TRACE((regs, regs->eip - eip,
   19.12  			"movb *0x%x, %%%s", addr, rnames[r]));
   19.13  		setreg8(regs, r, read8(addr));
   19.14 -		break;
   19.15 +		return 1;
   19.16  
   19.17  	case 0x89: /* addr32 mov r16, r/m16 */
   19.18  		val = getreg32(regs, r);
   19.19 +		if ((modrm & 0xC0) == 0xC0) {
   19.20 +			if (prefix & DATA32)
   19.21 +				setreg32(regs, modrm & 7, val);
   19.22 +			else
   19.23 +				setreg16(regs, modrm & 7, MASK16(val));
   19.24 +			return 1;
   19.25 +		}
   19.26 +
   19.27  		if (prefix & DATA32) {
   19.28  			TRACE((regs, regs->eip - eip,
   19.29  				"movl %%e%s, *0x%x", rnames[r], addr));
   19.30 @@ -613,9 +621,17 @@ movr(struct regs *regs, unsigned prefix,
   19.31  				"movw %%%s, *0x%x", rnames[r], addr));
   19.32  			write16(addr, MASK16(val));
   19.33  		}
   19.34 -		break;
   19.35 +		return 1;
   19.36  
   19.37 -	case 0x8B: /* addr32 mov r/m16, r16 */
   19.38 +	case 0x8B: /* mov r/m16, r16 */
   19.39 +		if ((modrm & 0xC0) == 0xC0) {
   19.40 +			if (prefix & DATA32)
   19.41 +				setreg32(regs, r, addr);
   19.42 +			else
   19.43 +				setreg16(regs, r, MASK16(addr));
   19.44 +			return 1;
   19.45 +		}
   19.46 +
   19.47  		if (prefix & DATA32) {
   19.48  			TRACE((regs, regs->eip - eip,
   19.49  				"movl *0x%x, %%e%s", addr, rnames[r]));
   19.50 @@ -625,7 +641,7 @@ movr(struct regs *regs, unsigned prefix,
   19.51  				"movw *0x%x, %%%s", addr, rnames[r]));
   19.52  			setreg16(regs, r, read16(addr));
   19.53  		}
   19.54 -		break;
   19.55 +		return 1;
   19.56  
   19.57  	case 0xC6: /* addr32 movb $imm, r/m8 */
   19.58  		if ((modrm >> 3) & 7)
   19.59 @@ -634,9 +650,9 @@ movr(struct regs *regs, unsigned prefix,
   19.60  		write8(addr, val);
   19.61  		TRACE((regs, regs->eip - eip, "movb $0x%x, *0x%x",
   19.62  							val, addr));
   19.63 -		break;
   19.64 +		return 1;
   19.65  	}
   19.66 -	return 1;
   19.67 +	return 0;
   19.68  }
   19.69  
   19.70  /*
   19.71 @@ -816,8 +832,8 @@ mov_to_seg(struct regs *regs, unsigned p
   19.72  	 * 1) real->protected mode.
   19.73  	 * 2) protected->real mode.
   19.74  	 */
   19.75 -	if ((mode != VM86_REAL_TO_PROTECTED) &&
   19.76 -	    (mode != VM86_PROTECTED_TO_REAL))
   19.77 +	if (mode != VM86_REAL_TO_PROTECTED &&
   19.78 +	    mode != VM86_PROTECTED_TO_REAL)
   19.79  		return 0;
   19.80  
   19.81  	/* Register source only. */
   19.82 @@ -1037,8 +1053,8 @@ set_mode(struct regs *regs, enum vm86_mo
   19.83  {
   19.84  	switch (newmode) {
   19.85  	case VM86_REAL:
   19.86 -		if ((mode == VM86_PROTECTED_TO_REAL) ||
   19.87 -		    (mode == VM86_REAL_TO_PROTECTED)) {
   19.88 +		if (mode == VM86_PROTECTED_TO_REAL ||
   19.89 +		    mode == VM86_REAL_TO_PROTECTED) {
   19.90  			regs->eflags &= ~EFLAGS_TF;
   19.91  			real_mode(regs);
   19.92  		} else if (mode != VM86_REAL)
   19.93 @@ -1121,7 +1137,7 @@ jmpl_indirect(struct regs *regs, int pre
   19.94  
   19.95  	if (mode == VM86_REAL_TO_PROTECTED)		/* jump to protected mode */
   19.96  		set_mode(regs, VM86_PROTECTED);
   19.97 -	else if (mode == VM86_PROTECTED_TO_REAL)/* jump to real mode */
   19.98 +	else if (mode == VM86_PROTECTED_TO_REAL)	/* jump to real mode */
   19.99  		set_mode(regs, VM86_REAL);
  19.100  	else
  19.101  		panic("jmpl");
  19.102 @@ -1147,7 +1163,7 @@ retl(struct regs *regs, int prefix)
  19.103  
  19.104  	if (mode == VM86_REAL_TO_PROTECTED)		/* jump to protected mode */
  19.105  		set_mode(regs, VM86_PROTECTED);
  19.106 -	else if (mode == VM86_PROTECTED_TO_REAL)/* jump to real mode */
  19.107 +	else if (mode == VM86_PROTECTED_TO_REAL)	/* jump to real mode */
  19.108  		set_mode(regs, VM86_REAL);
  19.109  	else
  19.110  		panic("retl");
  19.111 @@ -1382,9 +1398,7 @@ opcode(struct regs *regs)
  19.112  
  19.113  		case 0x39: /* addr32 cmp r16, r/m16 */
  19.114  		case 0x3B: /* addr32 cmp r/m16, r16 */
  19.115 -			if (mode != VM86_REAL && mode != VM86_REAL_TO_PROTECTED)
  19.116 -				goto invalid;
  19.117 -			if ((prefix & ADDR32) == 0)
  19.118 +			if (mode == VM86_PROTECTED_TO_REAL || !(prefix & ADDR32))
  19.119  				goto invalid;
  19.120  			if (!cmp(regs, prefix, opc))
  19.121  				goto invalid;
  19.122 @@ -1427,37 +1441,17 @@ opcode(struct regs *regs)
  19.123  			}
  19.124  			continue;
  19.125  
  19.126 -		case 0x88: /* mov r8, r/m8 */
  19.127 -		case 0x8A: /* mov r/m8, r8 */
  19.128 -			if (mode != VM86_REAL && mode != VM86_REAL_TO_PROTECTED)
  19.129 -				goto invalid;
  19.130 -			if ((prefix & ADDR32) == 0)
  19.131 +		case 0x88: /* addr32 mov r8, r/m8 */
  19.132 +		case 0x8A: /* addr32 mov r/m8, r8 */
  19.133 +			if (mode == VM86_PROTECTED_TO_REAL || !(prefix & ADDR32))
  19.134  				goto invalid;
  19.135  			if (!movr(regs, prefix, opc))
  19.136  				goto invalid;
  19.137  			return OPC_EMULATED;
  19.138  
  19.139 -		case 0x89: /* addr32 mov r16, r/m16 */
  19.140 -			if (mode == VM86_PROTECTED_TO_REAL) {
  19.141 -				unsigned modrm = fetch8(regs);
  19.142 -				unsigned addr = operand(prefix, regs, modrm);
  19.143 -				unsigned val, r = (modrm >> 3) & 7;
  19.144 -
  19.145 -				if (prefix & DATA32) {
  19.146 -					val = getreg16(regs, r);
  19.147 -					write32(addr, val);
  19.148 -				} else {
  19.149 -					val = getreg32(regs, r);
  19.150 -					write16(addr, MASK16(val));
  19.151 -				}
  19.152 -				TRACE((regs, regs->eip - eip,
  19.153 -					"mov %%%s, *0x%x", rnames[r], addr));
  19.154 -				return OPC_EMULATED;
  19.155 -			}
  19.156 -		case 0x8B: /* addr32 mov r/m16, r16 */
  19.157 -			if (mode != VM86_REAL && mode != VM86_REAL_TO_PROTECTED)
  19.158 -				goto invalid;
  19.159 -			if ((prefix & ADDR32) == 0)
  19.160 +		case 0x89: /* mov r16, r/m16 */
  19.161 +		case 0x8B: /* mov r/m16, r16 */
  19.162 +			if (mode != VM86_PROTECTED_TO_REAL && !(prefix & ADDR32))
  19.163  				goto invalid;
  19.164  			if (!movr(regs, prefix, opc))
  19.165  				goto invalid;
  19.166 @@ -1469,7 +1463,7 @@ opcode(struct regs *regs)
  19.167  			return OPC_EMULATED;
  19.168  
  19.169  		case 0x8F: /* addr32 pop r/m16 */
  19.170 -			if ((prefix & ADDR32) == 0)
  19.171 +			if (!(prefix & ADDR32))
  19.172  				goto invalid;
  19.173  			if (!pop(regs, prefix, opc))
  19.174  				goto invalid;
  19.175 @@ -1498,48 +1492,48 @@ opcode(struct regs *regs)
  19.176  			return OPC_EMULATED;
  19.177  
  19.178  		case 0xA1: /* mov ax, r/m16 */
  19.179 -			{
  19.180 -				int addr, data;
  19.181 -				int seg = segment(prefix, regs, regs->vds);
  19.182 -				int offset = prefix & ADDR32? fetch32(regs) : fetch16(regs);
  19.183 +		{
  19.184 +			int addr, data;
  19.185 +			int seg = segment(prefix, regs, regs->vds);
  19.186 +			int offset = prefix & ADDR32 ? fetch32(regs) : fetch16(regs);
  19.187  
  19.188 -				if (prefix & DATA32) {
  19.189 -					addr = address(regs, seg, offset);
  19.190 -					data = read32(addr);
  19.191 -					setreg32(regs, 0, data);
  19.192 -				} else {
  19.193 -					addr = address(regs, seg, offset);
  19.194 -					data = read16(addr);
  19.195 -					setreg16(regs, 0, data);
  19.196 -				}
  19.197 -				TRACE((regs, regs->eip - eip, "mov *0x%x, %%ax", addr));
  19.198 +			if (prefix & DATA32) {
  19.199 +				addr = address(regs, seg, offset);
  19.200 +				data = read32(addr);
  19.201 +				setreg32(regs, 0, data);
  19.202 +			} else {
  19.203 +				addr = address(regs, seg, offset);
  19.204 +				data = read16(addr);
  19.205 +				setreg16(regs, 0, data);
  19.206  			}
  19.207 +			TRACE((regs, regs->eip - eip, "mov *0x%x, %%ax", addr));
  19.208  			return OPC_EMULATED;
  19.209 +		}
  19.210  
  19.211  		case 0xBB: /* mov bx, imm16 */
  19.212 -			{
  19.213 -				int data;
  19.214 -				if (prefix & DATA32) {
  19.215 -					data = fetch32(regs);
  19.216 -					setreg32(regs, 3, data);
  19.217 -				} else {
  19.218 -					data = fetch16(regs);
  19.219 -					setreg16(regs, 3, data);
  19.220 -				}
  19.221 -				TRACE((regs, regs->eip - eip, "mov $0x%x, %%bx", data));
  19.222 +		{
  19.223 +			int data;
  19.224 +			if (prefix & DATA32) {
  19.225 +				data = fetch32(regs);
  19.226 +				setreg32(regs, 3, data);
  19.227 +			} else {
  19.228 +				data = fetch16(regs);
  19.229 +				setreg16(regs, 3, data);
  19.230  			}
  19.231 +			TRACE((regs, regs->eip - eip, "mov $0x%x, %%bx", data));
  19.232  			return OPC_EMULATED;
  19.233 +		}
  19.234  
  19.235  		case 0xC6: /* addr32 movb $imm, r/m8 */
  19.236 -			if ((prefix & ADDR32) == 0)
  19.237 +			if (!(prefix & ADDR32))
  19.238  				goto invalid;
  19.239  			if (!movr(regs, prefix, opc))
  19.240  				goto invalid;
  19.241  			return OPC_EMULATED;
  19.242  
  19.243  		case 0xCB: /* retl */
  19.244 -			if ((mode == VM86_REAL_TO_PROTECTED) ||
  19.245 -				(mode == VM86_PROTECTED_TO_REAL)) {
  19.246 +			if (mode == VM86_REAL_TO_PROTECTED ||
  19.247 +				mode == VM86_PROTECTED_TO_REAL) {
  19.248  				retl(regs, prefix);
  19.249  				return OPC_INVALID;
  19.250  			}
  19.251 @@ -1576,37 +1570,37 @@ opcode(struct regs *regs)
  19.252  			return OPC_EMULATED;
  19.253  
  19.254  		case 0xEA: /* jmpl */
  19.255 -			if ((mode == VM86_REAL_TO_PROTECTED) ||
  19.256 -				(mode == VM86_PROTECTED_TO_REAL)) {
  19.257 +			if (mode == VM86_REAL_TO_PROTECTED ||
  19.258 +				mode == VM86_PROTECTED_TO_REAL) {
  19.259  				jmpl(regs, prefix);
  19.260  				return OPC_INVALID;
  19.261  			}
  19.262  			goto invalid;
  19.263  
  19.264 -		case 0xFF: /* jmpl (indirect) */
  19.265 -			{
  19.266 -				unsigned modrm = fetch8(regs);
  19.267 -				switch((modrm >> 3) & 7) {
  19.268 -				case 5: /* jmpl (indirect) */
  19.269 -					if ((mode == VM86_REAL_TO_PROTECTED) ||
  19.270 -						(mode == VM86_PROTECTED_TO_REAL)) {
  19.271 -						jmpl_indirect(regs, prefix, modrm);
  19.272 -						return OPC_INVALID;
  19.273 -					}
  19.274 -					goto invalid;
  19.275 +		case 0xFF:
  19.276 +		{
  19.277 +			unsigned modrm = fetch8(regs);
  19.278 +			switch((modrm >> 3) & 7) {
  19.279 +			case 5: /* jmpl (indirect) */
  19.280 +				if (mode == VM86_REAL_TO_PROTECTED ||
  19.281 +					mode == VM86_PROTECTED_TO_REAL) {
  19.282 +					jmpl_indirect(regs, prefix, modrm);
  19.283 +					return OPC_INVALID;
  19.284 +				}
  19.285 +				goto invalid;
  19.286  
  19.287 -				case 6: /* push r/m16 */
  19.288 -					pushrm(regs, prefix, modrm);
  19.289 -					return OPC_EMULATED;
  19.290 +			case 6: /* push r/m16 */
  19.291 +				pushrm(regs, prefix, modrm);
  19.292 +				return OPC_EMULATED;
  19.293  
  19.294 -				default:
  19.295 -					goto invalid;
  19.296 -				}
  19.297 +			default:
  19.298 +				goto invalid;
  19.299  			}
  19.300 +		}
  19.301  
  19.302  		case 0xEB: /* short jump */
  19.303 -			if ((mode == VM86_REAL_TO_PROTECTED) ||
  19.304 -				(mode == VM86_PROTECTED_TO_REAL)) {
  19.305 +			if (mode == VM86_REAL_TO_PROTECTED ||
  19.306 +				mode == VM86_PROTECTED_TO_REAL) {
  19.307  				disp = (char) fetch8(regs);
  19.308  				TRACE((regs, 2, "jmp 0x%x", regs->eip + disp));
  19.309  				regs->eip += disp;
  19.310 @@ -1629,7 +1623,7 @@ opcode(struct regs *regs)
  19.311  			continue;
  19.312  
  19.313  		case 0xF6: /* addr32 testb $imm, r/m8 */
  19.314 -			if ((prefix & ADDR32) == 0)
  19.315 +			if (!(prefix & ADDR32))
  19.316  				goto invalid;
  19.317  			if (!test(regs, prefix, opc))
  19.318  				goto invalid;
    20.1 --- a/tools/ioemu/keymaps/ja	Mon Jul 09 09:22:58 2007 -0600
    20.2 +++ b/tools/ioemu/keymaps/ja	Tue Jul 10 08:39:26 2007 -0600
    20.3 @@ -101,6 +101,7 @@ yen 0x7d
    20.4  bar 0x7d shift
    20.5  underscore 0x73 shift
    20.6  Henkan_Mode 0x79
    20.7 +Katakana_Real 0x70
    20.8  Katakana 0x70
    20.9  Muhenkan 0x7b
   20.10  Henkan_Mode_Real 0x79
    21.1 --- a/tools/ioemu/keymaps/modifiers	Mon Jul 09 09:22:58 2007 -0600
    21.2 +++ b/tools/ioemu/keymaps/modifiers	Tue Jul 10 08:39:26 2007 -0600
    21.3 @@ -11,8 +11,8 @@ Control_L 0x1d
    21.4  
    21.5  # Translate Super to Windows keys. 
    21.6  # This is hardcoded. See documentation for details. 
    21.7 -Super_R 0xdb
    21.8 -Super_L 0xdc
    21.9 +Super_R 0xdc
   21.10 +Super_L 0xdb
   21.11  
   21.12  # Translate Menu to the Windows Application key. 
   21.13  Menu 0xdd
    22.1 --- a/tools/ioemu/vnc_keysym.h	Mon Jul 09 09:22:58 2007 -0600
    22.2 +++ b/tools/ioemu/vnc_keysym.h	Tue Jul 10 08:39:26 2007 -0600
    22.3 @@ -290,12 +290,14 @@ static name2keysym_t name2keysym[]={
    22.4      /* localized keys */
    22.5  {"BackApostrophe", 0xff21},
    22.6  {"Muhenkan", 0xff22},
    22.7 -{"Katakana", 0xff25},
    22.8 +{"Katakana", 0xff27},
    22.9  {"Hankaku", 0xff29},
   22.10  {"Zenkaku_Hankaku", 0xff2a},
   22.11  {"Henkan_Mode_Real", 0xff23},
   22.12  {"Henkan_Mode_Ultra", 0xff3e},
   22.13  {"backslash_ja", 0xffa5},
   22.14 +{"Katakana_Real", 0xff25},
   22.15 +{"Eisu_toggle", 0xff30},
   22.16  
   22.17      /* dead keys */
   22.18  {"dead_grave", 0xfe50},
    23.1 --- a/tools/libxc/Makefile	Mon Jul 09 09:22:58 2007 -0600
    23.2 +++ b/tools/libxc/Makefile	Tue Jul 10 08:39:26 2007 -0600
    23.3 @@ -57,7 +57,6 @@ GUEST_SRCS-$(CONFIG_POWERPC) += xc_dom_p
    23.4  -include $(XEN_TARGET_ARCH)/Makefile
    23.5  
    23.6  CFLAGS   += -Werror -Wmissing-prototypes
    23.7 -CFLAGS   += -fno-strict-aliasing
    23.8  CFLAGS   += $(INCLUDES) -I. -I../xenstore
    23.9  
   23.10  # Needed for posix_fadvise64() in xc_linux.c
    24.1 --- a/tools/libxc/xc_domain.c	Mon Jul 09 09:22:58 2007 -0600
    24.2 +++ b/tools/libxc/xc_domain.c	Tue Jul 10 08:39:26 2007 -0600
    24.3 @@ -181,6 +181,7 @@ int xc_domain_getinfo(int xc_handle,
    24.4          info->blocked  = !!(domctl.u.getdomaininfo.flags&XEN_DOMINF_blocked);
    24.5          info->running  = !!(domctl.u.getdomaininfo.flags&XEN_DOMINF_running);
    24.6          info->hvm      = !!(domctl.u.getdomaininfo.flags&XEN_DOMINF_hvm_guest);
    24.7 +        info->debugged = !!(domctl.u.getdomaininfo.flags&XEN_DOMINF_debugged);
    24.8  
    24.9          info->shutdown_reason =
   24.10              (domctl.u.getdomaininfo.flags>>XEN_DOMINF_shutdownshift) &
    25.1 --- a/tools/libxc/xc_misc.c	Mon Jul 09 09:22:58 2007 -0600
    25.2 +++ b/tools/libxc/xc_misc.c	Tue Jul 10 08:39:26 2007 -0600
    25.3 @@ -60,6 +60,8 @@ int xc_physinfo(int xc_handle,
    25.4  
    25.5      sysctl.cmd = XEN_SYSCTL_physinfo;
    25.6  
    25.7 +    memcpy(&sysctl.u.physinfo, put_info, sizeof(*put_info));
    25.8 +
    25.9      if ( (ret = do_sysctl(xc_handle, &sysctl)) != 0 )
   25.10          return ret;
   25.11  
    26.1 --- a/tools/libxc/xenctrl.h	Mon Jul 09 09:22:58 2007 -0600
    26.2 +++ b/tools/libxc/xenctrl.h	Tue Jul 10 08:39:26 2007 -0600
    26.3 @@ -153,7 +153,7 @@ typedef struct xc_dominfo {
    26.4      uint32_t      ssidref;
    26.5      unsigned int  dying:1, crashed:1, shutdown:1,
    26.6                    paused:1, blocked:1, running:1,
    26.7 -                  hvm:1;
    26.8 +                  hvm:1, debugged:1;
    26.9      unsigned int  shutdown_reason; /* only meaningful if shutdown==1 */
   26.10      unsigned long nr_pages;
   26.11      unsigned long shared_info_frame;
   26.12 @@ -485,6 +485,7 @@ int xc_readconsolering(int xc_handle,
   26.13  int xc_send_debug_keys(int xc_handle, char *keys);
   26.14  
   26.15  typedef xen_sysctl_physinfo_t xc_physinfo_t;
   26.16 +typedef uint32_t xc_cpu_to_node_t;
   26.17  int xc_physinfo(int xc_handle,
   26.18                  xc_physinfo_t *info);
   26.19  
    27.1 --- a/tools/python/xen/lowlevel/xc/xc.c	Mon Jul 09 09:22:58 2007 -0600
    27.2 +++ b/tools/python/xen/lowlevel/xc/xc.c	Tue Jul 10 08:39:26 2007 -0600
    27.3 @@ -680,33 +680,62 @@ static PyObject *pyxc_pages_to_kib(XcObj
    27.4  
    27.5  static PyObject *pyxc_physinfo(XcObject *self)
    27.6  {
    27.7 +#define MAX_CPU_ID 255
    27.8      xc_physinfo_t info;
    27.9      char cpu_cap[128], *p=cpu_cap, *q=cpu_cap;
   27.10 -    int i;
   27.11 -    
   27.12 +    int i, j, max_cpu_id;
   27.13 +    PyObject *ret_obj, *node_to_cpu_obj;
   27.14 +    xc_cpu_to_node_t map[MAX_CPU_ID];
   27.15 +
   27.16 +    set_xen_guest_handle(info.cpu_to_node, map);
   27.17 +    info.max_cpu_id = MAX_CPU_ID;
   27.18 +
   27.19      if ( xc_physinfo(self->xc_handle, &info) != 0 )
   27.20          return pyxc_error_to_exception();
   27.21  
   27.22 -    *q=0;
   27.23 -    for(i=0;i<sizeof(info.hw_cap)/4;i++)
   27.24 +    *q = 0;
   27.25 +    for ( i = 0; i < sizeof(info.hw_cap)/4; i++ )
   27.26      {
   27.27 -        p+=sprintf(p,"%08x:",info.hw_cap[i]);
   27.28 -        if(info.hw_cap[i])
   27.29 -            q=p;
   27.30 +        p += sprintf(p, "%08x:", info.hw_cap[i]);
   27.31 +        if ( info.hw_cap[i] )
   27.32 +            q = p;
   27.33      }
   27.34 -    if(q>cpu_cap)
   27.35 -        *(q-1)=0;
   27.36 +    if ( q > cpu_cap )
   27.37 +        *(q-1) = 0;
   27.38 +
   27.39 +    ret_obj = Py_BuildValue("{s:i,s:i,s:i,s:i,s:i,s:l,s:l,s:l,s:i,s:s}",
   27.40 +                            "nr_nodes",         info.nr_nodes,
   27.41 +                            "max_cpu_id",       info.max_cpu_id,
   27.42 +                            "threads_per_core", info.threads_per_core,
   27.43 +                            "cores_per_socket", info.cores_per_socket,
   27.44 +                            "sockets_per_node", info.sockets_per_node,
   27.45 +                            "total_memory",     pages_to_kib(info.total_pages),
   27.46 +                            "free_memory",      pages_to_kib(info.free_pages),
   27.47 +                            "scrub_memory",     pages_to_kib(info.scrub_pages),
   27.48 +                            "cpu_khz",          info.cpu_khz,
   27.49 +                            "hw_caps",          cpu_cap);
   27.50  
   27.51 -    return Py_BuildValue("{s:i,s:i,s:i,s:i,s:l,s:l,s:l,s:i,s:s}",
   27.52 -                         "threads_per_core", info.threads_per_core,
   27.53 -                         "cores_per_socket", info.cores_per_socket,
   27.54 -                         "sockets_per_node", info.sockets_per_node,
   27.55 -                         "nr_nodes",         info.nr_nodes,
   27.56 -                         "total_memory",     pages_to_kib(info.total_pages),
   27.57 -                         "free_memory",      pages_to_kib(info.free_pages),
   27.58 -                         "scrub_memory",     pages_to_kib(info.scrub_pages),
   27.59 -                         "cpu_khz",          info.cpu_khz,
   27.60 -                         "hw_caps",          cpu_cap);
   27.61 +    max_cpu_id = info.max_cpu_id;
   27.62 +    if ( max_cpu_id > MAX_CPU_ID )
   27.63 +        max_cpu_id = MAX_CPU_ID;
   27.64 +
   27.65 +    /* Construct node-to-cpu lists. */
   27.66 +    node_to_cpu_obj = PyList_New(0);
   27.67 +
   27.68 +    /* Make a list for each node. */
   27.69 +    for ( i = 0; i < info.nr_nodes; i++ )
   27.70 +    {
   27.71 +        PyObject *cpus = PyList_New(0);
   27.72 +        for ( j = 0; j <= max_cpu_id; j++ )
   27.73 +            if ( i == map[j])
   27.74 +                PyList_Append(cpus, PyInt_FromLong(j));
   27.75 +        PyList_Append(node_to_cpu_obj, cpus); 
   27.76 +    }
   27.77 +
   27.78 +    PyDict_SetItemString(ret_obj, "node_to_cpu", node_to_cpu_obj);
   27.79 + 
   27.80 +    return ret_obj;
   27.81 +#undef MAX_CPU_ID
   27.82  }
   27.83  
   27.84  static PyObject *pyxc_xeninfo(XcObject *self)
    28.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    28.2 +++ b/tools/python/xen/util/acmpolicy.py	Tue Jul 10 08:39:26 2007 -0600
    28.3 @@ -0,0 +1,1199 @@
    28.4 +#============================================================================
    28.5 +# This library is free software; you can redistribute it and/or
    28.6 +# modify it under the terms of version 2.1 of the GNU Lesser General Public
    28.7 +# License as published by the Free Software Foundation.
    28.8 +#
    28.9 +# This library is distributed in the hope that it will be useful,
   28.10 +# but WITHOUT ANY WARRANTY; without even the implied warranty of
   28.11 +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   28.12 +# Lesser General Public License for more details.
   28.13 +#
   28.14 +# You should have received a copy of the GNU Lesser General Public
   28.15 +# License along with this library; if not, write to the Free Software
   28.16 +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
   28.17 +#============================================================================
   28.18 +# Copyright (C) 2006,2007 International Business Machines Corp.
   28.19 +# Author: Stefan Berger <stefanb@us.ibm.com>
   28.20 +#============================================================================
   28.21 +
   28.22 +import os
   28.23 +import commands
   28.24 +import struct
   28.25 +import stat
   28.26 +import array
   28.27 +from xml.dom import minidom, Node
   28.28 +from xen.xend.XendLogging import log
   28.29 +from xen.util import security, xsconstants, bootloader, mkdir
   28.30 +from xen.util.xspolicy import XSPolicy
   28.31 +from xen.util.security import ACMError
   28.32 +from xen.xend.XendError import SecurityError
   28.33 +
   28.34 +ACM_POLICIES_DIR = security.policy_dir_prefix + "/"
   28.35 +
   28.36 +# Constants needed for generating a binary policy from its XML
   28.37 +# representation
   28.38 +ACM_POLICY_VERSION = 3  # Latest one
   28.39 +ACM_CHWALL_VERSION = 1
   28.40 +
   28.41 +ACM_STE_VERSION = 1
   28.42 +
   28.43 +ACM_MAGIC = 0x001debc;
   28.44 +
   28.45 +ACM_NULL_POLICY = 0
   28.46 +ACM_CHINESE_WALL_POLICY = 1
   28.47 +ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY = 2
   28.48 +ACM_POLICY_UNDEFINED = 15
   28.49 +
   28.50 +
   28.51 +ACM_SCHEMA_FILE = "/etc/xen/acm-security/policies/security_policy.xsd"
   28.52 +
   28.53 +class ACMPolicy(XSPolicy):
   28.54 +    """
   28.55 +     ACMPolicy class. Implements methods for getting information from
   28.56 +     the XML representation of the policy as well as compilation and
   28.57 +     loading of a policy into the HV.
   28.58 +    """
   28.59 +
   28.60 +    def __init__(self, name=None, dom=None, ref=None, xml=None):
   28.61 +        if name:
   28.62 +            self.name = name
   28.63 +            self.dom = minidom.parse(self.path_from_policy_name(name))
   28.64 +        elif dom:
   28.65 +            self.dom = dom
   28.66 +            self.name = self.get_name()
   28.67 +        elif xml:
   28.68 +            self.dom = minidom.parseString(xml)
   28.69 +            self.name = self.get_name()
   28.70 +        rc = self.validate()
   28.71 +        if rc != xsconstants.XSERR_SUCCESS:
   28.72 +            raise SecurityError(rc)
   28.73 +        mkdir.parents(ACM_POLICIES_DIR, stat.S_IRWXU)
   28.74 +        if ref:
   28.75 +            from xen.xend.XendXSPolicy import XendACMPolicy
   28.76 +            self.xendacmpolicy = XendACMPolicy(self, {}, ref)
   28.77 +        else:
   28.78 +            self.xendacmpolicy = None
   28.79 +        XSPolicy.__init__(self, name=self.name, ref=ref)
   28.80 +
   28.81 +    def get_dom(self):
   28.82 +        return self.dom
   28.83 +
   28.84 +    def get_name(self):
   28.85 +        return self.policy_dom_get_hdr_item("PolicyName")
   28.86 +
   28.87 +    def get_type(self):
   28.88 +        return xsconstants.XS_POLICY_ACM
   28.89 +
   28.90 +    def get_type_name(self):
   28.91 +        return xsconstants.ACM_POLICY_ID
   28.92 +
   28.93 +    def __str__(self):
   28.94 +        return self.get_name()
   28.95 +
   28.96 +
   28.97 +    def validate(self):
   28.98 +        """
   28.99 +            validate against the policy's schema Does not fail if the
  28.100 +            libxml2 python lib is not installed
  28.101 +        """
  28.102 +        rc = xsconstants.XSERR_SUCCESS
  28.103 +        try:
  28.104 +            import libxml2
  28.105 +        except Exception, e:
  28.106 +            log.warn("Libxml2 python-wrapper is not installed on the system.")
  28.107 +            return xsconstants.XSERR_SUCCESS
  28.108 +        try:
  28.109 +            parserctxt = libxml2.schemaNewParserCtxt(ACM_SCHEMA_FILE)
  28.110 +            schemaparser = parserctxt.schemaParse()
  28.111 +            valid = schemaparser.schemaNewValidCtxt()
  28.112 +            doc = libxml2.parseDoc(self.toxml())
  28.113 +            if doc.schemaValidateDoc(valid) != 0:
  28.114 +                rc = -xsconstants.XSERR_BAD_XML
  28.115 +        except Exception, e:
  28.116 +            log.warn("Problem with the schema: %s" % str(e))
  28.117 +            rc = -xsconstants.XSERR_GENERAL_FAILURE
  28.118 +        if rc != xsconstants.XSERR_SUCCESS:
  28.119 +            log.warn("XML did not validate against schema")
  28.120 +        rc = self.__validate_name_and_labels()
  28.121 +        return rc
  28.122 +
  28.123 +    def __validate_name_and_labels(self):
  28.124 +        """ no ':' allowed in the policy name and the labels """
  28.125 +        if ':' in self.get_name():
  28.126 +            return -xsconstants.XSERR_BAD_POLICY_NAME
  28.127 +        for s in self.policy_get_resourcelabel_names():
  28.128 +            if ':' in s:
  28.129 +                return -xsconstants.XSERR_BAD_LABEL
  28.130 +        for s in self.policy_get_virtualmachinelabel_names():
  28.131 +            if ':' in s:
  28.132 +                return -xsconstants.XSERR_BAD_LABEL
  28.133 +        return xsconstants.XSERR_SUCCESS
  28.134 +
  28.135 +
  28.136 +    def update(self, xml_new):
  28.137 +        """
  28.138 +            Update the policy with the new XML. The hypervisor decides
  28.139 +            whether the new policy can be applied.
  28.140 +        """
  28.141 +        rc = -xsconstants.XSERR_XML_PROCESSING
  28.142 +        errors = ""
  28.143 +        acmpol_old = self
  28.144 +        try:
  28.145 +            acmpol_new = ACMPolicy(xml=xml_new)
  28.146 +        except Exception:
  28.147 +            return -xsconstants.XSERR_XML_PROCESSING, errors
  28.148 +
  28.149 +        vmlabel_map = acmpol_new.policy_get_vmlabel_translation_map()
  28.150 +        # An update requires version information in the current
  28.151 +        # and new policy. The version number of the current policy
  28.152 +        # must be the same as what is in the FromPolicy/Version node
  28.153 +        # in the new one and the current policy's name must be the
  28.154 +        # same as in FromPolicy/PolicyName
  28.155 +
  28.156 +        now_vers    = acmpol_old.policy_dom_get_hdr_item("Version")
  28.157 +        now_name    = acmpol_old.policy_dom_get_hdr_item("PolicyName")
  28.158 +        req_oldvers = acmpol_new.policy_dom_get_frompol_item("Version")
  28.159 +        req_oldname = acmpol_new.policy_dom_get_frompol_item("PolicyName")
  28.160 +
  28.161 +        if now_vers == "" or \
  28.162 +           now_vers != req_oldvers or \
  28.163 +           now_name != req_oldname:
  28.164 +            log.info("Policy rejected: %s != %s or %s != %s" % \
  28.165 +                     (now_vers,req_oldvers,now_name,req_oldname))
  28.166 +            return -xsconstants.XSERR_VERSION_PREVENTS_UPDATE, errors
  28.167 +
  28.168 +        if not self.isVersionUpdate(acmpol_new):
  28.169 +            log.info("Policy rejected since new version is not an update.")
  28.170 +            return -xsconstants.XSERR_VERSION_PREVENTS_UPDATE, errors
  28.171 +
  28.172 +        if self.isloaded():
  28.173 +            newvmnames = \
  28.174 +                 acmpol_new.policy_get_virtualmachinelabel_names_sorted()
  28.175 +            oldvmnames = \
  28.176 +                 acmpol_old.policy_get_virtualmachinelabel_names_sorted()
  28.177 +            del_array = ""
  28.178 +            chg_array = ""
  28.179 +            for o in oldvmnames:
  28.180 +                if o not in newvmnames:
  28.181 +                    old_idx = oldvmnames.index(o) + 1 # for _NULL_LABEL_
  28.182 +                    if vmlabel_map.has_key(o):
  28.183 +                        #not a deletion, but a renaming
  28.184 +                        new = vmlabel_map[o]
  28.185 +                        new_idx = newvmnames.index(new) + 1 # for _NULL_LABEL_
  28.186 +                        chg_array += struct.pack("ii", old_idx, new_idx)
  28.187 +                    else:
  28.188 +                        del_array += struct.pack("i", old_idx)
  28.189 +            for v in newvmnames:
  28.190 +                if v in oldvmnames:
  28.191 +                    old_idx = oldvmnames.index(v) + 1 # for _NULL_LABEL_
  28.192 +                    new_idx = newvmnames.index(v) + 1 # for _NULL_LABEL_
  28.193 +                    if old_idx != new_idx:
  28.194 +                        chg_array += struct.pack("ii", old_idx, new_idx)
  28.195 +
  28.196 +            # VM labels indicated in the 'from' attribute of a VM or
  28.197 +            # resource node but that did not exist in the old policy
  28.198 +            # are considered bad labels.
  28.199 +            bad_renamings = set(vmlabel_map.keys()) - set(oldvmnames)
  28.200 +            if len(bad_renamings) > 0:
  28.201 +                log.error("Bad VM label renamings: %s" %
  28.202 +                          list(bad_renamings))
  28.203 +                return -xsconstants.XSERR_BAD_LABEL, errors
  28.204 +
  28.205 +            reslabel_map = acmpol_new.policy_get_reslabel_translation_map()
  28.206 +            oldresnames  = acmpol_old.policy_get_resourcelabel_names()
  28.207 +            bad_renamings = set(reslabel_map.keys()) - set(oldresnames)
  28.208 +            if len(bad_renamings) > 0:
  28.209 +                log.error("Bad resource label renamings: %s" %
  28.210 +                          list(bad_renamings))
  28.211 +                return -xsconstants.XSERR_BAD_LABEL, errors
  28.212 +
  28.213 +            #Get binary and map from the new policy
  28.214 +            rc, map, bin_pol = acmpol_new.policy_create_map_and_bin()
  28.215 +            if rc != xsconstants.XSERR_SUCCESS:
  28.216 +                log.error("Could not build the map and binary policy.")
  28.217 +                return rc, errors
  28.218 +
  28.219 +            #Need to do / check the following:
  28.220 +            # - relabel all resources where there is a 'from' field in
  28.221 +            #   the policy and mark those as unlabeled where the label
  28.222 +            #   does not appear in the new policy anymore
  28.223 +            # - relabel all VMs where there is a 'from' field in the
  28.224 +            #   policy and mark those as unlabeled where the label
  28.225 +            #   does not appear in the new policy anymore; no running
  28.226 +            #   or paused VM may be unlabeled through this
  28.227 +            # - check that under the new labeling conditions the VMs
  28.228 +            #   still have access to their resources as before. Unlabeled
  28.229 +            #   resources are inaccessible. If this check fails, the
  28.230 +            #   update failed.
  28.231 +            # - Attempt changes in the hypervisor; if this step fails,
  28.232 +            #   roll back the relabeling of resources and VMs
  28.233 +            # - Commit the relabeling of resources
  28.234 +
  28.235 +
  28.236 +            rc, errors = security.change_acm_policy(bin_pol,
  28.237 +                                        del_array, chg_array,
  28.238 +                                        vmlabel_map, reslabel_map,
  28.239 +                                        self, acmpol_new)
  28.240 +
  28.241 +            if rc == 0:
  28.242 +                # Replace the old DOM with the new one and save it
  28.243 +                self.dom = acmpol_new.dom
  28.244 +                self.compile()
  28.245 +                log.info("ACM policy update was successful")
  28.246 +        else:
  28.247 +            #Not loaded in HV
  28.248 +            self.dom = acmpol_new.dom
  28.249 +            self.compile()
  28.250 +        return rc, errors
  28.251 +
  28.252 +    def compareVersions(self, v1, v2):
  28.253 +        """
  28.254 +            Compare two policy versions given their tuples of major and
  28.255 +            minor.
  28.256 +            Return '0' if versions are equal, '>0' if v1 > v2 and
  28.257 +            '<' if v1 < v2
  28.258 +        """
  28.259 +        rc = v1[0] - v2[0]
  28.260 +        if rc == 0:
  28.261 +            rc = v1[1] - v2[1]
  28.262 +        return rc
  28.263 +
  28.264 +    def getVersionTuple(self, item="Version"):
  28.265 +        v_str = self.policy_dom_get_hdr_item(item)
  28.266 +        return self.__convVersionToTuple(v_str)
  28.267 +
  28.268 +    def get_version(self):
  28.269 +        return self.policy_dom_get_hdr_item("Version")
  28.270 +
  28.271 +    def isVersionUpdate(self, polnew):
  28.272 +        if self.compareVersions(polnew.getVersionTuple(),
  28.273 +                                self.getVersionTuple()) > 0:
  28.274 +            return True
  28.275 +        return False
  28.276 +
  28.277 +    def __convVersionToTuple(self, v_str):
  28.278 +        """ Convert a version string, formatted according to the scheme
  28.279 +            "%d.%d" into a tuple of (major, minor). Return (0,0) if the
  28.280 +            string is empty.
  28.281 +        """
  28.282 +        major = 0
  28.283 +        minor = 0
  28.284 +        if v_str != "":
  28.285 +            tmp = v_str.split(".")
  28.286 +            major = int(tmp[0])
  28.287 +            if len(tmp) > 1:
  28.288 +                minor = int(tmp[1])
  28.289 +        return (major, minor)
  28.290 +
  28.291 +
  28.292 +    def policy_path(self, name, prefix = ACM_POLICIES_DIR ):
  28.293 +        path = prefix + name.replace('.','/')
  28.294 +        _path = path.split("/")
  28.295 +        del _path[-1]
  28.296 +        mkdir.parents("/".join(_path), stat.S_IRWXU)
  28.297 +        return path
  28.298 +
  28.299 +    def path_from_policy_name(self, name):
  28.300 +        return self.policy_path(name) + "-security_policy.xml"
  28.301 +
  28.302 +    #
  28.303 +    # Functions interacting with the bootloader
  28.304 +    #
  28.305 +    def vmlabel_to_ssidref(self, vm_label):
  28.306 +        """ Convert a VMlabel into an ssidref given the current
  28.307 +            policy
  28.308 +            Return xsconstants.INVALID_SSIDREF if conversion failed.
  28.309 +        """
  28.310 +        ssidref = xsconstants.INVALID_SSIDREF
  28.311 +        names = self.policy_get_virtualmachinelabel_names_sorted()
  28.312 +        try:
  28.313 +            vmidx = names.index(vm_label) + 1 # for _NULL_LABEL_
  28.314 +            ssidref = (vmidx << 16) | vmidx
  28.315 +        except:
  28.316 +            pass
  28.317 +        return ssidref
  28.318 +
  28.319 +    def set_vm_bootlabel(self, vm_label):
  28.320 +        parms="<>"
  28.321 +        if vm_label != "":
  28.322 +            ssidref = self.vmlabel_to_ssidref(vm_label)
  28.323 +            if ssidref == xsconstants.INVALID_SSIDREF:
  28.324 +                return -xsconstants.XSERR_BAD_LABEL
  28.325 +            parms = "0x%08x:%s:%s:%s" % \
  28.326 +                        (ssidref, xsconstants.ACM_POLICY_ID, \
  28.327 +                         self.get_name(),vm_label)
  28.328 +        else:
  28.329 +            ssidref = 0 #Identifier for removal
  28.330 +        try:
  28.331 +            def_title = bootloader.get_default_title()
  28.332 +            bootloader.set_kernel_attval(def_title, "ssidref", parms)
  28.333 +        except:
  28.334 +            return -xsconstants.XSERR_GENERAL_FAILURE
  28.335 +        return ssidref
  28.336 +
  28.337 +    #
  28.338 +    # Utility functions related to the policy's files
  28.339 +    #
  28.340 +    def get_filename(self, postfix, prefix = ACM_POLICIES_DIR, dotted=False):
  28.341 +        """
  28.342 +           Create the filename for the policy. The prefix is prepended
  28.343 +           to the path. If dotted is True, then a policy name like
  28.344 +           'a.b.c' will remain as is, otherwise it will become 'a/b/c'
  28.345 +        """
  28.346 +        name = self.get_name()
  28.347 +        if name:
  28.348 +            p = name.split(".")
  28.349 +            path = ""
  28.350 +            if dotted == True:
  28.351 +                sep = "."
  28.352 +            else:
  28.353 +                sep = "/"
  28.354 +            if len(p) > 1:
  28.355 +                path = sep.join(p[0:len(p)-1])
  28.356 +            if prefix != "" or path != "":
  28.357 +                allpath = prefix + path + sep + p[-1] + postfix
  28.358 +            else:
  28.359 +                allpath = p[-1] + postfix
  28.360 +            return allpath
  28.361 +        return None
  28.362 +
  28.363 +    def __readfile(self, name):
  28.364 +        cont = ""
  28.365 +        filename = self.get_filename(name)
  28.366 +        f = open(filename, "r")
  28.367 +        if f:
  28.368 +            cont = f.read()
  28.369 +            f.close()
  28.370 +        return cont
  28.371 +
  28.372 +    def get_map(self):
  28.373 +        return self.__readfile(".map")
  28.374 +
  28.375 +    def get_bin(self):
  28.376 +        return self.__readfile(".bin")
  28.377 +
  28.378 +    #
  28.379 +    # DOM-related functions
  28.380 +    #
  28.381 +
  28.382 +    def policy_dom_get(self, parent, key, createit=False):
  28.383 +        for node in parent.childNodes:
  28.384 +            if node.nodeType == Node.ELEMENT_NODE:
  28.385 +                if node.nodeName == key:
  28.386 +                    return node
  28.387 +        if createit:
  28.388 +            self.dom_create_node(parent, key)
  28.389 +            return self.policy_dom_get(parent, key)
  28.390 +
  28.391 +    def dom_create_node(self, parent, newname, value=" "):
  28.392 +        xml = "<a><"+newname+">"+ value +"</"+newname+"></a>"
  28.393 +        frag = minidom.parseString(xml)
  28.394 +        frag.childNodes[0].nodeType = Node.DOCUMENT_FRAGMENT_NODE
  28.395 +        parent.appendChild(frag.childNodes[0])
  28.396 +        return frag.childNodes[0]
  28.397 +
  28.398 +    def dom_get_node(self, path, createit=False):
  28.399 +        node = None
  28.400 +        parts = path.split("/")
  28.401 +        doc = self.get_dom()
  28.402 +        if len(parts) > 0:
  28.403 +            node = self.policy_dom_get(doc.documentElement, parts[0])
  28.404 +            if node:
  28.405 +                i = 1
  28.406 +                while i < len(parts):
  28.407 +                    _node = self.policy_dom_get(node, parts[i], createit)
  28.408 +                    if not _node:
  28.409 +                        if not createit:
  28.410 +                            break
  28.411 +                        else:
  28.412 +                            self.dom_create_node(node, parts[i])
  28.413 +                            _node = self.policy_dom_get(node, parts[i])
  28.414 +                    node = _node
  28.415 +                    i += 1
  28.416 +        return node
  28.417 +
  28.418 +    #
  28.419 +    # Header-related functions
  28.420 +    #
  28.421 +    def policy_dom_get_header_subnode(self, nodename):
  28.422 +        node = self.dom_get_node("PolicyHeader/%s" % nodename)
  28.423 +        return node
  28.424 +
  28.425 +    def policy_dom_get_hdr_item(self, name, default=""):
  28.426 +        node = self.policy_dom_get_header_subnode(name)
  28.427 +        if node and len(node.childNodes) > 0:
  28.428 +            return node.childNodes[0].nodeValue
  28.429 +        return default
  28.430 +
  28.431 +    def policy_dom_get_frompol_item(self, name, default="", createit=False):
  28.432 +        node = self.dom_get_node("PolicyHeader/FromPolicy",createit)
  28.433 +        if node:
  28.434 +            node = self.policy_dom_get(node, name, createit)
  28.435 +            if node and len(node.childNodes) > 0:
  28.436 +                return node.childNodes[0].nodeValue
  28.437 +        return default
  28.438 +
  28.439 +    def get_header_fields_map(self):
  28.440 +        header = {
  28.441 +          'policyname'   : self.policy_dom_get_hdr_item("PolicyName"),
  28.442 +          'policyurl'    : self.policy_dom_get_hdr_item("PolicyUrl"),
  28.443 +          'reference'    : self.policy_dom_get_hdr_item("Reference"),
  28.444 +          'date'         : self.policy_dom_get_hdr_item("Date"),
  28.445 +          'namespaceurl' : self.policy_dom_get_hdr_item("NameSpaceUrl"),
  28.446 +          'version'      : self.policy_dom_get_hdr_item("Version")
  28.447 +        }
  28.448 +        return header
  28.449 +
  28.450 +    def set_frompolicy_name(self, name):
  28.451 +        """ For tools to adapt the header of the policy """
  28.452 +        node = self.dom_get_node("PolicyHeader/FromPolicy/PolicyName",
  28.453 +                                 createit=True)
  28.454 +        node.childNodes[0].nodeValue = name
  28.455 +
  28.456 +    def set_frompolicy_version(self, version):
  28.457 +        """ For tools to adapt the header of the policy """
  28.458 +        node = self.dom_get_node("PolicyHeader/FromPolicy/Version",
  28.459 +                                 createit=True)
  28.460 +        node.childNodes[0].nodeValue = version
  28.461 +
  28.462 +    def set_policy_name(self, name):
  28.463 +        """ For tools to adapt the header of the policy """
  28.464 +        node = self.dom_get_node("PolicyHeader/PolicyName")
  28.465 +        node.childNodes[0].nodeValue = name
  28.466 +
  28.467 +    def set_policy_version(self, version):
  28.468 +        """ For tools to adapt the header of the policy """
  28.469 +        node = self.dom_get_node("PolicyHeader/Version")
  28.470 +        node.childNodes[0].nodeValue = version
  28.471 +
  28.472 +    def update_frompolicy(self, curpol):
  28.473 +        self.set_frompolicy_name(curpol.policy_dom_get_hdr_item("PolicyName"))
  28.474 +        version = curpol.policy_dom_get_hdr_item("Version")
  28.475 +        self.set_frompolicy_version(version)
  28.476 +        (maj, min) = self.__convVersionToTuple(version)
  28.477 +        self.set_policy_version("%s.%s" % (maj, min+1))
  28.478 +
  28.479 +    #
  28.480 +    # Get all types that are part of a node
  28.481 +    #
  28.482 +
  28.483 +    def policy_get_types(self, node):
  28.484 +        strings = []
  28.485 +        i = 0
  28.486 +        while i < len(node.childNodes):
  28.487 +            if node.childNodes[i].nodeName == "Type":
  28.488 +                strings.append(node.childNodes[i].childNodes[0].nodeValue)
  28.489 +            i += 1
  28.490 +        return strings
  28.491 +
  28.492 +    #
  28.493 +    # Simple Type Enforcement-related functions
  28.494 +    #
  28.495 +
  28.496 +    def policy_get_stetypes_node(self):
  28.497 +        node = self.dom_get_node("SimpleTypeEnforcement/SimpleTypeEnforcementTypes")
  28.498 +        return node
  28.499 +
  28.500 +    def policy_get_stetypes_types(self):
  28.501 +        strings = []
  28.502 +        node = self.policy_get_stetypes_node()
  28.503 +        if node:
  28.504 +            strings = self.policy_get_types(node)
  28.505 +        return strings
  28.506 +
  28.507 +    #
  28.508 +    # Chinese Wall Type-related functions
  28.509 +    #
  28.510 +
  28.511 +    def policy_get_chwall_types(self):
  28.512 +        strings = []
  28.513 +        node = self.dom_get_node("ChineseWall/ChineseWallTypes")
  28.514 +        if node:
  28.515 +            strings = self.policy_get_types(node)
  28.516 +        return strings
  28.517 +
  28.518 +    def policy_get_chwall_cfses(self):
  28.519 +        cfs = []
  28.520 +        node = self.dom_get_node("ChineseWall/ConflictSets")
  28.521 +        if node:
  28.522 +            i = 0
  28.523 +            while i < len(node.childNodes):
  28.524 +                _cfs = {}
  28.525 +                if node.childNodes[i].nodeName == "Conflict":
  28.526 +                    _cfs['name']  = node.childNodes[i].getAttribute('name')
  28.527 +                    _cfs['chws'] = self.policy_get_types(node.childNodes[i])
  28.528 +                    cfs.append(_cfs)
  28.529 +                i += 1
  28.530 +        return cfs
  28.531 +
  28.532 +    def policy_get_chwall_cfses_names_sorted(self):
  28.533 +        """
  28.534 +           Return the list of all conflict set names in alphabetical
  28.535 +           order.
  28.536 +        """
  28.537 +        cfs_names = []
  28.538 +        node = self.dom_get_node("ChineseWall/ConflictSets")
  28.539 +        if node:
  28.540 +            i = 0
  28.541 +            while i < len(node.childNodes):
  28.542 +                if node.childNodes[i].nodeName == "Conflict":
  28.543 +                    n  = node.childNodes[i].getAttribute('name')
  28.544 +                    #it better have a name!
  28.545 +                    if n:
  28.546 +                        cfs_names.append(n)
  28.547 +                i += 1
  28.548 +        cfs_names.sort()
  28.549 +        return cfs_names
  28.550 +
  28.551 +    #
  28.552 +    # Subject Label-related functions
  28.553 +    #
  28.554 +
  28.555 +    def policy_get_bootstrap_vmlabel(self):
  28.556 +        node = self.dom_get_node("SecurityLabelTemplate/SubjectLabels")
  28.557 +        if node:
  28.558 +            vmlabel = node.getAttribute("bootstrap")
  28.559 +        return vmlabel
  28.560 +
  28.561 +    # Get the names of all virtual machine labels; returns an array
  28.562 +    def policy_get_virtualmachinelabel_names(self):
  28.563 +        strings = []
  28.564 +        node = self.dom_get_node("SecurityLabelTemplate/SubjectLabels")
  28.565 +        if node:
  28.566 +            i = 0
  28.567 +            while i < len(node.childNodes):
  28.568 +                if node.childNodes[i].nodeName == "VirtualMachineLabel":
  28.569 +                    name = self.policy_dom_get(node.childNodes[i], "Name")
  28.570 +                    strings.append(name.childNodes[0].nodeValue)
  28.571 +                i += 1
  28.572 +        return strings
  28.573 +
  28.574 +    def policy_sort_virtualmachinelabel_names(self, vmnames):
  28.575 +        bootstrap = self.policy_get_bootstrap_vmlabel()
  28.576 +        if bootstrap not in vmnames:
  28.577 +            raise SecurityError(-xsconstants.XSERR_POLICY_INCONSISTENT)
  28.578 +        vmnames.remove(bootstrap)
  28.579 +        vmnames.sort()
  28.580 +        vmnames.insert(0, bootstrap)
  28.581 +        return vmnames
  28.582 +
  28.583 +    def policy_get_virtualmachinelabel_names_sorted(self):
  28.584 +        """ Get a sorted list of VMlabel names. The bootstrap VM's
  28.585 +            label will be the first one in that list, followed
  28.586 +            by an alphabetically sorted list of VM label names """
  28.587 +        vmnames = self.policy_get_virtualmachinelabel_names()
  28.588 +        return self.policy_sort_virtualmachinelabel_names(vmnames)
  28.589 +
  28.590 +    def policy_get_virtualmachinelabels(self):
  28.591 +        """ Get a list of all virtual machine labels in this policy """
  28.592 +        res = []
  28.593 +        node = self.dom_get_node("SecurityLabelTemplate/SubjectLabels")
  28.594 +        if node:
  28.595 +            i = 0
  28.596 +            while i < len(node.childNodes):
  28.597 +                if node.childNodes[i].nodeName == "VirtualMachineLabel":
  28.598 +                    _res = {}
  28.599 +                    _res['type'] = xsconstants.ACM_LABEL_VM
  28.600 +                    name = self.policy_dom_get(node.childNodes[i], "Name")
  28.601 +                    _res['name'] = name.childNodes[0].nodeValue
  28.602 +                    stes = self.policy_dom_get(node.childNodes[i],
  28.603 +                                               "SimpleTypeEnforcementTypes")
  28.604 +                    if stes:
  28.605 +                        _res['stes'] = self.policy_get_types(stes)
  28.606 +                    else:
  28.607 +                        _res['stes'] = []
  28.608 +                    chws = self.policy_dom_get(node.childNodes[i],
  28.609 +                                               "ChineseWallTypes")
  28.610 +                    if chws:
  28.611 +                        _res['chws'] = self.policy_get_types(chws)
  28.612 +                    else:
  28.613 +                        _res['chws'] = []
  28.614 +                    res.append(_res)
  28.615 +                i += 1
  28.616 +        return res
  28.617 +
  28.618 +    def policy_get_stes_of_vmlabel(self, vmlabel):
  28.619 +        """ Get a list of all STEs of a given VMlabel """
  28.620 +        return self.__policy_get_stes_of_labeltype(vmlabel,
  28.621 +                                                   "VirtualMachineLabel")
  28.622 +
  28.623 +    def policy_get_stes_of_resource(self, reslabel):
  28.624 +        """ Get a list of all resources of a given VMlabel """
  28.625 +        return self.__policy_get_stes_of_labeltype(reslabel, "ResourceLabel")
  28.626 +
  28.627 +    def __policy_get_stes_of_labeltype(self, label, labeltype):
  28.628 +        node = self.dom_get_node("SecurityLabelTemplate/SubjectLabels")
  28.629 +        if node:
  28.630 +            i = 0
  28.631 +            while i < len(node.childNodes):
  28.632 +                if node.childNodes[i].nodeName == labeltype:
  28.633 +                    name = self.policy_dom_get(node.childNodes[i], "Name")
  28.634 +                    if name.childNodes[0].nodeValue == label:
  28.635 +                        stes = self.policy_dom_get(node.childNodes[i],
  28.636 +                                            "SimpleTypeEnforcementTypes")
  28.637 +                        if not stes:
  28.638 +                            return []
  28.639 +                        return self.policy_get_types(stes)
  28.640 +                i += 1
  28.641 +        return []
  28.642 +
  28.643 +    def policy_check_vmlabel_against_reslabels(self, vmlabel, resources):
  28.644 +        """
  28.645 +           Check whether the given vmlabel is compatible with the given
  28.646 +           resource labels. Do this by getting all the STEs of the
  28.647 +           vmlabel and the STEs of the resources. Any STE type of the
  28.648 +           VM label must match an STE type of the resource.
  28.649 +        """
  28.650 +        vm_stes = self.policy_get_stes_of_vmlabel(vmlabel)
  28.651 +        if len(vm_stes) == 0:
  28.652 +            return False
  28.653 +        for res in resources:
  28.654 +            res_stes = self.policy_get_stes_of_resource(res)
  28.655 +            if len( set(res_stes).union( set(vm_stes) ) ) == 0:
  28.656 +                return False
  28.657 +        return True
  28.658 +
  28.659 +    def __policy_get_label_translation_map(self, path, labeltype):
  28.660 +        res = {}
  28.661 +        node = self.dom_get_node("SecurityLabelTemplate/" + path)
  28.662 +        if node:
  28.663 +            i = 0
  28.664 +            while i < len(node.childNodes):
  28.665 +                if node.childNodes[i].nodeName == labeltype:
  28.666 +                    name = self.policy_dom_get(node.childNodes[i], "Name")
  28.667 +                    from_name = name.getAttribute("from")
  28.668 +                    if from_name:
  28.669 +                        res.update({from_name : name.childNodes[0].nodeValue})
  28.670 +                i += 1
  28.671 +        return res
  28.672 +
  28.673 +    def policy_get_vmlabel_translation_map(self):
  28.674 +        """
  28.675 +            Get a dictionary of virtual machine mappings from their
  28.676 +            old VMlabel name to the new VMlabel name.
  28.677 +        """
  28.678 +        return self.__policy_get_label_translation_map("SubjectLabels",
  28.679 +                                                       "VirtualMachineLabel")
  28.680 +
  28.681 +    def policy_get_reslabel_translation_map(self):
  28.682 +        """
  28.683 +            Get a dictionary of resource mappings from their
  28.684 +            old resource label name to the new resource label name.
  28.685 +        """
  28.686 +        return self.__policy_get_label_translation_map("ObjectLabels",
  28.687 +                                                       "ResourceLabel")
  28.688 +
  28.689 +    #
  28.690 +    # Object Label-related functions
  28.691 +    #
  28.692 +    def policy_get_resourcelabel_names(self):
  28.693 +        """
  28.694 +            Get the names of all resource labels in an array but
  28.695 +            only those that actually have types
  28.696 +        """
  28.697 +        strings = []
  28.698 +        node = self.dom_get_node("SecurityLabelTemplate/ObjectLabels")
  28.699 +        if node:
  28.700 +            i = 0
  28.701 +            while i < len(node.childNodes):
  28.702 +                if node.childNodes[i].nodeName == "ResourceLabel":
  28.703 +                    name = self.policy_dom_get(node.childNodes[i], "Name")
  28.704 +                    stes = self.policy_dom_get(node.childNodes[i],
  28.705 +                                          "SimpleTypeEnforcementTypes")
  28.706 +                    if stes:
  28.707 +                        strings.append(name.childNodes[0].nodeValue)
  28.708 +                i += 1
  28.709 +        return strings
  28.710 +
  28.711 +    def policy_get_resourcelabels(self):
  28.712 +        """
  28.713 +           Get all information about all resource labels of this policy.
  28.714 +        """
  28.715 +        res = []
  28.716 +        node = self.dom_get_node("SecurityLabelTemplate/ObjectLabels")
  28.717 +        if node:
  28.718 +            i = 0
  28.719 +            while i < len(node.childNodes):
  28.720 +                if node.childNodes[i].nodeName == "ResourceLabel":
  28.721 +                    _res = {}
  28.722 +                    _res['type'] = xsconstants.ACM_LABEL_RES
  28.723 +                    name = self.policy_dom_get(node.childNodes[i], "Name")
  28.724 +                    _res['name'] = name.childNodes[0].nodeValue
  28.725 +                    stes = self.policy_dom_get(node.childNodes[i],
  28.726 +                                               "SimpleTypeEnforcementTypes")
  28.727 +                    if stes:
  28.728 +                        _res['stes'] = self.policy_get_types(stes)
  28.729 +                    else:
  28.730 +                        _res['stes'] = []
  28.731 +                    _res['chws'] = []
  28.732 +                    res.append(_res)
  28.733 +                i += 1
  28.734 +        return res
  28.735 +
  28.736 +
  28.737 +    def policy_find_reslabels_with_stetype(self, stetype):
  28.738 +        """
  28.739 +           Find those resource labels that hold a given STE type.
  28.740 +        """
  28.741 +        res = []
  28.742 +        reslabels = self.policy_get_resourcelabels()
  28.743 +        for resl in reslabels:
  28.744 +            if stetype in resl['stes']:
  28.745 +                res.append(resl['name'])
  28.746 +        return res
  28.747 +
  28.748 +
  28.749 +    def toxml(self):
  28.750 +        dom = self.get_dom()
  28.751 +        if dom:
  28.752 +            return dom.toxml()
  28.753 +        return None
  28.754 +
  28.755 +    def save(self):
  28.756 +        ### Save the XML policy into a file ###
  28.757 +        rc = -xsconstants.XSERR_FILE_ERROR
  28.758 +        name = self.get_name()
  28.759 +        if name:
  28.760 +            path = self.path_from_policy_name(name)
  28.761 +            if path:
  28.762 +                f = open(path, 'w')
  28.763 +                if f:
  28.764 +                    f.write(self.toxml())
  28.765 +                    f.close()
  28.766 +                    rc = 0
  28.767 +        return rc
  28.768 +
  28.769 +    def __write_to_file(self, suffix, data):
  28.770 +        #write the data into a file with the given suffix
  28.771 +        f = open(self.get_filename(suffix),"w")
  28.772 +        if f:
  28.773 +            try:
  28.774 +                try:
  28.775 +                    f.write(data)
  28.776 +                except Exception, e:
  28.777 +                    log.error("Error writing file: %s" % str(e))
  28.778 +                    return -xsconstants.XSERR_FILE_ERROR
  28.779 +            finally:
  28.780 +                f.close()
  28.781 +        else:
  28.782 +            return -xsconstants.XSERR_FILE_ERROR
  28.783 +        return xsconstants.XSERR_SUCCESS
  28.784 +
  28.785 +
  28.786 +    def compile(self):
  28.787 +        rc = self.save()
  28.788 +        if rc == 0:
  28.789 +            rc, mapfile, bin_pol = self.policy_create_map_and_bin()
  28.790 +
  28.791 +            if rc == 0:
  28.792 +                rc = self.__write_to_file(".map", mapfile)
  28.793 +                if rc != 0:
  28.794 +                    log.error("Error writing map file")
  28.795 +
  28.796 +            if rc == 0:
  28.797 +                rc = self.__write_to_file(".bin", bin_pol)
  28.798 +                if rc != 0:
  28.799 +                    log.error("Error writing binary policy file")
  28.800 +        return rc
  28.801 +
  28.802 +    def loadintohv(self):
  28.803 +        """
  28.804 +            load this policy into the hypervisor
  28.805 +            if successful,the policy's flags will indicate that the
  28.806 +            policy is the one loaded into the hypervisor
  28.807 +        """
  28.808 +        (ret, output) = commands.getstatusoutput(
  28.809 +                                   security.xensec_tool +
  28.810 +                                   " loadpolicy " +
  28.811 +                                   self.get_filename(".bin"))
  28.812 +        if ret != 0:
  28.813 +            return -xsconstants.XSERR_POLICY_LOAD_FAILED
  28.814 +        return xsconstants.XSERR_SUCCESS
  28.815 +
  28.816 +    def isloaded(self):
  28.817 +        """
  28.818 +            Determine whether this policy is the active one.
  28.819 +        """
  28.820 +        security.refresh_security_policy()
  28.821 +        if self.get_name() == security.active_policy:
  28.822 +            return True
  28.823 +        return False
  28.824 +
  28.825 +    def destroy(self):
  28.826 +        """
  28.827 +            Destroy the policy including its binary, mapping and
  28.828 +            XML files.
  28.829 +            This only works if the policy is not the one that's loaded
  28.830 +        """
  28.831 +        if self.isloaded():
  28.832 +            return -xsconstants.XSERR_POLICY_LOADED
  28.833 +        files = [ self.get_filename(".map",""),
  28.834 +                  self.get_filename(".bin",""),
  28.835 +                  self.path_from_policy_name(self.get_name())]
  28.836 +        for f in files:
  28.837 +            try:
  28.838 +                os.unlink(f)
  28.839 +            except:
  28.840 +                pass
  28.841 +        if self.xendacmpolicy:
  28.842 +            self.xendacmpolicy.destroy()
  28.843 +        XSPolicy.destroy(self)
  28.844 +        return xsconstants.XSERR_SUCCESS
  28.845 +
  28.846 +    def policy_get_domain_label(self, domid):
  28.847 +        """
  28.848 +           Given a domain's ID, retrieve the label it has using
  28.849 +           its ssidref for reverse calculation.
  28.850 +        """
  28.851 +        try:
  28.852 +            mgmt_dom = security.get_ssid(domid)
  28.853 +        except:
  28.854 +            return ""
  28.855 +        return self.policy_get_domain_label_by_ssidref(int(mgmt_dom[3]))
  28.856 +
  28.857 +    def policy_get_domain_label_by_ssidref(self, ssidref):
  28.858 +        """ Given an ssidref, find the corresponding VM label """
  28.859 +        chwall_ref = ssidref & 0xffff
  28.860 +        try:
  28.861 +            allvmtypes = self.policy_get_virtualmachinelabel_names_sorted()
  28.862 +        except:
  28.863 +            return None
  28.864 +        return allvmtypes[chwall_ref-1] # skip _NULL_LABEL_
  28.865 +
  28.866 +    def policy_get_domain_label_formatted(self, domid):
  28.867 +        label = self.policy_get_domain_label(domid)
  28.868 +        if label == "":
  28.869 +            return ""
  28.870 +        return "%s:%s:%s" % (xsconstants.ACM_POLICY_ID, self.get_name(), label)
  28.871 +
  28.872 +    def policy_get_domain_label_by_ssidref_formatted(self, ssidref):
  28.873 +        label = self.policy_get_domain_label_by_ssidref(ssidref)
  28.874 +        if label == "":
  28.875 +            return ""
  28.876 +        return "%s:%s:%s" % (xsconstants.ACM_POLICY_ID, self.get_name(), label)
  28.877 +
  28.878 +    def policy_create_map_and_bin(self):
  28.879 +        """
  28.880 +            Create the policy's map and binary files -- compile the policy.
  28.881 +        """
  28.882 +        def roundup8(len):
  28.883 +            return ((len + 7) & ~7)
  28.884 +
  28.885 +        rc = xsconstants.XSERR_SUCCESS
  28.886 +        mapfile = ""
  28.887 +        primpolcode = ACM_POLICY_UNDEFINED
  28.888 +        secpolcode  = ACM_POLICY_UNDEFINED
  28.889 +        unknown_ste = set()
  28.890 +        unknown_chw = set()
  28.891 +
  28.892 +        rc = self.validate()
  28.893 +        if rc:
  28.894 +            return rc, "", ""
  28.895 +
  28.896 +        stes = self.policy_get_stetypes_types()
  28.897 +        if stes:
  28.898 +            stes.sort()
  28.899 +
  28.900 +        chws = self.policy_get_chwall_types()
  28.901 +        if chws:
  28.902 +            chws.sort()
  28.903 +
  28.904 +        vms = self.policy_get_virtualmachinelabels()
  28.905 +        bootstrap = self.policy_get_bootstrap_vmlabel()
  28.906 +
  28.907 +        vmlabels = self.policy_get_virtualmachinelabel_names_sorted()
  28.908 +        if bootstrap not in vmlabels:
  28.909 +            log.error("Bootstrap label '%s' not found among VM labels '%s'." \
  28.910 +                      % (bootstrap, vmlabels))
  28.911 +            return -xsconstants.XSERR_POLICY_INCONSISTENT, "", ""
  28.912 +
  28.913 +        vms_with_chws = []
  28.914 +        chws_by_vm = {}
  28.915 +        for v in vms:
  28.916 +            if v.has_key("chws"):
  28.917 +                vms_with_chws.append(v["name"])
  28.918 +                chws_by_vm[v["name"]] = v["chws"]
  28.919 +        if bootstrap in vms_with_chws:
  28.920 +            vms_with_chws.remove(bootstrap)
  28.921 +            vms_with_chws.sort()
  28.922 +            vms_with_chws.insert(0, bootstrap)
  28.923 +        else:
  28.924 +            vms_with_chws.sort()
  28.925 +
  28.926 +        vms_with_stes = []
  28.927 +        stes_by_vm = {}
  28.928 +        for v in vms:
  28.929 +            if v.has_key("stes"):
  28.930 +                vms_with_stes.append(v["name"])
  28.931 +                stes_by_vm[v["name"]] = v["stes"]
  28.932 +        if bootstrap in vms_with_stes:
  28.933 +            vms_with_stes.remove(bootstrap)
  28.934 +            vms_with_stes.sort()
  28.935 +            vms_with_stes.insert(0, bootstrap)
  28.936 +        else:
  28.937 +            vms_with_stes.sort()
  28.938 +
  28.939 +        resnames = self.policy_get_resourcelabel_names()
  28.940 +        resnames.sort()
  28.941 +        stes_by_res = {}
  28.942 +        res = self.policy_get_resourcelabels()
  28.943 +        for r in res:
  28.944 +            if r.has_key("stes"):
  28.945 +                stes_by_res[r["name"]] = r["stes"]
  28.946 +
  28.947 +        max_chw_ssids = 1 + len(vms_with_chws)
  28.948 +        max_chw_types = 1 + len(vms_with_chws)
  28.949 +        max_ste_ssids = 1 + len(vms_with_stes) + len(resnames)
  28.950 +        max_ste_types = 1 + len(vms_with_stes) + len(resnames)
  28.951 +
  28.952 +        mapfile  = "POLICYREFERENCENAME    %s\n" % self.get_name()
  28.953 +        mapfile += "MAGIC                  %08x\n" % ACM_MAGIC
  28.954 +        mapfile += "POLICFILE              %s\n" % \
  28.955 +            self.path_from_policy_name(self.get_name())
  28.956 +        mapfile += "BINARYFILE             %s\n" % self.get_filename(".bin")
  28.957 +        mapfile += "MAX-CHWALL-TYPES       %08x\n" % len(chws)
  28.958 +        mapfile += "MAX-CHWALL-SSIDS       %08x\n" % max_chw_ssids
  28.959 +        mapfile += "MAX-CHWALL-LABELS      %08x\n" % max_chw_ssids
  28.960 +        mapfile += "MAX-STE-TYPES          %08x\n" % len(stes)
  28.961 +        mapfile += "MAX-STE-SSIDS          %08x\n" % max_ste_ssids
  28.962 +        mapfile += "MAX-STE-LABELS         %08x\n" % max_ste_ssids
  28.963 +        mapfile += "\n"
  28.964 +
  28.965 +        if chws:
  28.966 +            mapfile += \
  28.967 +                 "PRIMARY                CHWALL\n"
  28.968 +            primpolcode = ACM_CHINESE_WALL_POLICY
  28.969 +            if stes:
  28.970 +                mapfile += \
  28.971 +                     "SECONDARY              STE\n"
  28.972 +            else:
  28.973 +                mapfile += \
  28.974 +                     "SECONDARY             NULL\n"
  28.975 +            secpolcode = ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY
  28.976 +        else:
  28.977 +            if stes:
  28.978 +                mapfile += \
  28.979 +                     "PRIMARY                STE\n"
  28.980 +                primpolcode = ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY
  28.981 +            mapfile += \
  28.982 +                     "SECONDARY             NULL\n"
  28.983 +
  28.984 +        mapfile += "\n"
  28.985 +
  28.986 +        if len(vms_with_chws) > 0:
  28.987 +            mapfile += \
  28.988 +                 "LABEL->SSID ANY CHWALL __NULL_LABEL__       %x\n" % 0
  28.989 +            i = 0
  28.990 +            for v in vms_with_chws:
  28.991 +                mapfile += \
  28.992 +                 "LABEL->SSID VM  CHWALL %-20s %x\n" % \
  28.993 +                  (v, i+1)
  28.994 +                i += 1
  28.995 +            mapfile += "\n"
  28.996 +
  28.997 +        if len(vms_with_stes) > 0 or len(resnames) > 0:
  28.998 +            mapfile += \
  28.999 +                 "LABEL->SSID ANY STE    __NULL_LABEL__       %08x\n" % 0
 28.1000 +            i = 0
 28.1001 +            for v in vms_with_stes:
 28.1002 +                mapfile += \
 28.1003 +                 "LABEL->SSID VM  STE    %-20s %x\n" % (v, i+1)
 28.1004 +                i += 1
 28.1005 +            j = 0
 28.1006 +            for r in resnames:
 28.1007 +                mapfile += \
 28.1008 +                 "LABEL->SSID RES STE    %-20s %x\n" % (r, j+i+1)
 28.1009 +                j += 1
 28.1010 +            mapfile += "\n"
 28.1011 +
 28.1012 +        if vms_with_chws:
 28.1013 +            mapfile += \
 28.1014 +                 "SSID->TYPE CHWALL      %08x\n" % 0
 28.1015 +            i = 1
 28.1016 +            for v in vms_with_chws:
 28.1017 +                mapfile += \
 28.1018 +                 "SSID->TYPE CHWALL      %08x" % i
 28.1019 +                for c in chws_by_vm[v]:
 28.1020 +                    mapfile += " %s" % c
 28.1021 +                mapfile += "\n"
 28.1022 +                i += 1
 28.1023 +            mapfile += "\n"
 28.1024 +
 28.1025 +        if len(vms_with_stes) > 0 or len(resnames) > 0:
 28.1026 +            mapfile += \
 28.1027 +                 "SSID->TYPE STE         %08x\n" % 0
 28.1028 +            i = 1
 28.1029 +            for v in vms_with_stes:
 28.1030 +                mapfile += \
 28.1031 +                 "SSID->TYPE STE         %08x" % i
 28.1032 +                for s in stes_by_vm[v]:
 28.1033 +                    mapfile += " %s" % s
 28.1034 +                mapfile += "\n"
 28.1035 +                i += 1
 28.1036 +
 28.1037 +            for r in resnames:
 28.1038 +                mapfile += \
 28.1039 +                 "SSID->TYPE STE         %08x" % i
 28.1040 +                for s in stes_by_res[r]:
 28.1041 +                    mapfile += " %s" % s
 28.1042 +                mapfile += "\n"
 28.1043 +                i += 1
 28.1044 +            mapfile += "\n"
 28.1045 +
 28.1046 +        if chws:
 28.1047 +            i = 0
 28.1048 +            while i < len(chws):
 28.1049 +                mapfile += \
 28.1050 +                 "TYPE CHWALL            %-20s %d\n" % (chws[i], i)
 28.1051 +                i += 1
 28.1052 +            mapfile += "\n"
 28.1053 +        if stes:
 28.1054 +            i = 0
 28.1055 +            while i < len(stes):
 28.1056 +                mapfile += \
 28.1057 +                 "TYPE STE               %-20s %d\n" % (stes[i], i)
 28.1058 +                i += 1
 28.1059 +            mapfile += "\n"
 28.1060 +
 28.1061 +        mapfile += "\n"
 28.1062 +
 28.1063 +        # Build header with policy name
 28.1064 +        length = roundup8(4 + len(self.get_name()) + 1)
 28.1065 +        polname = self.get_name();
 28.1066 +        pr_bin = struct.pack("!i", len(polname)+1)
 28.1067 +        pr_bin += polname;
 28.1068 +        while len(pr_bin) < length:
 28.1069 +             pr_bin += "\x00"
 28.1070 +
 28.1071 +        # Build chinese wall part
 28.1072 +        cfses_names = self.policy_get_chwall_cfses_names_sorted()
 28.1073 +        cfses = self.policy_get_chwall_cfses()
 28.1074 +
 28.1075 +        chwformat = "!iiiiiiiii"
 28.1076 +        max_chw_cfs = len(cfses)
 28.1077 +        chw_ssid_offset = struct.calcsize(chwformat)
 28.1078 +        chw_confset_offset = chw_ssid_offset + \
 28.1079 +                             2 * len(chws) * max_chw_types
 28.1080 +        chw_running_types_offset = 0
 28.1081 +        chw_conf_agg_offset = 0
 28.1082 +
 28.1083 +        chw_bin = struct.pack(chwformat,
 28.1084 +                              ACM_CHWALL_VERSION,
 28.1085 +                              ACM_CHINESE_WALL_POLICY,
 28.1086 +                              len(chws),
 28.1087 +                              max_chw_ssids,
 28.1088 +                              max_chw_cfs,
 28.1089 +                              chw_ssid_offset,
 28.1090 +                              chw_confset_offset,
 28.1091 +                              chw_running_types_offset,
 28.1092 +                              chw_conf_agg_offset)
 28.1093 +        chw_bin_body = ""
 28.1094 +        # simulate __NULL_LABEL__
 28.1095 +        for c in chws:
 28.1096 +            chw_bin_body += struct.pack("!h",0)
 28.1097 +        # VMs that are listed and their chinese walls
 28.1098 +        for v in vms_with_chws:
 28.1099 +            for c in chws:
 28.1100 +                unknown_chw |= (set(chws_by_vm[v]) - set(chws))
 28.1101 +                if c in chws_by_vm[v]:
 28.1102 +                    chw_bin_body += struct.pack("!h",1)
 28.1103 +                else:
 28.1104 +                    chw_bin_body += struct.pack("!h",0)
 28.1105 +
 28.1106 +        # Conflict sets -- they need to be processed in alphabetical order
 28.1107 +        for cn in cfses_names:
 28.1108 +            if cn == "" or cn is None:
 28.1109 +                return -xsconstants.XSERR_BAD_CONFLICTSET, "", ""
 28.1110 +            i = 0
 28.1111 +            while i < len(cfses):
 28.1112 +                if cfses[i]['name'] == cn:
 28.1113 +                    conf = cfses[i]['chws']
 28.1114 +                    break
 28.1115 +                i += 1
 28.1116 +            for c in chws:
 28.1117 +                if c in conf:
 28.1118 +                    chw_bin_body += struct.pack("!h",1)
 28.1119 +                else:
 28.1120 +                    chw_bin_body += struct.pack("!h",0)
 28.1121 +            del cfses[i]
 28.1122 +
 28.1123 +        if len(cfses) != 0:
 28.1124 +            return -xsconstants.XSERR_BAD_CONFLICTSET, "", ""
 28.1125 +
 28.1126 +        chw_bin += chw_bin_body
 28.1127 +
 28.1128 +        while len(chw_bin) < roundup8(len(chw_bin)):
 28.1129 +            chw_bin += "\x00"
 28.1130 +
 28.1131 +        # Build STE part
 28.1132 +        steformat="!iiiii"
 28.1133 +        ste_bin = struct.pack(steformat,
 28.1134 +                              ACM_STE_VERSION,
 28.1135 +                              ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY,
 28.1136 +                              len(stes),
 28.1137 +                              max_ste_types,
 28.1138 +                              struct.calcsize(steformat))
 28.1139 +        ste_bin_body = ""
 28.1140 +        if stes:
 28.1141 +            # Simulate __NULL_LABEL__
 28.1142 +            for s in stes:
 28.1143 +                ste_bin_body += struct.pack("!h",0)
 28.1144 +            # VMs that are listed and their chinese walls
 28.1145 +            for v in vms_with_stes:
 28.1146 +                unknown_ste |= (set(stes_by_vm[v]) - set(stes))
 28.1147 +                for s in stes:
 28.1148 +                    if s in stes_by_vm[v]:
 28.1149 +                        ste_bin_body += struct.pack("!h",1)
 28.1150 +                    else:
 28.1151 +                        ste_bin_body += struct.pack("!h",0)
 28.1152 +            for r in resnames:
 28.1153 +                unknown_ste |= (set(stes_by_res[r]) - set(stes))
 28.1154 +                for s in stes:
 28.1155 +                    if s in stes_by_res[r]:
 28.1156 +                        ste_bin_body += struct.pack("!h",1)
 28.1157 +                    else:
 28.1158 +                        ste_bin_body += struct.pack("!h",0)
 28.1159 +
 28.1160 +        ste_bin += ste_bin_body;
 28.1161 +
 28.1162 +        while len(ste_bin) < roundup8(len(ste_bin)):
 28.1163 +            ste_bin += "\x00"
 28.1164 +
 28.1165 +        #Write binary header:
 28.1166 +        headerformat="!iiiiiiiiii"
 28.1167 +        totallen_bin = struct.calcsize(headerformat) + \
 28.1168 +                       len(pr_bin) + len(chw_bin) + len(ste_bin)
 28.1169 +        polref_offset = struct.calcsize(headerformat)
 28.1170 +        primpoloffset = polref_offset + len(pr_bin)
 28.1171 +        if primpolcode == ACM_CHINESE_WALL_POLICY:
 28.1172 +            secpoloffset = primpoloffset + len(chw_bin)
 28.1173 +        elif primpolcode == ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY:
 28.1174 +            secpoloffset = primpoloffset + len(ste_bin)
 28.1175 +        else:
 28.1176 +            secpoloffset = primpoloffset
 28.1177 +
 28.1178 +        (major, minor) = self.getVersionTuple()
 28.1179 +        hdr_bin = struct.pack(headerformat,
 28.1180 +                              ACM_POLICY_VERSION,
 28.1181 +                              ACM_MAGIC,
 28.1182 +                              totallen_bin,
 28.1183 +                              polref_offset,
 28.1184 +                              primpolcode,
 28.1185 +                              primpoloffset,
 28.1186 +                              secpolcode,
 28.1187 +                              secpoloffset,
 28.1188 +                              major, minor)
 28.1189 +
 28.1190 +        all_bin = array.array('B')
 28.1191 +        for s in [ hdr_bin, pr_bin, chw_bin, ste_bin ]:
 28.1192 +            for c in s:
 28.1193 +                all_bin.append(ord(c))
 28.1194 +
 28.1195 +        log.info("Compiled policy: rc = %s" % hex(rc))
 28.1196 +        if len(unknown_ste) > 0:
 28.1197 +            log.info("The following STEs in VM/res labels were unknown:" \
 28.1198 +                     " %s" % list(unknown_ste))
 28.1199 +        if len(unknown_chw) > 0:
 28.1200 +            log.info("The following Ch. Wall types in labels were unknown:" \
 28.1201 +                     " %s" % list(unknown_chw))
 28.1202 +        return rc, mapfile, all_bin.tostring()
    29.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    29.2 +++ b/tools/python/xen/util/bootloader.py	Tue Jul 10 08:39:26 2007 -0600
    29.3 @@ -0,0 +1,521 @@
    29.4 +#============================================================================
    29.5 +# This library is free software; you can redistribute it and/or
    29.6 +# modify it under the terms of version 2.1 of the GNU Lesser General Public
    29.7 +# License as published by the Free Software Foundation.
    29.8 +#
    29.9 +# This library is distributed in the hope that it will be useful,
   29.10 +# but WITHOUT ANY WARRANTY; without even the implied warranty of
   29.11 +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   29.12 +# Lesser General Public License for more details.
   29.13 +#
   29.14 +# You should have received a copy of the GNU Lesser General Public
   29.15 +# License along with this library; if not, write to the Free Software
   29.16 +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
   29.17 +#============================================================================
   29.18 +# Copyright (C) 2006,2007 International Business Machines Corp.
   29.19 +# Author: Stefan Berger <stefanb@us.ibm.com>
   29.20 +#============================================================================
   29.21 +
   29.22 +import re
   29.23 +import os, stat
   29.24 +import tempfile
   29.25 +import shutil
   29.26 +import threading
   29.27 +from xen.xend.XendLogging import log
   29.28 +
   29.29 +__bootloader = None
   29.30 +
   29.31 +#
   29.32 +# Functions for modifying entries in the bootloader, i.e. adding
   29.33 +# a module to boot the system with a policy.
   29.34 +#
   29.35 +
   29.36 +def get_default_title():
   29.37 +    """ See description in Bootloader class below """
   29.38 +    return __bootloader.get_default_title()
   29.39 +
   29.40 +
   29.41 +def get_boot_policies():
   29.42 +    """ See description in Bootloader class below """
   29.43 +    return __bootloader.get_boot_policies()
   29.44 +
   29.45 +
   29.46 +def add_boot_policy(index, binpolname):
   29.47 +    """ See description in Bootloader class below """
   29.48 +    return __bootloader.add_boot_policy(index, binpolname)
   29.49 +
   29.50 +
   29.51 +def rm_policy_from_boottitle(index, unamelist):
   29.52 +    """ See description in Bootloader class below """
   29.53 +    return __bootloader.rm_policy_from_boottitle(index, unamelist)
   29.54 +
   29.55 +
   29.56 +def set_kernel_attval(index, att, val):
   29.57 +    """ See description in Bootloader class below """
   29.58 +    return __bootloader.set_kernel_attval(index, att, val)
   29.59 +
   29.60 +
   29.61 +def get_kernel_val(index, att):
   29.62 +    """ See description in Bootloader class below """
   29.63 +    return __bootloader.get_kernel_val(index, att)
   29.64 +
   29.65 +
   29.66 +def set_boot_policy(title_idx, filename):
   29.67 +    boottitles = get_boot_policies()
   29.68 +    if boottitles.has_key(title_idx):
   29.69 +        rm_policy_from_boottitle(title_idx, [ boottitles[title_idx] ])
   29.70 +    rc = add_boot_policy(title_idx, filename)
   29.71 +    return rc
   29.72 +
   29.73 +
   29.74 +def loads_default_policy(filename):
   29.75 +    """ Determine whether the given policy is loaded by the default boot title """
   29.76 +    polfile = get_default_policy()
   29.77 +    if polfile != None:
   29.78 +        if     polfile == filename or \
   29.79 +           "/"+polfile == filename:
   29.80 +            return True
   29.81 +    return False
   29.82 +
   29.83 +
   29.84 +def get_default_policy():
   29.85 +    """ Get the name of the policy loaded by the default boot title """
   29.86 +    title = get_default_title()
   29.87 +    policies = get_boot_policies()
   29.88 +    return policies.get(title)
   29.89 +
   29.90 +
   29.91 +def set_default_boot_policy(filename):
   29.92 +    """ Set the boot policy in the default title to the given name. """
   29.93 +    title = get_default_title()
   29.94 +    return set_boot_policy(title, filename)
   29.95 +
   29.96 +
   29.97 +def __is_bootdir_mounted():
   29.98 +    """
   29.99 +       Determine whether the boot partition /boot is mounted or not
  29.100 +    """
  29.101 +    rc = False
  29.102 +    file = open("/proc/mounts")
  29.103 +    for line in file:
  29.104 +        tmp = line.split(" ")
  29.105 +        if tmp[1] == "/boot":
  29.106 +            rc = True
  29.107 +            break
  29.108 +    return rc
  29.109 +
  29.110 +def get_prefix():
  29.111 +    if __is_bootdir_mounted():
  29.112 +        return "/"
  29.113 +    else:
  29.114 +        return "/boot/"
  29.115 +
  29.116 +
  29.117 +
  29.118 +class Bootloader:
  29.119 +    """ Bootloader class that real bootloader implementations must overwrite """
  29.120 +    def __init__(self):
  29.121 +        pass
  29.122 +
  29.123 +    def probe(self):
  29.124 +        """ Test whether this implementation of a bootloader is supported on the
  29.125 +            local system """
  29.126 +        return True
  29.127 +
  29.128 +    def get_default_title(self):
  29.129 +        """ Get the index (starting with 0) of the default boot title
  29.130 +            This number is read from the grub configuration file.
  29.131 +            In case of an error '-1' is returned
  29.132 +            @rtype: int
  29.133 +            @return: the index of the default boot title
  29.134 +        """
  29.135 +        return None
  29.136 +
  29.137 +    def get_boot_policies(self):
  29.138 +        """ Get a dictionary of policies that the system is booting with.
  29.139 +            @rtype: dict
  29.140 +            @return: dictionary of boot titles where the keys are the
  29.141 +                     indices of the boot titles
  29.142 +        """
  29.143 +        return {}
  29.144 +
  29.145 +    def add_boot_policy(self, index, binpolname):
  29.146 +        """ Add the binary policy for automatic loading when
  29.147 +            booting the system. Add it to the boot title at index
  29.148 +            'index'.
  29.149 +        """
  29.150 +        return False
  29.151 +
  29.152 +    def rm_policy_from_boottitle(self, index, unamelist):
  29.153 +        """ Remove a policy from the given title. A list of possible policies
  29.154 +            must be given to detect what module to remove
  29.155 +        """
  29.156 +        return False
  29.157 +
  29.158 +    def set_kernel_attval(self, index, att, val):
  29.159 +        """
  29.160 +            Append an attribut/value pair to the kernel line.
  29.161 +            @param index : The index of the title to modify
  29.162 +            @param att   : The attribute to add
  29.163 +            @param val   : The value to add. If no value or the special value
  29.164 +                           '<>' is given, then the attribute will be removed.
  29.165 +                           If an empty value is given, then only the attribute
  29.166 +                           is added in the format "att", otherwise "att=val"
  29.167 +                           is added.
  29.168 +        """
  29.169 +        return False
  29.170 +
  29.171 +    def get_kernel_val(self, index, att):
  29.172 +        """
  29.173 +            Get an attribute's value from the kernel line.
  29.174 +            @param index : The index of the title to get the attribute/value from
  29.175 +            @param att   : The attribute to read the value of
  29.176 +        """
  29.177 +        return None
  29.178 +
  29.179 +
  29.180 +class Grub(Bootloader):
  29.181 +    """ Implementation for manipulating bootloader entries in grub according
  29.182 +        to the 'Bootloader' class interface """
  29.183 +
  29.184 +    def __init__(self):
  29.185 +        self.__bootfile_lock = threading.RLock()
  29.186 +        self.title_re = re.compile("\s*title\s", re.IGNORECASE)
  29.187 +        self.module_re = re.compile("\s+module\s", re.IGNORECASE)
  29.188 +        self.policy_re = re.compile(".*\.bin", re.IGNORECASE)
  29.189 +        self.kernel_re = re.compile("\s*kernel\s", re.IGNORECASE)
  29.190 +        Bootloader.__init__(self)
  29.191 +
  29.192 +    def probe(self):
  29.193 +        try:
  29.194 +            boot_file = self.__get_bootfile()
  29.195 +        except:
  29.196 +            return False
  29.197 +        return True
  29.198 +
  29.199 +
  29.200 +    def __get_bootfile(self):
  29.201 +        """ Get the name of the bootfile """
  29.202 +        boot_file = "/boot/grub/grub.conf"
  29.203 +        alt_boot_file = "/boot/grub/menu.lst"
  29.204 +
  29.205 +        if not os.path.isfile(boot_file):
  29.206 +            #take alternate boot file instead
  29.207 +            boot_file = alt_boot_file
  29.208 +
  29.209 +        #follow symlink since menue.lst might be linked to grub.conf
  29.210 +        if not os.path.exists(boot_file):
  29.211 +            raise IOError("Boot file \'%s\' not found." % boot_file)
  29.212 +
  29.213 +        if stat.S_ISLNK(os.lstat(boot_file)[stat.ST_MODE]):
  29.214 +            new_name = os.readlink(boot_file)
  29.215 +            if new_name[0] == "/":
  29.216 +                boot_file = new_name
  29.217 +            else:
  29.218 +                path = boot_file.split('/')
  29.219 +                path[len(path)-1] = new_name
  29.220 +                boot_file = '/'.join(path)
  29.221 +        if not os.path.exists(boot_file):
  29.222 +            raise IOError("Boot file \'%s\' not found." % boot_file)
  29.223 +        return boot_file
  29.224 +
  29.225 +
  29.226 +    def __get_titles(self):
  29.227 +        """ Get the names of all boot titles in the grub config file
  29.228 +          @rtype: list
  29.229 +          @return: list of names of available boot titles
  29.230 +        """
  29.231 +        titles = []
  29.232 +        try:
  29.233 +            boot_file = self.__get_bootfile()
  29.234 +        except:
  29.235 +            return []
  29.236 +        try:
  29.237 +            self.__bootfile_lock.acquire()
  29.238 +            grub_fd = open(boot_file)
  29.239 +            for line in grub_fd:
  29.240 +                if self.title_re.match(line):
  29.241 +                    line = line.rstrip().lstrip()
  29.242 +                    titles.append(line.lstrip('title').lstrip())
  29.243 +        finally:
  29.244 +            self.__bootfile_lock.release()
  29.245 +        return titles
  29.246 +
  29.247 +
  29.248 +    def get_default_title(self):
  29.249 +        """ Get the index (starting with 0) of the default boot title
  29.250 +            This number is read from the grub configuration file.
  29.251 +            In case of an error '-1' is returned
  29.252 +            @rtype: int
  29.253 +            @return: the index of the default boot title
  29.254 +        """
  29.255 +        def_re = re.compile("default", re.IGNORECASE)
  29.256 +        default = None
  29.257 +        try:
  29.258 +            boot_file = self.__get_bootfile()
  29.259 +        except:
  29.260 +            return default
  29.261 +        try:
  29.262 +            self.__bootfile_lock.acquire()
  29.263 +            grub_fd = open(boot_file)
  29.264 +            for line in grub_fd:
  29.265 +                line = line.rstrip()
  29.266 +                if def_re.match(line):
  29.267 +                    line = line.rstrip()
  29.268 +                    line = line.lstrip("default=")
  29.269 +                    default = int(line)
  29.270 +                    break
  29.271 +        finally:
  29.272 +            self.__bootfile_lock.release()
  29.273 +        return default
  29.274 +
  29.275 +
  29.276 +    def get_boot_policies(self):
  29.277 +        """ Get a dictionary of policies that the system is booting with.
  29.278 +            @rtype: dict
  29.279 +            @return: dictionary of boot titles where the keys are the
  29.280 +                     indices of the boot titles
  29.281 +        """
  29.282 +        policies = {}
  29.283 +        within_title = 0
  29.284 +        idx = -1
  29.285 +        try:
  29.286 +            boot_file = self.__get_bootfile()
  29.287 +        except:
  29.288 +            return policies
  29.289 +        try:
  29.290 +            self.__bootfile_lock.acquire()
  29.291 +
  29.292 +            grub_fd = open(boot_file)
  29.293 +            for line in grub_fd:
  29.294 +                if self.title_re.match(line):
  29.295 +                    within_title = 1
  29.296 +                    idx = idx + 1
  29.297 +                if within_title and self.module_re.match(line):
  29.298 +                    if self.policy_re.match(line):
  29.299 +                        start = line.find("module")
  29.300 +                        pol = line[start+6:]
  29.301 +                        pol = pol.lstrip().rstrip()
  29.302 +                        if pol[0] == '/':
  29.303 +                            pol = pol[1:]
  29.304 +                        if pol[0:5] == "boot/":
  29.305 +                            pol = pol[5:]
  29.306 +                        policies[idx] = pol
  29.307 +        finally:
  29.308 +            self.__bootfile_lock.release()
  29.309 +        return policies
  29.310 +
  29.311 +
  29.312 +    def add_boot_policy(self, index, binpolname):
  29.313 +        """ Add the binary policy for automatic loading when
  29.314 +            booting the system. Add it to the boot title at index
  29.315 +            'index'.
  29.316 +        """
  29.317 +        ctr = 0
  29.318 +        module_line = ""
  29.319 +        within_title = 0
  29.320 +        found = False
  29.321 +        try:
  29.322 +            boot_file = self.__get_bootfile()
  29.323 +        except:
  29.324 +            return False
  29.325 +        try:
  29.326 +            self.__bootfile_lock.acquire()
  29.327 +            grub_fd = open(boot_file)
  29.328 +            (tmp_fd, tmp_grub) = tempfile.mkstemp()
  29.329 +            for line in grub_fd:
  29.330 +                if self.title_re.match(line):
  29.331 +                    if module_line != "" and not found:
  29.332 +                        os.write(tmp_fd, module_line)
  29.333 +                        found = True
  29.334 +
  29.335 +                    if ctr == index:
  29.336 +                        within_title = 1
  29.337 +                    else:
  29.338 +                        within_title = 0
  29.339 +                    ctr = ctr + 1
  29.340 +                elif within_title and self.module_re.match(line):
  29.341 +                    start = line.find("module")
  29.342 +                    l = line[start+6:len(line)]
  29.343 +                    l = l.lstrip()
  29.344 +                    if l[0] == '/':
  29.345 +                        prefix = "/"
  29.346 +                    else:
  29.347 +                        prefix = ""
  29.348 +                    prefix = get_prefix()
  29.349 +                    module_line = "\tmodule %s%s\n" % (prefix,binpolname)
  29.350 +                else:
  29.351 +                    if module_line != "" and not found:
  29.352 +                        os.write(tmp_fd, module_line)
  29.353 +                        found = True
  29.354 +
  29.355 +                os.write(tmp_fd, line)
  29.356 +
  29.357 +            if module_line != "" and not found:
  29.358 +                os.write(tmp_fd, module_line)
  29.359 +                found = True
  29.360 +
  29.361 +            shutil.move(boot_file, boot_file+"_save")
  29.362 +            shutil.copyfile(tmp_grub, boot_file)
  29.363 +            os.close(tmp_fd)
  29.364 +            try:
  29.365 +                os.remove(tmp_grub)
  29.366 +            except:
  29.367 +                pass
  29.368 +        finally:
  29.369 +            self.__bootfile_lock.release()
  29.370 +        return found
  29.371 +
  29.372 +
  29.373 +    def rm_policy_from_boottitle(self, index, unamelist):
  29.374 +        """ Remove a policy from the given title. A list of possible policies
  29.375 +            must be given to detect what module to remove
  29.376 +        """
  29.377 +        found = False
  29.378 +        ctr = 0
  29.379 +        within_title = 0
  29.380 +
  29.381 +        prefix = get_prefix()
  29.382 +        namelist = [prefix+name for name in unamelist]
  29.383 +
  29.384 +        try:
  29.385 +            boot_file = self.__get_bootfile()
  29.386 +        except:
  29.387 +            return False
  29.388 +        try:
  29.389 +            self.__bootfile_lock.acquire()
  29.390 +
  29.391 +            grub_fd = open(boot_file)
  29.392 +            (tmp_fd, tmp_grub) = tempfile.mkstemp()
  29.393 +            for line in grub_fd:
  29.394 +                omit_line = False
  29.395 +                if self.title_re.match(line):
  29.396 +                    if ctr == index:
  29.397 +                        within_title = 1
  29.398 +                    else:
  29.399 +                        within_title = 0
  29.400 +                    ctr = ctr + 1
  29.401 +                if within_title and self.module_re.match(line):
  29.402 +                    if self.policy_re.match(line):
  29.403 +                        start = line.find("module")
  29.404 +                        pol = line[start+6:len(line)]
  29.405 +                        pol = pol.lstrip().rstrip()
  29.406 +                        if pol in namelist:
  29.407 +                            omit_line = True
  29.408 +                            found = True
  29.409 +                if not omit_line:
  29.410 +                    os.write(tmp_fd, line)
  29.411 +            if found:
  29.412 +                shutil.move(boot_file, boot_file+"_save")
  29.413 +                shutil.copyfile(tmp_grub, boot_file)
  29.414 +            os.close(tmp_fd)
  29.415 +            try:
  29.416 +                os.remove(tmp_grub)
  29.417 +            except:
  29.418 +                pass
  29.419 +        finally:
  29.420 +            self.__bootfile_lock.release()
  29.421 +        return found
  29.422 +
  29.423 +
  29.424 +    def set_kernel_attval(self, index, att, val):
  29.425 +        """
  29.426 +            Append an attribut/value pair to the kernel line.
  29.427 +            @param index : The index of the title to modify
  29.428 +            @param att   : The attribute to add
  29.429 +            @param val   : The value to add. If no value or the special value
  29.430 +                           '<>' is given, then the attribute will be removed.
  29.431 +                           If an empty value is given, then only the attribute
  29.432 +                           is added in the format "att", otherwise "att=val"
  29.433 +                           is added.
  29.434 +        """
  29.435 +        found = False
  29.436 +        ctr = 0
  29.437 +        within_title = 0
  29.438 +        try:
  29.439 +            boot_file = self.__get_bootfile()
  29.440 +        except:
  29.441 +            False
  29.442 +        try:
  29.443 +            self.__bootfile_lock.acquire()
  29.444 +
  29.445 +            grub_fd = open(boot_file)
  29.446 +            (tmp_fd, tmp_grub) = tempfile.mkstemp()
  29.447 +            for line in grub_fd:
  29.448 +                if self.title_re.match(line):
  29.449 +                    if ctr == index:
  29.450 +                        within_title = 1
  29.451 +                    else:
  29.452 +                        within_title = 0
  29.453 +                    ctr = ctr + 1
  29.454 +                if within_title and self.kernel_re.match(line):
  29.455 +                    nitems = []
  29.456 +                    items = line.split(" ")
  29.457 +                    i = 0
  29.458 +                    while i < len(items):
  29.459 +                        el = items[i].split("=",1)
  29.460 +                        if el[0] != att:
  29.461 +                            nitems.append(items[i].rstrip("\n"))
  29.462 +                        i += 1
  29.463 +                    if val == "":
  29.464 +                        nitems.append("%s" % (att))
  29.465 +                    elif val != None and val != "<>":
  29.466 +                        nitems.append("%s=%s" % (att,val))
  29.467 +                    line = " ".join(nitems) + "\n"
  29.468 +                os.write(tmp_fd, line)
  29.469 +            shutil.move(boot_file, boot_file+"_save")
  29.470 +            shutil.copyfile(tmp_grub, boot_file)
  29.471 +            os.close(tmp_fd)
  29.472 +            try:
  29.473 +                os.remove(tmp_grub)
  29.474 +            except:
  29.475 +                pass
  29.476 +        finally:
  29.477 +            self.__bootfile_lock.release()
  29.478 +        return found
  29.479 +
  29.480 +
  29.481 +    def get_kernel_val(self, index, att):
  29.482 +        """
  29.483 +            Get an attribute's value from the kernel line.
  29.484 +            @param index : The index of the title to get the attribute/value from
  29.485 +            @param att   : The attribute to read the value of
  29.486 +        """
  29.487 +        ctr = 0
  29.488 +        within_title = 0
  29.489 +        try:
  29.490 +            boot_file = self.__get_bootfile()
  29.491 +        except:
  29.492 +            return None
  29.493 +        try:
  29.494 +            self.__bootfile_lock.acquire()
  29.495 +
  29.496 +            grub_fd = open(boot_file)
  29.497 +            for line in grub_fd:
  29.498 +                if self.title_re.match(line):
  29.499 +                    if ctr == index:
  29.500 +                        within_title = 1
  29.501 +                    else:
  29.502 +                        within_title = 0
  29.503 +                    ctr = ctr + 1
  29.504 +                if within_title and self.kernel_re.match(line):
  29.505 +                    line = line.rstrip().lstrip()
  29.506 +                    items = line.split(" ")
  29.507 +                    i = 0
  29.508 +                    while i < len(items):
  29.509 +                        el = items[i].split("=",1)
  29.510 +                        if el[0] == att:
  29.511 +                            if len(el) == 1:
  29.512 +                                return "<>"
  29.513 +                            return el[1]
  29.514 +                        i += 1
  29.515 +        finally:
  29.516 +            self.__bootfile_lock.release()
  29.517 +        return None # Not found
  29.518 +
  29.519 +
  29.520 +__bootloader = Bootloader()
  29.521 +
  29.522 +grub = Grub()
  29.523 +if grub.probe() == True:
  29.524 +    __bootloader = grub
    30.1 --- a/tools/python/xen/util/security.py	Mon Jul 09 09:22:58 2007 -0600
    30.2 +++ b/tools/python/xen/util/security.py	Tue Jul 10 08:39:26 2007 -0600
    30.3 @@ -15,17 +15,22 @@
    30.4  # Copyright (C) 2006 International Business Machines Corp.
    30.5  # Author: Reiner Sailer
    30.6  # Author: Bryan D. Payne <bdpayne@us.ibm.com>
    30.7 +# Author: Stefan Berger <stefanb@us.ibm.com>
    30.8  #============================================================================
    30.9  
   30.10  import commands
   30.11  import logging
   30.12 -import sys, os, string, re
   30.13 -import traceback
   30.14 -import shutil
   30.15 +import os, string, re
   30.16 +import threading
   30.17 +import struct
   30.18 +import stat
   30.19  from xen.lowlevel import acm
   30.20  from xen.xend import sxp
   30.21 +from xen.xend import XendConstants
   30.22  from xen.xend.XendLogging import log
   30.23 -from xen.util import dictio
   30.24 +from xen.xend.XendError import VmError
   30.25 +from xen.util import dictio, xsconstants
   30.26 +from xen.xend.XendConstants import *
   30.27  
   30.28  #global directories and tools for security management
   30.29  policy_dir_prefix = "/etc/xen/acm-security/policies"
   30.30 @@ -60,6 +65,10 @@ policy_name_re = re.compile(".*[chwall|s
   30.31  #other global variables
   30.32  NULL_SSIDREF = 0
   30.33  
   30.34 +#general Rlock for map files; only one lock for all mapfiles
   30.35 +__mapfile_lock = threading.RLock()
   30.36 +__resfile_lock = threading.RLock()
   30.37 +
   30.38  log = logging.getLogger("xend.util.security")
   30.39  
   30.40  # Our own exception definition. It is masked (pass) if raised and
   30.41 @@ -75,7 +84,6 @@ class ACMError(Exception):
   30.42  def err(msg):
   30.43      """Raise ACM exception.
   30.44      """
   30.45 -    sys.stderr.write("ACMError: " + msg + "\n")
   30.46      raise ACMError(msg)
   30.47  
   30.48  
   30.49 @@ -83,6 +91,13 @@ def err(msg):
   30.50  active_policy = None
   30.51  
   30.52  
   30.53 +def mapfile_lock():
   30.54 +    __mapfile_lock.acquire()
   30.55 +
   30.56 +def mapfile_unlock():
   30.57 +    __mapfile_lock.release()
   30.58 +
   30.59 +
   30.60  def refresh_security_policy():
   30.61      """
   30.62      retrieves security policy
   30.63 @@ -106,6 +121,39 @@ def on():
   30.64      return (active_policy not in ['INACTIVE', 'NULL'])
   30.65  
   30.66  
   30.67 +def calc_dom_ssidref_from_info(info):
   30.68 +    """
   30.69 +       Calculate a domain's ssidref from the security_label in its
   30.70 +       info.
   30.71 +       This function is called before the domain is started and
   30.72 +       makes sure that:
   30.73 +        - the type of the policy is the same as indicated in the label
   30.74 +        - the name of the policy is the same as indicated in the label
   30.75 +        - calculates an up-to-date ssidref for the domain
   30.76 +       The latter is necessary since the domain's ssidref could have
   30.77 +       changed due to changes to the policy.
   30.78 +    """
   30.79 +    import xen.xend.XendConfig
   30.80 +    if isinstance(info, xen.xend.XendConfig.XendConfig):
   30.81 +        if info.has_key('security_label'):
   30.82 +            seclab = info['security_label']
   30.83 +            tmp = seclab.split(":")
   30.84 +            if len(tmp) != 3:
   30.85 +                raise VmError("VM label '%s' in wrong format." % seclab)
   30.86 +            typ, policyname, vmlabel = seclab.split(":")
   30.87 +            if typ != xsconstants.ACM_POLICY_ID:
   30.88 +                raise VmError("Policy type '%s' not supported." % typ)
   30.89 +            refresh_security_policy()
   30.90 +            if active_policy != policyname:
   30.91 +                raise VmError("Active policy '%s' different than "
   30.92 +                              "what in VM's label ('%s')." %
   30.93 +                              (active_policy, policyname))
   30.94 +            ssidref = label2ssidref(vmlabel, policyname, "dom")
   30.95 +            return ssidref
   30.96 +        else:
   30.97 +            return 0
   30.98 +    raise VmError("security.calc_dom_ssidref_from_info: info of type '%s'"
   30.99 +                  "not supported." % type(info))
  30.100  
  30.101  # Assumes a 'security' info  [security access_control ...] [ssidref ...]
  30.102  def get_security_info(info, field):
  30.103 @@ -146,7 +194,6 @@ def get_security_info(info, field):
  30.104          return None
  30.105  
  30.106  
  30.107 -
  30.108  def get_security_printlabel(info):
  30.109      """retrieves printable security label from self.info['security']),
  30.110      preferably the label name and otherwise (if label is not specified
  30.111 @@ -250,32 +297,37 @@ def ssidref2label(ssidref_var):
  30.112      else:
  30.113          err("Instance type of ssidref not supported (must be of type 'str' or 'int')")
  30.114  
  30.115 -    (primary, secondary, f, pol_exists) = getmapfile(None)
  30.116 -    if not f:
  30.117 -        if (pol_exists):
  30.118 -            err("Mapping file for policy \'" + policyname + "\' not found.\n" +
  30.119 -                "Please use makepolicy command to create mapping file!")
  30.120 -        else:
  30.121 -            err("Policy file for \'" + active_policy + "\' not found.")
  30.122 +    try:
  30.123 +        mapfile_lock()
  30.124 +
  30.125 +        (primary, secondary, f, pol_exists) = getmapfile(None)
  30.126 +        if not f:
  30.127 +            if (pol_exists):
  30.128 +                err("Mapping file for policy not found.\n" +
  30.129 +                    "Please use makepolicy command to create mapping file!")
  30.130 +            else:
  30.131 +                err("Policy file for \'" + active_policy + "\' not found.")
  30.132  
  30.133 -    #2. get labelnames for both ssidref parts
  30.134 -    pri_ssid = ssidref & 0xffff
  30.135 -    sec_ssid = ssidref >> 16
  30.136 -    pri_null_ssid = NULL_SSIDREF & 0xffff
  30.137 -    sec_null_ssid = NULL_SSIDREF >> 16
  30.138 -    pri_labels = []
  30.139 -    sec_labels = []
  30.140 -    labels = []
  30.141 +        #2. get labelnames for both ssidref parts
  30.142 +        pri_ssid = ssidref & 0xffff
  30.143 +        sec_ssid = ssidref >> 16
  30.144 +        pri_null_ssid = NULL_SSIDREF & 0xffff
  30.145 +        sec_null_ssid = NULL_SSIDREF >> 16
  30.146 +        pri_labels = []
  30.147 +        sec_labels = []
  30.148 +        labels = []
  30.149  
  30.150 -    for line in f:
  30.151 -        l = line.split()
  30.152 -        if (len(l) < 5) or (l[0] != "LABEL->SSID"):
  30.153 -            continue
  30.154 -        if primary and (l[2] == primary) and (int(l[4], 16) == pri_ssid):
  30.155 -            pri_labels.append(l[3])
  30.156 -        if secondary and (l[2] == secondary) and (int(l[4], 16) == sec_ssid):
  30.157 -            sec_labels.append(l[3])
  30.158 -    f.close()
  30.159 +        for line in f:
  30.160 +            l = line.split()
  30.161 +            if (len(l) < 5) or (l[0] != "LABEL->SSID"):
  30.162 +                continue
  30.163 +            if primary and (l[2] == primary) and (int(l[4], 16) == pri_ssid):
  30.164 +                pri_labels.append(l[3])
  30.165 +            if secondary and (l[2] == secondary) and (int(l[4], 16) == sec_ssid):
  30.166 +                sec_labels.append(l[3])
  30.167 +        f.close()
  30.168 +    finally:
  30.169 +        mapfile_unlock()
  30.170  
  30.171      #3. get the label that is in both lists (combination must be a single label)
  30.172      if (primary == "CHWALL") and (pri_ssid == pri_null_ssid) and (sec_ssid != sec_null_ssid):
  30.173 @@ -297,7 +349,7 @@ def ssidref2label(ssidref_var):
  30.174  
  30.175  
  30.176  
  30.177 -def label2ssidref(labelname, policyname, type):
  30.178 +def label2ssidref(labelname, policyname, typ):
  30.179      """
  30.180      returns ssidref corresponding to labelname;
  30.181      maps current policy to default directory
  30.182 @@ -307,42 +359,51 @@ def label2ssidref(labelname, policyname,
  30.183          err("Cannot translate labels for \'" + policyname + "\' policy.")
  30.184  
  30.185      allowed_types = ['ANY']
  30.186 -    if type == 'dom':
  30.187 +    if typ == 'dom':
  30.188          allowed_types.append('VM')
  30.189 -    elif type == 'res':
  30.190 +    elif typ == 'res':
  30.191          allowed_types.append('RES')
  30.192      else:
  30.193          err("Invalid type.  Must specify 'dom' or 'res'.")
  30.194  
  30.195 -    (primary, secondary, f, pol_exists) = getmapfile(policyname)
  30.196 +    try:
  30.197 +        mapfile_lock()
  30.198 +        (primary, secondary, f, pol_exists) = getmapfile(policyname)
  30.199  
  30.200 -    #2. get labelnames for ssidref parts and find a common label
  30.201 -    pri_ssid = []
  30.202 -    sec_ssid = []
  30.203 -    for line in f:
  30.204 -        l = line.split()
  30.205 -        if (len(l) < 5) or (l[0] != "LABEL->SSID"):
  30.206 -            continue
  30.207 -        if primary and (l[1] in allowed_types) and (l[2] == primary) and (l[3] == labelname):
  30.208 -            pri_ssid.append(int(l[4], 16))
  30.209 -        if secondary and (l[1] in allowed_types) and (l[2] == secondary) and (l[3] == labelname):
  30.210 -            sec_ssid.append(int(l[4], 16))
  30.211 -    f.close()
  30.212 -    if (type == 'res') and (primary == "CHWALL") and (len(pri_ssid) == 0):
  30.213 -        pri_ssid.append(NULL_SSIDREF)
  30.214 -    elif (type == 'res') and (secondary == "CHWALL") and (len(sec_ssid) == 0):
  30.215 -        sec_ssid.append(NULL_SSIDREF)
  30.216 +        #2. get labelnames for ssidref parts and find a common label
  30.217 +        pri_ssid = []
  30.218 +        sec_ssid = []
  30.219 +        for line in f:
  30.220 +            l = line.split()
  30.221 +            if (len(l) < 5) or (l[0] != "LABEL->SSID"):
  30.222 +                continue
  30.223 +            if primary and (l[1] in allowed_types) and \
  30.224 +                           (l[2] == primary) and \
  30.225 +                           (l[3] == labelname):
  30.226 +                pri_ssid.append(int(l[4], 16))
  30.227 +            if secondary and (l[1] in allowed_types) and \
  30.228 +                             (l[2] == secondary) and \
  30.229 +                             (l[3] == labelname):
  30.230 +                sec_ssid.append(int(l[4], 16))
  30.231 +        f.close()
  30.232 +        if (typ == 'res') and (primary == "CHWALL") and (len(pri_ssid) == 0):
  30.233 +            pri_ssid.append(NULL_SSIDREF)
  30.234 +        elif (typ == 'res') and (secondary == "CHWALL") and \
  30.235 +             (len(sec_ssid) == 0):
  30.236 +            sec_ssid.append(NULL_SSIDREF)
  30.237  
  30.238 -    #3. sanity check and composition of ssidref
  30.239 -    if (len(pri_ssid) == 0) or ((len(sec_ssid) == 0) and (secondary != "NULL")):
  30.240 -        err("Label \'" + labelname + "\' not found.")
  30.241 -    elif (len(pri_ssid) > 1) or (len(sec_ssid) > 1):
  30.242 -        err("Label \'" + labelname + "\' not unique in policy (policy error)")
  30.243 -    if secondary == "NULL":
  30.244 -        return pri_ssid[0]
  30.245 -    else:
  30.246 -        return (sec_ssid[0] << 16) | pri_ssid[0]
  30.247 -
  30.248 +        #3. sanity check and composition of ssidref
  30.249 +        if (len(pri_ssid) == 0) or ((len(sec_ssid) == 0) and \
  30.250 +            (secondary != "NULL")):
  30.251 +            err("Label \'" + labelname + "\' not found.")
  30.252 +        elif (len(pri_ssid) > 1) or (len(sec_ssid) > 1):
  30.253 +            err("Label \'" + labelname + "\' not unique in policy (policy error)")
  30.254 +        if secondary == "NULL":
  30.255 +            return pri_ssid[0]
  30.256 +        else:
  30.257 +            return (sec_ssid[0] << 16) | pri_ssid[0]
  30.258 +    finally:
  30.259 +       mapfile_unlock()
  30.260  
  30.261  
  30.262  def refresh_ssidref(config):
  30.263 @@ -381,8 +442,9 @@ def refresh_ssidref(config):
  30.264                      err("Illegal field in access_control")
  30.265      #verify policy is correct
  30.266      if active_policy != policyname:
  30.267 -        err("Policy \'" + policyname + "\' in label does not match active policy \'"
  30.268 -            + active_policy +"\'!")
  30.269 +        err("Policy \'" + str(policyname) +
  30.270 +            "\' in label does not match active policy \'"
  30.271 +            + str(active_policy) +"\'!")
  30.272  
  30.273      new_ssidref = label2ssidref(labelname, policyname, 'dom')
  30.274      if not new_ssidref:
  30.275 @@ -470,6 +532,25 @@ def get_decision(arg1, arg2):
  30.276          err("Cannot determine decision (Invalid parameter).")
  30.277  
  30.278  
  30.279 +def hv_chg_policy(bin_pol, del_array, chg_array):
  30.280 +    """
  30.281 +        Change the binary policy in the hypervisor
  30.282 +        The 'del_array' and 'chg_array' give hints about deleted ssidrefs
  30.283 +        and changed ssidrefs which can be due to deleted VM labels
  30.284 +        or reordered VM labels
  30.285 +    """
  30.286 +    rc = -xsconstants.XSERR_GENERAL_FAILURE
  30.287 +    errors = ""
  30.288 +    if not on():
  30.289 +        err("No policy active.")
  30.290 +    try:
  30.291 +        rc, errors = acm.chgpolicy(bin_pol, del_array, chg_array)
  30.292 +    except Exception, e:
  30.293 +        pass
  30.294 +    if (len(errors) > 0):
  30.295 +        rc = -xsconstants.XSERR_HV_OP_FAILED
  30.296 +    return rc, errors
  30.297 +
  30.298  
  30.299  def make_policy(policy_name):
  30.300      policy_file = string.join(string.split(policy_name, "."), "/")
  30.301 @@ -480,8 +561,6 @@ def make_policy(policy_name):
  30.302      if ret:
  30.303          err("Creating policy failed:\n" + output)
  30.304  
  30.305 -
  30.306 -
  30.307  def load_policy(policy_name):
  30.308      global active_policy
  30.309      policy_file = policy_dir_prefix + "/" + string.join(string.split(policy_name, "."), "/")
  30.310 @@ -538,8 +617,8 @@ def list_labels(policy_name, condition):
  30.311  
  30.312  
  30.313  def get_res_label(resource):
  30.314 -    """Returns resource label information (label, policy) if it exists.
  30.315 -       Otherwise returns null label and policy.
  30.316 +    """Returns resource label information (policytype, label, policy) if
  30.317 +       it exists. Otherwise returns null label and policy.
  30.318      """
  30.319      def default_res_label():
  30.320          ssidref = NULL_SSIDREF
  30.321 @@ -547,23 +626,19 @@ def get_res_label(resource):
  30.322              label = ssidref2label(ssidref)
  30.323          else:
  30.324              label = None
  30.325 -        return (label, 'NULL')
  30.326 +        return (xsconstants.ACM_POLICY_ID, 'NULL', label)
  30.327  
  30.328 -    (label, policy) = default_res_label()
  30.329  
  30.330 -    # load the resource label file
  30.331 -    res_label_cache = {}
  30.332 -    try:
  30.333 -        res_label_cache = dictio.dict_read("resources", res_label_filename)
  30.334 -    except:
  30.335 -        log.info("Resource label file not found.")
  30.336 -        return default_res_label()
  30.337 +    tmp = get_resource_label(resource)
  30.338 +    if len(tmp) == 2:
  30.339 +        policytype = xsconstants.ACM_POLICY_ID
  30.340 +        policy, label = tmp
  30.341 +    elif len(tmp) == 3:
  30.342 +        policytype, policy, label = tmp
  30.343 +    else:
  30.344 +        policytype, policy, label = default_res_label()
  30.345  
  30.346 -    # find the resource information
  30.347 -    if res_label_cache.has_key(resource):
  30.348 -        (policy, label) = res_label_cache[resource]
  30.349 -
  30.350 -    return (label, policy)
  30.351 +    return (policytype, label, policy)
  30.352  
  30.353  
  30.354  def get_res_security_details(resource):
  30.355 @@ -582,7 +657,7 @@ def get_res_security_details(resource):
  30.356      (label, ssidref, policy) = default_security_details()
  30.357  
  30.358      # find the entry associated with this resource
  30.359 -    (label, policy) = get_res_label(resource)
  30.360 +    (policytype, label, policy) = get_res_label(resource)
  30.361      if policy == 'NULL':
  30.362          log.info("Resource label for "+resource+" not in file, using DEFAULT.")
  30.363          return default_security_details()
  30.364 @@ -596,8 +671,29 @@ def get_res_security_details(resource):
  30.365  
  30.366      return (label, ssidref, policy)
  30.367  
  30.368 +def security_label_to_details(seclab):
  30.369 +    """ Convert a Xen-API type of security label into details """
  30.370 +    def default_security_details():
  30.371 +        ssidref = NULL_SSIDREF
  30.372 +        if on():
  30.373 +            label = ssidref2label(ssidref)
  30.374 +        else:
  30.375 +            label = None
  30.376 +        policy = active_policy
  30.377 +        return (label, ssidref, policy)
  30.378  
  30.379 -def unify_resname(resource):
  30.380 +    (policytype, policy, label) = seclab.split(":")
  30.381 +
  30.382 +    # is this resource label for the running policy?
  30.383 +    if policy == active_policy:
  30.384 +        ssidref = label2ssidref(label, policy, 'res')
  30.385 +    else:
  30.386 +        log.info("Resource label not for active policy, using DEFAULT.")
  30.387 +        return default_security_details()
  30.388 +
  30.389 +    return (label, ssidref, policy)
  30.390 +
  30.391 +def unify_resname(resource, mustexist=True):
  30.392      """Makes all resource locations absolute. In case of physical
  30.393      resources, '/dev/' is added to local file names"""
  30.394  
  30.395 @@ -606,28 +702,53 @@ def unify_resname(resource):
  30.396  
  30.397      # sanity check on resource name
  30.398      try:
  30.399 -        (type, resfile) = resource.split(":", 1)
  30.400 +        (typ, resfile) = resource.split(":", 1)
  30.401      except:
  30.402          err("Resource spec '%s' contains no ':' delimiter" % resource)
  30.403  
  30.404 -    if type == "tap":
  30.405 +    if typ == "tap":
  30.406          try:
  30.407              (subtype, resfile) = resfile.split(":")
  30.408          except:
  30.409              err("Resource spec '%s' contains no tap subtype" % resource)
  30.410  
  30.411 -    if type in ["phy", "tap"]:
  30.412 +    import os
  30.413 +    if typ in ["phy", "tap"]:
  30.414          if not resfile.startswith("/"):
  30.415              resfile = "/dev/" + resfile
  30.416 +        if mustexist:
  30.417 +            stats = os.lstat(resfile)
  30.418 +            if stat.S_ISLNK(stats[stat.ST_MODE]):
  30.419 +                resolved = os.readlink(resfile)
  30.420 +                if resolved[0] != "/":
  30.421 +                    resfile = os.path.join(os.path.dirname(resfile), resolved)
  30.422 +                    resfile = os.path.abspath(resfile)
  30.423 +                else:
  30.424 +                    resfile = resolved
  30.425 +                stats = os.lstat(resfile)
  30.426 +            if not (stat.S_ISBLK(stats[stat.ST_MODE])):
  30.427 +                err("Invalid resource")
  30.428 +
  30.429 +    if typ in [ "file", "tap" ]:
  30.430 +        if mustexist:
  30.431 +            stats = os.lstat(resfile)
  30.432 +            if stat.S_ISLNK(stats[stat.ST_MODE]):
  30.433 +                resfile = os.readlink(resfile)
  30.434 +                stats = os.lstat(resfile)
  30.435 +            if not stat.S_ISREG(stats[stat.ST_MODE]):
  30.436 +                err("Invalid resource")
  30.437  
  30.438      #file: resources must specified with absolute path
  30.439 -    if (not resfile.startswith("/")) or (not os.path.exists(resfile)):
  30.440 -        err("Invalid resource.")
  30.441 +    #vlan resources don't start with '/'
  30.442 +    if typ != "vlan":
  30.443 +        if (not resfile.startswith("/")) or \
  30.444 +           (mustexist and not os.path.exists(resfile)):
  30.445 +            err("Invalid resource.")
  30.446  
  30.447      # from here on absolute file names with resources
  30.448 -    if type == "tap":
  30.449 -        type = type + ":" + subtype
  30.450 -    resource = type + ":" + resfile
  30.451 +    if typ == "tap":
  30.452 +        typ = typ + ":" + subtype
  30.453 +    resource = typ + ":" + resfile
  30.454      return resource
  30.455  
  30.456  
  30.457 @@ -662,9 +783,481 @@ def res_security_check(resource, domain_
  30.458      else:
  30.459          # Note, we can't canonicalise the resource here, because people using
  30.460          # xm without ACM are free to use relative paths.
  30.461 -        (label, policy) = get_res_label(resource)
  30.462 +        (policytype, label, policy) = get_res_label(resource)
  30.463          if policy != 'NULL':
  30.464              raise ACMError("Security is off, but '"+resource+"' is labeled")
  30.465              rtnval = 0
  30.466  
  30.467      return rtnval
  30.468 +
  30.469 +def res_security_check_xapi(rlabel, rssidref, rpolicy, xapi_dom_label):
  30.470 +    """Checks if the given resource can be used by the given domain
  30.471 +       label.  Returns 1 if the resource can be used, otherwise 0.
  30.472 +    """
  30.473 +    rtnval = 1
  30.474 +    # if security is on, ask the hypervisor for a decision
  30.475 +    if on():
  30.476 +        typ, dpolicy, domain_label = xapi_dom_label.split(":")
  30.477 +        if not dpolicy or not domain_label:
  30.478 +            raise VmError("VM security label in wrong format.")
  30.479 +        if active_policy != rpolicy:
  30.480 +            raise VmError("Resource's policy '%s' != active policy '%s'" %
  30.481 +                          (rpolicy, active_policy))
  30.482 +        domac = ['access_control']
  30.483 +        domac.append(['policy', active_policy])
  30.484 +        domac.append(['label', domain_label])
  30.485 +        domac.append(['type', 'dom'])
  30.486 +        decision = get_decision(domac, ['ssidref', str(rssidref)])
  30.487 +
  30.488 +        log.info("Access Control Decision : %s" % decision)
  30.489 +        # provide descriptive error messages
  30.490 +        if decision == 'DENIED':
  30.491 +            if rlabel == ssidref2label(NULL_SSIDREF):
  30.492 +                #raise ACMError("Resource is not labeled")
  30.493 +                rtnval = 0
  30.494 +            else:
  30.495 +                #raise ACMError("Permission denied for resource because label '"+rlabel+"' is not allowed")
  30.496 +                rtnval = 0
  30.497 +
  30.498 +    # security is off, make sure resource isn't labeled
  30.499 +    else:
  30.500 +        # Note, we can't canonicalise the resource here, because people using
  30.501 +        # xm without ACM are free to use relative paths.
  30.502 +        if rpolicy != 'NULL':
  30.503 +            #raise ACMError("Security is off, but resource is labeled")
  30.504 +            rtnval = 0
  30.505 +
  30.506 +    return rtnval
  30.507 +
  30.508 +
  30.509 +def set_resource_label_xapi(resource, reslabel_xapi, oldlabel_xapi):
  30.510 +    """Assign a resource label to a resource
  30.511 +    @param resource: The name of a resource, i.e., "phy:/dev/hda", or
  30.512 +              "tap:qcow:/path/to/file.qcow"
  30.513 +
  30.514 +    @param reslabel_xapi: A resource label foramtted as in all other parts of
  30.515 +                          the Xen-API, i.e., ACM:xm-test:blue"
  30.516 +    @rtype: int
  30.517 +    @return Success (0) or failure value (< 0)
  30.518 +    """
  30.519 +    olabel = ""
  30.520 +    if reslabel_xapi == "":
  30.521 +        return rm_resource_label(resource, oldlabel_xapi)
  30.522 +    typ, policyref, label = reslabel_xapi.split(":")
  30.523 +    if typ != xsconstants.ACM_POLICY_ID:
  30.524 +        return -xsconstants.XSERR_WRONG_POLICY_TYPE
  30.525 +    if not policyref or not label:
  30.526 +        return -xsconstants.XSERR_BAD_LABEL_FORMAT
  30.527 +    if oldlabel_xapi not in [ "" ]:
  30.528 +        tmp = oldlabel_xapi.split(":")
  30.529 +        if len(tmp) != 3:
  30.530 +            return -xsconstants.XSERR_BAD_LABEL_FORMAT
  30.531 +        otyp, opolicyref, olabel = tmp
  30.532 +        # Only ACM is supported
  30.533 +        if otyp != xsconstants.ACM_POLICY_ID:
  30.534 +            return -xsconstants.XSERR_WRONG_POLICY_TYPE
  30.535 +    return set_resource_label(resource, typ, policyref, label, olabel)
  30.536 +
  30.537 +def is_resource_in_use(resource):
  30.538 +    """ Investigate all running domains whether they use this device """
  30.539 +    from xen.xend import XendDomain
  30.540 +    dominfos = XendDomain.instance().list('all')
  30.541 +    lst = []
  30.542 +    for dominfo in dominfos:
  30.543 +        if is_resource_in_use_by_dom(dominfo, resource):
  30.544 +            lst.append(dominfo)
  30.545 +    return lst
  30.546 +
  30.547 +def devices_equal(res1, res2):
  30.548 +    """ Determine whether two devices are equal """
  30.549 +    return (unify_resname(res1) == unify_resname(res2))
  30.550 +
  30.551 +def is_resource_in_use_by_dom(dominfo, resource):
  30.552 +    """ Determine whether a resources is in use by a given domain
  30.553 +        @return True or False
  30.554 +    """
  30.555 +    if not dominfo.domid:
  30.556 +        return False
  30.557 +    if dominfo._stateGet() not in [ DOM_STATE_RUNNING ]:
  30.558 +        return False
  30.559 +    devs = dominfo.info['devices']
  30.560 +    uuids = devs.keys()
  30.561 +    for uuid in uuids:
  30.562 +        dev = devs[uuid]
  30.563 +        if len(dev) >= 2 and dev[1].has_key('uname'):
  30.564 +            # dev[0] is type, i.e. 'vbd'
  30.565 +            if devices_equal(dev[1]['uname'], resource):
  30.566 +                log.info("RESOURCE IN USE: Domain %d uses %s." %
  30.567 +                         (dominfo.domid, resource))
  30.568 +                return True
  30.569 +    return False
  30.570 +
  30.571 +
  30.572 +def get_domain_resources(dominfo):
  30.573 +    """ Collect all resources of a domain in a map where each entry of
  30.574 +        the map is a list.
  30.575 +        Entries are strored in the following formats:
  30.576 +          tap:qcow:/path/xyz.qcow
  30.577 +    """
  30.578 +    resources = { 'vbd' : [], 'tap' : []}
  30.579 +    devs = dominfo.info['devices']
  30.580 +    uuids = devs.keys()
  30.581 +    for uuid in uuids:
  30.582 +        dev = devs[uuid]
  30.583 +        typ = dev[0]
  30.584 +        if typ in [ 'vbd', 'tap' ]:
  30.585 +            resources[typ].append(dev[1]['uname'])
  30.586 +
  30.587 +    return resources
  30.588 +
  30.589 +
  30.590 +def resources_compatible_with_vmlabel(xspol, dominfo, vmlabel):
  30.591 +    """
  30.592 +       Check whether the resources' labels are compatible with the
  30.593 +       given VM label. This is a function to be used when for example
  30.594 +       a running domain is to get the new label 'vmlabel'
  30.595 +    """
  30.596 +    if not xspol:
  30.597 +        return False
  30.598 +
  30.599 +    try:
  30.600 +        __resfile_lock.acquire()
  30.601 +        try:
  30.602 +            access_control = dictio.dict_read("resources",
  30.603 +                                              res_label_filename)
  30.604 +        except:
  30.605 +            return False
  30.606 +        return __resources_compatible_with_vmlabel(xspol, dominfo, vmlabel,
  30.607 +                                                   access_control)
  30.608 +    finally:
  30.609 +        __resfile_lock.release()
  30.610 +    return False
  30.611 +
  30.612 +
  30.613 +def __resources_compatible_with_vmlabel(xspol, dominfo, vmlabel,
  30.614 +                                        access_control):
  30.615 +    """
  30.616 +        Check whether the resources' labels are compatible with the
  30.617 +        given VM label. The access_control parameter provides a
  30.618 +        dictionary of the resource name to resource label mappings
  30.619 +        under which the evaluation should be done.
  30.620 +    """
  30.621 +    resources = get_domain_resources(dominfo)
  30.622 +    reslabels = []  # all resource labels
  30.623 +    polname = xspol.get_name()
  30.624 +    for key in resources.keys():
  30.625 +        for res in resources[key]:
  30.626 +            try:
  30.627 +                tmp = access_control[res]
  30.628 +                if len(tmp) != 3:
  30.629 +                    return False
  30.630 +
  30.631 +                if polname != tmp[1]:
  30.632 +                    return False
  30.633 +                label = tmp[2]
  30.634 +                if not label in reslabels:
  30.635 +                    reslabels.append(label)
  30.636 +            except:
  30.637 +                return False
  30.638 +    # Check that all resource labes have a common STE type with the
  30.639 +    # vmlabel
  30.640 +    rc = xspol.policy_check_vmlabel_against_reslabels(vmlabel, reslabels)
  30.641 +    return rc;
  30.642 +
  30.643 +def set_resource_label(resource, policytype, policyref, reslabel, \
  30.644 +                       oreslabel = None):
  30.645 +    """Assign a label to a resource
  30.646 +       If the old label (oreslabel) is given, then the resource must have
  30.647 +       that old label.
  30.648 +       A resource label may be changed if
  30.649 +       - the resource is not in use
  30.650 +    @param resource  : The name of a resource, i.e., "phy:/dev/hda"
  30.651 +    @param policyref : The name of the policy
  30.652 +    @param reslabel     : the resource label within the policy
  30.653 +    @param oreslabel    : optional current resource label
  30.654 +
  30.655 +    @rtype: int
  30.656 +    @return Success (0) or failure value (< 0)
  30.657 +    """
  30.658 +    try:
  30.659 +        resource = unify_resname(resource, mustexist=False)
  30.660 +    except Exception:
  30.661 +        return -xsconstants.XSERR_BAD_RESOURCE_FORMAT
  30.662 +
  30.663 +    domains = is_resource_in_use(resource)
  30.664 +    if len(domains) > 0:
  30.665 +        return -xsconstants.XSERR_RESOURCE_IN_USE
  30.666 +
  30.667 +    try:
  30.668 +        __resfile_lock.acquire()
  30.669 +        access_control = {}
  30.670 +        try:
  30.671 +             access_control = dictio.dict_read("resources", res_label_filename)
  30.672 +        except:
  30.673 +            pass
  30.674 +        if oreslabel:
  30.675 +            if not access_control.has_key(resource):
  30.676 +                return -xsconstants.XSERR_BAD_LABEL
  30.677 +            tmp = access_control[resource]
  30.678 +            if len(tmp) != 3:
  30.679 +                return -xsconstants.XSERR_BAD_LABEL
  30.680 +            if tmp[2] != oreslabel:
  30.681 +                return -xsconstants.XSERR_BAD_LABEL
  30.682 +        if reslabel != "":
  30.683 +            new_entry = { resource : tuple([policytype, policyref, reslabel])}
  30.684 +            access_control.update(new_entry)
  30.685 +        else:
  30.686 +            if access_control.has_key(resource):
  30.687 +                del access_control[resource]
  30.688 +        dictio.dict_write(access_control, "resources", res_label_filename)
  30.689 +    finally:
  30.690 +        __resfile_lock.release()
  30.691 +    return xsconstants.XSERR_SUCCESS
  30.692 +
  30.693 +def rm_resource_label(resource, oldlabel_xapi):
  30.694 +    """Remove a resource label from a physical resource
  30.695 +    @param resource: The name of a resource, i.e., "phy:/dev/hda"
  30.696 +
  30.697 +    @rtype: int
  30.698 +    @return Success (0) or failure value (< 0)
  30.699 +    """
  30.700 +    tmp = oldlabel_xapi.split(":")
  30.701 +    if len(tmp) != 3:
  30.702 +        return -xsconstants.XSERR_BAD_LABEL_FORMAT
  30.703 +    otyp, opolicyref, olabel = tmp
  30.704 +    # Only ACM is supported
  30.705 +    if otyp != xsconstants.ACM_POLICY_ID and \
  30.706 +       otyp != xsconstants.INVALID_POLICY_PREFIX + xsconstants.ACM_POLICY_ID:
  30.707 +        return -xsconstants.XSERR_WRONG_POLICY_TYPE
  30.708 +    return set_resource_label(resource, "", "", "", olabel)
  30.709 +
  30.710 +def get_resource_label_xapi(resource):
  30.711 +    """Get the assigned resource label of a physical resource
  30.712 +      in the format used by then Xen-API, i.e., "ACM:xm-test:blue"
  30.713 +
  30.714 +      @rtype: string
  30.715 +      @return the string representing policy type, policy name and label of
  30.716 +              the resource
  30.717 +    """
  30.718 +    res = get_resource_label(resource)
  30.719 +    return format_resource_label(res)
  30.720 +
  30.721 +def format_resource_label(res):
  30.722 +    if res:
  30.723 +        if len(res) == 2:
  30.724 +            return xsconstants.ACM_POLICY_ID + ":" + res[0] + ":" + res[1]
  30.725 +        if len(res) == 3:
  30.726 +            return ":".join(res)
  30.727 +    return ""
  30.728 +
  30.729 +def get_resource_label(resource):
  30.730 +    """Get the assigned resource label of a given resource
  30.731 +    @param resource: The name of a resource, i.e., "phy:/dev/hda"
  30.732 +
  30.733 +    @rtype: list
  30.734 +    @return tuple of (policy name, resource label), i.e., (xm-test, blue)
  30.735 +    """
  30.736 +    try:
  30.737 +        resource = unify_resname(resource, mustexist=False)
  30.738 +    except Exception:
  30.739 +        return []
  30.740 +
  30.741 +    reslabel_map = get_labeled_resources()
  30.742 +
  30.743 +    if reslabel_map.has_key(resource):
  30.744 +        return list(reslabel_map[resource])
  30.745 +    else:
  30.746 +        #Try to resolve each label entry
  30.747 +        for key, value in reslabel_map.items():
  30.748 +            try:
  30.749 +                if resource == unify_resname(key):
  30.750 +                    return list(value)
  30.751 +            except:
  30.752 +                pass
  30.753 +
  30.754 +    return []
  30.755 +
  30.756 +
  30.757 +def get_labeled_resources_xapi():
  30.758 +    """ Get a map of all labeled resource with the labels formatted in the
  30.759 +        xen-api resource label format.
  30.760 +    """
  30.761 +    reslabel_map = get_labeled_resources()
  30.762 +    for key, labeldata in reslabel_map.items():
  30.763 +        reslabel_map[key] = format_resource_label(labeldata)
  30.764 +    return reslabel_map
  30.765 +
  30.766 +
  30.767 +def get_labeled_resources():
  30.768 +    """Get a map of all labeled resources
  30.769 +    @rtype: list
  30.770 +    @return list of labeled resources
  30.771 +    """
  30.772 +    try:
  30.773 +        __resfile_lock.acquire()
  30.774 +        try:
  30.775 +            access_control = dictio.dict_read("resources", res_label_filename)
  30.776 +        except:
  30.777 +            return {}
  30.778 +    finally:
  30.779 +        __resfile_lock.release()
  30.780 +    return access_control
  30.781 +
  30.782 +
  30.783 +def relabel_domains(relabel_list):
  30.784 +    """
  30.785 +      Relabel the given domains to have a new ssidref.
  30.786 +      @param relabel_list: a list containing tuples of domid, ssidref
  30.787 +                           example: [ [0, 0x00020002] ]
  30.788 +    """
  30.789 +    rel_rules = ""
  30.790 +    for r in relabel_list:
  30.791 +        log.info("Relabeling domain with domid %d to new ssidref 0x%08x",
  30.792 +                r[0], r[1])
  30.793 +        rel_rules += struct.pack("ii", r[0], r[1])
  30.794 +    try:
  30.795 +        rc, errors = acm.relabel_domains(rel_rules)
  30.796 +    except Exception, e:
  30.797 +        log.info("Error after relabel_domains: %s" % str(e))
  30.798 +        rc = -xsconstants.XSERR_GENERAL_FAILURE
  30.799 +        errors = ""
  30.800 +    if (len(errors) > 0):
  30.801 +        rc = -xsconstants.XSERR_HV_OP_FAILED
  30.802 +    return rc, errors
  30.803 +
  30.804 +
  30.805 +def change_acm_policy(bin_pol, del_array, chg_array,
  30.806 +                      vmlabel_map, reslabel_map, cur_acmpol, new_acmpol):
  30.807 +    """
  30.808 +       Change the ACM policy of the system by relabeling
  30.809 +       domains and resources first and doing some access checks.
  30.810 +       Then update the policy in the hypervisor. If this is all successful,
  30.811 +       relabel the domains permanently and commit the relabed resources.
  30.812 +
  30.813 +       Need to do / check the following:
  30.814 +        - relabel all resources where there is a 'from' field in
  30.815 +          the policy. [ NOT DOING THIS: and mark those as unlabeled where the label
  30.816 +          does not appear in the new policy anymore (deletion) ]
  30.817 +        - relabel all VMs where there is a 'from' field in the
  30.818 +          policy and mark those as unlabeled where the label
  30.819 +          does not appear in the new policy anymore; no running
  30.820 +          or paused VM may be unlabeled through this
  30.821 +        - check that under the new labeling conditions the VMs
  30.822 +          still have access to their resources as before. Unlabeled
  30.823 +          resources are inaccessible. If this check fails, the
  30.824 +          update failed.
  30.825 +        - Attempt changes in the hypervisor; if this step fails,
  30.826 +          roll back the relabeling of resources and VMs
  30.827 +        - Make the relabeling of resources and VMs permanent
  30.828 +    """
  30.829 +    rc = xsconstants.XSERR_SUCCESS
  30.830 +
  30.831 +    domain_label_map = {}
  30.832 +    new_policyname = new_acmpol.get_name()
  30.833 +    new_policytype = new_acmpol.get_type_name()
  30.834 +    cur_policyname = cur_acmpol.get_name()
  30.835 +    cur_policytype = cur_acmpol.get_type_name()
  30.836 +    polnew_reslabels = new_acmpol.policy_get_resourcelabel_names()
  30.837 +    errors=""
  30.838 +
  30.839 +    try:
  30.840 +        __resfile_lock.acquire()
  30.841 +        mapfile_lock()
  30.842 +
  30.843 +        # Get all domains' dominfo.
  30.844 +        from xen.xend import XendDomain
  30.845 +        dominfos = XendDomain.instance().list('all')
  30.846 +
  30.847 +        log.info("----------------------------------------------")
  30.848 +        # relabel resources
  30.849 +
  30.850 +        access_control = {}
  30.851 +        try:
  30.852 +            access_control = dictio.dict_read("resources", res_label_filename)
  30.853 +        finally:
  30.854 +            pass
  30.855 +        for key, labeldata in access_control.items():
  30.856 +            if len(labeldata) == 2:
  30.857 +                policy, label = labeldata
  30.858 +                policytype = xsconstants.ACM_POLICY_ID
  30.859 +            elif len(labeldata) == 3:
  30.860 +                policytype, policy, label = labeldata
  30.861 +            else:
  30.862 +                return -xsconstants.XSERR_BAD_LABEL_FORMAT, ""
  30.863 +
  30.864 +            if policytype != cur_policytype or \
  30.865 +               policy     != cur_policyname:
  30.866 +                continue
  30.867 +
  30.868 +            # label been renamed or deleted?
  30.869 +            if reslabel_map.has_key(label) and cur_policyname == policy:
  30.870 +                label = reslabel_map[label]
  30.871 +            elif label not in polnew_reslabels:
  30.872 +                policytype = xsconstants.INVALID_POLICY_PREFIX + policytype
  30.873 +            # Update entry
  30.874 +            access_control[key] = \
  30.875 +                   tuple([ policytype, new_policyname, label ])
  30.876 +
  30.877 +        # All resources have new labels in the access_control map
  30.878 +        # There may still be labels in there that are invalid now.
  30.879 +
  30.880 +        # Do this in memory without writing to disk:
  30.881 +        #  - Relabel all domains independent of whether they are running
  30.882 +        #    or not
  30.883 +        #  - later write back to config files
  30.884 +        polnew_vmlabels = new_acmpol.policy_get_virtualmachinelabel_names()
  30.885 +
  30.886 +        for dominfo in dominfos:
  30.887 +            sec_lab = dominfo.get_security_label()
  30.888 +            if not sec_lab:
  30.889 +                continue
  30.890 +            policytype, policy, vmlabel = sec_lab.split(":")
  30.891 +            name  = dominfo.getName()
  30.892 +
  30.893 +            if policytype != cur_policytype or \
  30.894 +               policy     != cur_policyname:
  30.895 +                continue
  30.896 +
  30.897 +            new_vmlabel = vmlabel
  30.898 +            if vmlabel_map.has_key(vmlabel):
  30.899 +                new_vmlabel = vmlabel_map[vmlabel]
  30.900 +            if new_vmlabel not in polnew_vmlabels:
  30.901 +                policytype = xsconstants.INVALID_POLICY_PREFIX + policytype
  30.902 +            new_seclab = "%s:%s:%s" % \
  30.903 +                    (policytype, new_policyname, new_vmlabel)
  30.904 +
  30.905 +            domain_label_map[dominfo] = [ sec_lab, new_seclab ]
  30.906 +
  30.907 +            if dominfo._stateGet() in (DOM_STATE_PAUSED, DOM_STATE_RUNNING):
  30.908 +                compatible = __resources_compatible_with_vmlabel(new_acmpol,
  30.909 +                                                      dominfo,
  30.910 +                                                      new_vmlabel,
  30.911 +                                                      access_control)
  30.912 +                log.info("Domain %s with new label '%s' can access its "
  30.913 +                         "resources? : %s" %
  30.914 +                         (name, new_vmlabel, str(compatible)))
  30.915 +                log.info("VM labels in new domain: %s" %
  30.916 +                         new_acmpol.policy_get_virtualmachinelabel_names())
  30.917 +                if not compatible:
  30.918 +                    return (-xsconstants.XSERR_RESOURCE_ACCESS, "")
  30.919 +
  30.920 +        rc, errors = hv_chg_policy(bin_pol, del_array, chg_array)
  30.921 +        if rc == 0:
  30.922 +            # Write the relabeled resources back into the file
  30.923 +            dictio.dict_write(access_control, "resources", res_label_filename)
  30.924 +            # Properly update all VMs to their new labels
  30.925 +            for dominfo, labels in domain_label_map.items():
  30.926 +                sec_lab, new_seclab = labels
  30.927 +                if sec_lab != new_seclab:
  30.928 +                    log.info("Updating domain %s to new label '%s'." % \
  30.929 +                             (new_seclab, sec_lab))
  30.930 +                    # This better be working!
  30.931 +                    dominfo.set_security_label(new_seclab,
  30.932 +                                               sec_lab,
  30.933 +                                               new_acmpol)
  30.934 +    finally:
  30.935 +        log.info("----------------------------------------------")
  30.936 +        mapfile_unlock()
  30.937 +        __resfile_lock.release()
  30.938 +
  30.939 +    return rc, errors
    31.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    31.2 +++ b/tools/python/xen/util/xsconstants.py	Tue Jul 10 08:39:26 2007 -0600
    31.3 @@ -0,0 +1,104 @@
    31.4 +#============================================================================
    31.5 +# This library is free software; you can redistribute it and/or
    31.6 +# modify it under the terms of version 2.1 of the GNU Lesser General Public
    31.7 +# License as published by the Free Software Foundation.
    31.8 +#
    31.9 +# This library is distributed in the hope that it will be useful,
   31.10 +# but WITHOUT ANY WARRANTY; without even the implied warranty of
   31.11 +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   31.12 +# Lesser General Public License for more details.
   31.13 +#
   31.14 +# You should have received a copy of the GNU Lesser General Public
   31.15 +# License along with this library; if not, write to the Free Software
   31.16 +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
   31.17 +#============================================================================
   31.18 +# Copyright (C) 2007 International Business Machines Corp.
   31.19 +# Author: Stefan Berger <stefanb@us.ibm.com>
   31.20 +#============================================================================
   31.21 +
   31.22 +XS_INST_NONE = 0
   31.23 +XS_INST_BOOT = (1 << 0)
   31.24 +XS_INST_LOAD = (1 << 1)
   31.25 +
   31.26 +XS_POLICY_NONE  = 0
   31.27 +XS_POLICY_ACM = (1 << 0)
   31.28 +
   31.29 +# Some internal variables used by the Xen-API
   31.30 +ACM_LABEL_VM  = (1 << 0)
   31.31 +ACM_LABEL_RES = (1 << 1)
   31.32 +
   31.33 +# Base for XS error codes for collision avoidance with other error codes
   31.34 +XSERR_BASE = 0x1000
   31.35 +
   31.36 +# XS error codes as used by the Xen-API
   31.37 +XSERR_SUCCESS                  =  0
   31.38 +XSERR_GENERAL_FAILURE          =  1 + XSERR_BASE
   31.39 +XSERR_BAD_XML                  =  2 + XSERR_BASE  # XML is wrong (not according to schema)
   31.40 +XSERR_XML_PROCESSING           =  3 + XSERR_BASE
   31.41 +XSERR_POLICY_INCONSISTENT      =  4 + XSERR_BASE  # i.e., bootstrap name not a VM label
   31.42 +XSERR_FILE_ERROR               =  5 + XSERR_BASE
   31.43 +XSERR_BAD_RESOURCE_FORMAT      =  6 + XSERR_BASE  # badly formatted resource
   31.44 +XSERR_BAD_LABEL_FORMAT         =  7 + XSERR_BASE
   31.45 +XSERR_RESOURCE_NOT_LABELED     =  8 + XSERR_BASE
   31.46 +XSERR_RESOURCE_ALREADY_LABELED =  9 + XSERR_BASE
   31.47 +XSERR_WRONG_POLICY_TYPE        = 10 + XSERR_BASE
   31.48 +XSERR_BOOTPOLICY_INSTALLED     = 11 + XSERR_BASE
   31.49 +XSERR_NO_DEFAULT_BOOT_TITLE    = 12 + XSERR_BASE
   31.50 +XSERR_POLICY_LOAD_FAILED       = 13 + XSERR_BASE
   31.51 +XSERR_POLICY_LOADED            = 14 + XSERR_BASE
   31.52 +XSERR_POLICY_TYPE_UNSUPPORTED  = 15 + XSERR_BASE
   31.53 +XSERR_BAD_CONFLICTSET          = 16 + XSERR_BASE
   31.54 +XSERR_RESOURCE_IN_USE          = 17 + XSERR_BASE
   31.55 +XSERR_BAD_POLICY_NAME          = 18 + XSERR_BASE
   31.56 +XSERR_VERSION_PREVENTS_UPDATE  = 19 + XSERR_BASE
   31.57 +XSERR_BAD_LABEL                = 20 + XSERR_BASE
   31.58 +XSERR_VM_WRONG_STATE           = 21 + XSERR_BASE
   31.59 +XSERR_POLICY_NOT_LOADED        = 22 + XSERR_BASE
   31.60 +XSERR_RESOURCE_ACCESS          = 23 + XSERR_BASE
   31.61 +XSERR_HV_OP_FAILED             = 24 + XSERR_BASE
   31.62 +XSERR_BOOTPOLICY_INSTALL_ERROR = 25 + XSERR_BASE
   31.63 +XSERR_LAST                     = 25 + XSERR_BASE ## KEEP LAST
   31.64 +
   31.65 +XSERR_MESSAGES = [
   31.66 +    '',
   31.67 +    'General Failure',
   31.68 +    'XML is malformed',
   31.69 +    'Error while processing XML',
   31.70 +    'Policy has inconsistencies',
   31.71 +    'A file access error occurred',
   31.72 +    'The resource format is not valid',
   31.73 +    'The label format is not valid',
   31.74 +    'The resource is not labeld',
   31.75 +    'The resource is already labeld',
   31.76 +    'The policy type is wrong',
   31.77 +    'The system boot policy is installed',
   31.78 +    'Could not find the default boot title',
   31.79 +    'Loading of the policy failed',
   31.80 +    'The policy is loaded',
   31.81 +    'The policy type is unsupported',
   31.82 +    'There is a bad conflict set',
   31.83 +    'The resource is in use',
   31.84 +    'The policy has an invalid name',
   31.85 +    'The version of the policy prevents an update',
   31.86 +    'The label is bad',
   31.87 +    'Operation not premittend - the VM is in the wrong state',
   31.88 +    'The policy is not loaded',
   31.89 +    'Error accessing resource',
   31.90 +    'Operation failed in hypervisor',
   31.91 +    'Boot policy installation error'
   31.92 +]
   31.93 +
   31.94 +def xserr2string(err):
   31.95 +    if err == XSERR_SUCCESS:
   31.96 +        return "Success"
   31.97 +    if err >= XSERR_GENERAL_FAILURE and \
   31.98 +       err <= XSERR_LAST:
   31.99 +        return XSERR_MESSAGES[err - XSERR_BASE]
  31.100 +    return "Unknown XSERR code '%s'." % (hex(err))
  31.101 +
  31.102 +# Policy identifiers used in labels
  31.103 +ACM_POLICY_ID = "ACM"
  31.104 +
  31.105 +INVALID_POLICY_PREFIX = "INV_"
  31.106 +
  31.107 +INVALID_SSIDREF = 0xFFFFFFFF
    32.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    32.2 +++ b/tools/python/xen/util/xspolicy.py	Tue Jul 10 08:39:26 2007 -0600
    32.3 @@ -0,0 +1,66 @@
    32.4 +#============================================================================
    32.5 +# This library is free software; you can redistribute it and/or
    32.6 +# modify it under the terms of version 2.1 of the GNU Lesser General Public
    32.7 +# License as published by the Free Software Foundation.
    32.8 +#
    32.9 +# This library is distributed in the hope that it will be useful,
   32.10 +# but WITHOUT ANY WARRANTY; without even the implied warranty of
   32.11 +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   32.12 +# Lesser General Public License for more details.
   32.13 +#
   32.14 +# You should have received a copy of the GNU Lesser General Public
   32.15 +# License along with this library; if not, write to the Free Software
   32.16 +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
   32.17 +#============================================================================
   32.18 +# Copyright (C) 2006,2007 International Business Machines Corp.
   32.19 +# Author: Stefan Berger <stefanb@us.ibm.com>
   32.20 +#============================================================================
   32.21 +
   32.22 +import threading
   32.23 +import xsconstants
   32.24 +
   32.25 +class XSPolicy:
   32.26 +    """
   32.27 +       The base policy class for all policies administered through
   32.28 +       XSPolicyAdmin.
   32.29 +    """
   32.30 +
   32.31 +    def __init__(self, name=None, ref=None):
   32.32 +        self.lock = threading.Lock()
   32.33 +        self.ref = ref
   32.34 +        self.name = name
   32.35 +        if ref:
   32.36 +            from xen.xend.XendXSPolicy import XendXSPolicy
   32.37 +            self.xendxspolicy = XendXSPolicy(self, {}, ref)
   32.38 +        else:
   32.39 +            self.xendxspolicy = None
   32.40 +
   32.41 +    def grab_lock(self):
   32.42 +        self.lock.acquire()
   32.43 +
   32.44 +    def unlock(self):
   32.45 +        self.lock.release()
   32.46 +
   32.47 +    def get_ref(self):
   32.48 +        return self.ref
   32.49 +
   32.50 +    def destroy(self):
   32.51 +        if self.xendxspolicy:
   32.52 +            self.xendxspolicy.destroy()
   32.53 +
   32.54 +    # All methods below should be overwritten by the inheriting class
   32.55 +
   32.56 +    def isloaded(self):
   32.57 +        return False
   32.58 +
   32.59 +    def loadintohv(self):
   32.60 +        return xsconstants.XSERR_POLICY_LOAD_FAILED
   32.61 +
   32.62 +    def get_type(self):
   32.63 +        return xsconstants.XS_POLICY_NONE
   32.64 +
   32.65 +    def get_type_name(self):
   32.66 +        return ""
   32.67 +
   32.68 +    def update(self, repr_new):
   32.69 +        return -xsconstants.XSERR_GENERAL_FAILURE, ""
    33.1 --- a/tools/python/xen/xend/XendAPI.py	Mon Jul 09 09:22:58 2007 -0600
    33.2 +++ b/tools/python/xen/xend/XendAPI.py	Tue Jul 10 08:39:26 2007 -0600
    33.3 @@ -40,11 +40,13 @@ from XendPIFMetrics import XendPIFMetric
    33.4  from XendVMMetrics import XendVMMetrics
    33.5  from XendPIF import XendPIF
    33.6  from XendPBD import XendPBD
    33.7 +from XendXSPolicy import XendXSPolicy, XendACMPolicy
    33.8  
    33.9  from XendAPIConstants import *
   33.10  from xen.util.xmlrpclib2 import stringify
   33.11  
   33.12  from xen.util.blkif import blkdev_name_to_number
   33.13 +from xen.util import xsconstants
   33.14  
   33.15  
   33.16  AUTH_NONE = 'none'
   33.17 @@ -467,6 +469,8 @@ classes = {
   33.18      'console'      : valid_console,
   33.19      'SR'           : valid_sr,
   33.20      'task'         : valid_task,
   33.21 +    'XSPolicy'     : valid_object("XSPolicy"),
   33.22 +    'ACMPolicy'    : valid_object("ACMPolicy"),
   33.23      'debug'        : valid_debug,
   33.24      'network'      : valid_object("network"),
   33.25      'PIF'          : valid_object("PIF"),
   33.26 @@ -481,6 +485,8 @@ autoplug_classes = {
   33.27      'VM_metrics'  : XendVMMetrics,
   33.28      'PBD'         : XendPBD,
   33.29      'PIF_metrics' : XendPIFMetrics,
   33.30 +    'XSPolicy'    : XendXSPolicy,
   33.31 +    'ACMPolicy'   : XendACMPolicy,
   33.32  }
   33.33  
   33.34  class XendAPI(object):
   33.35 @@ -1170,7 +1176,8 @@ class XendAPI(object):
   33.36                    'HVM_boot_params',
   33.37                    'platform',
   33.38                    'PCI_bus',
   33.39 -                  'other_config']
   33.40 +                  'other_config',
   33.41 +                  'security_label']
   33.42  
   33.43      VM_methods = [('clone', 'VM'),
   33.44                    ('start', None),
   33.45 @@ -1230,7 +1237,8 @@ class XendAPI(object):
   33.46          'HVM_boot_params',
   33.47          'platform',
   33.48          'PCI_bus',
   33.49 -        'other_config']
   33.50 +        'other_config',
   33.51 +        'security_label']
   33.52          
   33.53      def VM_get(self, name, session, vm_ref):
   33.54          return xen_api_success(
   33.55 @@ -1601,7 +1609,22 @@ class XendAPI(object):
   33.56          if dom:
   33.57              return xen_api_success([dom.get_uuid()])
   33.58          return xen_api_success([])
   33.59 -    
   33.60 +
   33.61 +    def VM_get_security_label(self, session, vm_ref):
   33.62 +        dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
   33.63 +        label = dom.get_security_label()
   33.64 +        return xen_api_success(label)
   33.65 +
   33.66 +    def VM_set_security_label(self, session, vm_ref, sec_label, old_label):
   33.67 +        dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
   33.68 +        (rc, errors, oldlabel, new_ssidref) = \
   33.69 +                                 dom.set_security_label(sec_label, old_label)
   33.70 +        if rc != xsconstants.XSERR_SUCCESS:
   33.71 +            return xen_api_error(['SECURITY_ERROR', rc])
   33.72 +        if rc == 0:
   33.73 +            rc = new_ssidref
   33.74 +        return xen_api_success(rc)
   33.75 +
   33.76      def VM_create(self, session, vm_struct):
   33.77          xendom = XendDomain.instance()
   33.78          domuuid = XendTask.log_progress(0, 100,
   33.79 @@ -1655,6 +1678,7 @@ class XendAPI(object):
   33.80              'domid': domid is None and -1 or domid,
   33.81              'is_control_domain': xeninfo.info['is_control_domain'],
   33.82              'metrics': xeninfo.get_metrics(),
   33.83 +            'security_label': xeninfo.get_security_label(),
   33.84              'crash_dumps': []
   33.85          }
   33.86          return xen_api_success(record)
   33.87 @@ -1952,7 +1976,8 @@ class XendAPI(object):
   33.88                     'runtime_properties']
   33.89      VIF_attr_rw = ['device',
   33.90                     'MAC',
   33.91 -                   'MTU']
   33.92 +                   'MTU',
   33.93 +                   'security_label']
   33.94  
   33.95      VIF_attr_inst = VIF_attr_rw
   33.96  
   33.97 @@ -2054,7 +2079,10 @@ class XendAPI(object):
   33.98          except Exception, exn:
   33.99              log.exception(exn)
  33.100              return xen_api_success({})
  33.101 -    
  33.102 +
  33.103 +    def VIF_get_security_label(self, session, vif_ref):
  33.104 +        return self._VIF_get(vif_ref, 'security_label')
  33.105 +
  33.106      # Xen API: Class VIF_metrics
  33.107      # ----------------------------------------------------------------
  33.108  
  33.109 @@ -2098,7 +2126,8 @@ class XendAPI(object):
  33.110                     'virtual_size',
  33.111                     'sharable',
  33.112                     'read_only',
  33.113 -                   'other_config']
  33.114 +                   'other_config',
  33.115 +                   'security_label']
  33.116      VDI_attr_inst = VDI_attr_ro + VDI_attr_rw
  33.117  
  33.118      VDI_methods = [('destroy', None)]
  33.119 @@ -2206,13 +2235,24 @@ class XendAPI(object):
  33.120          xennode = XendNode.instance()
  33.121          return xen_api_success(xennode.get_vdi_by_name_label(name))
  33.122  
  33.123 +    def VDI_set_security_label(self, session, vdi_ref, sec_lab, old_lab):
  33.124 +        vdi = XendNode.instance().get_vdi_by_uuid(vdi_ref)
  33.125 +        rc = vdi.set_security_label(sec_lab, old_lab)
  33.126 +        if rc < 0:
  33.127 +            return xen_api_error(['SECURITY_ERROR', rc])
  33.128 +        return xen_api_success(rc)
  33.129 +
  33.130 +    def VDI_get_security_label(self, session, vdi_ref):
  33.131 +        vdi = XendNode.instance().get_vdi_by_uuid(vdi_ref)
  33.132 +        return xen_api_success(vdi.get_security_label())
  33.133  
  33.134      # Xen API: Class VTPM
  33.135      # ----------------------------------------------------------------
  33.136  
  33.137      VTPM_attr_rw = [ ]
  33.138      VTPM_attr_ro = ['VM',
  33.139 -                    'backend']
  33.140 +                    'backend',
  33.141 +                    'runtime_properties' ]
  33.142  
  33.143      VTPM_attr_inst = VTPM_attr_rw
  33.144  
  33.145 @@ -2290,6 +2330,18 @@ class XendAPI(object):
  33.146          vtpms = reduce(lambda x, y: x + y, vtpms)
  33.147          return xen_api_success(vtpms)
  33.148  
  33.149 +    def VTPM_get_runtime_properties(self, _, vtpm_ref):
  33.150 +        xendom = XendDomain.instance()
  33.151 +        dominfo = xendom.get_vm_with_dev_uuid('vtpm', vtpm_ref)
  33.152 +        device = dominfo.get_dev_config_by_uuid('vtpm', vtpm_ref)
  33.153 +
  33.154 +        try:
  33.155 +            device_sxps = dominfo.getDeviceSxprs('vtpm')
  33.156 +            device_dict = dict(device_sxps[0][1])
  33.157 +            return xen_api_success(device_dict)
  33.158 +        except:
  33.159 +            return xen_api_success({})
  33.160 +
  33.161      # Xen API: Class console
  33.162      # ----------------------------------------------------------------
  33.163  
    34.1 --- a/tools/python/xen/xend/XendConfig.py	Mon Jul 09 09:22:58 2007 -0600
    34.2 +++ b/tools/python/xen/xend/XendConfig.py	Tue Jul 10 08:39:26 2007 -0600
    34.3 @@ -22,6 +22,7 @@ import types
    34.4  
    34.5  from xen.xend import sxp
    34.6  from xen.xend import uuid
    34.7 +from xen.xend import XendOptions
    34.8  from xen.xend import XendAPIStore
    34.9  from xen.xend.XendError import VmError
   34.10  from xen.xend.XendDevices import XendDevices
   34.11 @@ -29,6 +30,8 @@ from xen.xend.PrettyPrint import prettyp
   34.12  from xen.xend.XendConstants import DOM_STATE_HALTED
   34.13  from xen.xend.server.netif import randomMAC
   34.14  from xen.util.blkif import blkdev_name_to_number
   34.15 +from xen.xend.XendXSPolicyAdmin import XSPolicyAdminInstance
   34.16 +from xen.util import xsconstants
   34.17  
   34.18  log = logging.getLogger("xend.XendConfig")
   34.19  log.setLevel(logging.WARN)
   34.20 @@ -159,6 +162,7 @@ XENAPI_CFG_TYPES = {
   34.21      'platform': dict,
   34.22      'tools_version': dict,
   34.23      'other_config': dict,
   34.24 +    'security_label': str,
   34.25  }
   34.26  
   34.27  # List of legacy configuration keys that have no equivalent in the
   34.28 @@ -167,7 +171,6 @@ XENAPI_CFG_TYPES = {
   34.29  LEGACY_UNSUPPORTED_BY_XENAPI_CFG = [
   34.30      # roundtripped (dynamic, unmodified)
   34.31      'shadow_memory',
   34.32 -    'security',
   34.33      'vcpu_avail',
   34.34      'cpu_weight',
   34.35      'cpu_cap',
   34.36 @@ -318,7 +321,6 @@ class XendConfig(dict):
   34.37              'memory_static_max': 0,
   34.38              'memory_dynamic_max': 0,
   34.39              'devices': {},
   34.40 -            'security': None,
   34.41              'on_xend_start': 'ignore',
   34.42              'on_xend_stop': 'ignore',
   34.43              'cpus': [],
   34.44 @@ -392,6 +394,9 @@ class XendConfig(dict):
   34.45  
   34.46      def _platform_sanity_check(self):
   34.47          if self.is_hvm():
   34.48 +            if 'keymap' not in self['platform'] and XendOptions.instance().get_keymap():
   34.49 +                self['platform']['keymap'] = XendOptions.instance().get_keymap()
   34.50 +
   34.51              if 'device_model' not in self['platform']:
   34.52                  self['platform']['device_model'] = DEFAULT_DM
   34.53  
   34.54 @@ -421,9 +426,10 @@ class XendConfig(dict):
   34.55              self._memory_sanity_check()
   34.56  
   34.57          self['cpu_time'] = dominfo['cpu_time']/1e9
   34.58 -        # TODO: i don't know what the security stuff expects here
   34.59          if dominfo.get('ssidref'):
   34.60 -            self['security'] = [['ssidref', dominfo['ssidref']]]
   34.61 +            ssidref = int(dominfo.get('ssidref'))
   34.62 +            self['security_label'] = XSPolicyAdminInstance().ssidref_to_vmlabel(ssidref)
   34.63 +
   34.64          self['shutdown_reason'] = dominfo['shutdown_reason']
   34.65  
   34.66          # parse state into Xen API states
   34.67 @@ -630,8 +636,26 @@ class XendConfig(dict):
   34.68                  except ValueError, e:
   34.69                      raise XendConfigError('cpus = %s: %s' % (cfg['cpus'], e))
   34.70  
   34.71 -        if 'security' in cfg and isinstance(cfg['security'], str):
   34.72 -            cfg['security'] = sxp.from_string(cfg['security'])
   34.73 +        if 'security' in cfg and not cfg.get('security_label'):
   34.74 +            secinfo = cfg['security']
   34.75 +            if isinstance(secinfo, list):
   34.76 +                # The xm command sends a list formatted like this:
   34.77 +                # [['access_control', ['policy', 'xm-test'],['label', 'red']],
   34.78 +                #                     ['ssidref', 196611]]
   34.79 +                policy = ""
   34.80 +                label = ""
   34.81 +                policytype = xsconstants.ACM_POLICY_ID
   34.82 +                for idx in range(0, len(secinfo)):
   34.83 +                    if secinfo[idx][0] == "access_control":
   34.84 +                        for aidx in range(1, len(secinfo[idx])):
   34.85 +                            if secinfo[idx][aidx][0] == "policy":
   34.86 +                                policy = secinfo[idx][aidx][1]
   34.87 +                            if secinfo[idx][aidx][0] == "label":
   34.88 +                                label  = secinfo[idx][aidx][1]
   34.89 +                if label != "" and policy != "":
   34.90 +                    cfg['security_label'] = "%s:%s:%s" % \
   34.91 +                            (policytype, policy, label)
   34.92 +                    del cfg['security']
   34.93  
   34.94          old_state = sxp.child_value(sxp_cfg, 'state')
   34.95          if old_state:
   34.96 @@ -774,7 +798,6 @@ class XendConfig(dict):
   34.97                      self[sxp_arg] = val
   34.98  
   34.99          _set_cfg_if_exists('shadow_memory')
  34.100 -        _set_cfg_if_exists('security')
  34.101          _set_cfg_if_exists('features')
  34.102          _set_cfg_if_exists('on_xend_stop')
  34.103          _set_cfg_if_exists('on_xend_start')
  34.104 @@ -887,6 +910,9 @@ class XendConfig(dict):
  34.105              if self.has_key(legacy) and self[legacy] not in (None, []):
  34.106                  sxpr.append([legacy, self[legacy]])
  34.107  
  34.108 +        if self.has_key('security_label'):
  34.109 +            sxpr.append(['security_label', self['security_label']])
  34.110 +
  34.111          sxpr.append(['image', self.image_sxpr()])
  34.112          sxpr.append(['status', domain._stateGet()])
  34.113  
    35.1 --- a/tools/python/xen/xend/XendDomain.py	Mon Jul 09 09:22:58 2007 -0600
    35.2 +++ b/tools/python/xen/xend/XendDomain.py	Tue Jul 10 08:39:26 2007 -0600
    35.3 @@ -49,7 +49,7 @@ from xen.xend.XendAPIConstants import *
    35.4  
    35.5  from xen.xend.xenstore.xstransact import xstransact
    35.6  from xen.xend.xenstore.xswatch import xswatch
    35.7 -from xen.util import mkdir, security
    35.8 +from xen.util import mkdir
    35.9  from xen.xend import uuid
   35.10  
   35.11  xc = xen.lowlevel.xc.xc()
   35.12 @@ -486,7 +486,6 @@ class XendDomain:
   35.13          """
   35.14          self.domains_lock.acquire()
   35.15          try:
   35.16 -            security.refresh_ssidref(config)
   35.17              dominfo = XendDomainInfo.restore(config)
   35.18              return dominfo
   35.19          finally:
   35.20 @@ -1113,6 +1112,10 @@ class XendDomain:
   35.21                  raise XendInvalidDomain(str(domid))
   35.22              if dominfo.getDomid() == DOM0_ID:
   35.23                  raise XendError("Cannot unpause privileged domain %s" % domid)
   35.24 +            if dominfo._stateGet() not in (DOM_STATE_PAUSED, DOM_STATE_RUNNING):
   35.25 +                raise VMBadState("Domain '%s' is not started" % domid,
   35.26 +                                 POWER_STATE_NAMES[DOM_STATE_PAUSED],
   35.27 +                                 POWER_STATE_NAMES[dominfo._stateGet()])
   35.28              log.info("Domain %s (%d) unpaused.", dominfo.getName(),
   35.29                       int(dominfo.getDomid()))
   35.30              dominfo.unpause()
   35.31 @@ -1138,6 +1141,10 @@ class XendDomain:
   35.32                  raise XendInvalidDomain(str(domid))
   35.33              if dominfo.getDomid() == DOM0_ID:
   35.34                  raise XendError("Cannot pause privileged domain %s" % domid)
   35.35 +            if dominfo._stateGet() not in (DOM_STATE_RUNNING, DOM_STATE_PAUSED):
   35.36 +                raise VMBadState("Domain '%s' is not started" % domid,
   35.37 +                                 POWER_STATE_NAMES[DOM_STATE_RUNNING],
   35.38 +                                 POWER_STATE_NAMES[dominfo._stateGet()])
   35.39              log.info("Domain %s (%d) paused.", dominfo.getName(),
   35.40                       int(dominfo.getDomid()))
   35.41              dominfo.pause()
   35.42 @@ -1253,7 +1260,11 @@ class XendDomain:
   35.43                  raise XendInvalidDomain(str(domid))
   35.44  
   35.45              if dominfo.getDomid() == DOM0_ID:
   35.46 -                raise XendError("Cannot save privileged domain %i" % domid)
   35.47 +                raise XendError("Cannot save privileged domain %s" % str(domid))
   35.48 +            if dominfo._stateGet() != DOM_STATE_RUNNING:
   35.49 +                raise VMBadState("Domain is not running",
   35.50 +                                 POWER_STATE_NAMES[DOM_STATE_RUNNING],
   35.51 +                                 POWER_STATE_NAMES[dominfo._stateGet()])
   35.52  
   35.53              oflags = os.O_WRONLY | os.O_CREAT | os.O_TRUNC
   35.54              if hasattr(os, "O_LARGEFILE"):
   35.55 @@ -1399,10 +1410,15 @@ class XendDomain:
   35.56          dominfo = self.domain_lookup_nr(domid)
   35.57          if not dominfo:
   35.58              raise XendInvalidDomain(str(domid))
   35.59 -        try:
   35.60 -            return xc.sched_credit_domain_get(dominfo.getDomid())
   35.61 -        except Exception, ex:
   35.62 -            raise XendError(str(ex))
   35.63 +        
   35.64 +        if dominfo._stateGet() in (DOM_STATE_RUNNING, DOM_STATE_PAUSED):
   35.65 +            try:
   35.66 +                return xc.sched_credit_domain_get(dominfo.getDomid())
   35.67 +            except Exception, ex:
   35.68 +                raise XendError(str(ex))
   35.69 +        else:
   35.70 +            return {'weight' : dominfo.getWeight(),
   35.71 +                    'cap'    : dominfo.getCap()} 
   35.72      
   35.73      def domain_sched_credit_set(self, domid, weight = None, cap = None):
   35.74          """Set credit scheduler parameters for a domain.
   35.75 @@ -1436,12 +1452,15 @@ class XendDomain:
   35.76              assert type(weight) == int
   35.77              assert type(cap) == int
   35.78  
   35.79 -            rc = xc.sched_credit_domain_set(dominfo.getDomid(), weight, cap)
   35.80 +            rc = 0
   35.81 +            if dominfo._stateGet() in (DOM_STATE_RUNNING, DOM_STATE_PAUSED):
   35.82 +                rc = xc.sched_credit_domain_set(dominfo.getDomid(), weight, cap)
   35.83              if rc == 0:
   35.84                  if set_weight:
   35.85                      dominfo.setWeight(weight)
   35.86                  if set_cap:
   35.87                      dominfo.setCap(cap)
   35.88 +                self.managed_config_save(dominfo)
   35.89              return rc
   35.90          except Exception, ex:
   35.91              log.exception(ex)
    36.1 --- a/tools/python/xen/xend/XendDomainInfo.py	Mon Jul 09 09:22:58 2007 -0600
    36.2 +++ b/tools/python/xen/xend/XendDomainInfo.py	Tue Jul 10 08:39:26 2007 -0600
    36.3 @@ -489,6 +489,9 @@ class XendDomainInfo:
    36.4  
    36.5      def send_sysrq(self, key):
    36.6          """ Send a Sysrq equivalent key via xenstored."""
    36.7 +        if self._stateGet() not in (DOM_STATE_RUNNING, DOM_STATE_PAUSED):
    36.8 +            raise XendError("Domain '%s' is not started" % self.info['name_label'])
    36.9 +
   36.10          asserts.isCharConvertible(key)
   36.11          self.storeDom("control/sysrq", '%c' % key)
   36.12  
   36.13 @@ -503,9 +506,18 @@ class XendDomainInfo:
   36.14          dev_uuid = self.info.device_add(dev_type, cfg_sxp = dev_config)
   36.15          dev_config_dict = self.info['devices'][dev_uuid][1]
   36.16          log.debug("XendDomainInfo.device_create: %s" % scrub_password(dev_config_dict))
   36.17 -        dev_config_dict['devid'] = devid = \
   36.18 -             self._createDevice(dev_type, dev_config_dict)
   36.19 -        self._waitForDevice(dev_type, devid)
   36.20 +
   36.21 +        if self.domid is not None:
   36.22 +            try:
   36.23 +                dev_config_dict['devid'] = devid = \
   36.24 +                    self._createDevice(dev_type, dev_config_dict)
   36.25 +                self._waitForDevice(dev_type, devid)
   36.26 +            except VmError, ex:
   36.27 +                raise ex
   36.28 +        else:
   36.29 +            devid = None
   36.30 +
   36.31 +        xen.xend.XendDomain.instance().managed_config_save(self)
   36.32          return self.getDeviceController(dev_type).sxpr(devid)
   36.33  
   36.34      def device_configure(self, dev_sxp, devid = None):
   36.35 @@ -819,6 +831,9 @@ class XendDomainInfo:
   36.36              else:
   36.37                  f('image/%s' % n, v)
   36.38  
   36.39 +        if self.info.has_key('security_label'):
   36.40 +            f('security_label', self.info['security_label'])
   36.41 +
   36.42          to_store.update(self._vcpuDomDetails())
   36.43  
   36.44          log.debug("Storing domain details: %s", scrub_password(to_store))
   36.45 @@ -989,9 +1004,6 @@ class XendDomainInfo:
   36.46          log.info("Set VCPU count on domain %s to %d", self.info['name_label'],
   36.47                   vcpus)
   36.48  
   36.49 -    def getLabel(self):
   36.50 -        return security.get_security_info(self.info, 'label')
   36.51 -
   36.52      def getMemoryTarget(self):
   36.53          """Get this domain's target memory size, in KB."""
   36.54          return self.info['memory_dynamic_max'] / 1024
   36.55 @@ -1435,11 +1447,20 @@ class XendDomainInfo:
   36.56          # allocation of 1MB. We free up 2MB here to be on the safe side.
   36.57          balloon.free(2*1024) # 2MB should be plenty
   36.58  
   36.59 -        self.domid = xc.domain_create(
   36.60 -            domid = 0,
   36.61 -            ssidref = security.get_security_info(self.info, 'ssidref'),
   36.62 -            handle = uuid.fromString(self.info['uuid']),
   36.63 -            hvm = int(hvm))
   36.64 +        ssidref = security.calc_dom_ssidref_from_info(self.info)
   36.65 +        if ssidref == 0 and security.on():
   36.66 +            raise VmError('VM is not properly labeled.')
   36.67 +
   36.68 +        try:
   36.69 +            self.domid = xc.domain_create(
   36.70 +                domid = 0,
   36.71 +                ssidref = ssidref,
   36.72 +                handle = uuid.fromString(self.info['uuid']),
   36.73 +                hvm = int(hvm))
   36.74 +        except Exception, e:
   36.75 +            # may get here if due to ACM the operation is not permitted
   36.76 +            if security.on():
   36.77 +                raise VmError('Domain in conflict set with running domain?')
   36.78  
   36.79          if self.domid < 0:
   36.80              raise VmError('Creating domain failed: name=%s' %
   36.81 @@ -1955,24 +1976,6 @@ class XendDomainInfo:
   36.82          if image_sxpr:
   36.83              to_store['image'] = sxp.to_string(image_sxpr)
   36.84  
   36.85 -        if self._infoIsSet('security'):
   36.86 -            secinfo = self.info['security']
   36.87 -            to_store['security'] = sxp.to_string(secinfo)
   36.88 -            for idx in range(0, len(secinfo)):
   36.89 -                if secinfo[idx][0] == 'access_control':
   36.90 -                    to_store['security/access_control'] = sxp.to_string(
   36.91 -                        [secinfo[idx][1], secinfo[idx][2]])
   36.92 -                    for aidx in range(1, len(secinfo[idx])):
   36.93 -                        if secinfo[idx][aidx][0] == 'label':
   36.94 -                            to_store['security/access_control/label'] = \
   36.95 -                                secinfo[idx][aidx][1]
   36.96 -                        if secinfo[idx][aidx][0] == 'policy':
   36.97 -                            to_store['security/access_control/policy'] = \
   36.98 -                                secinfo[idx][aidx][1]
   36.99 -                if secinfo[idx][0] == 'ssidref':
  36.100 -                    to_store['security/ssidref'] = str(secinfo[idx][1])
  36.101 -
  36.102 -
  36.103          if not self._readVm('xend/restart_count'):
  36.104              to_store['xend/restart_count'] = str(0)
  36.105  
  36.106 @@ -2090,15 +2093,6 @@ class XendDomainInfo:
  36.107              info["maxmem_kb"] = XendNode.instance() \
  36.108                                  .physinfo_dict()['total_memory'] * 1024
  36.109  
  36.110 -        #manually update ssidref / security fields
  36.111 -        if security.on() and info.has_key('ssidref'):
  36.112 -            if (info['ssidref'] != 0) and self.info.has_key('security'):
  36.113 -                security_field = self.info['security']
  36.114 -                if not security_field:
  36.115 -                    #create new security element
  36.116 -                    self.info.update({'security':
  36.117 -                                      [['ssidref', str(info['ssidref'])]]})
  36.118 -                    
  36.119          #ssidref field not used any longer
  36.120          if 'ssidref' in info:
  36.121              info.pop('ssidref')
  36.122 @@ -2182,7 +2176,133 @@ class XendDomainInfo:
  36.123          return self.info.get('tools_version', {})
  36.124      def get_metrics(self):
  36.125          return self.metrics.get_uuid();
  36.126 -    
  36.127 +
  36.128 +
  36.129 +    def get_security_label(self):
  36.130 +        domid = self.getDomid()
  36.131 +
  36.132 +        from xen.xend.XendXSPolicyAdmin import XSPolicyAdminInstance
  36.133 +        xspol = XSPolicyAdminInstance().get_loaded_policy()
  36.134 +
  36.135 +        if domid == 0:
  36.136 +            if xspol:
  36.137 +                label = xspol.policy_get_domain_label_formatted(domid)
  36.138 +            else:
  36.139 +                label = ""
  36.140 +        else:
  36.141 +            label = self.info.get('security_label', '')
  36.142 +        return label
  36.143 +
  36.144 +    def set_security_label(self, seclab, old_seclab, xspol=None):
  36.145 +        """
  36.146 +           Set the security label of a domain from its old to
  36.147 +           a new value.
  36.148 +           @param seclab  New security label formatted in the form
  36.149 +                          <policy type>:<policy name>:<vm label>
  36.150 +           @param old_seclab  The current security label that the
  36.151 +                          VM must have.
  36.152 +           @param xspol   An optional policy under which this
  36.153 +                          update should be done. If not given,
  36.154 +                          then the current active policy is used.
  36.155 +           @return Returns return code, a string with errors from
  36.156 +                   the hypervisor's operation, old label of the
  36.157 +                   domain
  36.158 +        """
  36.159 +        rc = 0
  36.160 +        errors = ""
  36.161 +        old_label = ""
  36.162 +        new_ssidref = 0
  36.163 +        domid = self.getDomid()
  36.164 +        res_labels = None
  36.165 +
  36.166 +        from xen.xend.XendXSPolicyAdmin import XSPolicyAdminInstance
  36.167 +        from xen.util import xsconstants
  36.168 +
  36.169 +        state = self._stateGet()
  36.170 +        # Relabel only HALTED or RUNNING or PAUSED domains
  36.171 +        if domid != 0 and \
  36.172 +           state not in \
  36.173 +              [ DOM_STATE_HALTED, DOM_STATE_RUNNING, DOM_STATE_PAUSED, \
  36.174 +                DOM_STATE_SUSPENDED ]:
  36.175 +            log.warn("Relabeling domain not possible in state '%s'" %
  36.176 +                     DOM_STATES[state])
  36.177 +            return (-xsconstants.XSERR_VM_WRONG_STATE, "", "", 0)
  36.178 +
  36.179 +        # Remove security label. Works only for halted domains
  36.180 +        if not seclab or seclab == "":
  36.181 +            if state not in [ DOM_STATE_HALTED ]:
  36.182 +                return (-xsconstants.XSERR_VM_WRONG_STATE, "", "", 0)
  36.183 +
  36.184 +            if self.info.has_key('security_label'):
  36.185 +                old_label = self.info['security_label']
  36.186 +                # Check label against expected one.
  36.187 +                if old_label != old_seclab:
  36.188 +                    return (-xsconstants.XSERR_BAD_LABEL, "", "", 0)
  36.189 +                del self.info['security_label']
  36.190 +                xen.xend.XendDomain.instance().managed_config_save(self)
  36.191 +                return (xsconstants.XSERR_SUCCESS, "", "", 0)
  36.192 +
  36.193 +        tmp = seclab.split(":")
  36.194 +        if len(tmp) != 3:
  36.195 +            return (-xsconstants.XSERR_BAD_LABEL_FORMAT, "", "", 0)
  36.196 +        typ, policy, label = tmp
  36.197 +
  36.198 +        poladmin = XSPolicyAdminInstance()
  36.199 +        if not xspol:
  36.200 +            xspol = poladmin.get_policy_by_name(policy)
  36.201 +
  36.202 +        if state in [ DOM_STATE_RUNNING, DOM_STATE_PAUSED ]:
  36.203 +            #if domain is running or paused try to relabel in hypervisor
  36.204 +            if not xspol:
  36.205 +                return (-xsconstants.XSERR_POLICY_NOT_LOADED, "", "", 0)
  36.206 +
  36.207 +            if typ != xspol.get_type_name() or \
  36.208 +               policy != xspol.get_name():
  36.209 +                return (-xsconstants.XSERR_BAD_LABEL, "", "", 0)
  36.210 +
  36.211 +            if typ == xsconstants.ACM_POLICY_ID:
  36.212 +                new_ssidref = xspol.vmlabel_to_ssidref(label)
  36.213 +                if new_ssidref == xsconstants.INVALID_SSIDREF:
  36.214 +                    return (-xsconstants.XSERR_BAD_LABEL, "", "", 0)
  36.215 +
  36.216 +                # Check that all used resources are accessible under the
  36.217 +                # new label
  36.218 +                if not security.resources_compatible_with_vmlabel(xspol,
  36.219 +                          self, label):
  36.220 +                    return (-xsconstants.XSERR_BAD_LABEL, "", "", 0)
  36.221 +
  36.222 +                #Check label against expected one.
  36.223 +                old_label = self.get_security_label()
  36.224 +                if old_label != old_seclab:
  36.225 +                    return (-xsconstants.XSERR_BAD_LABEL, "", "", 0)
  36.226 +
  36.227 +                # relabel domain in the hypervisor
  36.228 +                rc, errors = security.relabel_domains([[domid, new_ssidref]])
  36.229 +                log.info("rc from relabeling in HV: %d" % rc)
  36.230 +            else:
  36.231 +                return (-xsconstants.XSERR_POLICY_TYPE_UNSUPPORTED, "", "", 0)
  36.232 +
  36.233 +        if rc == 0:
  36.234 +            # HALTED, RUNNING or PAUSED
  36.235 +            if domid == 0:
  36.236 +                if xspol:
  36.237 +                    ssidref = poladmin.set_domain0_bootlabel(xspol, label)
  36.238 +                else:
  36.239 +                    return (-xsconstants.XSERR_POLICY_NOT_LOADED, "", "", 0)
  36.240 +            else:
  36.241 +                if self.info.has_key('security_label'):
  36.242 +                    old_label = self.info['security_label']
  36.243 +                    # Check label against expected one, unless wildcard
  36.244 +                    if old_label != old_seclab:
  36.245 +                        return (-xsconstants.XSERR_BAD_LABEL, "", "", 0)
  36.246 +
  36.247 +                self.info['security_label'] = seclab
  36.248 +                try:
  36.249 +                    xen.xend.XendDomain.instance().managed_config_save(self)
  36.250 +                except:
  36.251 +                    pass
  36.252 +        return (rc, errors, old_label, new_ssidref)
  36.253 +
  36.254      def get_on_shutdown(self):
  36.255          after_shutdown = self.info.get('actions_after_shutdown')
  36.256          if not after_shutdown or after_shutdown not in XEN_API_ON_NORMAL_EXIT:
    37.1 --- a/tools/python/xen/xend/XendError.py	Mon Jul 09 09:22:58 2007 -0600
    37.2 +++ b/tools/python/xen/xend/XendError.py	Tue Jul 10 08:39:26 2007 -0600
    37.3 @@ -174,6 +174,23 @@ class NetworkError(XendAPIError):
    37.4  
    37.5      def __str__(self):
    37.6          return 'NETWORK_ERROR: %s %s' % (self.error, self.network)
    37.7 +
    37.8 +from xen.util.xsconstants import xserr2string
    37.9 +
   37.10 +class SecurityError(XendAPIError):
   37.11 +    def __init__(self, error, message=None):
   37.12 +        XendAPIError.__init__(self)
   37.13 +        self.error = error
   37.14 +        if not message:
   37.15 +            self.message = xserr2string(-error)
   37.16 +        else:
   37.17 +            self.message = message
   37.18 +
   37.19 +    def get_api_error(self):
   37.20 +        return ['SECURITY_ERROR', self.error, self.message]
   37.21 +
   37.22 +    def __str__(self):
   37.23 +        return 'SECURITY_ERROR: %s:%s' % (self.error, self.message)
   37.24      
   37.25  XEND_ERROR_AUTHENTICATION_FAILED = ('ELUSER', 'Authentication Failed')
   37.26  XEND_ERROR_SESSION_INVALID       = ('EPERMDENIED', 'Session Invalid')
   37.27 @@ -188,4 +205,5 @@ XEND_ERROR_VIF_INVALID           = ('EVI
   37.28  XEND_ERROR_VTPM_INVALID          = ('EVTPMINVALID', 'VTPM Invalid')
   37.29  XEND_ERROR_VDI_INVALID           = ('EVDIINVALID', 'VDI Invalid')
   37.30  XEND_ERROR_SR_INVALID           = ('ESRINVALID', 'SR Invalid')
   37.31 +XEND_ERROR_XSPOLICY_INVALID      = ('EXSPOLICYINVALID', 'XS Invalid')
   37.32  XEND_ERROR_TODO                  = ('ETODO', 'Lazy Programmer Error')
    38.1 --- a/tools/python/xen/xend/XendNode.py	Mon Jul 09 09:22:58 2007 -0600
    38.2 +++ b/tools/python/xen/xend/XendNode.py	Tue Jul 10 08:39:26 2007 -0600
    38.3 @@ -533,18 +533,70 @@ class XendNode:
    38.4                  ['version', ver],
    38.5                  ['machine', mch]]
    38.6  
    38.7 +    def list_to_rangepairs(self,cmap):
    38.8 +            cmap.sort()
    38.9 +            pairs = []
   38.10 +            x = y = 0
   38.11 +            for i in range(0,len(cmap)):
   38.12 +                try:
   38.13 +                    if ((cmap[y+1] - cmap[i]) > 1):
   38.14 +                        pairs.append((cmap[x],cmap[y]))
   38.15 +                        x = y = i+1
   38.16 +                    else:
   38.17 +                        y = y + 1
   38.18 +                # if we go off the end, then just add x to y
   38.19 +                except IndexError:
   38.20 +                    pairs.append((cmap[x],cmap[y]))
   38.21 +
   38.22 +            return pairs
   38.23 +
   38.24 +    def format_pairs(self,pairs):
   38.25 +            if not pairs:
   38.26 +                return "no cpus"
   38.27 +            out = ""
   38.28 +            for f,s in pairs:
   38.29 +                if (f==s):
   38.30 +                    out += '%d'%f
   38.31 +                else:
   38.32 +                    out += '%d-%d'%(f,s)
   38.33 +                out += ','
   38.34 +            # trim trailing ','
   38.35 +            return out[:-1]
   38.36 +
   38.37 +    def list_to_strrange(self,list):
   38.38 +        return self.format_pairs(self.list_to_rangepairs(list))
   38.39 +
   38.40 +    def format_node_to_cpu(self, pinfo):
   38.41 +        str=''
   38.42 +        whitespace=''
   38.43 +        try:
   38.44 +            node_to_cpu=pinfo['node_to_cpu']
   38.45 +            for i in range(0, pinfo['nr_nodes']):
   38.46 +                str+='%snode%d:%s\n' % (whitespace,
   38.47 +                                        i, 
   38.48 +                                      self.list_to_strrange(node_to_cpu[i]))
   38.49 +                whitespace='%25s' % ''        
   38.50 +        except:
   38.51 +            str='none\n'
   38.52 +        return str[:-1];
   38.53 +
   38.54 +    def count_cpus(self, pinfo):
   38.55 +        count=0
   38.56 +        node_to_cpu=pinfo['node_to_cpu']
   38.57 +        for i in range(0, pinfo['nr_nodes']):
   38.58 +            count+=len(node_to_cpu[i])
   38.59 +        return count;
   38.60 +
   38.61      def physinfo(self):
   38.62          info = self.xc.physinfo()
   38.63  
   38.64 -        info['nr_cpus'] = (info['nr_nodes'] *
   38.65 -                           info['sockets_per_node'] *
   38.66 -                           info['cores_per_socket'] *
   38.67 -                           info['threads_per_core'])
   38.68 +        info['nr_cpus'] = self.count_cpus(info)
   38.69          info['cpu_mhz'] = info['cpu_khz'] / 1000
   38.70          
   38.71          # physinfo is in KiB, need it in MiB
   38.72          info['total_memory'] = info['total_memory'] / 1024
   38.73          info['free_memory']  = info['free_memory'] / 1024
   38.74 +        info['node_to_cpu']  = self.format_node_to_cpu(info)
   38.75  
   38.76          ITEM_ORDER = ['nr_cpus',
   38.77                        'nr_nodes',
   38.78 @@ -555,6 +607,7 @@ class XendNode:
   38.79                        'hw_caps',
   38.80                        'total_memory',
   38.81                        'free_memory',
   38.82 +                      'node_to_cpu'
   38.83                        ]
   38.84  
   38.85          return [[k, info[k]] for k in ITEM_ORDER]
    39.1 --- a/tools/python/xen/xend/XendOptions.py	Mon Jul 09 09:22:58 2007 -0600
    39.2 +++ b/tools/python/xen/xend/XendOptions.py	Tue Jul 10 08:39:26 2007 -0600
    39.3 @@ -278,6 +278,9 @@ class XendOptions:
    39.4          return self.get_config_string('vncpasswd',
    39.5                                       self.vncpasswd_default)
    39.6  
    39.7 +    def get_keymap(self):
    39.8 +        return self.get_config_value('keymap', None)
    39.9 +
   39.10  class XendOptionsFile(XendOptions):
   39.11  
   39.12      """Default path to the config file."""
    40.1 --- a/tools/python/xen/xend/XendVDI.py	Mon Jul 09 09:22:58 2007 -0600
    40.2 +++ b/tools/python/xen/xend/XendVDI.py	Tue Jul 10 08:39:26 2007 -0600
    40.3 @@ -23,6 +23,7 @@ import os
    40.4  
    40.5  from xen.util.xmlrpclib2 import stringify
    40.6  from xmlrpclib import dumps, loads
    40.7 +from xen.util import security, xsconstants
    40.8  
    40.9  KB = 1024
   40.10  MB = 1024 * 1024
   40.11 @@ -160,6 +161,17 @@ class XendVDI(AutoSaveObject):
   40.12  
   40.13      def get_location(self):
   40.14          raise NotImplementedError()
   40.15 +
   40.16 +    def set_security_label(self, sec_lab, old_lab):
   40.17 +        image = self.get_location()
   40.18 +        rc = security.set_resource_label_xapi(image, sec_lab, old_lab)
   40.19 +        if rc != xsconstants.XSERR_SUCCESS:
   40.20 +            raise SecurityError(rc)
   40.21 +        return rc
   40.22 +
   40.23 +    def get_security_label(self):
   40.24 +        image = self.get_location()
   40.25 +        return security.get_resource_label_xapi(image)
   40.26                  
   40.27  
   40.28  class XendQCoWVDI(XendVDI):
    41.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    41.2 +++ b/tools/python/xen/xend/XendXSPolicy.py	Tue Jul 10 08:39:26 2007 -0600
    41.3 @@ -0,0 +1,222 @@
    41.4 +#============================================================================
    41.5 +# This library is free software; you can redistribute it and/or
    41.6 +# modify it under the terms of version 2.1 of the GNU Lesser General Public
    41.7 +# License as published by the Free Software Foundation.
    41.8 +#
    41.9 +# This library is distributed in the hope that it will be useful,
   41.10 +# but WITHOUT ANY WARRANTY; without even the implied warranty of
   41.11 +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   41.12 +# Lesser General Public License for more details.
   41.13 +#
   41.14 +# You should have received a copy of the GNU Lesser General Public
   41.15 +# License along with this library; if not, write to the Free Software
   41.16 +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
   41.17 +#============================================================================
   41.18 +# Copyright (c) 2007 IBM Corporation
   41.19 +# Copyright (c) 2006 Xensource
   41.20 +#============================================================================
   41.21 +
   41.22 +import logging
   41.23 +from xen.xend.XendBase import XendBase
   41.24 +from xen.xend.XendError import *
   41.25 +from xen.xend.XendXSPolicyAdmin import XSPolicyAdminInstance
   41.26 +from xen.util import xsconstants, security
   41.27 +import base64
   41.28 +
   41.29 +log = logging.getLogger("xend.XendXSPolicy")
   41.30 +log.setLevel(logging.TRACE)
   41.31 +
   41.32 +
   41.33 +class XendXSPolicy(XendBase):
   41.34 +    """ Administration class for an XSPolicy. """
   41.35 +
   41.36 +    def getClass(self):
   41.37 +        return "XSPolicy"
   41.38 +
   41.39 +    def getMethods(self):
   41.40 +        methods = ['activate_xspolicy']
   41.41 +        return XendBase.getMethods() + methods
   41.42 +
   41.43 +    def getFuncs(self):
   41.44 +        funcs = [ 'get_xstype',
   41.45 +                  'set_xspolicy',
   41.46 +                  'get_xspolicy',
   41.47 +                  'rm_xsbootpolicy',
   41.48 +                  'get_resource_label',
   41.49 +                  'set_resource_label',
   41.50 +                  'get_labeled_resources' ]
   41.51 +        return XendBase.getFuncs() + funcs
   41.52 +
   41.53 +    getClass    = classmethod(getClass)
   41.54 +    getMethods  = classmethod(getMethods)
   41.55 +    getFuncs    = classmethod(getFuncs)
   41.56 +
   41.57 +    def __init__(self, xspol, record, uuid):
   41.58 +        """ xspol = actual XSPolicy  object """
   41.59 +        self.xspol = xspol
   41.60 +        XendBase.__init__(self, uuid, record)
   41.61 +
   41.62 +    def get_record(self):
   41.63 +        xspol_record = {
   41.64 +          'uuid'   : self.get_uuid(),
   41.65 +          'flags'  : XSPolicyAdminInstance().get_policy_flags(self.xspol),
   41.66 +          'repr'   : self.xspol.toxml(),
   41.67 +          'type'   : self.xspol.get_type(),
   41.68 +        }
   41.69 +        return xspol_record
   41.70 +
   41.71 +    def get_xstype(self):
   41.72 +        return XSPolicyAdminInstance().isXSEnabled()
   41.73 +
   41.74 +    def set_xspolicy(self, xstype, xml, flags, overwrite):
   41.75 +        ref = ""
   41.76 +        xstype = int(xstype)
   41.77 +        flags  = int(flags)
   41.78 +
   41.79 +        polstate = { 'xs_ref': "", 'repr'   : "", 'type'   : 0,
   41.80 +                     'flags' : 0 , 'version': 0 , 'errors' : "", 'xserr' : 0 }
   41.81 +        if xstype == xsconstants.XS_POLICY_ACM:
   41.82 +            poladmin = XSPolicyAdminInstance()
   41.83 +            try:
   41.84 +                (xspol, rc, errors) = poladmin.add_acmpolicy_to_system(
   41.85 +                                                                   xml, flags,
   41.86 +                                                                   overwrite)
   41.87 +                if rc != 0:
   41.88 +                    polstate.update( { 'xserr' : rc,
   41.89 +                                       'errors': base64.b64encode(errors) } )
   41.90 +                else:
   41.91 +                    ref = xspol.get_ref()
   41.92 +                    polstate = {
   41.93 +                      'xs_ref' : ref,
   41.94 +                      'flags'  : poladmin.get_policy_flags(xspol),
   41.95 +                      'type'   : xstype,
   41.96 +                      'repr'   : "",
   41.97 +                      'version': xspol.get_version(),
   41.98 +                      'errors' : base64.b64encode(errors),
   41.99 +                      'xserr'  : rc,
  41.100 +                    }
  41.101 +            except Exception, e:
  41.102 +                raise
  41.103 +        else:
  41.104 +            raise SecurityError(-xsconstants.XSERR_POLICY_TYPE_UNSUPPORTED)
  41.105 +        return polstate
  41.106 +
  41.107 +    def activate_xspolicy(self, flags):
  41.108 +        flags = int(flags)
  41.109 +        rc = -xsconstants.XSERR_GENERAL_FAILURE
  41.110 +        poladmin = XSPolicyAdminInstance()
  41.111 +        try:
  41.112 +            rc = poladmin.activate_xspolicy(self.xspol, flags)
  41.113 +        except Exception, e:
  41.114 +            log.info("Activate_policy: %s" % str(e))
  41.115 +        if rc != flags:
  41.116 +            raise SecurityError(rc)
  41.117 +        return flags
  41.118 +
  41.119 +    def get_xspolicy(self):
  41.120 +        polstate = { 'xs_ref' : "",
  41.121 +                     'repr'   : "",
  41.122 +                     'type'   : 0,
  41.123 +                     'flags'  : 0,
  41.124 +                     'version': "",
  41.125 +                     'errors' : "",
  41.126 +                     'xserr'  : 0 }
  41.127 +        poladmin = XSPolicyAdminInstance()
  41.128 +        refs = poladmin.get_policies_refs()
  41.129 +        # Will return one or no policy
  41.130 +        if refs and len(refs) > 0:
  41.131 +            ref = refs[0]
  41.132 +            xspol = XSPolicyAdminInstance().policy_from_ref(ref)
  41.133 +            try:
  41.134 +                xspol.grab_lock()
  41.135 +
  41.136 +                polstate = {
  41.137 +                  'xs_ref' : ref,
  41.138 +                  'repr'   : xspol.toxml(),
  41.139 +                  'type'   : xspol.get_type(),
  41.140 +                  'flags'  : poladmin.get_policy_flags(xspol),
  41.141 +                  'version': xspol.get_version(),
  41.142 +                  'errors' : "",
  41.143 +                  'xserr'  : 0,
  41.144 +                }
  41.145 +            finally:
  41.146 +                if xspol:
  41.147 +                    xspol.unlock()
  41.148 +        return polstate
  41.149 +
  41.150 +    def rm_xsbootpolicy(self):
  41.151 +        rc = XSPolicyAdminInstance().rm_bootpolicy()
  41.152 +        if rc != xsconstants.XSERR_SUCCESS:
  41.153 +            raise SecurityError(rc)
  41.154 +
  41.155 +    def get_labeled_resources(self):
  41.156 +        return security.get_labeled_resources_xapi()
  41.157 +
  41.158 +    def set_resource_label(self, resource, sec_lab, old_lab):
  41.159 +        rc = security.set_resource_label_xapi(resource, sec_lab, old_lab)
  41.160 +        if rc != xsconstants.XSERR_SUCCESS:
  41.161 +            raise SecurityError(rc)
  41.162 +
  41.163 +    def get_resource_label(self, resource):
  41.164 +        res = security.get_resource_label_xapi(resource)
  41.165 +        return res
  41.166 +
  41.167 +    get_xstype      = classmethod(get_xstype)
  41.168 +    get_xspolicy    = classmethod(get_xspolicy)
  41.169 +    set_xspolicy    = classmethod(set_xspolicy)
  41.170 +    rm_xsbootpolicy = classmethod(rm_xsbootpolicy)
  41.171 +    set_resource_label = classmethod(set_resource_label)
  41.172 +    get_resource_label = classmethod(get_resource_label)
  41.173 +    get_labeled_resources = classmethod(get_labeled_resources)
  41.174 +
  41.175 +
  41.176 +class XendACMPolicy(XendXSPolicy):
  41.177 +    """ Administration class of an ACMPolicy """
  41.178 +
  41.179 +    def getClass(self):
  41.180 +        return "ACMPolicy"
  41.181 +
  41.182 +    def getAttrRO(self):
  41.183 +        attrRO = [ 'xml',
  41.184 +                   'map',
  41.185 +                   'binary',
  41.186 +                   'header' ]
  41.187 +        return XendXSPolicy.getAttrRO() + attrRO
  41.188 +
  41.189 +    getClass    = classmethod(getClass)
  41.190 +    getAttrRO   = classmethod(getAttrRO)
  41.191 +
  41.192 +    def __init__(self, acmpol, record, uuid):
  41.193 +        """ acmpol = actual ACMPolicy object """
  41.194 +        self.acmpol = acmpol
  41.195 +        XendXSPolicy.__init__(self, acmpol, record, uuid)
  41.196 +
  41.197 +    def get_record(self):
  41.198 +        polstate = {
  41.199 +          'uuid'   : self.get_uuid(),
  41.200 +          'flags'  : XSPolicyAdminInstance().get_policy_flags(self.acmpol),
  41.201 +          'repr'   : self.acmpol.toxml(),
  41.202 +          'type'   : self.acmpol.get_type(),
  41.203 +        }
  41.204 +        return polstate
  41.205 +
  41.206 +    def get_header(self):
  41.207 +        header = {
  41.208 +          'policyname'   : "", 'policyurl'    : "", 'reference'    : "",
  41.209 +          'date'         : "", 'namespaceurl' : "", 'version'      : "",
  41.210 +        }
  41.211 +        try:
  41.212 +            header = self.acmpol.get_header_fields_map()
  41.213 +        except:
  41.214 +            pass
  41.215 +        return header
  41.216 +
  41.217 +    def get_xml(self):
  41.218 +        return self.acmpol.toxml()
  41.219 +
  41.220 +    def get_map(self):
  41.221 +        return self.acmpol.get_map()
  41.222 +
  41.223 +    def get_binary(self):
  41.224 +        polbin = self.acmpol.get_bin()
  41.225 +        return base64.b64encode(polbin)
    42.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    42.2 +++ b/tools/python/xen/xend/XendXSPolicyAdmin.py	Tue Jul 10 08:39:26 2007 -0600
    42.3 @@ -0,0 +1,314 @@
    42.4 +#============================================================================
    42.5 +# This library is free software; you can redistribute it and/or
    42.6 +# modify it under the terms of version 2.1 of the GNU Lesser General Public
    42.7 +# License as published by the Free Software Foundation.
    42.8 +#
    42.9 +# This library is distributed in the hope that it will be useful,
   42.10 +# but WITHOUT ANY WARRANTY; without even the implied warranty of
   42.11 +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   42.12 +# Lesser General Public License for more details.
   42.13 +#
   42.14 +# You should have received a copy of the GNU Lesser General Public
   42.15 +# License along with this library; if not, write to the Free Software
   42.16 +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
   42.17 +#============================================================================
   42.18 +# Copyright (C) 2006,2007 International Business Machines Corp.
   42.19 +# Author: Stefan Berger <stefanb@us.ibm.com>
   42.20 +#============================================================================
   42.21 +import os
   42.22 +import shutil
   42.23 +
   42.24 +from xml.dom import minidom, Node
   42.25 +
   42.26 +from xen.xend.XendLogging import log
   42.27 +from xen.xend import uuid
   42.28 +from xen.util import security, xsconstants, dictio, bootloader
   42.29 +from xen.util.xspolicy import XSPolicy
   42.30 +from xen.util.acmpolicy import ACMPolicy
   42.31 +from xen.xend.XendError import SecurityError
   42.32 +
   42.33 +XS_MANAGED_POLICIES_FILE = "/etc/xen/acm-security/policies/managed_policies"
   42.34 +
   42.35 +class XSPolicyAdmin:
   42.36 +    """ The class that handles the managed policies in the system.
   42.37 +        Handles adding and removing managed policies. All managed
   42.38 +        policies are handled using a reference (UUID) which is
   42.39 +        assigned to the policy by this class.
   42.40 +    """
   42.41 +
   42.42 +    def __init__(self, maxpolicies):
   42.43 +        """ Create a management class for managing the system's
   42.44 +            policies.
   42.45 +
   42.46 +            @param maxpolicies: The max. number of policies allowed
   42.47 +                                on the system (currently '1')
   42.48 +        """
   42.49 +        self.maxpolicies = maxpolicies
   42.50 +        try:
   42.51 +            self.policies = dictio.dict_read("managed_policies",
   42.52 +                                             XS_MANAGED_POLICIES_FILE)
   42.53 +        except Exception, e:
   42.54 +            self.policies = {}
   42.55 +
   42.56 +        self.xsobjs = {}
   42.57 +        for ref, data in self.policies.items():
   42.58 +            name = data[0]
   42.59 +            typ = data[1]
   42.60 +            try:
   42.61 +                if typ == xsconstants.ACM_POLICY_ID:
   42.62 +                    self.xsobjs[ref] = ACMPolicy(name=name, ref=ref)
   42.63 +                else:
   42.64 +                    del self.policies[ref]
   42.65 +            except Exception, e:
   42.66 +                log.error("XSPolicyAdmin: Could not find policy '%s': %s" %
   42.67 +                         (name, str(e)))
   42.68 +                del self.policies[ref]
   42.69 +        log.debug("XSPolicyAdmin: Known policies: %s" % self.policies)
   42.70 +
   42.71 +    def isXSEnabled(self):
   42.72 +        """ Check whether 'security' is enabled on this system.
   42.73 +            This currently only checks for ACM-enablement.
   42.74 +        """
   42.75 +        rc = 0
   42.76 +        if security.on():
   42.77 +            rc |= xsconstants.XS_POLICY_ACM
   42.78 +        return rc
   42.79 +
   42.80 +    def add_acmpolicy_to_system(self, xmltext, flags, overwrite):
   42.81 +        """ Add an ACM policy's xml representation to the system. The
   42.82 +            policy will automatically be compiled
   42.83 +         flags:
   42.84 +          XS_INST_BOOT : make policy the one to boot the system with
   42.85 +                         by default; if there's a policy already installed,
   42.86 +                         refuse to install this policy unless its one with
   42.87 +                         the same name
   42.88 +          XS_INST_LOAD : load the policy immediately; if this does not work
   42.89 +                         refuse to install this policy
   42.90 +         overwrite:
   42.91 +          If any policy is installed and this is False, refuse to install
   42.92 +          this policy
   42.93 +          If flags is True, then any existing policy will be removed from
   42.94 +          the system and the new one will be installed
   42.95 +        """
   42.96 +        errors = ""
   42.97 +        loadedpol = self.get_loaded_policy()
   42.98 +        if loadedpol:
   42.99 +            # This is meant as an update to a currently loaded policy
  42.100 +            if flags & xsconstants.XS_INST_LOAD == 0:
  42.101 +                raise SecurityError(-xsconstants.XSERR_POLICY_LOADED)
  42.102 +            rc, errors = loadedpol.update(xmltext)
  42.103 +            if rc == 0:
  42.104 +                self.rm_bootpolicy()
  42.105 +                irc = self.activate_xspolicy(loadedpol, flags)
  42.106 +            return (loadedpol, rc, errors)
  42.107 +
  42.108 +        try:
  42.109 +            dom = minidom.parseString(xmltext.encode("utf-8"))
  42.110 +        except:
  42.111 +            raise SecurityError(-xsconstants.XSERR_BAD_XML)
  42.112 +
  42.113 +        ref = uuid.createString()
  42.114 +
  42.115 +        acmpol = ACMPolicy(dom=dom, ref=ref)
  42.116 +
  42.117 +        #First some basic tests that do not modify anything:
  42.118 +
  42.119 +        if flags & xsconstants.XS_INST_BOOT and not overwrite:
  42.120 +            filename = acmpol.get_filename(".bin","",dotted=True)
  42.121 +            if bootloader.get_default_policy != None and \
  42.122 +               not bootloader.loads_default_policy(filename):
  42.123 +                raise SecurityError(-xsconstants.XSERR_BOOTPOLICY_INSTALLED)
  42.124 +
  42.125 +        if not overwrite and len(self.policies) >= self.maxpolicies:
  42.126 +            raise SecurityError(-xsconstants.XSERR_BOOTPOLICY_INSTALLED)
  42.127 +
  42.128 +        if overwrite:
  42.129 +            #This should only give one key since only one policy is
  42.130 +            #allowed.
  42.131 +            keys = self.policies.keys()
  42.132 +            for k in keys:
  42.133 +                self.rm_bootpolicy()
  42.134 +                rc = self.rm_policy_from_system(k, force=overwrite)
  42.135 +                if rc != xsconstants.XSERR_SUCCESS:
  42.136 +                    raise SecurityError(rc)
  42.137 +
  42.138 +        rc = acmpol.compile()
  42.139 +        if rc != 0:
  42.140 +            raise SecurityError(rc)
  42.141 +
  42.142 +        if flags & xsconstants.XS_INST_LOAD:
  42.143 +            rc = acmpol.loadintohv()
  42.144 +            if rc != 0:
  42.145 +                raise SecurityError(rc)
  42.146 +
  42.147 +        if flags & xsconstants.XS_INST_BOOT:
  42.148 +            rc = self.make_boot_policy(acmpol)
  42.149 +            if rc != 0:
  42.150 +                # If it cannot be installed due to unsupported
  42.151 +                # bootloader, let it be ok.
  42.152 +                pass
  42.153 +
  42.154 +        if dom:
  42.155 +            new_entry = { ref : tuple([acmpol.get_name(),
  42.156 +                                       xsconstants.ACM_POLICY_ID]) }
  42.157 +            self.policies.update(new_entry)
  42.158 +            self.xsobjs[ref]  = acmpol
  42.159 +            dictio.dict_write(self.policies,
  42.160 +                              "managed_policies",
  42.161 +                              XS_MANAGED_POLICIES_FILE)
  42.162 +        return (acmpol, xsconstants.XSERR_SUCCESS, errors)
  42.163 +
  42.164 +    def make_boot_policy(self, acmpol):
  42.165 +        spolfile = acmpol.get_filename(".bin")
  42.166 +        dpolfile = "/boot/" + acmpol.get_filename(".bin","",dotted=True)
  42.167 +        if not os.path.isfile(spolfile):
  42.168 +            log.error("binary policy file does not exist.")
  42.169 +            return -xsconstants.XSERR_FILE_ERROR
  42.170 +        try:
  42.171 +            shutil.copyfile(spolfile, dpolfile)
  42.172 +        except:
  42.173 +            return -xsconstants.XSERR_FILE_ERROR
  42.174 +
  42.175 +        try:
  42.176 +            filename = acmpol.get_filename(".bin","",dotted=True)
  42.177 +            if bootloader.set_default_boot_policy(filename) != True:
  42.178 +                return xsconstants.XSERR_BOOTPOLICY_INSTALL_ERROR
  42.179 +        except:
  42.180 +            return xsconstants.XSERR_FILE_ERROR
  42.181 +        return xsconstants.XSERR_SUCCESS
  42.182 +
  42.183 +    def activate_xspolicy(self, xspol, flags):
  42.184 +        rc = xsconstants.XSERR_SUCCESS
  42.185 +        if flags & xsconstants.XS_INST_LOAD:
  42.186 +            rc = xspol.loadintohv()
  42.187 +        if rc == xsconstants.XSERR_SUCCESS and \
  42.188 +           flags & xsconstants.XS_INST_BOOT:
  42.189 +            rc = self.make_boot_policy(xspol)
  42.190 +        if rc == xsconstants.XSERR_SUCCESS:
  42.191 +            rc = flags
  42.192 +        return rc
  42.193 +
  42.194 +    def rm_policy_from_system(self, ref, force=False):
  42.195 +        if self.policies.has_key(ref):
  42.196 +            acmpol = self.xsobjs[ref]
  42.197 +            rc = acmpol.destroy()
  42.198 +            if rc == xsconstants.XSERR_SUCCESS or force:
  42.199 +                del self.policies[ref]
  42.200 +                del self.xsobjs[ref]
  42.201 +                dictio.dict_write(self.policies,
  42.202 +                                  "managed_policies",
  42.203 +                                  XS_MANAGED_POLICIES_FILE)
  42.204 +                rc = xsconstants.XSERR_SUCCESS
  42.205 +            return rc
  42.206 +
  42.207 +    def rm_bootpolicy(self):
  42.208 +        """ Remove any (ACM) boot policy from the grub configuration file
  42.209 +        """
  42.210 +        rc = 0
  42.211 +        title = bootloader.get_default_title()
  42.212 +        if title != None:
  42.213 +            polnames = []
  42.214 +            for (k, v) in self.xsobjs.items():
  42.215 +                polnames.append(v.get_filename(".bin","",dotted=True))
  42.216 +            bootloader.rm_policy_from_boottitle(title, polnames)
  42.217 +        else:
  42.218 +            rc = -xsconstants.XSERR_NO_DEFAULT_BOOT_TITLE
  42.219 +        return rc
  42.220 +
  42.221 +    def get_policy_flags(self, acmpol):
  42.222 +        """ Get the currently active flags of a policy, i.e., whether the
  42.223 +            system is using this policy as its boot policy for the default
  42.224 +            boot title.
  42.225 +        """
  42.226 +        flags = 0
  42.227 +
  42.228 +        filename = acmpol.get_filename(".bin","", dotted=True)
  42.229 +        if bootloader.loads_default_policy(filename):
  42.230 +            flags |= xsconstants.XS_INST_BOOT
  42.231 +
  42.232 +        if acmpol.isloaded():
  42.233 +            flags |= xsconstants.XS_INST_LOAD
  42.234 +        return flags
  42.235 +
  42.236 +    def get_policies(self):
  42.237 +        """ Get all managed policies. """
  42.238 +        return self.xsobjs.values()
  42.239 +
  42.240 +    def get_policies_refs(self):
  42.241 +        """ Get all managed policies' references. """
  42.242 +        return self.xsobjs.keys()
  42.243 +
  42.244 +    def has_ref(self, ref):
  42.245 +        """ Check whether there is a policy with the given reference """
  42.246 +        return self.xsobjs.has_key(ref)
  42.247 +
  42.248 +    def policy_from_ref(self, ref):
  42.249 +        """ Get the policy's object given its reference """
  42.250 +        if ref in self.xsobjs.keys():
  42.251 +            return self.xsobjs[ref]
  42.252 +        return None
  42.253 +
  42.254 +    def ref_from_polname(self, polname):
  42.255 +        """ Get the reference of the policy given its name """
  42.256 +        ref = None
  42.257 +        for (k, v) in self.xsobjs.items():
  42.258 +            if v.get_name() == polname:
  42.259 +                ref = k
  42.260 +                break
  42.261 +        return ref
  42.262 +
  42.263 +    def lock_policy(self, ref):
  42.264 +        """ get exclusive access to a policy """
  42.265 +        self.xsobjs[ref].grab_lock()
  42.266 +
  42.267 +    def unlock_policy(self, ref):
  42.268 +        """ release exclusive access to a policy """
  42.269 +        self.xsobjs[ref].unlock()
  42.270 +
  42.271 +    def get_loaded_policy(self):
  42.272 +        for pol in self.xsobjs.values():
  42.273 +            if pol.isloaded():
  42.274 +                return pol
  42.275 +        return None
  42.276 +
  42.277 +    def get_policy_by_name(self, name):
  42.278 +        for pol in self.xsobjs.values():
  42.279 +            if pol.get_name() == name:
  42.280 +                return pol
  42.281 +        return None
  42.282 +
  42.283 +    def get_domain0_bootlabel(self):
  42.284 +        """ Get the domain0 bootlabel from the default boot title """
  42.285 +        title = ""
  42.286 +        def_title = bootloader.get_default_title()
  42.287 +        line = bootloader.get_kernel_val(def_title, "ssidref")
  42.288 +        if line:
  42.289 +            parms = line.split(":",1)
  42.290 +            if len(parms) > 1:
  42.291 +                title = parms[1]
  42.292 +        return title
  42.293 +
  42.294 +    def set_domain0_bootlabel(self, xspol, label):
  42.295 +        """ Set the domain-0 bootlabel under the given policy """
  42.296 +        return xspol.set_vm_bootlabel(label)
  42.297 +
  42.298 +    def rm_domain0_bootlabel(self):
  42.299 +        """ Remove the domain-0 bootlabel from the default boot title """
  42.300 +        def_title = bootloader.get_default_title()
  42.301 +        return bootloader.set_kernel_attval(def_title, "ssidref", None)
  42.302 +
  42.303 +    def ssidref_to_vmlabel(self, ssidref):
  42.304 +        """ Given an ssidref, return the vmlabel under the current policy """
  42.305 +        vmlabel = ""
  42.306 +        pol = self.get_loaded_policy()
  42.307 +        if pol:
  42.308 +            vmlabel = pol.policy_get_domain_label_by_ssidref_formatted(ssidref)
  42.309 +        return vmlabel
  42.310 +
  42.311 +poladmin = None
  42.312 +
  42.313 +def XSPolicyAdminInstance(maxpolicies=1):
  42.314 +    global poladmin
  42.315 +    if poladmin == None:
  42.316 +        poladmin = XSPolicyAdmin(maxpolicies)
  42.317 +    return poladmin
    43.1 --- a/tools/python/xen/xend/server/SrvDomain.py	Mon Jul 09 09:22:58 2007 -0600
    43.2 +++ b/tools/python/xen/xend/server/SrvDomain.py	Tue Jul 10 08:39:26 2007 -0600
    43.3 @@ -155,7 +155,8 @@ class SrvDomain(SrvDir):
    43.4      def op_domain_sched_credit_set(self, _, req):
    43.5          fn = FormFn(self.xd.domain_sched_credit_set,
    43.6                      [['dom', 'int'],
    43.7 -                     ['weight', 'int']])
    43.8 +                     ['weight', 'int'],
    43.9 +                     ['cap', 'int']])
   43.10          val = fn(req.args, {'dom': self.dom.domid})
   43.11          return val
   43.12  
    44.1 --- a/tools/python/xen/xend/server/blkif.py	Mon Jul 09 09:22:58 2007 -0600
    44.2 +++ b/tools/python/xen/xend/server/blkif.py	Tue Jul 10 08:39:26 2007 -0600
    44.3 @@ -73,10 +73,17 @@ class BlkifController(DevController):
    44.4              back['uuid'] = uuid
    44.5  
    44.6          if security.on():
    44.7 -            (label, ssidref, policy) = security.get_res_security_details(uname)
    44.8 -            back.update({'acm_label'  : label,
    44.9 -                         'acm_ssidref': str(ssidref),
   44.10 -                         'acm_policy' : policy})
   44.11 +            (label, ssidref, policy) = \
   44.12 +                                 security.get_res_security_details(uname)
   44.13 +            domain_label = self.vm.get_security_label()
   44.14 +            if domain_label:
   44.15 +                rc = security.res_security_check_xapi(label, ssidref, policy,
   44.16 +                                                      domain_label)
   44.17 +                if rc == 0:
   44.18 +                    raise VmError("VM's access to block device '%s' denied." %
   44.19 +                                  uname)
   44.20 +            else:
   44.21 +                raise VmError("VM must have a security label.")
   44.22  
   44.23          devid = blkif.blkdev_name_to_number(dev)
   44.24          if devid is None:
    45.1 --- a/tools/python/xen/xend/server/netif.py	Mon Jul 09 09:22:58 2007 -0600
    45.2 +++ b/tools/python/xen/xend/server/netif.py	Tue Jul 10 08:39:26 2007 -0600
    45.3 @@ -107,6 +107,7 @@ class NetifController(DevController):
    45.4          uuid    = config.get('uuid')
    45.5          ipaddr  = config.get('ip')
    45.6          model   = config.get('model')
    45.7 +        accel   = config.get('accel')
    45.8  
    45.9          if not typ:
   45.10              typ = xoptions.netback_type
   45.11 @@ -131,6 +132,8 @@ class NetifController(DevController):
   45.12              back['uuid'] = uuid
   45.13          if model:
   45.14              back['model'] = model
   45.15 +        if accel:
   45.16 +            back['accel'] = accel
   45.17  
   45.18          config_path = "device/%s/%d/" % (self.deviceClass, devid)
   45.19          for x in back:
   45.20 @@ -157,10 +160,10 @@ class NetifController(DevController):
   45.21          config_path = "device/%s/%d/" % (self.deviceClass, devid)
   45.22          devinfo = ()
   45.23          for x in ( 'script', 'ip', 'bridge', 'mac',
   45.24 -                   'type', 'vifname', 'rate', 'uuid', 'model' ):
   45.25 +                   'type', 'vifname', 'rate', 'uuid', 'model', 'accel'):
   45.26              y = self.vm._readVm(config_path + x)
   45.27              devinfo += (y,)
   45.28 -        (script, ip, bridge, mac, typ, vifname, rate, uuid, model) = devinfo
   45.29 +        (script, ip, bridge, mac, typ, vifname, rate, uuid, model, accel) = devinfo
   45.30  
   45.31          if script:
   45.32              result['script'] = script
   45.33 @@ -180,5 +183,7 @@ class NetifController(DevController):
   45.34              result['uuid'] = uuid
   45.35          if model:
   45.36              result['model'] = model
   45.37 +        if accel:
   45.38 +            result['accel'] = accel
   45.39              
   45.40          return result
    46.1 --- a/tools/python/xen/xend/server/vfbif.py	Mon Jul 09 09:22:58 2007 -0600
    46.2 +++ b/tools/python/xen/xend/server/vfbif.py	Tue Jul 10 08:39:26 2007 -0600
    46.3 @@ -76,6 +76,11 @@ class VfbifController(DevController):
    46.4              args += [ "--listen", vnclisten ]
    46.5              if config.has_key("keymap"):
    46.6                  args += ["-k", "%s" % config["keymap"]]
    46.7 +            else:
    46.8 +                xoptions = xen.xend.XendOptions.instance()
    46.9 +                if xoptions.get_keymap():
   46.10 +                    args += ["-k", "%s" % xoptions.get_keymap()]
   46.11 +
   46.12              spawn_detached(args[0], args + std_args, os.environ)
   46.13          elif t == "sdl":
   46.14              args = [xen.util.auxbin.pathTo("xen-sdlfb")]
    47.1 --- a/tools/python/xen/xm/create.py	Mon Jul 09 09:22:58 2007 -0600
    47.2 +++ b/tools/python/xen/xm/create.py	Tue Jul 10 08:39:26 2007 -0600
    47.3 @@ -318,7 +318,8 @@ gopts.var('vfb', val="type={vnc,sdl},vnc
    47.4            given DISPLAY and XAUTHORITY, which default to the current user's
    47.5            ones.""")
    47.6  
    47.7 -gopts.var('vif', val="type=TYPE,mac=MAC,bridge=BRIDGE,ip=IPADDR,script=SCRIPT,backend=DOM,vifname=NAME",
    47.8 +gopts.var('vif', val="type=TYPE,mac=MAC,bridge=BRIDGE,ip=IPADDR,script=SCRIPT," + \
    47.9 +          "backend=DOM,vifname=NAME,rate=RATE,model=MODEL,accel=ACCEL",
   47.10            fn=append_value, default=[],
   47.11            use="""Add a network interface with the given MAC address and bridge.
   47.12            The vif is configured by calling the given configuration script.
   47.13 @@ -330,6 +331,9 @@ gopts.var('vif', val="type=TYPE,mac=MAC,
   47.14            If backend is not specified the default backend driver domain is used.
   47.15            If vifname is not specified the backend virtual interface will have name vifD.N
   47.16            where D is the domain id and N is the interface id.
   47.17 +          If rate is not specified the default rate is used.
   47.18 +          If model is not specified the default model is used.
   47.19 +          If accel is not specified an accelerator plugin module is not used.
   47.20            This option may be repeated to add more than one vif.
   47.21            Specifying vifs will increase the number of interfaces as needed.""")
   47.22  
   47.23 @@ -710,7 +714,7 @@ def configure_vifs(config_devs, vals):
   47.24  
   47.25          def f(k):
   47.26              if k not in ['backend', 'bridge', 'ip', 'mac', 'script', 'type',
   47.27 -                         'vifname', 'rate', 'model']:
   47.28 +                         'vifname', 'rate', 'model', 'accel']:
   47.29                  err('Invalid vif option: ' + k)
   47.30  
   47.31              config_vif.append([k, d[k]])
    48.1 --- a/tools/python/xen/xm/main.py	Mon Jul 09 09:22:58 2007 -0600
    48.2 +++ b/tools/python/xen/xm/main.py	Tue Jul 10 08:39:26 2007 -0600
    48.3 @@ -700,13 +700,7 @@ def xm_save(args):
    48.4      if serverType == SERVER_XEN_API:       
    48.5          server.xenapi.VM.save(get_single_vm(dom), savefile, checkpoint)
    48.6      else:
    48.7 -        try:
    48.8 -            dominfo = parse_doms_info(server.xend.domain(dom))
    48.9 -        except xmlrpclib.Fault, ex:
   48.10 -            raise ex
   48.11 -    
   48.12 -        domid = dominfo['domid']
   48.13 -        server.xend.domain.save(domid, savefile, checkpoint)
   48.14 +        server.xend.domain.save(dom, savefile, checkpoint)
   48.15      
   48.16  def xm_restore(args):
   48.17      arg_check(args, "restore", 1, 2)
   48.18 @@ -1529,7 +1523,7 @@ def xm_sched_credit(args):
   48.19  
   48.20      doms = filter(lambda x : domid_match(domid, x),
   48.21                    [parse_doms_info(dom)
   48.22 -                  for dom in getDomains(None, 'running')])
   48.23 +                  for dom in getDomains(None, 'all')])
   48.24  
   48.25      if weight is None and cap is None:
   48.26          if domid is not None and doms == []: 
   48.27 @@ -1545,7 +1539,7 @@ def xm_sched_credit(args):
   48.28                          server.xenapi.VM.get_metrics(
   48.29                              get_single_vm(d['name'])))
   48.30                  else:
   48.31 -                    info = server.xend.domain.sched_credit_get(d['domid'])
   48.32 +                    info = server.xend.domain.sched_credit_get(d['name'])
   48.33              except xmlrpclib.Fault:
   48.34                  pass
   48.35  
   48.36 @@ -1557,8 +1551,8 @@ def xm_sched_credit(args):
   48.37              info['cap']    = int(info['cap'])
   48.38              
   48.39              info['name']  = d['name']
   48.40 -            info['domid'] = int(d['domid'])
   48.41 -            print( ("%(name)-32s %(domid)5d %(weight)6d %(cap)4d") % info)
   48.42 +            info['domid'] = str(d['domid'])
   48.43 +            print( ("%(name)-32s %(domid)5s %(weight)6d %(cap)4d") % info)
   48.44      else:
   48.45          if domid is None:
   48.46              # place holder for system-wide scheduler parameters
   48.47 @@ -1566,14 +1560,24 @@ def xm_sched_credit(args):
   48.48              usage('sched-credit')
   48.49  
   48.50          if serverType == SERVER_XEN_API:
   48.51 -            server.xenapi.VM.add_to_VCPUs_params_live(
   48.52 -                get_single_vm(domid),
   48.53 -                "weight",
   48.54 -                weight)
   48.55 -            server.xenapi.VM.add_to_VCPUs_params_live(
   48.56 -                get_single_vm(domid),
   48.57 -                "cap",
   48.58 -                cap)            
   48.59 +            if doms[0]['domid']:
   48.60 +                server.xenapi.VM.add_to_VCPUs_params_live(
   48.61 +                    get_single_vm(domid),
   48.62 +                    "weight",
   48.63 +                    weight)
   48.64 +                server.xenapi.VM.add_to_VCPUs_params_live(
   48.65 +                    get_single_vm(domid),
   48.66 +                    "cap",
   48.67 +                    cap)
   48.68 +            else:
   48.69 +                server.xenapi.VM.add_to_VCPUs_params(
   48.70 +                    get_single_vm(domid),
   48.71 +                    "weight",
   48.72 +                    weight)
   48.73 +                server.xenapi.VM.add_to_VCPUs_params(
   48.74 +                    get_single_vm(domid),
   48.75 +                    "cap",
   48.76 +                    cap)
   48.77          else:
   48.78              result = server.xend.domain.sched_credit_set(domid, weight, cap)
   48.79              if result != 0:
    49.1 --- a/tools/security/policies/security_policy.xsd	Mon Jul 09 09:22:58 2007 -0600
    49.2 +++ b/tools/security/policies/security_policy.xsd	Tue Jul 10 08:39:26 2007 -0600
    49.3 @@ -22,7 +22,7 @@
    49.4  				<xsd:element name="Reference" type="xsd:string" minOccurs="0" maxOccurs="1" />
    49.5  				<xsd:element name="Date" minOccurs="0" maxOccurs="1" type="xsd:string"></xsd:element>
    49.6  				<xsd:element name="NameSpaceUrl" minOccurs="0" maxOccurs="1" type="xsd:string"></xsd:element>
    49.7 -				<xsd:element name="Version" minOccurs="0" maxOccurs="1" type="VersionFormat"/>
    49.8 +				<xsd:element name="Version" minOccurs="1" maxOccurs="1" type="VersionFormat"/>
    49.9  				<xsd:element ref="FromPolicy" minOccurs="0" maxOccurs="1"/>
   49.10  			</xsd:sequence>
   49.11  		</xsd:complexType>
   49.12 @@ -91,23 +91,23 @@
   49.13  			<xsd:sequence>
   49.14  				<xsd:element maxOccurs="unbounded" minOccurs="1" ref="Type" />
   49.15  			</xsd:sequence>
   49.16 -			<xsd:attribute name="name" type="xsd:string" use="optional"></xsd:attribute>
   49.17 +			<xsd:attribute name="name" type="xsd:string" use="required"></xsd:attribute>
   49.18  		</xsd:complexType>
   49.19  	</xsd:element>
   49.20  	<xsd:element name="VirtualMachineLabel">
   49.21  		<xsd:complexType>
   49.22  			<xsd:sequence>
   49.23 -				<xsd:element ref="Name"></xsd:element>
   49.24 +				<xsd:element name="Name" type="NameWithFrom"></xsd:element>
   49.25  				<xsd:element ref="SimpleTypeEnforcementTypes" minOccurs="0" maxOccurs="unbounded" />
   49.26 -				<xsd:element ref="ChineseWallTypes" minOccurs="0" maxOccurs="unbounded" />
   49.27 +				<xsd:element name="ChineseWallTypes" type="SingleChineseWallType" />
   49.28  			</xsd:sequence>
   49.29  		</xsd:complexType>
   49.30  	</xsd:element>
   49.31  	<xsd:element name="ResourceLabel">
   49.32  		<xsd:complexType>
   49.33  			<xsd:sequence>
   49.34 -				<xsd:element ref="Name"></xsd:element>
   49.35 -				<xsd:element ref="SimpleTypeEnforcementTypes" minOccurs="0" maxOccurs="unbounded" />
   49.36 +				<xsd:element name="Name" type="NameWithFrom"></xsd:element>
   49.37 +				<xsd:element name="SimpleTypeEnforcementTypes" type="SingleSimpleTypeEnforcementType" />
   49.38  			</xsd:sequence>
   49.39  		</xsd:complexType>
   49.40  	</xsd:element>
   49.41 @@ -131,4 +131,21 @@
   49.42  			<xsd:pattern value="[0-9]{1,8}.[0-9]{1,8}"></xsd:pattern>
   49.43  		</xsd:restriction>
   49.44  	</xsd:simpleType>
   49.45 +	<xsd:complexType name="NameWithFrom">
   49.46 +		<xsd:simpleContent>
   49.47 +			<xsd:extension base="xsd:string">
   49.48 +				<xsd:attribute name="from" type="xsd:string" use="optional"></xsd:attribute>
   49.49 +			</xsd:extension>
   49.50 +		</xsd:simpleContent>
   49.51 +	</xsd:complexType>
   49.52 +	<xsd:complexType name="SingleSimpleTypeEnforcementType">
   49.53 +		<xsd:sequence>
   49.54 +			<xsd:element maxOccurs="1" minOccurs="1" ref="Type" />
   49.55 +		</xsd:sequence>
   49.56 +	</xsd:complexType>
   49.57 +	<xsd:complexType name="SingleChineseWallType">
   49.58 +		<xsd:sequence>
   49.59 +			<xsd:element maxOccurs="1" minOccurs="1" ref="Type" />
   49.60 +		</xsd:sequence>
   49.61 +	</xsd:complexType>
   49.62  </xsd:schema>
    50.1 --- a/tools/security/xensec_ezpolicy	Mon Jul 09 09:22:58 2007 -0600
    50.2 +++ b/tools/security/xensec_ezpolicy	Tue Jul 10 08:39:26 2007 -0600
    50.3 @@ -1102,8 +1102,10 @@ def org2dict():
    50.4      for i in iterchildren(app.win.orgs.GetRootItem()):
    50.5          d = []
    50.6          for j in iterchildren(i):
    50.7 -            d.append(str(app.win.orgspanel.orgs.GetItemText(j)))
    50.8 -        o.append([str(app.win.orgspanel.orgs.GetItemText(i)) , d])
    50.9 +            d.append(
   50.10 +                  str(app.win.orgspanel.orgs.GetItemText(j).encode("utf-8")))
   50.11 +        o.append([str(app.win.orgspanel.orgs.GetItemText(i).encode("utf-8")),
   50.12 +                 d])
   50.13      dic['orgs'] = o
   50.14      c=[]
   50.15      for i in app.win.conspanel.conflictsets:
   50.16 @@ -1175,12 +1177,14 @@ def printPolicy(fd, types, cons):
   50.17                  continue
   50.18              #name is optional but must be set
   50.19              if i[0]:
   50.20 -                rer_name = str(i[0])
   50.21 +                rer_name = i[0]
   50.22              else:
   50.23 -                rer_name = str("RER")
   50.24 -            fd.write("""            <Conflict name=\"%s\">\n""" % rer_name)
   50.25 +                rer_name = "RER"
   50.26 +            fd.write("""            <Conflict name=\"""" +
   50.27 +                     rer_name.encode("utf-8") + """\">\n""")
   50.28              for j in i[1]:
   50.29 -                fd.write("""                <Type>%s</Type>\n""" % str(j))
   50.30 +                typ = j.encode("utf-8")
   50.31 +                fd.write("""                <Type>%s</Type>\n""" % typ)
   50.32              fd.write("""            </Conflict>\n""")
   50.33          fd.write("""       </ConflictSets>\n""")
   50.34  
    51.1 --- a/tools/xcutils/Makefile	Mon Jul 09 09:22:58 2007 -0600
    51.2 +++ b/tools/xcutils/Makefile	Tue Jul 10 08:39:26 2007 -0600
    51.3 @@ -15,7 +15,7 @@ PROGRAMS_INSTALL_DIR = /usr/$(LIBDIR)/xe
    51.4  
    51.5  INCLUDES += -I $(XEN_LIBXC) -I $(XEN_XENSTORE)
    51.6  
    51.7 -CFLAGS += -Werror -fno-strict-aliasing
    51.8 +CFLAGS += -Werror
    51.9  CFLAGS += $(INCLUDES)
   51.10  
   51.11  # Make gcc generate dependencies.
    52.1 --- a/tools/xenmon/xenbaked.c	Mon Jul 09 09:22:58 2007 -0600
    52.2 +++ b/tools/xenmon/xenbaked.c	Tue Jul 10 08:39:26 2007 -0600
    52.3 @@ -444,7 +444,7 @@ struct t_rec **init_rec_ptrs(struct t_bu
    52.4   */
    52.5  unsigned int get_num_cpus(void)
    52.6  {
    52.7 -    xc_physinfo_t physinfo;
    52.8 +    xc_physinfo_t physinfo = { 0 };
    52.9      int xc_handle = xc_interface_open();
   52.10      int ret;
   52.11  
    53.1 --- a/tools/xenstat/libxenstat/src/xenstat.c	Mon Jul 09 09:22:58 2007 -0600
    53.2 +++ b/tools/xenstat/libxenstat/src/xenstat.c	Tue Jul 10 08:39:26 2007 -0600
    53.3 @@ -135,7 +135,7 @@ xenstat_node *xenstat_get_node(xenstat_h
    53.4  {
    53.5  #define DOMAIN_CHUNK_SIZE 256
    53.6  	xenstat_node *node;
    53.7 -	xc_physinfo_t physinfo;
    53.8 +	xc_physinfo_t physinfo = { 0 };
    53.9  	xc_domaininfo_t domaininfo[DOMAIN_CHUNK_SIZE];
   53.10  	unsigned int new_domains;
   53.11  	unsigned int i;
    54.1 --- a/tools/xenstore/Makefile	Mon Jul 09 09:22:58 2007 -0600
    54.2 +++ b/tools/xenstore/Makefile	Tue Jul 10 08:39:26 2007 -0600
    54.3 @@ -11,15 +11,11 @@ BASECFLAGS=-Werror
    54.4  BASECFLAGS += -Wp,-MD,.$(@F).d
    54.5  PROG_DEP = .*.d
    54.6  BASECFLAGS+= $(PROFILE)
    54.7 -#BASECFLAGS+= -I$(XEN_ROOT)/tools
    54.8  BASECFLAGS+= -I$(XEN_ROOT)/tools/libxc
    54.9  BASECFLAGS+= -I.
   54.10  
   54.11  CFLAGS  += $(BASECFLAGS)
   54.12  LDFLAGS += $(PROFILE) -L$(XEN_LIBXC)
   54.13 -TESTDIR  = testsuite/tmp
   54.14 -TESTFLAGS= -DTESTING
   54.15 -TESTENV  = XENSTORED_ROOTDIR=$(TESTDIR) XENSTORED_RUNDIR=$(TESTDIR)
   54.16  
   54.17  CLIENTS := xenstore-exists xenstore-list xenstore-read xenstore-rm xenstore-chmod
   54.18  CLIENTS += xenstore-write
   54.19 @@ -35,12 +31,6 @@ XENSTORED_OBJS += $(XENSTORED_OBJS_y)
   54.20  .PHONY: all
   54.21  all: libxenstore.so libxenstore.a xenstored $(CLIENTS) xs_tdb_dump xenstore-control xenstore-ls
   54.22  
   54.23 -test_interleaved_transactions: test_interleaved_transactions.o
   54.24 -	$(CC) $(CFLAGS) $(LDFLAGS) $^ $(LOADLIBES) $(LDLIBS) -L. -lxenstore -o $@
   54.25 -
   54.26 -.PHONY: testcode
   54.27 -testcode: xs_test xenstored_test xs_random
   54.28 -
   54.29  xenstored: $(XENSTORED_OBJS)
   54.30  	$(CC) $(CFLAGS) $(LDFLAGS) $^ $(LOADLIBES) $(LDLIBS) -lxenctrl $(SOCKET_LIBS) -o $@
   54.31  
   54.32 @@ -56,35 +46,9 @@ xenstore-control: xenstore_control.o lib
   54.33  xenstore-ls: xsls.o libxenstore.so
   54.34  	$(CC) $(CFLAGS) $(LDFLAGS) $< $(LOADLIBES) $(LDLIBS) -L. -lxenstore $(SOCKET_LIBS) -o $@
   54.35  
   54.36 -xenstored_test: xenstored_core_test.o xenstored_watch_test.o xenstored_domain_test.o xenstored_transaction_test.o xs_lib.o talloc_test.o fake_libxc.o utils.o tdb.o
   54.37 -	$(CC) $(CFLAGS) $(LDFLAGS) $^ $(LOADLIBES) $(LDLIBS) -o $@
   54.38 -
   54.39  xs_tdb_dump: xs_tdb_dump.o utils.o tdb.o talloc.o
   54.40  	$(CC) $(CFLAGS) $(LDFLAGS) $^ $(LOADLIBES) $(LDLIBS) -o $@
   54.41  
   54.42 -xs_test xs_random xs_stress xs_crashme: LDFLAGS+=-lpthread
   54.43 -xs_test: xs_test.o xs_lib.o utils.o
   54.44 -xs_random: xs_random.o xs_test_lib.o xs_lib.o talloc.o utils.o
   54.45 -xs_stress: xs_stress.o xs_test_lib.o xs_lib.o talloc.o utils.o
   54.46 -xs_crashme: xs_crashme.o xs_lib.o talloc.o utils.o
   54.47 -
   54.48 -speedtest: speedtest.o xs.o xs_lib.o utils.o talloc.o
   54.49 -
   54.50 -.PHONY: check-speed
   54.51 -check-speed: speedtest xenstored_test $(TESTDIR)
   54.52 -	$(TESTENV) time ./speedtest 100
   54.53 -
   54.54 -xs_test.o xs_stress.o xenstored_core_test.o xenstored_watch_test.o xenstored_transaction_test.o xenstored_domain_test.o xs_random.o xs_test_lib.o talloc_test.o fake_libxc.o xs_crashme.o: CFLAGS=$(BASECFLAGS) $(TESTFLAGS)
   54.55 -
   54.56 -xenstored_%_test.o: xenstored_%.c
   54.57 -	$(COMPILE.c) -o $@ $<
   54.58 -
   54.59 -xs_test_lib.o: xs.c
   54.60 -	$(COMPILE.c) -o $@ $<
   54.61 -
   54.62 -talloc_test.o: talloc.c
   54.63 -	$(COMPILE.c) -o $@ $<
   54.64 -
   54.65  libxenstore.so: libxenstore.so.$(MAJOR)
   54.66  	ln -sf $< $@
   54.67  libxenstore.so.$(MAJOR): libxenstore.so.$(MAJOR).$(MINOR)
   54.68 @@ -97,67 +61,13 @@ libxenstore.a: xs.o xs_lib.o
   54.69  	$(AR) rcs libxenstore.a $^
   54.70  
   54.71  .PHONY: clean
   54.72 -clean: testsuite-clean
   54.73 +clean:
   54.74  	rm -f *.a *.o *.opic *.so*
   54.75  	rm -f xenstored xs_random xs_stress xs_crashme
   54.76 -	rm -f xs_test xenstored_test xs_tdb_dump xenstore-control xenstore-ls
   54.77 +	rm -f xs_tdb_dump xenstore-control xenstore-ls
   54.78  	rm -f $(CLIENTS)
   54.79  	$(RM) $(PROG_DEP)
   54.80  
   54.81 -.PHONY: print-dir
   54.82 -print-dir:
   54.83 -	@echo -n tools/xenstore: 
   54.84 -
   54.85 -.PHONY: print-end
   54.86 -print-end:
   54.87 -	@echo
   54.88 -
   54.89 -.PHONY: check
   54.90 -check: print-dir testsuite-fast randomcheck-fast print-end
   54.91 -
   54.92 -.PHONY: fullcheck
   54.93 -fullcheck: testsuite-run randomcheck stresstest
   54.94 -
   54.95 -$(TESTDIR):
   54.96 -	mkdir $@
   54.97 -
   54.98 -.PHONY: testsuite-run
   54.99 -testsuite-run: xenstored_test xs_test $(TESTDIR)
  54.100 -	$(TESTENV) testsuite/test.sh && echo
  54.101 -
  54.102 -.PHONY: testsuite-fast
  54.103 -testsuite-fast: xenstored_test xs_test $(TESTDIR)
  54.104 -	@$(TESTENV) testsuite/test.sh --fast
  54.105 -
  54.106 -.PHONY: testsuite-clean
  54.107 -testsuite-clean:
  54.108 -	rm -rf $(TESTDIR)
  54.109 -
  54.110 -# Make this visible so they can see repeat tests without --fast if they
  54.111 -# fail.
  54.112 -RANDSEED=$(shell date +%s)
  54.113 -.PHONY: randomcheck
  54.114 -randomcheck: xs_random xenstored_test $(TESTDIR)
  54.115 -	$(TESTENV) ./xs_random --simple --fast /tmp/xs_random 200000 $(RANDSEED) && echo
  54.116 -	$(TESTENV) ./xs_random --fast /tmp/xs_random 100000 $(RANDSEED) && echo
  54.117 -#	$(TESTENV) ./xs_random --fail /tmp/xs_random 10000 $(RANDSEED)
  54.118 -
  54.119 -.PHONY: crashme
  54.120 -crashme:  xs_crashme xenstored_test $(TESTDIR)
  54.121 -	rm -rf $(TESTDIR)/store $(TESTDIR)/transactions /tmp/xs_crashme.vglog* /tmp/trace
  54.122 -	export $(TESTENV); ./xs_crashme 5000 $(RANDSEED) 2>/dev/null
  54.123 -	if [ -n "`cat /tmp/xs_crashme.vglog*`" ]; then echo Valgrind complained; cat /tmp/xs_crashme.vglog*; exit 1; fi
  54.124 -	rm -rf $(TESTDIR)/store $(TESTDIR)/transactions /tmp/xs_crashme.vglog* /tmp/trace
  54.125 -
  54.126 -.PHONY: randomcheck-fast
  54.127 -randomcheck-fast: xs_random xenstored_test $(TESTDIR)
  54.128 -	@$(TESTENV) ./xs_random --fast /tmp/xs_random 2000 $(RANDSEED)
  54.129 -
  54.130 -.PHONY: stresstest
  54.131 -stresstest: xs_stress xenstored_test $(TESTDIR)
  54.132 -	rm -rf $(TESTDIR)/store $(TESTDIR)/transactions
  54.133 -	export $(TESTENV); PID=`./xenstored_test --output-pid --trace-file=/tmp/trace`; ./xs_stress 5000; ret=$$?; kill $$PID; exit $$ret
  54.134 -
  54.135  .PHONY: TAGS
  54.136  TAGS:
  54.137  	etags `find . -name '*.[ch]'`
    55.1 --- a/tools/xenstore/fake_libxc.c	Mon Jul 09 09:22:58 2007 -0600
    55.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    55.3 @@ -1,143 +0,0 @@
    55.4 -/* 
    55.5 -    Fake libxc which doesn't require hypervisor but talks to xs_test.
    55.6 -    Copyright (C) 2005 Rusty Russell IBM Corporation
    55.7 -
    55.8 -    This program is free software; you can redistribute it and/or modify
    55.9 -    it under the terms of the GNU General Public License as published by
   55.10 -    the Free Software Foundation; either version 2 of the License, or
   55.11 -    (at your option) any later version.
   55.12 -
   55.13 -    This program is distributed in the hope that it will be useful,
   55.14 -    but WITHOUT ANY WARRANTY; without even the implied warranty of
   55.15 -    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   55.16 -    GNU General Public License for more details.
   55.17 -
   55.18 -    You should have received a copy of the GNU General Public License
   55.19 -    along with this program; if not, write to the Free Software
   55.20 -    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
   55.21 -*/
   55.22 -
   55.23 -#include <stdio.h>
   55.24 -#include <stdlib.h>
   55.25 -#include <sys/types.h>
   55.26 -#include <sys/stat.h>
   55.27 -#include <fcntl.h>
   55.28 -#include <sys/mman.h>
   55.29 -#include <unistd.h>
   55.30 -#include <assert.h>
   55.31 -#include <signal.h>
   55.32 -#include "utils.h"
   55.33 -#include "xenstored_core.h"
   55.34 -#include "xenstored_domain.h"
   55.35 -#include "xenstored_test.h"
   55.36 -#include <xenctrl.h>
   55.37 -
   55.38 -static int sigfd;
   55.39 -static int xs_test_pid;
   55.40 -static evtchn_port_t port;
   55.41 -
   55.42 -/* The event channel maps to a signal, shared page to an mmapped file. */
   55.43 -void xc_evtchn_notify(int xce_handle, int local_port)
   55.44 -{
   55.45 -	assert(local_port == port);
   55.46 -	if (kill(xs_test_pid, SIGUSR2) != 0)
   55.47 -		barf_perror("fake event channel failed");
   55.48 -}
   55.49 -
   55.50 -void *xc_map_foreign_range(int xc_handle, uint32_t dom __attribute__((unused)),
   55.51 -			   int size, int prot,
   55.52 -			   unsigned long mfn __attribute__((unused)))
   55.53 -{
   55.54 -	void *ret;
   55.55 -
   55.56 -	ret = mmap(NULL, size, prot, MAP_SHARED, xc_handle, 0);
   55.57 -	if (ret == MAP_FAILED)
   55.58 -		return NULL;
   55.59 -
   55.60 -	/* xs_test tells us pid and port by putting it in buffer, we reply. */
   55.61 -	xs_test_pid = *(int *)(ret + 32);
   55.62 -	port = *(int *)(ret + 36);
   55.63 -	*(int *)(ret + 32) = getpid();
   55.64 -	return ret;
   55.65 -}
   55.66 -
   55.67 -int xc_interface_open(void)
   55.68 -{
   55.69 -	int fd;
   55.70 -	char page[getpagesize()];
   55.71 -
   55.72 -	fd = open("/tmp/xcmap", O_RDWR|O_CREAT|O_TRUNC, 0600);
   55.73 -	if (fd < 0)
   55.74 -		return fd;
   55.75 -
   55.76 -	memset(page, 0, sizeof(page));
   55.77 -	if (!xs_write_all(fd, page, sizeof(page)))
   55.78 -		barf_perror("Failed to write /tmp/xcmap page");
   55.79 -	
   55.80 -	return fd;
   55.81 -}
   55.82 -
   55.83 -int xc_interface_close(int xc_handle)
   55.84 -{
   55.85 -	close(xc_handle);
   55.86 -	return 0;
   55.87 -}
   55.88 -
   55.89 -int xc_domain_getinfo(int xc_handle __attribute__((unused)),
   55.90 -		      uint32_t first_domid, unsigned int max_doms,
   55.91 -                      xc_dominfo_t *info)
   55.92 -{
   55.93 -	assert(max_doms == 1);
   55.94 -        info->domid = first_domid;
   55.95 -
   55.96 -        info->dying    = 0;
   55.97 -        info->shutdown = 0;
   55.98 -        info->paused   = 0;
   55.99 -        info->blocked  = 0;
  55.100 -        info->running  = 1;
  55.101 -
  55.102 -        info->shutdown_reason = 0;
  55.103 -
  55.104 -        if ( info->shutdown && (info->shutdown_reason == SHUTDOWN_crash) )
  55.105 -        {
  55.106 -            info->shutdown = 0;
  55.107 -            info->crashed  = 1;
  55.108 -        }
  55.109 -
  55.110 -	return 1;
  55.111 -}
  55.112 -
  55.113 -static void send_to_fd(int signo __attribute__((unused)))
  55.114 -{
  55.115 -	int saved_errno = errno;
  55.116 -	write(sigfd, &port, sizeof(port));
  55.117 -	errno = saved_errno;
  55.118 -}
  55.119 -
  55.120 -void fake_block_events(void)
  55.121 -{
  55.122 -	signal(SIGUSR2, SIG_IGN);
  55.123 -}
  55.124 -
  55.125 -void fake_ack_event(void)
  55.126 -{
  55.127 -	signal(SIGUSR2, send_to_fd);
  55.128 -}
  55.129 -
  55.130 -int xc_evtchn_open(void)
  55.131 -{
  55.132 -	int fds[2];
  55.133 -
  55.134 -	if (pipe(fds) != 0)
  55.135 -		return -1;
  55.136 -
  55.137 -	if (signal(SIGUSR2, send_to_fd) == SIG_ERR) {
  55.138 -		int saved_errno = errno;
  55.139 -		close(fds[0]);
  55.140 -		close(fds[1]);
  55.141 -		errno = saved_errno;
  55.142 -		return -1;
  55.143 -	}
  55.144 -	sigfd = fds[1];
  55.145 -	return fds[0];
  55.146 -}
    56.1 --- a/tools/xenstore/speedtest.c	Mon Jul 09 09:22:58 2007 -0600
    56.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    56.3 @@ -1,130 +0,0 @@
    56.4 -/* 
    56.5 -    Xen Store Daemon Speed test
    56.6 -    Copyright (C) 2005 Rusty Russell IBM Corporation
    56.7 -
    56.8 -    This program is free software; you can redistribute it and/or modify
    56.9 -    it under the terms of the GNU General Public License as published by
   56.10 -    the Free Software Foundation; either version 2 of the License, or
   56.11 -    (at your option) any later version.
   56.12 -
   56.13 -    This program is distributed in the hope that it will be useful,
   56.14 -    but WITHOUT ANY WARRANTY; without even the implied warranty of
   56.15 -    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   56.16 -    GNU General Public License for more details.
   56.17 -
   56.18 -    You should have received a copy of the GNU General Public License
   56.19 -    along with this program; if not, write to the Free Software
   56.20 -    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
   56.21 -*/
   56.22 -
   56.23 -#include <stdlib.h>
   56.24 -#include <sys/types.h>
   56.25 -#include <sys/wait.h>
   56.26 -#include <stdio.h>
   56.27 -#include <stdarg.h>
   56.28 -#include <unistd.h>
   56.29 -#include <fcntl.h>
   56.30 -#include <errno.h>
   56.31 -#include "utils.h"
   56.32 -#include "xs.h"
   56.33 -#include "list.h"
   56.34 -#include "talloc.h"
   56.35 -
   56.36 -static void do_command(const char *cmd)
   56.37 -{
   56.38 -	int ret;
   56.39 -
   56.40 -	ret = system(cmd);
   56.41 -	if (ret == -1 || !WIFEXITED(ret) || WEXITSTATUS(ret) != 0)
   56.42 -		barf_perror("Failed '%s': %i", cmd, ret);
   56.43 -}
   56.44 -
   56.45 -static int start_daemon(void)
   56.46 -{
   56.47 -	int fds[2], pid;
   56.48 -
   56.49 -	do_command(talloc_asprintf(NULL, "rm -rf testsuite/tmp/*"));
   56.50 -
   56.51 -	/* Start daemon. */
   56.52 -	pipe(fds);
   56.53 -	if ((pid = fork())) {
   56.54 -		/* Child writes PID when its ready: we wait for that. */
   56.55 -		char buffer[20];
   56.56 -		close(fds[1]);
   56.57 -		if (read(fds[0], buffer, sizeof(buffer)) < 0)
   56.58 -			barf("Failed to summon daemon");
   56.59 -		close(fds[0]);
   56.60 -	} else {
   56.61 -		dup2(fds[1], STDOUT_FILENO);
   56.62 -		close(fds[0]);
   56.63 -#if 0
   56.64 -		execlp("valgrind", "valgrind", "-q", "--suppressions=testsuite/vg-suppressions", "xenstored_test", "--output-pid",
   56.65 -		       "--no-fork", "--trace-file=/tmp/trace", NULL);
   56.66 -#else
   56.67 -		execlp("./xenstored_test", "xenstored_test", "--output-pid", "--no-fork", NULL);
   56.68 -//		execlp("strace", "strace", "-o", "/tmp/out", "./xenstored_test", "--output-pid", "--no-fork", NULL);
   56.69 -#endif
   56.70 -		exit(1);
   56.71 -	}
   56.72 -	return pid;
   56.73 -}
   56.74 -
   56.75 -static void kill_daemon(int pid)
   56.76 -{
   56.77 -	int saved_errno = errno;
   56.78 -	kill(pid, SIGTERM);
   56.79 -	errno = saved_errno;
   56.80 -}
   56.81 -
   56.82 -#define NUM_ENTRIES 50
   56.83 -
   56.84 -/* We create the given number of trees, each with NUM_ENTRIES, using
   56.85 - * transactions. */
   56.86 -int main(int argc, char *argv[])
   56.87 -{
   56.88 -	int i, j, pid, print;
   56.89 -	struct xs_handle *h;
   56.90 -
   56.91 -	if (argc != 2)
   56.92 -		barf("Usage: speedtest <numdomains>");
   56.93 -
   56.94 -	pid = start_daemon();
   56.95 -	h = xs_daemon_open();
   56.96 -	print = atoi(argv[1]) / 76;
   56.97 -	if (!print)
   56.98 -		print = 1;
   56.99 -	for (i = 0; i < atoi(argv[1]); i ++) {
  56.100 -		char name[64];
  56.101 -
  56.102 -		if (i % print == 0)
  56.103 -			write(1, ".", 1);
  56.104 -		if (!xs_transaction_start(h)) {
  56.105 -			kill_daemon(pid);
  56.106 -			barf_perror("Starting transaction");
  56.107 -		}
  56.108 -		sprintf(name, "/%i", i);
  56.109 -		if (!xs_mkdir(h, name)) {
  56.110 -			kill_daemon(pid);
  56.111 -			barf_perror("Making directory %s", name);
  56.112 -		}
  56.113 -
  56.114 -		for (j = 0; j < NUM_ENTRIES; j++) {
  56.115 -			sprintf(name, "/%i/%i", i, j);
  56.116 -			if (!xs_write(h, name, name, strlen(name))) {
  56.117 -				kill_daemon(pid);
  56.118 -				barf_perror("Making directory %s", name);
  56.119 -			}
  56.120 -		}
  56.121 -		if (!xs_transaction_end(h, false)) {
  56.122 -			kill_daemon(pid);
  56.123 -			barf_perror("Ending transaction");
  56.124 -		}
  56.125 -	}
  56.126 -	write(1, "\n", 1);
  56.127 -
  56.128 -	kill_daemon(pid);
  56.129 -	wait(NULL);
  56.130 -	return 0;
  56.131 -}
  56.132 -	
  56.133 -	
    57.1 --- a/tools/xenstore/testsuite/01simple.test	Mon Jul 09 09:22:58 2007 -0600
    57.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    57.3 @@ -1,4 +0,0 @@
    57.4 -# Create an entry, read it.
    57.5 -write /test contents
    57.6 -expect contents
    57.7 -read /test
    58.1 --- a/tools/xenstore/testsuite/02directory.test	Mon Jul 09 09:22:58 2007 -0600
    58.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    58.3 @@ -1,45 +0,0 @@
    58.4 -# Root directory has only tool dir in it.
    58.5 -expect tool
    58.6 -dir /
    58.7 -
    58.8 -# Create a file.
    58.9 -write /test contents
   58.10 -
   58.11 -# Directory shows it.
   58.12 -expect test
   58.13 -expect tool
   58.14 -dir /
   58.15 -
   58.16 -# Make a new directory, check it's there
   58.17 -mkdir /dir
   58.18 -expect dir
   58.19 -expect test
   58.20 -expect tool
   58.21 -dir /
   58.22 -
   58.23 -# Check it's empty.
   58.24 -dir /dir
   58.25 -
   58.26 -# Create a file, check it exists.
   58.27 -write /dir/test2 contents2
   58.28 -expect test2
   58.29 -dir /dir
   58.30 -expect contents2
   58.31 -read /dir/test2
   58.32 -
   58.33 -# Creating dir over the top should succeed.
   58.34 -mkdir /dir
   58.35 -mkdir /dir/test2
   58.36 -
   58.37 -# Mkdir implicitly creates directories.
   58.38 -mkdir /dir/1/2/3/4
   58.39 -expect test2
   58.40 -expect 1
   58.41 -dir /dir
   58.42 -expect 2
   58.43 -dir /dir/1
   58.44 -expect 3
   58.45 -dir /dir/1/2
   58.46 -expect 4
   58.47 -dir /dir/1/2/3
   58.48 -dir /dir/1/2/3/4
    59.1 --- a/tools/xenstore/testsuite/03write.test	Mon Jul 09 09:22:58 2007 -0600
    59.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    59.3 @@ -1,28 +0,0 @@
    59.4 -# Write succeeds
    59.5 -write /test contents
    59.6 -expect contents
    59.7 -read /test
    59.8 -
    59.9 -# Overwrite succeeds.
   59.10 -write /test contents2
   59.11 -expect contents2
   59.12 -read /test
   59.13 -
   59.14 -# Write should implicitly create directories
   59.15 -write /dir/test contents
   59.16 -expect test
   59.17 -dir /dir
   59.18 -expect contents
   59.19 -read /dir/test
   59.20 -write /dir/1/2/3/4 contents4
   59.21 -expect test
   59.22 -expect 1
   59.23 -dir /dir
   59.24 -expect 2
   59.25 -dir /dir/1
   59.26 -expect 3
   59.27 -dir /dir/1/2
   59.28 -expect 4
   59.29 -dir /dir/1/2/3
   59.30 -expect contents4
   59.31 -read /dir/1/2/3/4
    60.1 --- a/tools/xenstore/testsuite/04rm.test	Mon Jul 09 09:22:58 2007 -0600
    60.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    60.3 @@ -1,20 +0,0 @@
    60.4 -# Remove non-existant is OK, as long as parent exists
    60.5 -rm /test
    60.6 -expect rm failed: No such file or directory
    60.7 -rm /dir/test
    60.8 -
    60.9 -# Create file and remove it
   60.10 -write /test contents
   60.11 -rm /test
   60.12 -expect tool
   60.13 -dir /
   60.14 -
   60.15 -# Create directory and remove it.
   60.16 -mkdir /dir
   60.17 -rm /dir
   60.18 -
   60.19 -# Create directory, create file, remove all.
   60.20 -mkdir /dir
   60.21 -write /dir/test contents
   60.22 -rm /dir
   60.23 -
    61.1 --- a/tools/xenstore/testsuite/05filepermissions.test	Mon Jul 09 09:22:58 2007 -0600
    61.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    61.3 @@ -1,81 +0,0 @@
    61.4 -# Fail to get perms on non-existent file.
    61.5 -expect getperm failed: No such file or directory
    61.6 -getperm /test
    61.7 -expect getperm failed: No such file or directory
    61.8 -getperm /dir/test
    61.9 -
   61.10 -# Create file: inherits from root (0 READ)
   61.11 -write /test contents
   61.12 -expect 0 READ
   61.13 -getperm /test
   61.14 -setid 1
   61.15 -expect 0 READ
   61.16 -getperm /test
   61.17 -expect contents
   61.18 -read /test
   61.19 -expect write failed: Permission denied
   61.20 -write /test contents
   61.21 -
   61.22 -# Take away read access to file.
   61.23 -setid 0
   61.24 -setperm /test 0 NONE
   61.25 -setid 1
   61.26 -expect getperm failed: Permission denied
   61.27 -getperm /test
   61.28 -expect read failed: Permission denied
   61.29 -read /test
   61.30 -expect write failed: Permission denied
   61.31 -write /test contents
   61.32 -
   61.33 -# Grant everyone write access to file.
   61.34 -setid 0
   61.35 -setperm /test 0 WRITE
   61.36 -setid 1
   61.37 -expect getperm failed: Permission denied
   61.38 -getperm /test
   61.39 -expect read failed: Permission denied
   61.40 -read /test
   61.41 -write /test contents2
   61.42 -setid 0
   61.43 -expect contents2
   61.44 -read /test
   61.45 -
   61.46 -# Grant everyone both read and write access.
   61.47 -setperm /test 0 READ/WRITE
   61.48 -setid 1
   61.49 -expect 0 READ/WRITE
   61.50 -getperm /test
   61.51 -expect contents2
   61.52 -read /test
   61.53 -write /test contents3
   61.54 -expect contents3
   61.55 -read /test
   61.56 -
   61.57 -# Change so that user 1 owns it, noone else can do anything.
   61.58 -setid 0
   61.59 -setperm /test 1 NONE
   61.60 -setid 1
   61.61 -expect 1 NONE
   61.62 -getperm /test
   61.63 -expect contents3
   61.64 -read /test
   61.65 -write /test contents4
   61.66 -
   61.67 -# User 2 can do nothing.
   61.68 -setid 2
   61.69 -expect setperm failed: Permission denied
   61.70 -setperm /test 2 NONE
   61.71 -expect getperm failed: Permission denied
   61.72 -getperm /test
   61.73 -expect read failed: Permission denied
   61.74 -read /test
   61.75 -expect write failed: Permission denied
   61.76 -write /test contents4
   61.77 -
   61.78 -# Tools can always access things.
   61.79 -setid 0
   61.80 -expect 1 NONE
   61.81 -getperm /test
   61.82 -expect contents4
   61.83 -read /test
   61.84 -write /test contents5
    62.1 --- a/tools/xenstore/testsuite/06dirpermissions.test	Mon Jul 09 09:22:58 2007 -0600
    62.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    62.3 @@ -1,119 +0,0 @@
    62.4 -# Root directory: owned by tool, everyone has read access.
    62.5 -expect 0 READ
    62.6 -getperm /
    62.7 -
    62.8 -# Create directory: inherits from root.
    62.9 -mkdir /dir
   62.10 -expect 0 READ
   62.11 -getperm /dir
   62.12 -setid 1
   62.13 -expect 0 READ
   62.14 -getperm /dir
   62.15 -dir /dir
   62.16 -expect write failed: Permission denied
   62.17 -write /dir/test contents2
   62.18 -
   62.19 -# Remove everyone's read access to directoy.
   62.20 -setid 0
   62.21 -setperm /dir 0 NONE
   62.22 -setid 1
   62.23 -expect dir failed: Permission denied
   62.24 -dir /dir
   62.25 -expect read failed: Permission denied
   62.26 -read /dir/test create contents2
   62.27 -expect write failed: Permission denied
   62.28 -write /dir/test contents2
   62.29 -
   62.30 -# Grant everyone write access to directory.
   62.31 -setid 0
   62.32 -setperm /dir 0 WRITE
   62.33 -setid 1
   62.34 -expect getperm failed: Permission denied
   62.35 -getperm /dir
   62.36 -expect dir failed: Permission denied
   62.37 -dir /dir
   62.38 -write /dir/test contents
   62.39 -setid 0
   62.40 -expect 1 WRITE
   62.41 -getperm /dir/test
   62.42 -setperm /dir/test 0 NONE
   62.43 -expect contents
   62.44 -read /dir/test
   62.45 -
   62.46 -# Grant everyone both read and write access.
   62.47 -setperm /dir 0 READ/WRITE
   62.48 -setid 1
   62.49 -expect 0 READ/WRITE
   62.50 -getperm /dir
   62.51 -expect test
   62.52 -dir /dir
   62.53 -write /dir/test2 contents
   62.54 -expect contents
   62.55 -read /dir/test2
   62.56 -setperm /dir/test2 1 NONE
   62.57 -
   62.58 -# Change so that user 1 owns it, noone else can do anything.
   62.59 -setid 0
   62.60 -setperm /dir 1 NONE
   62.61 -expect 1 NONE
   62.62 -getperm /dir
   62.63 -expect test
   62.64 -expect test2
   62.65 -dir /dir
   62.66 -write /dir/test3 contents
   62.67 -
   62.68 -# User 2 can do nothing.  Can't even tell if file exists.
   62.69 -setid 2
   62.70 -expect setperm failed: Permission denied
   62.71 -setperm /dir 2 NONE
   62.72 -expect getperm failed: Permission denied
   62.73 -getperm /dir
   62.74 -expect dir failed: Permission denied
   62.75 -dir /dir
   62.76 -expect read failed: Permission denied
   62.77 -read /dir/test
   62.78 -expect read failed: Permission denied
   62.79 -read /dir/test2
   62.80 -expect read failed: Permission denied
   62.81 -read /dir/test3
   62.82 -expect read failed: Permission denied
   62.83 -read /dir/test4
   62.84 -expect write failed: Permission denied
   62.85 -write /dir/test contents
   62.86 -expect write failed: Permission denied
   62.87 -write /dir/test4 contents
   62.88 -
   62.89 -# Tools can always access things.
   62.90 -setid 0
   62.91 -expect 1 NONE
   62.92 -getperm /dir
   62.93 -expect test
   62.94 -expect test2
   62.95 -expect test3
   62.96 -dir /dir
   62.97 -write /dir/test4 contents
   62.98 -
   62.99 -# Inherited by child.
  62.100 -mkdir /dir/subdir
  62.101 -expect 1 NONE
  62.102 -getperm /dir/subdir
  62.103 -write /dir/subfile contents
  62.104 -expect 1 NONE
  62.105 -getperm /dir/subfile
  62.106 -
  62.107 -# But for domains, they own it.
  62.108 -setperm /dir/subdir 2 READ/WRITE
  62.109 -expect 2 READ/WRITE
  62.110 -getperm /dir/subdir
  62.111 -setid 3
  62.112 -write /dir/subdir/subfile contents
  62.113 -expect 3 READ/WRITE
  62.114 -getperm /dir/subdir/subfile
  62.115 -
  62.116 -# Inheritence works through multiple directories, too.
  62.117 -write /dir/subdir/1/2/3/4 contents
  62.118 -expect 3 READ/WRITE
  62.119 -getperm /dir/subdir/1/2/3/4
  62.120 -mkdir /dir/subdir/a/b/c/d
  62.121 -expect 3 READ/WRITE
  62.122 -getperm /dir/subdir/a/b/c/d
    63.1 --- a/tools/xenstore/testsuite/07watch.test	Mon Jul 09 09:22:58 2007 -0600
    63.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    63.3 @@ -1,176 +0,0 @@
    63.4 -# Watch something, write to it, check watch has fired.
    63.5 -write /test contents
    63.6 -
    63.7 -1 watch /test token
    63.8 -2 write /test contents2
    63.9 -expect 1:/test:token
   63.10 -1 waitwatch
   63.11 -1 close
   63.12 -
   63.13 -# Check that reads don't set it off.
   63.14 -1 watch /test token
   63.15 -expect 2:contents2
   63.16 -2 read /test
   63.17 -expect 1: waitwatch failed: Connection timed out
   63.18 -1 waitwatch
   63.19 -1 close
   63.20 -
   63.21 -# mkdir, setperm and rm should (also tests watching dirs)
   63.22 -mkdir /dir
   63.23 -1 watch /dir token
   63.24 -2 mkdir /dir/newdir
   63.25 -expect 1:/dir/newdir:token
   63.26 -1 waitwatch
   63.27 -2 setperm /dir/newdir 0 READ
   63.28 -expect 1:/dir/newdir:token
   63.29 -1 waitwatch
   63.30 -2 rm /dir/newdir
   63.31 -expect 1:/dir/newdir:token
   63.32 -1 waitwatch
   63.33 -1 close
   63.34 -2 close
   63.35 -
   63.36 -# Changed in b594bb976a743d509f1ffabb5bc698874ab90d8f
   63.37 -## We don't get a watch from our own commands.
   63.38 -#watch /dir token
   63.39 -#mkdir /dir/newdir
   63.40 -#expect waitwatch failed: Connection timed out
   63.41 -#waitwatch
   63.42 -#close
   63.43 -
   63.44 -# ignore watches while doing commands, should work.
   63.45 -watch /dir token
   63.46 -1 write /dir/test contents
   63.47 -expect contents
   63.48 -read /dir/test
   63.49 -expect /dir/test:token
   63.50 -waitwatch
   63.51 -close
   63.52 -
   63.53 -# watch priority test: all simultaneous
   63.54 -1 watch /dir token1
   63.55 -3 watch /dir token3
   63.56 -2 watch /dir token2
   63.57 -write /dir/test contents
   63.58 -expect 3:/dir/test:token3
   63.59 -3 waitwatch
   63.60 -expect 2:/dir/test:token2
   63.61 -2 waitwatch
   63.62 -expect 1:/dir/test:token1
   63.63 -1 waitwatch
   63.64 -1 close
   63.65 -2 close
   63.66 -3 close
   63.67 -
   63.68 -# If one dies (without acking), the other should still get ack.
   63.69 -1 watch /dir token1
   63.70 -2 watch /dir token2
   63.71 -write /dir/test contents
   63.72 -expect 2:/dir/test:token2
   63.73 -2 waitwatch
   63.74 -2 close
   63.75 -expect 1:/dir/test:token1
   63.76 -1 waitwatch
   63.77 -1 close
   63.78 -
   63.79 -# If one dies (without reading at all), the other should still get ack.
   63.80 -1 watch /dir token1
   63.81 -2 watch /dir token2
   63.82 -write /dir/test contents
   63.83 -2 close
   63.84 -expect 1:/dir/test:token1
   63.85 -1 waitwatch
   63.86 -1 close
   63.87 -2 close
   63.88 -
   63.89 -# unwatch
   63.90 -1 watch /dir token1
   63.91 -1 unwatch /dir token1
   63.92 -1 watch /dir token2
   63.93 -2 write /dir/test2 contents
   63.94 -expect 1:/dir/test2:token2
   63.95 -1 waitwatch
   63.96 -1 unwatch /dir token2
   63.97 -1 close
   63.98 -2 close
   63.99 -
  63.100 -# unwatch while watch pending.  Other watcher still gets the event.
  63.101 -1 watch /dir token1
  63.102 -2 watch /dir token2
  63.103 -write /dir/test contents
  63.104 -2 unwatch /dir token2
  63.105 -expect 1:/dir/test:token1
  63.106 -1 waitwatch
  63.107 -1 close
  63.108 -2 close
  63.109 -
  63.110 -# unwatch while watch pending.  Should clear this so we get next event.
  63.111 -1 watch /dir token1
  63.112 -write /dir/test contents
  63.113 -1 unwatch /dir token1
  63.114 -1 watch /dir/test token2
  63.115 -write /dir/test contents2
  63.116 -expect 1:/dir/test:token2
  63.117 -1 waitwatch
  63.118 -
  63.119 -# check we only get notified once.
  63.120 -1 watch /test token
  63.121 -2 write /test contents2
  63.122 -expect 1:/test:token
  63.123 -1 waitwatch
  63.124 -expect 1: waitwatch failed: Connection timed out
  63.125 -1 waitwatch
  63.126 -1 close
  63.127 -
  63.128 -# watches are queued in order.
  63.129 -1 watch / token
  63.130 -2 write /test1 contents
  63.131 -2 write /test2 contents
  63.132 -2 write /test3 contents
  63.133 -expect 1:/test1:token
  63.134 -1 waitwatch
  63.135 -expect 1:/test2:token
  63.136 -1 waitwatch
  63.137 -expect 1:/test3:token
  63.138 -1 waitwatch
  63.139 -1 close
  63.140 -
  63.141 -# Creation of subpaths should be covered correctly.
  63.142 -1 watch / token
  63.143 -2 write /test/subnode contents2
  63.144 -2 write /test/subnode/subnode contents2
  63.145 -expect 1:/test/subnode:token
  63.146 -1 waitwatch
  63.147 -expect 1:/test/subnode/subnode:token
  63.148 -1 waitwatch
  63.149 -expect 1: waitwatch failed: Connection timed out
  63.150 -1 waitwatch
  63.151 -1 close
  63.152 -
  63.153 -# Watch event must have happened before we registered interest.
  63.154 -1 watch / token
  63.155 -2 write /test/subnode contents2
  63.156 -1 watchnoack / token2 0
  63.157 -expect 1:/test/subnode:token
  63.158 -1 waitwatch
  63.159 -expect 1:/:token2
  63.160 -1 waitwatch
  63.161 -expect 1: waitwatch failed: Connection timed out
  63.162 -1 waitwatch
  63.163 -1 close
  63.164 -
  63.165 -# Rm fires notification on child.
  63.166 -1 watch /test/subnode token
  63.167 -2 rm /test
  63.168 -expect 1:/test/subnode:token
  63.169 -1 waitwatch
  63.170 -
  63.171 -# Watch should not double-send after we ack, even if we did something in between.
  63.172 -1 watch /test2 token
  63.173 -2 write /test2/foo contents2
  63.174 -expect 1:/test2/foo:token
  63.175 -1 waitwatch
  63.176 -expect 1:contents2
  63.177 -1 read /test2/foo
  63.178 -expect 1: waitwatch failed: Connection timed out
  63.179 -1 waitwatch
    64.1 --- a/tools/xenstore/testsuite/08transaction.slowtest	Mon Jul 09 09:22:58 2007 -0600
    64.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    64.3 @@ -1,43 +0,0 @@
    64.4 -# Test transaction clashes.
    64.5 -
    64.6 -mkdir /test
    64.7 -write /test/entry1 contents
    64.8 -
    64.9 -# Start transaction, do read-only op, transaction succeeds
   64.10 -1 start
   64.11 -1 write /test/entry1 contents2
   64.12 -expect contents
   64.13 -read /test/entry1
   64.14 -1 commit
   64.15 -expect contents2
   64.16 -read /test/entry1
   64.17 -
   64.18 -# Start transaction, abort other transaction, transaction succeeds.
   64.19 -1 start
   64.20 -1 write /test/entry1 contents3
   64.21 -start
   64.22 -write /test/entry1 contents
   64.23 -abort
   64.24 -1 commit
   64.25 -expect contents3
   64.26 -read /test/entry1
   64.27 -
   64.28 -# Start transaction, do write op, transaction fails
   64.29 -1 start
   64.30 -1 write /test/entry1 contents4
   64.31 -write /test/entry1 contents
   64.32 -expect 1: commit failed: Resource temporarily unavailable
   64.33 -1 commit
   64.34 -expect contents
   64.35 -read /test/entry1
   64.36 -
   64.37 -# Start transaction, do other transaction, transaction fails
   64.38 -1 start
   64.39 -1 write /test/entry1 contents4
   64.40 -start
   64.41 -write /test/entry1 contents5
   64.42 -commit
   64.43 -expect 1: commit failed: Resource temporarily unavailable
   64.44 -1 commit
   64.45 -expect contents5
   64.46 -read /test/entry1
    65.1 --- a/tools/xenstore/testsuite/08transaction.test	Mon Jul 09 09:22:58 2007 -0600
    65.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    65.3 @@ -1,92 +0,0 @@
    65.4 -# Test transactions.
    65.5 -
    65.6 -mkdir /test
    65.7 -
    65.8 -# Simple transaction: create a file inside transaction.
    65.9 -1 start
   65.10 -1 write /test/entry1 contents
   65.11 -2 dir /test
   65.12 -expect 1:entry1
   65.13 -1 dir /test
   65.14 -1 commit
   65.15 -expect 2:contents
   65.16 -2 read /test/entry1
   65.17 -
   65.18 -rm /test/entry1
   65.19 -
   65.20 -# Create a file and abort transaction.
   65.21 -1 start
   65.22 -1 write /test/entry1 contents
   65.23 -2 dir /test
   65.24 -expect 1:entry1
   65.25 -1 dir /test
   65.26 -1 abort
   65.27 -2 dir /test
   65.28 -
   65.29 -write /test/entry1 contents
   65.30 -# Delete in transaction, commit
   65.31 -1 start
   65.32 -1 rm /test/entry1
   65.33 -expect 2:entry1
   65.34 -2 dir /test
   65.35 -1 dir /test
   65.36 -1 commit
   65.37 -2 dir /test
   65.38 -
   65.39 -# Delete in transaction, abort.
   65.40 -write /test/entry1 contents
   65.41 -1 start
   65.42 -1 rm /test/entry1
   65.43 -expect 2:entry1
   65.44 -2 dir /test
   65.45 -1 dir /test
   65.46 -1 abort
   65.47 -expect 2:entry1
   65.48 -2 dir /test
   65.49 -
   65.50 -# Events inside transactions don't trigger watches until (successful) commit.
   65.51 -mkdir /test/dir
   65.52 -1 watch /test token
   65.53 -2 start
   65.54 -2 mkdir /test/dir/sub
   65.55 -expect 1: waitwatch failed: Connection timed out
   65.56 -1 waitwatch
   65.57 -2 close
   65.58 -1 close
   65.59 -
   65.60 -1 watch /test token
   65.61 -2 start
   65.62 -2 mkdir /test/dir/sub
   65.63 -2 abort
   65.64 -expect 1: waitwatch failed: Connection timed out
   65.65 -1 waitwatch
   65.66 -1 close
   65.67 -
   65.68 -1 watch /test token
   65.69 -2 start
   65.70 -2 mkdir /test/dir/sub
   65.71 -2 commit
   65.72 -expect 1:/test/dir/sub:token
   65.73 -1 waitwatch
   65.74 -1 close
   65.75 -
   65.76 -# Rm inside transaction works like rm outside: children get notified.
   65.77 -1 watch /test/dir/sub token
   65.78 -2 start
   65.79 -2 rm /test/dir
   65.80 -2 commit
   65.81 -expect 1:/test/dir/sub:token
   65.82 -1 waitwatch
   65.83 -1 close
   65.84 -
   65.85 -# Multiple events from single transaction don't trigger assert
   65.86 -1 watch /test token
   65.87 -2 start
   65.88 -2 write /test/1 contents
   65.89 -2 write /test/2 contents
   65.90 -2 commit
   65.91 -expect 1:/test/1:token
   65.92 -1 waitwatch
   65.93 -expect 1:/test/2:token
   65.94 -1 waitwatch
   65.95 -1 close
    66.1 --- a/tools/xenstore/testsuite/09domain.test	Mon Jul 09 09:22:58 2007 -0600
    66.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    66.3 @@ -1,19 +0,0 @@
    66.4 -# Test domain communication.
    66.5 -
    66.6 -# Create a domain, write an entry.
    66.7 -expect handle is 1
    66.8 -introduce 1 100 7 /my/home
    66.9 -1 write /entry1 contents
   66.10 -expect entry1
   66.11 -expect tool
   66.12 -dir /
   66.13 -close
   66.14 -
   66.15 -# Release that domain.
   66.16 -release 1
   66.17 -close
   66.18 -
   66.19 -# Introduce and release by same connection.
   66.20 -expect handle is 2
   66.21 -introduce 1 100 7 /my/home
   66.22 -release 1
    67.1 --- a/tools/xenstore/testsuite/10domain-homedir.test	Mon Jul 09 09:22:58 2007 -0600
    67.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    67.3 @@ -1,18 +0,0 @@
    67.4 -# Test domain "implicit" paths.
    67.5 -
    67.6 -# Create a domain, write an entry using implicit path, read using implicit
    67.7 -mkdir /home
    67.8 -expect handle is 1
    67.9 -introduce 1 100 7 /home
   67.10 -1 write entry1 contents
   67.11 -expect contents
   67.12 -read /home/entry1
   67.13 -expect entry1
   67.14 -dir /home
   67.15 -
   67.16 -# Place a watch using a relative path: expect relative answer.
   67.17 -1 mkdir foo
   67.18 -1 watch foo token
   67.19 -write /home/foo/bar contents
   67.20 -expect 1:foo/bar:token
   67.21 -1 waitwatch
    68.1 --- a/tools/xenstore/testsuite/11domain-watch.test	Mon Jul 09 09:22:58 2007 -0600
    68.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    68.3 @@ -1,50 +0,0 @@
    68.4 -# Test watching from a domain.
    68.5 -
    68.6 -# Watch something, write to it, check watch has fired.
    68.7 -write /test contents
    68.8 -mkdir /dir
    68.9 -
   68.10 -expect handle is 1
   68.11 -introduce 1 100 7 /my/home
   68.12 -1 watch /test token
   68.13 -write /test contents2
   68.14 -expect 1:/test:token
   68.15 -1 waitwatch
   68.16 -1 unwatch /test token
   68.17 -release 1
   68.18 -1 close
   68.19 -
   68.20 -# ignore watches while doing commands, should work.
   68.21 -expect handle is 1
   68.22 -introduce 1 100 7 /my/home
   68.23 -1 watch /dir token
   68.24 -write /dir/test contents
   68.25 -1 write /dir/test2 contents2
   68.26 -1 write /dir/test3 contents3
   68.27 -1 write /dir/test4 contents4
   68.28 -expect 1:/dir/test:token
   68.29 -1 waitwatch
   68.30 -release 1
   68.31 -1 close
   68.32 -
   68.33 -# unwatch
   68.34 -expect handle is 1
   68.35 -introduce 1 100 7 /my/home
   68.36 -1 watch /dir token1
   68.37 -1 unwatch /dir token1
   68.38 -1 watch /dir token2
   68.39 -write /dir/test2 contents
   68.40 -expect 1:/dir/test2:token2
   68.41 -1 waitwatch
   68.42 -1 unwatch /dir token2
   68.43 -release 1
   68.44 -1 close
   68.45 -
   68.46 -# unwatch while watch pending.
   68.47 -expect handle is 1
   68.48 -introduce 1 100 7 /my/home
   68.49 -1 watch /dir token1
   68.50 -write /dir/test2 contents
   68.51 -1 unwatch /dir token1
   68.52 -release 1
   68.53 -1 close
    69.1 --- a/tools/xenstore/testsuite/12readonly.test	Mon Jul 09 09:22:58 2007 -0600
    69.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    69.3 @@ -1,38 +0,0 @@
    69.4 -# Test that read only connection can't alter store.
    69.5 -
    69.6 -write /test contents
    69.7 -
    69.8 -readonly
    69.9 -expect test
   69.10 -expect tool
   69.11 -dir /
   69.12 -
   69.13 -expect contents
   69.14 -read /test
   69.15 -expect 0 READ
   69.16 -getperm /test
   69.17 -watch /test token
   69.18 -unwatch /test token 
   69.19 -start
   69.20 -commit
   69.21 -start
   69.22 -abort
   69.23 -
   69.24 -# These don't work
   69.25 -expect write failed: Permission denied
   69.26 -write /test2 contents
   69.27 -expect write failed: Permission denied
   69.28 -write /test contents
   69.29 -expect setperm failed: Permission denied
   69.30 -setperm /test 100 NONE
   69.31 -expect setperm failed: Permission denied
   69.32 -setperm /test 100 NONE
   69.33 -expect introduce failed: Permission denied
   69.34 -introduce 1 100 7 /home
   69.35 -
   69.36 -# Check that watches work like normal.
   69.37 -watch / token
   69.38 -1 readwrite
   69.39 -1 write /test contents
   69.40 -expect /test:token
   69.41 -waitwatch
    70.1 --- a/tools/xenstore/testsuite/13watch-ack.test	Mon Jul 09 09:22:58 2007 -0600
    70.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    70.3 @@ -1,21 +0,0 @@
    70.4 -# This demonstrates a bug where an xs_acknowledge_watch returns
    70.5 -# EINVAL, because the daemon doesn't track what watch event it sent
    70.6 -# and relies on it being the "first" watch which has an event.
    70.7 -# Watches firing after the first event is sent out will change this.
    70.8 -
    70.9 -# Create three things to watch.
   70.10 -mkdir /test
   70.11 -mkdir /test/1
   70.12 -mkdir /test/2
   70.13 -mkdir /test/3
   70.14 -
   70.15 -# Watch all three, fire event on 2, read watch, fire event on 1 and 3, ack 2.
   70.16 -1 watch /test/1 token1
   70.17 -1 watch /test/2 token2
   70.18 -1 watch /test/3 token3
   70.19 -2 write /test/2 contents2
   70.20 -expect 1:/test/2:token2
   70.21 -1 waitwatch
   70.22 -3 write /test/1 contents1
   70.23 -4 write /test/3 contents3
   70.24 -1 close
    71.1 --- a/tools/xenstore/testsuite/14complexperms.test	Mon Jul 09 09:22:58 2007 -0600
    71.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    71.3 @@ -1,68 +0,0 @@
    71.4 -# We should not be able to tell the difference between a node which
    71.5 -# doesn't exist, and a node we don't have permission on, if we don't
    71.6 -# have permission on it directory.
    71.7 -
    71.8 -mkdir /dir
    71.9 -setperm /dir 0 NONE
   71.10 -
   71.11 -# First when it doesn't exist
   71.12 -setid 1
   71.13 -expect *Permission denied
   71.14 -dir /dir/file
   71.15 -expect *Permission denied
   71.16 -read /dir/file 
   71.17 -expect *Permission denied
   71.18 -write /dir/file value 
   71.19 -expect *Permission denied
   71.20 -mkdir /dir/file 
   71.21 -expect *Permission denied
   71.22 -rm /dir/file 
   71.23 -expect *Permission denied
   71.24 -rm /dir 
   71.25 -expect *Permission denied
   71.26 -getperm /dir/file 
   71.27 -expect *Permission denied
   71.28 -setperm /dir/file 0 NONE 
   71.29 -# We get no watch event when there's no permission.  It's a corner case.
   71.30 -watchnoack /dir/file token 
   71.31 -1 write /dir/file contents
   71.32 -1 rm /dir/file
   71.33 -expect waitwatch failed: Connection timed out
   71.34 -waitwatch
   71.35 -unwatch /dir/file token 
   71.36 -expect *No such file or directory
   71.37 -unwatch /dir/file token 
   71.38 -expect *Permission denied
   71.39 -introduce 2 100 7 /dir/file
   71.40 -
   71.41 -# Now it exists
   71.42 -setid 0
   71.43 -write /dir/file contents
   71.44 -
   71.45 -setid 1
   71.46 -expect *Permission denied
   71.47 -dir /dir/file
   71.48 -expect *Permission denied
   71.49 -read /dir/file 
   71.50 -expect *Permission denied
   71.51 -write /dir/file value 
   71.52 -expect *Permission denied
   71.53 -mkdir /dir/file 
   71.54 -expect *Permission denied
   71.55 -rm /dir/file 
   71.56 -expect *Permission denied
   71.57 -rm /dir 
   71.58 -expect *Permission denied
   71.59 -getperm /dir/file 
   71.60 -expect *Permission denied
   71.61 -setperm /dir/file 0 NONE 
   71.62 -watchnoack /dir/file token 
   71.63 -1 write /dir/file contents
   71.64 -1 rm /dir/file
   71.65 -expect waitwatch failed: Connection timed out
   71.66 -waitwatch
   71.67 -unwatch /dir/file token 
   71.68 -expect *No such file or directory
   71.69 -unwatch /dir/file token 
   71.70 -expect *Permission denied
   71.71 -introduce 2 100 7 /dir/file
    72.1 --- a/tools/xenstore/testsuite/test.sh	Mon Jul 09 09:22:58 2007 -0600
    72.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    72.3 @@ -1,64 +0,0 @@
    72.4 -#! /bin/sh
    72.5 -
    72.6 -set -e
    72.7 -set -m
    72.8 -
    72.9 -run_test()
   72.10 -{
   72.11 -    rm -rf $XENSTORED_ROOTDIR
   72.12 -    mkdir $XENSTORED_ROOTDIR
   72.13 -    if [ $VALGRIND -eq 1 ]; then
   72.14 -	valgrind --suppressions=testsuite/vg-suppressions -q ./xenstored_test --output-pid --trace-file=testsuite/tmp/trace --no-fork > /tmp/pid 2> testsuite/tmp/xenstored_errors &
   72.15 -	while [ ! -s /tmp/pid ]; do sleep 0; done
   72.16 -	PID=`cat /tmp/pid`
   72.17 -	rm /tmp/pid
   72.18 -    else
   72.19 -	# We don't get error messages from this, though. 
   72.20 -	PID=`./xenstored_test --output-pid --trace-file=testsuite/tmp/trace`
   72.21 -    fi
   72.22 -    if ./xs_test $2 $1; then
   72.23 -	if [ -s testsuite/tmp/xenstored_errors ]; then
   72.24 -	    kill $PID
   72.25 -	    echo Errors:
   72.26 -	    cat testsuite/tmp/xenstored_errors
   72.27 -	    return 1
   72.28 -	fi
   72.29 -	kill $PID
   72.30 -	sleep 1
   72.31 -	return 0
   72.32 -    else
   72.33 -	# In case daemon is wedged.
   72.34 -	kill $PID
   72.35 -	sleep 1
   72.36 -	return 1
   72.37 -    fi
   72.38 -}
   72.39 -
   72.40 -if [ x$1 = x--fast ]; then
   72.41 -    VALGRIND=0
   72.42 -    SLOWTESTS=""
   72.43 -    shift
   72.44 -else
   72.45 -    if type valgrind >/dev/null 2>&1; then
   72.46 -	VALGRIND=1
   72.47 -    else
   72.48 -	echo "WARNING: valgrind not available" >&2
   72.49 -	VALGRIND=0
   72.50 -    fi
   72.51 -    SLOWTESTS=testsuite/[0-9]*.slowtest
   72.52 -fi
   72.53 -
   72.54 -MATCH=${1:-"*"}
   72.55 -for f in testsuite/[0-9]*.test $SLOWTESTS; do
   72.56 -    case `basename $f` in $MATCH) RUN=1;; esac
   72.57 -    [ -n "$RUN" ] || continue
   72.58 -
   72.59 -    if run_test $f -x >/tmp/out; then
   72.60 -	echo -n .
   72.61 -    else
   72.62 -	cat /tmp/out
   72.63 -	# That will have filled the screen, repeat message.
   72.64 -	echo Test $f failed
   72.65 -	exit 1
   72.66 -    fi
   72.67 -done
    73.1 --- a/tools/xenstore/testsuite/vg-suppressions	Mon Jul 09 09:22:58 2007 -0600
    73.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    73.3 @@ -1,9 +0,0 @@
    73.4 -{
    73.5 -   Glibc goes boom from _start (Debian glibc 2.3.5-3)
    73.6 -   Memcheck:Cond
    73.7 -   obj:/lib/ld-2.3.5.so
    73.8 -   obj:/lib/ld-2.3.5.so
    73.9 -   obj:/lib/ld-2.3.5.so
   73.10 -   obj:/lib/ld-2.3.5.so
   73.11 -   obj:/lib/ld-2.3.5.so
   73.12 -}
    74.1 --- a/tools/xenstore/xenstored_core.c	Mon Jul 09 09:22:58 2007 -0600
    74.2 +++ b/tools/xenstore/xenstored_core.c	Tue Jul 10 08:39:26 2007 -0600
    74.3 @@ -39,7 +39,6 @@
    74.4  #include <assert.h>
    74.5  #include <setjmp.h>
    74.6  
    74.7 -//#define DEBUG
    74.8  #include "utils.h"
    74.9  #include "list.h"
   74.10  #include "talloc.h"
   74.11 @@ -53,7 +52,6 @@
   74.12  
   74.13  #include "hashtable.h"
   74.14  
   74.15 -
   74.16  extern int xce_handle; /* in xenstored_domain.c */
   74.17  
   74.18  static bool verbose = false;
   74.19 @@ -82,50 +80,6 @@ int quota_nb_watch_per_domain = 128;
   74.20  int quota_max_entry_size = 2048; /* 2K */
   74.21  int quota_max_transaction = 10;
   74.22  
   74.23 -#ifdef TESTING
   74.24 -static bool failtest = false;
   74.25 -
   74.26 -/* We override talloc's malloc. */
   74.27 -void *test_malloc(size_t size)
   74.28 -{
   74.29 -	/* 1 in 20 means only about 50% of connections establish. */
   74.30 -	if (failtest && (random() % 32) == 0)
   74.31 -		return NULL;
   74.32 -	return malloc(size);
   74.33 -}
   74.34 -
   74.35 -static void stop_failtest(int signum __attribute__((unused)))
   74.36 -{
   74.37 -	failtest = false;
   74.38 -}
   74.39 -
   74.40 -/* Need these before we #define away write_all/mkdir in testing.h */
   74.41 -bool test_write_all(int fd, void *contents, unsigned int len);
   74.42 -bool test_write_all(int fd, void *contents, unsigned int len)
   74.43 -{
   74.44 -	if (failtest && (random() % 8) == 0) {
   74.45 -		if (len)
   74.46 -			len = random() % len;
   74.47 -		write(fd, contents, len);
   74.48 -		errno = ENOSPC;
   74.49 -		return false;
   74.50 -	}
   74.51 -	return xs_write_all(fd, contents, len);
   74.52 -}
   74.53 -
   74.54 -int test_mkdir(const char *dir, int perms);
   74.55 -int test_mkdir(const char *dir, int perms)
   74.56 -{
   74.57 -	if (failtest && (random() % 8) == 0) {
   74.58 -		errno = ENOSPC;
   74.59 -		return -1;
   74.60 -	}
   74.61 -	return mkdir(dir, perms);
   74.62 -}
   74.63 -#endif /* TESTING */
   74.64 -
   74.65 -#include "xenstored_test.h"
   74.66 -
   74.67  TDB_CONTEXT *tdb_context(struct connection *conn)
   74.68  {
   74.69  	/* conn = NULL used in manual_node at setup. */
   74.70 @@ -1163,12 +1117,10 @@ static void do_debug(struct connection *
   74.71  {
   74.72  	int num;
   74.73  
   74.74 -#ifndef TESTING
   74.75  	if (conn->id != 0) {
   74.76  		send_error(conn, EACCES);
   74.77  		return;
   74.78  	}
   74.79 -#endif
   74.80  
   74.81  	num = xs_count_strings(in->buffer, in->used);
   74.82  
   74.83 @@ -1179,18 +1131,10 @@ static void do_debug(struct connection *
   74.84  		}
   74.85  		xprintf("debug: %s", in->buffer + get_string(in, 0));
   74.86  	}
   74.87 +
   74.88  	if (streq(in->buffer, "check"))
   74.89  		check_store();
   74.90 -#ifdef TESTING
   74.91 -	/* For testing, we allow them to set id. */
   74.92 -	if (streq(in->buffer, "setid")) {
   74.93 -		conn->id = atoi(in->buffer + get_string(in, 0));
   74.94 -	} else if (streq(in->buffer, "failtest")) {
   74.95 -		if (get_string(in, 0) < in->used)
   74.96 -			srandom(atoi(in->buffer + get_string(in, 0)));
   74.97 -		failtest = true;
   74.98 -	}
   74.99 -#endif /* TESTING */
  74.100 +
  74.101  	send_ack(conn, XS_DEBUG);
  74.102  }
  74.103  
  74.104 @@ -1319,10 +1263,8 @@ static void handle_input(struct connecti
  74.105  			return;
  74.106  
  74.107  		if (in->hdr.msg.len > PATH_MAX) {
  74.108 -#ifndef TESTING
  74.109  			syslog(LOG_ERR, "Client tried to feed us %i",
  74.110  			       in->hdr.msg.len);
  74.111 -#endif
  74.112  			goto bad_client;
  74.113  		}
  74.114  
  74.115 @@ -1414,39 +1356,7 @@ static void accept_connection(int sock, 
  74.116  		close(fd);
  74.117  }
  74.118  
  74.119 -#ifdef TESTING
  74.120 -/* Valgrind can check our writes better if we don't use mmap */
  74.121 -#define TDB_FLAGS TDB_NOMMAP
  74.122 -/* Useful for running under debugger. */
  74.123 -void dump_connection(void)
  74.124 -{
  74.125 -	struct connection *i;
  74.126 -
  74.127 -	list_for_each_entry(i, &connections, list) {
  74.128 -		printf("Connection %p:\n", i);
  74.129 -		printf("    state = %s\n",
  74.130 -		       list_empty(&i->out_list) ? "OK" : "BUSY");
  74.131 -		if (i->id)
  74.132 -			printf("    id = %i\n", i->id);
  74.133 -		if (!i->in->inhdr || i->in->used)
  74.134 -			printf("    got %i bytes of %s\n",
  74.135 -			       i->in->used, i->in->inhdr ? "header" : "data");
  74.136 -#if 0
  74.137 -		if (i->out)
  74.138 -			printf("    sending message %s (%s) out\n",
  74.139 -			       sockmsg_string(i->out->hdr.msg.type),
  74.140 -			       i->out->buffer);
  74.141 -		if (i->transaction)
  74.142 -			dump_transaction(i);
  74.143 -		if (i->domain)
  74.144 -			dump_domain(i);
  74.145 -#endif
  74.146 -		dump_watches(i);
  74.147 -	}
  74.148 -}
  74.149 -#else
  74.150  #define TDB_FLAGS 0
  74.151 -#endif
  74.152  
  74.153  /* We create initial nodes manually. */
  74.154  static void manual_node(const char *name, const char *child)
  74.155 @@ -1693,10 +1603,6 @@ static void corrupt(struct connection *c
  74.156  	log("corruption detected by connection %i: err %s: %s",
  74.157  	    conn ? (int)conn->id : -1, strerror(saved_errno), str);
  74.158  
  74.159 -#ifdef TESTING
  74.160 -	/* Allow them to attach debugger. */
  74.161 -	sleep(30);
  74.162 -#endif
  74.163  	check_store();
  74.164  }
  74.165  
  74.166 @@ -1740,11 +1646,10 @@ static void daemonize(void)
  74.167  	if (pid != 0)
  74.168  		exit(0);
  74.169  
  74.170 -#ifndef TESTING	/* Relative paths for socket names */
  74.171  	/* Move off any mount points we might be in. */
  74.172  	if (chdir("/") == -1)
  74.173  		barf_perror("Failed to chdir");
  74.174 -#endif
  74.175 +
  74.176  	/* Discard our parent's old-fashioned umask prejudices. */
  74.177  	umask(0);
  74.178  }
  74.179 @@ -1941,10 +1846,6 @@ int main(int argc, char *argv[])
  74.180  
  74.181  	signal(SIGHUP, trigger_reopen_log);
  74.182  
  74.183 -#ifdef TESTING
  74.184 -	signal(SIGUSR1, stop_failtest);
  74.185 -#endif
  74.186 -
  74.187  	if (xce_handle != -1)
  74.188  		evtchn_fd = xc_evtchn_fd(xce_handle);
  74.189  
    75.1 --- a/tools/xenstore/xenstored_domain.c	Mon Jul 09 09:22:58 2007 -0600
    75.2 +++ b/tools/xenstore/xenstored_domain.c	Tue Jul 10 08:39:26 2007 -0600
    75.3 @@ -23,14 +23,12 @@
    75.4  #include <stdlib.h>
    75.5  #include <stdarg.h>
    75.6  
    75.7 -//#define DEBUG
    75.8  #include "utils.h"
    75.9  #include "talloc.h"
   75.10  #include "xenstored_core.h"
   75.11  #include "xenstored_domain.h"
   75.12  #include "xenstored_transaction.h"
   75.13  #include "xenstored_watch.h"
   75.14 -#include "xenstored_test.h"
   75.15  
   75.16  #include <xenctrl.h>
   75.17  
   75.18 @@ -217,10 +215,8 @@ void handle_event(void)
   75.19  	if (port == virq_port)
   75.20  		domain_cleanup();
   75.21  
   75.22 -#ifndef TESTING
   75.23  	if (xc_evtchn_unmask(xce_handle, port) == -1)
   75.24  		barf_perror("Failed to write to event fd");
   75.25 -#endif
   75.26  }
   75.27  
   75.28  bool domain_can_read(struct connection *conn)
    76.1 --- a/tools/xenstore/xenstored_test.h	Mon Jul 09 09:22:58 2007 -0600
    76.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    76.3 @@ -1,37 +0,0 @@
    76.4 -/* 
    76.5 -    Testing replcements for Xen Store Daemon.
    76.6 -    Copyright (C) 2005 Rusty Russell IBM Corporation
    76.7 -
    76.8 -    This program is free software; you can redistribute it and/or modify
    76.9 -    it under the terms of the GNU General Public License as published by
   76.10 -    the Free Software Foundation; either version 2 of the License, or
   76.11 -    (at your option) any later version.
   76.12 -
   76.13 -    This program is distributed in the hope that it will be useful,
   76.14 -    but WITHOUT ANY WARRANTY; without even the implied warranty of
   76.15 -    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   76.16 -    GNU General Public License for more details.
   76.17 -
   76.18 -    You should have received a copy of the GNU General Public License
   76.19 -    along with this program; if not, write to the Free Software
   76.20 -    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
   76.21 -*/
   76.22 -#ifndef _XENSTORED_TEST_H
   76.23 -#define _XENSTORED_TEST_H
   76.24 -
   76.25 -#ifdef TESTING
   76.26 -bool test_write_all(int fd, void *contents, unsigned int len);
   76.27 -#define xs_write_all test_write_all
   76.28 -
   76.29 -int test_mkdir(const char *dir, int perms);
   76.30 -#define mkdir test_mkdir
   76.31 -
   76.32 -int fake_open_eventchn(void);
   76.33 -void fake_block_events(void);
   76.34 -void fake_ack_event(void);
   76.35 -
   76.36 -#define ioctl(a,b,c) 0
   76.37 -
   76.38 -#endif
   76.39 -
   76.40 -#endif /* _XENSTORED_INTERNAL_H */
    77.1 --- a/tools/xenstore/xenstored_transaction.c	Mon Jul 09 09:22:58 2007 -0600
    77.2 +++ b/tools/xenstore/xenstored_transaction.c	Tue Jul 10 08:39:26 2007 -0600
    77.3 @@ -35,7 +35,6 @@
    77.4  #include "xenstored_domain.h"
    77.5  #include "xs_lib.h"
    77.6  #include "utils.h"
    77.7 -#include "xenstored_test.h"
    77.8  
    77.9  struct changed_node
   77.10  {
    78.1 --- a/tools/xenstore/xenstored_watch.c	Mon Jul 09 09:22:58 2007 -0600
    78.2 +++ b/tools/xenstore/xenstored_watch.c	Tue Jul 10 08:39:26 2007 -0600
    78.3 @@ -29,7 +29,6 @@
    78.4  #include "xenstored_watch.h"
    78.5  #include "xs_lib.h"
    78.6  #include "utils.h"
    78.7 -#include "xenstored_test.h"
    78.8  #include "xenstored_domain.h"
    78.9  
   78.10  extern int quota_nb_watch_per_domain;
   78.11 @@ -196,17 +195,6 @@ void conn_delete_all_watches(struct conn
   78.12  	}
   78.13  }
   78.14  
   78.15 -#ifdef TESTING
   78.16 -void dump_watches(struct connection *conn)
   78.17 -{
   78.18 -	struct watch *watch;
   78.19 -
   78.20 -	list_for_each_entry(watch, &conn->watches, list)
   78.21 -		printf("    watch on %s token %s\n",
   78.22 -		       watch->node, watch->token);
   78.23 -}
   78.24 -#endif
   78.25 -
   78.26  /*
   78.27   * Local variables:
   78.28   *  c-file-style: "linux"
    79.1 --- a/tools/xenstore/xs_crashme.c	Mon Jul 09 09:22:58 2007 -0600
    79.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    79.3 @@ -1,393 +0,0 @@
    79.4 -/* Code which randomly corrupts bits going to the daemon.
    79.5 -    Copyright (C) 2005 Rusty Russell IBM Corporation
    79.6 -
    79.7 -    This program is free software; you can redistribute it and/or modify
    79.8 -    it under the terms of the GNU General Public License as published by
    79.9 -    the Free Software Foundation; either version 2 of the License, or
   79.10 -    (at your option) any later version.
   79.11 -
   79.12 -    This program is distributed in the hope that it will be useful,
   79.13 -    but WITHOUT ANY WARRANTY; without even the implied warranty of
   79.14 -    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   79.15 -    GNU General Public License for more details.
   79.16 -
   79.17 -    You should have received a copy of the GNU General Public License
   79.18 -    along with this program; if not, write to the Free Software
   79.19 -    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
   79.20 -*/
   79.21 -#include <stdbool.h>
   79.22 -#include <stdio.h>
   79.23 -#include <sys/types.h>
   79.24 -#include <stdarg.h>
   79.25 -#include <string.h>
   79.26 -#include <sys/time.h>
   79.27 -#include "xs.h"
   79.28 -#include "talloc.h"
   79.29 -#include <errno.h>
   79.30 -
   79.31 -#define XSTEST
   79.32 -#define RAND_FREQ 128 		/* One char in 32 is corrupted. */
   79.33 -
   79.34 -/* jhash.h: Jenkins hash support.
   79.35 - *
   79.36 - * Copyright (C) 1996 Bob Jenkins (bob_jenkins@burtleburtle.net)
   79.37 - *
   79.38 - * http://burtleburtle.net/bob/hash/
   79.39 - *
   79.40 - * These are the credits from Bob's sources:
   79.41 - *
   79.42 - * lookup2.c, by Bob Jenkins, December 1996, Public Domain.
   79.43 - * hash(), hash2(), hash3, and mix() are externally useful functions.
   79.44 - * Routines to test the hash are included if SELF_TEST is defined.
   79.45 - * You can use this free for any purpose.  It has no warranty.
   79.46 - *
   79.47 - * Copyright (C) 2003 David S. Miller (davem@redhat.com)
   79.48 - *
   79.49 - * I've modified Bob's hash to be useful in the Linux kernel, and
   79.50 - * any bugs present are surely my fault.  -DaveM
   79.51 - */
   79.52 -
   79.53 -/* NOTE: Arguments are modified. */
   79.54 -#define __jhash_mix(a, b, c) \
   79.55 -{ \
   79.56 -  a -= b; a -= c; a ^= (c>>13); \
   79.57 -  b -= c; b -= a; b ^= (a<<8); \
   79.58 -  c -= a; c -= b; c ^= (b>>13); \
   79.59 -  a -= b; a -= c; a ^= (c>>12);  \
   79.60 -  b -= c; b -= a; b ^= (a<<16); \
   79.61 -  c -= a; c -= b; c ^= (b>>5); \
   79.62 -  a -= b; a -= c; a ^= (c>>3);  \
   79.63 -  b -= c; b -= a; b ^= (a<<10); \
   79.64 -  c -= a; c -= b; c ^= (b>>15); \
   79.65 -}
   79.66 -
   79.67 -/* The golden ration: an arbitrary value */
   79.68 -#define JHASH_GOLDEN_RATIO	0x9e3779b9
   79.69 -
   79.70 -/* The most generic version, hashes an arbitrary sequence
   79.71 - * of bytes.  No alignment or length assumptions are made about
   79.72 - * the input key.
   79.73 - */
   79.74 -static inline uint32_t jhash(const void *key, uint32_t length, uint32_t initval)
   79.75 -{
   79.76 -	uint32_t a, b, c, len;
   79.77 -	const uint8_t *k = key;
   79.78 -
   79.79 -	len = length;
   79.80 -	a = b = JHASH_GOLDEN_RATIO;
   79.81 -	c = initval;
   79.82 -
   79.83 -	while (len >= 12) {
   79.84 -		a += (k[0] +((uint32_t)k[1]<<8) +((uint32_t)k[2]<<16) +((uint32_t)k[3]<<24));
   79.85 -		b += (k[4] +((uint32_t)k[5]<<8) +((uint32_t)k[6]<<16) +((uint32_t)k[7]<<24));
   79.86 -		c += (k[8] +((uint32_t)k[9]<<8) +((uint32_t)k[10]<<16)+((uint32_t)k[11]<<24));
   79.87 -
   79.88 -		__jhash_mix(a,b,c);
   79.89 -
   79.90 -		k += 12;
   79.91 -		len -= 12;
   79.92 -	}
   79.93 -
   79.94 -	c += length;
   79.95 -	switch (len) {
   79.96 -	case 11: c += ((uint32_t)k[10]<<24);
   79.97 -	case 10: c += ((uint32_t)k[9]<<16);
   79.98 -	case 9 : c += ((uint32_t)k[8]<<8);
   79.99 -	case 8 : b += ((uint32_t)k[7]<<24);
  79.100 -	case 7 : b += ((uint32_t)k[6]<<16);
  79.101 -	case 6 : b += ((uint32_t)k[5]<<8);
  79.102 -	case 5 : b += k[4];
  79.103 -	case 4 : a += ((uint32_t)k[3]<<24);
  79.104 -	case 3 : a += ((uint32_t)k[2]<<16);
  79.105 -	case 2 : a += ((uint32_t)k[1]<<8);
  79.106 -	case 1 : a += k[0];
  79.107 -	};
  79.108 -
  79.109 -	__jhash_mix(a,b,c);
  79.110 -
  79.111 -	return c;
  79.112 -}
  79.113 -
  79.114 -/* A special optimized version that handles 1 or more of uint32_ts.
  79.115 - * The length parameter here is the number of uint32_ts in the key.
  79.116 - */
  79.117 -static inline uint32_t jhash2(uint32_t *k, uint32_t length, uint32_t initval)
  79.118 -{
  79.119 -	uint32_t a, b, c, len;
  79.120 -
  79.121 -	a = b = JHASH_GOLDEN_RATIO;
  79.122 -	c = initval;
  79.123 -	len = length;
  79.124 -
  79.125 -	while (len >= 3) {
  79.126 -		a += k[0];
  79.127 -		b += k[1];
  79.128 -		c += k[2];
  79.129 -		__jhash_mix(a, b, c);
  79.130 -		k += 3; len -= 3;
  79.131 -	}
  79.132 -
  79.133 -	c += length * 4;
  79.134 -
  79.135 -	switch (len) {
  79.136 -	case 2 : b += k[1];
  79.137 -	case 1 : a += k[0];
  79.138 -	};
  79.139 -
  79.140 -	__jhash_mix(a,b,c);
  79.141 -
  79.142 -	return c;
  79.143 -}
  79.144 -
  79.145 -
  79.146 -/* A special ultra-optimized versions that knows they are hashing exactly
  79.147 - * 3, 2 or 1 word(s).
  79.148 - *
  79.149 - * NOTE: In partilar the "c += length; __jhash_mix(a,b,c);" normally
  79.150 - *       done at the end is not done here.
  79.151 - */
  79.152 -static inline uint32_t jhash_3words(uint32_t a, uint32_t b, uint32_t c, uint32_t initval)
  79.153 -{
  79.154 -	a += JHASH_GOLDEN_RATIO;
  79.155 -	b += JHASH_GOLDEN_RATIO;
  79.156 -	c += initval;
  79.157 -
  79.158 -	__jhash_mix(a, b, c);
  79.159 -
  79.160 -	return c;
  79.161 -}
  79.162 -
  79.163 -static inline uint32_t jhash_2words(uint32_t a, uint32_t b, uint32_t initval)
  79.164 -{
  79.165 -	return jhash_3words(a, b, 0, initval);
  79.166 -}
  79.167 -
  79.168 -static inline uint32_t jhash_1word(uint32_t a, uint32_t initval)
  79.169 -{
  79.170 -	return jhash_3words(a, 0, 0, initval);
  79.171 -}
  79.172 -
  79.173 -static unsigned int get_randomness(int *state)
  79.174 -{
  79.175 -	return jhash_1word((*state)++, *state * 1103515243);
  79.176 -}
  79.177 -
  79.178 -static int state;
  79.179 -
  79.180 -/* Lengthening headers is pointless: other end will just wait for more
  79.181 - * data and timeout.  We merely shorten the length. */
  79.182 -static void corrupt_header(char *output, const struct xsd_sockmsg *msg,
  79.183 -			   unsigned int *next_bit)
  79.184 -{
  79.185 -	struct xsd_sockmsg newmsg = *msg;
  79.186 -
  79.187 -	while (*next_bit < sizeof(*msg)) {
  79.188 -		if (newmsg.len)
  79.189 -			newmsg.len = get_randomness(&state) % newmsg.len;
  79.190 -		*next_bit += get_randomness(&state) % RAND_FREQ;
  79.191 -	}
  79.192 -	memcpy(output, &newmsg, sizeof(newmsg));
  79.193 -}
  79.194 -
  79.195 -#define read_all_choice read_all
  79.196 -static bool write_all_choice(int fd, const void *data, unsigned int len)
  79.197 -{
  79.198 -	char corrupt_data[len];
  79.199 -	bool ret;
  79.200 -	static unsigned int next_bit;
  79.201 -
  79.202 -	if (len == sizeof(struct xsd_sockmsg)
  79.203 -	    && ((unsigned long)data % __alignof__(struct xsd_sockmsg)) == 0)
  79.204 -		corrupt_header(corrupt_data, data, &next_bit);
  79.205 -	else {
  79.206 -		memcpy(corrupt_data, data, len);
  79.207 -		while (next_bit < len * CHAR_BIT) {
  79.208 -			corrupt_data[next_bit/CHAR_BIT]
  79.209 -				^= (1 << (next_bit%CHAR_BIT));
  79.210 -			next_bit += get_randomness(&state) % RAND_FREQ;
  79.211 -		}
  79.212 -	}
  79.213 -
  79.214 -	ret = xs_write_all(fd, corrupt_data, len);
  79.215 -	next_bit -= len * CHAR_BIT;
  79.216 -	return ret;
  79.217 -}
  79.218 -
  79.219 -#include "xs.c"
  79.220 -
  79.221 -static char *random_path(void)
  79.222 -{
  79.223 -	unsigned int i;
  79.224 -	char *ret = NULL;
  79.225 -
  79.226 -	if (get_randomness(&state) % 20 == 0)
  79.227 -		return talloc_strdup(NULL, "/");
  79.228 -
  79.229 -	for (i = 0; i < 1 || (get_randomness(&state) % 2); i++) {
  79.230 -		ret = talloc_asprintf_append(ret, "/%i", 
  79.231 -					     get_randomness(&state) % 15);
  79.232 -	}
  79.233 -	return ret;
  79.234 -}
  79.235 -
  79.236 -/* Do the next operation, return the results. */
  79.237 -static void do_next_op(struct xs_handle *h, bool verbose)
  79.238 -{
  79.239 -	char *name;
  79.240 -	unsigned int num;
  79.241 -
  79.242 -	if (verbose)
  79.243 -		printf("State %i: ", state);
  79.244 -
  79.245 -	name = random_path();
  79.246 -	switch (get_randomness(&state) % 9) {
  79.247 -	case 0:
  79.248 -		if (verbose)
  79.249 -			printf("DIR %s\n", name);
  79.250 -		free(xs_directory(h, name, &num));
  79.251 -		break;
  79.252 -	case 1:
  79.253 -		if (verbose)
  79.254 -			printf("READ %s\n", name);
  79.255 -		free(xs_read(h, name, &num));
  79.256 -		break;
  79.257 -	case 2: {
  79.258 -		char *contents = talloc_asprintf(NULL, "%i",
  79.259 -						 get_randomness(&state));
  79.260 -		unsigned int len = get_randomness(&state)%(strlen(contents)+1);
  79.261 -		if (verbose)
  79.262 -			printf("WRITE %s %.*s\n", name, len, contents);
  79.263 -		xs_write(h, name, contents, len);
  79.264 -		break;
  79.265 -	}
  79.266 -	case 3:
  79.267 -		if (verbose)
  79.268 -			printf("MKDIR %s\n", name);
  79.269 -		xs_mkdir(h, name);
  79.270 -		break;
  79.271 -	case 4:
  79.272 -		if (verbose)
  79.273 -			printf("RM %s\n", name);
  79.274 -		xs_rm(h, name);
  79.275 -		break;
  79.276 -	case 5:
  79.277 -		if (verbose)
  79.278 -			printf("GETPERMS %s\n", name);
  79.279 -		free(xs_get_permissions(h, name, &num));
  79.280 -		break;
  79.281 -	case 6: {
  79.282 -		unsigned int i, num = get_randomness(&state)%8;
  79.283 -		struct xs_permissions perms[num];
  79.284 -
  79.285 -		if (verbose)
  79.286 -			printf("SETPERMS %s: ", name);
  79.287 -		for (i = 0; i < num; i++) {
  79.288 -			perms[i].id = get_randomness(&state)%8;
  79.289 -			perms[i].perms = get_randomness(&state)%4;
  79.290 -			if (verbose)
  79.291 -				printf("%i%c ", perms[i].id,
  79.292 -				       perms[i].perms == XS_PERM_WRITE ? 'W'
  79.293 -				       : perms[i].perms == XS_PERM_READ ? 'R'
  79.294 -				       : perms[i].perms == 
  79.295 -				       (XS_PERM_READ|XS_PERM_WRITE) ? 'B'
  79.296 -				       : 'N');
  79.297 -		}
  79.298 -		if (verbose)
  79.299 -			printf("\n");
  79.300 -		xs_set_permissions(h, name, perms, num);
  79.301 -		break;
  79.302 -	}
  79.303 -	case 7: {
  79.304 -		if (verbose)
  79.305 -			printf("START %s\n", name);
  79.306 -		xs_transaction_start(h);
  79.307 -		break;
  79.308 -	}
  79.309 -	case 8: {
  79.310 -		bool abort = (get_randomness(&state) % 2);
  79.311 -
  79.312 -		if (verbose)
  79.313 -			printf("STOP %s\n", abort ? "ABORT" : "COMMIT");
  79.314 -		xs_transaction_end(h, abort);
  79.315 -		break;
  79.316 -	}
  79.317 -	default:
  79.318 -		barf("Impossible randomness");
  79.319 -	}
  79.320 -}
  79.321 -
  79.322 -static struct xs_handle *h;
  79.323 -static void alarmed(int sig __attribute__((unused)))
  79.324 -{
  79.325 -	/* We force close on timeout. */
  79.326 -	close(h->fd);
  79.327 -}
  79.328 -
  79.329 -static int start_daemon(void)
  79.330 -{
  79.331 -	int fds[2];
  79.332 -	int daemon_pid;
  79.333 -
  79.334 -	/* Start daemon. */
  79.335 -	pipe(fds);
  79.336 -	if ((daemon_pid = fork())) {
  79.337 -		/* Child writes PID when its ready: we wait for that. */
  79.338 -		char buffer[20];
  79.339 -		close(fds[1]);
  79.340 -		if (read(fds[0], buffer, sizeof(buffer)) < 0)
  79.341 -			barf("Failed to summon daemon");
  79.342 -		close(fds[0]);
  79.343 -		return daemon_pid;
  79.344 -	} else {
  79.345 -		dup2(fds[1], STDOUT_FILENO);
  79.346 -		close(fds[0]);
  79.347 -#if 1
  79.348 -		execlp("valgrind", "valgrind", "--log-file=/tmp/xs_crashme.vglog", "-q", "./xenstored_test", "--output-pid",
  79.349 -		       "--no-fork", "--trace-file=/tmp/trace", NULL);
  79.350 -#else
  79.351 -		execlp("./xenstored_test", "xenstored_test", "--output-pid",
  79.352 -		       "--no-fork", NULL);
  79.353 -#endif
  79.354 -		exit(1);
  79.355 -	}
  79.356 -}
  79.357 -
  79.358 -
  79.359 -int main(int argc, char **argv)
  79.360 -{
  79.361 -	unsigned int i;
  79.362 -	int pid;
  79.363 -
  79.364 -	if (argc != 3 && argc != 4)
  79.365 -		barf("Usage: xs_crashme <iterations> <seed> [pid]");
  79.366 -
  79.367 -	if (argc == 3)
  79.368 -		pid = start_daemon();
  79.369 -	else
  79.370 -		pid = atoi(argv[3]);
  79.371 -
  79.372 -	state = atoi(argv[2]);
  79.373 -	h = xs_daemon_open();
  79.374 -	if (!h)
  79.375 -		barf_perror("Opening connection to daemon");
  79.376 -	signal(SIGALRM, alarmed);
  79.377 -	for (i = 0; i < (unsigned)atoi(argv[1]); i++) {
  79.378 -		alarm(1);
  79.379 -		do_next_op(h, false);
  79.380 -		if (i % (atoi(argv[1]) / 72 ?: 1) == 0) {
  79.381 -			printf(".");
  79.382 -			fflush(stdout);
  79.383 -		}
  79.384 -		if (kill(pid, 0) != 0)
  79.385 -			barf_perror("Pinging daemon on iteration %i", i);
  79.386 -		if (h->fd < 0) {
  79.387 -			xs_daemon_close(h);
  79.388 -			h = xs_daemon_open();
  79.389 -			if (!h)
  79.390 -				barf_perror("Connecting on iteration %i", i);
  79.391 -		}
  79.392 -	}
  79.393 -	kill(pid, SIGTERM);
  79.394 -	return 0;
  79.395 -}
  79.396 -
    80.1 --- a/tools/xenstore/xs_random.c	Mon Jul 09 09:22:58 2007 -0600
    80.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    80.3 @@ -1,1590 +0,0 @@
    80.4 -/* Random tests.
    80.5 -
    80.6 -   We check that the results from a real filesystem are the same.
    80.7 -*/
    80.8 -#include <sys/types.h>
    80.9 -#include <stdio.h>
   80.10 -#include <stdarg.h>
   80.11 -#include <stdlib.h>
   80.12 -#include <dirent.h>
   80.13 -#include <errno.h>
   80.14 -#include <sys/stat.h>
   80.15 -#include <unistd.h>
   80.16 -#include <fcntl.h>
   80.17 -#include <signal.h>
   80.18 -#include <sys/wait.h>
   80.19 -#include "xs.h"
   80.20 -#include "talloc.h"
   80.21 -#include "utils.h"
   80.22 -
   80.23 -struct ops
   80.24 -{
   80.25 -	char *name;
   80.26 -
   80.27 -	char **(*dir)(void *h, const char *path, unsigned int *num);
   80.28 -
   80.29 -	void *(*read)(void *h, const char *path, unsigned int *len);
   80.30 -
   80.31 -	bool (*write)(void *h, const char *path, const void *data,
   80.32 -		      unsigned int len);
   80.33 -
   80.34 -	bool (*mkdir)(void *h, const char *path);
   80.35 -
   80.36 -	bool (*rm)(void *h, const char *path);
   80.37 -
   80.38 -	struct xs_permissions *(*get_perms)(void *h,
   80.39 -					    const char *path,
   80.40 -					    unsigned int *num);
   80.41 -
   80.42 -	bool (*set_perms)(void *h,
   80.43 -			  const char *path,
   80.44 -			  struct xs_permissions *perms,
   80.45 -			  unsigned int num);
   80.46 -
   80.47 -	bool (*transaction_start)(void *h);
   80.48 -	bool (*transaction_end)(void *h, bool abort);
   80.49 -
   80.50 -	/* Create and destroy a new handle. */
   80.51 -	void *(*handle)(const char *path);
   80.52 -	void (*close)(void *);
   80.53 -};
   80.54 -
   80.55 -struct file_ops_info
   80.56 -{
   80.57 -	const char *base;
   80.58 -	char *transact_base;
   80.59 -};
   80.60 -
   80.61 -static void convert_to_dir(const char *dirname)
   80.62 -{
   80.63 -	char *tmpname = talloc_asprintf(dirname, "%s.tmp", dirname);
   80.64 -	if (rename(dirname, tmpname) != 0)
   80.65 -		barf_perror("Failed to rename %s to %s", dirname, tmpname);
   80.66 -	if (mkdir(dirname, 0700) != 0) 
   80.67 -		barf_perror("Failed to mkdir %s", dirname);
   80.68 -	if (rename(tmpname,talloc_asprintf(dirname, "%s/.DATA", dirname)) != 0)
   80.69 -		barf_perror("Failed to rename into %s", dirname);
   80.70 -	/* If perms exists, move it in. */
   80.71 -	rename(talloc_asprintf(dirname, "%s.perms", dirname),
   80.72 -	       talloc_asprintf(dirname, "%s/.perms", dirname));
   80.73 -}
   80.74 -
   80.75 -/* Files can be used as dirs, too.  Convert them when they are. */
   80.76 -static void maybe_convert_to_directory(const char *filename)
   80.77 -{
   80.78 -	struct stat st;
   80.79 -	char *dirname = talloc_asprintf(
   80.80 -		filename, "%.*s",
   80.81 -		(int)(strrchr(filename, '/') - filename), filename);
   80.82 -	if (lstat(dirname, &st) == 0 && S_ISREG(st.st_mode))
   80.83 -		convert_to_dir(dirname);
   80.84 -}
   80.85 -
   80.86 -static char *get_name(struct file_ops_info *info, const char *path)
   80.87 -{
   80.88 -	if (info->transact_base)
   80.89 -		return talloc_asprintf(path, "%s%s", info->transact_base,
   80.90 -				       path);
   80.91 -	return talloc_asprintf(path, "%s%s", info->base, path);
   80.92 -}
   80.93 -
   80.94 -static char *path_to_name(struct file_ops_info *info, const char *path)
   80.95 -{
   80.96 -	char *filename = get_name(info, path);
   80.97 -	maybe_convert_to_directory(filename);
   80.98 -	return filename;
   80.99 -}
  80.100 -
  80.101 -static char **file_directory(struct file_ops_info *info,
  80.102 -			     const char *path, unsigned int *num)
  80.103 -{
  80.104 -	char **ret;
  80.105 -	DIR *dir;
  80.106 -	struct dirent *dirent;
  80.107 -	char *p, *dirname = path_to_name(info, path);
  80.108 -	unsigned int i, len = 0;
  80.109 -	struct stat st;
  80.110 -
  80.111 -	/* If it exists, but isn't a directory, we convert it. */
  80.112 -	if (lstat(dirname, &st) == 0 && !S_ISDIR(st.st_mode))
  80.113 -		convert_to_dir(dirname);
  80.114 -
  80.115 -	*num = 0;
  80.116 -	dir = opendir(dirname);
  80.117 -	if (!dir)
  80.118 -		return NULL;;
  80.119 -
  80.120 -	/* Once to count them. */
  80.121 -	while ((dirent = readdir(dir)) != NULL) {
  80.122 -		if (strchr(dirent->d_name, '.'))
  80.123 -			continue;
  80.124 -		len += strlen(dirent->d_name) + 1;
  80.125 -		(*num)++;
  80.126 -	}
  80.127 -	rewinddir(dir);
  80.128 -
  80.129 -	/* Now allocate and fill in. */
  80.130 -	ret = malloc(sizeof(char *) * *num + len);
  80.131 -	p = (char *)&ret[*num];
  80.132 -	i = 0;
  80.133 -	while ((dirent = readdir(dir)) != NULL) {
  80.134 -		if (strchr(dirent->d_name, '.'))
  80.135 -			continue;
  80.136 -		ret[i] = p;
  80.137 -		strcpy(p, dirent->d_name);
  80.138 -		p += strlen(p) + 1;
  80.139 -		i++;
  80.140 -	}
  80.141 -	closedir(dir);
  80.142 -
  80.143 -	return ret;
  80.144 -}
  80.145 -
  80.146 -static char *filename_to_data(const char *filename)
  80.147 -{
  80.148 -	struct stat st;
  80.149 -
  80.150 -	if (lstat(filename, &st) == 0 && S_ISDIR(st.st_mode))
  80.151 -		return talloc_asprintf(filename, "%s/.DATA", filename);
  80.152 -	return (char *)filename;
  80.153 -}
  80.154 -
  80.155 -static void *file_read(struct file_ops_info *info,
  80.156 -		       const char *path, unsigned int *len)
  80.157 -{
  80.158 -	void *ret;
  80.159 -	char *filename = filename_to_data(path_to_name(info, path));
  80.160 -	unsigned long size;
  80.161 -
  80.162 -	ret = grab_file(filename, &size);
  80.163 -	/* Directory exists, .DATA doesn't. */
  80.164 -	if (!ret && errno == ENOENT && strends(filename, ".DATA")) {
  80.165 -		ret = strdup("");
  80.166 -		size = 0;
  80.167 -	}
  80.168 -	*len = size;
  80.169 -	return ret;
  80.170 -}
  80.171 -
  80.172 -static struct xs_permissions *file_get_perms(struct file_ops_info *info,
  80.173 -					     const char *path,
  80.174 -					     unsigned int *num)
  80.175 -{
  80.176 -	void *perms;
  80.177 -	struct xs_permissions *ret;
  80.178 -	char *filename = path_to_name(info, path);
  80.179 -	char *permfile;
  80.180 -	unsigned long size;
  80.181 -	struct stat st;
  80.182 -
  80.183 -	if (lstat(filename, &st) != 0)
  80.184 -		return NULL;
  80.185 -
  80.186 -	if (S_ISDIR(st.st_mode)) 
  80.187 -		permfile = talloc_asprintf(path, "%s/.perms", filename);
  80.188 -	else
  80.189 -		permfile = talloc_asprintf(path, "%s.perms", filename);
  80.190 -
  80.191 -	perms = grab_file(permfile, &size);
  80.192 -	if (!perms)
  80.193 -		barf("Grabbing permissions for %s", permfile);
  80.194 -	*num = xs_count_strings(perms, size);
  80.195 -
  80.196 -	ret = new_array(struct xs_permissions, *num);
  80.197 -	if (!xs_strings_to_perms(ret, *num, perms))
  80.198 -		barf("Reading permissions from %s", permfile);
  80.199 -	release_file(perms, size);
  80.200 -	return ret;
  80.201 -}
  80.202 -
  80.203 -static void do_command(const char *cmd)
  80.204 -{
  80.205 -	int ret;
  80.206 -
  80.207 -	ret = system(cmd);
  80.208 -	if (ret == -1 || !WIFEXITED(ret) || WEXITSTATUS(ret) != 0)
  80.209 -		barf_perror("Failed '%s': %i", cmd, ret);
  80.210 -}
  80.211 -
  80.212 -static void init_perms(const char *filename)
  80.213 -{
  80.214 -	struct stat st;
  80.215 -	char *permfile, *command;
  80.216 -
  80.217 -	if (lstat(filename, &st) != 0)
  80.218 -		barf_perror("Failed to stat %s", filename);
  80.219 -
  80.220 -	if (S_ISDIR(st.st_mode)) 
  80.221 -		permfile = talloc_asprintf(filename, "%s/.perms", filename);
  80.222 -	else
  80.223 -		permfile = talloc_asprintf(filename, "%s.perms", filename);
  80.224 -
  80.225 -	/* Leave permfile if it already exists. */
  80.226 -	if (lstat(permfile, &st) == 0)
  80.227 -		return;
  80.228 -
  80.229 -	/* Copy permissions from parent */
  80.230 -	command = talloc_asprintf(filename, "cp %.*s/.perms %s",
  80.231 -				  (int)(strrchr(filename, '/') - filename),
  80.232 -				  filename, permfile);
  80.233 -	do_command(command);
  80.234 -}	
  80.235 -
  80.236 -static bool file_set_perms(struct file_ops_info *info,
  80.237 -			   const char *path,
  80.238 -			   struct xs_permissions *perms,
  80.239 -			   unsigned int num)
  80.240 -{
  80.241 -	unsigned int i;
  80.242 -	char *filename = path_to_name(info, path);
  80.243 -	char *permfile;
  80.244 -	int fd;
  80.245 -	struct stat st;
  80.246 -
  80.247 -	if (num < 1) {
  80.248 -		errno = EINVAL;
  80.249 -		return false;
  80.250 -	}
  80.251 -
  80.252 -	/* Check non-perm file exists/ */
  80.253 -	if (lstat(filename, &st) != 0)
  80.254 -		return false;
  80.255 -
  80.256 -	if (S_ISDIR(st.st_mode)) 
  80.257 -		permfile = talloc_asprintf(path, "%s/.perms", filename);
  80.258 -	else
  80.259 -		permfile = talloc_asprintf(path, "%s.perms", filename);
  80.260 -
  80.261 -	fd = open(permfile, O_WRONLY|O_CREAT|O_TRUNC, 0600);
  80.262 -	if (fd < 0)
  80.263 -		return false;
  80.264 -
  80.265 -	for (i = 0; i < num; i++) {
  80.266 -		char buffer[100];
  80.267 -
  80.268 -		if (!xs_perm_to_string(&perms[i], buffer)) {
  80.269 -			int saved_errno = errno;
  80.270 -			close(fd);
  80.271 -			errno = saved_errno;
  80.272 -			return false;
  80.273 -		}
  80.274 -		if (write(fd, buffer, strlen(buffer) + 1)
  80.275 -		    != (int)strlen(buffer) + 1)
  80.276 -			barf_perror("Failed to write perm");
  80.277 -	}
  80.278 -	close(fd);
  80.279 -	return true;
  80.280 -}
  80.281 -
  80.282 -static char *parent_filename(const char *name)
  80.283 -{
  80.284 -	char *slash = strrchr(name + 1, '/');
  80.285 -	if (!slash)
  80.286 -		return talloc_strdup(name, "/");
  80.287 -	return talloc_asprintf(name, "%.*s", (int)(slash-name), name);
  80.288 -}
  80.289 -
  80.290 -static void make_dirs(const char *filename)
  80.291 -{
  80.292 -	struct stat st;
  80.293 -
  80.294 -	if (lstat(filename, &st) == 0 && S_ISREG(st.st_mode))
  80.295 -		convert_to_dir(filename);
  80.296 -
  80.297 -	if (mkdir(filename, 0700) == 0) {
  80.298 -		init_perms(filename);
  80.299 -		return;
  80.300 -	}
  80.301 -	if (errno == EEXIST)
  80.302 -		return;
  80.303 -
  80.304 -	make_dirs(parent_filename(filename));
  80.305 -	if (mkdir(filename, 0700) != 0)
  80.306 -		barf_perror("Failed to mkdir %s", filename);
  80.307 -	init_perms(filename);
  80.308 -}
  80.309 -
  80.310 -static bool file_write(struct file_ops_info *info,
  80.311 -		       const char *path, const void *data,
  80.312 -		       unsigned int len)
  80.313 -{
  80.314 -	char *filename = filename_to_data(path_to_name(info, path));
  80.315 -	int fd;
  80.316 -
  80.317 -	make_dirs(parent_filename(filename));
  80.318 -	fd = open(filename, O_CREAT|O_TRUNC|O_WRONLY, 0600);
  80.319 -	if (fd < 0)
  80.320 -		return false;
  80.321 -
  80.322 -	if (write(fd, data, len) != (int)len)
  80.323 -		barf_perror("Bad write to %s", filename);
  80.324 -
  80.325 -	init_perms(filename);
  80.326 -	close(fd);
  80.327 -	return true;
  80.328 -}
  80.329 -
  80.330 -static bool file_mkdir(struct file_ops_info *info, const char *path)
  80.331 -{
  80.332 -	char *dirname = path_to_name(info, path);
  80.333 -
  80.334 -	make_dirs(parent_filename(dirname));
  80.335 -	if (mkdir(dirname, 0700) != 0)
  80.336 -		return (errno == EEXIST);
  80.337 -
  80.338 -	init_perms(dirname);
  80.339 -	return true;
  80.340 -}
  80.341 -
  80.342 -static bool file_rm(struct file_ops_info *info, const char *path)
  80.343 -{
  80.344 -	char *filename = path_to_name(info, path);
  80.345 -	struct stat st;
  80.346 -
  80.347 -	if (lstat(filename, &st) != 0) {
  80.348 -		if (lstat(parent_filename(filename), &st) != 0)
  80.349 -			return false;
  80.350 -		return true;
  80.351 -	}
  80.352 -
  80.353 -	if (streq(path, "/")) {
  80.354 -		errno = EINVAL;
  80.355 -		return false;
  80.356 -	}
  80.357 -
  80.358 -	do_command(talloc_asprintf(path, "rm -f %s.perms; rm -r %s", 
  80.359 -				   filename, filename));
  80.360 -	return true;
  80.361 -}
  80.362 -
  80.363 -static bool file_transaction_start(struct file_ops_info *info)
  80.364 -{
  80.365 -	char *cmd;
  80.366 -
  80.367 -	if (info->transact_base) {
  80.368 -		errno = EBUSY;
  80.369 -		return false;
  80.370 -	}
  80.371 -
  80.372 -	info->transact_base = talloc_asprintf(NULL, "%s.transact", info->base);
  80.373 -	cmd = talloc_asprintf(NULL, "cp -r %s %s",
  80.374 -			      info->base, info->transact_base);
  80.375 -	do_command(cmd);
  80.376 -	talloc_free(cmd);
  80.377 -	return true;
  80.378 -}
  80.379 -
  80.380 -static bool file_transaction_end(struct file_ops_info *info, bool abort)
  80.381 -{
  80.382 -	char *old, *cmd;
  80.383 -
  80.384 -	if (!info->transact_base) {
  80.385 -		errno = ENOENT;
  80.386 -		return false;
  80.387 -	}
  80.388 -
  80.389 -	if (abort) {
  80.390 -		cmd = talloc_asprintf(NULL, "rm -rf %s", info->transact_base);
  80.391 -		do_command(cmd);
  80.392 -		goto success;
  80.393 -	}
  80.394 -
  80.395 -	old = talloc_asprintf(NULL, "rm -rf %s", info->base);
  80.396 -	do_command(old);
  80.397 -	talloc_free(old);
  80.398 -
  80.399 -	cmd = talloc_asprintf(NULL, "mv %s %s",
  80.400 -			      info->transact_base, info->base);
  80.401 -	do_command(cmd);
  80.402 -
  80.403 -success:
  80.404 -	talloc_free(cmd);
  80.405 -	talloc_free(info->transact_base);
  80.406 -	info->transact_base = NULL;
  80.407 -	return true;
  80.408 -}
  80.409 -
  80.410 -static struct file_ops_info *file_handle(const char *dir)
  80.411 -{
  80.412 -	struct file_ops_info *info = talloc(NULL, struct file_ops_info);
  80.413 -
  80.414 -	info->base = dir;
  80.415 -	info->transact_base = NULL;
  80.416 -	return info;
  80.417 -}
  80.418 -
  80.419 -static void file_close(struct file_ops_info *handle)
  80.420 -{
  80.421 -	talloc_free(handle);
  80.422 -}
  80.423 -
  80.424 -static struct xs_handle *xs_handle(const char *dir __attribute__((unused)))
  80.425 -{
  80.426 -	struct xs_handle *h;
  80.427 -
  80.428 -	h = xs_daemon_open();
  80.429 -	if (!h)
  80.430 -		barf_perror("Connecting to xs daemon");
  80.431 -	return h;
  80.432 -}
  80.433 -
  80.434 -static void xs_close(struct xs_handle *handle)
  80.435 -{
  80.436 -	xs_daemon_close(handle);
  80.437 -}
  80.438 -
  80.439 -struct ops file_ops = {
  80.440 -	.name = "FILE",
  80.441 -	.dir = (void *)file_directory,
  80.442 -	.read = (void *)file_read,
  80.443 -	.write = (void *)file_write,
  80.444 -	.mkdir = (void *)file_mkdir,
  80.445 -	.rm = (void *)file_rm,
  80.446 -	.get_perms = (void *)file_get_perms,
  80.447 -	.set_perms = (void *)file_set_perms,
  80.448 -	.transaction_start = (void *)file_transaction_start,
  80.449 -	.transaction_end = (void *)file_transaction_end,
  80.450 -	.handle = (void *)file_handle,
  80.451 -	.close = (void *)file_close,
  80.452 -};
  80.453 -
  80.454 -struct ops xs_ops = {
  80.455 -	.name = "XS",
  80.456 -	.dir = (void *)xs_directory,
  80.457 -	.read = (void *)xs_read,
  80.458 -	.write = (void *)xs_write,
  80.459 -	.mkdir = (void *)xs_mkdir,
  80.460 -	.rm = (void *)xs_rm,
  80.461 -	.get_perms = (void *)xs_get_permissions,
  80.462 -	.set_perms = (void *)xs_set_permissions,
  80.463 -	.transaction_start = (void *)xs_transaction_start,
  80.464 -	.transaction_end = (void *)xs_transaction_end,
  80.465 -	.handle = (void *)xs_handle,
  80.466 -	.close = (void *)xs_close,
  80.467 -};
  80.468 -
  80.469 -static int strptrcmp(const void *a, const void *b)
  80.470 -{
  80.471 -	return strcmp(*(char **)a, *(char **)b);
  80.472 -}
  80.473 -
  80.474 -static void sort_dir(char **dir, unsigned int num)
  80.475 -{
  80.476 -	qsort(dir, num, sizeof(char *), strptrcmp);
  80.477 -}
  80.478 -
  80.479 -static char *dump_dir(struct ops *ops,
  80.480 -		      void *h,
  80.481 -		      const char *node,
  80.482 -		      char **dir,
  80.483 -		      unsigned int numdirs,
  80.484 -		      unsigned int depth)
  80.485 -{
  80.486 -	char *ret = talloc_strdup(node, "");
  80.487 -	unsigned int i;
  80.488 -	char spacing[depth+1];
  80.489 -
  80.490 -	memset(spacing, ' ', depth);
  80.491 -	spacing[depth] = '\0';
  80.492 -
  80.493 -	sort_dir(dir, numdirs);
  80.494 -
  80.495 -	for (i = 0; i < numdirs; i++) {
  80.496 -		struct xs_permissions *perms;
  80.497 -		unsigned int j, numperms;
  80.498 -		unsigned int len;
  80.499 -		char *contents;
  80.500 -		unsigned int subnum;
  80.501 -		char **subdirs;
  80.502 -		char *subret;
  80.503 -		char *subnode = talloc_asprintf(node, "%s/%s", node, dir[i]);
  80.504 -
  80.505 -		perms = ops->get_perms(h, subnode, &numperms);
  80.506 -		if (!perms)
  80.507 -			return NULL;
  80.508 -		ret = talloc_asprintf_append(ret, "%s%s: ", spacing, dir[i]);
  80.509 -		for (j = 0; j < numperms; j++) {
  80.510 -			char buffer[100];
  80.511 -			if (!xs_perm_to_string(&perms[j], buffer))
  80.512 -				barf("perm to string");
  80.513 -			ret = talloc_asprintf_append(ret, "%s ", buffer);
  80.514 -		}
  80.515 -		free(perms);
  80.516 -		ret = talloc_asprintf_append(ret, "\n");
  80.517 -
  80.518 -		/* Even directories can have contents. */
  80.519 -		contents = ops->read(h, subnode, &len);
  80.520 -		if (!contents) {
  80.521 -			if (errno != EISDIR)
  80.522 -				return NULL;
  80.523 -		} else {
  80.524 -			ret = talloc_asprintf_append(ret, " %s(%.*s)\n",
  80.525 -						     spacing, len, contents);
  80.526 -			free(contents);
  80.527 -		}			
  80.528 -
  80.529 -		/* Every node is a directory. */
  80.530 -		subdirs = ops->dir(h, subnode, &subnum);
  80.531 -		if (!subdirs)
  80.532 -			return NULL;
  80.533 -		subret = dump_dir(ops, h, subnode, subdirs, subnum, depth+1);
  80.534 -		if (!subret)
  80.535 -			return NULL;
  80.536 -		ret = talloc_asprintf_append(ret, "%s", subret);
  80.537 -		free(subdirs);
  80.538 -	}
  80.539 -	return ret;
  80.540 -}
  80.541 -
  80.542 -static char *dump(struct ops *ops, void *h)
  80.543 -{
  80.544 -	char **subdirs;
  80.545 -	unsigned int subnum;
  80.546 -	char *ret = NULL, *root = talloc_strdup(NULL, "/");
  80.547 -
  80.548 -	subdirs = ops->dir(h, root, &subnum);
  80.549 -	if (subdirs) {
  80.550 -		ret = dump_dir(ops, h, talloc_strdup(root, ""), subdirs,
  80.551 -			       subnum, 0);
  80.552 -		free(subdirs);
  80.553 -		if (ret)
  80.554 -			talloc_steal(NULL, ret);
  80.555 -	}
  80.556 -	talloc_free(root);
  80.557 -	return ret;
  80.558 -}
  80.559 -
  80.560 -/* jhash.h: Jenkins hash support.
  80.561 - *
  80.562 - * Copyright (C) 1996 Bob Jenkins (bob_jenkins@burtleburtle.net)
  80.563 - *
  80.564 - * http://burtleburtle.net/bob/hash/
  80.565 - *
  80.566 - * These are the credits from Bob's sources:
  80.567 - *
  80.568 - * lookup2.c, by Bob Jenkins, December 1996, Public Domain.
  80.569 - * hash(), hash2(), hash3, and mix() are externally useful functions.
  80.570 - * Routines to test the hash are included if SELF_TEST is defined.
  80.571 - * You can use this free for any purpose.  It has no warranty.
  80.572 - *
  80.573 - * Copyright (C) 2003 David S. Miller (davem@redhat.com)
  80.574 - *
  80.575 - * I've modified Bob's hash to be useful in the Linux kernel, and
  80.576 - * any bugs present are surely my fault.  -DaveM
  80.577 - */
  80.578 -
  80.579 -/* NOTE: Arguments are modified. */
  80.580 -#define __jhash_mix(a, b, c) \
  80.581 -{ \
  80.582 -  a -= b; a -= c; a ^= (c>>13); \
  80.583 -  b -= c; b -= a; b ^= (a<<8); \
  80.584 -  c -= a; c -= b; c ^= (b>>13); \
  80.585 -  a -= b; a -= c; a ^= (c>>12);  \
  80.586 -  b -= c; b -= a; b ^= (a<<16); \
  80.587 -  c -= a; c -= b; c ^= (b>>5); \
  80.588 -  a -= b; a -= c; a ^= (c>>3);  \
  80.589 -  b -= c; b -= a; b ^= (a<<10); \
  80.590 -  c -= a; c -= b; c ^= (b>>15); \
  80.591 -}
  80.592 -
  80.593 -/* The golden ration: an arbitrary value */
  80.594 -#define JHASH_GOLDEN_RATIO	0x9e3779b9
  80.595 -
  80.596 -/* The most generic version, hashes an arbitrary sequence
  80.597 - * of bytes.  No alignment or length assumptions are made about
  80.598 - * the input key.
  80.599 - */
  80.600 -static inline uint32_t jhash(const void *key, uint32_t length, uint32_t initval)
  80.601 -{
  80.602 -	uint32_t a, b, c, len;
  80.603 -	const uint8_t *k = key;
  80.604 -
  80.605 -	len = length;
  80.606 -	a = b = JHASH_GOLDEN_RATIO;
  80.607 -	c = initval;
  80.608 -
  80.609 -	while (len >= 12) {
  80.610 -		a += (k[0] +((uint32_t)k[1]<<8) +((uint32_t)k[2]<<16) +((uint32_t)k[3]<<24));
  80.611 -		b += (k[4] +((uint32_t)k[5]<<8) +((uint32_t)k[6]<<16) +((uint32_t)k[7]<<24));
  80.612 -		c += (k[8] +((uint32_t)k[9]<<8) +((uint32_t)k[10]<<16)+((uint32_t)k[11]<<24));
  80.613 -
  80.614 -		__jhash_mix(a,b,c);
  80.615 -
  80.616 -		k += 12;
  80.617 -		len -= 12;
  80.618 -	}
  80.619 -
  80.620 -	c += length;
  80.621 -	switch (len) {
  80.622 -	case 11: c += ((uint32_t)k[10]<<24);
  80.623 -	case 10: c += ((uint32_t)k[9]<<16);
  80.624 -	case 9 : c += ((uint32_t)k[8]<<8);
  80.625 -	case 8 : b += ((uint32_t)k[7]<<24);
  80.626 -	case 7 : b += ((uint32_t)k[6]<<16);
  80.627 -	case 6 : b += ((uint32_t)k[5]<<8);
  80.628 -	case 5 : b += k[4];
  80.629 -	case 4 : a += ((uint32_t)k[3]<<24);
  80.630 -	case 3 : a += ((uint32_t)k[2]<<16);
  80.631 -	case 2 : a += ((uint32_t)k[1]<<8);
  80.632 -	case 1 : a += k[0];
  80.633 -	};
  80.634 -
  80.635 -	__jhash_mix(a,b,c);
  80.636 -
  80.637 -	return c;
  80.638 -}
  80.639 -
  80.640 -/* A special optimized version that handles 1 or more of uint32_ts.
  80.641 - * The length parameter here is the number of uint32_ts in the key.
  80.642 - */
  80.643 -static inline uint32_t jhash2(uint32_t *k, uint32_t length, uint32_t initval)
  80.644 -{
  80.645 -	uint32_t a, b, c, len;
  80.646 -
  80.647 -	a = b = JHASH_GOLDEN_RATIO;
  80.648 -	c = initval;
  80.649 -	len = length;
  80.650 -
  80.651 -	while (len >= 3) {
  80.652 -		a += k[0];
  80.653 -		b += k[1];
  80.654 -		c += k[2];
  80.655 -		__jhash_mix(a, b, c);
  80.656 -		k += 3; len -= 3;
  80.657 -	}
  80.658 -
  80.659 -	c += length * 4;
  80.660 -
  80.661 -	switch (len) {
  80.662 -	case 2 : b += k[1];
  80.663 -	case 1 : a += k[0];
  80.664 -	};
  80.665 -
  80.666 -	__jhash_mix(a,b,c);
  80.667 -
  80.668 -	return c;
  80.669 -}
  80.670 -
  80.671 -
  80.672 -/* A special ultra-optimized versions that knows they are hashing exactly
  80.673 - * 3, 2 or 1 word(s).
  80.674 - *
  80.675 - * NOTE: In partilar the "c += length; __jhash_mix(a,b,c);" normally
  80.676 - *       done at the end is not done here.
  80.677 - */
  80.678 -static inline uint32_t jhash_3words(uint32_t a, uint32_t b, uint32_t c, uint32_t initval)
  80.679 -{
  80.680 -	a += JHASH_GOLDEN_RATIO;
  80.681 -	b += JHASH_GOLDEN_RATIO;
  80.682 -	c += initval;
  80.683 -
  80.684 -	__jhash_mix(a, b, c);
  80.685 -
  80.686 -	return c;
  80.687 -}
  80.688 -
  80.689 -static inline uint32_t jhash_2words(uint32_t a, uint32_t b, uint32_t initval)
  80.690 -{
  80.691 -	return jhash_3words(a, b, 0, initval);
  80.692 -}
  80.693 -
  80.694 -static inline uint32_t jhash_1word(uint32_t a, uint32_t initval)
  80.695 -{
  80.696 -	return jhash_3words(a, 0, 0, initval);
  80.697 -}
  80.698 -
  80.699 -static unsigned int get_randomness(int *state)
  80.700 -{
  80.701 -	return jhash_1word((*state)++, *state * 1103515243);
  80.702 -}
  80.703 -
  80.704 -static char *random_path(int *state)
  80.705 -{
  80.706 -	unsigned int i;
  80.707 -	char *ret = NULL;
  80.708 -
  80.709 -	if (get_randomness(state) % 20 == 0)
  80.710 -		return talloc_strdup(NULL, "/");
  80.711 -
  80.712 -	for (i = 0; i < 1 || (get_randomness(state) % 2); i++) {
  80.713 -		ret = talloc_asprintf_append(ret, "/%i", 
  80.714 -					     get_randomness(state) % 15);
  80.715 -	}
  80.716 -	return ret;
  80.717 -}
  80.718 -
  80.719 -static char *bool_to_errstring(bool result)
  80.720 -{
  80.721 -	if (result)
  80.722 -		return talloc_strdup(NULL, "OK");
  80.723 -
  80.724 -	/* Real daemon can never return this. */
  80.725 -	if (errno == ENOTDIR)
  80.726 -		errno = ENOENT;
  80.727 -	return talloc_asprintf(NULL, "FAILED:%s", strerror(errno));
  80.728 -}
  80.729 -
  80.730 -static char *linearize_dir(char **dir, unsigned int *num)
  80.731 -{
  80.732 -	char *result = NULL;
  80.733 -	unsigned int i;
  80.734 -
  80.735 -	if (!dir)
  80.736 -		return bool_to_errstring(false);
  80.737 -
  80.738 -	if (!*num) {
  80.739 -		free(dir);
  80.740 -		return talloc_strdup(NULL, "");
  80.741 -	}
  80.742 -
  80.743 -	sort_dir(dir, *num);
  80.744 -	for (i = 0; i < *num; i++)
  80.745 -		result = talloc_asprintf_append(result, "%s\n", dir[i]);
  80.746 -	free(dir);
  80.747 -	return result;
  80.748 -}
  80.749 -
  80.750 -static char *linearize_read(char *read, unsigned int *size)
  80.751 -{
  80.752 -	char *ret;
  80.753 -
  80.754 -	if (!read)
  80.755 -		return bool_to_errstring(false);
  80.756 -
  80.757 -	ret = talloc_asprintf(NULL, "%i:%.*s", *size, *size, read);
  80.758 -	free(read);
  80.759 -	return ret;
  80.760 -}
  80.761 -
  80.762 -static char *linearize_perms(struct xs_permissions *perms, unsigned int *size)
  80.763 -{
  80.764 -	char *ret = NULL;
  80.765 -	unsigned int i;
  80.766 -
  80.767 -	if (!perms)
  80.768 -		return bool_to_errstring(false);
  80.769 -
  80.770 -	for (i = 0; i < *size; i++)
  80.771 -		ret = talloc_asprintf_append(ret, "(%u %u)",
  80.772 -					     perms[i].id, perms[i].perms);
  80.773 -
  80.774 -	free(perms);
  80.775 -	return ret;
  80.776 -}
  80.777 -
  80.778 -/* Do the next operation, return the results. */
  80.779 -static char *do_next_op(struct ops *ops, void *h, int state, bool verbose)
  80.780 -{
  80.781 -	char *name;
  80.782 -	unsigned int num;
  80.783 -	char *ret;
  80.784 -
  80.785 -	if (verbose)
  80.786 -		printf("State %i: ", state);
  80.787 -
  80.788 -	name = random_path(&state);
  80.789 -	switch (get_randomness(&state) % 9) {
  80.790 -	case 0:
  80.791 -		if (verbose)
  80.792 -			printf("DIR %s\n", name);
  80.793 -		ret = linearize_dir(ops->dir(h, name, &num), &num);
  80.794 -		break;
  80.795 -	case 1:
  80.796 -		if (verbose)
  80.797 -			printf("READ %s\n", name);
  80.798 -		ret = linearize_read(ops->read(h, name, &num), &num);
  80.799 -		break;
  80.800 -	case 2: {
  80.801 -		char *contents = talloc_asprintf(NULL, "%i",
  80.802 -						 get_randomness(&state));
  80.803 -		unsigned int len = get_randomness(&state)%(strlen(contents)+1);
  80.804 -		if (verbose)
  80.805 -			printf("WRITE %s %.*s\n", name, len, contents);
  80.806 -		ret = bool_to_errstring(ops->write(h, name, contents, len));
  80.807 -		talloc_steal(ret, contents);
  80.808 -		break;
  80.809 -	}
  80.810 -	case 3:
  80.811 -		if (verbose)
  80.812 -			printf("MKDIR %s\n", name);
  80.813 -		ret = bool_to_errstring(ops->mkdir(h, name));
  80.814 -		break;
  80.815 -	case 4:
  80.816 -		if (verbose)
  80.817 -			printf("RM %s\n", name);
  80.818 -		ret = bool_to_errstring(ops->rm(h, name));
  80.819 -		break;
  80.820 -	case 5:
  80.821 -		if (verbose)
  80.822 -			printf("GETPERMS %s\n", name);
  80.823 -		ret = linearize_perms(ops->get_perms(h, name, &num),
  80.824 -				      &num);
  80.825 -		break;
  80.826 -	case 6: {
  80.827 -		unsigned int i, num = get_randomness(&state)%8;
  80.828 -		struct xs_permissions perms[num];
  80.829 -
  80.830 -		if (verbose)
  80.831 -			printf("SETPERMS %s: ", name);
  80.832 -		for (i = 0; i < num; i++) {
  80.833 -			perms[i].id = get_randomness(&state)%8;
  80.834 -			perms[i].perms = get_randomness(&state)%4;
  80.835 -			if (verbose)
  80.836 -				printf("%i%c ", perms[i].id,
  80.837 -				       perms[i].perms == XS_PERM_WRITE ? 'W'
  80.838 -				       : perms[i].perms == XS_PERM_READ ? 'R'
  80.839 -				       : perms[i].perms == 
  80.840 -				       (XS_PERM_READ|XS_PERM_WRITE) ? 'B'
  80.841 -				       : 'N');
  80.842 -		}
  80.843 -		if (verbose)
  80.844 -			printf("\n");
  80.845 -		ret = bool_to_errstring(ops->set_perms(h, name, perms,
  80.846 -						       num));
  80.847 -		break;
  80.848 -	}
  80.849 -	case 7: {
  80.850 -		if (verbose)
  80.851 -			printf("START %s\n", name);
  80.852 -		ret = bool_to_errstring(ops->transaction_start(h));
  80.853 -		if (streq(ret, "OK")) {
  80.854 -			talloc_free(ret);
  80.855 -			ret = talloc_asprintf(NULL, "OK:START-TRANSACT");
  80.856 -		}
  80.857 -
  80.858 -		break;
  80.859 -	}
  80.860 -	case 8: {
  80.861 -		bool abort = (get_randomness(&state) % 2);
  80.862 -
  80.863 -		if (verbose)
  80.864 -			printf("STOP %s\n", abort ? "ABORT" : "COMMIT");
  80.865 -		ret = bool_to_errstring(ops->transaction_end(h, abort));
  80.866 -		if (streq(ret, "OK")) {
  80.867 -			talloc_free(ret);
  80.868 -			ret = talloc_strdup(NULL, "OK:STOP-TRANSACT");
  80.869 -		}
  80.870 -		break;
  80.871 -	}
  80.872 -	default:
  80.873 -		barf("Impossible randomness");
  80.874 -	}
  80.875 -
  80.876 -	talloc_steal(ret, name);
  80.877 -	return ret;
  80.878 -}
  80.879 -
  80.880 -static int daemon_pid;
  80.881 -
  80.882 -static void cleanup_xs_ops(void)
  80.883 -{
  80.884 -	char *cmd;
  80.885 -
  80.886 -	if (daemon_pid) {
  80.887 -		kill(daemon_pid, SIGTERM);
  80.888 -		waitpid(daemon_pid, NULL, 0);
  80.889 -		daemon_pid = 0;
  80.890 -	}
  80.891 -	
  80.892 -	cmd = talloc_asprintf(NULL, "rm -rf testsuite/tmp/*");
  80.893 -	do_command(cmd);
  80.894 -	talloc_free(cmd);
  80.895 -}
  80.896 -
  80.897 -static void cleanup_file_ops(const char *dir)
  80.898 -{
  80.899 -	char *cmd;
  80.900 -
  80.901 -	cmd = talloc_asprintf(NULL, "rm -rf %s %s.transact", dir, dir);
  80.902 -	do_command(cmd);
  80.903 -	talloc_free(cmd);
  80.904 -}
  80.905 -
  80.906 -static void cleanup(const char *dir)
  80.907 -{
  80.908 -	cleanup_xs_ops();
  80.909 -	cleanup_file_ops(dir);
  80.910 -}
  80.911 -
  80.912 -static void setup_file_ops(const char *dir)
  80.913 -{
  80.914 -	struct xs_permissions perm = { .id = 0, .perms = XS_PERM_READ };
  80.915 -	struct file_ops_info *h = file_handle(dir);
  80.916 -	if (mkdir(dir, 0700) != 0)
  80.917 -		barf_perror("Creating directory %s", dir);
  80.918 -	if (mkdir(talloc_asprintf(h, "%s/tool", dir), 0700) != 0)
  80.919 -		barf_perror("Creating directory %s/tool", dir);
  80.920 -	if (!file_set_perms(h, talloc_strdup(h, "/"), &perm, 1))
  80.921 -		barf_perror("Setting root perms in %s", dir);
  80.922 -	if (!file_set_perms(h, talloc_strdup(h, "/tool"), &perm, 1))
  80.923 -		barf_perror("Setting root perms in %s/tool", dir);
  80.924 -	file_close(h);
  80.925 -}
  80.926 -
  80.927 -static void setup_xs_ops(void)
  80.928 -{
  80.929 -	int fds[2];
  80.930 -
  80.931 -	/* Start daemon. */
  80.932 -	pipe(fds);
  80.933 -	if ((daemon_pid = fork())) {
  80.934 -		/* Child writes PID when its ready: we wait for that. */
  80.935 -		char buffer[20];
  80.936 -		close(fds[1]);
  80.937 -		if (read(fds[0], buffer, sizeof(buffer)) < 0)
  80.938 -			barf("Failed to summon daemon");
  80.939 -		close(fds[0]);
  80.940 -	} else {
  80.941 -		dup2(fds[1], STDOUT_FILENO);
  80.942 -		close(fds[0]);
  80.943 -#if 1
  80.944 -		execlp("valgrind", "valgrind", "-q", "--suppressions=testsuite/vg-suppressions", "xenstored_test", "--output-pid",
  80.945 -		       "--no-fork", NULL);
  80.946 -#else
  80.947 -		execlp("./xenstored_test", "xenstored_test", "--output-pid",
  80.948 -		       "--no-fork", NULL);
  80.949 -#endif
  80.950 -		exit(1);
  80.951 -	}
  80.952 -}
  80.953 -
  80.954 -static void setup(const char *dir)
  80.955 -{
  80.956 -	setup_file_ops(dir);
  80.957 -	setup_xs_ops();
  80.958 -};
  80.959 -
  80.960 -struct simple_data
  80.961 -{
  80.962 -	unsigned int seed;
  80.963 -	bool print_progress;
  80.964 -	bool fast;
  80.965 -	struct ops *ops;
  80.966 -	const char *dir;
  80.967 -};
  80.968 -
  80.969 -/* Just a random test.  Don't care about results, just that it doesn't
  80.970 - * go boom. */
  80.971 -static unsigned int try_simple(const bool *trymap,
  80.972 -			       unsigned int number,
  80.973 -			       bool verbose,
  80.974 -			       void *_data)
  80.975 -{
  80.976 -	unsigned int i, print;
  80.977 -	void *h;
  80.978 -	char *snapshot = NULL;
  80.979 -	struct simple_data *data = _data;
  80.980 -
  80.981 -	if (data->ops == &xs_ops) {
  80.982 -		cleanup_xs_ops();
  80.983 -		setup_xs_ops();
  80.984 -	} else {
  80.985 -		cleanup_file_ops(data->dir);
  80.986 -		setup_file_ops(data->dir);
  80.987 -	}
  80.988 -	h = data->ops->handle(data->dir);
  80.989 -
  80.990 -	print = number / 76;
  80.991 -	if (!print)
  80.992 -		print = 1;
  80.993 -
  80.994 -	for (i = 0; i < number; i++) {
  80.995 -		char *ret;
  80.996 -
  80.997 -		if (data->print_progress) {
  80.998 -			if (i % print == 0) {
  80.999 -				printf(".");
 80.1000 -				fflush(stdout);
 80.1001 -			}
 80.1002 -		}
 80.1003 -
 80.1004 -		if (trymap && !trymap[i])
 80.1005 -			continue;
 80.1006 -
 80.1007 -		ret = do_next_op(data->ops, h, i + data->seed, verbose);
 80.1008 -		if (verbose)
 80.1009 -			printf("-> %.*s\n",
 80.1010 -			       (int)(strchr(ret, '\n') - ret), ret);
 80.1011 -		if (streq(ret, "FAILED:Bad file descriptor"))
 80.1012 -			goto out;
 80.1013 -		if (kill(daemon_pid, 0) != 0)
 80.1014 -			goto out;
 80.1015 -
 80.1016 -		if (!data->fast) {
 80.1017 -			if (streq(ret, "OK:START-TRANSACT")) {
 80.1018 -				void *pre = data->ops->handle(data->dir);
 80.1019 -
 80.1020 -				snapshot = dump(data->ops, pre);
 80.1021 -				if (!snapshot)
 80.1022 -					goto out;
 80.1023 -				data->ops->close(pre);
 80.1024 -			} else if (streq(ret, "OK:STOP-TRANSACT")) {
 80.1025 -				talloc_free(snapshot);
 80.1026 -				snapshot = NULL;
 80.1027 -			}
 80.1028 -		}
 80.1029 -
 80.1030 -		talloc_free(ret);
 80.1031 -
 80.1032 -		if (snapshot) {
 80.1033 -			void *pre = data->ops->handle(data->dir);
 80.1034 -			char *contents;
 80.1035 -
 80.1036 -			contents = dump(data->ops, pre);
 80.1037 -			if (!contents)
 80.1038 -				goto out;
 80.1039 -
 80.1040 -			if (!streq(contents, snapshot))
 80.1041 -				goto out;
 80.1042 -
 80.1043 -			talloc_free(contents);
 80.1044 -			data->ops->close(pre);
 80.1045 -		}
 80.1046 -	}
 80.1047 -out:
 80.1048 -	data->ops->close(h);	
 80.1049 -	return i;
 80.1050 -}
 80.1051 -
 80.1052 -/* Binary elimination: try eliminating all of them, then reduce. */
 80.1053 -static void reduce(bool *map,
 80.1054 -		   unsigned int number,
 80.1055 -		   unsigned int try_start, unsigned int try_num,
 80.1056 -		   unsigned int (*try)(const bool *map,
 80.1057 -				       unsigned int number,
 80.1058 -				       bool verbose,
 80.1059 -				       void *),
 80.1060 -		   void *data)
 80.1061 -{
 80.1062 -	bool newmap[number];
 80.1063 -
 80.1064 -	if (try_num == 0)
 80.1065 -		return;
 80.1066 -
 80.1067 -	/* Try skipping everything between start and end.  */
 80.1068 -	memcpy(newmap, map, sizeof(newmap));
 80.1069 -	memset(newmap + try_start, 0, try_num * sizeof(bool));
 80.1070 -
 80.1071 -	/* We want the *same* failure: must fail at "number-1". */
 80.1072 -	if (try(newmap, number, false, data) == number - 1) {
 80.1073 -		memset(map + try_start, 0, try_num * sizeof(bool));
 80.1074 -		return;
 80.1075 -	}
 80.1076 -
 80.1077 -	if (try_num == 1)
 80.1078 -		return;
 80.1079 -
 80.1080 -	/* Try each half... */
 80.1081 -	reduce(map, number, try_start, try_num/2, try, data);
 80.1082 -	reduce(map, number, try_start + try_num/2, try_num - try_num/2,
 80.1083 -	       try, data);
 80.1084 -}
 80.1085 -
 80.1086 -static void reduce_problem(unsigned int failed,
 80.1087 -			   unsigned int (*try)(const bool *map,
 80.1088 -					       unsigned int number,
 80.1089 -					       bool verbose,
 80.1090 -					       void *data),
 80.1091 -			   void *data)
 80.1092 -{
 80.1093 -	bool map[failed];
 80.1094 -
 80.1095 -	memset(map, 1, sizeof(map));
 80.1096 -	reduce(map, failed, 0, failed-1, try, data);
 80.1097 -
 80.1098 -	printf("Cut down:\n");
 80.1099 -	if (try(map, failed, true, data) != failed - 1) {
 80.1100 -		printf("Except, that didn't actually fail.  Bugger!");
 80.1101 -		exit(2);
 80.1102 -	}
 80.1103 -	exit(1);
 80.1104 -}
 80.1105 -
 80.1106 -/* Just a random test.  Don't care about results, just that it doesn't
 80.1107 - * go boom. */
 80.1108 -static void simple_test(const char *dir,
 80.1109 -			unsigned int iters, unsigned int seed,
 80.1110 -			bool fast, bool verbose)
 80.1111 -{
 80.1112 -	struct simple_data data;
 80.1113 -	unsigned int tr