ia64/xen-unstable
changeset 1611:cdccf1a15b0f
bitkeeper revision 1.1026.1.2 (40e15b09oBOK6QWmjoE3IKmAR5xlVA)
Merge http://xen.bkbits.net:8080/xeno-unstable.bk
into gandalf.hpl.hp.com:/var/bk/xeno-unstable.bk
Merge http://xen.bkbits.net:8080/xeno-unstable.bk
into gandalf.hpl.hp.com:/var/bk/xeno-unstable.bk
line diff
1.1 --- a/.rootkeys Tue Jun 29 00:51:10 2004 +0000 1.2 +++ b/.rootkeys Tue Jun 29 12:05:29 2004 +0000 1.3 @@ -164,6 +164,44 @@ 401d7e16RJj-lbtsVEjua6HYAIiKiA tools/exa 1.4 40c9c468pXANclL7slGaoD0kSrIwoQ tools/examples/xm_dom_create.py 1.5 40cf2937oKlROYOJTN8GWwWM5AmjBg tools/examples/xmdefaults 1.6 40dfd40auJwNnb8NoiSnRkvZaaXkUg tools/examples/xmnetbsd 1.7 +40e033325Sjqs-_4TuzeUEprP_gYFg tools/lib/allocate.c 1.8 +40e03332KYz7o1bn2MG_KPbBlyoIMA tools/lib/allocate.h 1.9 +40e03332IyRttYoXKoJla5qCC514SQ tools/lib/debug.h 1.10 +40e03332qV5tJ-GJZjo-LBCeGuEjJA tools/lib/enum.c 1.11 +40e03332wwMVxfobgA1PSMTSAGLiCw tools/lib/enum.h 1.12 +40e03332p5Dc_owJQRuN72ymJZddFQ tools/lib/file_stream.c 1.13 +40e03332jWfB2viAhLSkq1WK0r_iDQ tools/lib/file_stream.h 1.14 +40e03332rUjNMGg11n2rN6V4DCrvOg tools/lib/gzip_stream.c 1.15 +40e033321O5Qg22haLoq5lpmk4tooQ tools/lib/gzip_stream.h 1.16 +40e03332QrTR96tc6yS2rMBpd2mq1A tools/lib/hash_table.c 1.17 +40e033325KoIb0d_uy8s7b5DUR9fPQ tools/lib/hash_table.h 1.18 +40e03332ihnBGzHykVwZnFmkAppb4g tools/lib/iostream.c 1.19 +40e03332UGwbLR4wsw4ft14p0Yw5pg tools/lib/iostream.h 1.20 +40e0333245DLDzJemeSVBLuutHtzEQ tools/lib/kernel_stream.c 1.21 +40e03332aK0GkgpDdc-PVTkWKTeOBg tools/lib/kernel_stream.h 1.22 +40e03332HJ0cDcZDKDUUT-tEiBWOZw tools/lib/lexis.c 1.23 +40e03332tnH9Ggzxbfi3xY9Vh2hUlg tools/lib/lexis.h 1.24 +40e03332aYIW0BNBh6wXuKKn_P7Yyg tools/lib/lzi_stream.c 1.25 +40e0333233voTffE4cJSMGJARfiSSQ tools/lib/lzi_stream.h 1.26 +40e03332FXuMoUnfsAKSgV8X4rFbYQ tools/lib/lzo_stream.c 1.27 +40e03332InJaiLfpDcIXBy2fI0RFGQ tools/lib/lzo_stream.h 1.28 +40e03332a5SCuRsejHStTuWzMQNv8Q tools/lib/marshal.c 1.29 +40e03332TwKyJrZQiiQfNq4vc2hpgw tools/lib/marshal.h 1.30 +40e033328ccHlJuTR1FswYL_EC6LFA tools/lib/socket_stream.c 1.31 +40e03332P0KVQGkmahj47aafo1X0nA tools/lib/socket_stream.h 1.32 +40e03332KT_tnnoAMbPVAZBB7kSOAQ tools/lib/string_stream.c 1.33 +40e03332-VtK6_OZa1vMHXFil8uq6w tools/lib/string_stream.h 1.34 +40e03332dDtczi6YX7_mMxhYjJeAdQ tools/lib/sxpr.c 1.35 +40e03332QPuyNKDOTIYVvkwK5qO-vg tools/lib/sxpr.h 1.36 +40e03332Pi0_osJ3XPBi38ADPqdl4A tools/lib/sxpr_parser.c 1.37 +40e033324v5QFMvWEXXzv38uUT9kHg tools/lib/sxpr_parser.h 1.38 +40e03332gKUInsqtxQOV4mPiMqf_dg tools/lib/sys_ctype.h 1.39 +40e03332Rkvq6nn_UNjzAAK_Tk9v1g tools/lib/sys_net.c 1.40 +40e03332lQHvQHw4Rh7VsT1_sui29A tools/lib/sys_net.h 1.41 +40e033321smklZd7bDSdWvQCeIshtg tools/lib/sys_string.c 1.42 +40e03332h5V611rRWURRLqb1Ekatxg tools/lib/sys_string.h 1.43 +40e03332u4q5kgF0N7RfqB4s0pZVew tools/lib/xdr.c 1.44 +40e03332hY16nfRXF4gGd5S1aUJUBw tools/lib/xdr.h 1.45 3f776bd2Xd-dUcPKlPN2vG89VGtfvQ tools/misc/Makefile 1.46 40ab2cfawIw8tsYo0dQKtp83h4qfTQ tools/misc/fakei386xen 1.47 3f6dc136ZKOjd8PIqLbFBl_v-rnkGg tools/misc/miniterm/Makefile 1.48 @@ -185,6 +223,8 @@ 3fbba6dbEVkVMX0JuDFzap9jeaucGA tools/xc/ 1.49 3fbba6dbasJQV-MVElDC0DGSHMiL5w tools/xc/lib/xc_domain.c 1.50 40278d99BLsfUv3qxv0I8C1sClZ0ow tools/xc/lib/xc_elf.h 1.51 403e0977Bjsm_e82pwvl9VvaJxh8Gg tools/xc/lib/xc_evtchn.c 1.52 +40e03333Eegw8czSWvHsbKxrRZJjRA tools/xc/lib/xc_io.c 1.53 +40e03333vrWGbLAhyJjXlqCHaJt7eA tools/xc/lib/xc_io.h 1.54 3fbba6dbNCU7U6nsMYiXzKkp3ztaJg tools/xc/lib/xc_linux_build.c 1.55 3fbba6dbl267zZOAVHYLOdLCdhcZMw tools/xc/lib/xc_linux_restore.c 1.56 3fbba6db7li3FJiABYtCmuGxOJxEGw tools/xc/lib/xc_linux_save.c
2.1 --- a/BitKeeper/etc/ignore Tue Jun 29 00:51:10 2004 +0000 2.2 +++ b/BitKeeper/etc/ignore Tue Jun 29 12:05:29 2004 +0000 2.3 @@ -3,8 +3,8 @@ 2.4 *.pyc 2.5 *.so 2.6 *.so.* 2.7 +*.tar.bz2 2.8 *.tar.gz 2.9 -*.tar.bz2 2.10 *~ 2.11 BitKeeper/*/* 2.12 PENDING/* 2.13 @@ -12,15 +12,34 @@ TAGS 2.14 extras/mini-os/h/hypervisor-ifs 2.15 install 2.16 install/* 2.17 +linux-*-xen*/* 2.18 +linux-2.4.26-xen/* 2.19 +linux-xen-sparse 2.20 patches/* 2.21 -linux-*-xen*/* 2.22 -linux-xen-sparse 2.23 tools/*/build/lib*/*.py 2.24 tools/balloon/balloon 2.25 tools/misc/miniterm/miniterm 2.26 tools/misc/xen_cpuperf 2.27 tools/misc/xen_log 2.28 tools/misc/xen_read_console 2.29 +tools/xc/lib/.allocate.o.d 2.30 +tools/xc/lib/.file_stream.o.d 2.31 +tools/xc/lib/.gzip_stream.o.d 2.32 +tools/xc/lib/.iostream.o.d 2.33 +tools/xc/lib/.sys_net.o.d 2.34 +tools/xc/lib/.sys_string.o.d 2.35 +tools/xc/lib/.xc_atropos.o.d 2.36 +tools/xc/lib/.xc_bvtsched.o.d 2.37 +tools/xc/lib/.xc_domain.o.d 2.38 +tools/xc/lib/.xc_evtchn.o.d 2.39 +tools/xc/lib/.xc_io.o.d 2.40 +tools/xc/lib/.xc_linux_build.o.d 2.41 +tools/xc/lib/.xc_linux_restore.o.d 2.42 +tools/xc/lib/.xc_linux_save.o.d 2.43 +tools/xc/lib/.xc_misc.o.d 2.44 +tools/xc/lib/.xc_netbsd_build.o.d 2.45 +tools/xc/lib/.xc_physdev.o.d 2.46 +tools/xc/lib/.xc_private.o.d 2.47 tools/xentrace/xentrace 2.48 xen/drivers/pci/classlist.h 2.49 xen/drivers/pci/devlist.h
3.1 --- a/tools/examples/xmdefaults Tue Jun 29 00:51:10 2004 +0000 3.2 +++ b/tools/examples/xmdefaults Tue Jun 29 12:05:29 2004 +0000 3.3 @@ -5,9 +5,6 @@ 3.4 # This file expects the variable 'vmid' to be set. 3.5 #============================================================================ 3.6 3.7 -import sys 3.8 -import xenctl.ip 3.9 - 3.10 try: 3.11 vmid = int(vmid) # convert to integer 3.12 except:
4.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 4.2 +++ b/tools/lib/allocate.c Tue Jun 29 12:05:29 2004 +0000 4.3 @@ -0,0 +1,116 @@ 4.4 +/* 4.5 + * Copyright (C) 2001 - 2004 Mike Wray <mike.wray@hp.com> 4.6 + * 4.7 + * This library is free software; you can redistribute it and/or modify 4.8 + * it under the terms of the GNU Lesser General Public License as published by 4.9 + * the Free Software Foundation; either version 2.1 of the License, or 4.10 + * (at your option) any later version. 4.11 + * 4.12 + * This library is distributed in the hope that it will be useful, 4.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 4.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 4.15 + * GNU Lesser General Public License for more details. 4.16 + * 4.17 + * You should have received a copy of the GNU Lesser General Public License 4.18 + * along with this library; if not, write to the Free Software 4.19 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 4.20 + */ 4.21 + 4.22 +#include "allocate.h" 4.23 + 4.24 +/** @file 4.25 + * Support for allocating memory. 4.26 + * Usable from user code or kernel code (with __KERNEL__ defined). 4.27 + * In user code will use GC if USE_GC is defined. 4.28 + */ 4.29 + 4.30 +#ifdef __KERNEL__ 4.31 +/*----------------------------------------------------------------------------*/ 4.32 +# include <linux/config.h> 4.33 +# include <linux/slab.h> 4.34 +# include <linux/string.h> 4.35 +# include <linux/types.h> 4.36 + 4.37 +# define DEFAULT_TYPE 0 4.38 +# define MALLOC(n, type) kmalloc(n, type) 4.39 +# define FREE(ptr) kfree(ptr) 4.40 + 4.41 +/*----------------------------------------------------------------------------*/ 4.42 +#else /* ! __KERNEL__ */ 4.43 + 4.44 +# include <stdlib.h> 4.45 +# include <string.h> 4.46 + 4.47 +# define DEFAULT_TYPE 0 4.48 + 4.49 +#ifdef USE_GC 4.50 +# include "gc.h" 4.51 +# define MALLOC(n, typ) GC_malloc(n) 4.52 +# define FREE(ptr) (ptr=NULL) 4.53 +//typedef void *GC_PTR; 4.54 +//GC_PTR (*GC_oom_fn)(size_t n); 4.55 +#else 4.56 +# define MALLOC(n, type) malloc(n) 4.57 +# define FREE(ptr) free(ptr) 4.58 +#endif 4.59 + 4.60 +/*----------------------------------------------------------------------------*/ 4.61 +#endif 4.62 + 4.63 +/** Function to call when memory cannot be allocated. */ 4.64 +AllocateFailedFn *allocate_failed_fn = NULL; 4.65 + 4.66 +/** Allocate memory and zero it. 4.67 + * The type is only relevant when calling from kernel code, 4.68 + * from user code it is ignored. 4.69 + * In kernel code the values accepted by kmalloc can be used: 4.70 + * GFP_USER, GFP_ATOMIC, GFP_KERNEL. 4.71 + * 4.72 + * @param size number of bytes to allocate 4.73 + * @param type memory type to allocate (kernel only) 4.74 + * @return pointer to the allocated memory or zero 4.75 + * if malloc failed 4.76 + */ 4.77 +void *allocate_type(int size, int type){ 4.78 + void *p = MALLOC(size, type); 4.79 + if(p){ 4.80 + memzero(p, size); 4.81 + } else if(allocate_failed_fn){ 4.82 + allocate_failed_fn(size, type); 4.83 + } 4.84 + return p; 4.85 +} 4.86 + 4.87 +/** Allocate memory and zero it. 4.88 + * 4.89 + * @param size number of bytes to allocate 4.90 + * @return pointer to the allocated memory or zero 4.91 + * if malloc failed 4.92 + */ 4.93 +void *allocate(int size){ 4.94 + return allocate_type(size, DEFAULT_TYPE); 4.95 +} 4.96 + 4.97 +/** Free memory allocated by allocate(). 4.98 + * No-op if 'p' is null. 4.99 + * 4.100 + * @param p memory to free 4.101 + */ 4.102 +void deallocate(void *p){ 4.103 + if(p){ 4.104 + FREE(p); 4.105 + } 4.106 +} 4.107 + 4.108 +/** Set bytes to zero. 4.109 + * No-op if 'p' is null. 4.110 + * 4.111 + * @param p memory to zero 4.112 + * @param size number of bytes to zero 4.113 + */ 4.114 +void memzero(void *p, int size){ 4.115 + if(p){ 4.116 + memset(p, 0, (size_t)size); 4.117 + } 4.118 +} 4.119 +
5.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 5.2 +++ b/tools/lib/allocate.h Tue Jun 29 12:05:29 2004 +0000 5.3 @@ -0,0 +1,45 @@ 5.4 +/* 5.5 + * Copyright (C) 2001 - 2004 Mike Wray <mike.wray@hp.com> 5.6 + * 5.7 + * This library is free software; you can redistribute it and/or modify 5.8 + * it under the terms of the GNU Lesser General Public License as published by 5.9 + * the Free Software Foundation; either version 2.1 of the License, or 5.10 + * (at your option) any later version. 5.11 + * 5.12 + * This library is distributed in the hope that it will be useful, 5.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 5.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 5.15 + * GNU Lesser General Public License for more details. 5.16 + * 5.17 + * You should have received a copy of the GNU Lesser General Public License 5.18 + * along with this library; if not, write to the Free Software 5.19 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 5.20 + */ 5.21 + 5.22 +#ifndef _XEN_LIB_ALLOCATE_H_ 5.23 +#define _XEN_LIB_ALLOCATE_H_ 5.24 + 5.25 +/** Allocate memory for a given type, and cast. */ 5.26 +#define ALLOCATE(ctype) (ctype *)allocate(sizeof(ctype)) 5.27 + 5.28 +/** Allocate memory for a given type, and cast. */ 5.29 +#define ALLOCATE_TYPE(ctype, type) (ctype *)allocate(sizeof(ctype)) 5.30 + 5.31 +extern void *allocate_type(int size, int type); 5.32 +extern void *allocate(int size); 5.33 +extern void deallocate(void *); 5.34 +extern void memzero(void *p, int size); 5.35 + 5.36 +typedef void AllocateFailedFn(int size, int type); 5.37 +extern AllocateFailedFn *allocate_failed_fn; 5.38 + 5.39 +#endif /* _XEN_LIB_ALLOCATE_H_ */ 5.40 + 5.41 + 5.42 + 5.43 + 5.44 + 5.45 + 5.46 + 5.47 + 5.48 +
6.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 6.2 +++ b/tools/lib/debug.h Tue Jun 29 12:05:29 2004 +0000 6.3 @@ -0,0 +1,72 @@ 6.4 +/* 6.5 + * Copyright (C) 2004 Mike Wray <mike.wray@hp.com> 6.6 + * 6.7 + * This library is free software; you can redistribute it and/or modify 6.8 + * it under the terms of the GNU Lesser General Public License as published by 6.9 + * the Free Software Foundation; either version 2.1 of the License, or 6.10 + * (at your option) any later version. 6.11 + * 6.12 + * This library is distributed in the hope that it will be useful, 6.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 6.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 6.15 + * GNU Lesser General Public License for more details. 6.16 + * 6.17 + * You should have received a copy of the GNU Lesser General Public License 6.18 + * along with this library; if not, write to the Free Software 6.19 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 6.20 + */ 6.21 +#ifndef _XEN_LIB_DEBUG_H_ 6.22 +#define _XEN_LIB_DEBUG_H_ 6.23 + 6.24 +#ifndef MODULE_NAME 6.25 +#define MODULE_NAME "" 6.26 +#endif 6.27 + 6.28 +#ifdef __KERNEL__ 6.29 +#include <linux/config.h> 6.30 +#include <linux/kernel.h> 6.31 + 6.32 +#ifdef DEBUG 6.33 + 6.34 +#define dprintf(fmt, args...) printk(KERN_DEBUG "[DBG] " MODULE_NAME ">%s" fmt, __FUNCTION__, ##args) 6.35 +#define wprintf(fmt, args...) printk(KERN_WARNING "[WRN] " MODULE_NAME ">%s" fmt, __FUNCTION__, ##args) 6.36 +#define iprintf(fmt, args...) printk(KERN_INFO "[INF] " MODULE_NAME ">%s" fmt, __FUNCTION__, ##args) 6.37 +#define eprintf(fmt, args...) printk(KERN_ERR "[ERR] " MODULE_NAME ">%s" fmt, __FUNCTION__, ##args) 6.38 + 6.39 +#else 6.40 + 6.41 +#define dprintf(fmt, args...) do {} while(0) 6.42 +#define wprintf(fmt, args...) printk(KERN_WARNING "[WRN] " MODULE_NAME fmt, ##args) 6.43 +#define iprintf(fmt, args...) printk(KERN_INFO "[INF] " MODULE_NAME fmt, ##args) 6.44 +#define eprintf(fmt, args...) printk(KERN_ERR "[ERR] " MODULE_NAME fmt, ##args) 6.45 + 6.46 +#endif 6.47 + 6.48 +#else 6.49 + 6.50 +#include <stdio.h> 6.51 + 6.52 +#ifdef DEBUG 6.53 + 6.54 +#define dprintf(fmt, args...) fprintf(stdout, "[DBG] " MODULE_NAME ">%s" fmt, __FUNCTION__, ##args) 6.55 +#define wprintf(fmt, args...) fprintf(stderr, "[WRN] " MODULE_NAME ">%s" fmt, __FUNCTION__, ##args) 6.56 +#define iprintf(fmt, args...) fprintf(stderr, "[INF] " MODULE_NAME ">%s" fmt, __FUNCTION__, ##args) 6.57 +#define eprintf(fmt, args...) fprintf(stderr, "[ERR] " MODULE_NAME ">%s" fmt, __FUNCTION__, ##args) 6.58 + 6.59 +#else 6.60 + 6.61 +#define dprintf(fmt, args...) do {} while(0) 6.62 +#define wprintf(fmt, args...) fprintf(stderr, "[WRN] " MODULE_NAME fmt, ##args) 6.63 +#define iprintf(fmt, args...) fprintf(stderr, "[INF] " MODULE_NAME fmt, ##args) 6.64 +#define eprintf(fmt, args...) fprintf(stderr, "[ERR] " MODULE_NAME fmt, ##args) 6.65 + 6.66 +#endif 6.67 + 6.68 +#endif 6.69 + 6.70 +/** Print format for an IP address. 6.71 + * See NIPQUAD(), HIPQUAD() 6.72 + */ 6.73 +#define IPFMT "%u.%u.%u.%u" 6.74 + 6.75 +#endif /* ! _XEN_LIB_DEBUG_H_ */
7.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 7.2 +++ b/tools/lib/enum.c Tue Jun 29 12:05:29 2004 +0000 7.3 @@ -0,0 +1,61 @@ 7.4 +/* 7.5 + * Copyright (C) 2002, 2004 Mike Wray <mike.wray@hp.com> 7.6 + * 7.7 + * This library is free software; you can redistribute it and/or modify 7.8 + * it under the terms of the GNU Lesser General Public License as 7.9 + * published by the Free Software Foundation; either version 2.1 of the 7.10 + * License, or (at your option) any later version. This library is 7.11 + * distributed in the hope that it will be useful, but WITHOUT ANY 7.12 + * WARRANTY; without even the implied warranty of MERCHANTABILITY or 7.13 + * FITNESS FOR A PARTICULAR PURPOSE. 7.14 + * See the GNU Lesser General Public License for more details. 7.15 + * 7.16 + * You should have received a copy of the GNU Lesser General Public License 7.17 + * along with this library; if not, write to the Free Software Foundation, 7.18 + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 7.19 + */ 7.20 + 7.21 +#ifdef __KERNEL__ 7.22 +#include <linux/errno.h> 7.23 +#else 7.24 +#include <errno.h> 7.25 +#endif 7.26 + 7.27 +#include "sys_string.h" 7.28 +#include "enum.h" 7.29 + 7.30 +/** Map an enum name to its value using a table. 7.31 + * 7.32 + * @param name enum name 7.33 + * @param defs enum definitions 7.34 + * @return enum value or -1 if not known 7.35 + */ 7.36 +int enum_name_to_val(char *name, EnumDef *defs){ 7.37 + int val = -1; 7.38 + for(; defs->name; defs++){ 7.39 + if(!strcmp(defs->name, name)){ 7.40 + val = defs->val; 7.41 + break; 7.42 + } 7.43 + } 7.44 + return val; 7.45 +} 7.46 + 7.47 +/** Map an enum value to its name using a table. 7.48 + * 7.49 + * @param val enum value 7.50 + * @param defs enum definitions 7.51 + * @param defs_n number of definitions 7.52 + * @return enum name or NULL if not known 7.53 + */ 7.54 +char *enum_val_to_name(int val, EnumDef *defs){ 7.55 + char *name = NULL; 7.56 + for(; defs->name; defs++){ 7.57 + if(val == defs->val){ 7.58 + name = defs->name; 7.59 + break; 7.60 + } 7.61 + } 7.62 + return name; 7.63 +} 7.64 +
8.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 8.2 +++ b/tools/lib/enum.h Tue Jun 29 12:05:29 2004 +0000 8.3 @@ -0,0 +1,30 @@ 8.4 +/* 8.5 + * Copyright (C) 2002, 2004 Mike Wray <mike.wray@hp.com> 8.6 + * 8.7 + * This library is free software; you can redistribute it and/or modify 8.8 + * it under the terms of the GNU Lesser General Public License as 8.9 + * published by the Free Software Foundation; either version 2.1 of the 8.10 + * License, or (at your option) any later version. This library is 8.11 + * distributed in the hope that it will be useful, but WITHOUT ANY 8.12 + * WARRANTY; without even the implied warranty of MERCHANTABILITY or 8.13 + * FITNESS FOR A PARTICULAR PURPOSE. 8.14 + * See the GNU Lesser General Public License for more details. 8.15 + * 8.16 + * You should have received a copy of the GNU Lesser General Public License 8.17 + * along with this library; if not, write to the Free Software Foundation, 8.18 + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 8.19 + */ 8.20 + 8.21 +#ifndef _XEN_LIB_ENUM_H_ 8.22 +#define _XEN_LIB_ENUM_H_ 8.23 + 8.24 +/** Mapping of an enum value to a name. */ 8.25 +typedef struct EnumDef { 8.26 + int val; 8.27 + char *name; 8.28 +} EnumDef; 8.29 + 8.30 +extern int enum_name_to_val(char *name, EnumDef *defs); 8.31 +extern char *enum_val_to_name(int val, EnumDef *defs); 8.32 + 8.33 +#endif /* _XEN_LIB_ENUM_H_ */
9.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 9.2 +++ b/tools/lib/file_stream.c Tue Jun 29 12:05:29 2004 +0000 9.3 @@ -0,0 +1,202 @@ 9.4 +/* 9.5 + * Copyright (C) 2001 - 2004 Mike Wray <mike.wray@hp.com> 9.6 + * 9.7 + * This library is free software; you can redistribute it and/or modify 9.8 + * it under the terms of the GNU Lesser General Public License as published by 9.9 + * the Free Software Foundation; either version 2.1 of the License, or 9.10 + * (at your option) any later version. 9.11 + * 9.12 + * This library is distributed in the hope that it will be useful, 9.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 9.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 9.15 + * GNU Lesser General Public License for more details. 9.16 + * 9.17 + * You should have received a copy of the GNU Lesser General Public License 9.18 + * along with this library; if not, write to the Free Software 9.19 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 9.20 + */ 9.21 + 9.22 +/** @file 9.23 + * An IOStream implementation using FILE*. 9.24 + */ 9.25 +#ifndef __KERNEL__ 9.26 +#include <stdio.h> 9.27 +#include <stdlib.h> 9.28 +#include "allocate.h" 9.29 +#include "file_stream.h" 9.30 + 9.31 +static int file_read(IOStream *s, void *buf, size_t n); 9.32 +static int file_write(IOStream *s, const void *buf, size_t n); 9.33 +static int file_error(IOStream *s); 9.34 +static int file_close(IOStream *s); 9.35 +static void file_free(IOStream *s); 9.36 +static int file_flush(IOStream *s); 9.37 + 9.38 +/** Methods used by a FILE* IOStream. */ 9.39 +static const IOMethods file_methods = { 9.40 + read: file_read, 9.41 + write: file_write, 9.42 + error: file_error, 9.43 + close: file_close, 9.44 + free: file_free, 9.45 + flush: file_flush, 9.46 +}; 9.47 + 9.48 +/** IOStream for stdin. */ 9.49 +static IOStream _iostdin = { 9.50 + methods: &file_methods, 9.51 + data: (void*)1, 9.52 +}; 9.53 + 9.54 +/** IOStream for stdout. */ 9.55 +static IOStream _iostdout = { 9.56 + methods: &file_methods, 9.57 + data: (void*)2, 9.58 +}; 9.59 + 9.60 +/** IOStream for stderr. */ 9.61 +static IOStream _iostderr = { 9.62 + methods: &file_methods, 9.63 + data: (void*)3, 9.64 +}; 9.65 + 9.66 +/** IOStream for stdin. */ 9.67 +IOStream *iostdin = &_iostdin; 9.68 + 9.69 +/** IOStream for stdout. */ 9.70 +IOStream *iostdout = &_iostdout; 9.71 + 9.72 +/** IOStream for stderr. */ 9.73 +IOStream *iostderr = &_iostderr; 9.74 + 9.75 +/** Get the underlying FILE*. 9.76 + * 9.77 + * @param s file stream 9.78 + * @return the stream s wraps 9.79 + */ 9.80 +static inline FILE *get_file(IOStream *s){ 9.81 + switch((long)s->data){ 9.82 + case 1: s->data = stdin; break; 9.83 + case 2: s->data = stdout; break; 9.84 + case 3: s->data = stderr; break; 9.85 + } 9.86 + return (FILE*)s->data; 9.87 +} 9.88 + 9.89 +/** Control buffering on the underlying stream, like setvbuf(). 9.90 + * 9.91 + * @param io file stream 9.92 + * @param buf buffer 9.93 + * @param mode buffering mode (see man setvbuf()) 9.94 + * @param size buffer size 9.95 + * @return 0 on success, non-zero otherwise 9.96 + */ 9.97 +int file_stream_setvbuf(IOStream *io, char *buf, int mode, size_t size){ 9.98 + return setvbuf(get_file(io), buf, mode, size); 9.99 +} 9.100 + 9.101 +/** Write to the underlying stream using fwrite(); 9.102 + * 9.103 + * @param stream input 9.104 + * @param buf where to put input 9.105 + * @param n number of bytes to write 9.106 + * @return number of bytes written 9.107 + */ 9.108 +static int file_write(IOStream *s, const void *buf, size_t n){ 9.109 + return fwrite(buf, 1, n, get_file(s)); 9.110 +} 9.111 + 9.112 +/** Read from the underlying stream using fread(); 9.113 + * 9.114 + * @param stream input 9.115 + * @param buf where to put input 9.116 + * @param n number of bytes to read 9.117 + * @return number of bytes read 9.118 + */ 9.119 +static int file_read(IOStream *s, void *buf, size_t n){ 9.120 + return fread(buf, 1, n, get_file(s)); 9.121 +} 9.122 + 9.123 +/** Fush the underlying stream using fflush(). 9.124 + * 9.125 + * @param s file stream 9.126 + * @return 0 on success, error code otherwise 9.127 + */ 9.128 +static int file_flush(IOStream *s){ 9.129 + return fflush(get_file(s)); 9.130 +} 9.131 + 9.132 +/** Check if a stream has an error. 9.133 + * 9.134 + * @param s file stream 9.135 + * @return 1 if has an error, 0 otherwise 9.136 + */ 9.137 +static int file_error(IOStream *s){ 9.138 + return ferror(get_file(s)); 9.139 +} 9.140 + 9.141 +/** Close a file stream. 9.142 + * 9.143 + * @param s file stream to close 9.144 + * @return result of the close 9.145 + */ 9.146 +static int file_close(IOStream *s){ 9.147 + return fclose(get_file(s)); 9.148 +} 9.149 + 9.150 +/** Free a file stream. 9.151 + * 9.152 + * @param s file stream 9.153 + */ 9.154 +static void file_free(IOStream *s){ 9.155 + // Do nothing - fclose does it all? 9.156 +} 9.157 + 9.158 +/** Create an IOStream for a stream. 9.159 + * 9.160 + * @param f stream to wrap 9.161 + * @return new IOStream using f for i/o 9.162 + */ 9.163 +IOStream *file_stream_new(FILE *f){ 9.164 + IOStream *io = ALLOCATE(IOStream); 9.165 + if(io){ 9.166 + io->methods = &file_methods; 9.167 + io->data = (void*)f; 9.168 + } 9.169 + return io; 9.170 +} 9.171 + 9.172 +/** IOStream version of fopen(). 9.173 + * 9.174 + * @param file name of the file to open 9.175 + * @param flags giving the mode to open in (as for fopen()) 9.176 + * @return new stream for the open file, or 0 if failed 9.177 + */ 9.178 +IOStream *file_stream_fopen(const char *file, const char *flags){ 9.179 + IOStream *io = 0; 9.180 + FILE *fin = fopen(file, flags); 9.181 + if(fin){ 9.182 + io = file_stream_new(fin); 9.183 + if(!io){ 9.184 + fclose(fin); 9.185 + //free(fin); // fclose frees ? 9.186 + } 9.187 + } 9.188 + return io; 9.189 +} 9.190 + 9.191 +/** IOStream version of fdopen(). 9.192 + * 9.193 + * @param fd file descriptor 9.194 + * @param flags giving the mode to open in (as for fdopen()) 9.195 + * @return new stream for the open file, or 0 if failed 9.196 + */ 9.197 +IOStream *file_stream_fdopen(int fd, const char *flags){ 9.198 + IOStream *io = 0; 9.199 + FILE *fin = fdopen(fd, flags); 9.200 + if(fin){ 9.201 + io = file_stream_new(fin); 9.202 + } 9.203 + return io; 9.204 +} 9.205 +#endif
10.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 10.2 +++ b/tools/lib/file_stream.h Tue Jun 29 12:05:29 2004 +0000 10.3 @@ -0,0 +1,35 @@ 10.4 +/* 10.5 + * Copyright (C) 2001 - 2004 Mike Wray <mike.wray@hp.com> 10.6 + * 10.7 + * This library is free software; you can redistribute it and/or modify 10.8 + * it under the terms of the GNU Lesser General Public License as published by 10.9 + * the Free Software Foundation; either version 2.1 of the License, or 10.10 + * (at your option) any later version. 10.11 + * 10.12 + * This library is distributed in the hope that it will be useful, 10.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 10.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 10.15 + * GNU Lesser General Public License for more details. 10.16 + * 10.17 + * You should have received a copy of the GNU Lesser General Public License 10.18 + * along with this library; if not, write to the Free Software 10.19 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 10.20 + */ 10.21 + 10.22 +#ifndef _XEN_LIB_FILE_STREAM_H_ 10.23 +#define _XEN_LIB_FILE_STREAM_H_ 10.24 + 10.25 +#ifndef __KERNEL__ 10.26 +#include "iostream.h" 10.27 +#include <stdio.h> 10.28 + 10.29 +extern IOStream *file_stream_new(FILE *f); 10.30 +extern IOStream *file_stream_fopen(const char *file, const char *flags); 10.31 +extern IOStream *file_stream_fdopen(int fd, const char *flags); 10.32 +extern IOStream get_stream_stdout(void); 10.33 +extern IOStream get_stream_stderr(void); 10.34 +extern IOStream get_stream_stdin(void); 10.35 + 10.36 +extern int file_stream_setvbuf(IOStream *io, char *buf, int mode, size_t size); 10.37 +#endif 10.38 +#endif /* !_XEN_LIB_FILE_STREAM_H_ */
11.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 11.2 +++ b/tools/lib/gzip_stream.c Tue Jun 29 12:05:29 2004 +0000 11.3 @@ -0,0 +1,171 @@ 11.4 +/* $Id: gzip_stream.c,v 1.4 2003/09/30 15:22:53 mjw Exp $ */ 11.5 +/* 11.6 + * Copyright (C) 2003 Hewlett-Packard Company. 11.7 + * 11.8 + * This library is free software; you can redistribute it and/or modify 11.9 + * it under the terms of the GNU Lesser General Public License as published by 11.10 + * the Free Software Foundation; either version 2.1 of the License, or 11.11 + * (at your option) any later version. 11.12 + * 11.13 + * This library is distributed in the hope that it will be useful, 11.14 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 11.15 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11.16 + * GNU Lesser General Public License for more details. 11.17 + * 11.18 + * You should have received a copy of the GNU Lesser General Public License 11.19 + * along with this library; if not, write to the Free Software 11.20 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 11.21 + */ 11.22 + 11.23 +/** @file 11.24 + * An IOStream implementation using zlib gzFile to provide 11.25 + * compression and decompression. 11.26 + */ 11.27 +#ifndef __KERNEL__ 11.28 + 11.29 +#include <stdio.h> 11.30 +#include <stdlib.h> 11.31 + 11.32 +#include "zlib.h" 11.33 + 11.34 +#include "allocate.h" 11.35 +#include "gzip_stream.h" 11.36 + 11.37 +static int gzip_read(IOStream *s, void *buf, size_t n); 11.38 +static int gzip_write(IOStream *s, const void *buf, size_t n); 11.39 +static int gzip_error(IOStream *s); 11.40 +static int gzip_close(IOStream *s); 11.41 +static void gzip_free(IOStream *s); 11.42 +static int gzip_flush(IOStream *s); 11.43 + 11.44 +/** Methods used by a gzFile* IOStream. */ 11.45 +static const IOMethods gzip_methods = { 11.46 + read: gzip_read, 11.47 + write: gzip_write, 11.48 + error: gzip_error, 11.49 + close: gzip_close, 11.50 + free: gzip_free, 11.51 + flush: gzip_flush, 11.52 +}; 11.53 + 11.54 +/** Get the underlying gzFile*. 11.55 + * 11.56 + * @param s gzip stream 11.57 + * @return the stream s wraps 11.58 + */ 11.59 +static inline gzFile get_gzfile(IOStream *s){ 11.60 + return (gzFile)s->data; 11.61 +} 11.62 + 11.63 +/** Write to the underlying stream. 11.64 + * 11.65 + * @param stream destination 11.66 + * @param buf data 11.67 + * @param n number of bytes to write 11.68 + * @return number of bytes written 11.69 + */ 11.70 +static int gzip_write(IOStream *s, const void *buf, size_t n){ 11.71 + return gzwrite(get_gzfile(s), (void*)buf, n); 11.72 +} 11.73 + 11.74 +/** Read from the underlying stream. 11.75 + * 11.76 + * @param stream input 11.77 + * @param buf where to put input 11.78 + * @param n number of bytes to read 11.79 + * @return number of bytes read 11.80 + */ 11.81 +static int gzip_read(IOStream *s, void *buf, size_t n){ 11.82 + return gzread(get_gzfile(s), buf, n); 11.83 +} 11.84 + 11.85 +/** Flush the underlying stream. 11.86 + * 11.87 + * @param s gzip stream 11.88 + * @return 0 on success, error code otherwise 11.89 + */ 11.90 +static int gzip_flush(IOStream *s){ 11.91 + //return gzflush(get_gzfile(s), Z_NO_FLUSH); 11.92 + return gzflush(get_gzfile(s), Z_SYNC_FLUSH); 11.93 + //return gzflush(get_gzfile(s), Z_FULL_FLUSH); 11.94 +} 11.95 + 11.96 +/** Check if a stream has an error. 11.97 + * 11.98 + * @param s gzip stream 11.99 + * @return 1 if has an error, 0 otherwise 11.100 + */ 11.101 +static int gzip_error(IOStream *s){ 11.102 + int err; 11.103 + gzFile *gz = get_gzfile(s); 11.104 + gzerror(gz, &err); 11.105 + return (err == Z_ERRNO ? 1 /* ferror(gzfile(gz)) */ : err); 11.106 +} 11.107 + 11.108 +/** Close a gzip stream. 11.109 + * 11.110 + * @param s gzip stream to close 11.111 + * @return result of the close 11.112 + */ 11.113 +static int gzip_close(IOStream *s){ 11.114 + return gzclose(get_gzfile(s)); 11.115 +} 11.116 + 11.117 +/** Free a gzip stream. 11.118 + * 11.119 + * @param s gzip stream 11.120 + */ 11.121 +static void gzip_free(IOStream *s){ 11.122 + // Do nothing - fclose does it all? 11.123 +} 11.124 + 11.125 +/** Create an IOStream for a gzip stream. 11.126 + * 11.127 + * @param f stream to wrap 11.128 + * @return new IOStream using f for i/o 11.129 + */ 11.130 +IOStream *gzip_stream_new(gzFile *f){ 11.131 + IOStream *io = ALLOCATE(IOStream); 11.132 + if(io){ 11.133 + io->methods = &gzip_methods; 11.134 + io->data = (void*)f; 11.135 + } 11.136 + return io; 11.137 +} 11.138 + 11.139 +/** IOStream version of fopen(). 11.140 + * 11.141 + * @param file name of the file to open 11.142 + * @param flags giving the mode to open in (as for fopen()) 11.143 + * @return new stream for the open file, or NULL if failed 11.144 + */ 11.145 +IOStream *gzip_stream_fopen(const char *file, const char *flags){ 11.146 + IOStream *io = NULL; 11.147 + gzFile *fgz; 11.148 + fgz = gzopen(file, flags); 11.149 + if(fgz){ 11.150 + io = gzip_stream_new(fgz); 11.151 + if(!io){ 11.152 + gzclose(fgz); 11.153 + //free(fgz); // gzclose frees ? 11.154 + } 11.155 + } 11.156 + return io; 11.157 +} 11.158 + 11.159 +/** IOStream version of fdopen(). 11.160 + * 11.161 + * @param fd file descriptor 11.162 + * @param flags giving the mode to open in (as for fdopen()) 11.163 + * @return new stream for the open file, or NULL if failed 11.164 + */ 11.165 +IOStream *gzip_stream_fdopen(int fd, const char *flags){ 11.166 + IOStream *io = NULL; 11.167 + gzFile *fgz; 11.168 + fgz = gzdopen(fd, flags); 11.169 + if(fgz){ 11.170 + io = gzip_stream_new(fgz); 11.171 + } 11.172 + return io; 11.173 +} 11.174 +#endif
12.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 12.2 +++ b/tools/lib/gzip_stream.h Tue Jun 29 12:05:29 2004 +0000 12.3 @@ -0,0 +1,31 @@ 12.4 +#/* $Id: gzip_stream.h,v 1.3 2003/09/30 15:22:53 mjw Exp $ */ 12.5 +/* 12.6 + * Copyright (C) 2003 Hewlett-Packard Company. 12.7 + * 12.8 + * This library is free software; you can redistribute it and/or modify 12.9 + * it under the terms of the GNU Lesser General Public License as published by 12.10 + * the Free Software Foundation; either version 2.1 of the License, or 12.11 + * (at your option) any later version. 12.12 + * 12.13 + * This library is distributed in the hope that it will be useful, 12.14 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 12.15 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12.16 + * GNU Lesser General Public License for more details. 12.17 + * 12.18 + * You should have received a copy of the GNU Lesser General Public License 12.19 + * along with this library; if not, write to the Free Software 12.20 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 12.21 + */ 12.22 + 12.23 +#ifndef _SP_GZIP_STREAM_H_ 12.24 +#define _SP_GZIP_STREAM_H_ 12.25 + 12.26 +#ifndef __KERNEL__ 12.27 +#include "iostream.h" 12.28 +#include "zlib.h" 12.29 + 12.30 +extern IOStream *gzip_stream_new(gzFile *f); 12.31 +extern IOStream *gzip_stream_fopen(const char *file, const char *flags); 12.32 +extern IOStream *gzip_stream_fdopen(int fd, const char *flags); 12.33 +#endif 12.34 +#endif /* !_SP_FILE_STREAM_H_ */
13.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 13.2 +++ b/tools/lib/hash_table.c Tue Jun 29 12:05:29 2004 +0000 13.3 @@ -0,0 +1,640 @@ 13.4 +/* 13.5 + * Copyright (C) 2001 - 2004 Mike Wray <mike.wray@hp.com> 13.6 + * 13.7 + * This library is free software; you can redistribute it and/or modify 13.8 + * it under the terms of the GNU Lesser General Public License as published by 13.9 + * the Free Software Foundation; either version 2.1 of the License, or 13.10 + * (at your option) any later version. 13.11 + * 13.12 + * This library is distributed in the hope that it will be useful, 13.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 13.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13.15 + * GNU Lesser General Public License for more details. 13.16 + * 13.17 + * You should have received a copy of the GNU Lesser General Public License 13.18 + * along with this library; if not, write to the Free Software 13.19 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 13.20 + */ 13.21 + 13.22 +#ifdef __KERNEL__ 13.23 +# include <linux/config.h> 13.24 +# include <linux/module.h> 13.25 +# include <linux/kernel.h> 13.26 +# include <linux/errno.h> 13.27 +#else 13.28 +# include <errno.h> 13.29 +# include <stddef.h> 13.30 +#endif 13.31 + 13.32 +//#include <limits.h> 13.33 + 13.34 +#include "allocate.h" 13.35 +#include "hash_table.h" 13.36 + 13.37 +/** @file 13.38 + * Base support for hashtables. 13.39 + * 13.40 + * Hash codes are reduced modulo the number of buckets to index tables, 13.41 + * so there is no need for hash functions to limit the range of hashcodes. 13.42 + * In fact it is assumed that hashcodes do not change when the number of 13.43 + * buckets in the table changes. 13.44 + */ 13.45 + 13.46 +/*==========================================================================*/ 13.47 +/** Number of bits in half a word. */ 13.48 +//#if __WORDSIZE == 64 13.49 +//#define HALF_WORD_BITS 32 13.50 +//#else 13.51 +#define HALF_WORD_BITS 16 13.52 +//#endif 13.53 + 13.54 +/** Mask for lo half of a word. On 32-bit this is 13.55 + * (1<<16) - 1 = 65535 = 0xffff 13.56 + * It's 4294967295 = 0xffffffff on 64-bit. 13.57 + */ 13.58 +#define LO_HALF_MASK ((1 << HALF_WORD_BITS) - 1) 13.59 + 13.60 +/** Get the lo half of a word. */ 13.61 +#define LO_HALF(x) ((x) & LO_HALF_MASK) 13.62 + 13.63 +/** Get the hi half of a word. */ 13.64 +#define HI_HALF(x) ((x) >> HALF_WORD_BITS) 13.65 + 13.66 +/** Do a full hash on both inputs, using DES-style non-linear scrambling. 13.67 + * Both inputs are replaced with the results of the hash. 13.68 + * 13.69 + * @param pleft input/output word 13.70 + * @param pright input/output word 13.71 + */ 13.72 +void pseudo_des(unsigned long *pleft, unsigned long *pright){ 13.73 + // Bit-rich mixing constant. 13.74 + static const unsigned long a_mixer[] = { 13.75 + 0xbaa96887L, 0x1e17d32cL, 0x03bcdc3cL, 0x0f33d1b2L, }; 13.76 + 13.77 + // Bit-rich mixing constant. 13.78 + static const unsigned long b_mixer[] = { 13.79 + 0x4b0f3b58L, 0xe874f0c3L, 0x6955c5a6L, 0x55a7ca46L, }; 13.80 + 13.81 + // Number of iterations - must be 2 or 4. 13.82 + static const int ncycle = 4; 13.83 + //static const int ncycle = 2; 13.84 + 13.85 + unsigned long left = *pleft, right = *pright; 13.86 + unsigned long v, v_hi, v_lo; 13.87 + int i; 13.88 + 13.89 + for(i=0; i<ncycle; i++){ 13.90 + // Flip some bits in right to get v. 13.91 + v = right; 13.92 + v ^= a_mixer[i]; 13.93 + // Get lo and hi halves of v. 13.94 + v_lo = LO_HALF(v); 13.95 + v_hi = HI_HALF(v); 13.96 + // Non-linear mix of the halves of v. 13.97 + v = ((v_lo * v_lo) + ~(v_hi * v_hi)); 13.98 + // Swap the halves of v. 13.99 + v = (HI_HALF(v) | (LO_HALF(v) << HALF_WORD_BITS)); 13.100 + // Flip some bits. 13.101 + v ^= b_mixer[i]; 13.102 + // More non-linear mixing. 13.103 + v += (v_lo * v_hi); 13.104 + v ^= left; 13.105 + left = right; 13.106 + right = v; 13.107 + } 13.108 + *pleft = left; 13.109 + *pright = right; 13.110 +} 13.111 + 13.112 +/** Hash a string. 13.113 + * 13.114 + * @param s input to hash 13.115 + * @return hashcode 13.116 + */ 13.117 +Hashcode hash_string(char *s){ 13.118 + Hashcode h = 0; 13.119 + if(s){ 13.120 + for( ; *s; s++){ 13.121 + h = hash_2ul(h, *s); 13.122 + } 13.123 + } 13.124 + return h; 13.125 +} 13.126 + 13.127 +/** Get the bucket for a hashcode in a hash table. 13.128 + * 13.129 + * @param table to get bucket from 13.130 + * @param hashcode to get bucket for 13.131 + * @return bucket 13.132 + */ 13.133 +inline HTBucket * get_bucket(HashTable *table, Hashcode hashcode){ 13.134 + return table->buckets + (hashcode % table->buckets_n); 13.135 +} 13.136 + 13.137 +/** Initialize a hash table. 13.138 + * Can be safely called more than once. 13.139 + * 13.140 + * @param table to initialize 13.141 + */ 13.142 +void HashTable_init(HashTable *table){ 13.143 + int i; 13.144 + 13.145 + if(!table->init_done){ 13.146 + table->init_done = 1; 13.147 + table->next_id = 0; 13.148 + for(i=0; i<table->buckets_n; i++){ 13.149 + HTBucket *bucket = get_bucket(table, i); 13.150 + bucket->head = 0; 13.151 + bucket->count = 0; 13.152 + } 13.153 + table->entry_count = 0; 13.154 + } 13.155 +} 13.156 + 13.157 +/** Allocate a new hashtable. 13.158 + * If the number of buckets is not positive the default is used. 13.159 + * The number of buckets should usually be prime. 13.160 + * 13.161 + * @param buckets_n number of buckets 13.162 + * @return new hashtable or null 13.163 + */ 13.164 +HashTable *HashTable_new(int buckets_n){ 13.165 + HashTable *z = ALLOCATE(HashTable); 13.166 + if(!z) goto exit; 13.167 + if(buckets_n <= 0){ 13.168 + buckets_n = HT_BUCKETS_N; 13.169 + } 13.170 + z->buckets = (HTBucket*)allocate(buckets_n * sizeof(HTBucket)); 13.171 + if(!z->buckets){ 13.172 + deallocate(z); 13.173 + z = 0; 13.174 + goto exit; 13.175 + } 13.176 + z->buckets_n = buckets_n; 13.177 + HashTable_init(z); 13.178 + exit: 13.179 + return z; 13.180 +} 13.181 + 13.182 +/** Free a hashtable. 13.183 + * Any entries are removed and freed. 13.184 + * 13.185 + * @param h hashtable (ignored if null) 13.186 + */ 13.187 +void HashTable_free(HashTable *h){ 13.188 + if(h){ 13.189 + HashTable_clear(h); 13.190 + deallocate(h->buckets); 13.191 + deallocate(h); 13.192 + } 13.193 +} 13.194 + 13.195 +/** Push an entry on the list in the bucket for a given hashcode. 13.196 + * 13.197 + * @param table to add entry to 13.198 + * @param hashcode for the entry 13.199 + * @param entry to add 13.200 + */ 13.201 +static inline void push_on_bucket(HashTable *table, Hashcode hashcode, 13.202 + HTEntry *entry){ 13.203 + HTBucket *bucket; 13.204 + HTEntry *old_head; 13.205 + 13.206 + bucket = get_bucket(table, hashcode); 13.207 + old_head = bucket->head; 13.208 + bucket->count++; 13.209 + bucket->head = entry; 13.210 + entry->next = old_head; 13.211 +} 13.212 + 13.213 +/** Change the number of buckets in a hashtable. 13.214 + * No-op if the number of buckets is not positive. 13.215 + * Existing entries are reallocated to buckets based on their hashcodes. 13.216 + * The table is unmodified if the number of buckets cannot be changed. 13.217 + * 13.218 + * @param table hashtable 13.219 + * @param buckets_n new number of buckets 13.220 + * @return 0 on success, error code otherwise 13.221 + */ 13.222 +int HashTable_set_buckets_n(HashTable *table, int buckets_n){ 13.223 + int err = 0; 13.224 + HTBucket *old_buckets = table->buckets; 13.225 + int old_buckets_n = table->buckets_n; 13.226 + int i; 13.227 + 13.228 + if(buckets_n <= 0){ 13.229 + err = -EINVAL; 13.230 + goto exit; 13.231 + } 13.232 + table->buckets = (HTBucket*)allocate(buckets_n * sizeof(HTBucket)); 13.233 + if(!table->buckets){ 13.234 + err = -ENOMEM; 13.235 + table->buckets = old_buckets; 13.236 + goto exit; 13.237 + } 13.238 + table->buckets_n = buckets_n; 13.239 + for(i=0; i<old_buckets_n; i++){ 13.240 + HTBucket *bucket = old_buckets + i; 13.241 + HTEntry *entry, *next; 13.242 + for(entry = bucket->head; entry; entry = next){ 13.243 + next = entry->next; 13.244 + push_on_bucket(table, entry->hashcode, entry); 13.245 + } 13.246 + } 13.247 + deallocate(old_buckets); 13.248 + exit: 13.249 + return err; 13.250 +} 13.251 + 13.252 +/** Adjust the number of buckets so the table is neither too full nor too empty. 13.253 + * The table is unmodified if adjusting fails. 13.254 + * 13.255 + * @param table hash table 13.256 + * @param buckets_min minimum number of buckets (use default if 0 or negative) 13.257 + * @return 0 on success, error code otherwise 13.258 + */ 13.259 +int HashTable_adjust(HashTable *table, int buckets_min){ 13.260 + int buckets_n = 0; 13.261 + int err = 0; 13.262 + if(buckets_min <= 0) buckets_min = HT_BUCKETS_N; 13.263 + if(table->entry_count >= table->buckets_n){ 13.264 + // The table is dense - expand it. 13.265 + buckets_n = 2 * table->buckets_n; 13.266 + } else if((table->buckets_n > buckets_min) && 13.267 + (4 * table->entry_count < table->buckets_n)){ 13.268 + // The table is more than minimum size and sparse - shrink it. 13.269 + buckets_n = 2 * table->entry_count; 13.270 + if(buckets_n < buckets_min) buckets_n = buckets_min; 13.271 + } 13.272 + if(buckets_n){ 13.273 + err = HashTable_set_buckets_n(table, buckets_n); 13.274 + } 13.275 + return err; 13.276 +} 13.277 + 13.278 +/** Allocate a new entry for a given value. 13.279 + * 13.280 + * @param value to put in the entry 13.281 + * @return entry, or 0 on failure 13.282 + */ 13.283 +HTEntry * HTEntry_new(Hashcode hashcode, void *key, void *value){ 13.284 + HTEntry *z = ALLOCATE(HTEntry); 13.285 + if(z){ 13.286 + z->hashcode = hashcode; 13.287 + z->key = key; 13.288 + z->value = value; 13.289 + } 13.290 + return z; 13.291 +} 13.292 + 13.293 +/** Free an entry. 13.294 + * 13.295 + * @param z entry to free 13.296 + */ 13.297 +inline void HTEntry_free(HTEntry *z){ 13.298 + if(z){ 13.299 + deallocate(z); 13.300 + } 13.301 +} 13.302 + 13.303 +/** Free an entry in a hashtable. 13.304 + * The table's entry_free_fn is used is defined, otherwise 13.305 + * the HTEntry itself is freed. 13.306 + * 13.307 + * @param table hashtable 13.308 + * @param entry to free 13.309 + */ 13.310 +inline void HashTable_free_entry(HashTable *table, HTEntry *entry){ 13.311 + if(!entry)return; 13.312 + if(table && table->entry_free_fn){ 13.313 + table->entry_free_fn(table, entry); 13.314 + } else { 13.315 + HTEntry_free(entry); 13.316 + } 13.317 +} 13.318 + 13.319 +/** Get the first entry satisfying a test from the bucket for the 13.320 + * given hashcode. 13.321 + * 13.322 + * @param table to look in 13.323 + * @param hashcode indicates the bucket 13.324 + * @param test_fn test to apply to elements 13.325 + * @param arg first argument to calls to test_fn 13.326 + * @return entry found, or 0 13.327 + */ 13.328 +inline HTEntry * HashTable_find_entry(HashTable *table, Hashcode hashcode, 13.329 + TableTestFn *test_fn, TableArg arg){ 13.330 + HTBucket *bucket; 13.331 + HTEntry *entry = 0; 13.332 + HTEntry *next; 13.333 + 13.334 + bucket = get_bucket(table, hashcode); 13.335 + for(entry = bucket->head; entry; entry = next){ 13.336 + next = entry->next; 13.337 + if(test_fn(arg, table, entry)){ 13.338 + break; 13.339 + } 13.340 + } 13.341 + return entry; 13.342 +} 13.343 + 13.344 +/** Test hashtable keys for equality. 13.345 + * Uses the table's key_equal_fn if defined, otherwise pointer equality. 13.346 + * 13.347 + * @param key1 key to compare 13.348 + * @param key2 key to compare 13.349 + * @return 1 if equal, 0 otherwise 13.350 + */ 13.351 +inline int HashTable_key_equal(HashTable *table, void *key1, void *key2){ 13.352 + return (table->key_equal_fn ? table->key_equal_fn(key1, key2) : key1==key2); 13.353 +} 13.354 + 13.355 +/** Compute the hashcode of a hashtable key. 13.356 + * The table's key_hash_fn is used if defined, otherwise the address of 13.357 + * the key is hashed. 13.358 + * 13.359 + * @param table hashtable 13.360 + * @param key to hash 13.361 + * @return hashcode 13.362 + */ 13.363 +inline Hashcode HashTable_key_hash(HashTable *table, void *key){ 13.364 + return (table->key_hash_fn ? table->key_hash_fn(key) : hash_ul((unsigned long)key)); 13.365 +} 13.366 + 13.367 +/** Test if an entry has a given key. 13.368 + * 13.369 + * @param arg containing key to test for 13.370 + * @param table the entry is in 13.371 + * @param entry to test 13.372 + * @return 1 if the entry has the key, 0 otherwise 13.373 + */ 13.374 +static inline int has_key(TableArg arg, HashTable *table, HTEntry *entry){ 13.375 + return HashTable_key_equal(table, arg.ptr, entry->key); 13.376 +} 13.377 + 13.378 +/** Get an entry with a given key. 13.379 + * 13.380 + * @param table to search 13.381 + * @param key to look for 13.382 + * @return entry if found, null otherwise 13.383 + */ 13.384 +#if 0 13.385 +inline HTEntry * HashTable_get_entry(HashTable *table, void *key){ 13.386 + TableArg arg = { ptr: key }; 13.387 + return HashTable_find_entry(table, HashTable_key_hash(table, key), has_key, arg); 13.388 +} 13.389 +#else 13.390 +inline HTEntry * HashTable_get_entry(HashTable *table, void *key){ 13.391 + Hashcode hashcode; 13.392 + HTBucket *bucket; 13.393 + HTEntry *entry = 0; 13.394 + HTEntry *next; 13.395 + 13.396 + hashcode = HashTable_key_hash(table, key); 13.397 + bucket = get_bucket(table, hashcode); 13.398 + for(entry = bucket->head; entry; entry = next){ 13.399 + next = entry->next; 13.400 + if(HashTable_key_equal(table, key, entry->key)){ 13.401 + break; 13.402 + } 13.403 + } 13.404 + return entry; 13.405 +} 13.406 +#endif 13.407 + 13.408 +/** Get the value of an entry with a given key. 13.409 + * 13.410 + * @param table to search 13.411 + * @param key to look for 13.412 + * @return value if an entry was found, null otherwise 13.413 + */ 13.414 +inline void * HashTable_get(HashTable *table, void *key){ 13.415 + HTEntry *entry = HashTable_get_entry(table, key); 13.416 + return (entry ? entry->value : 0); 13.417 +} 13.418 + 13.419 +/** Print the buckets in a table. 13.420 + * 13.421 + * @param table to print 13.422 + */ 13.423 +void show_buckets(HashTable *table, IOStream *io){ 13.424 + int i,j ; 13.425 + IOStream_print(io, "entry_count=%d buckets_n=%d\n", table->entry_count, table->buckets_n); 13.426 + for(i=0; i<table->buckets_n; i++){ 13.427 + if(0 || table->buckets[i].count>0){ 13.428 + IOStream_print(io, "bucket %3d %3d %10p ", i, 13.429 + table->buckets[i].count, 13.430 + table->buckets[i].head); 13.431 + for(j = table->buckets[i].count; j>0; j--){ 13.432 + IOStream_print(io, "+"); 13.433 + } 13.434 + IOStream_print(io, "\n"); 13.435 + } 13.436 + } 13.437 + HashTable_print(table, io); 13.438 +} 13.439 + 13.440 +/** Print an entry in a table. 13.441 + * 13.442 + * @param entry to print 13.443 + * @param arg a pointer to an IOStream to print to 13.444 + * @return 0 13.445 + */ 13.446 +static int print_entry(TableArg arg, HashTable *table, HTEntry *entry){ 13.447 + IOStream *io = (IOStream*)arg.ptr; 13.448 + IOStream_print(io, " b=%4lx h=%08lx i=%08lx |-> e=%8p k=%8p v=%8p\n", 13.449 + entry->hashcode % table->buckets_n, 13.450 + entry->hashcode, 13.451 + entry->index, 13.452 + entry, entry->key, entry->value); 13.453 + return 0; 13.454 +} 13.455 + 13.456 +/** Print a hash table. 13.457 + * 13.458 + * @param table to print 13.459 + */ 13.460 +void HashTable_print(HashTable *table, IOStream *io){ 13.461 + IOStream_print(io, "{\n"); 13.462 + HashTable_map(table, print_entry, (TableArg){ ptr: io }); 13.463 + IOStream_print(io, "}\n"); 13.464 +} 13.465 +/*==========================================================================*/ 13.466 + 13.467 +/** Get the next entry id to use for a table. 13.468 + * 13.469 + * @param table hash table 13.470 + * @return non-zero entry id 13.471 + */ 13.472 +static inline unsigned long get_next_id(HashTable *table){ 13.473 + unsigned long id; 13.474 + 13.475 + if(table->next_id == 0){ 13.476 + table->next_id = 1; 13.477 + } 13.478 + id = table->next_id++; 13.479 + return id; 13.480 +} 13.481 + 13.482 +/** Add an entry to the bucket for the 13.483 + * given hashcode. 13.484 + * 13.485 + * @param table to insert in 13.486 + * @param hashcode indicates the bucket 13.487 + * @param key to add an entry for 13.488 + * @param value to add an entry for 13.489 + * @return entry on success, 0 on failure 13.490 + */ 13.491 +inline HTEntry * HashTable_add_entry(HashTable *table, Hashcode hashcode, void *key, void *value){ 13.492 + HTEntry *entry = HTEntry_new(hashcode, key, value); 13.493 + if(entry){ 13.494 + entry->index = get_next_id(table); 13.495 + push_on_bucket(table, hashcode, entry); 13.496 + table->entry_count++; 13.497 + } 13.498 + return entry; 13.499 +} 13.500 + 13.501 +/** Move the front entry for a bucket to the correct point in the bucket order as 13.502 + * defined by the order function. If this is called every time a new entry is added 13.503 + * the bucket will be maintained in sorted order. 13.504 + * 13.505 + * @param table to modify 13.506 + * @param hashcode indicates the bucket 13.507 + * @param order entry comparison function 13.508 + * @return 0 if an entry was moved, 1 if not 13.509 + */ 13.510 +int HashTable_order_bucket(HashTable *table, Hashcode hashcode, TableOrderFn *order){ 13.511 + HTEntry *new_entry = NULL, *prev = NULL, *entry = NULL; 13.512 + HTBucket *bucket; 13.513 + int err = 1; 13.514 + 13.515 + bucket = get_bucket(table, hashcode); 13.516 + new_entry = bucket->head; 13.517 + if(!new_entry || !new_entry->next) goto exit; 13.518 + for(entry = new_entry->next; entry; prev = entry, entry = entry->next){ 13.519 + if(order(new_entry, entry) <= 0) break; 13.520 + } 13.521 + if(prev){ 13.522 + err = 0; 13.523 + bucket->head = new_entry->next; 13.524 + new_entry->next = entry; 13.525 + prev->next = new_entry; 13.526 + } 13.527 + exit: 13.528 + return err; 13.529 +} 13.530 + 13.531 +/** Add an entry to a hashtable. 13.532 + * The entry is added to the bucket for its key's hashcode. 13.533 + * 13.534 + * @param table to insert in 13.535 + * @param key to add an entry for 13.536 + * @param value to add an entry for 13.537 + * @return entry on success, 0 on failure 13.538 + */ 13.539 +inline HTEntry * HashTable_add(HashTable *table, void *key, void *value){ 13.540 + return HashTable_add_entry(table, HashTable_key_hash(table, key), key, value); 13.541 +} 13.542 + 13.543 + 13.544 +/** Remove entries satisfying a test from the bucket for the 13.545 + * given hashcode. 13.546 + * 13.547 + * @param table to remove from 13.548 + * @param hashcode indicates the bucket 13.549 + * @param test_fn test to apply to elements 13.550 + * @param arg first argument to calls to test_fn 13.551 + * @return number of entries removed 13.552 + */ 13.553 +inline int HashTable_remove_entry(HashTable *table, Hashcode hashcode, 13.554 + TableTestFn *test_fn, TableArg arg){ 13.555 + HTBucket *bucket; 13.556 + HTEntry *entry, *prev = 0, *next; 13.557 + int removed_count = 0; 13.558 + 13.559 + bucket = get_bucket(table, hashcode); 13.560 + for(entry = bucket->head; entry; entry = next){ 13.561 + next = entry->next; 13.562 + if(test_fn(arg, table, entry)){ 13.563 + if(prev){ 13.564 + prev->next = next; 13.565 + } else { 13.566 + bucket->head = next; 13.567 + } 13.568 + bucket->count--; 13.569 + table->entry_count--; 13.570 + removed_count++; 13.571 + HashTable_free_entry(table, entry); 13.572 + entry = 0; 13.573 + } 13.574 + prev = entry; 13.575 + } 13.576 + return removed_count; 13.577 +} 13.578 + 13.579 +/** Remove entries with a given key. 13.580 + * 13.581 + * @param table to remove from 13.582 + * @param key of entries to remove 13.583 + * @return number of entries removed 13.584 + */ 13.585 +inline int HashTable_remove(HashTable *table, void *key){ 13.586 +#if 1 13.587 + Hashcode hashcode; 13.588 + HTBucket *bucket; 13.589 + HTEntry *entry, *prev = 0, *next; 13.590 + int removed_count = 0; 13.591 + 13.592 + hashcode = HashTable_key_hash(table, key); 13.593 + bucket = get_bucket(table, hashcode); 13.594 + for(entry = bucket->head; entry; entry = next){ 13.595 + next = entry->next; 13.596 + if(HashTable_key_equal(table, key, entry->key)){ 13.597 + if(prev){ 13.598 + prev->next = next; 13.599 + } else { 13.600 + bucket->head = next; 13.601 + } 13.602 + bucket->count--; 13.603 + table->entry_count--; 13.604 + removed_count++; 13.605 + HashTable_free_entry(table, entry); 13.606 + entry = 0; 13.607 + } 13.608 + prev = entry; 13.609 + } 13.610 + return removed_count; 13.611 +#else 13.612 + return HashTable_remove_entry(table, HashTable_key_hash(table, key), 13.613 + has_key, (TableArg){ ptr: key}); 13.614 +#endif 13.615 +} 13.616 + 13.617 +/** Remove (and free) all the entries in a bucket. 13.618 + * 13.619 + * @param bucket to clear 13.620 + */ 13.621 +static inline void bucket_clear(HashTable *table, HTBucket *bucket){ 13.622 + HTEntry *entry, *next; 13.623 + 13.624 + for(entry = bucket->head; entry; entry = next){ 13.625 + next = entry->next; 13.626 + HashTable_free_entry(table, entry); 13.627 + } 13.628 + bucket->head = 0; 13.629 + table->entry_count -= bucket->count; 13.630 + bucket->count = 0; 13.631 +} 13.632 + 13.633 +/** Remove (and free) all the entries in a table. 13.634 + * 13.635 + * @param table to clear 13.636 + */ 13.637 +void HashTable_clear(HashTable *table){ 13.638 + int i, n = table->buckets_n; 13.639 + 13.640 + for(i=0; i<n; i++){ 13.641 + bucket_clear(table, table->buckets + i); 13.642 + } 13.643 +}
14.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 14.2 +++ b/tools/lib/hash_table.h Tue Jun 29 12:05:29 2004 +0000 14.3 @@ -0,0 +1,295 @@ 14.4 +/* $Id: hash_table.h,v 1.1 2004/03/30 16:21:26 mjw Exp $ */ 14.5 +/* 14.6 + * Copyright (C) 2001 - 2004 Mike Wray <mike.wray@hp.com> 14.7 + * 14.8 + * This library is free software; you can redistribute it and/or modify 14.9 + * it under the terms of the GNU Lesser General Public License as published by 14.10 + * the Free Software Foundation; either version 2.1 of the License, or 14.11 + * (at your option) any later version. 14.12 + * 14.13 + * This library is distributed in the hope that it will be useful, 14.14 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 14.15 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14.16 + * GNU Lesser General Public License for more details. 14.17 + * 14.18 + * You should have received a copy of the GNU Lesser General Public License 14.19 + * along with this library; if not, write to the Free Software 14.20 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 14.21 + */ 14.22 + 14.23 +#ifndef _XEN_LIB_HASH_TABLE_H_ 14.24 +#define _XEN_LIB_HASH_TABLE_H_ 14.25 + 14.26 +#include "iostream.h" 14.27 + 14.28 +typedef unsigned long Hashcode; 14.29 + 14.30 +/** Type used to pass parameters to table functions. */ 14.31 +typedef union TableArg { 14.32 + unsigned long ul; 14.33 + void *ptr; 14.34 +} TableArg; 14.35 + 14.36 +/** An entry in a bucket list. */ 14.37 +typedef struct HTEntry { 14.38 + /** Hashcode of the entry's key. */ 14.39 + Hashcode hashcode; 14.40 + /** Identifier for this entry in the table. */ 14.41 + int index; 14.42 + /** The key for this entry. */ 14.43 + void *key; 14.44 + /** The value in this entry. */ 14.45 + void *value; 14.46 + /** The next entry in the list. */ 14.47 + struct HTEntry *next; 14.48 +} HTEntry; 14.49 + 14.50 +/** A bucket in a rule table. */ 14.51 +typedef struct HTBucket { 14.52 + /** Number of entries in the bucket. */ 14.53 + int count; 14.54 + /** First entry in the bucket (may be null). */ 14.55 + HTEntry *head; 14.56 +} HTBucket; 14.57 + 14.58 +/** Default number of buckets in a hash table. 14.59 + * You want enough buckets so the lists in the buckets will typically be short. 14.60 + * It's a good idea if this is prime, since that will help to spread hashcodes 14.61 + * around the table. 14.62 + */ 14.63 +//#define HT_BUCKETS_N 1 14.64 +//#define HT_BUCKETS_N 3 14.65 +//#define HT_BUCKETS_N 7 14.66 +//#define HT_BUCKETS_N 17 14.67 +//#define HT_BUCKETS_N 97 14.68 +//#define HT_BUCKETS_N 211 14.69 +//#define HT_BUCKETS_N 401 14.70 +#define HT_BUCKETS_N 1021 14.71 + 14.72 +typedef struct HashTable HashTable; 14.73 + 14.74 +/** Type for a function used to select table entries. */ 14.75 +typedef int TableTestFn(TableArg arg, HashTable *table, HTEntry *entry); 14.76 + 14.77 +/** Type for a function to map over table entries. */ 14.78 +typedef int TableMapFn(TableArg arg, HashTable *table, HTEntry *entry); 14.79 + 14.80 +/** Type for a function to free table entries. */ 14.81 +typedef void TableFreeFn(HashTable *table, HTEntry *entry); 14.82 + 14.83 +/** Type for a function to hash table keys. */ 14.84 +typedef Hashcode TableHashFn(void *key); 14.85 + 14.86 +/** Type for a function to test table keys for equality. */ 14.87 +typedef int TableEqualFn(void *key1, void *key2); 14.88 + 14.89 +/** Type for a function to order table entries. */ 14.90 +typedef int TableOrderFn(HTEntry *e1, HTEntry *e2); 14.91 + 14.92 +/** General hash table. 14.93 + * A hash table with a list in each bucket. 14.94 + * Functions can be supplied for freeing entries, hashing keys, and comparing keys. 14.95 + * These all default to 0, when default behaviour treating keys as integers is used. 14.96 + */ 14.97 +struct HashTable { 14.98 + /** Flag indicating whether the table has been initialised. */ 14.99 + int init_done; 14.100 + /** Next value for the id field in inserted rules. */ 14.101 + unsigned long next_id; 14.102 + /** Number of buckets in the bucket array. */ 14.103 + int buckets_n; 14.104 + /** Array of buckets, each with its own list. */ 14.105 + HTBucket *buckets; 14.106 + /** Number of entries in the table. */ 14.107 + int entry_count; 14.108 + /** Function to free keys and values in entries. */ 14.109 + TableFreeFn *entry_free_fn; 14.110 + /** Function to hash keys. */ 14.111 + TableHashFn *key_hash_fn; 14.112 + /** Function to compare keys for equality. */ 14.113 + TableEqualFn *key_equal_fn; 14.114 + /** Place for the user of the table to hang extra data. */ 14.115 + void *user_data; 14.116 +}; 14.117 + 14.118 +extern HashTable *HashTable_new(int bucket_n); 14.119 +extern void HashTable_free(HashTable *table); 14.120 +extern HTEntry * HTEntry_new(Hashcode hashcode, void *key, void *value); 14.121 +extern void HTEntry_free(HTEntry *entry); 14.122 +extern int HashTable_set_bucket_n(HashTable *table, int bucket_n); 14.123 +extern void HashTable_clear(HashTable *table); 14.124 +extern HTEntry * HashTable_add_entry(HashTable *table, Hashcode hashcode, void *key, void *value); 14.125 +extern HTEntry * HashTable_get_entry(HashTable *table, void *key); 14.126 +extern HTEntry * HashTable_add(HashTable *table, void *key, void *value); 14.127 +extern void * HashTable_get(HashTable *table, void *key); 14.128 +extern int HashTable_remove(HashTable *table, void *key); 14.129 +extern HTEntry * HashTable_find_entry(HashTable *table, Hashcode hashcode, 14.130 + TableTestFn *test_fn, TableArg arg); 14.131 +extern int HashTable_remove_entry(HashTable *table, Hashcode hashcode, 14.132 + TableTestFn *test_fn, TableArg arg); 14.133 +//extern int HashTable_map(HashTable *table, TableMapFn *map_fn, TableArg arg); 14.134 +extern void HashTable_print(HashTable *table, IOStream *out); 14.135 +extern int HashTable_set_buckets_n(HashTable *table, int buckets_n); 14.136 +extern int HashTable_adjust(HashTable *table, int buckets_min); 14.137 +extern void pseudo_des(unsigned long *pleft, unsigned long *pright); 14.138 +extern Hashcode hash_string(char *s); 14.139 + 14.140 +extern int HashTable_order_bucket(HashTable *table, Hashcode hashcode, TableOrderFn *order); 14.141 + 14.142 +/** Control whether to use hashing based on DES or simple 14.143 + * hashing. DES hashing is `more random' but much more expensive. 14.144 + */ 14.145 +#define HASH_PSEUDO_DES 0 14.146 + 14.147 +/** Hash a long using a quick and dirty linear congruential random number generator. 14.148 + * See `Numerical Recipes in C', Chapter 7, "An Even Quicker Generator". 14.149 + * 14.150 + * @param a value to hash 14.151 + * @return hashed input 14.152 + */ 14.153 +static inline unsigned long lcrng_hash(unsigned long a){ 14.154 + return (1664525L * a + 1013904223L); 14.155 +} 14.156 + 14.157 +/** Hash an unsigned long. 14.158 + * 14.159 + * @param a input to hash 14.160 + * @return hashcode 14.161 + */ 14.162 +static inline Hashcode hash_ul(unsigned long a){ 14.163 +#if HASH_PSEUDO_DES 14.164 + unsigned long left = a; 14.165 + unsigned long right = 0L; 14.166 + pseudo_des(&left, &right); 14.167 + return right; 14.168 +#else 14.169 + a = lcrng_hash(a); 14.170 + a = lcrng_hash(a); 14.171 + return a; 14.172 +#endif 14.173 +} 14.174 + 14.175 +/** Hash two unsigned longs together. 14.176 + * 14.177 + * @param a input to hash 14.178 + * @param b input to hash 14.179 + * @return hashcode 14.180 + */ 14.181 +static inline Hashcode hash_2ul(unsigned long a, unsigned long b){ 14.182 +#if HASH_PSEUDO_DES 14.183 + unsigned long left = a; 14.184 + unsigned long right = b; 14.185 + pseudo_des(&left, &right); 14.186 + return right; 14.187 +#else 14.188 + a = lcrng_hash(a); 14.189 + a ^= b; 14.190 + a = lcrng_hash(a); 14.191 + return a; 14.192 +#endif 14.193 +} 14.194 + 14.195 +/** Hash a hashcode and an unsigned long together. 14.196 + * 14.197 + * @param a input hashcode 14.198 + * @param b input to hash 14.199 + * @return hashcode 14.200 + */ 14.201 +static inline Hashcode hash_hul(Hashcode a, unsigned long b){ 14.202 +#if HASH_PSEUDO_DES 14.203 + unsigned long left = a; 14.204 + unsigned long right = b; 14.205 + pseudo_des(&left, &right); 14.206 + return right; 14.207 +#else 14.208 + a ^= b; 14.209 + a = lcrng_hash(a); 14.210 + return a; 14.211 +#endif 14.212 +} 14.213 + 14.214 +/** Macro to declare variables for HashTable_for_each() to use. 14.215 + * 14.216 + * @param entry variable that is set to entries in the table 14.217 + */ 14.218 +#define HashTable_for_decl(entry) \ 14.219 + HashTable *_var_table; \ 14.220 + HTBucket *_var_bucket; \ 14.221 + HTBucket *_var_end; \ 14.222 + HTEntry *_var_next; \ 14.223 + HTEntry *entry 14.224 + 14.225 +/** Macro to iterate over the entries in a hashtable. 14.226 + * Must be in a scope where HashTable_for_decl() has been used to declare 14.227 + * variables for it to use. 14.228 + * The variable 'entry' is iterated over entries in the table. 14.229 + * The code produced is syntactically a loop, so it must be followed by 14.230 + * a loop body, typically some statements in braces: 14.231 + * HashTable_for_each(entry, table){ ...loop body... } 14.232 + * 14.233 + * HashTable_for_each() and HashTable_for_decl() cannot be used for nested 14.234 + * loops as variables will clash. 14.235 + * 14.236 + * @note The simplest way to code a direct loop over the entries in a hashtable 14.237 + * is to use a loop over the buckets, with a nested loop over the entries 14.238 + * in a bucket. Using this approach in a macro means the macro contains 14.239 + * an opening brace, and calls to it must be followed by 2 braces! 14.240 + * To avoid this the code has been restructured so that it is a for loop. 14.241 + * So that statements could be used in the test expression of the for loop, 14.242 + * we have used the gcc statement expression extension ({ ... }). 14.243 + * 14.244 + * @param entry variable to iterate over the entries 14.245 + * @param table to iterate over (non-null) 14.246 + */ 14.247 +#define HashTable_for_each(entry, table) \ 14.248 + _var_table = table; \ 14.249 + _var_bucket = _var_table->buckets; \ 14.250 + _var_end = _var_bucket + _var_table->buckets_n; \ 14.251 + for(entry=0, _var_next=0; \ 14.252 + ({ if(_var_next){ \ 14.253 + entry = _var_next; \ 14.254 + _var_next = entry->next; \ 14.255 + } else { \ 14.256 + while(_var_bucket < _var_end){ \ 14.257 + entry = _var_bucket->head; \ 14.258 + _var_bucket++; \ 14.259 + if(entry){ \ 14.260 + _var_next = entry->next; \ 14.261 + break; \ 14.262 + } \ 14.263 + } \ 14.264 + }; \ 14.265 + entry; }); \ 14.266 + entry = _var_next ) 14.267 + 14.268 +/** Map a function over the entries in a table. 14.269 + * Mapping stops when the function returns a non-zero value. 14.270 + * Uses the gcc statement expression extension ({ ... }). 14.271 + * 14.272 + * @param table to map over 14.273 + * @param fn function to apply to entries 14.274 + * @param arg first argument to call the function with 14.275 + * @return 0 if fn always returned 0, first non-zero value otherwise 14.276 + */ 14.277 +#define HashTable_map(table, fn, arg) \ 14.278 + ({ HashTable_for_decl(_var_entry); \ 14.279 + TableArg _var_arg = arg; \ 14.280 + int _var_value = 0; \ 14.281 + HashTable_for_each(_var_entry, table){ \ 14.282 + if((_var_value = fn(_var_arg, _var_table, _var_entry))) break; \ 14.283 + } \ 14.284 + _var_value; }) 14.285 + 14.286 +/** Cast x to the type for a key or value in a hash table. 14.287 + * This avoids compiler warnings when using short integers 14.288 + * as keys or values (especially on 64-bit platforms). 14.289 + */ 14.290 +#define HKEY(x) ((void*)(unsigned long)(x)) 14.291 + 14.292 +/** Cast x from the type for a key or value in a hash table. 14.293 + * to an unsigned long. This avoids compiler warnings when using 14.294 + * short integers as keys or values (especially on 64-bit platforms). 14.295 + */ 14.296 +#define HVAL(x) ((unsigned long)(x)) 14.297 + 14.298 +#endif /* !_XEN_LIB_HASH_TABLE_H_ */
15.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 15.2 +++ b/tools/lib/iostream.c Tue Jun 29 12:05:29 2004 +0000 15.3 @@ -0,0 +1,37 @@ 15.4 +#include "iostream.h" 15.5 +#include "sys_string.h" 15.6 + 15.7 +/** Print on a stream, like vfprintf(). 15.8 + * 15.9 + * @param stream to print to 15.10 + * @param format for the print (as fprintf()) 15.11 + * @param args arguments to print 15.12 + * @return result code from the print 15.13 + */ 15.14 +int IOStream_vprint(IOStream *stream, const char *format, va_list args){ 15.15 + char buffer[1024]; 15.16 + int k = sizeof(buffer), n; 15.17 + 15.18 + n = vsnprintf(buffer, k, (char*)format, args); 15.19 + if(n < 0 || n > k ){ 15.20 + n = k; 15.21 + } 15.22 + n = IOStream_write(stream, buffer, n); 15.23 + return n; 15.24 +} 15.25 + 15.26 +/** Print on a stream, like fprintf(). 15.27 + * 15.28 + * @param stream to print to 15.29 + * @param format for the print (as fprintf()) 15.30 + * @return result code from the print 15.31 + */ 15.32 +int IOStream_print(IOStream *stream, const char *format, ...){ 15.33 + va_list args; 15.34 + int result = -1; 15.35 + 15.36 + va_start(args, format); 15.37 + result = IOStream_vprint(stream, format, args); 15.38 + va_end(args); 15.39 + return result; 15.40 +}
16.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 16.2 +++ b/tools/lib/iostream.h Tue Jun 29 12:05:29 2004 +0000 16.3 @@ -0,0 +1,243 @@ 16.4 +#ifndef _XC_LINUX_SAVE_H_ 16.5 +#define _XC_LINUX_SAVE_H_ 16.6 + 16.7 +#include <stdarg.h> 16.8 +#include <stdint.h> 16.9 +#include <stddef.h> 16.10 + 16.11 +#ifdef __KERNEL__ 16.12 +#include <linux/errno.h> 16.13 +#else 16.14 +#include <errno.h> 16.15 +#endif 16.16 + 16.17 +#include "allocate.h" 16.18 + 16.19 +/** End of input return value. */ 16.20 +#define IOSTREAM_EOF -1 16.21 + 16.22 +/** An input/output abstraction. 16.23 + */ 16.24 +typedef struct IOStream IOStream; 16.25 + 16.26 +/** Record of the functions to use for operations on an 16.27 + * IOStream implementation. 16.28 + */ 16.29 +typedef struct IOMethods { 16.30 + /** Read function. Called with the user data, buffer to read into 16.31 + * and number of bytes to read. Must return number of bytes read 16.32 + * on success, less than zero on error. 16.33 + */ 16.34 + int (*read)(IOStream *stream, void *buf, size_t n); 16.35 + 16.36 + /** Write function. Called with user data, buffer to write and 16.37 + * number of bytes to write. Must return number of bytes written on 16.38 + * success, less than zero otherwise. 16.39 + */ 16.40 + int (*write)(IOStream *stream, const void *buf, size_t n); 16.41 + 16.42 + int (*flush)(IOStream *s); 16.43 + 16.44 + int (*error)(IOStream *s); 16.45 + 16.46 + int (*close)(IOStream *s); 16.47 + 16.48 + void (*free)(IOStream *s); 16.49 + 16.50 + void (*lock)(IOStream *s); 16.51 + void (*unlock)(IOStream *s); 16.52 + 16.53 +} IOMethods; 16.54 + 16.55 +/** Abstract i/o object. 16.56 + */ 16.57 +struct IOStream { 16.58 + /** Methods to use to implement operations. */ 16.59 + const IOMethods *methods; 16.60 + /** Private state for the implementation. */ 16.61 + const void *data; 16.62 + /** Flag indicating whether the stream is closed. */ 16.63 + int closed; 16.64 + /** Number of bytes written. */ 16.65 + int written; 16.66 + /** Number of bytes read. */ 16.67 + int read; 16.68 +}; 16.69 + 16.70 + 16.71 +/** IOStream version of stdin. */ 16.72 +extern IOStream *iostdin; 16.73 + 16.74 +/** IOStream version of stdout, */ 16.75 +extern IOStream *iostdout; 16.76 + 16.77 +/** IOStream version of stderr. */ 16.78 +extern IOStream *iostderr; 16.79 + 16.80 +extern int IOStream_print(IOStream *io, const char *format, ...); 16.81 +extern int IOStream_vprint(IOStream *io, const char *format, va_list args); 16.82 + 16.83 +/** Read from a stream. 16.84 + * 16.85 + * @param stream input 16.86 + * @param buf where to put input 16.87 + * @param n number of bytes to read 16.88 + * @return if ok, number of bytes read, otherwise negative error code 16.89 + */ 16.90 +static inline int IOStream_read(IOStream *stream, void *buf, size_t n){ 16.91 + int result = 0; 16.92 + if(stream->closed) goto exit; 16.93 + if(!stream->methods || !stream->methods->read){ 16.94 + result = -EINVAL; 16.95 + goto exit; 16.96 + } 16.97 + result = stream->methods->read(stream, buf, n); 16.98 + if(result > 0){ 16.99 + stream->read += result; 16.100 + } 16.101 + exit: 16.102 + return result; 16.103 +} 16.104 + 16.105 +/** Write to a stream. 16.106 + * 16.107 + * @param stream input 16.108 + * @param buf where to put input 16.109 + * @param n number of bytes to write 16.110 + * @return if ok, number of bytes read, otherwise negative error code 16.111 + */ 16.112 +static inline int IOStream_write(IOStream *stream, const void *buf, size_t n){ 16.113 + int result = 0; 16.114 + if(stream->closed) goto exit; 16.115 + if(!stream->methods || !stream->methods->write){ 16.116 + result = -EINVAL; 16.117 + goto exit; 16.118 + } 16.119 + result = stream->methods->write(stream, buf, n); 16.120 + if(result > 0){ 16.121 + stream->written += result; 16.122 + } 16.123 + exit: 16.124 + return result; 16.125 +} 16.126 + 16.127 +/** Flush the stream. 16.128 + * 16.129 + * @param stream stream 16.130 + * @return 0 on success, IOSTREAM_EOF otherwise 16.131 + */ 16.132 +static inline int IOStream_flush(IOStream *stream){ 16.133 + int result = 0; 16.134 + if(stream->closed){ 16.135 + result = IOSTREAM_EOF; 16.136 + } else if(stream->methods->flush){ 16.137 + result = stream->methods->flush(stream); 16.138 + if(result < 0) result = IOSTREAM_EOF; 16.139 + } 16.140 + return result; 16.141 +} 16.142 + 16.143 +/** Check whether the stream has an error. 16.144 + * 16.145 + * @param stream to check 16.146 + * @return 1 for error, 0 otherwise 16.147 + */ 16.148 +static inline int IOStream_error(IOStream *stream){ 16.149 + int err = 0; 16.150 + if(stream->methods && stream->methods->error){ 16.151 + err = stream->methods->error(stream); 16.152 + } 16.153 + return err; 16.154 +} 16.155 + 16.156 +/** Close the stream. 16.157 + * 16.158 + * @param stream to close 16.159 + * @return 1 for error, 0 otherwise 16.160 + */ 16.161 +static inline int IOStream_close(IOStream *stream){ 16.162 + int err = 1; 16.163 + if(stream->methods && stream->methods->close){ 16.164 + err = stream->methods->close(stream); 16.165 + } 16.166 + return err; 16.167 +} 16.168 + 16.169 +/** Test if the stream has been closed. 16.170 + * 16.171 + * @param stream to check 16.172 + * @return 1 if closed, 0 otherwise 16.173 + */ 16.174 +static inline int IOStream_is_closed(IOStream *stream){ 16.175 + return stream->closed; 16.176 +} 16.177 + 16.178 +/** Free the memory used by the stream. 16.179 + * 16.180 + * @param stream to free 16.181 + */ 16.182 +static inline void IOStream_free(IOStream *stream){ 16.183 + if(stream->methods && stream->methods->free){ 16.184 + stream->methods->free(stream); 16.185 + } 16.186 + *stream = (IOStream){}; 16.187 + deallocate(stream); 16.188 +} 16.189 + 16.190 + 16.191 +/** Print a character to a stream, like fputc(). 16.192 + * 16.193 + * @param stream to print to 16.194 + * @param c character to print 16.195 + * @return result code from the print 16.196 + */ 16.197 +static inline int IOStream_putc(IOStream *stream, int c){ 16.198 + int err; 16.199 + unsigned char b = (unsigned char)c; 16.200 + err = IOStream_write(stream, &b, 1); 16.201 + if(err < 1){ 16.202 + err = IOSTREAM_EOF; 16.203 + } else { 16.204 + err = b; 16.205 + } 16.206 + return err; 16.207 +} 16.208 + 16.209 +/** Read from a stream, like fgetc(). 16.210 + * 16.211 + * @param stream to read from 16.212 + * @return IOSTREAM_EOF on error, character read otherwise 16.213 + */ 16.214 +static inline int IOStream_getc(IOStream *stream){ 16.215 + int err, rc; 16.216 + unsigned char b; 16.217 + 16.218 + err = IOStream_read(stream, &b, 1); 16.219 + if(err < 1){ 16.220 + rc = IOSTREAM_EOF; 16.221 + } else { 16.222 + rc = b; 16.223 + } 16.224 + return rc; 16.225 +} 16.226 + 16.227 +/** Get number of bytes read. 16.228 + * 16.229 + * @param stream to get from 16.230 + * @return number of bytes read 16.231 + */ 16.232 +static inline int IOStream_get_read(IOStream *stream){ 16.233 + return stream->read; 16.234 +} 16.235 + 16.236 +/** Get number of bytes written. 16.237 + * 16.238 + * @param stream to get from 16.239 + * @return number of bytes written 16.240 + */ 16.241 +static inline int IOStream_get_written(IOStream *stream){ 16.242 + return stream->written; 16.243 +} 16.244 + 16.245 + 16.246 +#endif /* ! _XC_LINUX_SAVE_H_ */
17.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 17.2 +++ b/tools/lib/kernel_stream.c Tue Jun 29 12:05:29 2004 +0000 17.3 @@ -0,0 +1,177 @@ 17.4 +/* 17.5 + * Copyright (C) 2001 - 2004 Mike Wray <mike.wray@hp.com> 17.6 + * 17.7 + * This library is free software; you can redistribute it and/or modify 17.8 + * it under the terms of the GNU Lesser General Public License as published by 17.9 + * the Free Software Foundation; either version 2.1 of the License, or 17.10 + * (at your option) any later version. 17.11 + * 17.12 + * This library is distributed in the hope that it will be useful, 17.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 17.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17.15 + * GNU Lesser General Public License for more details. 17.16 + * 17.17 + * You should have received a copy of the GNU Lesser General Public License 17.18 + * along with this library; if not, write to the Free Software 17.19 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 17.20 + */ 17.21 + 17.22 +/** @file 17.23 + * An IOStream implementation using printk() for output. 17.24 + * Input is not implemented. 17.25 + */ 17.26 +#ifdef __KERNEL__ 17.27 + 17.28 +#include <linux/config.h> 17.29 +#include <linux/module.h> 17.30 +#include <linux/kernel.h> 17.31 +#include <linux/types.h> 17.32 +#include <linux/errno.h> 17.33 +#include <linux/slab.h> 17.34 +#include <linux/spinlock.h> 17.35 + 17.36 +#include "kernel_stream.h" 17.37 +#include "allocate.h" 17.38 + 17.39 +/** Number of characters in the output buffer. 17.40 + * The kernel uses 1024 for printk, so that should suffice. 17.41 + */ 17.42 +#define BUF_N 1024 17.43 + 17.44 +/** State for a kernel stream. */ 17.45 +typedef struct KernelData { 17.46 + /** Stream lock. We need a lock to serialize access to the stream. */ 17.47 + spinlock_t lock; 17.48 + /** Saved flags for locking. */ 17.49 + unsigned long flags; 17.50 + /** Size of the output buffer. */ 17.51 + int buf_n; 17.52 + /** Output buffer. */ 17.53 + char buf[BUF_N]; 17.54 +} KernelData; 17.55 + 17.56 +static int kernel_write(IOStream *s, const char *msg, int n); 17.57 +static void kernel_free(IOStream *s); 17.58 +static void kernel_stream_lock(IOStream *s); 17.59 +static void kernel_stream_unlock(IOStream *s); 17.60 + 17.61 +/** Methods for a kernel stream. Output only. */ 17.62 +static const IOMethods kernel_methods = { 17.63 + write: kernel_write, 17.64 + free: kernel_free, 17.65 + lock: kernel_stream_lock, 17.66 + unlock: kernel_stream_unlock, 17.67 +}; 17.68 + 17.69 +/** Shared state for kernel streams. 17.70 + * All implementations write using printk, so we can use 17.71 + * shared state and avoid allocating it. 17.72 + */ 17.73 +static const KernelData kernel_data = { 17.74 + lock: SPIN_LOCK_UNLOCKED, 17.75 + flags: 0, 17.76 + buf_n: BUF_N, 17.77 +}; 17.78 + 17.79 +/** Stream for kernel printk. */ 17.80 +static IOStream iokernel = { 17.81 + methods: &kernel_methods, 17.82 + data: &kernel_data, 17.83 +}; 17.84 + 17.85 +/** Stream for kernel printk. */ 17.86 +IOStream *iostdout = &iokernel; 17.87 + 17.88 +/** Stream for kernel printk. */ 17.89 +IOStream *iostdin = &iokernel; 17.90 + 17.91 +/** Stream for kernel printk. */ 17.92 +IOStream *iostderr = &iokernel; 17.93 + 17.94 +/** Get an output-only stream implementation using 17.95 + * printk(). The stream uses static storage, and must not be freed. 17.96 + * 17.97 + * @return kernel stream 17.98 + */ 17.99 +IOStream get_stream_kernel(void){ 17.100 + return iokernel; 17.101 +} 17.102 + 17.103 +/** Obtain the lock on the stream state. 17.104 + * 17.105 + * @param kdata stream state 17.106 + */ 17.107 +static inline void KernelData_lock(KernelData *kdata){ 17.108 + spin_lock_irqsave(&kdata->lock, kdata->flags); 17.109 +} 17.110 + 17.111 +/** Release the lock on the stream state. 17.112 + * 17.113 + * @param kdata stream state 17.114 + */ 17.115 +static inline void KernelData_unlock(KernelData *kdata){ 17.116 + spin_unlock_irqrestore(&kdata->lock, kdata->flags); 17.117 +} 17.118 + 17.119 +/** Get the stream state. 17.120 + * 17.121 + * @param s kernel stream 17.122 + * @return stream state 17.123 + */ 17.124 +static inline KernelData *get_kernel_data(IOStream *s){ 17.125 + return (KernelData*)s->data; 17.126 +} 17.127 + 17.128 +/** Obtain the lock on the stream state. 17.129 + * 17.130 + * @param s stream 17.131 + */ 17.132 +void kernel_stream_lock(IOStream *s){ 17.133 + KernelData_lock(get_kernel_data(s)); 17.134 +} 17.135 + 17.136 +/** Release the lock on the stream state. 17.137 + * 17.138 + * @param s stream 17.139 + */ 17.140 +void kernel_stream_unlock(IOStream *s){ 17.141 + KernelData_unlock(get_kernel_data(s)); 17.142 +} 17.143 + 17.144 +/** Write to a kernel stream. 17.145 + * 17.146 + * @param stream kernel stream 17.147 + * @param format print format 17.148 + * @param args print arguments 17.149 + * @return result of the print 17.150 + */ 17.151 +static int kernel_write(IOStream *stream, const char *buf, int n){ 17.152 + KernelData *kdata = get_kernel_data(stream); 17.153 + int k; 17.154 + k = kdata->buf_n - 1; 17.155 + if(n < k) k = n; 17.156 + memcpy(kdata->buf, buf, k); 17.157 + kdata->buf[k] = '\0' 17.158 + printk(kdata->buf); 17.159 + return k; 17.160 +} 17.161 + 17.162 +/** Free a kernel stream. 17.163 + * Frees the internal state of the stream. 17.164 + * Do not call this unless the stream was dynamically allocated. 17.165 + * Do not call this on a stream returned from get_stream_kernel(). 17.166 + * 17.167 + * @param io stream to free 17.168 + */ 17.169 +static void kernel_free(IOStream *io){ 17.170 + KernelData *kdata; 17.171 + if(io == &iokernel) return; 17.172 + kdata = get_kernel_data(io); 17.173 + zero(kdata, sizeof(*kdata)); 17.174 + deallocate(kdata); 17.175 +} 17.176 +#endif /* __KERNEL__ */ 17.177 + 17.178 + 17.179 + 17.180 +
18.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 18.2 +++ b/tools/lib/kernel_stream.h Tue Jun 29 12:05:29 2004 +0000 18.3 @@ -0,0 +1,29 @@ 18.4 +/* 18.5 + * Copyright (C) 2001 - 2004 Mike Wray <mike.wray@hp.com> 18.6 + * 18.7 + * This library is free software; you can redistribute it and/or modify 18.8 + * it under the terms of the GNU Lesser General Public License as published by 18.9 + * the Free Software Foundation; either version 2.1 of the License, or 18.10 + * (at your option) any later version. 18.11 + * 18.12 + * This library is distributed in the hope that it will be useful, 18.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 18.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18.15 + * GNU Lesser General Public License for more details. 18.16 + * 18.17 + * You should have received a copy of the GNU Lesser General Public License 18.18 + * along with this library; if not, write to the Free Software 18.19 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 18.20 + */ 18.21 + 18.22 +#ifndef _XEN_LIB_KERNEL_STREAM_H_ 18.23 +#define _XEN_LIB_KERNEL_STREAM_H_ 18.24 + 18.25 +#ifdef __KERNEL__ 18.26 +#include "iostream.h" 18.27 + 18.28 +extern IOStream get_stream_kernel(void); 18.29 +#define get_stream_stdout get_stream_kernel 18.30 + 18.31 +#endif /* __KERNEL__ */ 18.32 +#endif /* !_XEN_LIB_KERNEL_STREAM_H_ */
19.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 19.2 +++ b/tools/lib/lexis.c Tue Jun 29 12:05:29 2004 +0000 19.3 @@ -0,0 +1,93 @@ 19.4 +/* 19.5 + * 19.6 + * This library is free software; you can redistribute it and/or modify 19.7 + * it under the terms of the GNU Lesser General Public License as 19.8 + * published by the Free Software Foundation; either version 2.1 of the 19.9 + * License, or (at your option) any later version. This library is 19.10 + * distributed in the hope that it will be useful, but WITHOUT ANY 19.11 + * WARRANTY; without even the implied warranty of MERCHANTABILITY or 19.12 + * FITNESS FOR A PARTICULAR PURPOSE. 19.13 + * See the GNU Lesser General Public License for more details. 19.14 + * 19.15 + * You should have received a copy of the GNU Lesser General Public License 19.16 + * along with this library; if not, write to the Free Software Foundation, 19.17 + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 19.18 + */ 19.19 + 19.20 +/** @file 19.21 + * Lexical analysis. 19.22 + */ 19.23 + 19.24 +#include "sys_string.h" 19.25 +#include "lexis.h" 19.26 +#include <errno.h> 19.27 + 19.28 +/** Check if a value lies in a (closed) range. 19.29 + * 19.30 + * @param x value to test 19.31 + * @param lo low end of the range 19.32 + * @param hi high end of the range 19.33 + * @return 1 if x is in the interval [lo, hi], 0 otherwise 19.34 + */ 19.35 +inline static int in_range(int x, int lo, int hi){ 19.36 + return (lo <= x) && (x <= hi); 19.37 +} 19.38 + 19.39 +/** Determine if a string is an (unsigned) decimal number. 19.40 + * 19.41 + * @param s pointer to characters to test 19.42 + * @param n length of string 19.43 + * @return 1 if s is a decimal number, 0 otherwise. 19.44 + */ 19.45 +int is_decimal_number(const char *s, int n){ 19.46 + int i; 19.47 + if(n <= 0)return 0; 19.48 + for(i = 0; i < n; i++){ 19.49 + if(!in_decimal_digit_class(s[i])) return 0; 19.50 + } 19.51 + return 1; 19.52 +} 19.53 + 19.54 +/** Determine if a string is a hex number. 19.55 + * Hex numbers are 0, or start with 0x or 0X followed 19.56 + * by a non-zero number of hex digits (0-9,a-f,A-F). 19.57 + * 19.58 + * @param s pointer to characters to test 19.59 + * @param n length of string 19.60 + * @return 1 if s is a hex number, 0 otherwise. 19.61 + */ 19.62 +int is_hex_number(const char *s, int n){ 19.63 + int i; 19.64 + if(n <= 0) return 0; 19.65 + if(n == 1){ 19.66 + return s[0]=='0'; 19.67 + } 19.68 + if(n <= 3) return 0; 19.69 + if(s[0] != '0' || (s[1] != 'x' && s[1] != 'X')) return 0; 19.70 + for(i = 2; i < n; i++){ 19.71 + if(!in_hex_digit_class(s[i])) return 0; 19.72 + } 19.73 + return 1; 19.74 +} 19.75 + 19.76 +/** Test if a string matches a keyword. 19.77 + * The comparison is case-insensitive. 19.78 + * The comparison fails if either argument is null. 19.79 + * 19.80 + * @param s string 19.81 + * @param k keyword 19.82 + * @return 1 if they match, 0 otherwise 19.83 + */ 19.84 +int is_keyword(const char *s, const char *k){ 19.85 + return s && k && !strcasecmp(s, k); 19.86 +} 19.87 + 19.88 +/** Test if a string matches a character. 19.89 + * 19.90 + * @param s string 19.91 + * @param c character (non-null) 19.92 + * @return 1 if s contains exactly c, 0 otherwise 19.93 + */ 19.94 +int is_keychar(const char *s, char c){ 19.95 + return c && (s[0] == c) && !s[1]; 19.96 +}
20.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 20.2 +++ b/tools/lib/lexis.h Tue Jun 29 12:05:29 2004 +0000 20.3 @@ -0,0 +1,122 @@ 20.4 +/* 20.5 + * 20.6 + * This library is free software; you can redistribute it and/or modify 20.7 + * it under the terms of the GNU Lesser General Public License as 20.8 + * published by the Free Software Foundation; either version 2.1 of the 20.9 + * License, or (at your option) any later version. This library is 20.10 + * distributed in the hope that it will be useful, but WITHOUT ANY 20.11 + * WARRANTY; without even the implied warranty of MERCHANTABILITY or 20.12 + * FITNESS FOR A PARTICULAR PURPOSE. 20.13 + * See the GNU Lesser General Public License for more details. 20.14 + * 20.15 + * You should have received a copy of the GNU Lesser General Public License 20.16 + * along with this library; if not, write to the Free Software Foundation, 20.17 + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 20.18 + */ 20.19 + 20.20 +#ifndef _SP_LEXIS_H_ 20.21 +#define _SP_LEXIS_H_ 20.22 + 20.23 +#include "sys_string.h" 20.24 +#include "sys_ctype.h" 20.25 + 20.26 +/** @file 20.27 + * Lexical analysis. 20.28 + */ 20.29 + 20.30 +/** Class of characters treated as space. */ 20.31 +#define space_class ((char []){ '\n', '\r', '\t', ' ', '\f' , 0 }) 20.32 + 20.33 +/** Class of separator characters. */ 20.34 +#define sep_class "{}()<>[]@!;" 20.35 + 20.36 +#define comment_class "#" 20.37 + 20.38 +/** Determine if a character is in a given class. 20.39 + * 20.40 + * @param c character to test 20.41 + * @param s null-terminated string of characters in the class 20.42 + * @return 1 if c is in the class, 0 otherwise. 20.43 + */ 20.44 +static inline int in_class(int c, const char *s){ 20.45 + return s && (strchr(s, c) != 0); 20.46 +} 20.47 + 20.48 +/** Determine if a character is in the space class. 20.49 + * 20.50 + * @param c character to test 20.51 + * @return 1 if c is in the class, 0 otherwise. 20.52 + */ 20.53 +static inline int in_space_class(int c){ 20.54 + return in_class(c, space_class); 20.55 +} 20.56 + 20.57 +static inline int in_comment_class(int c){ 20.58 + return in_class(c, comment_class); 20.59 +} 20.60 + 20.61 +/** Determine if a character is in the separator class. 20.62 + * Separator characters terminate tokens, and do not need space 20.63 + * to separate them. 20.64 + * 20.65 + * @param c character to test 20.66 + * @return 1 if c is in the class, 0 otherwise. 20.67 + */ 20.68 +static inline int in_sep_class(int c){ 20.69 + return in_class(c, sep_class); 20.70 +} 20.71 + 20.72 +/** Determine if a character is in the alpha class. 20.73 + * 20.74 + * @param c character to test 20.75 + * @return 1 if c is in the class, 0 otherwise. 20.76 + */ 20.77 +static inline int in_alpha_class(int c){ 20.78 + return isalpha(c); 20.79 +} 20.80 + 20.81 +/** Determine if a character is in the octal digit class. 20.82 + * 20.83 + * @param c character to test 20.84 + * @return 1 if c is in the class, 0 otherwise. 20.85 + */ 20.86 +static inline int in_octal_digit_class(int c){ 20.87 + return '0' <= c && c <= '7'; 20.88 +} 20.89 + 20.90 +/** Determine if a character is in the decimal digit class. 20.91 + * 20.92 + * @param c character to test 20.93 + * @return 1 if c is in the class, 0 otherwise. 20.94 + */ 20.95 +static inline int in_decimal_digit_class(int c){ 20.96 + return isdigit(c); 20.97 +} 20.98 + 20.99 +/** Determine if a character is in the hex digit class. 20.100 + * 20.101 + * @param c character to test 20.102 + * @return 1 if c is in the class, 0 otherwise. 20.103 + */ 20.104 +static inline int in_hex_digit_class(int c){ 20.105 + return isdigit(c) || in_class(c, "abcdefABCDEF"); 20.106 +} 20.107 + 20.108 + 20.109 +static inline int in_string_quote_class(int c){ 20.110 + return in_class(c, "'\""); 20.111 +} 20.112 + 20.113 +static inline int in_printable_class(int c){ 20.114 + return ('A' <= c && c <= 'Z') 20.115 + || ('a' <= c && c <= 'z') 20.116 + || ('0' <= c && c <= '9') 20.117 + || in_class(c, "!$%&*+,-./:;<=>?@^_`{|}~"); 20.118 +} 20.119 + 20.120 +extern int is_decimal_number(const char *s, int n); 20.121 +extern int is_hex_number(const char *s, int n); 20.122 +extern int is_keyword(const char *s, const char *k); 20.123 +extern int is_keychar(const char *s, char c); 20.124 + 20.125 +#endif /* !_SP_LEXIS_H_ */
21.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 21.2 +++ b/tools/lib/lzi_stream.c Tue Jun 29 12:05:29 2004 +0000 21.3 @@ -0,0 +1,590 @@ 21.4 +/* $Id: lzi_stream.c,v 1.4 2003/09/30 15:22:53 mjw Exp $ */ 21.5 +#define __FILE_ID_INFO "$Id: lzi_stream.c,v 1.4 2003/09/30 15:22:53 mjw Exp $" 21.6 +#include <what.h> 21.7 +static char __rcsid[] __attribute__((unused)) = WHAT_ID __FILE_ID_INFO; 21.8 +/* 21.9 + * Copyright (C) 2003 Hewlett-Packard Company. 21.10 + * 21.11 + * This library is free software; you can redistribute it and/or modify 21.12 + * it under the terms of the GNU Lesser General Public License as published by 21.13 + * the Free Software Foundation; either version 2.1 of the License, or 21.14 + * (at your option) any later version. 21.15 + * 21.16 + * This library is distributed in the hope that it will be useful, 21.17 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 21.18 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 21.19 + * GNU Lesser General Public License for more details. 21.20 + * 21.21 + * You should have received a copy of the GNU Lesser General Public License 21.22 + * along with this library; if not, write to the Free Software 21.23 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 21.24 + */ 21.25 + 21.26 +/** @file 21.27 + * An IOStream implementation using LZI to provide compression and decompression. 21.28 + * This is designed to provide compression without output latency. 21.29 + * Flushing an LZI stream flushes all pending data to the underlying stream. 21.30 + * This is essential for stream-based (e.g. networked) applications. 21.31 + * 21.32 + * A compressed data stream is a sequence of blocks. 21.33 + * Each block is the block size followed by the compressed data. 21.34 + * The last block has size zero. 21.35 + * Sizes are 4-byte unsigned in network order. 21.36 + * 21.37 + * This format allows compressed data to be read from a stream without reading 21.38 + * past the logical end of compressed data. 21.39 + * 21.40 + * @author Mike Wray <mike.wray@hpl.hp.com> 21.41 + */ 21.42 +#ifndef __KERNEL__ 21.43 + 21.44 +#include <stdio.h> 21.45 +#include <stdlib.h> 21.46 +#include <errno.h> 21.47 +#include <string.h> 21.48 + 21.49 +#include "zlib.h" 21.50 + 21.51 +#include "allocate.h" 21.52 +#include "lzi_stream.h" 21.53 +#include "file_stream.h" 21.54 +#include "marshal.h" 21.55 + 21.56 +#define dprintf(fmt, args...) fprintf(stdout, "[DEBUG] LZI>%s" fmt, __FUNCTION__, ##args) 21.57 +#define wprintf(fmt, args...) fprintf(stderr, "[WARN] LZI>%s" fmt, __FUNCTION__, ##args) 21.58 +#define iprintf(fmt, args...) fprintf(stdout, "[INFO] LZI>%s" fmt, __FUNCTION__, ##args) 21.59 +#define eprintf(fmt, args...) fprintf(stderr, "[ERROR] LZI>%s" fmt, __FUNCTION__, ##args) 21.60 + 21.61 +static int lzi_read(IOStream *s, void *buf, size_t size, size_t count); 21.62 +static int lzi_write(IOStream *s, const void *buf, size_t size, size_t count); 21.63 +static int lzi_print(IOStream *s, const char *msg, va_list args); 21.64 +static int lzi_getc(IOStream *s); 21.65 +static int lzi_error(IOStream *s); 21.66 +static int lzi_close(IOStream *s); 21.67 +static void lzi_free(IOStream *s); 21.68 +static int lzi_flush(IOStream *s); 21.69 + 21.70 +enum { 21.71 + LZI_WRITE = 1, 21.72 + LZI_READ = 2, 21.73 +}; 21.74 + 21.75 +/** Methods used by a gzFile* IOStream. */ 21.76 +static const IOMethods lzi_methods = { 21.77 + read: lzi_read, 21.78 + write: lzi_write, 21.79 + print: lzi_print, 21.80 + getc: lzi_getc, 21.81 + error: lzi_error, 21.82 + close: lzi_close, 21.83 + free: lzi_free, 21.84 + flush: lzi_flush, 21.85 +}; 21.86 + 21.87 +#define BUFFER_SIZE (512 * 1024) 21.88 + 21.89 +typedef struct LZIState { 21.90 + z_stream zstream; 21.91 + void *inbuf; 21.92 + uint32_t inbuf_size; 21.93 + void *outbuf; 21.94 + uint32_t outbuf_size; 21.95 + /** Underlying stream for I/O. */ 21.96 + IOStream *io; 21.97 + /** Flags. */ 21.98 + int flags; 21.99 + /** Error indicator. */ 21.100 + int error; 21.101 + int eof; 21.102 + int plain_bytes; 21.103 + int comp_bytes; 21.104 + int zstream_initialized; 21.105 + int flushed; 21.106 +} LZIState; 21.107 + 21.108 +static inline int LZIState_writeable(LZIState *s){ 21.109 + return (s->flags & LZI_WRITE) != 0; 21.110 +} 21.111 + 21.112 +static inline int LZIState_readable(LZIState *s){ 21.113 + return (s->flags & LZI_READ) != 0; 21.114 +} 21.115 + 21.116 +void LZIState_free(LZIState *z){ 21.117 + if(!z) return; 21.118 + if(z->zstream_initialized){ 21.119 + if(LZIState_writeable(z)){ 21.120 + deflateEnd(&z->zstream); 21.121 + } else if(LZIState_readable(z)){ 21.122 + inflateEnd(&z->zstream); 21.123 + } 21.124 + } 21.125 + deallocate(z->inbuf); 21.126 + deallocate(z->outbuf); 21.127 + deallocate(z); 21.128 +} 21.129 + 21.130 +static int mode_flags(const char *mode, int *flags){ 21.131 + int err = 0; 21.132 + int r=0, w=0; 21.133 + if(!mode){ 21.134 + err = -EINVAL; 21.135 + goto exit; 21.136 + } 21.137 + for(; *mode; mode++){ 21.138 + if(*mode == 'w') w = 1; 21.139 + if(*mode == 'r') r = 1; 21.140 + } 21.141 + if(r + w != 1){ 21.142 + err = -EINVAL; 21.143 + goto exit; 21.144 + } 21.145 + if(r) *flags |= LZI_READ; 21.146 + if(w) *flags |= LZI_WRITE; 21.147 + exit: 21.148 + return err; 21.149 +} 21.150 + 21.151 +/** Get the stream state. 21.152 + * 21.153 + * @param s lzi stream 21.154 + * @return stream state. 21.155 + */ 21.156 +static inline LZIState * lzi_state(IOStream *io){ 21.157 + return io->data; 21.158 +} 21.159 + 21.160 +IOStream *lzi_stream_io(IOStream *io){ 21.161 + LZIState *s = lzi_state(io); 21.162 + return s->io; 21.163 +} 21.164 + 21.165 +static inline void set_error(LZIState *s, int err){ 21.166 + if(err < 0 && !s->error){ 21.167 + s->error = err; 21.168 + } 21.169 +} 21.170 + 21.171 +static int zerror(LZIState *s, int err){ 21.172 + if(err){ 21.173 + //dprintf("> err=%d\n", err); 21.174 + if(err < 0) set_error(s, -EIO); 21.175 + } 21.176 + return s->error; 21.177 +} 21.178 + 21.179 +int lzi_stream_plain_bytes(IOStream *io){ 21.180 + LZIState *s = lzi_state(io); 21.181 + return s->plain_bytes; 21.182 +} 21.183 + 21.184 +int lzi_stream_comp_bytes(IOStream *io){ 21.185 + LZIState *s = lzi_state(io); 21.186 + return s->comp_bytes; 21.187 +} 21.188 + 21.189 +float lzi_stream_ratio(IOStream *io){ 21.190 + LZIState *s = lzi_state(io); 21.191 + float ratio = 0.0; 21.192 + if(s->comp_bytes){ 21.193 + ratio = ((float) s->comp_bytes)/((float) s->plain_bytes); 21.194 + } 21.195 + return ratio; 21.196 +} 21.197 + 21.198 +static int alloc(void **p, int n){ 21.199 + *p = allocate(n); 21.200 + return (p ? 0 : -ENOMEM); 21.201 +} 21.202 + 21.203 +LZIState * LZIState_new(IOStream *io, int flags){ 21.204 + int err = -ENOMEM; 21.205 + int zlevel = Z_BEST_SPEED; // Level 1 compression - fastest. 21.206 + int zstrategy = Z_DEFAULT_STRATEGY; 21.207 + int zwindow = MAX_WBITS; 21.208 + int zmemory = 8; 21.209 + LZIState *z = ALLOCATE(LZIState); 21.210 + 21.211 + //dprintf(">\n"); 21.212 + if(!z) goto exit; 21.213 + z->io = io; 21.214 + z->flags = flags; 21.215 + 21.216 + if(LZIState_writeable(z)){ 21.217 + z->outbuf_size = BUFFER_SIZE; 21.218 + /* windowBits is passed < 0 to suppress zlib header */ 21.219 + err = deflateInit2(&z->zstream, zlevel, Z_DEFLATED, -zwindow, zmemory, zstrategy); 21.220 + if (err != Z_OK) goto exit; 21.221 + z->zstream_initialized = 1; 21.222 + err = alloc(&z->outbuf, z->outbuf_size); 21.223 + if(err) goto exit; 21.224 + z->zstream.next_out = z->outbuf; 21.225 + z->zstream.avail_out = z->outbuf_size; 21.226 + } else { 21.227 + z->inbuf_size = BUFFER_SIZE; 21.228 + err = alloc(&z->inbuf, z->inbuf_size); 21.229 + if(err) goto exit; 21.230 + ///z->zstream.next_in = z->inbuf; 21.231 + 21.232 + /* windowBits is passed < 0 to tell that there is no zlib header. 21.233 + * Note that in this case inflate *requires* an extra "dummy" byte 21.234 + * after the compressed stream in order to complete decompression and 21.235 + * return Z_STREAM_END. Here the gzip CRC32 ensures that 4 bytes are 21.236 + * present after the compressed stream. 21.237 + */ 21.238 + err = inflateInit2(&z->zstream, -zwindow); 21.239 + if(err != Z_OK) goto exit; 21.240 + z->zstream_initialized = 1; 21.241 + } 21.242 + 21.243 + exit: 21.244 + if(err){ 21.245 + LZIState_free(z); 21.246 + z = NULL; 21.247 + } 21.248 + //dprintf("< z=%p\n", z); 21.249 + return z; 21.250 +} 21.251 + 21.252 +int read_block(LZIState *s){ 21.253 + int err = 0, k = 0; 21.254 + //dprintf(">\n"); 21.255 + if(s->eof) goto exit; 21.256 + err = unmarshal_uint32(s->io, &k); 21.257 + if(err) goto exit; 21.258 + if(k > s->inbuf_size){ 21.259 + err = -EINVAL; 21.260 + goto exit; 21.261 + } 21.262 + if(k){ 21.263 + err = unmarshal_bytes(s->io, s->inbuf, k); 21.264 + if(err) goto exit; 21.265 + } else { 21.266 + s->eof = 1; 21.267 + } 21.268 + s->zstream.avail_in = k; 21.269 + s->zstream.next_in = s->inbuf; 21.270 + s->comp_bytes += 4; 21.271 + s->comp_bytes += k; 21.272 + exit: 21.273 + //dprintf("< err=%d\n", err); 21.274 + return err; 21.275 +} 21.276 + 21.277 +int write_block(LZIState *s){ 21.278 + int err = 0; 21.279 + int k = ((char*)s->zstream.next_out) - ((char*)s->outbuf); 21.280 + int k2 = s->outbuf_size - s->zstream.avail_out; 21.281 + //dprintf("> k=%d k2=%d\n", k, k2); 21.282 + if(!k) goto exit; 21.283 + err = marshal_uint32(s->io, k); 21.284 + if(err) goto exit; 21.285 + err = marshal_bytes(s->io, s->outbuf, k); 21.286 + if(err) goto exit; 21.287 + s->zstream.next_out = s->outbuf; 21.288 + s->zstream.avail_out = s->outbuf_size; 21.289 + s->comp_bytes += 4; 21.290 + s->comp_bytes += k; 21.291 + exit: 21.292 + //dprintf("< err=%d\n", err); 21.293 + return err; 21.294 +} 21.295 + 21.296 +int write_terminator(LZIState *s){ 21.297 + int err = 0; 21.298 + char c = 0; 21.299 + err = marshal_uint32(s->io, 1); 21.300 + if(err) goto exit; 21.301 + err = marshal_bytes(s->io, &c, 1); 21.302 + if(err) goto exit; 21.303 + err = marshal_uint32(s->io, 0); 21.304 + if(err) goto exit; 21.305 + s->comp_bytes += 9; 21.306 + exit: 21.307 + return err; 21.308 +} 21.309 + 21.310 +/** Write to the underlying stream using fwrite(); 21.311 + * 21.312 + * @param io destination 21.313 + * @param buf data 21.314 + * @param size size of data elements 21.315 + * @param count number of data elements to write 21.316 + * @return number of data elements written 21.317 + */ 21.318 +static int lzi_write(IOStream *io, const void *buf, size_t size, size_t count){ 21.319 + int err = 0; 21.320 + int n = size * count; 21.321 + LZIState *s = lzi_state(io); 21.322 + 21.323 + //dprintf("> buf=%p size=%d count=%d n=%d\n", buf, size, count, n); 21.324 + if(!LZIState_writeable(s)){ 21.325 + err = -EINVAL; 21.326 + goto exit; 21.327 + } 21.328 + s->flushed = 0; 21.329 + s->zstream.next_in = (void*)buf; 21.330 + s->zstream.avail_in = n; 21.331 + while(s->zstream.avail_in){ 21.332 + if(s->zstream.avail_out == 0){ 21.333 + err = write_block(s); 21.334 + if(err) goto exit; 21.335 + } 21.336 + //dprintf("> 1 deflate avail_in=%d avail_out=%d\n", s->zstream.avail_in, s->zstream.avail_out); 21.337 + //dprintf("> 1 deflate next_in=%p next_out=%p\n", s->zstream.next_in, s->zstream.next_out); 21.338 + err = zerror(s, deflate(&s->zstream, Z_NO_FLUSH)); 21.339 + //dprintf("> 2 deflate avail_in=%d avail_out=%d\n", s->zstream.avail_in, s->zstream.avail_out); 21.340 + //dprintf("> 2 deflate next_in=%p next_out=%p\n", s->zstream.next_in, s->zstream.next_out); 21.341 + if(err) goto exit; 21.342 + } 21.343 + err = n; 21.344 + s->plain_bytes += n; 21.345 + if(size != 1) err /= size; 21.346 + exit: 21.347 + //dprintf("< err=%d\n", err); 21.348 + return err; 21.349 +} 21.350 + 21.351 + 21.352 +/** Read from the underlying stream. 21.353 + * 21.354 + * @param io input 21.355 + * @param buf where to put input 21.356 + * @param size size of data elements 21.357 + * @param count number of data elements to read 21.358 + * @return number of data elements read 21.359 + */ 21.360 +static int lzi_read(IOStream *io, void *buf, size_t size, size_t count){ 21.361 + int err, zerr; 21.362 + int n = size * count; 21.363 + LZIState *s = lzi_state(io); 21.364 + 21.365 + //dprintf("> size=%d count=%d n=%d\n", size, count, n); 21.366 + if(!LZIState_readable(s)){ 21.367 + err = -EINVAL; 21.368 + goto exit; 21.369 + } 21.370 + s->zstream.next_out = buf; 21.371 + s->zstream.avail_out = n; 21.372 + while(s->zstream.avail_out){ 21.373 + if(s->zstream.avail_in == 0){ 21.374 + err = read_block(s); 21.375 + } 21.376 + //dprintf("> 1 deflate avail_in=%d avail_out=%d\n", s->zstream.avail_in, s->zstream.avail_out); 21.377 + zerr = inflate(&s->zstream, Z_NO_FLUSH); 21.378 + //dprintf("> 2 deflate avail_in=%d avail_out=%d\n", s->zstream.avail_in, s->zstream.avail_out); 21.379 + if(zerr == Z_STREAM_END) break; 21.380 + //dprintf("> zerr=%d\n", zerr); 21.381 + err = zerror(s, zerr); 21.382 + if(err) goto exit; 21.383 + } 21.384 + err = n - s->zstream.avail_out; 21.385 + s->plain_bytes += err; 21.386 + if(size != 1) err /= size; 21.387 + exit: 21.388 + set_error(s, err); 21.389 + //dprintf("< err=%d\n", err); 21.390 + return err; 21.391 +} 21.392 + 21.393 +/** Print to the underlying stream. 21.394 + * Returns 0 if the formatted output is too big for the internal buffer. 21.395 + * 21.396 + * @param io lzi stream 21.397 + * @param msg format to use 21.398 + * @param args arguments 21.399 + * @return result of the print 21.400 + */ 21.401 +static int lzi_print(IOStream *io, const char *msg, va_list args){ 21.402 + char buf[1024]; 21.403 + int buf_n = sizeof(buf); 21.404 + int n; 21.405 + LZIState *s = lzi_state(io); 21.406 + if(!LZIState_writeable(s)){ 21.407 + n = -EINVAL; 21.408 + goto exit; 21.409 + } 21.410 + n = vsnprintf(buf, buf_n, (char*)msg, args); 21.411 + if(n < 0) goto exit; 21.412 + if(n > buf_n){ 21.413 + n = 0; 21.414 + } else { 21.415 + n = lzi_write(io, buf, 1, n); 21.416 + } 21.417 + exit: 21.418 + return n; 21.419 +} 21.420 + 21.421 +/** Read a character from the underlying stream 21.422 + * 21.423 + * @param io lzi stream 21.424 + * @return character read, IOSTREAM_EOF on end of file (or error) 21.425 + */ 21.426 +static int lzi_getc(IOStream *io){ 21.427 + int err; 21.428 + char c; 21.429 + err = lzi_read(io, &c, 1, 1); 21.430 + if(err < 1) c = EOF; 21.431 + err = (c==EOF ? IOSTREAM_EOF : c); 21.432 + return err; 21.433 +} 21.434 + 21.435 +static int flush_output(LZIState *s, int mode){ 21.436 + int err = 0, zerr; 21.437 + int done = 0; 21.438 + int avail_out_old; 21.439 + int count = 10; 21.440 + 21.441 + //dprintf("> avail_in=%d avail_out=%d\n", s->zstream.avail_in, s->zstream.avail_out); 21.442 + if(s->flushed == 1 + mode) goto exit; 21.443 + //s->zstream.avail_in = 0; /* should be zero already anyway */ 21.444 + for(;;){ 21.445 + // Write any available output. 21.446 + if(done || s->zstream.avail_out == 0){ 21.447 + err = write_block(s); 21.448 + if(err) goto exit; 21.449 + if(done) break; 21.450 + } 21.451 + //dprintf("> 1 deflate avail_in=%d avail_out=%d\n", s->zstream.avail_in, s->zstream.avail_out); 21.452 + avail_out_old = s->zstream.avail_out; 21.453 + zerr = deflate(&s->zstream, mode); 21.454 + err = zerror(s, zerr); 21.455 + //dprintf("> 2 deflate avail_in=%d avail_out=%d\n", s->zstream.avail_in, s->zstream.avail_out); 21.456 + //dprintf("> deflate=%d\n", err); 21.457 + //done = (s->zstream.avail_out != 0); 21.458 + //done = (s->zstream.avail_in == 0) && (s->zstream.avail_out == avail_out_old); 21.459 + if(0 && mode == Z_FINISH){ 21.460 + done = (zerr == Z_STREAM_END); 21.461 + } else { 21.462 + done = (s->zstream.avail_in == 0) 21.463 + //&& (s->zstream.avail_out == avail_out_old) 21.464 + && (s->zstream.avail_out != 0); 21.465 + } 21.466 + } 21.467 + s->flushed = 1 + mode; 21.468 + exit: 21.469 + //dprintf("< err=%d\n", err); 21.470 + return err; 21.471 +} 21.472 + 21.473 +/** Flush any pending input to the underlying stream. 21.474 + * 21.475 + * @param s lzi stream 21.476 + * @return 0 on success, error code otherwise 21.477 + */ 21.478 +static int lzi_flush(IOStream *io){ 21.479 + int err = 0; 21.480 + LZIState *s = lzi_state(io); 21.481 + //dprintf(">\n"); 21.482 + if(!LZIState_writeable(s)){ 21.483 + err = -EINVAL; 21.484 + goto exit; 21.485 + } 21.486 + err = flush_output(s, Z_SYNC_FLUSH); 21.487 + if(err) goto exit; 21.488 + err = IOStream_flush(s->io); 21.489 + exit: 21.490 + set_error(s, err); 21.491 + //dprintf("< err=%d\n", err); 21.492 + return (err < 0 ? err : 0); 21.493 +} 21.494 + 21.495 +/** Check if a stream has an error. 21.496 + * 21.497 + * @param s lzi stream 21.498 + * @return code if has an error, 0 otherwise 21.499 + */ 21.500 +static int lzi_error(IOStream *s){ 21.501 + int err = 0; 21.502 + LZIState *state = lzi_state(s); 21.503 + err = state->error; 21.504 + if(err) goto exit; 21.505 + err = IOStream_error(state->io); 21.506 + exit: 21.507 + return err; 21.508 +} 21.509 + 21.510 +/** Close an lzi stream. 21.511 + * 21.512 + * @param s lzi stream to close 21.513 + * @return result of the close 21.514 + */ 21.515 +static int lzi_close(IOStream *io){ 21.516 + int err = 0; 21.517 + LZIState *s = lzi_state(io); 21.518 + if(LZIState_writeable(s)){ 21.519 + err = flush_output(s, Z_FINISH); 21.520 + if(err) goto exit; 21.521 + err = write_terminator(s); 21.522 + if(err) goto exit; 21.523 + err = IOStream_flush(s->io); 21.524 + } 21.525 + exit: 21.526 + err = IOStream_close(s->io); 21.527 + set_error(s, err); 21.528 + return err; 21.529 +} 21.530 + 21.531 +/** Free an lzi stream. 21.532 + * 21.533 + * @param s lzi stream 21.534 + */ 21.535 +static void lzi_free(IOStream *s){ 21.536 + LZIState *state = lzi_state(s); 21.537 + IOStream_free(state->io); 21.538 + LZIState_free(state); 21.539 + s->data = NULL; 21.540 +} 21.541 + 21.542 +/** Create an lzi stream for an IOStream. 21.543 + * 21.544 + * @param io stream to wrap 21.545 + * @return new IOStream using f for i/o 21.546 + */ 21.547 +IOStream *lzi_stream_new(IOStream *io, const char *mode){ 21.548 + int err = -ENOMEM; 21.549 + int flags = 0; 21.550 + IOStream *zio = NULL; 21.551 + LZIState *state = NULL; 21.552 + 21.553 + zio = ALLOCATE(IOStream); 21.554 + if(!zio) goto exit; 21.555 + err = mode_flags(mode, &flags); 21.556 + if(err) goto exit; 21.557 + state = LZIState_new(io, flags); 21.558 + if(!state) goto exit; 21.559 + err = 0; 21.560 + zio->data = state; 21.561 + zio->methods = &lzi_methods; 21.562 + exit: 21.563 + if(err){ 21.564 + if(state) LZIState_free(state); 21.565 + if(zio) deallocate(zio); 21.566 + zio = NULL; 21.567 + } 21.568 + return zio; 21.569 +} 21.570 + 21.571 +/** IOStream version of fdopen(). 21.572 + * 21.573 + * @param fd file descriptor 21.574 + * @param flags giving the mode to open in (as for fdopen()) 21.575 + * @return new stream for the open file, or NULL if failed 21.576 + */ 21.577 +IOStream *lzi_stream_fdopen(int fd, const char *mode){ 21.578 + int err = -ENOMEM; 21.579 + IOStream *io = NULL, *zio = NULL; 21.580 + io = file_stream_fdopen(fd, mode); 21.581 + if(!io) goto exit; 21.582 + zio = lzi_stream_new(io, mode); 21.583 + if(!io) goto exit; 21.584 + err = 0; 21.585 + exit: 21.586 + if(err){ 21.587 + IOStream_free(io); 21.588 + IOStream_free(zio); 21.589 + zio = NULL; 21.590 + } 21.591 + return zio; 21.592 +} 21.593 +#endif
22.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 22.2 +++ b/tools/lib/lzi_stream.h Tue Jun 29 12:05:29 2004 +0000 22.3 @@ -0,0 +1,36 @@ 22.4 +#/* $Id: lzi_stream.h,v 1.3 2003/09/30 15:22:53 mjw Exp $ */ 22.5 +/* 22.6 + * Copyright (C) 2003 Hewlett-Packard Company. 22.7 + * 22.8 + * This library is free software; you can redistribute it and/or modify 22.9 + * it under the terms of the GNU Lesser General Public License as published by 22.10 + * the Free Software Foundation; either version 2.1 of the License, or 22.11 + * (at your option) any later version. 22.12 + * 22.13 + * This library is distributed in the hope that it will be useful, 22.14 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 22.15 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 22.16 + * GNU Lesser General Public License for more details. 22.17 + * 22.18 + * You should have received a copy of the GNU Lesser General Public License 22.19 + * along with this library; if not, write to the Free Software 22.20 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 22.21 + */ 22.22 + 22.23 +#ifndef _SP_LZI_STREAM_H_ 22.24 +#define _SP_LZI_STREAM_H_ 22.25 + 22.26 +#ifndef __KERNEL__ 22.27 +#include "iostream.h" 22.28 + 22.29 +extern IOStream *lzi_stream_new(IOStream *io, const char *mode); 22.30 +extern IOStream *lzi_stream_fopen(const char *file, const char *mode); 22.31 +extern IOStream *lzi_stream_fdopen(int fd, const char *mode); 22.32 +extern IOStream *lzi_stream_io(IOStream *zio); 22.33 + 22.34 +extern int lzi_stream_plain_bytes(IOStream *io); 22.35 +extern int lzi_stream_comp_bytes(IOStream *io); 22.36 +extern float lzi_stream_ratio(IOStream *io); 22.37 + 22.38 +#endif 22.39 +#endif /* !_SP_FILE_STREAM_H_ */
23.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 23.2 +++ b/tools/lib/lzo_stream.c Tue Jun 29 12:05:29 2004 +0000 23.3 @@ -0,0 +1,596 @@ 23.4 +/* $Id: lzo_stream.c,v 1.4 2003/09/30 15:22:53 mjw Exp $ */ 23.5 +#define __FILE_ID_INFO "$Id: lzo_stream.c,v 1.4 2003/09/30 15:22:53 mjw Exp $" 23.6 +#include <what.h> 23.7 +static char __rcsid[] __attribute__((unused)) = WHAT_ID __FILE_ID_INFO; 23.8 +/* 23.9 + * Copyright (C) 2003 Hewlett-Packard Company. 23.10 + * 23.11 + * This library is free software; you can redistribute it and/or modify 23.12 + * it under the terms of the GNU Lesser General Public License as published by 23.13 + * the Free Software Foundation; either version 2.1 of the License, or 23.14 + * (at your option) any later version. 23.15 + * 23.16 + * This library is distributed in the hope that it will be useful, 23.17 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 23.18 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 23.19 + * GNU Lesser General Public License for more details. 23.20 + * 23.21 + * You should have received a copy of the GNU Lesser General Public License 23.22 + * along with this library; if not, write to the Free Software 23.23 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 23.24 + */ 23.25 + 23.26 +/** @file 23.27 + * An IOStream implementation using LZO to provide compression and decompression. 23.28 + * This is designed to provide reasonable compression without output latency. 23.29 + * Flushing an LZO stream flushes all pending data to the underlying stream. 23.30 + * This is essential for stream-based (e.g. networked) applications. 23.31 + * 23.32 + * A compressed data stream is a sequence of blocks. 23.33 + * Each block except the last is the plain data size followed by the compressed data size 23.34 + * and the compressed data. The last block has plain data size zero and omits the rest. 23.35 + * Sizes are 4-byte unsigned in network order. If the compressed size is smaller than 23.36 + * the plain size the block data is compressed, otherwise it is plain (uncompressed). 23.37 + * 23.38 + * This format allows compressed data to be read from a stream without reading 23.39 + * past the logical end of compressed data. 23.40 + * 23.41 + * @author Mike Wray <mike.wray@hpl.hp.com> 23.42 + */ 23.43 +#ifndef __KERNEL__ 23.44 + 23.45 +#include <stdio.h> 23.46 +#include <stdlib.h> 23.47 +#include <errno.h> 23.48 +#include <string.h> 23.49 + 23.50 +#include "lzo1x.h" 23.51 + 23.52 +#include "allocate.h" 23.53 +#include "lzo_stream.h" 23.54 +#include "file_stream.h" 23.55 +#include "marshal.h" 23.56 + 23.57 +#define dprintf(fmt, args...) fprintf(stdout, "[DEBUG] LZO>%s" fmt, __FUNCTION__, ##args) 23.58 +#define wprintf(fmt, args...) fprintf(stderr, "[WARN] LZO>%s" fmt, __FUNCTION__, ##args) 23.59 +#define iprintf(fmt, args...) fprintf(stdout, "[INFO] LZO>%s" fmt, __FUNCTION__, ##args) 23.60 +#define eprintf(fmt, args...) fprintf(stderr, "[ERROR] LZO>%s" fmt, __FUNCTION__, ##args) 23.61 + 23.62 +static int lzo_read(IOStream *s, void *buf, size_t size, size_t count); 23.63 +static int lzo_write(IOStream *s, const void *buf, size_t size, size_t count); 23.64 +static int lzo_print(IOStream *s, const char *msg, va_list args); 23.65 +static int lzo_getc(IOStream *s); 23.66 +static int lzo_error(IOStream *s); 23.67 +static int lzo_close(IOStream *s); 23.68 +static void lzo_free(IOStream *s); 23.69 +static int lzo_flush(IOStream *s); 23.70 + 23.71 +enum { 23.72 + LZO_WRITE = 1, 23.73 + LZO_READ = 2, 23.74 +}; 23.75 + 23.76 +/** Methods used by a gzFile* IOStream. */ 23.77 +static const IOMethods lzo_methods = { 23.78 + read: lzo_read, 23.79 + write: lzo_write, 23.80 + print: lzo_print, 23.81 + getc: lzo_getc, 23.82 + error: lzo_error, 23.83 + close: lzo_close, 23.84 + free: lzo_free, 23.85 + flush: lzo_flush, 23.86 +}; 23.87 + 23.88 +//#define PLAIN_SIZE (64 * 1024) 23.89 +//#define PLAIN_SIZE (128 * 1024) 23.90 +#define PLAIN_SIZE (512 * 1024) 23.91 + 23.92 +//#define NOCOMPRESS 23.93 + 23.94 +typedef struct LZOState { 23.95 + /** Flags. */ 23.96 + int flags; 23.97 + /** Error indicator. */ 23.98 + int error; 23.99 + /** Underlying stream for I/O. */ 23.100 + IOStream *io; 23.101 + /** Working memory (only needed for compression, not decompression). */ 23.102 + lzo_byte *memory; 23.103 + /** Buffer for plain (uncompressed) data. */ 23.104 + lzo_byte *plain; 23.105 + /** Size of the plain buffer. */ 23.106 + lzo_uint plain_size; 23.107 + /** Pointer into the plain buffer. */ 23.108 + lzo_byte *plain_ptr; 23.109 + /** Number of bytes of plain data available. */ 23.110 + lzo_uint plain_n; 23.111 + /** Buffer for compressed data. */ 23.112 + lzo_byte *comp; 23.113 + /** Size of the compressed buffer. */ 23.114 + lzo_uint comp_size; 23.115 + 23.116 + int plain_bytes; 23.117 + int comp_bytes; 23.118 +} LZOState; 23.119 + 23.120 +void LZOState_free(LZOState *z){ 23.121 + if(!z) return; 23.122 + deallocate(z->memory); 23.123 + deallocate(z->plain); 23.124 + deallocate(z->comp); 23.125 + deallocate(z); 23.126 +} 23.127 + 23.128 +/** Maximum size of compressed data for the given plain data size. 23.129 + * 23.130 + * @param plain_size size of plain data 23.131 + * @return maximum size of compressed data 23.132 + */ 23.133 +static int comp_size(int plain_size){ 23.134 + return plain_size + (plain_size / 64) + 16 + 3; 23.135 +} 23.136 + 23.137 +static int mode_flags(const char *mode, int *flags){ 23.138 + int err = 0; 23.139 + int r=0, w=0; 23.140 + if(!mode){ 23.141 + err = -EINVAL; 23.142 + goto exit; 23.143 + } 23.144 + for(; *mode; mode++){ 23.145 + if(*mode == 'w') w = 1; 23.146 + if(*mode == 'r') r = 1; 23.147 + } 23.148 + if(r + w != 1){ 23.149 + err = -EINVAL; 23.150 + goto exit; 23.151 + } 23.152 + if(r) *flags |= LZO_READ; 23.153 + if(w) *flags |= LZO_WRITE; 23.154 + exit: 23.155 + return err; 23.156 +} 23.157 + 23.158 +/** Get the stream state. 23.159 + * 23.160 + * @param s lzo stream 23.161 + * @return stream state. 23.162 + */ 23.163 +static inline LZOState * lzo_state(IOStream *s){ 23.164 + return s->data; 23.165 +} 23.166 + 23.167 +IOStream *lzo_stream_io(IOStream *s){ 23.168 + LZOState *state = lzo_state(s); 23.169 + return state->io; 23.170 +} 23.171 + 23.172 +static inline void set_error(LZOState *state, int err){ 23.173 + if(err < 0 && !state->error){ 23.174 + state->error = err; 23.175 + } 23.176 +} 23.177 + 23.178 +int lzo_stream_plain_bytes(IOStream *s){ 23.179 + LZOState *state = lzo_state(s); 23.180 + return state->plain_bytes; 23.181 +} 23.182 + 23.183 +int lzo_stream_comp_bytes(IOStream *s){ 23.184 + LZOState *state = lzo_state(s); 23.185 + return state->comp_bytes; 23.186 +} 23.187 + 23.188 +float lzo_stream_ratio(IOStream *s){ 23.189 + LZOState *state = lzo_state(s); 23.190 + float ratio = 0.0; 23.191 + if(state->comp_bytes){ 23.192 + ratio = ((float) state->comp_bytes)/((float) state->plain_bytes); 23.193 + } 23.194 + return ratio; 23.195 +} 23.196 + 23.197 +static inline int LZOState_writeable(LZOState *state){ 23.198 + return (state->flags & LZO_WRITE) != 0; 23.199 +} 23.200 + 23.201 +static inline int LZOState_readable(LZOState *state){ 23.202 + return (state->flags & LZO_READ) != 0; 23.203 +} 23.204 + 23.205 +LZOState * LZOState_new(IOStream *io, int flags){ 23.206 + int err = -ENOMEM; 23.207 + LZOState *z = ALLOCATE(LZOState); 23.208 + //dprintf(">\n"); 23.209 + if(!z) goto exit; 23.210 + z->io = io; 23.211 + z->flags = flags; 23.212 + if(LZOState_writeable(z)){ 23.213 + z->memory = allocate(LZO1X_1_MEM_COMPRESS); 23.214 + if(!z->memory) goto exit; 23.215 + } 23.216 + z->plain_size = PLAIN_SIZE; 23.217 + z->plain = allocate(z->plain_size); 23.218 + if(!z->plain) goto exit; 23.219 + z->plain_ptr = z->plain; 23.220 + z->comp_size = comp_size(z->plain_size); 23.221 + z->comp = allocate(z->comp_size); 23.222 + if(!z->comp) goto exit; 23.223 + err = 0; 23.224 + exit: 23.225 + if(err){ 23.226 + LZOState_free(z); 23.227 + z = NULL; 23.228 + } 23.229 + //dprintf("< z=%p\n", z); 23.230 + return z; 23.231 +} 23.232 + 23.233 +static int lzo_compress(LZOState *state){ 23.234 + int err = 0; 23.235 + int k, comp_n; 23.236 + //dprintf(">\n"); 23.237 + //dprintf(">plain=%p plain_n=%d comp=%p memory=%p\n", state->plain, state->plain_n, state->comp, state->memory); 23.238 + // Compress the plain buffer. 23.239 + err = lzo1x_1_compress(state->plain, state->plain_n, 23.240 + state->comp, &comp_n, 23.241 + state->memory); 23.242 + //dprintf("> err=%d plain_n=%d comp_n=%d\n", err, state->plain_n, comp_n); 23.243 + // Write plain size, compressed size. 23.244 + err = marshal_uint32(state->io, state->plain_n); 23.245 + if(err) goto exit; 23.246 + err = marshal_uint32(state->io, comp_n); 23.247 + if(err) goto exit; 23.248 + //dprintf("> write data...\n"); 23.249 + // Write the smaller of the compressed and plain data. 23.250 + if(state->plain_n < comp_n){ 23.251 + k = state->plain_n; 23.252 + err = marshal_bytes(state->io, state->plain, state->plain_n); 23.253 + } else { 23.254 + k = comp_n; 23.255 + err = marshal_bytes(state->io, state->comp, comp_n); 23.256 + } 23.257 + if(err) goto exit; 23.258 + // Total output bytes. 23.259 + k+= 8; 23.260 + //dprintf("> wrote %d bytes\n", k); 23.261 + state->plain_bytes += state->plain_n; 23.262 + state->comp_bytes += k; 23.263 + //dprintf("> plain=%d, comp=%d, ratio=%3.2f\n", 23.264 + // state->plain_bytes, state->comp_bytes, 23.265 + // ((float)state->comp_bytes)/((float)state->plain_bytes)); 23.266 + // Reset the plain buffer. 23.267 + state->plain_ptr = state->plain; 23.268 + state->plain_n = 0; 23.269 + err = k; 23.270 + exit: 23.271 + //dprintf("< err=%d\n", err); 23.272 + return err; 23.273 +} 23.274 + 23.275 +static int lzo_decompress(LZOState *state){ 23.276 + int plain_n, comp_n; 23.277 + int err, k; 23.278 + //dprintf(">\n"); 23.279 + err = unmarshal_uint32(state->io, &plain_n); 23.280 + //dprintf("> err=%d plain_n=%d\n", err, plain_n); 23.281 + if(err) goto exit; 23.282 + state->comp_bytes += 4; 23.283 + if(plain_n == 0) goto exit; 23.284 + err = unmarshal_uint32(state->io, &comp_n); 23.285 + //dprintf("> err=%d comp_n=%d\n", err, comp_n); 23.286 + if(err) goto exit; 23.287 + state->comp_bytes += 4; 23.288 + if(plain_n > state->plain_size){ 23.289 + err = -EINVAL; 23.290 + goto exit; 23.291 + } 23.292 + if(comp_n > plain_n){ 23.293 + //dprintf("> reading plain data %d...\n", plain_n); 23.294 + k = plain_n; 23.295 + err = unmarshal_bytes(state->io, state->plain, plain_n); 23.296 + state->plain_n = plain_n; 23.297 + } else { 23.298 + //dprintf("> reading comp data %d...\n", comp_n); 23.299 + k = comp_n; 23.300 + err = unmarshal_bytes(state->io, state->comp, comp_n); 23.301 + //dprintf("> decompress comp_n=%d\n", comp_n); 23.302 + err = lzo1x_decompress(state->comp, comp_n, 23.303 + state->plain, &state->plain_n, 23.304 + state->memory); 23.305 + //dprintf("> err=%d plain=%d state->plain_n=%d\n", err, plain_n, state->plain_n); 23.306 + if(err != LZO_E_OK || state->plain_n != plain_n){ 23.307 + // Bad. Corrupted input. 23.308 + err = -EINVAL; 23.309 + eprintf("> Corrupted!\n"); 23.310 + goto exit; 23.311 + } 23.312 + } 23.313 + state->comp_bytes += k; 23.314 + state->plain_bytes += state->plain_n; 23.315 + state->plain_ptr = state->plain; 23.316 + err = k; 23.317 + exit: 23.318 + //dprintf("< err=%d\n", err); 23.319 + return err; 23.320 +} 23.321 + 23.322 +/** Write to the underlying stream using fwrite(); 23.323 + * 23.324 + * @param stream destination 23.325 + * @param buf data 23.326 + * @param size size of data elements 23.327 + * @param count number of data elements to write 23.328 + * @return number of data elements written 23.329 + */ 23.330 +static int lzo_write(IOStream *s, const void *buf, size_t size, size_t count){ 23.331 + int err = 0; 23.332 + int n = size * count; // Total number of bytes to write. 23.333 + int chunk; // Size of chunk to write. 23.334 + int remaining; // Number of bytes remaining to write. 23.335 + int space; // Amount of space left in plain buffer. 23.336 + LZOState *state = lzo_state(s); 23.337 +#ifdef NOCOMPRESS 23.338 + //dprintf("> buf=%p size=%d count=%d\n", buf, size, count); 23.339 + err = IOStream_write(state->io, buf, size, count); 23.340 + //dprintf("< err=%d\n", err); 23.341 +#else 23.342 + //dprintf("> buf=%p size=%d count=%d n=%d\n", buf, size, count, n); 23.343 + remaining = n; 23.344 + space = state->plain_size - state->plain_n; 23.345 + //dprintf("> plain=%p plain_ptr=%p plain_n=%d space=%d\n", 23.346 + // state->plain, state->plain_ptr, state->plain_n, space); 23.347 + while(remaining){ 23.348 + chunk = remaining; 23.349 + if(chunk > space) chunk = space; 23.350 + //dprintf("> memcpy %p %p %d\n", state->plain_ptr, buf, chunk); 23.351 + memcpy(state->plain_ptr, buf, chunk); 23.352 + remaining -= chunk; 23.353 + space -= chunk; 23.354 + state->plain_ptr += chunk; 23.355 + state->plain_n += chunk; 23.356 + if(space == 0){ 23.357 + // Input buffer is full. Compress and write it. 23.358 + err = lzo_compress(state); 23.359 + if(err < 0) goto exit; 23.360 + space = state->plain_size - state->plain_n; 23.361 + } 23.362 + } 23.363 + err = (size > 1 ? n / size : n); 23.364 + exit: 23.365 + set_error(state, err); 23.366 +#endif 23.367 + return err; 23.368 +} 23.369 + 23.370 + 23.371 +/** Read from the underlying stream. 23.372 + * 23.373 + * @param stream input 23.374 + * @param buf where to put input 23.375 + * @param size size of data elements 23.376 + * @param count number of data elements to read 23.377 + * @return number of data elements read 23.378 + */ 23.379 +static int lzo_read(IOStream *s, void *buf, size_t size, size_t count){ 23.380 + int err = 0; 23.381 + int k = 0; // Number of (plain) bytes read. 23.382 + int remaining = size * count; // Number of bytes remaining to read. 23.383 + int chunk; // Size of chunk to read. 23.384 + LZOState *state = lzo_state(s); 23.385 +#ifdef NOCOMPRESS 23.386 + //dprintf("> buf=%p size=%d count=%d\n", buf, size, count); 23.387 + err = IOStream_read(state->io, buf, size, count); 23.388 + //dprintf("< err=%d\n", err); 23.389 +#else 23.390 + if(!(state->flags & LZO_READ)){ 23.391 + err = -EINVAL; 23.392 + goto exit; 23.393 + } 23.394 + while(remaining){ 23.395 + if(state->plain_n == 0){ 23.396 + // No more plain input, decompress some more. 23.397 + err = lzo_decompress(state); 23.398 + if(err < 0) goto exit; 23.399 + // Stop reading if there is no more input. 23.400 + if(err == 0 || state->plain_n == 0) break; 23.401 + } 23.402 + chunk = remaining; 23.403 + if(chunk > state->plain_n) chunk = state->plain_n; 23.404 + memcpy(buf, state->plain_ptr, chunk); 23.405 + k += chunk; 23.406 + buf += chunk; 23.407 + state->plain_ptr += chunk; 23.408 + state->plain_n -= chunk; 23.409 + remaining -= chunk; 23.410 + } 23.411 + err = k; 23.412 + exit: 23.413 + set_error(state, err); 23.414 +#endif 23.415 + return err; 23.416 +} 23.417 + 23.418 +/** Print to the underlying stream. 23.419 + * Returns 0 if the formatted output is too big for the internal buffer. 23.420 + * 23.421 + * @param s lzo stream 23.422 + * @param msg format to use 23.423 + * @param args arguments 23.424 + * @return result of the print 23.425 + */ 23.426 +static int lzo_print(IOStream *s, const char *msg, va_list args){ 23.427 + char buf[1024]; 23.428 + int buf_n = sizeof(buf); 23.429 + int n; 23.430 + LZOState *state = lzo_state(s); 23.431 + if(!LZOState_writeable(state)){ 23.432 + n = -EINVAL; 23.433 + goto exit; 23.434 + } 23.435 + n = vsnprintf(buf, buf_n, (char*)msg, args); 23.436 + if(n < 0) goto exit; 23.437 + if(n > buf_n){ 23.438 + n = 0; 23.439 + } else { 23.440 + n = lzo_write(s, buf, 1, n); 23.441 + } 23.442 + exit: 23.443 + return n; 23.444 +} 23.445 + 23.446 +/** Read a character from the underlying stream 23.447 + * 23.448 + * @param s lzo stream 23.449 + * @return character read, IOSTREAM_EOF on end of file (or error) 23.450 + */ 23.451 +static int lzo_getc(IOStream *s){ 23.452 + int err; 23.453 + char c; 23.454 + err = lzo_read(s, &c, 1, 1); 23.455 + if(err < 1) c = EOF; 23.456 + err = (c==EOF ? IOSTREAM_EOF : c); 23.457 + return err; 23.458 +} 23.459 + 23.460 +/** Flush any pending input to the underlying stream. 23.461 + * 23.462 + * @param s lzo stream 23.463 + * @return 0 on success, error code otherwise 23.464 + */ 23.465 +static int lzo_flush(IOStream *s){ 23.466 + int err = 0; 23.467 + LZOState *state = lzo_state(s); 23.468 + //dprintf(">\n"); 23.469 +#ifdef NOCOMPRESS 23.470 + err = IOStream_flush(state->io); 23.471 +#else 23.472 + if(!LZOState_writeable(state)){ 23.473 + err = -EINVAL; 23.474 + goto exit; 23.475 + } 23.476 + if(state->plain_n){ 23.477 + err = lzo_compress(state); 23.478 + if(err < 0) goto exit; 23.479 + } 23.480 + err = IOStream_flush(state->io); 23.481 + exit: 23.482 + set_error(state, err); 23.483 +#endif 23.484 + //dprintf("< err=%d\n", err); 23.485 + return (err < 0 ? err : 0); 23.486 +} 23.487 + 23.488 +/** Check if a stream has an error. 23.489 + * 23.490 + * @param s lzo stream 23.491 + * @return code if has an error, 0 otherwise 23.492 + */ 23.493 +static int lzo_error(IOStream *s){ 23.494 + int err = 0; 23.495 + LZOState *state = lzo_state(s); 23.496 + err = state->error; 23.497 + if(err) goto exit; 23.498 + err = IOStream_error(state->io); 23.499 + exit: 23.500 + return err; 23.501 +} 23.502 + 23.503 +int lzo_stream_finish(IOStream *s){ 23.504 + int err = 0; 23.505 + LZOState *state = lzo_state(s); 23.506 + if(!LZOState_writeable(state)){ 23.507 + err = -EINVAL; 23.508 + goto exit; 23.509 + } 23.510 + err = lzo_flush(s); 23.511 + if(err < 0) goto exit; 23.512 + err = marshal_int32(state->io, 0); 23.513 + exit: 23.514 + return err; 23.515 +} 23.516 + 23.517 +/** Close an lzo stream. 23.518 + * 23.519 + * @param s lzo stream to close 23.520 + * @return result of the close 23.521 + */ 23.522 +static int lzo_close(IOStream *s){ 23.523 + int err = 0; 23.524 + LZOState *state = lzo_state(s); 23.525 +#ifdef NOCOMPRESS 23.526 + err = IOStream_close(state->io); 23.527 +#else 23.528 + if(LZOState_writeable(state)){ 23.529 + err = lzo_stream_finish(s); 23.530 + } 23.531 + err = IOStream_close(state->io); 23.532 + set_error(state, err); 23.533 +#endif 23.534 + return err; 23.535 +} 23.536 + 23.537 +/** Free an lzo stream. 23.538 + * 23.539 + * @param s lzo stream 23.540 + */ 23.541 +static void lzo_free(IOStream *s){ 23.542 + LZOState *state = lzo_state(s); 23.543 + IOStream_free(state->io); 23.544 + LZOState_free(state); 23.545 + s->data = NULL; 23.546 +} 23.547 + 23.548 +/** Create an lzo stream for an IOStream. 23.549 + * 23.550 + * @param io stream to wrap 23.551 + * @return new IOStream using f for i/o 23.552 + */ 23.553 +IOStream *lzo_stream_new(IOStream *io, const char *mode){ 23.554 + int err = -ENOMEM; 23.555 + int flags = 0; 23.556 + IOStream *zio = NULL; 23.557 + LZOState *state = NULL; 23.558 + 23.559 + zio = ALLOCATE(IOStream); 23.560 + if(!zio) goto exit; 23.561 + err = mode_flags(mode, &flags); 23.562 + if(err) goto exit; 23.563 + state = LZOState_new(io, flags); 23.564 + if(!state) goto exit; 23.565 + err = 0; 23.566 + zio->data = state; 23.567 + zio->methods = &lzo_methods; 23.568 + exit: 23.569 + if(err){ 23.570 + if(state) LZOState_free(state); 23.571 + if(zio) deallocate(zio); 23.572 + zio = NULL; 23.573 + } 23.574 + return zio; 23.575 +} 23.576 + 23.577 +/** IOStream version of fdopen(). 23.578 + * 23.579 + * @param fd file descriptor 23.580 + * @param flags giving the mode to open in (as for fdopen()) 23.581 + * @return new stream for the open file, or NULL if failed 23.582 + */ 23.583 +IOStream *lzo_stream_fdopen(int fd, const char *mode){ 23.584 + int err = -ENOMEM; 23.585 + IOStream *io = NULL, *zio = NULL; 23.586 + io = file_stream_fdopen(fd, mode); 23.587 + if(!io) goto exit; 23.588 + zio = lzo_stream_new(io, mode); 23.589 + if(!io) goto exit; 23.590 + err = 0; 23.591 + exit: 23.592 + if(err){ 23.593 + IOStream_free(io); 23.594 + IOStream_free(zio); 23.595 + zio = NULL; 23.596 + } 23.597 + return zio; 23.598 +} 23.599 +#endif
24.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 24.2 +++ b/tools/lib/lzo_stream.h Tue Jun 29 12:05:29 2004 +0000 24.3 @@ -0,0 +1,36 @@ 24.4 +#/* $Id: lzo_stream.h,v 1.3 2003/09/30 15:22:53 mjw Exp $ */ 24.5 +/* 24.6 + * Copyright (C) 2003 Hewlett-Packard Company. 24.7 + * 24.8 + * This library is free software; you can redistribute it and/or modify 24.9 + * it under the terms of the GNU Lesser General Public License as published by 24.10 + * the Free Software Foundation; either version 2.1 of the License, or 24.11 + * (at your option) any later version. 24.12 + * 24.13 + * This library is distributed in the hope that it will be useful, 24.14 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 24.15 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 24.16 + * GNU Lesser General Public License for more details. 24.17 + * 24.18 + * You should have received a copy of the GNU Lesser General Public License 24.19 + * along with this library; if not, write to the Free Software 24.20 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 24.21 + */ 24.22 + 24.23 +#ifndef _SP_LZO_STREAM_H_ 24.24 +#define _SP_LZO_STREAM_H_ 24.25 + 24.26 +#ifndef __KERNEL__ 24.27 +#include "iostream.h" 24.28 + 24.29 +extern IOStream *lzo_stream_new(IOStream *io, const char *mode); 24.30 +extern IOStream *lzo_stream_fopen(const char *file, const char *mode); 24.31 +extern IOStream *lzo_stream_fdopen(int fd, const char *mode); 24.32 +extern IOStream *lzo_stream_io(IOStream *zio); 24.33 + 24.34 +extern int lzo_stream_plain_bytes(IOStream *io); 24.35 +extern int lzo_stream_comp_bytes(IOStream *io); 24.36 +extern float lzo_stream_ratio(IOStream *io); 24.37 + 24.38 +#endif 24.39 +#endif /* !_SP_FILE_STREAM_H_ */
25.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 25.2 +++ b/tools/lib/marshal.c Tue Jun 29 12:05:29 2004 +0000 25.3 @@ -0,0 +1,207 @@ 25.4 +#include <errno.h> 25.5 +#include "sys_net.h" 25.6 +#include "allocate.h" 25.7 +#include "marshal.h" 25.8 + 25.9 +#define dprintf(fmt, args...) IOStream_print(iostdout, "[DEBUG] %s" fmt, __FUNCTION__, ##args) 25.10 +#define wprintf(fmt, args...) IOStream_print(iostderr, "[WARN] %s" fmt, __FUNCTION__, ##args) 25.11 +#define iprintf(fmt, args...) IOStream_print(iostdout, "[INFO] %s" fmt, __FUNCTION__, ##args) 25.12 +#define eprintf(fmt, args...) IOStream_print(iostderr, "[ERROR] %s" fmt, __FUNCTION__, ##args) 25.13 + 25.14 + 25.15 +#define ARRAY_SIZE(ary) (sizeof(ary)/sizeof((ary)[0])) 25.16 + 25.17 +/* Messages are coded as msgid followed by message fields. 25.18 + * Initial message on any channel is hello - so can check version 25.19 + * compatibility. 25.20 + * 25.21 + * char* -> uint16_t:n <n bytes> 25.22 + * ints/uints go as suitable number of bytes (e.g. uint16_t is 2 bytes). 25.23 + * optional fields go as '1' <val> or '0' (the 0/1 is 1 byte). 25.24 + * lists go as ('1' <elt>)* '0' 25.25 + */ 25.26 + 25.27 +int marshal_flush(IOStream *io){ 25.28 + int err = 0; 25.29 + err = IOStream_flush(io); 25.30 + return err; 25.31 +} 25.32 + 25.33 +int marshal_bytes(IOStream *io, void *s, uint32_t s_n){ 25.34 + int err = 0; 25.35 + int n; 25.36 + n = IOStream_write(io, s, s_n); 25.37 + if(n < 0){ 25.38 + err = n; 25.39 + } else if (n < s_n){ 25.40 + wprintf("> Wanted %d, got %d\n", s_n, n); 25.41 + err = -EIO; 25.42 + } 25.43 + return err; 25.44 +} 25.45 + 25.46 +int unmarshal_bytes(IOStream *io, void *s, uint32_t s_n){ 25.47 + int err = 0; 25.48 + int n; 25.49 + //dprintf("> s_n=%d\n", s_n); 25.50 + n = IOStream_read(io, s, s_n); 25.51 + //dprintf("> n=%d\n", n); 25.52 + if(n < 0){ 25.53 + err = n; 25.54 + } else if(n < s_n){ 25.55 + wprintf("> Wanted %d, got %d\n", s_n, n); 25.56 + err = -EIO; 25.57 + } 25.58 + //dprintf("< err=%d\n", err); 25.59 + return err; 25.60 +} 25.61 + 25.62 +int marshal_uint8(IOStream *io, uint8_t x){ 25.63 + return marshal_bytes(io, &x, sizeof(x)); 25.64 +} 25.65 + 25.66 +int unmarshal_uint8(IOStream *io, uint8_t *x){ 25.67 + return unmarshal_bytes(io, x, sizeof(*x)); 25.68 +} 25.69 + 25.70 +int marshal_uint16(IOStream *io, uint16_t x){ 25.71 + x = htons(x); 25.72 + return marshal_bytes(io, &x, sizeof(x)); 25.73 +} 25.74 + 25.75 +int unmarshal_uint16(IOStream *io, uint16_t *x){ 25.76 + int err = 0; 25.77 + err = unmarshal_bytes(io, x, sizeof(*x)); 25.78 + *x = ntohs(*x); 25.79 + return err; 25.80 +} 25.81 + 25.82 +int marshal_int32(IOStream *io, int32_t x){ 25.83 + int err = 0; 25.84 + //dprintf("> x=%d\n", x); 25.85 + x = htonl(x); 25.86 + err = marshal_bytes(io, &x, sizeof(x)); 25.87 + //dprintf("< err=%d\n", err); 25.88 + return err; 25.89 +} 25.90 + 25.91 +int unmarshal_int32(IOStream *io, int32_t *x){ 25.92 + int err = 0; 25.93 + //dprintf(">\n"); 25.94 + err = unmarshal_bytes(io, x, sizeof(*x)); 25.95 + *x = ntohl(*x); 25.96 + //dprintf("< err=%d x=%d\n", err, *x); 25.97 + return err; 25.98 +} 25.99 + 25.100 +int marshal_uint32(IOStream *io, uint32_t x){ 25.101 + int err = 0; 25.102 + //dprintf("> x=%u\n", x); 25.103 + x = htonl(x); 25.104 + err = marshal_bytes(io, &x, sizeof(x)); 25.105 + //dprintf("< err=%d\n", err); 25.106 + return err; 25.107 +} 25.108 + 25.109 +int unmarshal_uint32(IOStream *io, uint32_t *x){ 25.110 + int err = 0; 25.111 + //dprintf(">\n"); 25.112 + err = unmarshal_bytes(io, x, sizeof(*x)); 25.113 + *x = ntohl(*x); 25.114 + //dprintf("< err=%d x=%u\n", err, *x); 25.115 + return err; 25.116 +} 25.117 + 25.118 +int marshal_uint64(IOStream *io, uint64_t x){ 25.119 + int err; 25.120 + err = marshal_uint32(io, (uint32_t) ((x >> 32) & 0xffffffff)); 25.121 + if(err) goto exit; 25.122 + err = marshal_uint32(io, (uint32_t) ( x & 0xffffffff)); 25.123 + exit: 25.124 + return err; 25.125 +} 25.126 + 25.127 +int unmarshal_uint64(IOStream *io, uint64_t *x){ 25.128 + int err = 0; 25.129 + uint32_t hi, lo; 25.130 + err = unmarshal_uint32(io, &hi); 25.131 + if(err) goto exit; 25.132 + err = unmarshal_uint32(io, &lo); 25.133 + *x = (((uint64_t) hi) << 32) | lo; 25.134 + exit: 25.135 + return err; 25.136 +} 25.137 + 25.138 +int marshal_net16(IOStream *io, net16_t x){ 25.139 + return marshal_bytes(io, &x, sizeof(x)); 25.140 +} 25.141 + 25.142 +int unmarshal_net16(IOStream *io, net16_t *x){ 25.143 + int err = 0; 25.144 + err = unmarshal_bytes(io, x, sizeof(*x)); 25.145 + return err; 25.146 +} 25.147 + 25.148 +int marshal_net32(IOStream *io, net32_t x){ 25.149 + return marshal_bytes(io, &x, sizeof(x)); 25.150 +} 25.151 + 25.152 +int unmarshal_net32(IOStream *io, net32_t *x){ 25.153 + int err = 0; 25.154 + err = unmarshal_bytes(io, x, sizeof(*x)); 25.155 + return err; 25.156 +} 25.157 + 25.158 +int marshal_string(IOStream *io, char *s, uint32_t s_n){ 25.159 + int err; 25.160 + //dprintf("> s=%s\n", s); 25.161 + err = marshal_uint32(io, s_n); 25.162 + if(err) goto exit; 25.163 + err = marshal_bytes(io, s, s_n); 25.164 + exit: 25.165 + //dprintf("< err=%d\n", err); 25.166 + return err; 25.167 +} 25.168 + 25.169 +int unmarshal_string(IOStream *io, char *s, uint32_t s_n){ 25.170 + int err = 0, val_n = 0; 25.171 + //dprintf(">\n"); 25.172 + err = unmarshal_uint32(io, &val_n); 25.173 + if(err) goto exit; 25.174 + if(val_n >= s_n){ 25.175 + err = -EINVAL; 25.176 + goto exit; 25.177 + } 25.178 + err = unmarshal_bytes(io, s, val_n); 25.179 + if(err) goto exit; 25.180 + s[val_n] = '\0'; 25.181 + exit: 25.182 + //dprintf("< err=%d s=%s\n", err, s); 25.183 + return err; 25.184 +} 25.185 + 25.186 +int unmarshal_new_string(IOStream *io, char **s, uint32_t *s_n){ 25.187 + int err = 0, val_n = 0; 25.188 + char *val = NULL; 25.189 + //dprintf(">\n"); 25.190 + err = unmarshal_uint32(io, &val_n); 25.191 + if(err) goto exit; 25.192 + val = allocate(val_n + 1); 25.193 + if(!val){ 25.194 + err = -ENOMEM; 25.195 + goto exit; 25.196 + } 25.197 + err = unmarshal_bytes(io, val, val_n); 25.198 + if(err) goto exit; 25.199 + val[val_n] = '\0'; 25.200 + exit: 25.201 + if(err){ 25.202 + if(val) deallocate(val); 25.203 + val = NULL; 25.204 + val_n = 0; 25.205 + } 25.206 + *s = val; 25.207 + if(s_n) *s_n = val_n; 25.208 + //dprintf("< err=%d s=%s\n", err, *s); 25.209 + return err; 25.210 +}
26.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 26.2 +++ b/tools/lib/marshal.h Tue Jun 29 12:05:29 2004 +0000 26.3 @@ -0,0 +1,43 @@ 26.4 +/* $Id: marshal.h,v 1.1 2003/10/17 15:48:43 mjw Exp $ */ 26.5 +#ifndef _SP_MARSHAL_H_ 26.6 +#define _SP_MARSHAL_H_ 26.7 + 26.8 +#include "iostream.h" 26.9 + 26.10 +/** A 16-bit uint in network order, e.g. a port number. */ 26.11 +typedef uint16_t net16_t; 26.12 + 26.13 +/** A 32-bit uint in network order, e.g. an IP address. */ 26.14 +typedef uint32_t net32_t; 26.15 + 26.16 +extern int marshal_flush(IOStream *io); 26.17 + 26.18 +extern int marshal_bytes(IOStream *io, void *s, uint32_t s_n); 26.19 +extern int unmarshal_bytes(IOStream *io, void *s, uint32_t s_n); 26.20 + 26.21 +extern int marshal_uint8(IOStream *io, uint8_t x); 26.22 +extern int unmarshal_uint8(IOStream *io, uint8_t *x); 26.23 + 26.24 +extern int marshal_uint16(IOStream *io, uint16_t x); 26.25 +extern int unmarshal_uint16(IOStream *io, uint16_t *x); 26.26 + 26.27 +extern int marshal_uint32(IOStream *io, uint32_t x); 26.28 +extern int unmarshal_uint32(IOStream *io, uint32_t *x); 26.29 + 26.30 +extern int marshal_int32(IOStream *io, int32_t x); 26.31 +extern int unmarshal_int32(IOStream *io, int32_t *x); 26.32 + 26.33 +extern int marshal_uint64(IOStream *io, uint64_t x); 26.34 +extern int unmarshal_uint64(IOStream *io, uint64_t *x); 26.35 + 26.36 +extern int marshal_net16(IOStream *io, net16_t x); 26.37 +extern int unmarshal_net16(IOStream *io, net16_t *x); 26.38 + 26.39 +extern int marshal_net32(IOStream *io, net32_t x); 26.40 +extern int unmarshal_net32(IOStream *io, net32_t *x); 26.41 + 26.42 +extern int marshal_string(IOStream *io, char *s, uint32_t s_n); 26.43 +extern int unmarshal_string(IOStream *io, char *s, uint32_t s_n); 26.44 +extern int unmarshal_new_string(IOStream *io, char **s, uint32_t *s_n); 26.45 + 26.46 +#endif /* ! _SP_MARSHAL_H_ */
27.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 27.2 +++ b/tools/lib/socket_stream.c Tue Jun 29 12:05:29 2004 +0000 27.3 @@ -0,0 +1,259 @@ 27.4 +/* $Id: socket_stream.c,v 1.9 2004/03/05 14:45:34 mjw Exp $ */ 27.5 +/* 27.6 + * Copyright (C) 2004 Mike Wray <mike.wray@hp.com> 27.7 + * 27.8 + * This library is free software; you can redistribute it and/or modify 27.9 + * it under the terms of the GNU Lesser General Public License as published by 27.10 + * the Free Software Foundation; either version 2.1 of the License, or 27.11 + * (at your option) any later version. 27.12 + * 27.13 + * This library is distributed in the hope that it will be useful, 27.14 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 27.15 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 27.16 + * GNU Lesser General Public License for more details. 27.17 + * 27.18 + * You should have received a copy of the GNU Lesser General Public License 27.19 + * along with this library; if not, write to the Free Software 27.20 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 27.21 + */ 27.22 + 27.23 +/** @file 27.24 + * An IOStream implementation using sockets. 27.25 + */ 27.26 + 27.27 +#include <stdio.h> 27.28 +#include <stdlib.h> 27.29 +#include <string.h> 27.30 +#include <unistd.h> 27.31 +#include <errno.h> 27.32 +#include "allocate.h" 27.33 +#include "socket_stream.h" 27.34 + 27.35 +#define MODULE_NAME "sock" 27.36 +#define DEBUG 0 27.37 +//#undef DEBUG 27.38 +#include "debug.h" 27.39 + 27.40 +static int socket_read(IOStream *s, void *buf, size_t n); 27.41 +static int socket_write(IOStream *s, const void *buf, size_t n); 27.42 +static int socket_error(IOStream *s); 27.43 +static int socket_close(IOStream *s); 27.44 +static void socket_free(IOStream *s); 27.45 +static int socket_flush(IOStream *s); 27.46 + 27.47 +/** Methods used by a socket IOStream. */ 27.48 +static const IOMethods socket_methods = { 27.49 + read: socket_read, 27.50 + write: socket_write, 27.51 + error: socket_error, 27.52 + close: socket_close, 27.53 + free: socket_free, 27.54 + flush: socket_flush, 27.55 +}; 27.56 + 27.57 +/** Get the socket data. 27.58 + * 27.59 + * @param io socket stream 27.60 + * @return data 27.61 + */ 27.62 +static inline SocketData * socket_data(IOStream *io){ 27.63 + return (SocketData *)io->data; 27.64 +} 27.65 + 27.66 +/** Test if a stream is a socket stream. 27.67 + * 27.68 + * @param io stream 27.69 + * @return 0 if a socket stream, -EINVAL if not 27.70 + */ 27.71 +int socket_stream_check(IOStream *io){ 27.72 + return (io && io->methods == &socket_methods ? 0 : -EINVAL); 27.73 +} 27.74 + 27.75 +/** Get the data for a socket stream. 27.76 + * 27.77 + * @param io stream 27.78 + * @param data return value for the data 27.79 + * @return 0 if a socket stream, -EINVAL if not 27.80 + */ 27.81 +int socket_stream_data(IOStream *io, SocketData **data){ 27.82 + int err = socket_stream_check(io); 27.83 + if(err){ 27.84 + *data = NULL; 27.85 + } else { 27.86 + *data = socket_data(io); 27.87 + } 27.88 + return err; 27.89 +} 27.90 + 27.91 +/** Set the destination address for a socket stream. 27.92 + * 27.93 + * @param io stream 27.94 + * @param addr address 27.95 + * @return 0 if a socket stream, -EINVAL if not 27.96 + */ 27.97 +int socket_stream_set_addr(IOStream *io, struct sockaddr_in *addr){ 27.98 + int err = 0; 27.99 + SocketData *data = NULL; 27.100 + err = socket_stream_data(io, &data); 27.101 + if(!err){ 27.102 + data->daddr = *addr; 27.103 + } 27.104 + return err; 27.105 +} 27.106 + 27.107 +/** Set the send flags for a socket stream. 27.108 + * 27.109 + * @param io stream 27.110 + * @param flags flags 27.111 + * @return 0 if a socket stream, -EINVAL if not 27.112 + */ 27.113 +int socket_stream_set_flags(IOStream *io, int flags){ 27.114 + int err = 0; 27.115 + SocketData *data = NULL; 27.116 + err = socket_stream_data(io, &data); 27.117 + if(!err){ 27.118 + data->flags = flags; 27.119 + } 27.120 + return err; 27.121 +} 27.122 + 27.123 +/** Write to the underlying socket using sendto. 27.124 + * 27.125 + * @param stream input 27.126 + * @param buf where to put input 27.127 + * @param n number of bytes to write 27.128 + * @return number of bytes written 27.129 + */ 27.130 +static int socket_write(IOStream *s, const void *buf, size_t n){ 27.131 + SocketData *data = socket_data(s); 27.132 + struct sockaddr *daddr = (struct sockaddr *)&data->daddr; 27.133 + socklen_t daddr_n = sizeof(data->daddr); 27.134 + int k; 27.135 + dprintf("> sock=%d addr=%s:%d n=%d\n", 27.136 + data->fd, inet_ntoa(data->daddr.sin_addr), ntohs(data->daddr.sin_port), n); 27.137 + if(0){ 27.138 + struct sockaddr_in self = {}; 27.139 + socklen_t self_n; 27.140 + getsockname(data->fd, (struct sockaddr *)&self, &self_n); 27.141 + dprintf("> sockname sock=%d %s:%d\n", 27.142 + data->fd, inet_ntoa(self.sin_addr), ntohs(self.sin_port)); 27.143 + } 27.144 + k = sendto(data->fd, buf, n, data->flags, daddr, daddr_n); 27.145 + dprintf("> sendto=%d\n", k); 27.146 + return k; 27.147 +} 27.148 + 27.149 +/** Read from the underlying stream using recv(); 27.150 + * 27.151 + * @param stream input 27.152 + * @param buf where to put input 27.153 + * @param n number of bytes to read 27.154 + * @return number of bytes read 27.155 + */ 27.156 +static int socket_read(IOStream *s, void *buf, size_t n){ 27.157 + SocketData *data = socket_data(s); 27.158 + int k; 27.159 + struct sockaddr *saddr = (struct sockaddr *)&data->saddr; 27.160 + socklen_t saddr_n = sizeof(data->saddr); 27.161 + k = recvfrom(data->fd, buf, n, data->flags, saddr, &saddr_n); 27.162 + return k; 27.163 +} 27.164 + 27.165 +/** Print to the underlying socket. 27.166 + * 27.167 + * @param s socket stream 27.168 + * @param msg format to use 27.169 + * @param args arguments 27.170 + * @return result of the print 27.171 + */ 27.172 +static int socket_print(IOStream *s, const char *msg, va_list args){ 27.173 + SocketData *data = socket_data(s); 27.174 + int n; 27.175 + n = vsnprintf(data->buf, data->buf_n - 1, msg, args); 27.176 + if(0 < n && n < data->buf_n){ 27.177 + socket_write(s, data->buf, n); 27.178 + } 27.179 + return n; 27.180 +} 27.181 + 27.182 +/** Read a character from the underlying socket 27.183 + * 27.184 + * @param s socket stream 27.185 + * @return character read, IOSTREAM_EOF on end of socket (or error) 27.186 + */ 27.187 +static int socket_getc(IOStream *s){ 27.188 + char b; 27.189 + int n, c; 27.190 + n = socket_read(s, &b, 1); 27.191 + c = (n <= 0 ? IOSTREAM_EOF : b); 27.192 + return c; 27.193 +} 27.194 + 27.195 +/** Flush the socket (no-op). 27.196 + * 27.197 + * @param s socket stream 27.198 + * @return 0 on success, error code otherwise 27.199 + */ 27.200 +static int socket_flush(IOStream *s){ 27.201 + return 0; 27.202 +} 27.203 + 27.204 +/** Check if a socket stream has an error (no-op). 27.205 + * 27.206 + * @param s socket stream 27.207 + * @return 1 if has an error, 0 otherwise 27.208 + */ 27.209 +static int socket_error(IOStream *s){ 27.210 + // Read SOL_SOCKET/SO_ERROR ? 27.211 + return 0; 27.212 +} 27.213 + 27.214 +/** Close a socket stream. 27.215 + * 27.216 + * @param s socket stream to close 27.217 + * @return result of the close 27.218 + */ 27.219 +static int socket_close(IOStream *s){ 27.220 + SocketData *data = socket_data(s); 27.221 + return close(data->fd); 27.222 +} 27.223 + 27.224 +/** Free a socket stream. 27.225 + * 27.226 + * @param s socket stream 27.227 + */ 27.228 +static void socket_free(IOStream *s){ 27.229 + SocketData *data = socket_data(s); 27.230 + deallocate(data); 27.231 +} 27.232 + 27.233 +/** Create an IOStream for a socket. 27.234 + * 27.235 + * @param fd socket to wtap 27.236 + * @return new IOStream using fd for i/o 27.237 + */ 27.238 +IOStream *socket_stream_new(int fd){ 27.239 + int err = -ENOMEM; 27.240 + IOStream *io = NULL; 27.241 + SocketData *data = NULL; 27.242 + 27.243 + io = ALLOCATE(IOStream); 27.244 + if(!io) goto exit; 27.245 + io->methods = &socket_methods; 27.246 + data = ALLOCATE(SocketData); 27.247 + if(!data) goto exit; 27.248 + io->data = data; 27.249 + data->fd = fd; 27.250 + data->buf_n = sizeof(data->buf); 27.251 + err = 0; 27.252 + exit: 27.253 + if(err){ 27.254 + if(io){ 27.255 + if(data) deallocate(data); 27.256 + deallocate(io); 27.257 + io = NULL; 27.258 + } 27.259 + } 27.260 + return io; 27.261 +} 27.262 +
28.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 28.2 +++ b/tools/lib/socket_stream.h Tue Jun 29 12:05:29 2004 +0000 28.3 @@ -0,0 +1,54 @@ 28.4 +/* $Id: socket_stream.h,v 1.2 2004/03/04 17:38:13 mjw Exp $ */ 28.5 +/* 28.6 + * Copyright (C) 2004 Mike Wray <mike.wray@hp.com> 28.7 + * 28.8 + * This library is free software; you can redistribute it and/or modify 28.9 + * it under the terms of the GNU Lesser General Public License as published by 28.10 + * the Free Software Foundation; either version 2.1 of the License, or 28.11 + * (at your option) any later version. 28.12 + * 28.13 + * This library is distributed in the hope that it will be useful, 28.14 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 28.15 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 28.16 + * GNU Lesser General Public License for more details. 28.17 + * 28.18 + * You should have received a copy of the GNU Lesser General Public License 28.19 + * along with this library; if not, write to the Free Software 28.20 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 28.21 + */ 28.22 + 28.23 +#ifndef _XEN_LIB_SOCKET_STREAM_H_ 28.24 +#define _XEN_LIB_SOCKET_STREAM_H_ 28.25 + 28.26 +#ifndef __KERNEL__ 28.27 +#include "iostream.h" 28.28 +#include <stdio.h> 28.29 + 28.30 +#include <sys/socket.h> 28.31 +#include <netinet/in.h> 28.32 +#include <arpa/inet.h> 28.33 + 28.34 +/** Data associated with a socket stream. */ 28.35 +typedef struct SocketData { 28.36 + /** The socket file descriptor. */ 28.37 + int fd; 28.38 + /** Source address from last read (recvfrom). */ 28.39 + struct sockaddr_in saddr; 28.40 + /** Destination address for writes (sendto). */ 28.41 + struct sockaddr_in daddr; 28.42 + /** Write flags (sendto). */ 28.43 + int flags; 28.44 + /** Buffer size. */ 28.45 + int buf_n; 28.46 + /** Buffer for formatted printing. */ 28.47 + char buf[1024]; 28.48 +} SocketData; 28.49 + 28.50 +extern IOStream *socket_stream_new(int fd); 28.51 +extern int socket_stream_data(IOStream *io, SocketData **data); 28.52 +extern int socket_stream_check(IOStream *io); 28.53 +extern int socket_stream_set_addr(IOStream *io, struct sockaddr_in *addr); 28.54 +extern int socket_stream_set_flags(IOStream *io, int flags); 28.55 + 28.56 +#endif 28.57 +#endif /* !_XEN_LIB_SOCKET_STREAM_H_ */
29.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 29.2 +++ b/tools/lib/string_stream.c Tue Jun 29 12:05:29 2004 +0000 29.3 @@ -0,0 +1,174 @@ 29.4 +/* 29.5 + * Copyright (C) 2001, 2002 Hewlett-Packard Company. 29.6 + * 29.7 + * This library is free software; you can redistribute it and/or modify 29.8 + * it under the terms of the GNU Lesser General Public License as published by 29.9 + * the Free Software Foundation; either version 2.1 of the License, or 29.10 + * (at your option) any later version. 29.11 + * 29.12 + * This library is distributed in the hope that it will be useful, 29.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 29.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 29.15 + * GNU Lesser General Public License for more details. 29.16 + * 29.17 + * You should have received a copy of the GNU Lesser General Public License 29.18 + * along with this library; if not, write to the Free Software 29.19 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 29.20 + */ 29.21 + 29.22 +/** @file 29.23 + * IOStream subtype for input and output to strings. 29.24 + * Usable from user or kernel code (with __KERNEL__ defined). 29.25 + */ 29.26 + 29.27 +#include "sys_string.h" 29.28 +#include "string_stream.h" 29.29 +#include "allocate.h" 29.30 + 29.31 +static int string_print(IOStream *io, const char *msg, va_list args); 29.32 +static int string_getc(IOStream *io); 29.33 +static int string_error(IOStream *io); 29.34 +static int string_close(IOStream *io); 29.35 +static void string_free(IOStream *io); 29.36 + 29.37 +/** Methods for a string stream. */ 29.38 +static IOMethods string_methods = { 29.39 + //print: string_print, 29.40 + //getc: string_getc, 29.41 + error: string_error, 29.42 + close: string_close, 29.43 + free: string_free, 29.44 +}; 29.45 + 29.46 +/** Get the string stream state. 29.47 + * 29.48 + * @param io string stream 29.49 + * @return state 29.50 + */ 29.51 +static inline StringData *get_string_data(IOStream *io){ 29.52 + return (StringData*)io->data; 29.53 +} 29.54 + 29.55 +/** Read a character from a string stream. 29.56 + * 29.57 + * @param io string stream 29.58 + * @return character read, IOSTREAM_EOF if no more input 29.59 + */ 29.60 +static int string_getc(IOStream *io){ 29.61 + StringData *data = get_string_data(io); 29.62 + int c = IOSTREAM_EOF; 29.63 + char *s = data->in; 29.64 + 29.65 + if(s && s < data->end){ 29.66 + c = (unsigned)*s; 29.67 + data->in = s+1; 29.68 + } 29.69 + return c; 29.70 +} 29.71 + 29.72 +/** Print to a string stream. 29.73 + * Formats the data to an internal buffer and prints it. 29.74 + * The formatted data must fit into the internal buffer. 29.75 + * 29.76 + * @param io string stream 29.77 + * @param format print format 29.78 + * @param args print arguments 29.79 + * @return result of the print 29.80 + */ 29.81 +static int string_print(IOStream *io, const char *msg, va_list args){ 29.82 + StringData *data = get_string_data(io); 29.83 + int k = data->end - data->out; 29.84 + int n = vsnprintf(data->out, k, (char*)msg, args); 29.85 + if(n < 0 || n > k ){ 29.86 + n = k; 29.87 + IOStream_close(io); 29.88 + } else { 29.89 + data->out += n; 29.90 + } 29.91 + return n; 29.92 +} 29.93 + 29.94 +/** Test if a string stream has an error. 29.95 + * 29.96 + * @param io string stream 29.97 + * @return 0 if ok, error code otherwise 29.98 + */ 29.99 +static int string_error(IOStream *io){ 29.100 + StringData *data = get_string_data(io); 29.101 + return data->out == NULL; 29.102 +} 29.103 + 29.104 +/** Close a string stream. 29.105 + * 29.106 + * @param io string stream 29.107 + * @return 0 29.108 + */ 29.109 +static int string_close(IOStream *io){ 29.110 + StringData *data = get_string_data(io); 29.111 + data->in = NULL; 29.112 + data->out = NULL; 29.113 + return 0; 29.114 +} 29.115 + 29.116 +/** Free a string stream. 29.117 + * The stream must have been allocated, not statically created. 29.118 + * The stream state is freed, but the underlying string is not. 29.119 + * 29.120 + * @param io string stream 29.121 + */ 29.122 +static void string_free(IOStream *io){ 29.123 + StringData *data = get_string_data(io); 29.124 + zero(data, sizeof(*data)); 29.125 + deallocate(data); 29.126 +} 29.127 + 29.128 +/** Get the methods to use for a string stream. 29.129 + * 29.130 + * @return methods 29.131 + */ 29.132 +IOMethods *string_stream_get_methods(void){ 29.133 + return &string_methods; 29.134 +} 29.135 + 29.136 +/** Initialise a string stream, usually from static data. 29.137 + * 29.138 + * @param io address of IOStream to fill in 29.139 + * @param data address of StringData to fill in 29.140 + * @param s string to use 29.141 + * @param n length of the string 29.142 + */ 29.143 +void string_stream_init(IOStream *io, StringData *data, char *s, int n){ 29.144 + if(data && io){ 29.145 + zero(data, sizeof(*data)); 29.146 + data->string = (char*)s; 29.147 + data->in = data->string; 29.148 + data->out = data->string; 29.149 + data->size = n; 29.150 + data->end = data->string + n; 29.151 + zero(io, sizeof(*io)); 29.152 + io->methods = &string_methods; 29.153 + io->data = data; 29.154 + } 29.155 +} 29.156 + 29.157 +/** Allocate and initialise a string stream. 29.158 + * 29.159 + * @param s string to use 29.160 + * @param n length of the string 29.161 + * @return new stream (free using IOStream_free) 29.162 + */ 29.163 +IOStream *string_stream_new(char *s, int n){ 29.164 + int ok = 0; 29.165 + StringData *data = ALLOCATE(StringData); 29.166 + IOStream *io = ALLOCATE(IOStream); 29.167 + if(data && io){ 29.168 + ok = 1; 29.169 + string_stream_init(io, data, s, n); 29.170 + } 29.171 + if(!ok){ 29.172 + deallocate(data); 29.173 + deallocate(io); 29.174 + io = NULL; 29.175 + } 29.176 + return io; 29.177 +}
30.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 30.2 +++ b/tools/lib/string_stream.h Tue Jun 29 12:05:29 2004 +0000 30.3 @@ -0,0 +1,46 @@ 30.4 +/* $Id: string_stream.h,v 1.1 2003/08/22 14:25:48 mjw Exp $ */ 30.5 +/* 30.6 + * Copyright (C) 2001, 2002 Hewlett-Packard Company. 30.7 + * 30.8 + * This library is free software; you can redistribute it and/or modify 30.9 + * it under the terms of the GNU Lesser General Public License as published by 30.10 + * the Free Software Foundation; either version 2.1 of the License, or 30.11 + * (at your option) any later version. 30.12 + * 30.13 + * This library is distributed in the hope that it will be useful, 30.14 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 30.15 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 30.16 + * GNU Lesser General Public License for more details. 30.17 + * 30.18 + * You should have received a copy of the GNU Lesser General Public License 30.19 + * along with this library; if not, write to the Free Software 30.20 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 30.21 + */ 30.22 + 30.23 +#ifndef _SP_STRING_STREAM_H_ 30.24 +#define _SP_STRING_STREAM_H_ 30.25 + 30.26 +#include "iostream.h" 30.27 + 30.28 +/** Internal state for a string stream. 30.29 + * Exposed here so that string streams can be statically created, using 30.30 + * string_stream_init(). 30.31 + */ 30.32 +typedef struct { 30.33 + /** The string used for input and ouput. */ 30.34 + char *string; 30.35 + /** Output pointer. */ 30.36 + char *out; 30.37 + /** Input pointer. */ 30.38 + char *in; 30.39 + /** Length of string. */ 30.40 + int size; 30.41 + /** End marker. */ 30.42 + char *end; 30.43 +} StringData; 30.44 + 30.45 +extern IOMethods *string_stream_get_methods(void); 30.46 +extern IOStream *string_stream_new(char *s, int n); 30.47 +extern void string_stream_init(IOStream *stream, StringData *data, char *s, int n); 30.48 + 30.49 +#endif /* !_SP_STRING_STREAM_H_ */
31.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 31.2 +++ b/tools/lib/sxpr.c Tue Jun 29 12:05:29 2004 +0000 31.3 @@ -0,0 +1,935 @@ 31.4 +/* 31.5 + * 31.6 + * This library is free software; you can redistribute it and/or modify 31.7 + * it under the terms of the GNU Lesser General Public License as 31.8 + * published by the Free Software Foundation; either version 2.1 of the 31.9 + * License, or (at your option) any later version. This library is 31.10 + * distributed in the hope that it will be useful, but WITHOUT ANY 31.11 + * WARRANTY; without even the implied warranty of MERCHANTABILITY or 31.12 + * FITNESS FOR A PARTICULAR PURPOSE. 31.13 + * See the GNU Lesser General Public License for more details. 31.14 + * 31.15 + * You should have received a copy of the GNU Lesser General Public License 31.16 + * along with this library; if not, write to the Free Software Foundation, 31.17 + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 31.18 + */ 31.19 + 31.20 +#include <stdarg.h> 31.21 +#include "sys_string.h" 31.22 +#include "lexis.h" 31.23 +#include "sys_net.h" 31.24 +#include "hash_table.h" 31.25 +#include "sxpr.h" 31.26 + 31.27 +#include <errno.h> 31.28 +#undef free 31.29 + 31.30 +/** @file 31.31 + * General representation of sxprs. 31.32 + * Includes print, equal, and free functions for the sxpr types. 31.33 + * 31.34 + * Zero memory containing an Sxpr will have the value ONONE - this is intentional. 31.35 + * When a function returning an sxpr cannot allocate memory we return ONOMEM. 31.36 + * 31.37 + */ 31.38 + 31.39 +static int atom_print(IOStream *io, Sxpr obj, unsigned flags); 31.40 +static int atom_equal(Sxpr x, Sxpr y); 31.41 +static void atom_free(Sxpr obj); 31.42 + 31.43 +static int string_print(IOStream *io, Sxpr obj, unsigned flags); 31.44 +static int string_equal(Sxpr x, Sxpr y); 31.45 +static void string_free(Sxpr obj); 31.46 + 31.47 +static int cons_print(IOStream *io, Sxpr obj, unsigned flags); 31.48 +static int cons_equal(Sxpr x, Sxpr y); 31.49 +static void cons_free(Sxpr obj); 31.50 + 31.51 +static int null_print(IOStream *io, Sxpr obj, unsigned flags); 31.52 +static int none_print(IOStream *io, Sxpr obj, unsigned flags); 31.53 +static int int_print(IOStream *io, Sxpr obj, unsigned flags); 31.54 +static int bool_print(IOStream *io, Sxpr obj, unsigned flags); 31.55 + 31.56 +/** Type definitions. */ 31.57 +static SxprType types[1024] = { 31.58 + [T_NONE] { type: T_NONE, name: "none", print: none_print }, 31.59 + [T_NULL] { type: T_NULL, name: "null", print: null_print }, 31.60 + [T_UINT] { type: T_UINT, name: "int", print: int_print, }, 31.61 + [T_BOOL] { type: T_BOOL, name: "bool", print: bool_print, }, 31.62 + [T_ATOM] { type: T_ATOM, name: "atom", print: atom_print, 31.63 + pointer: TRUE, 31.64 + free: atom_free, 31.65 + equal: atom_equal, 31.66 + }, 31.67 + [T_STRING] { type: T_STRING, name: "string", print: string_print, 31.68 + pointer: TRUE, 31.69 + free: string_free, 31.70 + equal: string_equal, 31.71 + }, 31.72 + [T_CONS] { type: T_CONS, name: "cons", print: cons_print, 31.73 + pointer: TRUE, 31.74 + free: cons_free, 31.75 + equal: cons_equal, 31.76 + }, 31.77 +}; 31.78 + 31.79 +/** Number of entries in the types array. */ 31.80 +static int type_sup = sizeof(types)/sizeof(types[0]); 31.81 + 31.82 +/** Get the type definition for a given type code. 31.83 + * 31.84 + * @param ty type code 31.85 + * @return type definition or null 31.86 + */ 31.87 +SxprType *get_sxpr_type(int ty){ 31.88 + if(0 <= ty && ty < type_sup){ 31.89 + return types+ty; 31.90 + } 31.91 + return NULL; 31.92 +} 31.93 + 31.94 +/** The default print function. 31.95 + * 31.96 + * @param io stream to print to 31.97 + * @param x sxpr to print 31.98 + * @param flags print flags 31.99 + * @return number of bytes written on success 31.100 + */ 31.101 +int default_print(IOStream *io, Sxpr x, unsigned flags){ 31.102 + return IOStream_print(io, "#<%u %lu>\n", get_type(x), get_ul(x)); 31.103 +} 31.104 + 31.105 +/** The default equal function. 31.106 + * Uses eq(). 31.107 + * 31.108 + * @param x sxpr to compare 31.109 + * @param y sxpr to compare 31.110 + * @return 1 if equal, 0 otherwise 31.111 + */ 31.112 +int default_equal(Sxpr x, Sxpr y){ 31.113 + return eq(x, y); 31.114 +} 31.115 + 31.116 +/** General sxpr print function. 31.117 + * Prints an sxpr on a stream using the print function for the sxpr type. 31.118 + * Printing is controlled by flags from the PrintFlags enum. 31.119 + * If PRINT_TYPE is in the flags the sxpr type is printed before the sxpr 31.120 + * (for debugging). 31.121 + * 31.122 + * @param io stream to print to 31.123 + * @param x sxpr to print 31.124 + * @param flags print flags 31.125 + * @return number of bytes written 31.126 + */ 31.127 +int objprint(IOStream *io, Sxpr x, unsigned flags){ 31.128 + SxprType *def = get_sxpr_type(get_type(x)); 31.129 + ObjPrintFn *print_fn = (def && def->print ? def->print : default_print); 31.130 + int k = 0; 31.131 + if(!io) return k; 31.132 + if(flags & PRINT_TYPE){ 31.133 + k += IOStream_print(io, "%s:", def->name); 31.134 + } 31.135 + k += print_fn(io, x, flags); 31.136 + return k; 31.137 +} 31.138 + 31.139 +/** General sxpr free function. 31.140 + * Frees an sxpr using the free function for its type. 31.141 + * Free functions must recursively free any subsxprs. 31.142 + * If no function is defined then the default is to 31.143 + * free sxprs whose type has pointer true. 31.144 + * Sxprs must not be used after freeing. 31.145 + * 31.146 + * @param x sxpr to free 31.147 + */ 31.148 +void objfree(Sxpr x){ 31.149 + SxprType *def = get_sxpr_type(get_type(x)); 31.150 + 31.151 + if(def){ 31.152 + if(def->free){ 31.153 + def->free(x); 31.154 + } else if (def->pointer){ 31.155 + hfree(x); 31.156 + } 31.157 + } 31.158 +} 31.159 + 31.160 +/** General sxpr equality function. 31.161 + * Compares x and y using the equal function for x. 31.162 + * Uses default_equal() if x has no equal function. 31.163 + * 31.164 + * @param x sxpr to compare 31.165 + * @param y sxpr to compare 31.166 + * @return 1 if equal, 0 otherwise 31.167 + */ 31.168 +int objequal(Sxpr x, Sxpr y){ 31.169 + SxprType *def = get_sxpr_type(get_type(x)); 31.170 + ObjEqualFn *equal_fn = (def && def->equal ? def->equal : default_equal); 31.171 + return equal_fn(x, y); 31.172 +} 31.173 + 31.174 +/** Search for a key in an alist. 31.175 + * An alist is a list of conses, where the cars 31.176 + * of the conses are the keys. Compares keys using equality. 31.177 + * 31.178 + * @param k key 31.179 + * @param l alist to search 31.180 + * @return first element of l with car k, or ONULL 31.181 + */ 31.182 +Sxpr assoc(Sxpr k, Sxpr l){ 31.183 + for( ; CONSP(l) ; l = CDR(l)){ 31.184 + Sxpr x = CAR(l); 31.185 + if(CONSP(x) && objequal(k, CAR(x))){ 31.186 + return x; 31.187 + } 31.188 + } 31.189 + return ONULL; 31.190 +} 31.191 + 31.192 +/** Search for a key in an alist. 31.193 + * An alist is a list of conses, where the cars 31.194 + * of the conses are the keys. Compares keys using eq. 31.195 + * 31.196 + * @param k key 31.197 + * @param l alist to search 31.198 + * @return first element of l with car k, or ONULL 31.199 + */ 31.200 +Sxpr assocq(Sxpr k, Sxpr l){ 31.201 + for( ; CONSP(l); l = CDR(l)){ 31.202 + Sxpr x = CAR(l); 31.203 + if(CONSP(x) && eq(k, CAR(x))){ 31.204 + return x; 31.205 + } 31.206 + } 31.207 + return ONULL; 31.208 +} 31.209 + 31.210 +/** Add a new key and value to an alist. 31.211 + * 31.212 + * @param k key 31.213 + * @param l value 31.214 + * @param l alist 31.215 + * @return l with the new cell added to the front 31.216 + */ 31.217 +Sxpr acons(Sxpr k, Sxpr v, Sxpr l){ 31.218 + Sxpr x, y; 31.219 + x = cons_new(k, v); 31.220 + if(NOMEMP(x)) return x; 31.221 + y = cons_new(x, l); 31.222 + if(NOMEMP(y)) cons_free_cells(x); 31.223 + return y; 31.224 +} 31.225 + 31.226 +/** Test if a list contains an element. 31.227 + * Uses sxpr equality. 31.228 + * 31.229 + * @param l list 31.230 + * @param x element to look for 31.231 + * @return a tail of l with x as car, or ONULL 31.232 + */ 31.233 +Sxpr cons_member(Sxpr l, Sxpr x){ 31.234 + for( ; CONSP(l) && !eq(x, CAR(l)); l = CDR(l)){} 31.235 + return l; 31.236 +} 31.237 + 31.238 +/** Test if a list contains an element satisfying a test. 31.239 + * The test function is called with v and an element of the list. 31.240 + * 31.241 + * @param l list 31.242 + * @param test_fn test function to use 31.243 + * @param v value for first argument to the test 31.244 + * @return a tail of l with car satisfying the test, or 0 31.245 + */ 31.246 +Sxpr cons_member_if(Sxpr l, ObjEqualFn *test_fn, Sxpr v){ 31.247 + for( ; CONSP(l) && !test_fn(v, CAR(l)); l = CDR(l)){ } 31.248 + return l; 31.249 +} 31.250 + 31.251 +/** Test if the elements of list 't' are a subset of the elements 31.252 + * of list 's'. Element order is not significant. 31.253 + * 31.254 + * @param s element list to check subset of 31.255 + * @param t element list to check if is a subset 31.256 + * @return 1 if is a subset, 0 otherwise 31.257 + */ 31.258 +int cons_subset(Sxpr s, Sxpr t){ 31.259 + for( ; CONSP(t); t = CDR(t)){ 31.260 + if(!CONSP(cons_member(s, CAR(t)))){ 31.261 + return 0; 31.262 + } 31.263 + } 31.264 + return 1; 31.265 +} 31.266 + 31.267 +/** Test if two lists have equal sets of elements. 31.268 + * Element order is not significant. 31.269 + * 31.270 + * @param s list to check 31.271 + * @param t list to check 31.272 + * @return 1 if equal, 0 otherwise 31.273 + */ 31.274 +int cons_set_equal(Sxpr s, Sxpr t){ 31.275 + return cons_subset(s, t) && cons_subset(t, s); 31.276 +} 31.277 + 31.278 +#ifdef USE_GC 31.279 +/*============================================================================*/ 31.280 +/* The functions inside this ifdef are only safe if GC is used. 31.281 + * Otherwise they may leak memory. 31.282 + */ 31.283 + 31.284 +/** Remove an element from a list (GC only). 31.285 + * Uses sxpr equality and removes all instances, even 31.286 + * if there are more than one. 31.287 + * 31.288 + * @param l list to remove elements from 31.289 + * @param x element to remove 31.290 + * @return modified input list 31.291 + */ 31.292 +Sxpr cons_remove(Sxpr l, Sxpr x){ 31.293 + return cons_remove_if(l, eq, x); 31.294 +} 31.295 + 31.296 +/** Remove elements satisfying a test (GC only). 31.297 + * The test function is called with v and an element of the set. 31.298 + * 31.299 + * @param l list to remove elements from 31.300 + * @param test_fn function to use to decide if an element should be removed 31.301 + * @return modified input list 31.302 + */ 31.303 +Sxpr cons_remove_if(Sxpr l, ObjEqualFn *test_fn, Sxpr v){ 31.304 + Sxpr prev = ONULL, elt, next; 31.305 + 31.306 + for(elt = l; CONSP(elt); elt = next){ 31.307 + next = CDR(elt); 31.308 + if(test_fn(v, CAR(elt))){ 31.309 + if(NULLP(prev)){ 31.310 + l = next; 31.311 + } else { 31.312 + CDR(prev) = next; 31.313 + } 31.314 + } 31.315 + } 31.316 + return l; 31.317 +} 31.318 + 31.319 +/** Set the value for a key in an alist (GC only). 31.320 + * If the key is present, changes the value, otherwise 31.321 + * adds a new cell. 31.322 + * 31.323 + * @param k key 31.324 + * @param v value 31.325 + * @param l alist 31.326 + * @return modified or extended list 31.327 + */ 31.328 +Sxpr setf(Sxpr k, Sxpr v, Sxpr l){ 31.329 + Sxpr e = assoc(k, l); 31.330 + if(NULLP(e)){ 31.331 + l = acons(k, v, l); 31.332 + } else { 31.333 + CAR(CDR(e)) = v; 31.334 + } 31.335 + return l; 31.336 +} 31.337 +/*============================================================================*/ 31.338 +#endif /* USE_GC */ 31.339 + 31.340 +/** Create a new atom with the given name. 31.341 + * 31.342 + * @param name the name 31.343 + * @return new atom 31.344 + */ 31.345 +Sxpr atom_new(char *name){ 31.346 + Sxpr n, obj = ONOMEM; 31.347 + 31.348 + n = string_new(name); 31.349 + if(NOMEMP(n)) goto exit; 31.350 + obj = HALLOC(ObjAtom, T_ATOM); 31.351 + if(NOMEMP(obj)) goto exit; 31.352 + OBJ_ATOM(obj)->name = n; 31.353 + exit: 31.354 + return obj; 31.355 +} 31.356 + 31.357 +/** Free an atom. 31.358 + * 31.359 + * @param obj to free 31.360 + */ 31.361 +void atom_free(Sxpr obj){ 31.362 + // Interned atoms are shared, so do not free. 31.363 + if(OBJ_ATOM(obj)->interned) return; 31.364 + objfree(OBJ_ATOM(obj)->name); 31.365 + hfree(obj); 31.366 +} 31.367 + 31.368 +/** Print an atom. Prints the atom name. 31.369 + * 31.370 + * @param io stream to print to 31.371 + * @param obj to print 31.372 + * @param flags print flags 31.373 + * @return number of bytes printed 31.374 + */ 31.375 +int atom_print(IOStream *io, Sxpr obj, unsigned flags){ 31.376 + //return string_print(io, OBJ_ATOM(obj)->name, (flags | PRINT_RAW)); 31.377 + return string_print(io, OBJ_ATOM(obj)->name, flags); 31.378 +} 31.379 + 31.380 +/** Atom equality. 31.381 + * 31.382 + * @param x to compare 31.383 + * @param y to compare 31.384 + * @return 1 if equal, 0 otherwise 31.385 + */ 31.386 +int atom_equal(Sxpr x, Sxpr y){ 31.387 + int ok; 31.388 + ok = eq(x, y); 31.389 + if(ok) goto exit; 31.390 + ok = ATOMP(y) && string_equal(OBJ_ATOM(x)->name, OBJ_ATOM(y)->name); 31.391 + if(ok) goto exit; 31.392 + ok = STRINGP(y) && string_equal(OBJ_ATOM(x)->name, y); 31.393 + exit: 31.394 + return ok; 31.395 +} 31.396 + 31.397 +/** Get the name of an atom. 31.398 + * 31.399 + * @param obj atom 31.400 + * @return name 31.401 + */ 31.402 +char * atom_name(Sxpr obj){ 31.403 + return string_string(OBJ_ATOM(obj)->name); 31.404 +} 31.405 + 31.406 +/** Get the C string from a string sxpr. 31.407 + * 31.408 + * @param obj string sxpr 31.409 + * @return string 31.410 + */ 31.411 +char * string_string(Sxpr obj){ 31.412 + return OBJ_STRING(obj); 31.413 +} 31.414 + 31.415 +/** Get the length of a string. 31.416 + * 31.417 + * @param obj string 31.418 + * @return length 31.419 + */ 31.420 +int string_length(Sxpr obj){ 31.421 + return strlen(OBJ_STRING(obj)); 31.422 +} 31.423 + 31.424 +/** Create a new string. The input string is copied, 31.425 + * and must be null-terminated. 31.426 + * 31.427 + * @param s characters to put in the string 31.428 + * @return new sxpr 31.429 + */ 31.430 +Sxpr string_new(char *s){ 31.431 + int n = (s ? strlen(s) : 0); 31.432 + Sxpr obj; 31.433 + obj = halloc(n+1, T_STRING); 31.434 + if(!NOMEMP(obj)){ 31.435 + char *str = OBJ_STRING(obj); 31.436 + strncpy(str, s, n); 31.437 + str[n] = '\0'; 31.438 + } 31.439 + return obj; 31.440 +} 31.441 + 31.442 +/** Free a string. 31.443 + * 31.444 + * @param obj to free 31.445 + */ 31.446 +void string_free(Sxpr obj){ 31.447 + hfree(obj); 31.448 +} 31.449 + 31.450 +/** Determine if a string needs escapes when printed 31.451 + * using the given flags. 31.452 + * 31.453 + * @param str string to check 31.454 + * @param flags print flags 31.455 + * @return 1 if needs escapes, 0 otherwise 31.456 + */ 31.457 +int needs_escapes(char *str, unsigned flags){ 31.458 + char *c; 31.459 + int val = 0; 31.460 + 31.461 + if(str){ 31.462 + for(c=str; *c; c++){ 31.463 + if(in_alpha_class(*c)) continue; 31.464 + if(in_decimal_digit_class(*c)) continue; 31.465 + if(in_class(*c, "/._+:@~-")) continue; 31.466 + val = 1; 31.467 + break; 31.468 + } 31.469 + } 31.470 + //printf("\n> val=%d str=|%s|\n", val, str); 31.471 + return val; 31.472 +} 31.473 + 31.474 +/** Print a string to a stream, with escapes if necessary. 31.475 + * 31.476 + * @param io stream to print to 31.477 + * @param str string 31.478 + * @param flags print flags 31.479 + * @return number of bytes written 31.480 + */ 31.481 +int _string_print(IOStream *io, char *str, unsigned flags){ 31.482 + int k = 0; 31.483 + if((flags & PRINT_RAW) || !needs_escapes(str, flags)){ 31.484 + k += IOStream_print(io, str); 31.485 + } else { 31.486 + k += IOStream_print(io, "\""); 31.487 + if(str){ 31.488 + char *s; 31.489 + for(s = str; *s; s++){ 31.490 + if(*s < ' ' || *s >= 127 ){ 31.491 + switch(*s){ 31.492 + case '\a': k += IOStream_print(io, "\\a"); break; 31.493 + case '\b': k += IOStream_print(io, "\\b"); break; 31.494 + case '\f': k += IOStream_print(io, "\\f"); break; 31.495 + case '\n': k += IOStream_print(io, "\\n"); break; 31.496 + case '\r': k += IOStream_print(io, "\\r"); break; 31.497 + case '\t': k += IOStream_print(io, "\\t"); break; 31.498 + case '\v': k += IOStream_print(io, "\\v"); break; 31.499 + default: 31.500 + // Octal escape; 31.501 + k += IOStream_print(io, "\\%o", *s); 31.502 + break; 31.503 + } 31.504 + } else if(*s == c_double_quote || 31.505 + *s == c_single_quote || 31.506 + *s == c_escape){ 31.507 + k += IOStream_print(io, "\\%c", *s); 31.508 + } else { 31.509 + k+= IOStream_print(io, "%c", *s); 31.510 + } 31.511 + } 31.512 + } 31.513 + k += IOStream_print(io, "\""); 31.514 + } 31.515 + return k; 31.516 +} 31.517 + 31.518 +/** Print a string to a stream, with escapes if necessary. 31.519 + * 31.520 + * @param io stream to print to 31.521 + * @param obj string 31.522 + * @param flags print flags 31.523 + * @return number of bytes written 31.524 + */ 31.525 +int string_print(IOStream *io, Sxpr obj, unsigned flags){ 31.526 + return _string_print(io, OBJ_STRING(obj), flags); 31.527 +} 31.528 + 31.529 +/** Compare an sxpr with a string for equality. 31.530 + * 31.531 + * @param x string to compare with 31.532 + * @param y sxpr to compare 31.533 + * @return 1 if equal, 0 otherwise 31.534 + */ 31.535 +int string_equal(Sxpr x, Sxpr y){ 31.536 + int ok = 0; 31.537 + ok = eq(x,y); 31.538 + if(ok) goto exit; 31.539 + ok = has_type(y, T_STRING) && !strcmp(OBJ_STRING(x), OBJ_STRING(y)); 31.540 + if(ok) goto exit; 31.541 + ok = has_type(y, T_ATOM) && !strcmp(OBJ_STRING(x), atom_name(y)); 31.542 + exit: 31.543 + return ok; 31.544 +} 31.545 + 31.546 +/** Create a new cons cell. 31.547 + * The cell is ONOMEM if either argument is. 31.548 + * 31.549 + * @param car sxpr for the car 31.550 + * @param cdr sxpr for the cdr 31.551 + * @return new cons 31.552 + */ 31.553 +Sxpr cons_new(Sxpr car, Sxpr cdr){ 31.554 + Sxpr obj; 31.555 + if(NOMEMP(car) || NOMEMP(cdr)){ 31.556 + obj = ONOMEM; 31.557 + } else { 31.558 + obj = HALLOC(ObjCons, T_CONS); 31.559 + if(!NOMEMP(obj)){ 31.560 + ObjCons *z = OBJ_CONS(obj); 31.561 + z->car = car; 31.562 + z->cdr = cdr; 31.563 + } 31.564 + } 31.565 + return obj; 31.566 +} 31.567 + 31.568 +/** Push a new element onto a list. 31.569 + * 31.570 + * @param list list to add to 31.571 + * @param elt element to add 31.572 + * @return 0 if successful, error code otherwise 31.573 + */ 31.574 +int cons_push(Sxpr *list, Sxpr elt){ 31.575 + Sxpr l; 31.576 + l = cons_new(elt, *list); 31.577 + if(NOMEMP(l)) return -ENOMEM; 31.578 + *list = l; 31.579 + return 0; 31.580 +} 31.581 + 31.582 +/** Free a cons. Recursively frees the car and cdr. 31.583 + * 31.584 + * @param obj to free 31.585 + */ 31.586 +void cons_free(Sxpr obj){ 31.587 + Sxpr next; 31.588 + for(; CONSP(obj); obj = next){ 31.589 + next = CDR(obj); 31.590 + objfree(CAR(obj)); 31.591 + hfree(obj); 31.592 + } 31.593 + if(!NULLP(obj)){ 31.594 + objfree(obj); 31.595 + } 31.596 +} 31.597 + 31.598 +/** Free a cons and its cdr cells, but not the car sxprs. 31.599 + * Does nothing if called on something that is not a cons. 31.600 + * 31.601 + * @param obj to free 31.602 + */ 31.603 +void cons_free_cells(Sxpr obj){ 31.604 + Sxpr next; 31.605 + for(; CONSP(obj); obj = next){ 31.606 + next = CDR(obj); 31.607 + hfree(obj); 31.608 + } 31.609 +} 31.610 + 31.611 +/** Print a cons. 31.612 + * Prints the cons in list format if the cdrs are conses. 31.613 + * uses pair (dot) format if the last cdr is not a cons (or null). 31.614 + * 31.615 + * @param io stream to print to 31.616 + * @param obj to print 31.617 + * @param flags print flags 31.618 + * @return number of bytes written 31.619 + */ 31.620 +int cons_print(IOStream *io, Sxpr obj, unsigned flags){ 31.621 + int first = 1; 31.622 + int k = 0; 31.623 + k += IOStream_print(io, "("); 31.624 + for( ; CONSP(obj) ; obj = CDR(obj)){ 31.625 + if(first){ 31.626 + first = 0; 31.627 + } else { 31.628 + k += IOStream_print(io, " "); 31.629 + } 31.630 + k += objprint(io, CAR(obj), flags); 31.631 + } 31.632 + if(!NULLP(obj)){ 31.633 + k += IOStream_print(io, " . "); 31.634 + k += objprint(io, obj, flags); 31.635 + } 31.636 + k += IOStream_print(io, ")"); 31.637 + return (IOStream_error(io) ? -1 : k); 31.638 +} 31.639 + 31.640 +/** Compare a cons with another sxpr for equality. 31.641 + * If y is a cons, compares the cars and cdrs recursively. 31.642 + * 31.643 + * @param x cons to compare 31.644 + * @param y sxpr to compare 31.645 + * @return 1 if equal, 0 otherwise 31.646 + */ 31.647 +int cons_equal(Sxpr x, Sxpr y){ 31.648 + return CONSP(y) && 31.649 + objequal(CAR(x), CAR(y)) && 31.650 + objequal(CDR(x), CDR(y)); 31.651 +} 31.652 + 31.653 +/** Return the length of a cons list. 31.654 + * 31.655 + * @param obj list 31.656 + * @return length 31.657 + */ 31.658 +int cons_length(Sxpr obj){ 31.659 + int count = 0; 31.660 + for( ; CONSP(obj); obj = CDR(obj)){ 31.661 + count++; 31.662 + } 31.663 + return count; 31.664 +} 31.665 + 31.666 +/** Destructively reverse a cons list in-place. 31.667 + * If the argument is not a cons it is returned unchanged. 31.668 + * 31.669 + * @param l to reverse 31.670 + * @return reversed list 31.671 + */ 31.672 +Sxpr nrev(Sxpr l){ 31.673 + if(CONSP(l)){ 31.674 + // Iterate down the cells in the list making the cdr of 31.675 + // each cell point to the previous cell. The last cell 31.676 + // is the head of the reversed list. 31.677 + Sxpr prev = ONULL; 31.678 + Sxpr cell = l; 31.679 + Sxpr next; 31.680 + 31.681 + while(1){ 31.682 + next = CDR(cell); 31.683 + CDR(cell) = prev; 31.684 + if(!CONSP(next)) break; 31.685 + prev = cell; 31.686 + cell = next; 31.687 + } 31.688 + l = cell; 31.689 + } 31.690 + return l; 31.691 +} 31.692 + 31.693 +/** Print the null sxpr. 31.694 + * 31.695 + * @param io stream to print to 31.696 + * @param obj to print 31.697 + * @param flags print flags 31.698 + * @return number of bytes written 31.699 + */ 31.700 +static int null_print(IOStream *io, Sxpr obj, unsigned flags){ 31.701 + return IOStream_print(io, "()"); 31.702 +} 31.703 + 31.704 +/** Print the `unspecified' sxpr none. 31.705 + * 31.706 + * @param io stream to print to 31.707 + * @param obj to print 31.708 + * @param flags print flags 31.709 + * @return number of bytes written 31.710 + */ 31.711 +static int none_print(IOStream *io, Sxpr obj, unsigned flags){ 31.712 + return IOStream_print(io, "<none>"); 31.713 +} 31.714 + 31.715 +/** Print an integer. 31.716 + * 31.717 + * @param io stream to print to 31.718 + * @param obj to print 31.719 + * @param flags print flags 31.720 + * @return number of bytes written 31.721 + */ 31.722 +static int int_print(IOStream *io, Sxpr obj, unsigned flags){ 31.723 + return IOStream_print(io, "%d", OBJ_INT(obj)); 31.724 +} 31.725 + 31.726 +/** Print a boolean. 31.727 + * 31.728 + * @param io stream to print to 31.729 + * @param obj to print 31.730 + * @param flags print flags 31.731 + * @return number of bytes written 31.732 + */ 31.733 +static int bool_print(IOStream *io, Sxpr obj, unsigned flags){ 31.734 + return IOStream_print(io, (OBJ_UINT(obj) ? k_true : k_false)); 31.735 +} 31.736 + 31.737 +int sxprp(Sxpr obj, Sxpr name){ 31.738 + return CONSP(obj) && objequal(CAR(obj), name); 31.739 +} 31.740 + 31.741 +/** Get the name of an element. 31.742 + * 31.743 + * @param obj element 31.744 + * @return name 31.745 + */ 31.746 +Sxpr sxpr_name(Sxpr obj){ 31.747 + Sxpr val = ONONE; 31.748 + if(CONSP(obj)){ 31.749 + val = CAR(obj); 31.750 + } else if(STRINGP(obj) || ATOMP(obj)){ 31.751 + val = obj; 31.752 + } 31.753 + return val; 31.754 +} 31.755 + 31.756 +int sxpr_is(Sxpr obj, char *s){ 31.757 + if(ATOMP(obj)) return !strcmp(atom_name(obj), s); 31.758 + if(STRINGP(obj)) return !strcmp(string_string(obj), s); 31.759 + return 0; 31.760 +} 31.761 + 31.762 +int sxpr_elementp(Sxpr obj, Sxpr name){ 31.763 + return CONSP(obj) && objequal(CAR(obj), name); 31.764 +} 31.765 + 31.766 +/** Get the attributes of an sxpr. 31.767 + * 31.768 + * @param obj sxpr 31.769 + * @return attributes 31.770 + */ 31.771 +Sxpr sxpr_attributes(Sxpr obj){ 31.772 + Sxpr val = ONULL; 31.773 + if(CONSP(obj)){ 31.774 + obj = CDR(obj); 31.775 + if(CONSP(obj)){ 31.776 + obj = CAR(obj); 31.777 + if(sxprp(obj, intern("@"))){ 31.778 + val = CDR(obj); 31.779 + } 31.780 + } 31.781 + } 31.782 + return val; 31.783 +} 31.784 + 31.785 +Sxpr sxpr_attribute(Sxpr obj, Sxpr key, Sxpr def){ 31.786 + Sxpr val = ONONE; 31.787 + val = assoc(sxpr_attributes(obj), key); 31.788 + if(CONSP(val) && CONSP(CDR(val))){ 31.789 + val = CADR(def); 31.790 + } else { 31.791 + val = def; 31.792 + } 31.793 + return val; 31.794 +} 31.795 + 31.796 +/** Get the children of an sxpr. 31.797 + * 31.798 + * @param obj sxpr 31.799 + * @return children 31.800 + */ 31.801 +Sxpr sxpr_children(Sxpr obj){ 31.802 + Sxpr val = ONULL; 31.803 + if(CONSP(obj)){ 31.804 + val = CDR(obj); 31.805 + if(CONSP(val) && sxprp(CAR(val), intern("@"))){ 31.806 + val = CDR(val); 31.807 + } 31.808 + } 31.809 + return val; 31.810 +} 31.811 + 31.812 +Sxpr sxpr_child(Sxpr obj, Sxpr name, Sxpr def){ 31.813 + Sxpr val = ONONE; 31.814 + Sxpr l; 31.815 + for(l = sxpr_children(obj); CONSP(l); l = CDR(l)){ 31.816 + if(sxprp(CAR(l), name)){ 31.817 + val = CAR(l); 31.818 + break; 31.819 + } 31.820 + } 31.821 + if(NONEP(val)) val = def; 31.822 + return val; 31.823 +} 31.824 + 31.825 +Sxpr sxpr_child0(Sxpr obj, Sxpr def){ 31.826 + Sxpr val = ONONE; 31.827 + Sxpr l = sxpr_children(obj); 31.828 + if(CONSP(l)){ 31.829 + val = CAR(l); 31.830 + } else { 31.831 + val = def; 31.832 + } 31.833 + return val; 31.834 +} 31.835 + 31.836 +Sxpr sxpr_child_value(Sxpr obj, Sxpr name, Sxpr def){ 31.837 + Sxpr val = ONONE; 31.838 + val = sxpr_child(obj, name, ONONE); 31.839 + if(NONEP(val)){ 31.840 + val = def; 31.841 + } else { 31.842 + val = sxpr_child0(val, def); 31.843 + } 31.844 + return val; 31.845 +} 31.846 + 31.847 +/** Table of interned symbols. Indexed by symbol name. */ 31.848 +static HashTable *symbols = NULL; 31.849 + 31.850 +/** Hash function for entries in the symbol table. 31.851 + * 31.852 + * @param key to hash 31.853 + * @return hashcode 31.854 + */ 31.855 +static Hashcode sym_hash_fn(void *key){ 31.856 + return hash_string((char*)key); 31.857 +} 31.858 + 31.859 +/** Key equality function for the symbol table. 31.860 + * 31.861 + * @param x to compare 31.862 + * @param y to compare 31.863 + * @return 1 if equal, 0 otherwise 31.864 + */ 31.865 +static int sym_equal_fn(void *x, void *y){ 31.866 + return !strcmp((char*)x, (char*)y); 31.867 +} 31.868 + 31.869 +/** Entry free function for the symbol table. 31.870 + * 31.871 + * @param table the entry is in 31.872 + * @param entry being freed 31.873 + */ 31.874 +static void sym_free_fn(HashTable *table, HTEntry *entry){ 31.875 + if(entry){ 31.876 + objfree(((ObjAtom*)entry->value)->name); 31.877 + HTEntry_free(entry); 31.878 + } 31.879 +} 31.880 + 31.881 +/** Initialize the symbol table. 31.882 + * 31.883 + * @return 0 on sucess, error code otherwise 31.884 + */ 31.885 +static int init_symbols(void){ 31.886 + symbols = HashTable_new(100); 31.887 + if(symbols){ 31.888 + symbols->key_hash_fn = sym_hash_fn; 31.889 + symbols->key_equal_fn = sym_equal_fn; 31.890 + symbols->entry_free_fn = sym_free_fn; 31.891 + return 0; 31.892 + } 31.893 + return -1; 31.894 +} 31.895 + 31.896 +/** Cleanup the symbol table. Frees the table and all its symbols. 31.897 + */ 31.898 +void cleanup_symbols(void){ 31.899 + HashTable_free(symbols); 31.900 + symbols = NULL; 31.901 +} 31.902 + 31.903 +/** Get the interned symbol with the given name. 31.904 + * No new symbol is created. 31.905 + * 31.906 + * @return symbol or null 31.907 + */ 31.908 +Sxpr get_symbol(char *sym){ 31.909 + HTEntry *entry; 31.910 + if(!symbols){ 31.911 + if(init_symbols()) return ONOMEM; 31.912 + return ONULL; 31.913 + } 31.914 + entry = HashTable_get_entry(symbols, sym); 31.915 + if(entry){ 31.916 + return OBJP(T_ATOM, entry->value); 31.917 + } else { 31.918 + return ONULL; 31.919 + } 31.920 +} 31.921 + 31.922 +/** Get the interned symbol with the given name. 31.923 + * Creates a new symbol if necessary. 31.924 + * 31.925 + * @return symbol 31.926 + */ 31.927 +Sxpr intern(char *sym){ 31.928 + Sxpr symbol = get_symbol(sym); 31.929 + if(NULLP(symbol)){ 31.930 + if(!symbols) return ONOMEM; 31.931 + symbol = atom_new(sym); 31.932 + if(!NOMEMP(symbol)){ 31.933 + OBJ_ATOM(symbol)->interned = TRUE; 31.934 + HashTable_add(symbols, atom_name(symbol), get_ptr(symbol)); 31.935 + } 31.936 + } 31.937 + return symbol; 31.938 +}
32.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 32.2 +++ b/tools/lib/sxpr.h Tue Jun 29 12:05:29 2004 +0000 32.3 @@ -0,0 +1,413 @@ 32.4 +/* 32.5 + * 32.6 + * This library is free software; you can redistribute it and/or modify 32.7 + * it under the terms of the GNU Lesser General Public License as 32.8 + * published by the Free Software Foundation; either version 2.1 of the 32.9 + * License, or (at your option) any later version. This library is 32.10 + * distributed in the hope that it will be useful, but WITHOUT ANY 32.11 + * WARRANTY; without even the implied warranty of MERCHANTABILITY or 32.12 + * FITNESS FOR A PARTICULAR PURPOSE. 32.13 + * See the GNU Lesser General Public License for more details. 32.14 + * 32.15 + * You should have received a copy of the GNU Lesser General Public License 32.16 + * along with this library; if not, write to the Free Software Foundation, 32.17 + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 32.18 + */ 32.19 +#ifndef _XEN_LIB_SXPR_H_ 32.20 +#define _XEN_LIB_SXPR_H_ 32.21 + 32.22 +#include <stdint.h> 32.23 + 32.24 +#include "hash_table.h" 32.25 +#include "iostream.h" 32.26 +#include "allocate.h" 32.27 + 32.28 +/** @file 32.29 + * Definitions for rules and sxprs. 32.30 + */ 32.31 + 32.32 +#ifndef NULL 32.33 +#define NULL 0 32.34 +#endif 32.35 + 32.36 +#ifndef TRUE 32.37 +#define TRUE 1 32.38 +#endif 32.39 + 32.40 +#ifndef FALSE 32.41 +#define FALSE 0 32.42 +#endif 32.43 + 32.44 +/** Sxpr type. */ 32.45 +typedef int16_t TypeCode; 32.46 + 32.47 +/** A typed sxpr handle.*/ 32.48 +typedef struct Sxpr { 32.49 + /** Sxpr type. */ 32.50 + TypeCode type; 32.51 + union { 32.52 + /** Sxpr value. */ 32.53 + unsigned long ul; 32.54 + /** Pointer. */ 32.55 + void *ptr; 32.56 + } v; 32.57 +} Sxpr; 32.58 + 32.59 +/** Sxpr type to indicate out of memory. */ 32.60 +#define T_NOMEM ((TypeCode)-1) 32.61 +/** The 'unspecified' sxpr. */ 32.62 +#define T_NONE ((TypeCode)0) 32.63 +/** The empty list. */ 32.64 +#define T_NULL ((TypeCode)1) 32.65 +/** Unsigned integer. */ 32.66 +#define T_UINT ((TypeCode)2) 32.67 +/** A string. */ 32.68 +#define T_STRING ((TypeCode)3) 32.69 +/** An atom. */ 32.70 +#define T_ATOM ((TypeCode)4) 32.71 +/** A boolean. */ 32.72 +#define T_BOOL ((TypeCode)5) 32.73 + 32.74 +/** A cons (pair or list). */ 32.75 +#define T_CONS ((TypeCode)10) 32.76 + 32.77 +/** An error. */ 32.78 +#define T_ERR ((TypeCode)40) 32.79 + 32.80 +/** An atom. */ 32.81 +typedef struct ObjAtom { 32.82 + Sxpr name; 32.83 + Hashcode hashcode; 32.84 + int interned; 32.85 +} ObjAtom; 32.86 + 32.87 +/** A cons (pair). */ 32.88 +typedef struct ObjCons { 32.89 + Sxpr car; 32.90 + Sxpr cdr; 32.91 +} ObjCons; 32.92 + 32.93 +/** A vector. */ 32.94 +typedef struct ObjVector { 32.95 + int n; 32.96 + Sxpr data[0]; 32.97 +} ObjVector; 32.98 + 32.99 +/** Flags for sxpr printing. */ 32.100 +enum PrintFlags { 32.101 + PRINT_RAW = 0x001, 32.102 + PRINT_TYPE = 0x002, 32.103 + PRINT_PRETTY = 0x004, 32.104 + PRINT_NUM = 0x008, 32.105 +}; 32.106 + 32.107 +/** An integer sxpr. 32.108 + * 32.109 + * @param ty type 32.110 + * @param val integer value 32.111 + */ 32.112 +#define OBJI(ty, val) (Sxpr){ type: (ty), v: { ul: (val) }} 32.113 + 32.114 +/** A pointer sxpr. 32.115 + * If the pointer is non-null, returns an sxpr containing it. 32.116 + * If the pointer is null, returns ONOMEM. 32.117 + * 32.118 + * @param ty type 32.119 + * @param val pointer 32.120 + */ 32.121 +#define OBJP(ty, val) ((val) ? (Sxpr){ type: (ty), v: { ptr: (val) }} : ONOMEM) 32.122 + 32.123 +/** Make an integer sxpr containing a pointer. 32.124 + * 32.125 + * @param val pointer 32.126 + */ 32.127 +#define PTR(val) OBJP(T_UINT, (void*)(val)) 32.128 + 32.129 +/** Make an integer sxpr. 32.130 + * @param x value 32.131 + */ 32.132 +#define OINT(x) OBJI(T_UINT, x) 32.133 + 32.134 +/** Make an error sxpr. 32.135 + * 32.136 + * @param x value 32.137 + */ 32.138 +#define OERR(x) OBJI(T_ERR, x) 32.139 + 32.140 +/** Out of memory constant. */ 32.141 +#define ONOMEM OBJI(T_NOMEM, 0) 32.142 + 32.143 +/** The `unspecified' constant. */ 32.144 +#define ONONE OBJI(T_NONE, 0) 32.145 + 32.146 +/** Empty list constant. */ 32.147 +#define ONULL OBJI(T_NULL, 0) 32.148 + 32.149 +/** False constant. */ 32.150 +#define OFALSE OBJI(T_BOOL, 0) 32.151 + 32.152 +/** True constant. */ 32.153 +#define OTRUE OBJI(T_BOOL, 1) 32.154 + 32.155 +/* Recognizers for the various sxpr types. */ 32.156 +#define ATOMP(obj) has_type(obj, T_ATOM) 32.157 +#define BOOLP(obj) has_type(obj, T_BOOL) 32.158 +#define CONSP(obj) has_type(obj, T_CONS) 32.159 +#define ERRP(obj) has_type(obj, T_ERR) 32.160 +#define INTP(obj) has_type(obj, T_UINT) 32.161 +#define NOMEMP(obj) has_type(obj, T_NOMEM) 32.162 +#define NONEP(obj) has_type(obj, T_NONE) 32.163 +#define NULLP(obj) has_type(obj, T_NULL) 32.164 +#define STRINGP(obj) has_type(obj, T_STRING) 32.165 + 32.166 +#define TRUEP(obj) get_ul(obj) 32.167 + 32.168 +/** Convert an sxpr to an unsigned integer. */ 32.169 +#define OBJ_UINT(x) get_ul(x) 32.170 +/** Convert an sxpr to an integer. */ 32.171 +#define OBJ_INT(x) (int)get_ul(x) 32.172 + 32.173 +/* Conversions of sxprs to their values. 32.174 + * No checking is done. 32.175 + */ 32.176 +#define OBJ_STRING(x) ((char*)get_ptr(x)) 32.177 +#define OBJ_CONS(x) ((ObjCons*)get_ptr(x)) 32.178 +#define OBJ_ATOM(x) ((ObjAtom*)get_ptr(x)) 32.179 +#define OBJ_SET(x) ((ObjSet*)get_ptr(x)) 32.180 +#define CAR(x) (OBJ_CONS(x)->car) 32.181 +#define CDR(x) (OBJ_CONS(x)->cdr) 32.182 + 32.183 +#define CAAR(x) (CAR(CAR(x))) 32.184 +#define CADR(x) (CAR(CDR(x))) 32.185 +#define CDAR(x) (CDR(CAR(x))) 32.186 +#define CDDR(x) (CDR(CDR(x))) 32.187 + 32.188 +/** Get the integer value from an sxpr. 32.189 + * 32.190 + * @param obj sxpr 32.191 + * @return value 32.192 + */ 32.193 +static inline unsigned long get_ul(Sxpr obj){ 32.194 + return obj.v.ul; 32.195 +} 32.196 + 32.197 +/** Get the pointer value from an sxpr. 32.198 + * 32.199 + * @param obj sxpr 32.200 + * @return value 32.201 + */ 32.202 +static inline void * get_ptr(Sxpr obj){ 32.203 + return obj.v.ptr; 32.204 +} 32.205 + 32.206 +/** Create an sxpr containing a pointer. 32.207 + * 32.208 + * @param type typecode 32.209 + * @param val pointer 32.210 + * @return sxpr 32.211 + */ 32.212 +static inline Sxpr obj_ptr(TypeCode type, void *val){ 32.213 + return (Sxpr){ type: type, v: { ptr: val } }; 32.214 +} 32.215 + 32.216 +/** Create an sxpr containing an integer. 32.217 + * 32.218 + * @param type typecode 32.219 + * @param val integer 32.220 + * @return sxpr 32.221 + */ 32.222 +static inline Sxpr obj_ul(TypeCode type, unsigned long val){ 32.223 + return (Sxpr){ type: type, v: { ul: val } }; 32.224 +} 32.225 + 32.226 +/** Get the type of an sxpr. 32.227 + * 32.228 + * @param obj sxpr 32.229 + * @return type 32.230 + */ 32.231 +static inline TypeCode get_type(Sxpr obj){ 32.232 + return obj.type; 32.233 +} 32.234 + 32.235 +/** Check the type of an sxpr. 32.236 + * 32.237 + * @param obj sxpr 32.238 + * @param type to check 32.239 + * @return 1 if has the type, 0 otherwise 32.240 + */ 32.241 +static inline int has_type(Sxpr obj, TypeCode type){ 32.242 + return get_type(obj) == type; 32.243 +} 32.244 + 32.245 +/** Compare sxprs for literal equality of type and value. 32.246 + * 32.247 + * @param x sxpr to compare 32.248 + * @param y sxpr to compare 32.249 + * @return 1 if equal, 0 otherwise 32.250 + */ 32.251 +static inline int eq(Sxpr x, Sxpr y){ 32.252 + return ((get_type(x) == get_type(y)) && (get_ul(x) == get_ul(y))); 32.253 +} 32.254 + 32.255 +/** Checked version of CAR 32.256 + * 32.257 + * @param x sxpr 32.258 + * @return CAR if a cons, x otherwise 32.259 + */ 32.260 +static inline Sxpr car(Sxpr x){ 32.261 + return (CONSP(x) ? CAR(x) : x); 32.262 +} 32.263 + 32.264 +/** Checked version of CDR. 32.265 + * 32.266 + * @param x sxpr 32.267 + * @return CDR if a cons, null otherwise 32.268 + */ 32.269 +static inline Sxpr cdr(Sxpr x){ 32.270 + return (CONSP(x) ? CDR(x) : ONULL); 32.271 +} 32.272 + 32.273 +/** Allocate some memory and return an sxpr containing it. 32.274 + * Returns ONOMEM if allocation failed. 32.275 + * 32.276 + * @param n number of bytes to allocate 32.277 + * @param ty typecode 32.278 + * @return sxpr 32.279 + */ 32.280 +static inline Sxpr halloc(size_t n, TypeCode ty){ 32.281 + return OBJP(ty, allocate(n)); 32.282 +} 32.283 + 32.284 +/** Allocate an sxpr containing a pointer to the given type. 32.285 + * 32.286 + * @param ty type (uses sizeof to determine how many bytes to allocate) 32.287 + * @param code typecode 32.288 + * @return sxpr, ONOMEM if allocation failed 32.289 + */ 32.290 +#define HALLOC(ty, code) halloc(sizeof(ty), code) 32.291 + 32.292 +typedef int ObjPrintFn(IOStream *io, Sxpr obj, unsigned flags); 32.293 +typedef int ObjEqualFn(Sxpr obj, Sxpr other); 32.294 +typedef void ObjFreeFn(Sxpr obj); 32.295 + 32.296 +/** An sxpr type definition. */ 32.297 +typedef struct SxprType { 32.298 + TypeCode type; 32.299 + char *name; 32.300 + int pointer; 32.301 + ObjPrintFn *print; 32.302 + ObjEqualFn *equal; 32.303 + ObjFreeFn *free; 32.304 +} SxprType; 32.305 + 32.306 + 32.307 +extern SxprType *get_sxpr_type(int ty); 32.308 + 32.309 +/** Free the pointer in an sxpr. 32.310 + * 32.311 + * @param x sxpr containing a pointer 32.312 + */ 32.313 +static inline void hfree(Sxpr x){ 32.314 + deallocate(get_ptr(x)); 32.315 +} 32.316 + 32.317 +extern int objprint(IOStream *io, Sxpr x, unsigned flags); 32.318 +extern int objequal(Sxpr x, Sxpr y); 32.319 +extern void objfree(Sxpr x); 32.320 + 32.321 +extern void cons_free_cells(Sxpr obj); 32.322 +extern Sxpr intern(char *s); 32.323 + 32.324 +extern Sxpr assoc(Sxpr k, Sxpr l); 32.325 +extern Sxpr assocq(Sxpr k, Sxpr l); 32.326 +extern Sxpr acons(Sxpr k, Sxpr v, Sxpr l); 32.327 +extern Sxpr nrev(Sxpr l); 32.328 +extern Sxpr cons_member(Sxpr l, Sxpr x); 32.329 +extern Sxpr cons_member_if(Sxpr l, ObjEqualFn *test_fn, Sxpr v); 32.330 +extern int cons_subset(Sxpr s, Sxpr t); 32.331 +extern int cons_set_equal(Sxpr s, Sxpr t); 32.332 + 32.333 +#ifdef USE_GC 32.334 +extern Sxpr cons_remove(Sxpr l, Sxpr x); 32.335 +extern Sxpr cons_remove_if(Sxpr l, ObjEqualFn *test_fn, Sxpr v); 32.336 +#endif 32.337 + 32.338 +extern Sxpr atom_new(char *name); 32.339 +extern char * atom_name(Sxpr obj); 32.340 + 32.341 +extern Sxpr string_new(char *s); 32.342 +extern char * string_string(Sxpr obj); 32.343 +extern int string_length(Sxpr obj); 32.344 + 32.345 +extern Sxpr cons_new(Sxpr car, Sxpr cdr); 32.346 +extern int cons_push(Sxpr *list, Sxpr elt); 32.347 +extern int cons_length(Sxpr obj); 32.348 + 32.349 +Sxpr sxpr_name(Sxpr obj); 32.350 +int sxpr_is(Sxpr obj, char *s); 32.351 +int sxpr_elementp(Sxpr obj, Sxpr name); 32.352 +Sxpr sxpr_attributes(Sxpr obj); 32.353 +Sxpr sxpr_attribute(Sxpr obj, Sxpr key, Sxpr def); 32.354 +Sxpr sxpr_children(Sxpr obj); 32.355 +Sxpr sxpr_child(Sxpr obj, Sxpr name, Sxpr def); 32.356 +Sxpr sxpr_child0(Sxpr obj, Sxpr def); 32.357 +Sxpr sxpr_child_value(Sxpr obj, Sxpr name, Sxpr def); 32.358 + 32.359 +/** Create a new atom. 32.360 + * 32.361 + * @param s atom name 32.362 + * @return new atom 32.363 + */ 32.364 +static inline Sxpr mkatom(char *s){ 32.365 + return atom_new(s); 32.366 +} 32.367 + 32.368 +/** Create a new string sxpr. 32.369 + * 32.370 + * @param s string bytes (copied) 32.371 + * @return new string 32.372 + */ 32.373 +static inline Sxpr mkstring(char *s){ 32.374 + return string_new(s); 32.375 +} 32.376 + 32.377 +/** Create an integer sxpr. 32.378 + * 32.379 + * @param i value 32.380 + * @return sxpr 32.381 + */ 32.382 +static inline Sxpr mkint(int i){ 32.383 + return OBJI(T_UINT, i); 32.384 +} 32.385 + 32.386 +/** Create a boolean sxpr. 32.387 + * 32.388 + * @param b value 32.389 + * @return sxpr 32.390 + */ 32.391 +static inline Sxpr mkbool(int b){ 32.392 + return OBJI(T_BOOL, (b ? 1 : 0)); 32.393 +} 32.394 + 32.395 +/* Constants used in parsing and printing. */ 32.396 +#define k_list_open "(" 32.397 +#define c_list_open '(' 32.398 +#define k_list_close ")" 32.399 +#define c_list_close ')' 32.400 +#define k_true "true" 32.401 +#define k_false "false" 32.402 + 32.403 +#define c_var '$' 32.404 +#define c_escape '\\' 32.405 +#define c_single_quote '\'' 32.406 +#define c_double_quote '"' 32.407 +#define c_string_open c_double_quote 32.408 +#define c_string_close c_double_quote 32.409 +#define c_data_open '[' 32.410 +#define c_data_close ']' 32.411 +#define c_binary '*' 32.412 +#define c_eval '!' 32.413 +#define c_concat_open '{' 32.414 +#define c_concat_close '}' 32.415 + 32.416 +#endif /* ! _XEN_LIB_SXPR_H_ */
33.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 33.2 +++ b/tools/lib/sxpr_parser.c Tue Jun 29 12:05:29 2004 +0000 33.3 @@ -0,0 +1,897 @@ 33.4 + 33.5 +#ifdef __KERNEL__ 33.6 +# include <linux/config.h> 33.7 +# include <linux/module.h> 33.8 +# include <linux/kernel.h> 33.9 +# include <linux/string.h> 33.10 +# include <linux/errno.h> 33.11 +#else 33.12 +# include <stdlib.h> 33.13 +# include <errno.h> 33.14 +#endif 33.15 + 33.16 +#include "iostream.h" 33.17 +#include "lexis.h" 33.18 +#include "sxpr_parser.h" 33.19 +#include "sys_string.h" 33.20 + 33.21 +/** @file 33.22 + * Sxpr parsing. 33.23 + * 33.24 + * So that the parser does not leak memory, all sxprs constructed by 33.25 + * the parser must be freed on error. On successful parse the sxpr 33.26 + * returned becomes the responsibility of the caller. 33.27 + * 33.28 + * @author Mike Wray <mike.wray@hpl.hp.com> 33.29 + */ 33.30 + 33.31 +#define dprintf(fmt, args...) IOStream_print(iostdout, "[DEBUG] %s" fmt, __FUNCTION__, ##args) 33.32 +#define printf(fmt, args...) IOStream_print(iostdout, fmt, ##args) 33.33 + 33.34 +static void reset(Parser *z); 33.35 +static int inputchar(Parser *p, char c); 33.36 +static int savechar(Parser *p, char c); 33.37 +extern void parse_error(Parser *in); 33.38 +extern void parse_error_id(Parser *in, ParseErrorId id); 33.39 + 33.40 +static int begin_start(Parser *p, char c); 33.41 +static int state_start(Parser *p, char c); 33.42 +static int end_start(Parser *p); 33.43 + 33.44 +static int begin_comment(Parser *p, char c); 33.45 +static int state_comment(Parser *p, char c); 33.46 +static int end_comment(Parser *p); 33.47 + 33.48 +static int begin_string(Parser *p, char c); 33.49 +static int state_string(Parser *p, char c); 33.50 +static int end_string(Parser *p); 33.51 +static int state_escape(Parser *p, char c); 33.52 +static int state_octal(Parser *p, char c); 33.53 +static int state_hex(Parser *p, char c); 33.54 + 33.55 +static int begin_atom(Parser *p, char c); 33.56 +static int state_atom(Parser *p, char c); 33.57 +static int end_atom(Parser *p); 33.58 + 33.59 +static int state_list(Parser *p, char c); 33.60 +static int begin_list(Parser *p, char c); 33.61 +static int end_list(Parser *p); 33.62 + 33.63 +/** Print a parse error. 33.64 + * 33.65 + * @param in parser 33.66 + * @param msg format followed by printf arguments 33.67 + */ 33.68 +void eprintf(Parser *in, char *msg, ...){ 33.69 + va_list args; 33.70 + if(in->error_out){ 33.71 + va_start(args, msg); 33.72 + IOStream_vprint(in->error_out, msg, args); 33.73 + va_end(args); 33.74 + } 33.75 +} 33.76 + 33.77 +/** Print a parse warning. 33.78 + * 33.79 + * @param in parser 33.80 + * @param msg format followed by printf arguments 33.81 + */ 33.82 +void wprintf(Parser *in, char *msg, ...){ 33.83 + va_list args; 33.84 + if(in->error_out){ 33.85 + va_start(args, msg); 33.86 + IOStream_vprint(in->error_out, msg, args); 33.87 + va_end(args); 33.88 + } 33.89 +} 33.90 + 33.91 +/*============================================================================*/ 33.92 + 33.93 +/** Record defining the message for a parse error. */ 33.94 +typedef struct { 33.95 + ParseErrorId id; 33.96 + char *message; 33.97 +} ParseError; 33.98 + 33.99 +/** Format for printing parse error messages. */ 33.100 +#define PARSE_ERR_FMT "parse error> line %3d, column %2d: %s" 33.101 + 33.102 +/** Message catalog for the parse error codes. */ 33.103 +static ParseError catalog[] = { 33.104 + { PARSE_ERR_UNSPECIFIED, "unspecified error" }, 33.105 + { PARSE_ERR_NOMEM, "out of memory" }, 33.106 + { PARSE_ERR_UNEXPECTED_EOF, "unexpected end of input" }, 33.107 + { PARSE_ERR_TOKEN_TOO_LONG, "token too long" }, 33.108 + { PARSE_ERR_INVALID_SYNTAX, "syntax error" }, 33.109 + { PARSE_ERR_INVALID_ESCAPE, "invalid escape" }, 33.110 + { 0, NULL } 33.111 +}; 33.112 + 33.113 +/** Number of entries in the message catalog. */ 33.114 +const static int catalog_n = sizeof(catalog)/sizeof(ParseError); 33.115 + 33.116 +void ParserState_free(ParserState *z){ 33.117 + if(!z) return; 33.118 + objfree(z->val); 33.119 + deallocate(z); 33.120 +} 33.121 + 33.122 +int ParserState_new(ParserStateFn *fn, ParserState *parent, ParserState **val){ 33.123 + int err = 0; 33.124 + ParserState *z; 33.125 + z = ALLOCATE(ParserState); 33.126 + if(z){ 33.127 + z->fn = fn; 33.128 + z->parent = parent; 33.129 + z->val = ONULL; 33.130 + } else { 33.131 + err = -ENOMEM; 33.132 + } 33.133 + if(!err) *val = z; 33.134 + return err; 33.135 +} 33.136 + 33.137 +/** Free a parser. 33.138 + * No-op if the parser is null. 33.139 + * 33.140 + * @param z parser 33.141 + */ 33.142 +void Parser_free(Parser *z){ 33.143 + if(!z) return; 33.144 + objfree(z->val); 33.145 + z->val = ONONE; 33.146 + deallocate(z); 33.147 +} 33.148 + 33.149 +/** Create a new parser. The error stream defaults to null. 33.150 + */ 33.151 +Parser * Parser_new(void){ 33.152 + Parser *z = ALLOCATE(Parser); 33.153 + int err = -ENOMEM; 33.154 + 33.155 + if(!z) goto exit; 33.156 + err = 0; 33.157 + reset(z); 33.158 + exit: 33.159 + if(err){ 33.160 + Parser_free(z); 33.161 + z = NULL; 33.162 + } 33.163 + return z; 33.164 +} 33.165 + 33.166 +/** Get the next character. 33.167 + * Records the character read in the parser, 33.168 + * and sets the line and character counts. 33.169 + * 33.170 + * @param p parser 33.171 + * @return error flag: 0 on success, non-zero on error 33.172 + */ 33.173 +static int inputchar(Parser *p, char c){ 33.174 + int err = 0; 33.175 + if(c=='\n'){ 33.176 + p->line_no++; 33.177 + p->char_no = 0; 33.178 + } else { 33.179 + p->char_no++; 33.180 + } 33.181 + return err; 33.182 +} 33.183 + 33.184 +static int savechar(Parser *p, char c){ 33.185 + int err = 0; 33.186 + if(p->buf_i >= p->buf_n){ 33.187 + err = -ENOMEM; 33.188 + goto exit; 33.189 + } 33.190 + p->buf[p->buf_i] = c; 33.191 + p->buf_i++; 33.192 + exit: 33.193 + return err; 33.194 +} 33.195 + 33.196 +int Parser_input_char(Parser *p, char c){ 33.197 + int err = 0; 33.198 + if(at_eof(p)){ 33.199 + //skip; 33.200 + } else { 33.201 + inputchar(p, c); 33.202 + } 33.203 + if(!p->state){ 33.204 + err = begin_start(p, c); 33.205 + if(err) goto exit; 33.206 + } 33.207 + err = p->state->fn(p, c); 33.208 + exit: 33.209 + return err; 33.210 +} 33.211 + 33.212 +int Parser_input_eof(Parser *p){ 33.213 + int err = 0; 33.214 + p->eof = 1; 33.215 + err = Parser_input_char(p, IOSTREAM_EOF); 33.216 + return err; 33.217 +} 33.218 + 33.219 +int Parser_input(Parser *p, char *buf, int buf_n){ 33.220 + int err = 0; 33.221 + int i = 0; 33.222 + if(buf_n <= 0){ 33.223 + err = Parser_input_eof(p); 33.224 + goto exit; 33.225 + } 33.226 + for(i = 0; i<buf_n; i++){ 33.227 + err = Parser_input_char(p, buf[i]); 33.228 + if(err) goto exit; 33.229 + } 33.230 + exit: 33.231 + err = (err < 0 ? err : buf_n); 33.232 + return err; 33.233 +} 33.234 + 33.235 +int Parser_push(Parser *p, ParserStateFn *fn){ 33.236 + int err = 0; 33.237 + err = ParserState_new(fn, p->state, &p->state); 33.238 + return err; 33.239 +} 33.240 + 33.241 +int Parser_pop(Parser *p){ 33.242 + int err = 0; 33.243 + ParserState *s = p->state; 33.244 + p->state = s->parent; 33.245 + ParserState_free(s); 33.246 + return err; 33.247 +} 33.248 + 33.249 +int Parser_return(Parser *p){ 33.250 + int err = 0; 33.251 + Sxpr val = ONONE; 33.252 + if(!p->state){ 33.253 + err = -EINVAL; 33.254 + goto exit; 33.255 + } 33.256 + val = p->state->val; 33.257 + p->state->val = ONONE; 33.258 + err = Parser_pop(p); 33.259 + if(err) goto exit; 33.260 + if(p->state){ 33.261 + err = cons_push(&p->state->val, val); 33.262 + } else { 33.263 + val = nrev(val); 33.264 + p->val = val; 33.265 + } 33.266 + exit: 33.267 + if(err){ 33.268 + objfree(val); 33.269 + } 33.270 + return err; 33.271 +} 33.272 + 33.273 +/** Determine if a character is a separator. 33.274 + * 33.275 + * @param p parser 33.276 + * @param c character to test 33.277 + * @return 1 if a separator, 0 otherwise 33.278 + */ 33.279 +static int is_separator(Parser *p, char c){ 33.280 + return in_sep_class(c); 33.281 +} 33.282 + 33.283 +/** Return the current token. 33.284 + * The return value points at the internal buffer, so 33.285 + * it must not be modified (or freed). Use copy_token() if you need a copy. 33.286 + * 33.287 + * @param p parser 33.288 + * @return token 33.289 + */ 33.290 +char *peek_token(Parser *p){ 33.291 + return p->buf; 33.292 +} 33.293 + 33.294 +/** Return a copy of the current token. 33.295 + * The returned value should be freed when finished with. 33.296 + * 33.297 + * @param p parser 33.298 + * @return copy of token 33.299 + */ 33.300 +char *copy_token(Parser *p){ 33.301 + return strdup(peek_token(p)); 33.302 +} 33.303 + 33.304 +static int do_intern(Parser *p){ 33.305 + int err = 0; 33.306 + Sxpr obj = intern(peek_token(p)); 33.307 + if(NOMEMP(obj)){ 33.308 + err = -ENOMEM; 33.309 + } else { 33.310 + p->state->val = obj; 33.311 + } 33.312 + return err; 33.313 +} 33.314 + 33.315 +static int do_string(Parser *p){ 33.316 + int err = 0; 33.317 + Sxpr obj; 33.318 + obj = string_new(peek_token(p)); 33.319 + if(NOMEMP(obj)){ 33.320 + err = -ENOMEM; 33.321 + } else { 33.322 + p->state->val = obj; 33.323 + } 33.324 + return err; 33.325 +} 33.326 + 33.327 +void newtoken(Parser *p){ 33.328 + memset(p->buf, 0, p->buf_n); 33.329 + p->buf_i = 0; 33.330 + p->tok_begin_line = p->line_no; 33.331 + p->tok_begin_char = p->char_no; 33.332 +} 33.333 + 33.334 +int get_escape(char c, char *d){ 33.335 + int err = 0; 33.336 + switch(c){ 33.337 + case 'a': *d = '\a'; break; 33.338 + case 'b': *d = '\b'; break; 33.339 + case 'f': *d = '\f'; break; 33.340 + case 'n': *d = '\n'; break; 33.341 + case 'r': *d = '\r'; break; 33.342 + case 't': *d = '\t'; break; 33.343 + case 'v': *d = '\v'; break; 33.344 + case c_escape: *d = c_escape; break; 33.345 + case c_single_quote: *d = c_single_quote; break; 33.346 + case c_double_quote: *d = c_double_quote; break; 33.347 + default: 33.348 + err = -EINVAL; 33.349 + } 33.350 + return err; 33.351 +} 33.352 + 33.353 + 33.354 +int begin_start(Parser *p, char c){ 33.355 + return Parser_push(p, state_start); 33.356 +} 33.357 + 33.358 +int state_start(Parser *p, char c){ 33.359 + int err = 0; 33.360 + if(at_eof(p)){ 33.361 + err = end_start(p); 33.362 + } else if(in_space_class(c)){ 33.363 + //skip 33.364 + } else if(in_comment_class(c)){ 33.365 + begin_comment(p, c); 33.366 + } else if(c == c_list_open){ 33.367 + begin_list(p, c); 33.368 + } else if(c == c_list_close){ 33.369 + parse_error(p); 33.370 + err = -EINVAL; 33.371 + } else if(in_string_quote_class(c)){ 33.372 + begin_string(p, c); 33.373 + } else if(in_printable_class(c)){ 33.374 + begin_atom(p, c); 33.375 + } else if(c == 0x04){ 33.376 + //ctrl-D, EOT: end-of-text. 33.377 + Parser_input_eof(p); 33.378 + } else { 33.379 + parse_error(p); 33.380 + err = -EINVAL; 33.381 + } 33.382 + return err; 33.383 +} 33.384 + 33.385 +int end_start(Parser *p){ 33.386 + int err = 0; 33.387 + err = Parser_return(p); 33.388 + return err; 33.389 +} 33.390 + 33.391 +int begin_comment(Parser *p, char c){ 33.392 + int err = 0; 33.393 + err = Parser_push(p, state_comment); 33.394 + if(err) goto exit; 33.395 + err = inputchar(p, c); 33.396 + exit: 33.397 + return err; 33.398 +} 33.399 + 33.400 +int state_comment(Parser *p, char c){ 33.401 + int err = 0; 33.402 + if(c == '\n' || at_eof(p)){ 33.403 + err = end_comment(p); 33.404 + } else { 33.405 + err = inputchar(p, c); 33.406 + } 33.407 + return err; 33.408 +} 33.409 + 33.410 +int end_comment(Parser *p){ 33.411 + return Parser_pop(p); 33.412 +} 33.413 + 33.414 +int begin_string(Parser *p, char c){ 33.415 + int err = 0; 33.416 + err = Parser_push(p, state_string); 33.417 + if(err) goto exit; 33.418 + newtoken(p); 33.419 + p->state->delim = c; 33.420 + exit: 33.421 + return err; 33.422 +} 33.423 + 33.424 +int state_string(Parser *p, char c){ 33.425 + int err = 0; 33.426 + if(at_eof(p)){ 33.427 + parse_error_id(p, PARSE_ERR_UNEXPECTED_EOF); 33.428 + err = -EINVAL; 33.429 + } else if(c == p->state->delim){ 33.430 + err = end_string(p); 33.431 + } else if(c == '\\'){ 33.432 + err = Parser_push(p, state_escape); 33.433 + } else { 33.434 + err = savechar(p, c); 33.435 + } 33.436 + return err; 33.437 +} 33.438 + 33.439 +int end_string(Parser *p){ 33.440 + int err = 0; 33.441 + err = do_string(p); 33.442 + if(err) goto exit; 33.443 + err = Parser_return(p); 33.444 + exit: 33.445 + return err; 33.446 +} 33.447 + 33.448 +int state_escape(Parser *p, char c){ 33.449 + int err = 0; 33.450 + char d; 33.451 + if(at_eof(p)){ 33.452 + parse_error_id(p, PARSE_ERR_UNEXPECTED_EOF); 33.453 + err = -EINVAL; 33.454 + goto exit; 33.455 + } 33.456 + if(get_escape(c, &d) == 0){ 33.457 + err = savechar(p, d); 33.458 + if(err) goto exit; 33.459 + err = Parser_pop(p); 33.460 + } else if(c == 'x'){ 33.461 + p->state->fn = state_hex; 33.462 + p->state->ival = 0; 33.463 + p->state->count = 0; 33.464 + } else { 33.465 + p->state->fn = state_octal; 33.466 + p->state->ival = 0; 33.467 + p->state->count = 0; 33.468 + err = Parser_input_char(p, c); 33.469 + } 33.470 + exit: 33.471 + return err; 33.472 +} 33.473 + 33.474 +int octaldone(Parser *p){ 33.475 + int err = 0; 33.476 + char d = (char)(p->state->ival & 0xff); 33.477 + err = Parser_pop(p); 33.478 + if(err) goto exit; 33.479 + err = Parser_input_char(p, d); 33.480 + exit: 33.481 + return err; 33.482 +} 33.483 + 33.484 +int octaldigit(Parser *p, char c){ 33.485 + int err = 0; 33.486 + p->state->ival *= 8; 33.487 + p->state->ival += c - '0'; 33.488 + p->state->count++; 33.489 + if(err) goto exit; 33.490 + if(p->state->ival < 0 || p->state->ival > 0xff){ 33.491 + parse_error(p); 33.492 + err = -EINVAL; 33.493 + goto exit; 33.494 + } 33.495 + if(p->state->count == 3){ 33.496 + err = octaldone(p); 33.497 + } 33.498 + exit: 33.499 + return err; 33.500 +} 33.501 + 33.502 +int state_octal(Parser *p, char c){ 33.503 + int err = 0; 33.504 + if(at_eof(p)){ 33.505 + parse_error_id(p, PARSE_ERR_UNEXPECTED_EOF); 33.506 + err = -EINVAL; 33.507 + goto exit; 33.508 + } else if('0' <= c && c <= '7'){ 33.509 + err = octaldigit(p, c); 33.510 + } else { 33.511 + err = octaldone(p); 33.512 + if(err) goto exit; 33.513 + Parser_input_char(p, c); 33.514 + } 33.515 + exit: 33.516 + return err; 33.517 +} 33.518 + 33.519 +int hexdone(Parser *p){ 33.520 + int err = 0; 33.521 + char d = (char)(p->state->ival & 0xff); 33.522 + err = Parser_pop(p); 33.523 + if(err) goto exit; 33.524 + err = Parser_input_char(p, d); 33.525 + exit: 33.526 + return err; 33.527 +} 33.528 + 33.529 +int hexdigit(Parser *p, char c, char d){ 33.530 + int err = 0; 33.531 + p->state->ival *= 16; 33.532 + p->state->ival += c - d; 33.533 + p->state->count++; 33.534 + if(err) goto exit; 33.535 + if(p->state->ival < 0 || p->state->ival > 0xff){ 33.536 + parse_error(p); 33.537 + err = -EINVAL; 33.538 + goto exit; 33.539 + } 33.540 + if(p->state->count == 2){ 33.541 + err = hexdone(p); 33.542 + } 33.543 + exit: 33.544 + return err; 33.545 +} 33.546 + 33.547 +int state_hex(Parser *p, char c){ 33.548 + int err = 0; 33.549 + if(at_eof(p)){ 33.550 + parse_error_id(p, PARSE_ERR_UNEXPECTED_EOF); 33.551 + err = -EINVAL; 33.552 + goto exit; 33.553 + } else if('0' <= c && c <= '9'){ 33.554 + err = hexdigit(p, c, '0'); 33.555 + } else if('A' <= c && c <= 'F'){ 33.556 + err = hexdigit(p, c, 'A'); 33.557 + } else if('a' <= c && c <= 'f'){ 33.558 + err = hexdigit(p, c, 'a'); 33.559 + } else if(p->state->count){ 33.560 + err =hexdone(p); 33.561 + if(err) goto exit; 33.562 + Parser_input_char(p, c); 33.563 + } 33.564 + exit: 33.565 + return err; 33.566 +} 33.567 + 33.568 +int begin_atom(Parser *p, char c){ 33.569 + int err = 0; 33.570 + err = Parser_push(p, state_atom); 33.571 + if(err) goto exit; 33.572 + newtoken(p); 33.573 + err = savechar(p, c); 33.574 + exit: 33.575 + return err; 33.576 +} 33.577 + 33.578 +int state_atom(Parser *p, char c){ 33.579 + int err = 0; 33.580 + if(at_eof(p)){ 33.581 + err = end_atom(p); 33.582 + } else if(is_separator(p, c) || 33.583 + in_space_class(c) || 33.584 + in_comment_class(c)){ 33.585 + err = end_atom(p); 33.586 + if(err) goto exit; 33.587 + err = Parser_input_char(p, c); 33.588 + } else { 33.589 + err = savechar(p, c); 33.590 + } 33.591 + exit: 33.592 + return err; 33.593 +} 33.594 + 33.595 +int end_atom(Parser *p){ 33.596 + int err = 0; 33.597 + err = do_intern(p); 33.598 + if(err) goto exit; 33.599 + err = Parser_return(p); 33.600 + exit: 33.601 + return err; 33.602 +} 33.603 + 33.604 +int state_list(Parser *p, char c){ 33.605 + int err = 0; 33.606 + if(at_eof(p)){ 33.607 + parse_error_id(p, PARSE_ERR_UNEXPECTED_EOF); 33.608 + err = -EINVAL; 33.609 + } else if(c == c_list_close){ 33.610 + p->state->val = nrev(p->state->val); 33.611 + err = end_list(p); 33.612 + } else { 33.613 + err = state_start(p, c); 33.614 + } 33.615 + return err; 33.616 + 33.617 +} 33.618 + 33.619 +int begin_list(Parser *p, char c){ 33.620 + return Parser_push(p, state_list); 33.621 +} 33.622 + 33.623 +int end_list(Parser *p){ 33.624 + return Parser_return(p); 33.625 +} 33.626 + 33.627 +/** Reset the fields of a parser to initial values. 33.628 + * 33.629 + * @param z parser 33.630 + */ 33.631 +static void reset(Parser *z){ 33.632 + IOStream *error_out = z->error_out; 33.633 + int flags = z->flags; 33.634 + zero(z, sizeof(Parser)); 33.635 + z->buf_n = sizeof(z->buf) - 1; 33.636 + z->buf_i = 0; 33.637 + z->line_no = 1; 33.638 + z->char_no = 0; 33.639 + z->error_out = error_out; 33.640 + z->flags = flags; 33.641 +} 33.642 + 33.643 +/** Set the parser error stream. 33.644 + * Parse errors are reported on the the error stream if it is non-null. 33.645 + * 33.646 + * @param z parser 33.647 + * @param error_out error stream 33.648 + */ 33.649 +void set_error_stream(Parser *z, IOStream *error_out){ 33.650 + if(z){ 33.651 + z->error_out = error_out; 33.652 + } 33.653 +} 33.654 + 33.655 +/** Get the parser error message for an error code. 33.656 + * 33.657 + * @param id error code 33.658 + * @return error message (empty string if the code is unknown) 33.659 + */ 33.660 +static char *get_message(ParseErrorId id){ 33.661 + int i; 33.662 + for(i=0; i<catalog_n; i++){ 33.663 + if(id == catalog[i].id){ 33.664 + return catalog[i].message; 33.665 + } 33.666 + } 33.667 + return ""; 33.668 +} 33.669 + 33.670 +/** Get the line number. 33.671 + * 33.672 + * @param in parser 33.673 + */ 33.674 +int get_line(Parser *in){ 33.675 + return in->line_no; 33.676 +} 33.677 + 33.678 +/** Get the column number. 33.679 + * 33.680 + * @param in parser 33.681 + */ 33.682 +int get_column(Parser *in){ 33.683 + return in->char_no; 33.684 +} 33.685 + 33.686 +/** Get the line number the current token started on. 33.687 + * 33.688 + * @param in parser 33.689 + */ 33.690 +int get_tok_line(Parser *in){ 33.691 + return in->tok_begin_line; 33.692 +} 33.693 + 33.694 +/** Get the column number the current token started on. 33.695 + * 33.696 + * @param in parser 33.697 + */ 33.698 +int get_tok_column(Parser *in){ 33.699 + return in->tok_begin_char; 33.700 +} 33.701 + 33.702 +/** Report a parse error. 33.703 + * Does nothing if the error stream is null or there is no error. 33.704 + * 33.705 + * @param in parser 33.706 + */ 33.707 +static void report_error(Parser *in){ 33.708 + if(in->error_out && in->err){ 33.709 + char *msg = get_message(in->err); 33.710 + char *tok = peek_token(in); 33.711 + IOStream_print(in->error_out, PARSE_ERR_FMT, 33.712 + get_tok_line(in), get_tok_column(in), msg); 33.713 + if(tok && tok[0]){ 33.714 + IOStream_print(in->error_out, " '%s'", tok); 33.715 + } 33.716 + IOStream_print(in->error_out, "\n"); 33.717 + } 33.718 +} 33.719 + 33.720 +/** Get the error message for the current parse error code. 33.721 + * Does nothing if there is no error. 33.722 + * 33.723 + * @param in parser 33.724 + * @param buf where to place the message 33.725 + * @param n maximum number of characters to place in buf 33.726 + * @return current error code (zero for no error) 33.727 + */ 33.728 +int parse_error_message(Parser *in, char *buf, int n){ 33.729 + if(in->err){ 33.730 + char *msg = get_message(in->err); 33.731 + snprintf(buf, n, PARSE_ERR_FMT, get_tok_line(in), get_tok_column(in), msg); 33.732 + } 33.733 + return in->err; 33.734 +} 33.735 + 33.736 +/** Flag an unspecified parse error. All subsequent reads will fail. 33.737 + * 33.738 + * @param in parser 33.739 + */ 33.740 +void parse_error(Parser *in){ 33.741 + parse_error_id(in, PARSE_ERR_INVALID_SYNTAX); 33.742 +} 33.743 + 33.744 +/** Flag a parse error. All subsequent reads will fail. 33.745 + * Does not change the parser error code if it is already set. 33.746 + * 33.747 + * @param in parser 33.748 + * @param id error code 33.749 + */ 33.750 +void parse_error_id(Parser *in, ParseErrorId id){ 33.751 + if(!in->err){ 33.752 + in->err = id; 33.753 + report_error(in); 33.754 + } 33.755 +} 33.756 + 33.757 +/** Test if the parser's error flag is set. 33.758 + * 33.759 + * @param in parser 33.760 + * @return 1 if set, 0 otherwise 33.761 + */ 33.762 +int has_error(Parser *in){ 33.763 + return (in->err > 0); 33.764 +} 33.765 + 33.766 +/** Test if the parser is at end of input. 33.767 + * 33.768 + * @param in parser 33.769 + * @return 1 if at EOF, 0 otherwise 33.770 + */ 33.771 +int at_eof(Parser *p){ 33.772 + return p->eof; 33.773 +} 33.774 + 33.775 +#ifdef SXPR_PARSER_MAIN 33.776 +/* Stuff for standalone testing. */ 33.777 + 33.778 +#include "file_stream.h" 33.779 +#include "string_stream.h" 33.780 + 33.781 +int stringof(Sxpr exp, char **s){ 33.782 + int err = 0; 33.783 + if(ATOMP(exp)){ 33.784 + *s = atom_name(exp); 33.785 + } else if(STRINGP(exp)){ 33.786 + *s = string_string(exp); 33.787 + } else { 33.788 + err = -EINVAL; 33.789 + *s = NULL; 33.790 + } 33.791 + return err; 33.792 +} 33.793 + 33.794 +int child_string(Sxpr exp, Sxpr key, char **s){ 33.795 + int err = 0; 33.796 + Sxpr val = sxpr_child_value(exp, key, ONONE); 33.797 + err = stringof(val, s); 33.798 + return err; 33.799 +} 33.800 + 33.801 +int intof(Sxpr exp, int *v){ 33.802 + int err = 0; 33.803 + char *s; 33.804 + unsigned long l; 33.805 + if(INTP(exp)){ 33.806 + *v = OBJ_INT(exp); 33.807 + } else { 33.808 + err = stringof(exp, &s); 33.809 + if(err) goto exit; 33.810 + err = convert_atoul(s, &l); 33.811 + *v = (int)l; 33.812 + } 33.813 + exit: 33.814 + return err; 33.815 +} 33.816 + 33.817 +int child_int(Sxpr exp, Sxpr key, int *v){ 33.818 + int err = 0; 33.819 + Sxpr val = sxpr_child_value(exp, key, ONONE); 33.820 + err = intof(val, v); 33.821 + return err; 33.822 +} 33.823 + 33.824 +int eval_vnet(Sxpr exp){ 33.825 + int err = 0; 33.826 + Sxpr oid = intern("id"); 33.827 + int id; 33.828 + err = child_int(exp, oid, &id); 33.829 + if(err) goto exit; 33.830 + dprintf("> vnet id=%d\n", id); 33.831 + exit: 33.832 + dprintf("< err=%d\n", err); 33.833 + return err; 33.834 +} 33.835 + 33.836 +int eval_connect(Sxpr exp){ 33.837 + int err = 0; 33.838 + Sxpr ovif = intern("vif"); 33.839 + Sxpr ovnet = intern("vnet"); 33.840 + char *vif; 33.841 + int vnet; 33.842 + 33.843 + err = child_string(exp, ovif, &vif); 33.844 + if(err) goto exit; 33.845 + err = child_int(exp, ovnet, &vnet); 33.846 + if(err) goto exit; 33.847 + dprintf("> connect vif=%s vnet=%d\n", vif, vnet); 33.848 + exit: 33.849 + dprintf("< err=%d\n", err); 33.850 + return err; 33.851 +} 33.852 + 33.853 +int eval(Sxpr exp){ 33.854 + int err = 0; 33.855 + Sxpr oconnect = intern("connect"); 33.856 + Sxpr ovnet = intern("vnet"); 33.857 + 33.858 + if(sxpr_elementp(exp, ovnet)){ 33.859 + err = eval_vnet(exp); 33.860 + } else if(sxpr_elementp(exp, oconnect)){ 33.861 + err = eval_connect(exp); 33.862 + } else { 33.863 + err = -EINVAL; 33.864 + } 33.865 + return err; 33.866 +} 33.867 + 33.868 +/** Main program for testing. 33.869 + * Parses input and prints it. 33.870 + * 33.871 + * @param argc number of arguments 33.872 + * @param argv arguments 33.873 + * @return error code 33.874 + */ 33.875 +int main(int argc, char *argv[]){ 33.876 + Parser *pin; 33.877 + int err = 0; 33.878 + char buf[1024]; 33.879 + int k; 33.880 + Sxpr obj, l, x; 33.881 + 33.882 + pin = Parser_new(); 33.883 + set_error_stream(pin, iostdout); 33.884 + dprintf("> parse...\n"); 33.885 + while(1){ 33.886 + k = fread(buf, 1, 1024, stdin); 33.887 + err = Parser_input(pin, buf, k); 33.888 + dprintf("> Parser_input=%d\n", err); 33.889 + if(k <= 0) break; 33.890 + } 33.891 + obj = pin->val; 33.892 + for(l = obj ; CONSP(l); l = CDR(l)){ 33.893 + x = CAR(l); 33.894 + objprint(iostdout, x, 0); printf("\n"); 33.895 + eval(x); 33.896 + } 33.897 + dprintf("> err=%d\n", err); 33.898 + return 0; 33.899 +} 33.900 +#endif
34.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 34.2 +++ b/tools/lib/sxpr_parser.h Tue Jun 29 12:05:29 2004 +0000 34.3 @@ -0,0 +1,125 @@ 34.4 +/* 34.5 + * 34.6 + * This library is free software; you can redistribute it and/or modify 34.7 + * it under the terms of the GNU Lesser General Public License as 34.8 + * published by the Free Software Foundation; either version 2.1 of the 34.9 + * License, or (at your option) any later version. This library is 34.10 + * distributed in the hope that it will be useful, but WITHOUT ANY 34.11 + * WARRANTY; without even the implied warranty of MERCHANTABILITY or 34.12 + * FITNESS FOR A PARTICULAR PURPOSE. 34.13 + * See the GNU Lesser General Public License for more details. 34.14 + * 34.15 + * You should have received a copy of the GNU Lesser General Public License 34.16 + * along with this library; if not, write to the Free Software Foundation, 34.17 + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 34.18 + */ 34.19 + 34.20 +#ifndef _XEN_LIB_SXPR_PARSER_H_ 34.21 +#define _XEN_LIB_SXPR_PARSER_H_ 34.22 + 34.23 +#include "sxpr.h" 34.24 +#include "iostream.h" 34.25 + 34.26 +/** @file 34.27 + * Sxpr parsing definitions. 34.28 + */ 34.29 + 34.30 +/** Size of a parser input buffer. 34.31 + * Tokens read must fit into this size (including trailing null). 34.32 + */ 34.33 +#define PARSER_BUF_SIZE 1024 34.34 + 34.35 +struct Parser; 34.36 +typedef int ParserStateFn(struct Parser *, char c); 34.37 + 34.38 +typedef struct ParserState { 34.39 + struct ParserState *parent; 34.40 + Sxpr val; 34.41 + int ival; 34.42 + int count; 34.43 + char delim; 34.44 + ParserStateFn *fn; 34.45 +} ParserState; 34.46 + 34.47 +/** Structure representing an input source for the parser. 34.48 + * Can read from any IOStream implementation. 34.49 + */ 34.50 +typedef struct Parser { 34.51 + Sxpr val; 34.52 + /** Error reporting stream (null for no reports). */ 34.53 + IOStream *error_out; 34.54 + int eof; 34.55 + /** Error flag. Non-zero if there has been a read error. */ 34.56 + int err; 34.57 + /** Line number on input (from 1). */ 34.58 + int line_no; 34.59 + /** Column number of input (reset on new line). */ 34.60 + int char_no; 34.61 + /** Lookahead character. */ 34.62 + char c; 34.63 + /** Buffer for reading tokens. */ 34.64 + char buf[PARSER_BUF_SIZE]; 34.65 + /** Size of token buffer. */ 34.66 + int buf_n; 34.67 + int buf_i; 34.68 + /** Line the last token started on. */ 34.69 + int tok_begin_line; 34.70 + /** Character number the last token started on. */ 34.71 + int tok_begin_char; 34.72 + /** Parsing flags. */ 34.73 + int flags; 34.74 + ParserState *state; 34.75 +} Parser; 34.76 + 34.77 +/** Parser error codes. */ 34.78 +typedef enum { 34.79 + PARSE_ERR_NONE=0, 34.80 + PARSE_ERR_UNSPECIFIED, 34.81 + PARSE_ERR_NOMEM, 34.82 + PARSE_ERR_UNEXPECTED_EOF, 34.83 + PARSE_ERR_TOKEN_TOO_LONG, 34.84 + PARSE_ERR_INVALID_SYNTAX, 34.85 + PARSE_ERR_INVALID_ESCAPE, 34.86 +} ParseErrorId; 34.87 + 34.88 + 34.89 +/** Parser flags. */ 34.90 +//enum { 34.91 +//}; 34.92 + 34.93 +/** Raise some parser flags. 34.94 + * 34.95 + * @param in parser 34.96 + * @param flags flags mask 34.97 + */ 34.98 +inline static void parser_flags_raise(Parser *in, int flags){ 34.99 + in->flags |= flags; 34.100 +} 34.101 + 34.102 +/** Lower some parser flags. 34.103 + * 34.104 + * @param in parser 34.105 + * @param flags flags mask 34.106 + */ 34.107 +inline static void parser_flags_lower(Parser *in, int flags){ 34.108 + in->flags &= ~flags; 34.109 +} 34.110 + 34.111 +/** Clear all parser flags. 34.112 + * 34.113 + * @param in parser 34.114 + */ 34.115 +inline static void parser_flags_clear(Parser *in){ 34.116 + in->flags = 0; 34.117 +} 34.118 + 34.119 +extern void Parser_free(Parser *z); 34.120 +extern Parser * Parser_new(void); 34.121 +extern int Parser_input(Parser *p, char *buf, int buf_n); 34.122 +extern int Parser_input_eof(Parser *p); 34.123 + 34.124 +extern int parse_error_message(Parser *in, char *buf, int n); 34.125 +extern int has_error(Parser *in); 34.126 +extern int at_eof(Parser *in); 34.127 + 34.128 +#endif /* ! _XEN_LIB_SXPR_PARSER_H_ */
35.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 35.2 +++ b/tools/lib/sys_ctype.h Tue Jun 29 12:05:29 2004 +0000 35.3 @@ -0,0 +1,12 @@ 35.4 +#ifndef _XENO_SYS_CTYPE_H_ 35.5 +#define _XENO_SYS_CTYPE_H_ 35.6 +/** @file 35.7 + ** Replacement for ctype include that can be used 35.8 + * from user or kernel code. 35.9 + */ 35.10 +#ifdef __KERNEL__ 35.11 +# include <linux/ctype.h> 35.12 +#else 35.13 +# include <ctype.h> 35.14 +#endif 35.15 +#endif /* ! _XENO_SYS_CTYPE_H_ */
36.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 36.2 +++ b/tools/lib/sys_net.c Tue Jun 29 12:05:29 2004 +0000 36.3 @@ -0,0 +1,309 @@ 36.4 +/* 36.5 + * Copyright (C) 2001 - 2004 Mike Wray <mike.wray@hp.com> 36.6 + * 36.7 + * This library is free software; you can redistribute it and/or modify 36.8 + * it under the terms of the GNU Lesser General Public License as 36.9 + * published by the Free Software Foundation; either version 2.1 of the 36.10 + * License, or (at your option) any later version. This library is 36.11 + * distributed in the hope that it will be useful, but WITHOUT ANY 36.12 + * WARRANTY; without even the implied warranty of MERCHANTABILITY or 36.13 + * FITNESS FOR A PARTICULAR PURPOSE. 36.14 + * See the GNU Lesser General Public License for more details. 36.15 + * 36.16 + * You should have received a copy of the GNU Lesser General Public License 36.17 + * along with this library; if not, write to the Free Software Foundation, 36.18 + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 36.19 + */ 36.20 + 36.21 +#include "sys_net.h" 36.22 +#include "sys_string.h" 36.23 + 36.24 +/** @file 36.25 + * All network data are kept in network order and only converted to 36.26 + * host order for display. Network data includes IP addresses, port numbers and 36.27 + * network masks. 36.28 + */ 36.29 + 36.30 +/** Maximum value for a port. */ 36.31 +#define PORT_MAX 0xffff 36.32 + 36.33 +/** Convert a number of bits to a network mask 36.34 + * for IP addresses. The number of bits must 36.35 + * be in the range 1-31. 36.36 + * 36.37 + * @param n number of bits to set in the mask 36.38 + * @return value with n high bits set (in network order) 36.39 + */ 36.40 +unsigned long bits_to_mask(int n){ 36.41 + unsigned long mask = (n ? (1 << 31) : 0); 36.42 + int i; 36.43 + for(i=1; i<n; i++){ 36.44 + mask |= (mask >> 1); 36.45 + } 36.46 + return htonl(mask); 36.47 +} 36.48 + 36.49 +/** Convert a network mask to a number of bits. 36.50 + * 36.51 + * @param mask network mask in network order 36.52 + * @return number of bits in mask 36.53 + */ 36.54 +int mask_to_bits(unsigned long mask){ 36.55 + // Start with n set to the number of bits in the mask. Then reduce n by 36.56 + // the number of low zero bits in the mask. 36.57 + int n = 32; 36.58 + for(mask = ntohl(mask); 36.59 + (mask & 1)==0 && n>0; 36.60 + mask >>= 1){ 36.61 + n--; 36.62 + } 36.63 + return n; 36.64 +} 36.65 + 36.66 +/** Get the index of the first occurrence of a character in a string. 36.67 + * Stops at end of string or after n characters. 36.68 + * 36.69 + * @param s input string 36.70 + * @param n maximum number of charactes to search 36.71 + * @param c character to look for 36.72 + * @return index of first occurrence, -1 if not found 36.73 + */ 36.74 +inline static int indexof(const char *s, int n, char c){ 36.75 + int i; 36.76 + for(i=0; i<n && *s; i++, s++){ 36.77 + if(*s == c) return i; 36.78 + } 36.79 + return -1; 36.80 +} 36.81 + 36.82 +/** Convert an IPv4 address in dot notation into an unsigned long (in network order). 36.83 + * 36.84 + * @param s input string 36.85 + * @param address where to put the address 36.86 + * @return 0 on success, -1 on error 36.87 + */ 36.88 +int get_inet_addr(const char *s, unsigned long *address){ 36.89 + // Number of bits in a byte. 36.90 + const int BYTE_BITS = 8; 36.91 + // Number of bytes in a word. 36.92 + const int WORD_BYTES = 4; 36.93 + // Max value for a component of an address. 36.94 + const int ADDR_MAX = 255; 36.95 + // Separator for components of an address. 36.96 + const char dot = '.'; 36.97 + 36.98 + int n; 36.99 + unsigned long addr = 0; 36.100 + unsigned long v; 36.101 + int i; 36.102 + int err = -1; 36.103 + // Bit shift for the current byte. 36.104 + int shift = BYTE_BITS * (WORD_BYTES - 1); 36.105 + char buf[64]; 36.106 + 36.107 + n = strlen(s); 36.108 + if(n >= sizeof(buf)){ 36.109 + goto exit; 36.110 + } 36.111 + for(i=0; i < WORD_BYTES; i++){ 36.112 + int idx = indexof(s, n, dot); 36.113 + idx = (idx < 0 ? strlen(s) : idx); 36.114 + strncpy(buf, s, idx); buf[idx]='\0'; 36.115 + if(convert_atoul(buf, &v)){ 36.116 + goto exit; 36.117 + } 36.118 + if(v < 0 || v > ADDR_MAX){ 36.119 + goto exit; 36.120 + } 36.121 + addr |= (v << shift); 36.122 + if(idx == n) break; 36.123 + shift -= BYTE_BITS; 36.124 + s += idx+1; 36.125 + } 36.126 + err = 0; 36.127 + exit: 36.128 + addr = htonl(addr); 36.129 + *address = (err ? 0 : addr); 36.130 + return err; 36.131 +} 36.132 + 36.133 +#ifdef __KERNEL__ 36.134 +/** Convert an address in network order to IPv4 dot notation. 36.135 + * The return value is a static buffer which is overwritten on each call. 36.136 + * 36.137 + * @param inaddr address (in network order) 36.138 + * @return address in dot notation 36.139 + */ 36.140 +char *inet_ntoa(struct in_addr inaddr){ 36.141 + static char address[16] = {}; 36.142 + uint32_t addr = ntohl(inaddr.s_addr); 36.143 + snprintf(address, sizeof(address), "%d.%d.%d.%d", 36.144 + (unsigned)((addr >> 24) & 0xff), 36.145 + (unsigned)((addr >> 16) & 0xff), 36.146 + (unsigned)((addr >> 8) & 0xff), 36.147 + (unsigned)((addr ) & 0xff)); 36.148 + return address; 36.149 +} 36.150 + 36.151 + 36.152 +/** Convert a string in IPv4 dot notation to an int in network order. 36.153 + * 36.154 + * @param address address in dot notation 36.155 + * @param inp result of conversion (in network order) 36.156 + * @return 0 on success, error code on error 36.157 + */ 36.158 +int inet_aton(const char *address, struct in_addr *inp){ 36.159 + int err = 0; 36.160 + unsigned long addr; 36.161 + 36.162 + err = get_inet_addr(address, &addr); 36.163 + if(err) goto exit; 36.164 + inp->s_addr = addr; 36.165 + exit: 36.166 + return err; 36.167 +} 36.168 +#endif 36.169 + 36.170 +/** Convert a hostname or IPv4 address string to an address in network order. 36.171 + * 36.172 + * @param name input hostname or address string 36.173 + * @param address where to put the address 36.174 + * @return 1 if address found OK, 0 otherwise 36.175 + */ 36.176 +int get_host_address(const char *name, unsigned long *address){ 36.177 +#ifdef __KERNEL__ 36.178 + return get_inet_addr(name, address) == 0; 36.179 +#else 36.180 + struct hostent *host = gethostbyname(name); 36.181 + if(!host){ 36.182 + return 0; 36.183 + } 36.184 + *address = ((struct in_addr *)(host->h_addr))->s_addr; 36.185 + return 1; 36.186 +#endif 36.187 +} 36.188 + 36.189 +/** Convert a service name to a port (in network order). 36.190 + * 36.191 + * @param name service name 36.192 + * @param port where to put the port 36.193 + * @return 1 if service port found OK, 0 otherwise 36.194 + */ 36.195 +int get_service_port(const char *name, unsigned long *port){ 36.196 +#ifdef __KERNEL__ 36.197 + return 0; 36.198 +#else 36.199 + struct servent *service; 36.200 + service = getservbyname(name, 0); 36.201 + if(!service){ 36.202 + return 0; 36.203 + } 36.204 + *port = service->s_port; 36.205 + return 1; 36.206 +#endif 36.207 +} 36.208 + 36.209 +/** Convert a port number (in network order) to a service name. 36.210 + * 36.211 + * @param port the port number 36.212 + * @return service name if found OK, 0 otherwise 36.213 + */ 36.214 +char *get_port_service(unsigned long port){ 36.215 +#ifdef __KERNEL__ 36.216 + return 0; 36.217 +#else 36.218 + struct servent *service = getservbyport(port, 0); 36.219 + return (service ? service->s_name : 0); 36.220 +#endif 36.221 +} 36.222 + 36.223 +/** Convert a decimal integer or service name to a port (in network order). 36.224 + * 36.225 + * @param s input to convert 36.226 + * @param port where to put the port 36.227 + * @return 1 if port found OK, 0 otherwise 36.228 + */ 36.229 +int convert_service_to_port(const char *s, unsigned long *port){ 36.230 + int ok = 0; 36.231 + unsigned long value; 36.232 + if(convert_atoul(s, &value)){ 36.233 + ok = get_service_port(s, &value); 36.234 + } else { 36.235 + ok = (0 <= value) && (value <= PORT_MAX); 36.236 + value = htons((unsigned short)value); 36.237 + } 36.238 + *port = (ok ? value : 0); 36.239 + return ok; 36.240 +} 36.241 + 36.242 +#define MAC_ELEMENT_N 6 // Number of elements in a MAC address. 36.243 +#define MAC_DIGIT_N 2 // Number of digits in an element in a MAC address. 36.244 +#define MAC_LENGTH 17 //((MAC_ELEMENT_N * MAC_DIGIT_N) + MAC_ELEMENT_N - 1) 36.245 + 36.246 +/** Convert a mac address from a string of the form 36.247 + * XX:XX:XX:XX:XX:XX to numerical form (an array of 6 unsigned chars). 36.248 + * Each X denotes a hex digit: 0..9, a..f, A..F. 36.249 + * Also supports using '-' as the separator instead of ':'. 36.250 + * 36.251 + * @param mac_in string to convert 36.252 + * @param mac destination for the value 36.253 + * @return 0 on success, -1 on error 36.254 + */ 36.255 +int mac_aton(const char *mac_in, unsigned char *mac){ 36.256 + int err = 0; 36.257 + int i, j; 36.258 + const char *p; 36.259 + char sep = 0; 36.260 + unsigned char d; 36.261 + if(!mac_in || strlen(mac_in) != MAC_LENGTH){ 36.262 + err = -1; 36.263 + goto exit; 36.264 + } 36.265 + for(i = 0, p = mac_in; i < MAC_ELEMENT_N; i++){ 36.266 + d = 0; 36.267 + if(i){ 36.268 + if(!sep){ 36.269 + if(*p == ':' || *p == '-') sep = *p; 36.270 + } 36.271 + if(sep && *p == sep){ 36.272 + p++; 36.273 + } else { 36.274 + err = -1; 36.275 + goto exit; 36.276 + } 36.277 + } 36.278 + for(j = 0; j < MAC_DIGIT_N; j++, p++){ 36.279 + if(j) d <<= 4; 36.280 + if(*p >= '0' && *p <= '9'){ 36.281 + d += (*p - '0'); 36.282 + } else if(*p >= 'A' && *p <= 'F'){ 36.283 + d += (*p - 'A') + 10; 36.284 + } else if(*p >= 'a' && *p <= 'f'){ 36.285 + d += (*p - 'a') + 10; 36.286 + } else { 36.287 + err = -1; 36.288 + goto exit; 36.289 + } 36.290 + } 36.291 + mac[i] = d; 36.292 + } 36.293 + exit: 36.294 + return err; 36.295 +} 36.296 + 36.297 +/** Convert a MAC address from numerical form to a string. 36.298 + * 36.299 + * @param mac address to convert 36.300 + * @return static string value 36.301 + */ 36.302 +char *mac_ntoa(const unsigned char *mac){ 36.303 + static char buf[MAC_LENGTH + 1]; 36.304 + int buf_n = sizeof(buf); 36.305 + 36.306 + memset(buf, buf_n, 0); 36.307 + snprintf(buf, buf_n, "%02x:%02x:%02x:%02x:%02x:%02x", 36.308 + mac[0], mac[1], mac[2], 36.309 + mac[3], mac[4], mac[5]); 36.310 + buf[buf_n - 1] = '\0'; 36.311 + return buf; 36.312 +}
37.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 37.2 +++ b/tools/lib/sys_net.h Tue Jun 29 12:05:29 2004 +0000 37.3 @@ -0,0 +1,78 @@ 37.4 +/* 37.5 + * Copyright (C) 2001 - 2004 Mike Wray <mike.wray@hp.com> 37.6 + * 37.7 + * This library is free software; you can redistribute it and/or modify 37.8 + * it under the terms of the GNU Lesser General Public License as published by 37.9 + * the Free Software Foundation; either version 2.1 of the License, or 37.10 + * (at your option) any later version. 37.11 + * 37.12 + * This library is distributed in the hope that it will be useful, 37.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 37.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 37.15 + * GNU Lesser General Public License for more details. 37.16 + * 37.17 + * You should have received a copy of the GNU Lesser General Public License 37.18 + * along with this library; if not, write to the Free Software 37.19 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 37.20 + */ 37.21 + 37.22 +#ifndef _XEN_LIB_SYS_NET_H_ 37.23 +#define _XEN_LIB_SYS_NET_H_ 37.24 +/** @file 37.25 + * 37.26 + * Replacement for standard network includes. 37.27 + * Works in user or kernel code. 37.28 + */ 37.29 + 37.30 +extern int get_inet_addr(const char *s, unsigned long *address); 37.31 +extern unsigned long bits_to_mask(int n); 37.32 +extern int mask_to_bits(unsigned long mask); 37.33 +extern int get_host_address(const char *name, unsigned long *address); 37.34 +extern int get_service_port(const char *name, unsigned long *port); 37.35 +extern char *get_port_service(unsigned long port); 37.36 +extern int convert_service_to_port(const char *s, unsigned long *port); 37.37 + 37.38 +#ifdef __KERNEL__ 37.39 +#include <linux/kernel.h> 37.40 +#include <linux/types.h> 37.41 +#include <linux/errno.h> 37.42 +#include <linux/slab.h> 37.43 +#include <asm/byteorder.h> 37.44 + 37.45 +#ifndef htonl 37.46 +#define htonl(x) __constant_htonl(x) 37.47 +#endif 37.48 + 37.49 +#ifndef ntohl 37.50 +#define ntohl(x) __constant_ntohl(x) 37.51 +#endif 37.52 + 37.53 +#ifndef htons 37.54 +#define htons(x) __constant_htons(x) 37.55 +#endif 37.56 + 37.57 +#ifndef ntohs 37.58 +#define ntohs(x) __constant_ntohs(x) 37.59 +#endif 37.60 + 37.61 +#include <linux/in.h> 37.62 +extern char *inet_ntoa(struct in_addr inaddr); 37.63 +extern int inet_aton(const char *address, struct in_addr *inp); 37.64 + 37.65 +#else 37.66 + 37.67 +#include <limits.h> 37.68 +#include <sys/socket.h> 37.69 +#include <netinet/in.h> 37.70 +#include <netdb.h> 37.71 +#include <arpa/inet.h> 37.72 + 37.73 +#endif 37.74 + 37.75 +extern char *mac_ntoa(const unsigned char *macaddr); 37.76 +extern int mac_aton(const char *addr, unsigned char *macaddr); 37.77 + 37.78 +#endif /* !_SP_SYS_NET_H_ */ 37.79 + 37.80 + 37.81 +
38.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 38.2 +++ b/tools/lib/sys_string.c Tue Jun 29 12:05:29 2004 +0000 38.3 @@ -0,0 +1,138 @@ 38.4 +/* 38.5 + * Copyright (C) 2001 - 2004 Mike Wray <mike.wray@hp.com> 38.6 + * 38.7 + * This library is free software; you can redistribute it and/or modify 38.8 + * it under the terms of the GNU Lesser General Public License as published by 38.9 + * the Free Software Foundation; either version 2.1 of the License, or 38.10 + * (at your option) any later version. 38.11 + * 38.12 + * This library is distributed in the hope that it will be useful, 38.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 38.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 38.15 + * GNU Lesser General Public License for more details. 38.16 + * 38.17 + * You should have received a copy of the GNU Lesser General Public License 38.18 + * along with this library; if not, write to the Free Software 38.19 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 38.20 + */ 38.21 + 38.22 +#ifdef __KERNEL__ 38.23 +# include <linux/config.h> 38.24 +# include <linux/module.h> 38.25 +# include <linux/kernel.h> 38.26 +# include <linux/errno.h> 38.27 +#else 38.28 +# include <errno.h> 38.29 +#endif 38.30 + 38.31 +#include "allocate.h" 38.32 +#include "sys_string.h" 38.33 + 38.34 +/** Set the base to use for converting a string to a number. Base is 38.35 + * hex if starts with 0x, otherwise decimal. 38.36 + * 38.37 + * @param s input string 38.38 + * @param base where to put the base 38.39 + * @return rest of s to parse as a number 38.40 + */ 38.41 +inline static const char * convert_set_base(const char *s, int *base){ 38.42 + *base = 10; 38.43 + if(s){ 38.44 + if(*s=='0'){ 38.45 + s++; 38.46 + if(*s=='x' || *s=='X'){ 38.47 + *base = 16; 38.48 + s++; 38.49 + } 38.50 + } 38.51 + } 38.52 + return s; 38.53 +} 38.54 + 38.55 +/** Get the numerical value of a digit in the given base. 38.56 + * 38.57 + * @param c digit character 38.58 + * @param base to use 38.59 + * @return numerical value of digit in range 0..base-1 or 38.60 + * -1 if not in range for the base 38.61 + */ 38.62 +inline static int convert_get_digit(char c, int base){ 38.63 + int d; 38.64 + 38.65 + if('0'<=c && c<='9'){ 38.66 + d = c - '0'; 38.67 + } else if('a'<=c && c<='f'){ 38.68 + d = c - 'a' + 10; 38.69 + } else if('A'<=c && c<='F'){ 38.70 + d = c - 'A' + 10; 38.71 + } else { 38.72 + d = -1; 38.73 + } 38.74 + return (d < base ? d : -1); 38.75 +} 38.76 + 38.77 +/** Convert a string to an unsigned long by parsing it as a number. 38.78 + * Will accept hex or decimal in usual C syntax. 38.79 + * 38.80 + * @param str input string 38.81 + * @param val where to put the result 38.82 + * @return 0 if converted OK, negative otherwise 38.83 + */ 38.84 +int convert_atoul(const char *str, unsigned long *val){ 38.85 + int err = 0; 38.86 + unsigned long v = 0; 38.87 + int base; 38.88 + const char *s = str; 38.89 + 38.90 + if(!s) { 38.91 + err = -EINVAL; 38.92 + goto exit; 38.93 + } 38.94 + s = convert_set_base(s, &base); 38.95 + for( ; !err && *s; s++){ 38.96 + int digit = convert_get_digit(*s, base); 38.97 + if(digit<0){ 38.98 + err = -EINVAL; 38.99 + goto exit; 38.100 + } 38.101 + v *= base; 38.102 + v += digit; 38.103 + } 38.104 + exit: 38.105 + *val = (err ? 0 : v); 38.106 + return err; 38.107 +} 38.108 + 38.109 +/** Combine a directory path with a relative path to produce 38.110 + * a new path. 38.111 + * 38.112 + * @param s directory path 38.113 + * @param t relative path 38.114 + * @return new combined path s/t 38.115 + */ 38.116 +int path_concat(char *s, char *t, char **val){ 38.117 + int err = 0; 38.118 + int sn, tn, vn; 38.119 + char *v; 38.120 + sn = strlen(s); 38.121 + if(sn > 0 && s[sn-1] == '/'){ 38.122 + sn--; 38.123 + } 38.124 + tn = strlen(t); 38.125 + if(tn > 0 && t[0] == '/'){ 38.126 + tn--; 38.127 + } 38.128 + vn = sn+tn+1; 38.129 + v = (char*)allocate(vn+1); 38.130 + if(!v){ 38.131 + err = -ENOMEM; 38.132 + goto exit; 38.133 + } 38.134 + strncpy(v, s, sn); 38.135 + v[sn] = '/'; 38.136 + strncpy(v+sn+1, t, tn); 38.137 + v[vn] = '\0'; 38.138 + exit: 38.139 + *val = (err ? NULL : v); 38.140 + return err; 38.141 +}
39.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 39.2 +++ b/tools/lib/sys_string.h Tue Jun 29 12:05:29 2004 +0000 39.3 @@ -0,0 +1,91 @@ 39.4 +/* 39.5 + * Copyright (C) 2001 - 2004 Mike Wray <mike.wray@hp.com> 39.6 + * 39.7 + * This library is free software; you can redistribute it and/or modify 39.8 + * it under the terms of the GNU Lesser General Public License as published by 39.9 + * the Free Software Foundation; either version 2.1 of the License, or 39.10 + * (at your option) any later version. 39.11 + * 39.12 + * This library is distributed in the hope that it will be useful, 39.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 39.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 39.15 + * GNU Lesser General Public License for more details. 39.16 + * 39.17 + * You should have received a copy of the GNU Lesser General Public License 39.18 + * along with this library; if not, write to the Free Software 39.19 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 39.20 + */ 39.21 + 39.22 +#ifndef _XEN_LIB_SYS_STRING_H_ 39.23 +#define _XEN_LIB_SYS_STRING_H_ 39.24 +/** @file 39.25 + * Replacement for standard string includes. 39.26 + * Works in user or kernel code. 39.27 + */ 39.28 +/*============================================================================*/ 39.29 +#ifdef __KERNEL__ 39.30 + 39.31 +#include <linux/config.h> 39.32 +#include <linux/kernel.h> 39.33 +#include <linux/string.h> 39.34 +#include <linux/types.h> 39.35 +#include <stdarg.h> 39.36 +#include "allocate.h" 39.37 + 39.38 +#if 0 39.39 +static inline int tolower(int c){ 39.40 + return (c>='A' && c<='Z' ? (c-'A')+'a' : c); 39.41 +} 39.42 +#endif 39.43 + 39.44 +static inline int isalpha(int c){ 39.45 + return (c>='A' && c<='Z') || (c>='a' && c<='z'); 39.46 +} 39.47 + 39.48 +static inline int isdigit(int c){ 39.49 + return (c>='0' && c<='9'); 39.50 +} 39.51 + 39.52 +#if 0 39.53 +static inline int strcasecmp(const char *s1, const char *s2){ 39.54 + int c1, c2; 39.55 + 39.56 + do { 39.57 + c1 = tolower(*s1++); 39.58 + c2 = tolower(*s2++); 39.59 + } while (c1 && c1 == c2); 39.60 + return c1 - c2; 39.61 +} 39.62 +#endif 39.63 + 39.64 +static inline char * strdup(const char *s){ 39.65 + int n = (s ? 1+strlen(s) : 0); 39.66 + char *copy = (n ? allocate(n) : NULL); 39.67 + if(copy){ 39.68 + strcpy(copy, s); 39.69 + } 39.70 + return copy; 39.71 +} 39.72 + 39.73 +/*============================================================================*/ 39.74 +#else 39.75 +#include <string.h> 39.76 +#include <stdio.h> 39.77 + 39.78 +#ifndef _GNU_SOURCE 39.79 +static inline size_t strnlen(const char *s, size_t n){ 39.80 + int k = 0; 39.81 + if(s){ 39.82 + for(k=0; *s && k<n; s++, k++){} 39.83 + } 39.84 + return k; 39.85 +} 39.86 +#endif 39.87 + 39.88 +#endif 39.89 +/*============================================================================*/ 39.90 + 39.91 +extern int convert_atoul(const char *s, unsigned long *v); 39.92 +extern int path_concat(char *s, char *t, char **val); 39.93 + 39.94 +#endif /* !_XEN_LIB_SYS_STRING_H_ */
40.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 40.2 +++ b/tools/lib/xdr.c Tue Jun 29 12:05:29 2004 +0000 40.3 @@ -0,0 +1,246 @@ 40.4 +/* $Id: xdr.c,v 1.3 2003/09/29 13:40:00 mjw Exp $ */ 40.5 +#include "xdr.h" 40.6 +#include <errno.h> 40.7 +/** @file 40.8 + * XDR packer/unpacker for elements. 40.9 + * 40.10 + * string -> [T_STRING] [len:u32] <len bytes> 40.11 + * atom -> [T_ATOM] [len:u32] <len bytes> 40.12 + * uint -> [T_UINT] [value] 40.13 + * cons -> [T_CONS] <car> <cdr> 40.14 + * null -> [T_NULL] 40.15 + * none -> [T_NONE] 40.16 + * bool -> [T_BOOL] { 0:u8 | 1:u8 } 40.17 + * 40.18 + * types packed as u16. 40.19 + * 40.20 + * So (a b c) -> [T_CONS] a [T_CONS] b [T_CONS] c [T_NULL] 40.21 + * () -> [T_NULL] 40.22 + */ 40.23 + 40.24 +int pack_bool(IOStream *io, int x){ 40.25 + int err=0; 40.26 + err = IOStream_print(io, "%c", 0xff & x); 40.27 + if(err > 0) err = 0; 40.28 + return err; 40.29 +} 40.30 + 40.31 +int unpack_bool(IOStream *io, int *x){ 40.32 + int err = 0; 40.33 + int c; 40.34 + c = IOStream_getc(io); 40.35 + *x = (c < 0 ? 0 : c); 40.36 + err = IOStream_error(io); 40.37 + if(c < 0 && !err) err = -EIO; 40.38 + return err; 40.39 +} 40.40 + 40.41 +int pack_ushort(IOStream *io, unsigned short x){ 40.42 + int err=0; 40.43 + err = IOStream_print(io, "%c%c", 40.44 + 0xff & (x >> 8), 40.45 + 0xff & (x )); 40.46 + if(err > 0) err = 0; 40.47 + return err; 40.48 +} 40.49 + 40.50 +int unpack_ushort(IOStream *io, unsigned short *x){ 40.51 + int err = 0; 40.52 + int i, c = 0; 40.53 + *x = 0; 40.54 + for(i = 0; i< 2; i++){ 40.55 + c = IOStream_getc(io); 40.56 + if(c < 0) break; 40.57 + *x <<= 8; 40.58 + *x |= (0xff & c); 40.59 + } 40.60 + err = IOStream_error(io); 40.61 + if(c < 0 && !err) err = -EIO; 40.62 + return err; 40.63 +} 40.64 + 40.65 +int pack_uint(IOStream *io, unsigned int x){ 40.66 + int err=0; 40.67 + err = IOStream_print(io, "%c%c%c%c", 40.68 + 0xff & (x >> 24), 40.69 + 0xff & (x >> 16), 40.70 + 0xff & (x >> 8), 40.71 + 0xff & (x )); 40.72 + if(err > 0) err = 0; 40.73 + return err; 40.74 +} 40.75 + 40.76 +int unpack_uint(IOStream *io, unsigned int *x){ 40.77 + int err = 0; 40.78 + int i, c = 0; 40.79 + *x = 0; 40.80 + for(i = 0; i< 4; i++){ 40.81 + c = IOStream_getc(io); 40.82 + if(c < 0) break; 40.83 + *x <<= 8; 40.84 + *x |= (0xff & c); 40.85 + } 40.86 + err = IOStream_error(io); 40.87 + if(c < 0 && !err) err = -EIO; 40.88 + return err; 40.89 +} 40.90 + 40.91 +int pack_string(IOStream *io, Sxpr x){ 40.92 + int err = 0; 40.93 + int n = string_length(x); 40.94 + char *s = string_string(x); 40.95 + int i; 40.96 + err = pack_uint(io, n); 40.97 + if(err) goto exit; 40.98 + for(i = 0; i < n; i++){ 40.99 + err = IOStream_print(io, "%c", s[i]); 40.100 + if(err < 0) break; 40.101 + } 40.102 + if(err > 0) err = 0; 40.103 + exit: 40.104 + return err; 40.105 +} 40.106 + 40.107 +int unpack_string(IOStream *io, Sxpr *x){ 40.108 + int err; 40.109 + unsigned int n; 40.110 + int i, c = 0; 40.111 + char *s; 40.112 + Sxpr val = ONONE; 40.113 + 40.114 + err = unpack_uint(io, &n); 40.115 + if(err) goto exit; 40.116 + val = halloc(n+1, T_STRING); 40.117 + if(NOMEMP(val)){ 40.118 + err = -ENOMEM; 40.119 + goto exit; 40.120 + } 40.121 + s = string_string(val); 40.122 + for(i=0; i<n; i++){ 40.123 + c = IOStream_getc(io); 40.124 + if(c < 0) break; 40.125 + s[i] = (char)c; 40.126 + } 40.127 + s[n] = '\0'; 40.128 + exit: 40.129 + err = IOStream_error(io); 40.130 + if(c < 0 && !err) err = -EIO; 40.131 + if(err){ 40.132 + objfree(val); 40.133 + val = ONONE; 40.134 + } 40.135 + *x = val; 40.136 + return err; 40.137 +} 40.138 + 40.139 +int pack_cons(IOStream *io, Sxpr x){ 40.140 + int err = 0; 40.141 + err = pack_sxpr(io, CAR(x)); 40.142 + if(err) goto exit; 40.143 + err = pack_sxpr(io, CDR(x)); 40.144 + exit: 40.145 + return err; 40.146 +} 40.147 + 40.148 +int unpack_cons(IOStream *io, Sxpr *x){ 40.149 + int err = 0; 40.150 + Sxpr u = ONONE, v = ONONE, val = ONONE; 40.151 + err = unpack_sxpr(io, &u); 40.152 + if(err) goto exit; 40.153 + err = unpack_sxpr(io, &v); 40.154 + if(err) goto exit; 40.155 + val = cons_new(u, v); 40.156 + if(NOMEMP(val)){ 40.157 + err = -ENOMEM; 40.158 + } 40.159 + exit: 40.160 + if(err){ 40.161 + objfree(u); 40.162 + objfree(v); 40.163 + val = ONONE; 40.164 + } 40.165 + *x = val; 40.166 + return err; 40.167 +} 40.168 + 40.169 +int pack_sxpr(IOStream *io, Sxpr x){ 40.170 + int err = 0; 40.171 + unsigned short type = get_type(x); 40.172 + err = pack_ushort(io, type); 40.173 + if(err) goto exit; 40.174 + switch(type){ 40.175 + case T_NULL: 40.176 + break; 40.177 + case T_NONE: 40.178 + break; 40.179 + break; 40.180 + case T_BOOL: 40.181 + err = pack_bool(io, get_ul(x)); 40.182 + break; 40.183 + case T_CONS: 40.184 + err = pack_cons(io, x); 40.185 + break; 40.186 + case T_ATOM: 40.187 + err = pack_string(io, OBJ_ATOM(x)->name); 40.188 + break; 40.189 + case T_STRING: 40.190 + err = pack_string(io, x); 40.191 + break; 40.192 + case T_UINT: 40.193 + err = pack_uint(io, get_ul(x)); 40.194 + break; 40.195 + default: 40.196 + err = -EINVAL; 40.197 + IOStream_print(iostderr, "%s> invalid type %d\n", __FUNCTION__, type); 40.198 + break; 40.199 + } 40.200 + exit: 40.201 + return err; 40.202 +} 40.203 + 40.204 +int unpack_sxpr(IOStream *io, Sxpr *x){ 40.205 + int err = 0; 40.206 + unsigned short type; 40.207 + unsigned int u; 40.208 + Sxpr val = ONONE, y; 40.209 + 40.210 + err = unpack_ushort(io, &type); 40.211 + if(err) goto exit; 40.212 + switch(type){ 40.213 + case T_NULL: 40.214 + val = ONULL; 40.215 + break; 40.216 + case T_NONE: 40.217 + val = ONONE; 40.218 + break; 40.219 + case T_CONS: 40.220 + err = unpack_cons(io, &val); 40.221 + break; 40.222 + case T_BOOL: 40.223 + err = unpack_bool(io, &u); 40.224 + if(err) goto exit; 40.225 + val = (u ? OTRUE : OFALSE); 40.226 + break; 40.227 + case T_ATOM: 40.228 + err = unpack_string(io, &y); 40.229 + if(err) goto exit; 40.230 + val = intern(string_string(y)); 40.231 + objfree(y); 40.232 + break; 40.233 + case T_STRING: 40.234 + err = unpack_string(io, &val); 40.235 + break; 40.236 + case T_UINT: 40.237 + err = unpack_uint(io, &u); 40.238 + if(err) goto exit; 40.239 + val = OBJI(type, u); 40.240 + break; 40.241 + default: 40.242 + err = -EINVAL; 40.243 + IOStream_print(iostderr, "%s> invalid type %d\n", __FUNCTION__, type); 40.244 + break; 40.245 + } 40.246 + exit: 40.247 + *x = (err ? ONONE : val); 40.248 + return err; 40.249 +}
41.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 41.2 +++ b/tools/lib/xdr.h Tue Jun 29 12:05:29 2004 +0000 41.3 @@ -0,0 +1,14 @@ 41.4 +/* $Id: xdr.h,v 1.2 2003/09/29 13:40:00 mjw Exp $ */ 41.5 +#ifndef _SP_XDR_H_ 41.6 +#define _SP_XDR_H_ 41.7 +#include "iostream.h" 41.8 +#include "sxpr.h" 41.9 +int pack_uint(IOStream *out, unsigned int x); 41.10 +int unpack_uint(IOStream *in, unsigned int *x); 41.11 +int pack_string(IOStream *out, Sxpr x); 41.12 +int unpack_string(IOStream *in, Sxpr *x); 41.13 +int pack_cons(IOStream *out, Sxpr x); 41.14 +int unpack_cons(IOStream *in, Sxpr *x); 41.15 +int pack_sxpr(IOStream *out, Sxpr x); 41.16 +int unpack_sxpr(IOStream *in, Sxpr *x); 41.17 +#endif /* _SP_XDR_H_ */
42.1 --- a/tools/misc/Makefile Tue Jun 29 00:51:10 2004 +0000 42.2 +++ b/tools/misc/Makefile Tue Jun 29 12:05:29 2004 +0000 42.3 @@ -4,6 +4,7 @@ CFLAGS = -Wall -O3 42.4 EXTRA_INC = -I../../xen/include/hypervisor-ifs 42.5 EXTRA_INC += -I../../linux-xen-sparse/include -I../xc/lib 42.6 EXTRA_INC += -I../xu/lib 42.7 +EXTRA_INC += -I../lib 42.8 42.9 HDRS = $(wildcard *.h) 42.10 SRCS = $(wildcard *.c)
43.1 --- a/tools/xc/lib/Makefile Tue Jun 29 00:51:10 2004 +0000 43.2 +++ b/tools/xc/lib/Makefile Tue Jun 29 12:05:29 2004 +0000 43.3 @@ -4,13 +4,73 @@ MINOR = 0 43.4 SONAME = libxc.so.$(MAJOR) 43.5 43.6 CC = gcc 43.7 -CFLAGS = -c -Werror -O3 -fno-strict-aliasing 43.8 -CFLAGS += -I../../../xen/include/hypervisor-ifs 43.9 -CFLAGS += -I../../xu/lib 43.10 -CFLAGS += -I../../../linux-xen-sparse/include 43.11 + 43.12 +XEN_ROOT = ../../.. 43.13 + 43.14 +vpath %.h $(XEN_ROOT)/xen/include/hypervisor-ifs 43.15 +INCLUDES += -I $(XEN_ROOT)/xen/include/hypervisor-ifs 43.16 + 43.17 +vpath %.h $(XEN_ROOT)/tools/xu/lib 43.18 +INCLUDES += -I $(XEN_ROOT)/tools/xu/lib 43.19 + 43.20 +vpath %h $(XEN_ROOT)/linux-xen-sparse/include 43.21 +INCLUDES += -I $(XEN_ROOT)/linux-xen-sparse/include 43.22 + 43.23 +vpath %c $(XEN_ROOT)/tools/lib 43.24 +INCLUDES += -I $(XEN_ROOT)/tools/lib 43.25 43.26 -HDRS = $(wildcard *.h) 43.27 -OBJS = $(patsubst %.c,%.o,$(wildcard *.c)) 43.28 +LIB_SRCS := 43.29 +LIB_SRCS += allocate.c 43.30 +#LIB_SRCS += enum.c 43.31 +LIB_SRCS += file_stream.c 43.32 +LIB_SRCS += gzip_stream.c 43.33 +#LIB_SRCS += hash_table.c 43.34 +LIB_SRCS += iostream.c 43.35 +#LIB_SRCS += kernel_stream.c 43.36 +#LIB_SRCS += lexis.c 43.37 +#LIB_SRCS += lzi_stream.c 43.38 +#LIB_SRCS += lzo_stream.c 43.39 +#LIB_SRCS += marshal.c 43.40 +#LIB_SRCS += socket_stream.c 43.41 +#LIB_SRCS += string_stream.c 43.42 +#LIB_SRCS += sxpr.c 43.43 +#LIB_SRCS += sxpr_parser.c 43.44 +LIB_SRCS += sys_net.c 43.45 +LIB_SRCS += sys_string.c 43.46 +#LIB_SRCS += xdr.c 43.47 + 43.48 +SRCS := 43.49 +SRCS += xc_atropos.c 43.50 +SRCS += xc_bvtsched.c 43.51 +SRCS += xc_domain.c 43.52 +SRCS += xc_evtchn.c 43.53 +SRCS += xc_io.c 43.54 +SRCS += xc_linux_build.c 43.55 +SRCS += xc_linux_restore.c 43.56 +SRCS += xc_linux_save.c 43.57 +SRCS += xc_misc.c 43.58 +SRCS += xc_netbsd_build.c 43.59 +SRCS += xc_physdev.c 43.60 +SRCS += xc_private.c 43.61 +SRCS += xc_rrobin.c 43.62 + 43.63 +SRCS += $(LIB_SRCS) 43.64 + 43.65 +#CFLAGS += -I../../../xen/include/hypervisor-ifs 43.66 +#CFLAGS += -I../../xu/lib 43.67 +#CFLAGS += -I../../../linux-xen-sparse/include 43.68 + 43.69 +CFLAGS += -Wall 43.70 +CFLAGS += -Werror 43.71 +CFLAGS += -g 43.72 +CFLAGS += -O3 43.73 +CFLAGS += -fno-strict-aliasing 43.74 +CFLAGS += $(INCLUDES) 43.75 +# Get gcc to generate the dependencies for us. 43.76 +CFLAGS += -Wp,-MD,.$(@F).d 43.77 +DEPS = .*.d 43.78 + 43.79 +OBJS = $(patsubst %.c,%.o,$(SRCS)) 43.80 43.81 LIB = libxc.so libxc.so.$(MAJOR) libxc.so.$(MAJOR).$(MINOR) 43.82 43.83 @@ -32,6 +92,8 @@ install: all 43.84 43.85 clean: 43.86 $(RM) *.a *.so *.o *.rpm $(LIB) 43.87 + $(RM) *~ 43.88 + $(RM) $(DEPS) 43.89 43.90 rpm: all 43.91 rm -rf staging 43.92 @@ -49,5 +111,8 @@ libxc.so.$(MAJOR): 43.93 libxc.so.$(MAJOR).$(MINOR): $(OBJS) 43.94 $(CC) -Wl,-soname -Wl,$(SONAME) -shared -o $@ $^ -lz 43.95 43.96 -%.o: %.c $(HDRS) Makefile 43.97 - $(CC) $(CFLAGS) -o $@ $< 43.98 +%.o: %.c Makefile 43.99 + 43.100 +# $(CC) $(CFLAGS) -o $@ $< 43.101 + 43.102 +-include $(DEPS)
44.1 --- a/tools/xc/lib/xc.h Tue Jun 29 00:51:10 2004 +0000 44.2 +++ b/tools/xc/lib/xc.h Tue Jun 29 12:05:29 2004 +0000 44.3 @@ -75,18 +75,9 @@ int xc_shadow_control(int xc_handle, 44.4 #define XCFLAGS_LIVE 2 44.5 #define XCFLAGS_DEBUG 4 44.6 44.7 -int xc_linux_save(int xc_handle, 44.8 - u32 domid, 44.9 - unsigned int flags, 44.10 - int (*writerfn)(void *, const void *, size_t), 44.11 - void *writerst); 44.12 - 44.13 -int xc_linux_restore(int xc_handle, 44.14 - u32 domid, 44.15 - unsigned int flags, 44.16 - int (*readerfn)(void *, void *, size_t), 44.17 - void *readerst, 44.18 - u32 *pdomid); 44.19 +struct XcIOContext; 44.20 +int xc_linux_save(int xc_handle, struct XcIOContext *ioctxt); 44.21 +int xc_linux_restore(int xc_handle, struct XcIOContext *ioctxt); 44.22 44.23 int xc_linux_build(int xc_handle, 44.24 u32 domid,
45.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 45.2 +++ b/tools/xc/lib/xc_io.c Tue Jun 29 12:05:29 2004 +0000 45.3 @@ -0,0 +1,27 @@ 45.4 +#include "xc_io.h" 45.5 + 45.6 +void xcio_error(XcIOContext *ctxt, const char *msg, ...){ 45.7 + va_list args; 45.8 + 45.9 + va_start(args, msg); 45.10 + IOStream_vprint(ctxt->info, msg, args); 45.11 + va_end(args); 45.12 +} 45.13 + 45.14 +void xcio_info(XcIOContext *ctxt, const char *msg, ...){ 45.15 + va_list args; 45.16 + 45.17 + if(!(ctxt->flags & XCFLAGS_VERBOSE)) return; 45.18 + va_start(args, msg); 45.19 + IOStream_vprint(ctxt->info, msg, args); 45.20 + va_end(args); 45.21 +} 45.22 + 45.23 +void xcio_debug(XcIOContext *ctxt, const char *msg, ...){ 45.24 + va_list args; 45.25 + 45.26 + if(!(ctxt->flags & XCFLAGS_DEBUG)) return; 45.27 + va_start(args, msg); 45.28 + IOStream_vprint(ctxt->info, msg, args); 45.29 + va_end(args); 45.30 +}
46.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 46.2 +++ b/tools/xc/lib/xc_io.h Tue Jun 29 12:05:29 2004 +0000 46.3 @@ -0,0 +1,44 @@ 46.4 +#ifndef __XC_XC_IO_H__ 46.5 +#define __XC_XC_IO_H__ 46.6 + 46.7 +#include "xc_private.h" 46.8 +#include "iostream.h" 46.9 + 46.10 +typedef struct XcIOContext { 46.11 + u32 domain; 46.12 + unsigned flags; 46.13 + IOStream *io; 46.14 + IOStream *info; 46.15 + IOStream *err; 46.16 + char *vmconfig; 46.17 + int vmconfig_n; 46.18 +} XcIOContext; 46.19 + 46.20 +static inline int xcio_read(XcIOContext *ctxt, void *buf, int n){ 46.21 + int rc; 46.22 + 46.23 + rc = IOStream_read(ctxt->io, buf, n); 46.24 + return (rc == n ? 0 : rc); 46.25 +} 46.26 + 46.27 +static inline int xcio_write(XcIOContext *ctxt, void *buf, int n){ 46.28 + int rc; 46.29 + 46.30 + rc = IOStream_write(ctxt->io, buf, n); 46.31 + return (rc == n ? 0 : rc); 46.32 +} 46.33 + 46.34 +static inline int xcio_flush(XcIOContext *ctxt){ 46.35 + return IOStream_flush(ctxt->io); 46.36 +} 46.37 + 46.38 +extern void xcio_error(XcIOContext *ctxt, const char *msg, ...); 46.39 +extern void xcio_info(XcIOContext *ctxt, const char *msg, ...); 46.40 + 46.41 +#define xcio_perror(_ctxt, _msg...) \ 46.42 +xcio_error(_ctxt, "(errno %d %s)" _msg, errno, strerror(errno), ## _msg) 46.43 + 46.44 +#endif /* ! __XC_XC_IO_H__ */ 46.45 + 46.46 + 46.47 +
47.1 --- a/tools/xc/lib/xc_linux_restore.c Tue Jun 29 00:51:10 2004 +0000 47.2 +++ b/tools/xc/lib/xc_linux_restore.c Tue Jun 29 12:05:29 2004 +0000 47.3 @@ -8,7 +8,6 @@ 47.4 47.5 #include "xc_private.h" 47.6 #include <asm-xen/suspend.h> 47.7 -#include <zlib.h> 47.8 47.9 #define MAX_BATCH_SIZE 1024 47.10 47.11 @@ -21,14 +20,6 @@ 47.12 #endif 47.13 47.14 47.15 -/* This may allow us to create a 'quiet' command-line option, if necessary. */ 47.16 -#define verbose_printf(_f, _a...) \ 47.17 - do { \ 47.18 - if ( !verbose ) break; \ 47.19 - printf( _f , ## _a ); \ 47.20 - fflush(stdout); \ 47.21 - } while ( 0 ) 47.22 - 47.23 static int get_pfn_list(int xc_handle, 47.24 u32 domain_id, 47.25 unsigned long *pfn_buf, 47.26 @@ -54,19 +45,44 @@ static int get_pfn_list(int xc_handle, 47.27 return (ret < 0) ? -1 : op.u.getmemlist.num_pfns; 47.28 } 47.29 47.30 +/** Read the vmconfig string from the state input. 47.31 + * It is stored as a 4-byte count 'n' followed by n bytes. 47.32 + * The config data is stored in a new string in 'ioctxt->vmconfig', 47.33 + * and is null-terminated. The count is stored in 'ioctxt->vmconfig_n'. 47.34 + * 47.35 + * @param ioctxt i/o context 47.36 + * @return 0 on success, non-zero on error. 47.37 + */ 47.38 +static int read_vmconfig(XcIOContext *ioctxt){ 47.39 + int err = -1; 47.40 + if(xcio_read(ioctxt, &ioctxt->vmconfig_n, sizeof(ioctxt->vmconfig_n))){ 47.41 + goto exit; 47.42 + } 47.43 + ioctxt->vmconfig = malloc(ioctxt->vmconfig_n + 1); 47.44 + if(!ioctxt->vmconfig) goto exit; 47.45 + if(xcio_read(ioctxt, ioctxt->vmconfig, ioctxt->vmconfig_n)){ 47.46 + goto exit; 47.47 + } 47.48 + ioctxt->vmconfig[ioctxt->vmconfig_n] = '\0'; 47.49 + err = 0; 47.50 + exit: 47.51 + if(err){ 47.52 + if(ioctxt->vmconfig){ 47.53 + free(ioctxt->vmconfig); 47.54 + } 47.55 + ioctxt->vmconfig = NULL; 47.56 + ioctxt->vmconfig_n = 0; 47.57 + } 47.58 + return err; 47.59 +} 47.60 47.61 -int xc_linux_restore(int xc_handle, 47.62 - u32 dom, 47.63 - unsigned int flags, 47.64 - int (*readerfn)(void *, void *, size_t), 47.65 - void *readerst, 47.66 - u32 *pdomid) 47.67 +int xc_linux_restore(int xc_handle, XcIOContext *ioctxt) 47.68 { 47.69 dom0_op_t op; 47.70 - int rc = 1, i, j, n, k; 47.71 + int rc = 1, i, n, k; 47.72 unsigned long mfn, pfn, xpfn; 47.73 unsigned int prev_pc, this_pc; 47.74 - int verbose = flags & XCFLAGS_VERBOSE; 47.75 + u32 dom = ioctxt->domain; 47.76 int verify = 0; 47.77 47.78 /* Number of page frames in use by this Linux session. */ 47.79 @@ -115,8 +131,7 @@ int xc_linux_restore(int xc_handle, 47.80 /* used by debug verify code */ 47.81 unsigned long buf[PAGE_SIZE/sizeof(unsigned long)]; 47.82 47.83 - if ( mlock(&ctxt, sizeof(ctxt) ) ) 47.84 - { 47.85 + if ( mlock(&ctxt, sizeof(ctxt) ) ) { 47.86 /* needed for when we do the build dom0 op, 47.87 but might as well do early */ 47.88 PERROR("Unable to mlock ctxt"); 47.89 @@ -124,35 +139,36 @@ int xc_linux_restore(int xc_handle, 47.90 } 47.91 47.92 /* Start writing out the saved-domain record. */ 47.93 - if ( (*readerfn)(readerst, signature, 16) || 47.94 - (memcmp(signature, "LinuxGuestRecord", 16) != 0) ) 47.95 - { 47.96 - ERROR("Unrecognised state format -- no signature found"); 47.97 + if ( xcio_read(ioctxt, signature, 16) || 47.98 + (memcmp(signature, "LinuxGuestRecord", 16) != 0) ) { 47.99 + xcio_error(ioctxt, "Unrecognised state format -- no signature found"); 47.100 goto out; 47.101 } 47.102 47.103 - if ( (*readerfn)(readerst, name, sizeof(name)) || 47.104 - (*readerfn)(readerst, &nr_pfns, sizeof(unsigned long)) || 47.105 - (*readerfn)(readerst, pfn_to_mfn_frame_list, PAGE_SIZE) ) 47.106 - { 47.107 - ERROR("Error when reading from state file"); 47.108 + if ( xcio_read(ioctxt, name, sizeof(name)) || 47.109 + xcio_read(ioctxt, &nr_pfns, sizeof(unsigned long)) || 47.110 + xcio_read(ioctxt, pfn_to_mfn_frame_list, PAGE_SIZE) ) { 47.111 + xcio_error(ioctxt, "Error reading header"); 47.112 goto out; 47.113 } 47.114 47.115 - for ( i = 0; i < MAX_DOMAIN_NAME; i++ ) 47.116 - { 47.117 + if(read_vmconfig(ioctxt)){ 47.118 + xcio_error(ioctxt, "Error writing vmconfig"); 47.119 + goto out; 47.120 + } 47.121 + 47.122 + for ( i = 0; i < MAX_DOMAIN_NAME; i++ ) { 47.123 if ( name[i] == '\0' ) break; 47.124 if ( name[i] & 0x80 ) 47.125 { 47.126 - ERROR("Random characters in domain name"); 47.127 + xcio_error(ioctxt, "Random characters in domain name"); 47.128 goto out; 47.129 } 47.130 } 47.131 name[MAX_DOMAIN_NAME-1] = '\0'; 47.132 47.133 - if ( nr_pfns > 1024*1024 ) 47.134 - { 47.135 - ERROR("Invalid state file -- pfn count out of range"); 47.136 + if ( nr_pfns > 1024*1024 ) { 47.137 + xcio_error(ioctxt, "Invalid state file -- pfn count out of range"); 47.138 goto out; 47.139 } 47.140 47.141 @@ -162,22 +178,19 @@ int xc_linux_restore(int xc_handle, 47.142 region_mfn = calloc(1, 4 * MAX_BATCH_SIZE); 47.143 47.144 if ( (pfn_to_mfn_table == NULL) || (pfn_type == NULL) || 47.145 - (region_mfn == NULL) ) 47.146 - { 47.147 + (region_mfn == NULL) ) { 47.148 errno = ENOMEM; 47.149 goto out; 47.150 } 47.151 47.152 - if ( mlock(region_mfn, 4 * MAX_BATCH_SIZE ) ) 47.153 - { 47.154 - ERROR("Could not mlock region_mfn"); 47.155 + if ( mlock(region_mfn, 4 * MAX_BATCH_SIZE ) ) { 47.156 + xcio_error(ioctxt, "Could not mlock region_mfn"); 47.157 goto out; 47.158 } 47.159 47.160 /* Set the domain's name to that from the restore file */ 47.161 - if ( xc_domain_setname( xc_handle, dom, name ) ) 47.162 - { 47.163 - ERROR("Could not set domain name"); 47.164 + if ( xc_domain_setname( xc_handle, dom, name ) ) { 47.165 + xcio_error(ioctxt, "Could not set domain name"); 47.166 goto out; 47.167 } 47.168 47.169 @@ -187,7 +200,7 @@ int xc_linux_restore(int xc_handle, 47.170 if ( xc_domain_setinitialmem(xc_handle, dom, 47.171 nr_pfns * (PAGE_SIZE / 1024)) ) 47.172 { 47.173 - ERROR("Could not set domain initial memory"); 47.174 + xcio_error(ioctxt, "Could not set domain initial memory"); 47.175 goto out; 47.176 } 47.177 47.178 @@ -195,9 +208,8 @@ int xc_linux_restore(int xc_handle, 47.179 op.cmd = DOM0_GETDOMAININFO; 47.180 op.u.getdomaininfo.domain = (domid_t)dom; 47.181 op.u.getdomaininfo.ctxt = NULL; 47.182 - if ( do_dom0_op(xc_handle, &op) < 0 ) 47.183 - { 47.184 - ERROR("Could not get information on new domain"); 47.185 + if ( do_dom0_op(xc_handle, &op) < 0 ) { 47.186 + xcio_error(ioctxt, "Could not get information on new domain"); 47.187 goto out; 47.188 } 47.189 shared_info_frame = op.u.getdomaininfo.shared_info_frame; 47.190 @@ -208,19 +220,17 @@ int xc_linux_restore(int xc_handle, 47.191 47.192 47.193 /* Build the pfn-to-mfn table. We choose MFN ordering returned by Xen. */ 47.194 - if ( get_pfn_list(xc_handle, dom, pfn_to_mfn_table, nr_pfns) != nr_pfns ) 47.195 - { 47.196 - ERROR("Did not read correct number of frame numbers for new dom"); 47.197 + if ( get_pfn_list(xc_handle, dom, pfn_to_mfn_table, nr_pfns) != nr_pfns ) { 47.198 + xcio_error(ioctxt, "Did not read correct number of frame numbers for new dom"); 47.199 goto out; 47.200 } 47.201 47.202 - if ( (mmu = init_mmu_updates(xc_handle, dom)) == NULL ) 47.203 - { 47.204 - ERROR("Could not initialise for MMU updates"); 47.205 + if ( (mmu = init_mmu_updates(xc_handle, dom)) == NULL ) { 47.206 + xcio_error(ioctxt, "Could not initialise for MMU updates"); 47.207 goto out; 47.208 } 47.209 47.210 - verbose_printf("Reloading memory pages: 0%%"); 47.211 + xcio_info(ioctxt, "Reloading memory pages: 0%%"); 47.212 47.213 /* 47.214 * Now simply read each saved frame into its new machine frame. 47.215 @@ -229,56 +239,45 @@ int xc_linux_restore(int xc_handle, 47.216 prev_pc = 0; 47.217 47.218 n=0; 47.219 - while(1) 47.220 - { 47.221 + while(1) { 47.222 int j; 47.223 unsigned long region_pfn_type[MAX_BATCH_SIZE]; 47.224 47.225 this_pc = (n * 100) / nr_pfns; 47.226 - if ( (this_pc - prev_pc) >= 5 ) 47.227 - { 47.228 - verbose_printf("\b\b\b\b%3d%%", this_pc); 47.229 + if ( (this_pc - prev_pc) >= 5 ) { 47.230 + xcio_info(ioctxt, "\b\b\b\b%3d%%", this_pc); 47.231 prev_pc = this_pc; 47.232 } 47.233 47.234 - if ( (*readerfn)(readerst, &j, sizeof(int)) ) 47.235 - { 47.236 - ERROR("Error when reading from state file"); 47.237 + if ( xcio_read(ioctxt, &j, sizeof(int)) ) { 47.238 + xcio_error(ioctxt, "Error when reading from state file"); 47.239 goto out; 47.240 } 47.241 47.242 DPRINTF("batch %d\n",j); 47.243 47.244 - if ( j == -1 ) 47.245 - { 47.246 + if ( j == -1 ) { 47.247 verify = 1; 47.248 printf("Entering page verify mode\n"); 47.249 continue; 47.250 } 47.251 47.252 - if ( j == 0 ) 47.253 - break; /* our work here is done */ 47.254 + if ( j == 0 ) break; /* our work here is done */ 47.255 47.256 - if( j > MAX_BATCH_SIZE ) 47.257 - { 47.258 - ERROR("Max batch size exceeded. Giving up."); 47.259 + if( j > MAX_BATCH_SIZE ) { 47.260 + xcio_error(ioctxt, "Max batch size exceeded. Giving up."); 47.261 goto out; 47.262 } 47.263 47.264 - if ( (*readerfn)(readerst, region_pfn_type, j*sizeof(unsigned long)) ) 47.265 - { 47.266 - ERROR("Error when reading from state file"); 47.267 + if ( xcio_read(ioctxt, region_pfn_type, j*sizeof(unsigned long)) ) { 47.268 + xcio_error(ioctxt, "Error when reading from state file"); 47.269 goto out; 47.270 } 47.271 47.272 - for(i=0;i<j;i++) 47.273 - { 47.274 - if ( (region_pfn_type[i] & LTAB_MASK) == XTAB) 47.275 - { 47.276 + for(i=0; i<j; i++) { 47.277 + if ( (region_pfn_type[i] & LTAB_MASK) == XTAB) { 47.278 region_mfn[i] = 0; /* we know map will fail, but don't care */ 47.279 - } 47.280 - else 47.281 - { 47.282 + } else { 47.283 pfn = region_pfn_type[i] & ~LTAB_MASK; 47.284 region_mfn[i] = pfn_to_mfn_table[pfn]; 47.285 } 47.286 @@ -287,24 +286,20 @@ int xc_linux_restore(int xc_handle, 47.287 if ( (region_base = mfn_mapper_map_batch( xc_handle, dom, 47.288 PROT_WRITE, 47.289 region_mfn, 47.290 - j )) == 0) 47.291 - { 47.292 - PERROR("map batch failed"); 47.293 + j )) == 0) { 47.294 + xcio_error(ioctxt, "map batch failed"); 47.295 goto out; 47.296 } 47.297 47.298 - for(i=0;i<j;i++) 47.299 - { 47.300 + for(i=0;i<j;i++) { 47.301 unsigned long *ppage; 47.302 47.303 pfn = region_pfn_type[i] & ~LTAB_MASK; 47.304 47.305 - if ( (region_pfn_type[i] & LTAB_MASK) == XTAB) 47.306 - continue; 47.307 + if ( (region_pfn_type[i] & LTAB_MASK) == XTAB) continue; 47.308 47.309 - if (pfn>nr_pfns) 47.310 - { 47.311 - ERROR("pfn out of range"); 47.312 + if (pfn>nr_pfns) { 47.313 + xcio_error(ioctxt, "pfn out of range"); 47.314 goto out; 47.315 } 47.316 47.317 @@ -314,36 +309,32 @@ int xc_linux_restore(int xc_handle, 47.318 47.319 mfn = pfn_to_mfn_table[pfn]; 47.320 47.321 - if ( verify ) 47.322 + if ( verify ) { 47.323 ppage = (unsigned long*) buf; /* debug case */ 47.324 - else 47.325 + } else { 47.326 ppage = (unsigned long*) (region_base + i*PAGE_SIZE); 47.327 + } 47.328 47.329 - if ( (*readerfn)(readerst, ppage, PAGE_SIZE) ) 47.330 - { 47.331 - ERROR("Error when reading from state file"); 47.332 + if ( xcio_read(ioctxt, ppage, PAGE_SIZE) ) { 47.333 + xcio_error(ioctxt, "Error when reading from state file"); 47.334 goto out; 47.335 } 47.336 47.337 - switch( region_pfn_type[i] ) 47.338 - { 47.339 + switch( region_pfn_type[i] ) { 47.340 case 0: 47.341 break; 47.342 47.343 case L1TAB: 47.344 { 47.345 - for ( k = 0; k < 1024; k++ ) 47.346 - { 47.347 - if ( ppage[k] & _PAGE_PRESENT ) 47.348 - { 47.349 + for ( k = 0; k < 1024; k++ ) { 47.350 + if ( ppage[k] & _PAGE_PRESENT ) { 47.351 xpfn = ppage[k] >> PAGE_SHIFT; 47.352 47.353 - if ( xpfn >= nr_pfns ) 47.354 - { 47.355 - ERROR("Frame number in type %d page table is " 47.356 - "out of range. i=%d k=%d pfn=0x%x " 47.357 - "nr_pfns=%d", region_pfn_type[i]>>28, i, 47.358 - k, xpfn,nr_pfns); 47.359 + if ( xpfn >= nr_pfns ) { 47.360 + xcio_error(ioctxt, "Frame number in type %lu page table is " 47.361 + "out of range. i=%d k=%d pfn=0x%lx " 47.362 + "nr_pfns=%lu", region_pfn_type[i]>>28, i, 47.363 + k, xpfn, nr_pfns); 47.364 goto out; 47.365 } 47.366 47.367 @@ -359,16 +350,13 @@ int xc_linux_restore(int xc_handle, 47.368 { 47.369 for ( k = 0; 47.370 k < (HYPERVISOR_VIRT_START>>L2_PAGETABLE_SHIFT); 47.371 - k++ ) 47.372 - { 47.373 - if ( ppage[k] & _PAGE_PRESENT ) 47.374 - { 47.375 + k++ ) { 47.376 + if ( ppage[k] & _PAGE_PRESENT ) { 47.377 xpfn = ppage[k] >> PAGE_SHIFT; 47.378 47.379 - if ( xpfn >= nr_pfns ) 47.380 - { 47.381 - ERROR("Frame number in type %d page table is " 47.382 - "out of range. i=%d k=%d pfn=%d nr_pfns=%d", 47.383 + if ( xpfn >= nr_pfns ) { 47.384 + xcio_error(ioctxt, "Frame number in type %lu page table is " 47.385 + "out of range. i=%d k=%d pfn=%lu nr_pfns=%lu", 47.386 region_pfn_type[i]>>28, i, k, xpfn, nr_pfns); 47.387 47.388 goto out; 47.389 @@ -383,24 +371,21 @@ int xc_linux_restore(int xc_handle, 47.390 break; 47.391 47.392 default: 47.393 - ERROR("Bogus page type %x page table is out of range." 47.394 - " i=%d nr_pfns=%d", region_pfn_type[i], i, nr_pfns); 47.395 + xcio_error(ioctxt, "Bogus page type %lx page table is out of range." 47.396 + " i=%d nr_pfns=%lu", region_pfn_type[i], i, nr_pfns); 47.397 goto out; 47.398 47.399 } /* end of page type switch statement */ 47.400 47.401 - if ( verify ) 47.402 - { 47.403 + if ( verify ) { 47.404 int res = memcmp(buf, (region_base + i*PAGE_SIZE), PAGE_SIZE ); 47.405 - if (res) 47.406 - { 47.407 + if (res) { 47.408 int v; 47.409 - printf("************** pfn=%x type=%x gotcs=%08lx " 47.410 + printf("************** pfn=%lx type=%lx gotcs=%08lx " 47.411 "actualcs=%08lx\n", pfn, pfn_type[pfn], 47.412 csum_page(region_base + i*PAGE_SIZE), 47.413 csum_page(buf)); 47.414 - for ( v = 0; v < 4; v++ ) 47.415 - { 47.416 + for ( v = 0; v < 4; v++ ) { 47.417 unsigned long *p = (unsigned long *) 47.418 (region_base + i*PAGE_SIZE); 47.419 if ( buf[v] != p[v] ) 47.420 @@ -411,8 +396,7 @@ int xc_linux_restore(int xc_handle, 47.421 } 47.422 47.423 if ( add_mmu_update(xc_handle, mmu, 47.424 - (mfn<<PAGE_SHIFT) | MMU_MACHPHYS_UPDATE, pfn) ) 47.425 - { 47.426 + (mfn<<PAGE_SHIFT) | MMU_MACHPHYS_UPDATE, pfn) ) { 47.427 printf("machpys mfn=%ld pfn=%ld\n",mfn,pfn); 47.428 goto out; 47.429 } 47.430 @@ -431,44 +415,36 @@ int xc_linux_restore(int xc_handle, 47.431 * Pin page tables. Do this after writing to them as otherwise Xen 47.432 * will barf when doing the type-checking. 47.433 */ 47.434 - for ( i = 0; i < nr_pfns; i++ ) 47.435 - { 47.436 - if ( pfn_type[i] == L1TAB ) 47.437 - { 47.438 + for ( i = 0; i < nr_pfns; i++ ) { 47.439 + if ( pfn_type[i] == L1TAB ) { 47.440 if ( add_mmu_update(xc_handle, mmu, 47.441 (pfn_to_mfn_table[i]<<PAGE_SHIFT) | 47.442 MMU_EXTENDED_COMMAND, 47.443 - MMUEXT_PIN_L1_TABLE) ) 47.444 - { 47.445 + MMUEXT_PIN_L1_TABLE) ) { 47.446 printf("ERR pin L1 pfn=%lx mfn=%lx\n", 47.447 - i, pfn_to_mfn_table[i]); 47.448 + (unsigned long)i, pfn_to_mfn_table[i]); 47.449 goto out; 47.450 } 47.451 - } 47.452 - else if ( pfn_type[i] == L2TAB ) 47.453 - { 47.454 + } else if ( pfn_type[i] == L2TAB ) { 47.455 if ( add_mmu_update(xc_handle, mmu, 47.456 (pfn_to_mfn_table[i]<<PAGE_SHIFT) | 47.457 MMU_EXTENDED_COMMAND, 47.458 - MMUEXT_PIN_L2_TABLE) ) 47.459 - { 47.460 + MMUEXT_PIN_L2_TABLE) ) { 47.461 printf("ERR pin L2 pfn=%lx mfn=%lx\n", 47.462 - i, pfn_to_mfn_table[i]); 47.463 + (unsigned long)i, pfn_to_mfn_table[i]); 47.464 goto out; 47.465 } 47.466 } 47.467 } 47.468 47.469 - if ( finish_mmu_updates(xc_handle, mmu) ) 47.470 - goto out; 47.471 + if ( finish_mmu_updates(xc_handle, mmu) ) goto out; 47.472 47.473 - verbose_printf("\b\b\b\b100%%\nMemory reloaded.\n"); 47.474 + xcio_info(ioctxt, "\b\b\b\b100%%\nMemory reloaded.\n"); 47.475 47.476 47.477 - if ( (*readerfn)(readerst, &ctxt, sizeof(ctxt)) || 47.478 - (*readerfn)(readerst, shared_info, PAGE_SIZE) ) 47.479 - { 47.480 - ERROR("Error when reading from state file"); 47.481 + if ( xcio_read(ioctxt, &ctxt, sizeof(ctxt)) || 47.482 + xcio_read(ioctxt, shared_info, PAGE_SIZE) ) { 47.483 + xcio_error(ioctxt, "Error when reading from state file"); 47.484 goto out; 47.485 } 47.486 47.487 @@ -476,7 +452,7 @@ int xc_linux_restore(int xc_handle, 47.488 pfn = ctxt.cpu_ctxt.esi; 47.489 if ( (pfn >= nr_pfns) || (pfn_type[pfn] != NOTAB) ) 47.490 { 47.491 - ERROR("Suspend record frame number is bad"); 47.492 + xcio_error(ioctxt, "Suspend record frame number is bad"); 47.493 goto out; 47.494 } 47.495 ctxt.cpu_ctxt.esi = mfn = pfn_to_mfn_table[pfn]; 47.496 @@ -487,17 +463,14 @@ int xc_linux_restore(int xc_handle, 47.497 unmap_pfn(pm_handle, p_srec); 47.498 47.499 /* Uncanonicalise each GDT frame number. */ 47.500 - if ( ctxt.gdt_ents > 8192 ) 47.501 - { 47.502 - ERROR("GDT entry count out of range"); 47.503 + if ( ctxt.gdt_ents > 8192 ) { 47.504 + xcio_error(ioctxt, "GDT entry count out of range"); 47.505 goto out; 47.506 } 47.507 - for ( i = 0; i < ctxt.gdt_ents; i += 512 ) 47.508 - { 47.509 + for ( i = 0; i < ctxt.gdt_ents; i += 512 ) { 47.510 pfn = ctxt.gdt_frames[i]; 47.511 - if ( (pfn >= nr_pfns) || (pfn_type[pfn] != NOTAB) ) 47.512 - { 47.513 - ERROR("GDT frame number is bad"); 47.514 + if ( (pfn >= nr_pfns) || (pfn_type[pfn] != NOTAB) ) { 47.515 + xcio_error(ioctxt, "GDT frame number is bad"); 47.516 goto out; 47.517 } 47.518 ctxt.gdt_frames[i] = pfn_to_mfn_table[pfn]; 47.519 @@ -505,11 +478,10 @@ int xc_linux_restore(int xc_handle, 47.520 47.521 /* Uncanonicalise the page table base pointer. */ 47.522 pfn = ctxt.pt_base >> PAGE_SHIFT; 47.523 - if ( (pfn >= nr_pfns) || (pfn_type[pfn] != L2TAB) ) 47.524 - { 47.525 - printf("PT base is bad. pfn=%d nr=%d type=%08lx %08lx\n", 47.526 - pfn, nr_pfns, pfn_type[pfn], L2TAB); 47.527 - ERROR("PT base is bad."); 47.528 + if ( (pfn >= nr_pfns) || (pfn_type[pfn] != L2TAB) ) { 47.529 + printf("PT base is bad. pfn=%lu nr=%lu type=%08lx %08lx\n", 47.530 + pfn, nr_pfns, pfn_type[pfn], (unsigned long)L2TAB); 47.531 + xcio_error(ioctxt, "PT base is bad."); 47.532 goto out; 47.533 } 47.534 ctxt.pt_base = pfn_to_mfn_table[pfn] << PAGE_SHIFT; 47.535 @@ -527,14 +499,12 @@ int xc_linux_restore(int xc_handle, 47.536 47.537 47.538 /* Uncanonicalise the pfn-to-mfn table frame-number list. */ 47.539 - for ( i = 0; i < (nr_pfns+1023)/1024; i++ ) 47.540 - { 47.541 + for ( i = 0; i < (nr_pfns+1023)/1024; i++ ) { 47.542 unsigned long pfn, mfn; 47.543 47.544 pfn = pfn_to_mfn_frame_list[i]; 47.545 - if ( (pfn >= nr_pfns) || (pfn_type[pfn] != NOTAB) ) 47.546 - { 47.547 - ERROR("PFN-to-MFN frame number is bad"); 47.548 + if ( (pfn >= nr_pfns) || (pfn_type[pfn] != NOTAB) ) { 47.549 + xcio_error(ioctxt, "PFN-to-MFN frame number is bad"); 47.550 goto out; 47.551 } 47.552 mfn = pfn_to_mfn_table[pfn]; 47.553 @@ -545,9 +515,8 @@ int xc_linux_restore(int xc_handle, 47.554 mfn_mapper_map_batch(xc_handle, dom, 47.555 PROT_WRITE, 47.556 pfn_to_mfn_frame_list, 47.557 - (nr_pfns+1023)/1024 )) == 0 ) 47.558 - { 47.559 - ERROR("Couldn't map pfn_to_mfn table"); 47.560 + (nr_pfns+1023)/1024 )) == 0 ) { 47.561 + xcio_error(ioctxt, "Couldn't map pfn_to_mfn table"); 47.562 goto out; 47.563 } 47.564 47.565 @@ -569,24 +538,26 @@ int xc_linux_restore(int xc_handle, 47.566 * 9. debugregs are checked by Xen. 47.567 * 10. callback code selectors need checking. 47.568 */ 47.569 - for ( i = 0; i < 256; i++ ) 47.570 - { 47.571 + for ( i = 0; i < 256; i++ ) { 47.572 ctxt.trap_ctxt[i].vector = i; 47.573 if ( (ctxt.trap_ctxt[i].cs & 3) == 0 ) 47.574 ctxt.trap_ctxt[i].cs = FLAT_GUESTOS_CS; 47.575 } 47.576 - if ( (ctxt.guestos_ss & 3) == 0 ) 47.577 + if ( (ctxt.guestos_ss & 3) == 0 ){ 47.578 ctxt.guestos_ss = FLAT_GUESTOS_DS; 47.579 - if ( (ctxt.event_callback_cs & 3) == 0 ) 47.580 + } 47.581 + if ( (ctxt.event_callback_cs & 3) == 0 ){ 47.582 ctxt.event_callback_cs = FLAT_GUESTOS_CS; 47.583 - if ( (ctxt.failsafe_callback_cs & 3) == 0 ) 47.584 + } 47.585 + if ( (ctxt.failsafe_callback_cs & 3) == 0 ){ 47.586 ctxt.failsafe_callback_cs = FLAT_GUESTOS_CS; 47.587 + } 47.588 if ( ((ctxt.ldt_base & (PAGE_SIZE - 1)) != 0) || 47.589 (ctxt.ldt_ents > 8192) || 47.590 (ctxt.ldt_base > HYPERVISOR_VIRT_START) || 47.591 ((ctxt.ldt_base + ctxt.ldt_ents*8) > HYPERVISOR_VIRT_START) ) 47.592 { 47.593 - ERROR("Bad LDT base or size"); 47.594 + xcio_error(ioctxt, "Bad LDT base or size"); 47.595 goto out; 47.596 } 47.597 47.598 @@ -597,34 +568,33 @@ int xc_linux_restore(int xc_handle, 47.599 47.600 /* don't start the domain as we have console etc to set up */ 47.601 47.602 - if( rc == 0 ) 47.603 - { 47.604 + if( rc == 0 ) { 47.605 /* Success: print the domain id. */ 47.606 - verbose_printf("DOM=%u\n", dom); 47.607 + xcio_info(ioctxt, "DOM=%lu\n", dom); 47.608 return 0; 47.609 } 47.610 47.611 47.612 out: 47.613 - if ( (rc != 0) && (dom != 0) ) 47.614 + if ( (rc != 0) && (dom != 0) ){ 47.615 xc_domain_destroy(xc_handle, dom); 47.616 - 47.617 - if ( mmu != NULL ) 47.618 + } 47.619 + if ( mmu != NULL ){ 47.620 free(mmu); 47.621 - 47.622 - if ( pm_handle >= 0 ) 47.623 + } 47.624 + if ( pm_handle >= 0 ){ 47.625 (void)close_pfn_mapper(pm_handle); 47.626 + } 47.627 + if ( pfn_to_mfn_table != NULL ){ 47.628 + free(pfn_to_mfn_table); 47.629 + } 47.630 + if ( pfn_type != NULL ){ 47.631 + free(pfn_type); 47.632 + } 47.633 47.634 - if ( pfn_to_mfn_table != NULL ) 47.635 - free(pfn_to_mfn_table); 47.636 - if ( pfn_type != NULL ) 47.637 - free(pfn_type); 47.638 - 47.639 - 47.640 - if ( rc == 0 ) 47.641 - *pdomid = dom; 47.642 - 47.643 + if ( rc == 0 ){ 47.644 + ioctxt->domain = dom; 47.645 + } 47.646 DPRINTF("Restore exit with rc=%d\n",rc); 47.647 - 47.648 return rc; 47.649 }
48.1 --- a/tools/xc/lib/xc_linux_save.c Tue Jun 29 00:51:10 2004 +0000 48.2 +++ b/tools/xc/lib/xc_linux_save.c Tue Jun 29 12:05:29 2004 +0000 48.3 @@ -6,6 +6,7 @@ 48.4 * Copyright (c) 2003, K A Fraser. 48.5 */ 48.6 48.7 +#include <sys/time.h> 48.8 #include "xc_private.h" 48.9 #include <asm-xen/suspend.h> 48.10 48.11 @@ -26,14 +27,6 @@ 48.12 #define DDPRINTF(_f, _a...) ((void)0) 48.13 #endif 48.14 48.15 -/* This may allow us to create a 'quiet' command-line option, if necessary. */ 48.16 -#define verbose_printf(_f, _a...) \ 48.17 - do { \ 48.18 - if ( !verbose ) break; \ 48.19 - printf( _f , ## _a ); \ 48.20 - fflush(stdout); \ 48.21 - } while ( 0 ) 48.22 - 48.23 /* 48.24 * Returns TRUE if the given machine frame number has a unique mapping 48.25 * in the guest's pseudophysical map. 48.26 @@ -189,6 +182,20 @@ static int print_stats( int xc_handle, u 48.27 return 0; 48.28 } 48.29 48.30 +/** Write the vmconfig string. 48.31 + * It is stored as a 4-byte count 'n' followed by n bytes. 48.32 + * 48.33 + * @param ioctxt i/o context 48.34 + * @return 0 on success, non-zero on error. 48.35 + */ 48.36 +static int write_vmconfig(XcIOContext *ioctxt){ 48.37 + int err = -1; 48.38 + if(xcio_write(ioctxt, &ioctxt->vmconfig_n, sizeof(ioctxt->vmconfig_n))) goto exit; 48.39 + if(xcio_write(ioctxt, ioctxt->vmconfig, ioctxt->vmconfig_n)) goto exit; 48.40 + err = 0; 48.41 + exit: 48.42 + return err; 48.43 +} 48.44 48.45 static int analysis_phase( int xc_handle, u32 domid, 48.46 int nr_pfns, unsigned long *arr ) 48.47 @@ -225,19 +232,15 @@ static int analysis_phase( int xc_handle 48.48 return -1; 48.49 } 48.50 48.51 -int xc_linux_save(int xc_handle, 48.52 - u32 domid, 48.53 - unsigned int flags, 48.54 - int (*writerfn)(void *, const void *, size_t), 48.55 - void *writerst ) 48.56 +int xc_linux_save(int xc_handle, XcIOContext *ioctxt) 48.57 { 48.58 dom0_op_t op; 48.59 int rc = 1, i, j, k, last_iter, iter = 0; 48.60 unsigned long mfn; 48.61 - int verbose = flags & XCFLAGS_VERBOSE; 48.62 - int live = flags & XCFLAGS_LIVE; 48.63 - int debug = flags & XCFLAGS_DEBUG; 48.64 - int sent_last_iter, sent_this_iter, skip_this_iter; 48.65 + u32 domid = ioctxt->domain; 48.66 + int live = (ioctxt->flags & XCFLAGS_LIVE); 48.67 + int debug = (ioctxt->flags & XCFLAGS_DEBUG); 48.68 + int sent_last_iter, skip_this_iter; 48.69 48.70 /* Important tuning parameters */ 48.71 int max_iters = 29; /* limit us to 30 times round loop */ 48.72 @@ -272,7 +275,7 @@ int xc_linux_save(int xc_handle, 48.73 unsigned long *live_shinfo; 48.74 48.75 /* base of the region in which domain memory is mapped */ 48.76 - unsigned char *region_base; 48.77 + unsigned char *region_base = NULL; 48.78 48.79 /* A temporary mapping, and a copy, of the guest's suspend record. */ 48.80 suspend_record_t *p_srec; 48.81 @@ -294,17 +297,14 @@ int xc_linux_save(int xc_handle, 48.82 int needed_to_fix = 0; 48.83 int total_sent = 0; 48.84 48.85 - if ( mlock(&ctxt, sizeof(ctxt) ) ) 48.86 - { 48.87 - PERROR("Unable to mlock ctxt"); 48.88 + if (mlock(&ctxt, sizeof(ctxt))) { 48.89 + xcio_perror(ioctxt, "Unable to mlock ctxt"); 48.90 return 1; 48.91 } 48.92 48.93 /* Ensure that the domain exists, and that it is stopped. */ 48.94 - 48.95 - if ( xc_domain_pause( xc_handle, domid ) ) 48.96 - { 48.97 - PERROR("Could not pause domain"); 48.98 + if ( xc_domain_pause(xc_handle, domid) ){ 48.99 + xcio_perror(ioctxt, "Could not pause domain"); 48.100 goto out; 48.101 } 48.102 48.103 @@ -317,9 +317,8 @@ int xc_linux_save(int xc_handle, 48.104 shared_info_frame = op.u.getdomaininfo.shared_info_frame; 48.105 48.106 /* A cheesy test to see whether the domain contains valid state. */ 48.107 - if ( ctxt.pt_base == 0 ) 48.108 - { 48.109 - ERROR("Domain is not in a valid Linux guest OS state"); 48.110 + if ( ctxt.pt_base == 0 ){ 48.111 + xcio_error(ioctxt, "Domain is not in a valid Linux guest OS state"); 48.112 goto out; 48.113 } 48.114 48.115 @@ -327,20 +326,17 @@ int xc_linux_save(int xc_handle, 48.116 domid for this to succeed. */ 48.117 p_srec = mfn_mapper_map_single(xc_handle, domid, 48.118 sizeof(*p_srec), PROT_READ, 48.119 - ctxt.cpu_ctxt.esi ); 48.120 - 48.121 - if (!p_srec) 48.122 - { 48.123 - ERROR("Couldn't map state record"); 48.124 + ctxt.cpu_ctxt.esi); 48.125 + if (!p_srec){ 48.126 + xcio_error(ioctxt, "Couldn't map state record"); 48.127 goto out; 48.128 } 48.129 48.130 nr_pfns = p_srec->nr_pfns; 48.131 48.132 /* cheesy sanity check */ 48.133 - if ( nr_pfns > 1024*1024 ) 48.134 - { 48.135 - ERROR("Invalid state record -- pfn count out of range"); 48.136 + if ( nr_pfns > 1024*1024 ){ 48.137 + xcio_error(ioctxt, "Invalid state record -- pfn count out of range"); 48.138 goto out; 48.139 } 48.140 48.141 @@ -350,9 +346,8 @@ int xc_linux_save(int xc_handle, 48.142 PAGE_SIZE, PROT_READ, 48.143 p_srec->pfn_to_mfn_frame_list ); 48.144 48.145 - if (!live_pfn_to_mfn_frame_list) 48.146 - { 48.147 - ERROR("Couldn't map pfn_to_mfn_frame_list"); 48.148 + if (!live_pfn_to_mfn_frame_list){ 48.149 + xcio_error(ioctxt, "Couldn't map pfn_to_mfn_frame_list"); 48.150 goto out; 48.151 } 48.152 48.153 @@ -379,24 +374,21 @@ int xc_linux_save(int xc_handle, 48.154 (its not clear why it would want to change them, and we'll be OK 48.155 from a safety POV anyhow. */ 48.156 48.157 - live_pfn_to_mfn_table = mfn_mapper_map_batch( xc_handle, domid, 48.158 - PROT_READ, 48.159 - live_pfn_to_mfn_frame_list, 48.160 - (nr_pfns+1023)/1024 ); 48.161 - if( !live_pfn_to_mfn_table ) 48.162 - { 48.163 - PERROR("Couldn't map pfn_to_mfn table"); 48.164 + live_pfn_to_mfn_table = mfn_mapper_map_batch(xc_handle, domid, 48.165 + PROT_READ, 48.166 + live_pfn_to_mfn_frame_list, 48.167 + (nr_pfns+1023)/1024 ); 48.168 + if( !live_pfn_to_mfn_table ){ 48.169 + xcio_perror(ioctxt, "Couldn't map pfn_to_mfn table"); 48.170 goto out; 48.171 } 48.172 48.173 48.174 /* Canonicalise the pfn-to-mfn table frame-number list. */ 48.175 memcpy( pfn_to_mfn_frame_list, live_pfn_to_mfn_frame_list, PAGE_SIZE ); 48.176 - for ( i = 0; i < nr_pfns; i += 1024 ) 48.177 - { 48.178 - if ( !translate_mfn_to_pfn(&pfn_to_mfn_frame_list[i/1024]) ) 48.179 - { 48.180 - ERROR("Frame # in pfn-to-mfn frame list is not in pseudophys"); 48.181 + for ( i = 0; i < nr_pfns; i += 1024 ){ 48.182 + if ( !translate_mfn_to_pfn(&pfn_to_mfn_frame_list[i/1024]) ){ 48.183 + xcio_error(ioctxt, "Frame # in pfn-to-mfn frame list is not in pseudophys"); 48.184 goto out; 48.185 } 48.186 } 48.187 @@ -404,27 +396,24 @@ int xc_linux_save(int xc_handle, 48.188 /* At this point, we can start the domain again if we're doing a 48.189 live suspend */ 48.190 48.191 - if( live ) 48.192 - { 48.193 + if( live ){ 48.194 if ( xc_shadow_control( xc_handle, domid, 48.195 DOM0_SHADOW_CONTROL_OP_ENABLE_LOGDIRTY, 48.196 - NULL, 0, NULL ) < 0 ) 48.197 - { 48.198 - ERROR("Couldn't enable shadow mode"); 48.199 + NULL, 0, NULL ) < 0 ) { 48.200 + xcio_error(ioctxt, "Couldn't enable shadow mode"); 48.201 goto out; 48.202 } 48.203 48.204 - if ( xc_domain_unpause( xc_handle, domid ) < 0 ) 48.205 - { 48.206 - ERROR("Couldn't unpause domain"); 48.207 + if ( xc_domain_unpause(xc_handle, domid) < 0 ){ 48.208 + xcio_error(ioctxt, "Couldn't unpause domain"); 48.209 goto out; 48.210 } 48.211 48.212 last_iter = 0; 48.213 sent_last_iter = 1<<20; /* 4GB of pages */ 48.214 + } else{ 48.215 + last_iter = 1; 48.216 } 48.217 - else 48.218 - last_iter = 1; 48.219 48.220 /* calculate the power of 2 order of nr_pfns, e.g. 48.221 15->4 16->4 17->5 */ 48.222 @@ -438,25 +427,22 @@ int xc_linux_save(int xc_handle, 48.223 to_fix = calloc( 1, sz ); 48.224 to_skip = malloc( sz ); 48.225 48.226 - if (!to_send || !to_fix || !to_skip) 48.227 - { 48.228 - ERROR("Couldn't allocate to_send array"); 48.229 + if (!to_send || !to_fix || !to_skip){ 48.230 + xcio_error(ioctxt, "Couldn't allocate to_send array"); 48.231 goto out; 48.232 } 48.233 48.234 memset( to_send, 0xff, sz ); 48.235 48.236 - if ( mlock( to_send, sz ) ) 48.237 - { 48.238 - PERROR("Unable to mlock to_send"); 48.239 + if ( mlock( to_send, sz ) ){ 48.240 + xcio_perror(ioctxt, "Unable to mlock to_send"); 48.241 return 1; 48.242 } 48.243 48.244 /* (to fix is local only) */ 48.245 48.246 - if ( mlock( to_skip, sz ) ) 48.247 - { 48.248 - PERROR("Unable to mlock to_skip"); 48.249 + if ( mlock( to_skip, sz ) ){ 48.250 + xcio_perror(ioctxt, "Unable to mlock to_skip"); 48.251 return 1; 48.252 } 48.253 48.254 @@ -468,15 +454,13 @@ int xc_linux_save(int xc_handle, 48.255 pfn_type = calloc(BATCH_SIZE, sizeof(unsigned long)); 48.256 pfn_batch = calloc(BATCH_SIZE, sizeof(unsigned long)); 48.257 48.258 - if ( (pfn_type == NULL) || (pfn_batch == NULL) ) 48.259 - { 48.260 + if ( (pfn_type == NULL) || (pfn_batch == NULL) ){ 48.261 errno = ENOMEM; 48.262 goto out; 48.263 } 48.264 48.265 - if ( mlock( pfn_type, BATCH_SIZE * sizeof(unsigned long) ) ) 48.266 - { 48.267 - ERROR("Unable to mlock"); 48.268 + if ( mlock( pfn_type, BATCH_SIZE * sizeof(unsigned long) ) ){ 48.269 + xcio_error(ioctxt, "Unable to mlock"); 48.270 goto out; 48.271 } 48.272 48.273 @@ -485,8 +469,7 @@ int xc_linux_save(int xc_handle, 48.274 * Quick belt and braces sanity check. 48.275 */ 48.276 #if DEBUG 48.277 - for ( i = 0; i < nr_pfns; i++ ) 48.278 - { 48.279 + for ( i = 0; i < nr_pfns; i++ ){ 48.280 mfn = live_pfn_to_mfn_table[i]; 48.281 48.282 if( (live_mfn_to_pfn_table[mfn] != i) && (mfn != 0x80000004) ) 48.283 @@ -500,20 +483,22 @@ int xc_linux_save(int xc_handle, 48.284 PAGE_SIZE, PROT_READ, 48.285 shared_info_frame); 48.286 48.287 - if (!live_shinfo) 48.288 - { 48.289 - ERROR("Couldn't map live_shinfo"); 48.290 + if (!live_shinfo){ 48.291 + xcio_error(ioctxt, "Couldn't map live_shinfo"); 48.292 goto out; 48.293 } 48.294 48.295 /* Start writing out the saved-domain record. */ 48.296 48.297 - if ( (*writerfn)(writerst, "LinuxGuestRecord", 16) || 48.298 - (*writerfn)(writerst, name, sizeof(name)) || 48.299 - (*writerfn)(writerst, &nr_pfns, sizeof(unsigned long)) || 48.300 - (*writerfn)(writerst, pfn_to_mfn_frame_list, PAGE_SIZE) ) 48.301 - { 48.302 - ERROR("Error when writing to state file (1)"); 48.303 + if ( xcio_write(ioctxt, "LinuxGuestRecord", 16) || 48.304 + xcio_write(ioctxt, name, sizeof(name)) || 48.305 + xcio_write(ioctxt, &nr_pfns, sizeof(unsigned long)) || 48.306 + xcio_write(ioctxt, pfn_to_mfn_frame_list, PAGE_SIZE) ){ 48.307 + xcio_error(ioctxt, "Error writing header"); 48.308 + goto out; 48.309 + } 48.310 + if(write_vmconfig(ioctxt)){ 48.311 + xcio_error(ioctxt, "Error writing vmconfig"); 48.312 goto out; 48.313 } 48.314 48.315 @@ -521,8 +506,7 @@ int xc_linux_save(int xc_handle, 48.316 48.317 /* Now write out each data page, canonicalising page tables as we go... */ 48.318 48.319 - while(1) 48.320 - { 48.321 + while(1){ 48.322 unsigned int prev_pc, sent_this_iter, N, batch; 48.323 48.324 iter++; 48.325 @@ -531,15 +515,13 @@ int xc_linux_save(int xc_handle, 48.326 prev_pc = 0; 48.327 N=0; 48.328 48.329 - verbose_printf("Saving memory pages: iter %d 0%%", iter); 48.330 + xcio_info(ioctxt, "Saving memory pages: iter %d 0%%", iter); 48.331 48.332 - while( N < nr_pfns ) 48.333 - { 48.334 + while( N < nr_pfns ){ 48.335 unsigned int this_pc = (N * 100) / nr_pfns; 48.336 48.337 - if ( (this_pc - prev_pc) >= 5 ) 48.338 - { 48.339 - verbose_printf("\b\b\b\b%3d%%", this_pc); 48.340 + if ( (this_pc - prev_pc) >= 5 ){ 48.341 + xcio_info(ioctxt, "\b\b\b\b%3d%%", this_pc); 48.342 prev_pc = this_pc; 48.343 } 48.344 48.345 @@ -549,9 +531,8 @@ int xc_linux_save(int xc_handle, 48.346 if ( !last_iter && 48.347 xc_shadow_control(xc_handle, domid, 48.348 DOM0_SHADOW_CONTROL_OP_PEEK, 48.349 - to_skip, nr_pfns, NULL) != nr_pfns ) 48.350 - { 48.351 - ERROR("Error peeking shadow bitmap"); 48.352 + to_skip, nr_pfns, NULL) != nr_pfns ) { 48.353 + xcio_error(ioctxt, "Error peeking shadow bitmap"); 48.354 goto out; 48.355 } 48.356 48.357 @@ -563,23 +544,26 @@ int xc_linux_save(int xc_handle, 48.358 { 48.359 int n = permute(N, nr_pfns, order_nr ); 48.360 48.361 - if ( 0 && debug ) 48.362 + if ( 0 && debug ) { 48.363 fprintf(stderr,"%d pfn= %08lx mfn= %08lx %d " 48.364 " [mfn]= %08lx\n", 48.365 - iter, n, live_pfn_to_mfn_table[n], 48.366 + iter, (unsigned long)n, live_pfn_to_mfn_table[n], 48.367 test_bit(n,to_send), 48.368 live_mfn_to_pfn_table[live_pfn_to_mfn_table[n]& 48.369 0xFFFFF]); 48.370 + } 48.371 48.372 if ( !last_iter && 48.373 test_bit(n, to_send) && 48.374 - test_bit(n, to_skip) ) 48.375 + test_bit(n, to_skip) ) { 48.376 skip_this_iter++; /* stats keeping */ 48.377 + } 48.378 48.379 if ( !((test_bit(n, to_send) && !test_bit(n, to_skip)) || 48.380 (test_bit(n, to_send) && last_iter) || 48.381 - (test_bit(n, to_fix) && last_iter)) ) 48.382 + (test_bit(n, to_fix) && last_iter)) ) { 48.383 continue; 48.384 + } 48.385 48.386 /* we get here if: 48.387 1. page is marked to_send & hasn't already been re-dirtied 48.388 @@ -590,8 +574,7 @@ int xc_linux_save(int xc_handle, 48.389 pfn_batch[batch] = n; 48.390 pfn_type[batch] = live_pfn_to_mfn_table[n]; 48.391 48.392 - if( pfn_type[batch] == 0x80000004 ) 48.393 - { 48.394 + if( pfn_type[batch] == 0x80000004 ){ 48.395 /* not currently in pusedo-physical map -- set bit 48.396 in to_fix that we must send this page in last_iter 48.397 unless its sent sooner anyhow */ 48.398 @@ -625,22 +608,18 @@ int xc_linux_save(int xc_handle, 48.399 if ( (region_base = mfn_mapper_map_batch(xc_handle, domid, 48.400 PROT_READ, 48.401 pfn_type, 48.402 - batch)) == 0 ) 48.403 - { 48.404 - PERROR("map batch failed"); 48.405 + batch)) == 0 ){ 48.406 + xcio_perror(ioctxt, "map batch failed"); 48.407 goto out; 48.408 } 48.409 48.410 - if ( get_pfn_type_batch(xc_handle, domid, batch, pfn_type) ) 48.411 - { 48.412 - ERROR("get_pfn_type_batch failed"); 48.413 + if ( get_pfn_type_batch(xc_handle, domid, batch, pfn_type) ){ 48.414 + xcio_error(ioctxt, "get_pfn_type_batch failed"); 48.415 goto out; 48.416 } 48.417 48.418 - for ( j = 0; j < batch; j++ ) 48.419 - { 48.420 - if ( (pfn_type[j] & LTAB_MASK) == XTAB ) 48.421 - { 48.422 + for ( j = 0; j < batch; j++ ){ 48.423 + if ( (pfn_type[j] & LTAB_MASK) == XTAB ){ 48.424 DDPRINTF("type fail: page %i mfn %08lx\n",j,pfn_type[j]); 48.425 continue; 48.426 } 48.427 @@ -658,39 +637,33 @@ int xc_linux_save(int xc_handle, 48.428 pfn_type[j] = (pfn_type[j] & LTAB_MASK) | pfn_batch[j]; 48.429 } 48.430 48.431 - if ( (*writerfn)(writerst, &batch, sizeof(int) ) ) 48.432 - { 48.433 - ERROR("Error when writing to state file (2)"); 48.434 + if ( xcio_write(ioctxt, &batch, sizeof(int) ) ){ 48.435 + xcio_error(ioctxt, "Error when writing to state file (2)"); 48.436 goto out; 48.437 } 48.438 48.439 - if ( (*writerfn)(writerst, pfn_type, sizeof(unsigned long)*j ) ) 48.440 - { 48.441 - ERROR("Error when writing to state file (3)"); 48.442 + if ( xcio_write(ioctxt, pfn_type, sizeof(unsigned long)*j ) ){ 48.443 + xcio_error(ioctxt, "Error when writing to state file (3)"); 48.444 goto out; 48.445 } 48.446 48.447 /* entering this loop, pfn_type is now in pfns (Not mfns) */ 48.448 - for( j = 0; j < batch; j++ ) 48.449 - { 48.450 + for( j = 0; j < batch; j++ ){ 48.451 /* write out pages in batch */ 48.452 - if( (pfn_type[j] & LTAB_MASK) == XTAB) 48.453 - { 48.454 + if( (pfn_type[j] & LTAB_MASK) == XTAB){ 48.455 DDPRINTF("SKIP BOGUS page %i mfn %08lx\n",j,pfn_type[j]); 48.456 continue; 48.457 } 48.458 48.459 if ( ((pfn_type[j] & LTAB_MASK) == L1TAB) || 48.460 - ((pfn_type[j] & LTAB_MASK) == L2TAB) ) 48.461 - { 48.462 + ((pfn_type[j] & LTAB_MASK) == L2TAB) ){ 48.463 memcpy(page, region_base + (PAGE_SIZE*j), PAGE_SIZE); 48.464 48.465 for ( k = 0; 48.466 k < (((pfn_type[j] & LTAB_MASK) == L2TAB) ? 48.467 (HYPERVISOR_VIRT_START >> L2_PAGETABLE_SHIFT) : 48.468 1024); 48.469 - k++ ) 48.470 - { 48.471 + k++ ){ 48.472 unsigned long pfn; 48.473 48.474 if ( !(page[k] & _PAGE_PRESENT) ) 48.475 @@ -726,20 +699,16 @@ int xc_linux_save(int xc_handle, 48.476 48.477 } /* end of page table rewrite for loop */ 48.478 48.479 - if ( (*writerfn)(writerst, page, PAGE_SIZE) ) 48.480 - { 48.481 - ERROR("Error when writing to state file (4)"); 48.482 + if ( xcio_write(ioctxt, page, PAGE_SIZE) ){ 48.483 + xcio_error(ioctxt, "Error when writing to state file (4)"); 48.484 goto out; 48.485 } 48.486 48.487 - } /* end of it's a PT page */ 48.488 - else 48.489 - { /* normal page */ 48.490 + } /* end of it's a PT page */ else { /* normal page */ 48.491 48.492 - if ( (*writerfn)(writerst, region_base + (PAGE_SIZE*j), 48.493 - PAGE_SIZE) ) 48.494 - { 48.495 - ERROR("Error when writing to state file (5)"); 48.496 + if ( xcio_write(ioctxt, region_base + (PAGE_SIZE*j), 48.497 + PAGE_SIZE) ){ 48.498 + xcio_error(ioctxt, "Error when writing to state file (5)"); 48.499 goto out; 48.500 } 48.501 } 48.502 @@ -755,37 +724,34 @@ int xc_linux_save(int xc_handle, 48.503 48.504 total_sent += sent_this_iter; 48.505 48.506 - verbose_printf("\r %d: sent %d, skipped %d, ", 48.507 + xcio_info(ioctxt, "\r %d: sent %d, skipped %d, ", 48.508 iter, sent_this_iter, skip_this_iter ); 48.509 48.510 - if ( last_iter ) 48.511 - { 48.512 + if ( last_iter ) { 48.513 print_stats( xc_handle, domid, sent_this_iter, &stats, 1); 48.514 48.515 - verbose_printf("Total pages sent= %d (%.2fx)\n", 48.516 + xcio_info(ioctxt, "Total pages sent= %d (%.2fx)\n", 48.517 total_sent, ((float)total_sent)/nr_pfns ); 48.518 - verbose_printf("(of which %d were fixups)\n", needed_to_fix ); 48.519 + xcio_info(ioctxt, "(of which %d were fixups)\n", needed_to_fix ); 48.520 } 48.521 48.522 - if ( debug && last_iter ) 48.523 - { 48.524 + if (last_iter && debug){ 48.525 int minusone = -1; 48.526 memset( to_send, 0xff, (nr_pfns+8)/8 ); 48.527 debug = 0; 48.528 printf("Entering debug resend-all mode\n"); 48.529 48.530 /* send "-1" to put receiver into debug mode */ 48.531 - if ( (*writerfn)(writerst, &minusone, sizeof(int)) ) 48.532 + if ( xcio_write(ioctxt, &minusone, sizeof(int)) ) 48.533 { 48.534 - ERROR("Error when writing to state file (6)"); 48.535 + xcio_error(ioctxt, "Error when writing to state file (6)"); 48.536 goto out; 48.537 } 48.538 48.539 continue; 48.540 } 48.541 48.542 - if ( last_iter ) 48.543 - break; 48.544 + if ( last_iter ) break; 48.545 48.546 if ( live ) 48.547 { 48.548 @@ -805,7 +771,7 @@ int xc_linux_save(int xc_handle, 48.549 DOM0_SHADOW_CONTROL_OP_CLEAN2, 48.550 to_send, nr_pfns, &stats ) != nr_pfns ) 48.551 { 48.552 - ERROR("Error flushing shadow PT"); 48.553 + xcio_error(ioctxt, "Error flushing shadow PT"); 48.554 goto out; 48.555 } 48.556 48.557 @@ -824,60 +790,51 @@ int xc_linux_save(int xc_handle, 48.558 rc = 0; 48.559 48.560 /* Zero terminate */ 48.561 - if ( (*writerfn)(writerst, &rc, sizeof(int)) ) 48.562 + if ( xcio_write(ioctxt, &rc, sizeof(int)) ) 48.563 { 48.564 - ERROR("Error when writing to state file (6)"); 48.565 + xcio_error(ioctxt, "Error when writing to state file (6)"); 48.566 goto out; 48.567 } 48.568 48.569 /* Get the final execution context */ 48.570 if ( xc_domain_getfullinfo( xc_handle, domid, &op, &ctxt) ) 48.571 { 48.572 - PERROR("Could not get full domain info"); 48.573 + xcio_perror(ioctxt, "Could not get full domain info"); 48.574 goto out; 48.575 } 48.576 48.577 /* Canonicalise the suspend-record frame number. */ 48.578 - if ( !translate_mfn_to_pfn(&ctxt.cpu_ctxt.esi) ) 48.579 - { 48.580 - ERROR("State record is not in range of pseudophys map"); 48.581 + if ( !translate_mfn_to_pfn(&ctxt.cpu_ctxt.esi) ){ 48.582 + xcio_error(ioctxt, "State record is not in range of pseudophys map"); 48.583 goto out; 48.584 } 48.585 48.586 /* Canonicalise each GDT frame number. */ 48.587 - for ( i = 0; i < ctxt.gdt_ents; i += 512 ) 48.588 - { 48.589 - if ( !translate_mfn_to_pfn(&ctxt.gdt_frames[i]) ) 48.590 - { 48.591 - ERROR("GDT frame is not in range of pseudophys map"); 48.592 + for ( i = 0; i < ctxt.gdt_ents; i += 512 ) { 48.593 + if ( !translate_mfn_to_pfn(&ctxt.gdt_frames[i]) ) { 48.594 + xcio_error(ioctxt, "GDT frame is not in range of pseudophys map"); 48.595 goto out; 48.596 } 48.597 } 48.598 48.599 /* Canonicalise the page table base pointer. */ 48.600 - if ( !MFN_IS_IN_PSEUDOPHYS_MAP(ctxt.pt_base >> PAGE_SHIFT) ) 48.601 - { 48.602 - ERROR("PT base is not in range of pseudophys map"); 48.603 + if ( !MFN_IS_IN_PSEUDOPHYS_MAP(ctxt.pt_base >> PAGE_SHIFT) ) { 48.604 + xcio_error(ioctxt, "PT base is not in range of pseudophys map"); 48.605 goto out; 48.606 } 48.607 ctxt.pt_base = live_mfn_to_pfn_table[ctxt.pt_base >> PAGE_SHIFT] << 48.608 PAGE_SHIFT; 48.609 48.610 - if ( (*writerfn)(writerst, &ctxt, sizeof(ctxt)) || 48.611 - (*writerfn)(writerst, live_shinfo, PAGE_SIZE) ) 48.612 - { 48.613 - ERROR("Error when writing to state file (1)"); 48.614 + if ( xcio_write(ioctxt, &ctxt, sizeof(ctxt)) || 48.615 + xcio_write(ioctxt, live_shinfo, PAGE_SIZE) ) { 48.616 + xcio_error(ioctxt, "Error when writing to state file (1)"); 48.617 goto out; 48.618 } 48.619 munmap(live_shinfo, PAGE_SIZE); 48.620 48.621 out: 48.622 - 48.623 - if ( pfn_type != NULL ) 48.624 - free(pfn_type); 48.625 - 48.626 + if ( pfn_type != NULL ) free(pfn_type); 48.627 DPRINTF("Save exit rc=%d\n",rc); 48.628 - 48.629 return !!rc; 48.630 48.631 }
49.1 --- a/tools/xc/lib/xc_private.h Tue Jun 29 00:51:10 2004 +0000 49.2 +++ b/tools/xc/lib/xc_private.h Tue Jun 29 12:05:29 2004 +0000 49.3 @@ -136,6 +136,8 @@ int close_pfn_mapper(int pm_handle); 49.4 void *map_pfn_writeable(int pm_handle, unsigned long pfn); 49.5 void *map_pfn_readonly(int pm_handle, unsigned long pfn); 49.6 void unmap_pfn(int pm_handle, void *vaddr); 49.7 +int get_pfn_type_batch(int xc_handle, u32 dom, int num, unsigned long *arr); 49.8 +unsigned long csum_page (void * page); 49.9 49.10 /* 49.11 * MMU updates. 49.12 @@ -202,4 +204,10 @@ void * mfn_mapper_queue_entry(mfn_mapper 49.13 49.14 long long xc_domain_get_cpu_usage( int xc_handle, domid_t domid ); 49.15 49.16 +#include "xc_io.h" 49.17 + 49.18 +int xc_domain_getfullinfo(int xc_handle, 49.19 + u32 domid, 49.20 + dom0_op_t *op, 49.21 + full_execution_context_t *ctxt ); 49.22 #endif /* __XC_PRIVATE_H__ */
50.1 --- a/tools/xc/py/Xc.c Tue Jun 29 00:51:10 2004 +0000 50.2 +++ b/tools/xc/py/Xc.c Tue Jun 29 12:05:29 2004 +0000 50.3 @@ -14,6 +14,8 @@ 50.4 #include <sys/socket.h> 50.5 #include <netdb.h> 50.6 #include <arpa/inet.h> 50.7 +#include "xc_private.h" 50.8 +#include "gzip_stream.h" 50.9 50.10 /* Needed for Python versions earlier than 2.3. */ 50.11 #ifndef PyMODINIT_FUNC 50.12 @@ -189,115 +191,35 @@ static PyObject *pyxc_domain_getinfo(PyO 50.13 return list; 50.14 } 50.15 50.16 -static PyObject *tcp_save(XcObject *xc, u32 dom, char *url, unsigned flags){ 50.17 -#define max_namelen 64 50.18 - char server[max_namelen]; 50.19 - char *port_s; 50.20 - int port=777; 50.21 - int sd = -1; 50.22 - struct hostent *h; 50.23 - struct sockaddr_in s; 50.24 - int sockbufsize; 50.25 +static int file_save(XcObject *xc, XcIOContext *ctxt, char *state_file){ 50.26 int rc = -1; 50.27 - 50.28 - int writerfn(void *fd, const void *buf, size_t count) { 50.29 - int tot = 0, rc; 50.30 - do { 50.31 - rc = write( (int) fd, ((char*)buf)+tot, count-tot ); 50.32 - if ( rc < 0 ) { perror("WRITE"); return rc; }; 50.33 - tot += rc; 50.34 - } 50.35 - while ( tot < count ); 50.36 - return 0; 50.37 - } 50.38 - 50.39 - strncpy( server, url+strlen("tcp://"), max_namelen); 50.40 - server[max_namelen-1]='\0'; 50.41 - if ( (port_s = strchr(server,':')) != NULL ) { 50.42 - *port_s = '\0'; 50.43 - port = atoi(port_s+1); 50.44 - } 50.45 - printf("X server=%s port=%d\n",server,port); 50.46 - h = gethostbyname(server); 50.47 - sd = socket(AF_INET, SOCK_STREAM,0); 50.48 - if (sd < 0) goto serr; 50.49 - s.sin_family = AF_INET; 50.50 - bcopy ( h->h_addr, &(s.sin_addr.s_addr), h->h_length); 50.51 - s.sin_port = htons(port); 50.52 - if ( connect(sd, (struct sockaddr *) &s, sizeof(s)) ) goto serr; 50.53 - sockbufsize=128*1024; 50.54 - if ( setsockopt(sd, SOL_SOCKET, SO_SNDBUF, &sockbufsize, sizeof sockbufsize) < 0 ) goto serr; 50.55 - 50.56 - if ( xc_linux_save(xc->xc_handle, dom, flags, writerfn, (void*)sd) == 0 ) { 50.57 - if ( read( sd, &rc, sizeof(int) ) != sizeof(int) ) goto serr; 50.58 - 50.59 - if ( rc == 0 ) { 50.60 - printf("Migration succesful -- destroy local copy\n"); 50.61 - xc_domain_destroy(xc->xc_handle, dom); 50.62 - close(sd); 50.63 - Py_INCREF(zero); 50.64 - return zero; 50.65 - } else { 50.66 - errno = rc; 50.67 - } 50.68 - } 50.69 + int fd = -1; 50.70 + int open_flags = (O_CREAT | O_EXCL | O_WRONLY); 50.71 + int open_mode = 0644; 50.72 50.73 - serr: 50.74 - printf("Migration failed -- restart local copy\n"); 50.75 - xc_domain_unpause(xc->xc_handle, dom); 50.76 - PyErr_SetFromErrno(xc_error); 50.77 - if ( sd >= 0 ) close(sd); 50.78 - return NULL; 50.79 - 50.80 -} 50.81 - 50.82 -static PyObject *file_save(XcObject *xc, u32 dom, char *state_file, unsigned flags){ 50.83 - int fd = -1; 50.84 - gzFile gfd = NULL; 50.85 - 50.86 - int writerfn(void *fd, const void *buf, size_t count) { 50.87 - int rc; 50.88 - while ( ((rc = gzwrite( (gzFile*)fd, (void*)buf, count)) == -1) && 50.89 - (errno = EINTR) ) 50.90 - continue; 50.91 - return ! (rc == count); 50.92 - } 50.93 - 50.94 - if (strncmp(state_file,"file:",strlen("file:")) == 0){ 50.95 - state_file += strlen("file:"); 50.96 - } 50.97 - 50.98 - if ( (fd = open(state_file, O_CREAT|O_EXCL|O_WRONLY, 0644)) == -1 ) { 50.99 - perror("Could not open file for writing"); 50.100 - goto err; 50.101 - } 50.102 - /* 50.103 - * Compression rate 1: we want speed over compression. 50.104 - * We're mainly going for those zero pages, after all. 50.105 - */ 50.106 - if ( (gfd = gzdopen(fd, "wb1")) == NULL ) { 50.107 - perror("Could not allocate compression state for state file"); 50.108 - close(fd); 50.109 - goto err; 50.110 - } 50.111 - if ( xc_linux_save(xc->xc_handle, dom, flags, writerfn, gfd) == 0 ) { 50.112 - /* kill domain. We don't want to do this for checkpointing, but 50.113 - if we don't do it here I think people will hurt themselves 50.114 - by accident... */ 50.115 - xc_domain_destroy(xc->xc_handle, dom); 50.116 - gzclose(gfd); 50.117 - close(fd); 50.118 - 50.119 - Py_INCREF(zero); 50.120 - return zero; 50.121 - } 50.122 - 50.123 - err: 50.124 - PyErr_SetFromErrno(xc_error); 50.125 - if ( gfd != NULL ) gzclose(gfd); 50.126 - if ( fd >= 0 ) close(fd); 50.127 - unlink(state_file); 50.128 - return NULL; 50.129 + printf("%s>\n", __FUNCTION__); 50.130 + fd = open(state_file, open_flags, open_mode); 50.131 + if(fd < 0){ 50.132 + xcio_perror(ctxt, "Could not open file for writing"); 50.133 + goto exit; 50.134 + } 50.135 + /* Compression rate 1: we want speed over compression. 50.136 + * We're mainly going for those zero pages, after all. 50.137 + */ 50.138 + printf("%s>gzip_stream_fdopen... \n", __FUNCTION__); 50.139 + ctxt->io = gzip_stream_fdopen(fd, "wb1"); 50.140 + if(!ctxt->io){ 50.141 + xcio_perror(ctxt, "Could not allocate compression state"); 50.142 + goto exit; 50.143 + } 50.144 + printf("%s> xc_linux_save...\n", __FUNCTION__); 50.145 + rc = xc_linux_save(xc->xc_handle, ctxt); 50.146 + exit: 50.147 + if(ctxt->io) IOStream_close(ctxt->io); 50.148 + if(fd >= 0) close(fd); 50.149 + unlink(state_file); 50.150 + printf("%s> rc=%d\n", __FUNCTION__, rc); 50.151 + return rc; 50.152 } 50.153 50.154 static PyObject *pyxc_linux_save(PyObject *self, 50.155 @@ -306,195 +228,92 @@ static PyObject *pyxc_linux_save(PyObjec 50.156 { 50.157 XcObject *xc = (XcObject *)self; 50.158 50.159 - u32 dom; 50.160 + u32 dom; 50.161 char *state_file; 50.162 - int progress = 1, live = -1, debug = 0; 50.163 + int progress = 1, debug = 0; 50.164 unsigned int flags = 0; 50.165 PyObject *val = NULL; 50.166 - 50.167 - static char *kwd_list[] = { "dom", "state_file", "progress", 50.168 - "live", "debug", NULL }; 50.169 + int rc = -1; 50.170 + XcIOContext ioctxt = { .info = iostdout, .err = iostderr }; 50.171 50.172 - if ( !PyArg_ParseTupleAndKeywords(args, kwds, "is|iii", kwd_list, 50.173 - &dom, &state_file, &progress, 50.174 - &live, &debug) ) 50.175 - goto exit; 50.176 + static char *kwd_list[] = { "dom", "state_file", "vmconfig", "progress", "debug", NULL }; 50.177 50.178 - if (progress) flags |= XCFLAGS_VERBOSE; 50.179 - if (live == 1) flags |= XCFLAGS_LIVE; 50.180 - if (debug) flags |= XCFLAGS_DEBUG; 50.181 - 50.182 - if ( strncmp(state_file,"tcp:", strlen("tcp:")) == 0 ) { 50.183 - /* default to live for tcp */ 50.184 - if (live == -1) flags |= XCFLAGS_LIVE; 50.185 - val = tcp_save(xc, dom, state_file, flags); 50.186 - } else { 50.187 - val = file_save(xc, dom, state_file, flags); 50.188 + if (!PyArg_ParseTupleAndKeywords(args, kwds, "is|sii", kwd_list, 50.189 + &ioctxt.domain, 50.190 + &state_file, 50.191 + &ioctxt.vmconfig, 50.192 + &progress, 50.193 + &debug)){ 50.194 + goto exit; 50.195 } 50.196 + ioctxt.vmconfig_n = (ioctxt.vmconfig ? strlen(ioctxt.vmconfig) : 0); 50.197 + if (progress) ioctxt.flags |= XCFLAGS_VERBOSE; 50.198 + if (debug) ioctxt.flags |= XCFLAGS_DEBUG; 50.199 + if(!state_file || state_file[0] == '\0') goto exit; 50.200 + rc = file_save(xc, &ioctxt, state_file); 50.201 + if(rc){ 50.202 + PyErr_SetFromErrno(xc_error); 50.203 + goto exit; 50.204 + } 50.205 + //xc_domain_destroy(xc->xc_handle, dom); 50.206 + Py_INCREF(zero); 50.207 + val = zero; 50.208 exit: 50.209 return val; 50.210 } 50.211 50.212 + 50.213 +static int file_restore(XcObject *xc, XcIOContext *ioctxt, char *state_file){ 50.214 + int rc = -1; 50.215 + 50.216 + ioctxt->io = gzip_stream_fopen(state_file, "rb"); 50.217 + if (!ioctxt->io) { 50.218 + xcio_perror(ioctxt, "Could not open file for reading"); 50.219 + goto exit; 50.220 + } 50.221 + 50.222 + rc = xc_linux_restore(xc->xc_handle, ioctxt); 50.223 + exit: 50.224 + if(ioctxt->io) IOStream_close(ioctxt->io); 50.225 + return rc; 50.226 +} 50.227 + 50.228 static PyObject *pyxc_linux_restore(PyObject *self, 50.229 PyObject *args, 50.230 PyObject *kwds) 50.231 { 50.232 XcObject *xc = (XcObject *)self; 50.233 - 50.234 - char *state_file; 50.235 - int progress = 1; 50.236 - u32 dom; 50.237 - unsigned int flags = 0; 50.238 - 50.239 - static char *kwd_list[] = { "dom", "state_file", "progress", NULL }; 50.240 - 50.241 - if ( !PyArg_ParseTupleAndKeywords(args, kwds, "is|i", kwd_list, 50.242 - &dom, &state_file, &progress) ) 50.243 - return NULL; 50.244 - 50.245 - if ( progress ) 50.246 - flags |= XCFLAGS_VERBOSE; 50.247 - 50.248 - if ( strncmp(state_file,"tcp:", strlen("tcp:")) == 0 ) 50.249 - { 50.250 -#define max_namelen 64 50.251 - char server[max_namelen]; 50.252 - char *port_s; 50.253 - int port=777; 50.254 - int ld = -1, sd = -1; 50.255 - struct hostent *h; 50.256 - struct sockaddr_in s, d, p; 50.257 - socklen_t dlen, plen; 50.258 - int sockbufsize; 50.259 - int on = 1, rc = -1; 50.260 + char *state_file; 50.261 + int progress = 1, debug = 0; 50.262 + u32 dom; 50.263 + PyObject *val = NULL; 50.264 + XcIOContext ioctxt = { .info = iostdout, .err = iostderr }; 50.265 + int rc =-1; 50.266 50.267 - int readerfn(void *fd, void *buf, size_t count) 50.268 - { 50.269 - int rc, tot = 0; 50.270 - do { 50.271 - rc = read( (int) fd, ((char*)buf)+tot, count-tot ); 50.272 - if ( rc < 0 ) { perror("READ"); return rc; } 50.273 - if ( rc == 0 ) { printf("read: need %d, tot=%d got zero\n", 50.274 - count-tot, tot); return -1; } 50.275 - tot += rc; 50.276 - } 50.277 - while ( tot < count ); 50.278 - return 0; 50.279 - } 50.280 - 50.281 - strncpy( server, state_file+strlen("tcp://"), max_namelen); 50.282 - server[max_namelen-1]='\0'; 50.283 - if ( (port_s = strchr(server,':')) != NULL ) 50.284 - { 50.285 - *port_s = '\0'; 50.286 - port = atoi(port_s+1); 50.287 - } 50.288 - 50.289 - printf("X server=%s port=%d\n",server,port); 50.290 - 50.291 - h = gethostbyname(server); 50.292 - ld = socket (AF_INET,SOCK_STREAM,0); 50.293 - if ( ld < 0 ) goto serr; 50.294 - s.sin_family = AF_INET; 50.295 - s.sin_addr.s_addr = htonl(INADDR_ANY); 50.296 - s.sin_port = htons(port); 50.297 - 50.298 - if ( setsockopt(ld, SOL_SOCKET, SO_REUSEADDR, &on, sizeof (on)) < 0 ) 50.299 - goto serr; 50.300 - 50.301 - if ( bind(ld, (struct sockaddr *) &s, sizeof(s)) ) 50.302 - goto serr; 50.303 - 50.304 - if ( listen(ld, 1) ) 50.305 - goto serr; 50.306 - 50.307 - dlen=sizeof(struct sockaddr); 50.308 - if ( (sd = accept(ld, (struct sockaddr *) &d, &dlen )) < 0 ) 50.309 - goto serr; 50.310 - 50.311 - plen = sizeof(p); 50.312 - if ( getpeername(sd, (struct sockaddr_in *) &p, 50.313 - &plen) < 0 ) 50.314 - goto serr; 50.315 + static char *kwd_list[] = { "state_file", "progress", "debug", NULL }; 50.316 50.317 - printf("Accepted connection from %s\n", inet_ntoa(p.sin_addr)); 50.318 - 50.319 - sockbufsize=128*1024; 50.320 - if ( setsockopt(sd, SOL_SOCKET, SO_SNDBUF, &sockbufsize, 50.321 - sizeof sockbufsize) < 0 ) 50.322 - goto serr; 50.323 - 50.324 - rc = xc_linux_restore(xc->xc_handle, dom, flags, 50.325 - readerfn, (void*)sd, &dom); 50.326 - 50.327 - write( sd, &rc, sizeof(int) ); 50.328 - 50.329 - if (rc == 0) 50.330 - { 50.331 - close(sd); 50.332 - Py_INCREF(zero); 50.333 - return zero; 50.334 - } 50.335 - errno = rc; 50.336 - 50.337 - serr: 50.338 - PyErr_SetFromErrno(xc_error); 50.339 - if ( ld >= 0 ) close(ld); 50.340 - if ( sd >= 0 ) close(sd); 50.341 - return NULL; 50.342 - } 50.343 - else 50.344 - { 50.345 - int fd = -1; 50.346 - gzFile gfd = NULL; 50.347 + if (!PyArg_ParseTupleAndKeywords(args, kwds, "is|ii", kwd_list, 50.348 + &ioctxt.domain, 50.349 + &state_file, 50.350 + &progress, 50.351 + &debug)){ 50.352 + goto exit; 50.353 + } 50.354 + if (progress) ioctxt.flags |= XCFLAGS_VERBOSE; 50.355 + if (debug) ioctxt.flags |= XCFLAGS_DEBUG; 50.356 50.357 - int readerfn(void *fd, void *buf, size_t count) 50.358 - { 50.359 - int rc; 50.360 - while ( ((rc = gzread( (gzFile*)fd, (void*)buf, count)) == -1) && 50.361 - (errno = EINTR) ) 50.362 - continue; 50.363 - return ! (rc == count); 50.364 - } 50.365 - 50.366 - if ( strncmp(state_file,"file:",strlen("file:")) == 0 ) 50.367 - state_file += strlen("file:"); 50.368 - 50.369 - if ( (fd = open(state_file, O_RDONLY)) == -1 ) 50.370 - { 50.371 - perror("Could not open file for writing"); 50.372 - goto err; 50.373 - } 50.374 - 50.375 - /* 50.376 - * Compression rate 1: we want speed over compression. 50.377 - * We're mainly going for those zero pages, after all. 50.378 - */ 50.379 - if ( (gfd = gzdopen(fd, "rb")) == NULL ) 50.380 - { 50.381 - perror("Could not allocate compression state for state file"); 50.382 - close(fd); 50.383 - goto err; 50.384 - } 50.385 - 50.386 - 50.387 - if ( xc_linux_restore(xc->xc_handle, dom, flags, 50.388 - readerfn, gfd, &dom) == 0 ) 50.389 - { 50.390 - gzclose(gfd); 50.391 - close(fd); 50.392 - 50.393 - Py_INCREF(zero); 50.394 - return zero; 50.395 - } 50.396 - 50.397 - err: 50.398 + if(!state_file || state_file[0] == '\0') goto exit; 50.399 + rc = file_restore(xc, &ioctxt, state_file); 50.400 + if(rc){ 50.401 PyErr_SetFromErrno(xc_error); 50.402 - if ( gfd != NULL ) gzclose(gfd); 50.403 - if ( fd >= 0 ) close(fd); 50.404 - return NULL; 50.405 + goto exit; 50.406 } 50.407 - 50.408 + val = Py_BuildValue("{s:i,s:s}", 50.409 + "dom", ioctxt.domain, 50.410 + "vmconfig", ioctxt.vmconfig); 50.411 + //? free(ioctxt.vmconfig); 50.412 + exit: 50.413 + return val; 50.414 } 50.415 50.416 static PyObject *pyxc_linux_build(PyObject *self,
51.1 --- a/tools/xc/py/setup.py Tue Jun 29 00:51:10 2004 +0000 51.2 +++ b/tools/xc/py/setup.py Tue Jun 29 12:05:29 2004 +0000 51.3 @@ -3,12 +3,17 @@ from distutils.core import setup, Extens 51.4 51.5 module = Extension("xc", 51.6 extra_compile_args = ["-fno-strict-aliasing"], 51.7 - include_dirs = ["../lib"], 51.8 - library_dirs = ["../lib"], 51.9 + include_dirs = ["../lib", 51.10 + "../../../xen/include/hypervisor-ifs", 51.11 + "../../../linux-xen-sparse/include", 51.12 + "../../xu/lib", 51.13 + "../../lib" ], 51.14 + library_dirs = ["../lib", 51.15 + "../../lib" ], 51.16 libraries = ["xc"], 51.17 sources = ["Xc.c"]) 51.18 51.19 setup(name = "xc", 51.20 - version = "1.0", 51.21 + version = "2.0", 51.22 ext_package = "xen.ext", 51.23 ext_modules = [module])
52.1 --- a/tools/xen/lib/xend/XendDomain.py Tue Jun 29 00:51:10 2004 +0000 52.2 +++ b/tools/xen/lib/xend/XendDomain.py Tue Jun 29 12:05:29 2004 +0000 52.3 @@ -9,7 +9,6 @@ import sys 52.4 from twisted.internet import defer 52.5 52.6 import xen.ext.xc; xc = xen.ext.xc.new() 52.7 -import xenctl.ip 52.8 52.9 import sxp 52.10 import XendRoot 52.11 @@ -235,7 +234,7 @@ class XendDomain: 52.12 def domain_get(self, id): 52.13 id = str(id) 52.14 self.refresh_domain(id) 52.15 - return self.domain[id] 52.16 + return self.domain.get(id) 52.17 52.18 def domain_unpause(self, id): 52.19 """(Re)start domain running. 52.20 @@ -278,22 +277,26 @@ class XendDomain: 52.21 """ 52.22 # Need a cancel too? 52.23 pass 52.24 - 52.25 + 52.26 def domain_save(self, id, dst, progress=0): 52.27 """Save domain state to file, destroy domain. 52.28 """ 52.29 dom = int(id) 52.30 + dominfo = self.domain_get(id) 52.31 + if not dominfo: 52.32 + return -1 52.33 + vmconfig = sxp.to_string(dominfo.sxpr()) 52.34 self.domain_pause(id) 52.35 eserver.inject('xend.domain.save', id) 52.36 - rc = xc.linux_save(dom=dom, state_file=dst, progress=progress) 52.37 + rc = xc.linux_save(dom=dom, state_file=dst, vmconfig=vmconfig, progress=progress) 52.38 if rc == 0: 52.39 self.domain_destroy(id) 52.40 return rc 52.41 52.42 - def domain_restore(self, src, config, progress=0): 52.43 + def domain_restore(self, src, progress=0): 52.44 """Restore domain from file. 52.45 """ 52.46 - dominfo = XendDomainInfo.dom_restore(dom, config) 52.47 + dominfo = XendDomainInfo.vm_restore(src, progress=progress) 52.48 self._add_domain(dominfo.id, dominfo) 52.49 return dominfo 52.50 52.51 @@ -332,9 +335,9 @@ class XendDomain: 52.52 if not dominfo: return None 52.53 return dominfo.get_device_by_index(vif) 52.54 52.55 - def domain_vif_ip_add(self, dom, vif, ip): 52.56 - dom = int(dom) 52.57 - return xenctl.ip.setup_vfr_rules_for_vif(dom, vif, ip) 52.58 +## def domain_vif_ip_add(self, dom, vif, ip): 52.59 +## dom = int(dom) 52.60 +## return xenctl.ip.setup_vfr_rules_for_vif(dom, vif, ip) 52.61 52.62 def domain_vbd_ls(self, dom): 52.63 dominfo = self.domain_get(dom)
53.1 --- a/tools/xen/lib/xend/XendDomainInfo.py Tue Jun 29 00:51:10 2004 +0000 53.2 +++ b/tools/xen/lib/xend/XendDomainInfo.py Tue Jun 29 12:05:29 2004 +0000 53.3 @@ -17,7 +17,7 @@ import os 53.4 from twisted.internet import defer 53.5 53.6 import xen.ext.xc; xc = xen.ext.xc.new() 53.7 -import xenctl.ip 53.8 +import xen.util.ip 53.9 53.10 import sxp 53.11 53.12 @@ -167,14 +167,14 @@ def vif_up(iplist): 53.13 print >> open(IP_NONLOCAL_BIND, 'w'), str(v) 53.14 53.15 def link_local(ip): 53.16 - return xenctl.ip.check_subnet(ip, '169.254.0.0', '255.255.0.0') 53.17 + return xen.util.ip.check_subnet(ip, '169.254.0.0', '255.255.0.0') 53.18 53.19 def arping(ip, gw): 53.20 cmd = '/usr/sbin/arping -A -b -I eth0 -c 1 -s %s %s' % (ip, gw) 53.21 print cmd 53.22 os.system(cmd) 53.23 53.24 - gateway = xenctl.ip.get_current_ipgw() or '255.255.255.255' 53.25 + gateway = xen.util.ip.get_current_ipgw() or '255.255.255.255' 53.26 nlb = get_ip_nonlocal_bind() 53.27 if not nlb: set_ip_nonlocal_bind(1) 53.28 try: 53.29 @@ -272,22 +272,23 @@ def vm_recreate(config, info): 53.30 d.callback(vm) 53.31 return d 53.32 53.33 -def vm_restore(src, config, progress=0): 53.34 +def vm_restore(src, progress=0): 53.35 """Restore a VM from a disk image. 53.36 53.37 src saved state to restore 53.38 - config configuration 53.39 progress progress reporting flag 53.40 returns deferred 53.41 raises VmError for invalid configuration 53.42 """ 53.43 vm = XendDomainInfo() 53.44 - vm.config = config 53.45 - ostype = "linux" #todo set from config 53.46 + ostype = "linux" #todo Set from somewhere (store in the src?). 53.47 restorefn = getattr(xc, "%s_restore" % ostype) 53.48 - dom = restorefn(state_file=src, progress=progress) 53.49 + d = restorefn(state_file=src, progress=progress) 53.50 + dom = int(d['dom']) 53.51 if dom < 0: 53.52 raise VMError('restore failed') 53.53 + vmconfig = sxp.from_string(d['vmconfig']) 53.54 + vm.config = sxp.child_value(vmconfig, 'config') 53.55 deferred = vm.dom_configure(dom) 53.56 def vifs_cb(val, vm): 53.57 vif_up(vm.ipaddrs) 53.58 @@ -855,9 +856,7 @@ def vm_field_vfr(vm, config, val, index) 53.59 if not ip: 53.60 raise VmError('vfr: missing ip address') 53.61 ipaddrs.append(ip); 53.62 - #Don't do this in new i/o model. 53.63 - #print 'vm_field_vfr> add rule', 'dom=', vm.dom, 'vif=', vif, 'ip=', ip 53.64 - #xenctl.ip.setup_vfr_rules_for_vif(vm.dom, vif, ip) 53.65 + # todo: Configure the ipaddrs. 53.66 vm.ipaddrs = ipaddrs 53.67 53.68 def vnet_bridge(vnet, vmac, dom, idx):
54.1 --- a/tools/xen/lib/xend/server/SrvDomain.py Tue Jun 29 00:51:10 2004 +0000 54.2 +++ b/tools/xen/lib/xend/server/SrvDomain.py Tue Jun 29 12:05:29 2004 +0000 54.3 @@ -44,13 +44,6 @@ class SrvDomain(SrvDir): 54.4 val = fn(req.args, {'dom': self.dom.id}) 54.5 return val 54.6 54.7 - def op_restore(self, op, req): 54.8 - fn = FormFn(self.xd.domain_restore, 54.9 - [['dom', 'int'], 54.10 - ['file', 'str']]) 54.11 - val = fn(req.args, {'dom': self.dom.id}) 54.12 - return val 54.13 - 54.14 def op_migrate(self, op, req): 54.15 fn = FormFn(self.xd.domain_migrate, 54.16 [['dom', 'int'],
55.1 --- a/tools/xen/lib/xend/server/SrvDomainDir.py Tue Jun 29 00:51:10 2004 +0000 55.2 +++ b/tools/xen/lib/xend/server/SrvDomainDir.py Tue Jun 29 12:05:29 2004 +0000 55.3 @@ -7,6 +7,7 @@ from twisted.web import error 55.4 55.5 from xen.xend import sxp 55.6 from xen.xend import XendDomain 55.7 +from xen.xend.Args import FormFn 55.8 55.9 from SrvDir import SrvDir 55.10 from SrvDomain import SrvDomain 55.11 @@ -88,6 +89,12 @@ class SrvDomainDir(SrvDir): 55.12 out.close() 55.13 return val 55.14 55.15 + def op_restore(self, op, req): 55.16 + fn = FormFn(self.xd.domain_restore, 55.17 + [['file', 'str']]) 55.18 + val = fn(req.args) 55.19 + return val 55.20 + 55.21 def render_POST(self, req): 55.22 return self.perform(req) 55.23 55.24 @@ -129,3 +136,9 @@ class SrvDomainDir(SrvDir): 55.25 req.write('<button type="submit" name="op" value="create">Create Domain</button>') 55.26 req.write('Config <input type="file" name="config"><br>') 55.27 req.write('</form>') 55.28 + req.write('<form method="post" action="%s" enctype="multipart/form-data">' 55.29 + % req.prePathURL()) 55.30 + req.write('<button type="submit" name="op" value="create">Restore Domain</button>') 55.31 + req.write('State <input type="string" name="state"><br>') 55.32 + req.write('</form>') 55.33 +
56.1 --- a/tools/xen/lib/xend/sxp.py Tue Jun 29 00:51:10 2004 +0000 56.2 +++ b/tools/xen/lib/xend/sxp.py Tue Jun 29 12:05:29 2004 +0000 56.3 @@ -16,6 +16,7 @@ import sys 56.4 import types 56.5 import errno 56.6 import string 56.7 +from StringIO import StringIO 56.8 56.9 __all__ = [ 56.10 "mime_type", 56.11 @@ -521,6 +522,28 @@ def elements(sxpr, ctxt=None): 56.12 yield v 56.13 i += 1 56.14 56.15 +def to_string(sxpr): 56.16 + """Convert an sxpr to a string. 56.17 + 56.18 + sxpr sxpr 56.19 + returns string 56.20 + """ 56.21 + io = StringIO() 56.22 + show(sxpr, io) 56.23 + io.seek(0) 56.24 + val = io.getvalue() 56.25 + io.close() 56.26 + return val 56.27 + 56.28 +def from_string(str): 56.29 + """Create an sxpr by parsing a string. 56.30 + 56.31 + str string 56.32 + returns sxpr 56.33 + """ 56.34 + io = StringIO(str) 56.35 + return parse(io) 56.36 + 56.37 def parse(io): 56.38 """Completely parse all input from 'io'. 56.39
57.1 --- a/tools/xen/lib/xm/create.py Tue Jun 29 00:51:10 2004 +0000 57.2 +++ b/tools/xen/lib/xm/create.py Tue Jun 29 12:05:29 2004 +0000 57.3 @@ -8,7 +8,7 @@ from xen.xend import sxp 57.4 from xen.xend import PrettyPrint 57.5 from xen.xend.XendClient import server 57.6 57.7 -from xen.xend.xm.opts import * 57.8 +from xen.xm.opts import * 57.9 57.10 gopts = Opts(use="""[options] 57.11
58.1 --- a/tools/xen/lib/xm/main.py Tue Jun 29 00:51:10 2004 +0000 58.2 +++ b/tools/xen/lib/xm/main.py Tue Jun 29 12:05:29 2004 +0000 58.3 @@ -9,7 +9,7 @@ from getopt import getopt 58.4 from xen.xend import PrettyPrint 58.5 from xen.xend import sxp 58.6 from xen.xend.XendClient import server 58.7 -from xen.xend.xm import create, shutdown 58.8 +from xen.xm import create, shutdown 58.9 58.10 class Prog: 58.11 """Base class for sub-programs.
59.1 --- a/tools/xen/lib/xm/opts.py Tue Jun 29 00:51:10 2004 +0000 59.2 +++ b/tools/xen/lib/xm/opts.py Tue Jun 29 12:05:29 2004 +0000 59.3 @@ -290,6 +290,7 @@ class Opts: 59.4 cmd = '\n'.join(["import sys", 59.5 "import os", 59.6 "import os.path", 59.7 + "import xen.util.ip", 59.8 "xm_file = '%s'" % defaults, 59.9 "xm_help = %d" % help ]) 59.10 exec cmd in globals, locals
60.1 --- a/tools/xen/lib/xm/shutdown.py Tue Jun 29 00:51:10 2004 +0000 60.2 +++ b/tools/xen/lib/xm/shutdown.py Tue Jun 29 12:05:29 2004 +0000 60.3 @@ -6,7 +6,7 @@ import sys 60.4 import time 60.5 60.6 from xen.xend.XendClient import server 60.7 -from xen.xend.xm.opts import * 60.8 +from xen.xm.opts import * 60.9 60.10 gopts = Opts(use="""[options] [DOM] 60.11
61.1 --- a/tools/xen/xend Tue Jun 29 00:51:10 2004 +0000 61.2 +++ b/tools/xen/xend Tue Jun 29 12:05:29 2004 +0000 61.3 @@ -13,8 +13,8 @@ 61.4 61.5 xend stop 61.6 61.7 - Unfortunately restarting it upsets the channel to dom0 and 61.8 - domain management stops working - needs a reboot to fix. 61.9 + The daemon should reconnect to device control interfaces 61.10 + and recover its state when restarted. 61.11 """ 61.12 import os 61.13 import sys
62.1 --- a/tools/xentrace/Makefile Tue Jun 29 00:51:10 2004 +0000 62.2 +++ b/tools/xentrace/Makefile Tue Jun 29 12:05:29 2004 +0000 62.3 @@ -4,6 +4,7 @@ CFLAGS = -Wall -O3 -Werror 62.4 CFLAGS += -I../../xen/include/hypervisor-ifs 62.5 CFLAGS += -I../../linux-xen-sparse/include 62.6 CFLAGS += -I../xu/lib 62.7 +CFLAGS += -I../lib 62.8 62.9 HDRS = $(wildcard *.h) 62.10 OBJS = $(patsubst %.c,%.o,$(wildcard *.c))