ia64/xen-unstable
changeset 1597:7fc121a3c8a0
bitkeeper revision 1.1010.1.11 (40e03333GhMB8qgYk92TiquiQmUajA)
Change domain save/restore deal with the config string.
Change domain save/restore deal with the config string.
line diff
1.1 --- a/.rootkeys Mon Jun 28 08:17:15 2004 +0000 1.2 +++ b/.rootkeys Mon Jun 28 15:03:15 2004 +0000 1.3 @@ -165,6 +165,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 Mon Jun 28 08:17:15 2004 +0000 2.2 +++ b/BitKeeper/etc/ignore Mon Jun 28 15:03:15 2004 +0000 2.3 @@ -31,3 +31,21 @@ xen/tools/figlet/figlet 2.4 xen/xen 2.5 xen/xen-syms 2.6 xen/xen.* 2.7 +tools/xc/lib/.allocate.o.d 2.8 +tools/xc/lib/.file_stream.o.d 2.9 +tools/xc/lib/.gzip_stream.o.d 2.10 +tools/xc/lib/.iostream.o.d 2.11 +tools/xc/lib/.sys_net.o.d 2.12 +tools/xc/lib/.sys_string.o.d 2.13 +tools/xc/lib/.xc_atropos.o.d 2.14 +tools/xc/lib/.xc_bvtsched.o.d 2.15 +tools/xc/lib/.xc_domain.o.d 2.16 +tools/xc/lib/.xc_evtchn.o.d 2.17 +tools/xc/lib/.xc_io.o.d 2.18 +tools/xc/lib/.xc_linux_build.o.d 2.19 +tools/xc/lib/.xc_linux_restore.o.d 2.20 +tools/xc/lib/.xc_linux_save.o.d 2.21 +tools/xc/lib/.xc_misc.o.d 2.22 +tools/xc/lib/.xc_netbsd_build.o.d 2.23 +tools/xc/lib/.xc_physdev.o.d 2.24 +tools/xc/lib/.xc_private.o.d
3.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 3.2 +++ b/tools/lib/allocate.c Mon Jun 28 15:03:15 2004 +0000 3.3 @@ -0,0 +1,116 @@ 3.4 +/* 3.5 + * Copyright (C) 2001 - 2004 Mike Wray <mike.wray@hp.com> 3.6 + * 3.7 + * This library is free software; you can redistribute it and/or modify 3.8 + * it under the terms of the GNU Lesser General Public License as published by 3.9 + * the Free Software Foundation; either version 2.1 of the License, or 3.10 + * (at your option) any later version. 3.11 + * 3.12 + * This library is distributed in the hope that it will be useful, 3.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 3.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 3.15 + * GNU Lesser General Public License for more details. 3.16 + * 3.17 + * You should have received a copy of the GNU Lesser General Public License 3.18 + * along with this library; if not, write to the Free Software 3.19 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 3.20 + */ 3.21 + 3.22 +#include "allocate.h" 3.23 + 3.24 +/** @file 3.25 + * Support for allocating memory. 3.26 + * Usable from user code or kernel code (with __KERNEL__ defined). 3.27 + * In user code will use GC if USE_GC is defined. 3.28 + */ 3.29 + 3.30 +#ifdef __KERNEL__ 3.31 +/*----------------------------------------------------------------------------*/ 3.32 +# include <linux/config.h> 3.33 +# include <linux/slab.h> 3.34 +# include <linux/string.h> 3.35 +# include <linux/types.h> 3.36 + 3.37 +# define DEFAULT_TYPE 0 3.38 +# define MALLOC(n, type) kmalloc(n, type) 3.39 +# define FREE(ptr) kfree(ptr) 3.40 + 3.41 +/*----------------------------------------------------------------------------*/ 3.42 +#else /* ! __KERNEL__ */ 3.43 + 3.44 +# include <stdlib.h> 3.45 +# include <string.h> 3.46 + 3.47 +# define DEFAULT_TYPE 0 3.48 + 3.49 +#ifdef USE_GC 3.50 +# include "gc.h" 3.51 +# define MALLOC(n, typ) GC_malloc(n) 3.52 +# define FREE(ptr) (ptr=NULL) 3.53 +//typedef void *GC_PTR; 3.54 +//GC_PTR (*GC_oom_fn)(size_t n); 3.55 +#else 3.56 +# define MALLOC(n, type) malloc(n) 3.57 +# define FREE(ptr) free(ptr) 3.58 +#endif 3.59 + 3.60 +/*----------------------------------------------------------------------------*/ 3.61 +#endif 3.62 + 3.63 +/** Function to call when memory cannot be allocated. */ 3.64 +AllocateFailedFn *allocate_failed_fn = NULL; 3.65 + 3.66 +/** Allocate memory and zero it. 3.67 + * The type is only relevant when calling from kernel code, 3.68 + * from user code it is ignored. 3.69 + * In kernel code the values accepted by kmalloc can be used: 3.70 + * GFP_USER, GFP_ATOMIC, GFP_KERNEL. 3.71 + * 3.72 + * @param size number of bytes to allocate 3.73 + * @param type memory type to allocate (kernel only) 3.74 + * @return pointer to the allocated memory or zero 3.75 + * if malloc failed 3.76 + */ 3.77 +void *allocate_type(int size, int type){ 3.78 + void *p = MALLOC(size, type); 3.79 + if(p){ 3.80 + memzero(p, size); 3.81 + } else if(allocate_failed_fn){ 3.82 + allocate_failed_fn(size, type); 3.83 + } 3.84 + return p; 3.85 +} 3.86 + 3.87 +/** Allocate memory and zero it. 3.88 + * 3.89 + * @param size number of bytes to allocate 3.90 + * @return pointer to the allocated memory or zero 3.91 + * if malloc failed 3.92 + */ 3.93 +void *allocate(int size){ 3.94 + return allocate_type(size, DEFAULT_TYPE); 3.95 +} 3.96 + 3.97 +/** Free memory allocated by allocate(). 3.98 + * No-op if 'p' is null. 3.99 + * 3.100 + * @param p memory to free 3.101 + */ 3.102 +void deallocate(void *p){ 3.103 + if(p){ 3.104 + FREE(p); 3.105 + } 3.106 +} 3.107 + 3.108 +/** Set bytes to zero. 3.109 + * No-op if 'p' is null. 3.110 + * 3.111 + * @param p memory to zero 3.112 + * @param size number of bytes to zero 3.113 + */ 3.114 +void memzero(void *p, int size){ 3.115 + if(p){ 3.116 + memset(p, 0, (size_t)size); 3.117 + } 3.118 +} 3.119 +
4.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 4.2 +++ b/tools/lib/allocate.h Mon Jun 28 15:03:15 2004 +0000 4.3 @@ -0,0 +1,45 @@ 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 +#ifndef _XEN_LIB_ALLOCATE_H_ 4.23 +#define _XEN_LIB_ALLOCATE_H_ 4.24 + 4.25 +/** Allocate memory for a given type, and cast. */ 4.26 +#define ALLOCATE(ctype) (ctype *)allocate(sizeof(ctype)) 4.27 + 4.28 +/** Allocate memory for a given type, and cast. */ 4.29 +#define ALLOCATE_TYPE(ctype, type) (ctype *)allocate(sizeof(ctype)) 4.30 + 4.31 +extern void *allocate_type(int size, int type); 4.32 +extern void *allocate(int size); 4.33 +extern void deallocate(void *); 4.34 +extern void memzero(void *p, int size); 4.35 + 4.36 +typedef void AllocateFailedFn(int size, int type); 4.37 +extern AllocateFailedFn *allocate_failed_fn; 4.38 + 4.39 +#endif /* _XEN_LIB_ALLOCATE_H_ */ 4.40 + 4.41 + 4.42 + 4.43 + 4.44 + 4.45 + 4.46 + 4.47 + 4.48 +
5.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 5.2 +++ b/tools/lib/debug.h Mon Jun 28 15:03:15 2004 +0000 5.3 @@ -0,0 +1,72 @@ 5.4 +/* 5.5 + * Copyright (C) 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 +#ifndef _XEN_LIB_DEBUG_H_ 5.22 +#define _XEN_LIB_DEBUG_H_ 5.23 + 5.24 +#ifndef MODULE_NAME 5.25 +#define MODULE_NAME "" 5.26 +#endif 5.27 + 5.28 +#ifdef __KERNEL__ 5.29 +#include <linux/config.h> 5.30 +#include <linux/kernel.h> 5.31 + 5.32 +#ifdef DEBUG 5.33 + 5.34 +#define dprintf(fmt, args...) printk(KERN_DEBUG "[DBG] " MODULE_NAME ">%s" fmt, __FUNCTION__, ##args) 5.35 +#define wprintf(fmt, args...) printk(KERN_WARNING "[WRN] " MODULE_NAME ">%s" fmt, __FUNCTION__, ##args) 5.36 +#define iprintf(fmt, args...) printk(KERN_INFO "[INF] " MODULE_NAME ">%s" fmt, __FUNCTION__, ##args) 5.37 +#define eprintf(fmt, args...) printk(KERN_ERR "[ERR] " MODULE_NAME ">%s" fmt, __FUNCTION__, ##args) 5.38 + 5.39 +#else 5.40 + 5.41 +#define dprintf(fmt, args...) do {} while(0) 5.42 +#define wprintf(fmt, args...) printk(KERN_WARNING "[WRN] " MODULE_NAME fmt, ##args) 5.43 +#define iprintf(fmt, args...) printk(KERN_INFO "[INF] " MODULE_NAME fmt, ##args) 5.44 +#define eprintf(fmt, args...) printk(KERN_ERR "[ERR] " MODULE_NAME fmt, ##args) 5.45 + 5.46 +#endif 5.47 + 5.48 +#else 5.49 + 5.50 +#include <stdio.h> 5.51 + 5.52 +#ifdef DEBUG 5.53 + 5.54 +#define dprintf(fmt, args...) fprintf(stdout, "[DBG] " MODULE_NAME ">%s" fmt, __FUNCTION__, ##args) 5.55 +#define wprintf(fmt, args...) fprintf(stderr, "[WRN] " MODULE_NAME ">%s" fmt, __FUNCTION__, ##args) 5.56 +#define iprintf(fmt, args...) fprintf(stderr, "[INF] " MODULE_NAME ">%s" fmt, __FUNCTION__, ##args) 5.57 +#define eprintf(fmt, args...) fprintf(stderr, "[ERR] " MODULE_NAME ">%s" fmt, __FUNCTION__, ##args) 5.58 + 5.59 +#else 5.60 + 5.61 +#define dprintf(fmt, args...) do {} while(0) 5.62 +#define wprintf(fmt, args...) fprintf(stderr, "[WRN] " MODULE_NAME fmt, ##args) 5.63 +#define iprintf(fmt, args...) fprintf(stderr, "[INF] " MODULE_NAME fmt, ##args) 5.64 +#define eprintf(fmt, args...) fprintf(stderr, "[ERR] " MODULE_NAME fmt, ##args) 5.65 + 5.66 +#endif 5.67 + 5.68 +#endif 5.69 + 5.70 +/** Print format for an IP address. 5.71 + * See NIPQUAD(), HIPQUAD() 5.72 + */ 5.73 +#define IPFMT "%u.%u.%u.%u" 5.74 + 5.75 +#endif /* ! _XEN_LIB_DEBUG_H_ */
6.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 6.2 +++ b/tools/lib/enum.c Mon Jun 28 15:03:15 2004 +0000 6.3 @@ -0,0 +1,61 @@ 6.4 +/* 6.5 + * Copyright (C) 2002, 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 6.9 + * published by the Free Software Foundation; either version 2.1 of the 6.10 + * License, or (at your option) any later version. This library is 6.11 + * distributed in the hope that it will be useful, but WITHOUT ANY 6.12 + * WARRANTY; without even the implied warranty of MERCHANTABILITY or 6.13 + * FITNESS FOR A PARTICULAR PURPOSE. 6.14 + * See the GNU Lesser General Public License for more details. 6.15 + * 6.16 + * You should have received a copy of the GNU Lesser General Public License 6.17 + * along with this library; if not, write to the Free Software Foundation, 6.18 + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 6.19 + */ 6.20 + 6.21 +#ifdef __KERNEL__ 6.22 +#include <linux/errno.h> 6.23 +#else 6.24 +#include <errno.h> 6.25 +#endif 6.26 + 6.27 +#include "sys_string.h" 6.28 +#include "enum.h" 6.29 + 6.30 +/** Map an enum name to its value using a table. 6.31 + * 6.32 + * @param name enum name 6.33 + * @param defs enum definitions 6.34 + * @return enum value or -1 if not known 6.35 + */ 6.36 +int enum_name_to_val(char *name, EnumDef *defs){ 6.37 + int val = -1; 6.38 + for(; defs->name; defs++){ 6.39 + if(!strcmp(defs->name, name)){ 6.40 + val = defs->val; 6.41 + break; 6.42 + } 6.43 + } 6.44 + return val; 6.45 +} 6.46 + 6.47 +/** Map an enum value to its name using a table. 6.48 + * 6.49 + * @param val enum value 6.50 + * @param defs enum definitions 6.51 + * @param defs_n number of definitions 6.52 + * @return enum name or NULL if not known 6.53 + */ 6.54 +char *enum_val_to_name(int val, EnumDef *defs){ 6.55 + char *name = NULL; 6.56 + for(; defs->name; defs++){ 6.57 + if(val == defs->val){ 6.58 + name = defs->name; 6.59 + break; 6.60 + } 6.61 + } 6.62 + return name; 6.63 +} 6.64 +
7.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 7.2 +++ b/tools/lib/enum.h Mon Jun 28 15:03:15 2004 +0000 7.3 @@ -0,0 +1,30 @@ 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 +#ifndef _XEN_LIB_ENUM_H_ 7.22 +#define _XEN_LIB_ENUM_H_ 7.23 + 7.24 +/** Mapping of an enum value to a name. */ 7.25 +typedef struct EnumDef { 7.26 + int val; 7.27 + char *name; 7.28 +} EnumDef; 7.29 + 7.30 +extern int enum_name_to_val(char *name, EnumDef *defs); 7.31 +extern char *enum_val_to_name(int val, EnumDef *defs); 7.32 + 7.33 +#endif /* _XEN_LIB_ENUM_H_ */
8.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 8.2 +++ b/tools/lib/file_stream.c Mon Jun 28 15:03:15 2004 +0000 8.3 @@ -0,0 +1,202 @@ 8.4 +/* 8.5 + * Copyright (C) 2001 - 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 published by 8.9 + * the Free Software Foundation; either version 2.1 of the License, or 8.10 + * (at your option) any later version. 8.11 + * 8.12 + * This library is distributed in the hope that it will be useful, 8.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 8.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 8.15 + * GNU Lesser General Public License for more details. 8.16 + * 8.17 + * You should have received a copy of the GNU Lesser General Public License 8.18 + * along with this library; if not, write to the Free Software 8.19 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 8.20 + */ 8.21 + 8.22 +/** @file 8.23 + * An IOStream implementation using FILE*. 8.24 + */ 8.25 +#ifndef __KERNEL__ 8.26 +#include <stdio.h> 8.27 +#include <stdlib.h> 8.28 +#include "allocate.h" 8.29 +#include "file_stream.h" 8.30 + 8.31 +static int file_read(IOStream *s, void *buf, size_t n); 8.32 +static int file_write(IOStream *s, const void *buf, size_t n); 8.33 +static int file_error(IOStream *s); 8.34 +static int file_close(IOStream *s); 8.35 +static void file_free(IOStream *s); 8.36 +static int file_flush(IOStream *s); 8.37 + 8.38 +/** Methods used by a FILE* IOStream. */ 8.39 +static const IOMethods file_methods = { 8.40 + read: file_read, 8.41 + write: file_write, 8.42 + error: file_error, 8.43 + close: file_close, 8.44 + free: file_free, 8.45 + flush: file_flush, 8.46 +}; 8.47 + 8.48 +/** IOStream for stdin. */ 8.49 +static IOStream _iostdin = { 8.50 + methods: &file_methods, 8.51 + data: (void*)1, 8.52 +}; 8.53 + 8.54 +/** IOStream for stdout. */ 8.55 +static IOStream _iostdout = { 8.56 + methods: &file_methods, 8.57 + data: (void*)2, 8.58 +}; 8.59 + 8.60 +/** IOStream for stderr. */ 8.61 +static IOStream _iostderr = { 8.62 + methods: &file_methods, 8.63 + data: (void*)3, 8.64 +}; 8.65 + 8.66 +/** IOStream for stdin. */ 8.67 +IOStream *iostdin = &_iostdin; 8.68 + 8.69 +/** IOStream for stdout. */ 8.70 +IOStream *iostdout = &_iostdout; 8.71 + 8.72 +/** IOStream for stderr. */ 8.73 +IOStream *iostderr = &_iostderr; 8.74 + 8.75 +/** Get the underlying FILE*. 8.76 + * 8.77 + * @param s file stream 8.78 + * @return the stream s wraps 8.79 + */ 8.80 +static inline FILE *get_file(IOStream *s){ 8.81 + switch((long)s->data){ 8.82 + case 1: s->data = stdin; break; 8.83 + case 2: s->data = stdout; break; 8.84 + case 3: s->data = stderr; break; 8.85 + } 8.86 + return (FILE*)s->data; 8.87 +} 8.88 + 8.89 +/** Control buffering on the underlying stream, like setvbuf(). 8.90 + * 8.91 + * @param io file stream 8.92 + * @param buf buffer 8.93 + * @param mode buffering mode (see man setvbuf()) 8.94 + * @param size buffer size 8.95 + * @return 0 on success, non-zero otherwise 8.96 + */ 8.97 +int file_stream_setvbuf(IOStream *io, char *buf, int mode, size_t size){ 8.98 + return setvbuf(get_file(io), buf, mode, size); 8.99 +} 8.100 + 8.101 +/** Write to the underlying stream using fwrite(); 8.102 + * 8.103 + * @param stream input 8.104 + * @param buf where to put input 8.105 + * @param n number of bytes to write 8.106 + * @return number of bytes written 8.107 + */ 8.108 +static int file_write(IOStream *s, const void *buf, size_t n){ 8.109 + return fwrite(buf, 1, n, get_file(s)); 8.110 +} 8.111 + 8.112 +/** Read from the underlying stream using fread(); 8.113 + * 8.114 + * @param stream input 8.115 + * @param buf where to put input 8.116 + * @param n number of bytes to read 8.117 + * @return number of bytes read 8.118 + */ 8.119 +static int file_read(IOStream *s, void *buf, size_t n){ 8.120 + return fread(buf, 1, n, get_file(s)); 8.121 +} 8.122 + 8.123 +/** Fush the underlying stream using fflush(). 8.124 + * 8.125 + * @param s file stream 8.126 + * @return 0 on success, error code otherwise 8.127 + */ 8.128 +static int file_flush(IOStream *s){ 8.129 + return fflush(get_file(s)); 8.130 +} 8.131 + 8.132 +/** Check if a stream has an error. 8.133 + * 8.134 + * @param s file stream 8.135 + * @return 1 if has an error, 0 otherwise 8.136 + */ 8.137 +static int file_error(IOStream *s){ 8.138 + return ferror(get_file(s)); 8.139 +} 8.140 + 8.141 +/** Close a file stream. 8.142 + * 8.143 + * @param s file stream to close 8.144 + * @return result of the close 8.145 + */ 8.146 +static int file_close(IOStream *s){ 8.147 + return fclose(get_file(s)); 8.148 +} 8.149 + 8.150 +/** Free a file stream. 8.151 + * 8.152 + * @param s file stream 8.153 + */ 8.154 +static void file_free(IOStream *s){ 8.155 + // Do nothing - fclose does it all? 8.156 +} 8.157 + 8.158 +/** Create an IOStream for a stream. 8.159 + * 8.160 + * @param f stream to wrap 8.161 + * @return new IOStream using f for i/o 8.162 + */ 8.163 +IOStream *file_stream_new(FILE *f){ 8.164 + IOStream *io = ALLOCATE(IOStream); 8.165 + if(io){ 8.166 + io->methods = &file_methods; 8.167 + io->data = (void*)f; 8.168 + } 8.169 + return io; 8.170 +} 8.171 + 8.172 +/** IOStream version of fopen(). 8.173 + * 8.174 + * @param file name of the file to open 8.175 + * @param flags giving the mode to open in (as for fopen()) 8.176 + * @return new stream for the open file, or 0 if failed 8.177 + */ 8.178 +IOStream *file_stream_fopen(const char *file, const char *flags){ 8.179 + IOStream *io = 0; 8.180 + FILE *fin = fopen(file, flags); 8.181 + if(fin){ 8.182 + io = file_stream_new(fin); 8.183 + if(!io){ 8.184 + fclose(fin); 8.185 + //free(fin); // fclose frees ? 8.186 + } 8.187 + } 8.188 + return io; 8.189 +} 8.190 + 8.191 +/** IOStream version of fdopen(). 8.192 + * 8.193 + * @param fd file descriptor 8.194 + * @param flags giving the mode to open in (as for fdopen()) 8.195 + * @return new stream for the open file, or 0 if failed 8.196 + */ 8.197 +IOStream *file_stream_fdopen(int fd, const char *flags){ 8.198 + IOStream *io = 0; 8.199 + FILE *fin = fdopen(fd, flags); 8.200 + if(fin){ 8.201 + io = file_stream_new(fin); 8.202 + } 8.203 + return io; 8.204 +} 8.205 +#endif
9.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 9.2 +++ b/tools/lib/file_stream.h Mon Jun 28 15:03:15 2004 +0000 9.3 @@ -0,0 +1,35 @@ 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 +#ifndef _XEN_LIB_FILE_STREAM_H_ 9.23 +#define _XEN_LIB_FILE_STREAM_H_ 9.24 + 9.25 +#ifndef __KERNEL__ 9.26 +#include "iostream.h" 9.27 +#include <stdio.h> 9.28 + 9.29 +extern IOStream *file_stream_new(FILE *f); 9.30 +extern IOStream *file_stream_fopen(const char *file, const char *flags); 9.31 +extern IOStream *file_stream_fdopen(int fd, const char *flags); 9.32 +extern IOStream get_stream_stdout(void); 9.33 +extern IOStream get_stream_stderr(void); 9.34 +extern IOStream get_stream_stdin(void); 9.35 + 9.36 +extern int file_stream_setvbuf(IOStream *io, char *buf, int mode, size_t size); 9.37 +#endif 9.38 +#endif /* !_XEN_LIB_FILE_STREAM_H_ */
10.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 10.2 +++ b/tools/lib/gzip_stream.c Mon Jun 28 15:03:15 2004 +0000 10.3 @@ -0,0 +1,185 @@ 10.4 +/* $Id: gzip_stream.c,v 1.4 2003/09/30 15:22:53 mjw Exp $ */ 10.5 +/* 10.6 + * Copyright (C) 2003 Hewlett-Packard Company. 10.7 + * 10.8 + * This library is free software; you can redistribute it and/or modify 10.9 + * it under the terms of the GNU Lesser General Public License as published by 10.10 + * the Free Software Foundation; either version 2.1 of the License, or 10.11 + * (at your option) any later version. 10.12 + * 10.13 + * This library is distributed in the hope that it will be useful, 10.14 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 10.15 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 10.16 + * GNU Lesser General Public License for more details. 10.17 + * 10.18 + * You should have received a copy of the GNU Lesser General Public License 10.19 + * along with this library; if not, write to the Free Software 10.20 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 10.21 + */ 10.22 + 10.23 +/** @file 10.24 + * An IOStream implementation using zlib gzFile to provide 10.25 + * compression and decompression. 10.26 + */ 10.27 +#ifndef __KERNEL__ 10.28 + 10.29 +#include <stdio.h> 10.30 +#include <stdlib.h> 10.31 + 10.32 +#include "zlib.h" 10.33 + 10.34 +extern FILE* gzfile(gzFile file); 10.35 + 10.36 +#include "allocate.h" 10.37 +#include "gzip_stream.h" 10.38 + 10.39 +static int gzip_read(IOStream *s, void *buf, size_t n); 10.40 +static int gzip_write(IOStream *s, const void *buf, size_t n); 10.41 +static int gzip_error(IOStream *s); 10.42 +static int gzip_close(IOStream *s); 10.43 +static void gzip_free(IOStream *s); 10.44 +static int gzip_flush(IOStream *s); 10.45 + 10.46 +/** Methods used by a gzFile* IOStream. */ 10.47 +static const IOMethods gzip_methods = { 10.48 + read: gzip_read, 10.49 + write: gzip_write, 10.50 + error: gzip_error, 10.51 + close: gzip_close, 10.52 + free: gzip_free, 10.53 + flush: gzip_flush, 10.54 +}; 10.55 + 10.56 +/** Get the underlying gzFile*. 10.57 + * 10.58 + * @param s gzip stream 10.59 + * @return the stream s wraps 10.60 + */ 10.61 +static inline gzFile get_gzfile(IOStream *s){ 10.62 + return (gzFile)s->data; 10.63 +} 10.64 + 10.65 +/** Control buffering on the underlying stream, like setvbuf(). 10.66 + * 10.67 + * @param io gzip stream 10.68 + * @param buf buffer 10.69 + * @param mode buffering mode (see man setvbuf()) 10.70 + * @param size buffer size 10.71 + * @return 0 on success, non-zero otherwise 10.72 + */ 10.73 +int gzip_stream_setvbuf(IOStream *io, char *buf, int mode, size_t size){ 10.74 + return setvbuf(gzfile(get_gzfile(io)), buf, mode, size); 10.75 +} 10.76 + 10.77 +/** Write to the underlying stream. 10.78 + * 10.79 + * @param stream destination 10.80 + * @param buf data 10.81 + * @param n number of bytes to write 10.82 + * @return number of bytes written 10.83 + */ 10.84 +static int gzip_write(IOStream *s, const void *buf, size_t n){ 10.85 + return gzwrite(get_gzfile(s), (void*)buf, n); 10.86 +} 10.87 + 10.88 +/** Read from the underlying stream. 10.89 + * 10.90 + * @param stream input 10.91 + * @param buf where to put input 10.92 + * @param n number of bytes to read 10.93 + * @return number of bytes read 10.94 + */ 10.95 +static int gzip_read(IOStream *s, void *buf, size_t n){ 10.96 + return gzread(get_gzfile(s), buf, n); 10.97 +} 10.98 + 10.99 +/** Flush the underlying stream. 10.100 + * 10.101 + * @param s gzip stream 10.102 + * @return 0 on success, error code otherwise 10.103 + */ 10.104 +static int gzip_flush(IOStream *s){ 10.105 + //return gzflush(get_gzfile(s), Z_NO_FLUSH); 10.106 + return gzflush(get_gzfile(s), Z_SYNC_FLUSH); 10.107 + //return gzflush(get_gzfile(s), Z_FULL_FLUSH); 10.108 +} 10.109 + 10.110 +/** Check if a stream has an error. 10.111 + * 10.112 + * @param s gzip stream 10.113 + * @return 1 if has an error, 0 otherwise 10.114 + */ 10.115 +static int gzip_error(IOStream *s){ 10.116 + int err; 10.117 + gzFile *gz = get_gzfile(s); 10.118 + gzerror(gz, &err); 10.119 + return (err == Z_ERRNO ? ferror(gzfile(gz)) : err); 10.120 +} 10.121 + 10.122 +/** Close a gzip stream. 10.123 + * 10.124 + * @param s gzip stream to close 10.125 + * @return result of the close 10.126 + */ 10.127 +static int gzip_close(IOStream *s){ 10.128 + return gzclose(get_gzfile(s)); 10.129 +} 10.130 + 10.131 +/** Free a gzip stream. 10.132 + * 10.133 + * @param s gzip stream 10.134 + */ 10.135 +static void gzip_free(IOStream *s){ 10.136 + // Do nothing - fclose does it all? 10.137 +} 10.138 + 10.139 +/** Create an IOStream for a gzip stream. 10.140 + * 10.141 + * @param f stream to wrap 10.142 + * @return new IOStream using f for i/o 10.143 + */ 10.144 +IOStream *gzip_stream_new(gzFile *f){ 10.145 + IOStream *io = ALLOCATE(IOStream); 10.146 + if(io){ 10.147 + io->methods = &gzip_methods; 10.148 + io->data = (void*)f; 10.149 + } 10.150 + return io; 10.151 +} 10.152 + 10.153 +/** IOStream version of fopen(). 10.154 + * 10.155 + * @param file name of the file to open 10.156 + * @param flags giving the mode to open in (as for fopen()) 10.157 + * @return new stream for the open file, or NULL if failed 10.158 + */ 10.159 +IOStream *gzip_stream_fopen(const char *file, const char *flags){ 10.160 + IOStream *io = NULL; 10.161 + gzFile *fgz; 10.162 + fgz = gzopen(file, flags); 10.163 + if(fgz){ 10.164 + io = gzip_stream_new(fgz); 10.165 + if(!io){ 10.166 + gzclose(fgz); 10.167 + //free(fgz); // gzclose frees ? 10.168 + } 10.169 + } 10.170 + return io; 10.171 +} 10.172 + 10.173 +/** IOStream version of fdopen(). 10.174 + * 10.175 + * @param fd file descriptor 10.176 + * @param flags giving the mode to open in (as for fdopen()) 10.177 + * @return new stream for the open file, or NULL if failed 10.178 + */ 10.179 +IOStream *gzip_stream_fdopen(int fd, const char *flags){ 10.180 + IOStream *io = NULL; 10.181 + gzFile *fgz; 10.182 + fgz = gzdopen(fd, flags); 10.183 + if(fgz){ 10.184 + io = gzip_stream_new(fgz); 10.185 + } 10.186 + return io; 10.187 +} 10.188 +#endif
11.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 11.2 +++ b/tools/lib/gzip_stream.h Mon Jun 28 15:03:15 2004 +0000 11.3 @@ -0,0 +1,33 @@ 11.4 +#/* $Id: gzip_stream.h,v 1.3 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 +#ifndef _SP_GZIP_STREAM_H_ 11.24 +#define _SP_GZIP_STREAM_H_ 11.25 + 11.26 +#ifndef __KERNEL__ 11.27 +#include "iostream.h" 11.28 +#include "zlib.h" 11.29 + 11.30 +extern IOStream *gzip_stream_new(gzFile *f); 11.31 +extern IOStream *gzip_stream_fopen(const char *file, const char *flags); 11.32 +extern IOStream *gzip_stream_fdopen(int fd, const char *flags); 11.33 + 11.34 +extern int gzip_stream_setvbuf(IOStream *io, char *buf, int mode, size_t size); 11.35 +#endif 11.36 +#endif /* !_SP_FILE_STREAM_H_ */
12.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 12.2 +++ b/tools/lib/hash_table.c Mon Jun 28 15:03:15 2004 +0000 12.3 @@ -0,0 +1,640 @@ 12.4 +/* 12.5 + * Copyright (C) 2001 - 2004 Mike Wray <mike.wray@hp.com> 12.6 + * 12.7 + * This library is free software; you can redistribute it and/or modify 12.8 + * it under the terms of the GNU Lesser General Public License as published by 12.9 + * the Free Software Foundation; either version 2.1 of the License, or 12.10 + * (at your option) any later version. 12.11 + * 12.12 + * This library is distributed in the hope that it will be useful, 12.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 12.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12.15 + * GNU Lesser General Public License for more details. 12.16 + * 12.17 + * You should have received a copy of the GNU Lesser General Public License 12.18 + * along with this library; if not, write to the Free Software 12.19 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 12.20 + */ 12.21 + 12.22 +#ifdef __KERNEL__ 12.23 +# include <linux/config.h> 12.24 +# include <linux/module.h> 12.25 +# include <linux/kernel.h> 12.26 +# include <linux/errno.h> 12.27 +#else 12.28 +# include <errno.h> 12.29 +# include <stddef.h> 12.30 +#endif 12.31 + 12.32 +//#include <limits.h> 12.33 + 12.34 +#include "allocate.h" 12.35 +#include "hash_table.h" 12.36 + 12.37 +/** @file 12.38 + * Base support for hashtables. 12.39 + * 12.40 + * Hash codes are reduced modulo the number of buckets to index tables, 12.41 + * so there is no need for hash functions to limit the range of hashcodes. 12.42 + * In fact it is assumed that hashcodes do not change when the number of 12.43 + * buckets in the table changes. 12.44 + */ 12.45 + 12.46 +/*==========================================================================*/ 12.47 +/** Number of bits in half a word. */ 12.48 +//#if __WORDSIZE == 64 12.49 +//#define HALF_WORD_BITS 32 12.50 +//#else 12.51 +#define HALF_WORD_BITS 16 12.52 +//#endif 12.53 + 12.54 +/** Mask for lo half of a word. On 32-bit this is 12.55 + * (1<<16) - 1 = 65535 = 0xffff 12.56 + * It's 4294967295 = 0xffffffff on 64-bit. 12.57 + */ 12.58 +#define LO_HALF_MASK ((1 << HALF_WORD_BITS) - 1) 12.59 + 12.60 +/** Get the lo half of a word. */ 12.61 +#define LO_HALF(x) ((x) & LO_HALF_MASK) 12.62 + 12.63 +/** Get the hi half of a word. */ 12.64 +#define HI_HALF(x) ((x) >> HALF_WORD_BITS) 12.65 + 12.66 +/** Do a full hash on both inputs, using DES-style non-linear scrambling. 12.67 + * Both inputs are replaced with the results of the hash. 12.68 + * 12.69 + * @param pleft input/output word 12.70 + * @param pright input/output word 12.71 + */ 12.72 +void pseudo_des(unsigned long *pleft, unsigned long *pright){ 12.73 + // Bit-rich mixing constant. 12.74 + static const unsigned long a_mixer[] = { 12.75 + 0xbaa96887L, 0x1e17d32cL, 0x03bcdc3cL, 0x0f33d1b2L, }; 12.76 + 12.77 + // Bit-rich mixing constant. 12.78 + static const unsigned long b_mixer[] = { 12.79 + 0x4b0f3b58L, 0xe874f0c3L, 0x6955c5a6L, 0x55a7ca46L, }; 12.80 + 12.81 + // Number of iterations - must be 2 or 4. 12.82 + static const int ncycle = 4; 12.83 + //static const int ncycle = 2; 12.84 + 12.85 + unsigned long left = *pleft, right = *pright; 12.86 + unsigned long v, v_hi, v_lo; 12.87 + int i; 12.88 + 12.89 + for(i=0; i<ncycle; i++){ 12.90 + // Flip some bits in right to get v. 12.91 + v = right; 12.92 + v ^= a_mixer[i]; 12.93 + // Get lo and hi halves of v. 12.94 + v_lo = LO_HALF(v); 12.95 + v_hi = HI_HALF(v); 12.96 + // Non-linear mix of the halves of v. 12.97 + v = ((v_lo * v_lo) + ~(v_hi * v_hi)); 12.98 + // Swap the halves of v. 12.99 + v = (HI_HALF(v) | (LO_HALF(v) << HALF_WORD_BITS)); 12.100 + // Flip some bits. 12.101 + v ^= b_mixer[i]; 12.102 + // More non-linear mixing. 12.103 + v += (v_lo * v_hi); 12.104 + v ^= left; 12.105 + left = right; 12.106 + right = v; 12.107 + } 12.108 + *pleft = left; 12.109 + *pright = right; 12.110 +} 12.111 + 12.112 +/** Hash a string. 12.113 + * 12.114 + * @param s input to hash 12.115 + * @return hashcode 12.116 + */ 12.117 +Hashcode hash_string(char *s){ 12.118 + Hashcode h = 0; 12.119 + if(s){ 12.120 + for( ; *s; s++){ 12.121 + h = hash_2ul(h, *s); 12.122 + } 12.123 + } 12.124 + return h; 12.125 +} 12.126 + 12.127 +/** Get the bucket for a hashcode in a hash table. 12.128 + * 12.129 + * @param table to get bucket from 12.130 + * @param hashcode to get bucket for 12.131 + * @return bucket 12.132 + */ 12.133 +inline HTBucket * get_bucket(HashTable *table, Hashcode hashcode){ 12.134 + return table->buckets + (hashcode % table->buckets_n); 12.135 +} 12.136 + 12.137 +/** Initialize a hash table. 12.138 + * Can be safely called more than once. 12.139 + * 12.140 + * @param table to initialize 12.141 + */ 12.142 +void HashTable_init(HashTable *table){ 12.143 + int i; 12.144 + 12.145 + if(!table->init_done){ 12.146 + table->init_done = 1; 12.147 + table->next_id = 0; 12.148 + for(i=0; i<table->buckets_n; i++){ 12.149 + HTBucket *bucket = get_bucket(table, i); 12.150 + bucket->head = 0; 12.151 + bucket->count = 0; 12.152 + } 12.153 + table->entry_count = 0; 12.154 + } 12.155 +} 12.156 + 12.157 +/** Allocate a new hashtable. 12.158 + * If the number of buckets is not positive the default is used. 12.159 + * The number of buckets should usually be prime. 12.160 + * 12.161 + * @param buckets_n number of buckets 12.162 + * @return new hashtable or null 12.163 + */ 12.164 +HashTable *HashTable_new(int buckets_n){ 12.165 + HashTable *z = ALLOCATE(HashTable); 12.166 + if(!z) goto exit; 12.167 + if(buckets_n <= 0){ 12.168 + buckets_n = HT_BUCKETS_N; 12.169 + } 12.170 + z->buckets = (HTBucket*)allocate(buckets_n * sizeof(HTBucket)); 12.171 + if(!z->buckets){ 12.172 + deallocate(z); 12.173 + z = 0; 12.174 + goto exit; 12.175 + } 12.176 + z->buckets_n = buckets_n; 12.177 + HashTable_init(z); 12.178 + exit: 12.179 + return z; 12.180 +} 12.181 + 12.182 +/** Free a hashtable. 12.183 + * Any entries are removed and freed. 12.184 + * 12.185 + * @param h hashtable (ignored if null) 12.186 + */ 12.187 +void HashTable_free(HashTable *h){ 12.188 + if(h){ 12.189 + HashTable_clear(h); 12.190 + deallocate(h->buckets); 12.191 + deallocate(h); 12.192 + } 12.193 +} 12.194 + 12.195 +/** Push an entry on the list in the bucket for a given hashcode. 12.196 + * 12.197 + * @param table to add entry to 12.198 + * @param hashcode for the entry 12.199 + * @param entry to add 12.200 + */ 12.201 +static inline void push_on_bucket(HashTable *table, Hashcode hashcode, 12.202 + HTEntry *entry){ 12.203 + HTBucket *bucket; 12.204 + HTEntry *old_head; 12.205 + 12.206 + bucket = get_bucket(table, hashcode); 12.207 + old_head = bucket->head; 12.208 + bucket->count++; 12.209 + bucket->head = entry; 12.210 + entry->next = old_head; 12.211 +} 12.212 + 12.213 +/** Change the number of buckets in a hashtable. 12.214 + * No-op if the number of buckets is not positive. 12.215 + * Existing entries are reallocated to buckets based on their hashcodes. 12.216 + * The table is unmodified if the number of buckets cannot be changed. 12.217 + * 12.218 + * @param table hashtable 12.219 + * @param buckets_n new number of buckets 12.220 + * @return 0 on success, error code otherwise 12.221 + */ 12.222 +int HashTable_set_buckets_n(HashTable *table, int buckets_n){ 12.223 + int err = 0; 12.224 + HTBucket *old_buckets = table->buckets; 12.225 + int old_buckets_n = table->buckets_n; 12.226 + int i; 12.227 + 12.228 + if(buckets_n <= 0){ 12.229 + err = -EINVAL; 12.230 + goto exit; 12.231 + } 12.232 + table->buckets = (HTBucket*)allocate(buckets_n * sizeof(HTBucket)); 12.233 + if(!table->buckets){ 12.234 + err = -ENOMEM; 12.235 + table->buckets = old_buckets; 12.236 + goto exit; 12.237 + } 12.238 + table->buckets_n = buckets_n; 12.239 + for(i=0; i<old_buckets_n; i++){ 12.240 + HTBucket *bucket = old_buckets + i; 12.241 + HTEntry *entry, *next; 12.242 + for(entry = bucket->head; entry; entry = next){ 12.243 + next = entry->next; 12.244 + push_on_bucket(table, entry->hashcode, entry); 12.245 + } 12.246 + } 12.247 + deallocate(old_buckets); 12.248 + exit: 12.249 + return err; 12.250 +} 12.251 + 12.252 +/** Adjust the number of buckets so the table is neither too full nor too empty. 12.253 + * The table is unmodified if adjusting fails. 12.254 + * 12.255 + * @param table hash table 12.256 + * @param buckets_min minimum number of buckets (use default if 0 or negative) 12.257 + * @return 0 on success, error code otherwise 12.258 + */ 12.259 +int HashTable_adjust(HashTable *table, int buckets_min){ 12.260 + int buckets_n = 0; 12.261 + int err = 0; 12.262 + if(buckets_min <= 0) buckets_min = HT_BUCKETS_N; 12.263 + if(table->entry_count >= table->buckets_n){ 12.264 + // The table is dense - expand it. 12.265 + buckets_n = 2 * table->buckets_n; 12.266 + } else if((table->buckets_n > buckets_min) && 12.267 + (4 * table->entry_count < table->buckets_n)){ 12.268 + // The table is more than minimum size and sparse - shrink it. 12.269 + buckets_n = 2 * table->entry_count; 12.270 + if(buckets_n < buckets_min) buckets_n = buckets_min; 12.271 + } 12.272 + if(buckets_n){ 12.273 + err = HashTable_set_buckets_n(table, buckets_n); 12.274 + } 12.275 + return err; 12.276 +} 12.277 + 12.278 +/** Allocate a new entry for a given value. 12.279 + * 12.280 + * @param value to put in the entry 12.281 + * @return entry, or 0 on failure 12.282 + */ 12.283 +HTEntry * HTEntry_new(Hashcode hashcode, void *key, void *value){ 12.284 + HTEntry *z = ALLOCATE(HTEntry); 12.285 + if(z){ 12.286 + z->hashcode = hashcode; 12.287 + z->key = key; 12.288 + z->value = value; 12.289 + } 12.290 + return z; 12.291 +} 12.292 + 12.293 +/** Free an entry. 12.294 + * 12.295 + * @param z entry to free 12.296 + */ 12.297 +inline void HTEntry_free(HTEntry *z){ 12.298 + if(z){ 12.299 + deallocate(z); 12.300 + } 12.301 +} 12.302 + 12.303 +/** Free an entry in a hashtable. 12.304 + * The table's entry_free_fn is used is defined, otherwise 12.305 + * the HTEntry itself is freed. 12.306 + * 12.307 + * @param table hashtable 12.308 + * @param entry to free 12.309 + */ 12.310 +inline void HashTable_free_entry(HashTable *table, HTEntry *entry){ 12.311 + if(!entry)return; 12.312 + if(table && table->entry_free_fn){ 12.313 + table->entry_free_fn(table, entry); 12.314 + } else { 12.315 + HTEntry_free(entry); 12.316 + } 12.317 +} 12.318 + 12.319 +/** Get the first entry satisfying a test from the bucket for the 12.320 + * given hashcode. 12.321 + * 12.322 + * @param table to look in 12.323 + * @param hashcode indicates the bucket 12.324 + * @param test_fn test to apply to elements 12.325 + * @param arg first argument to calls to test_fn 12.326 + * @return entry found, or 0 12.327 + */ 12.328 +inline HTEntry * HashTable_find_entry(HashTable *table, Hashcode hashcode, 12.329 + TableTestFn *test_fn, TableArg arg){ 12.330 + HTBucket *bucket; 12.331 + HTEntry *entry = 0; 12.332 + HTEntry *next; 12.333 + 12.334 + bucket = get_bucket(table, hashcode); 12.335 + for(entry = bucket->head; entry; entry = next){ 12.336 + next = entry->next; 12.337 + if(test_fn(arg, table, entry)){ 12.338 + break; 12.339 + } 12.340 + } 12.341 + return entry; 12.342 +} 12.343 + 12.344 +/** Test hashtable keys for equality. 12.345 + * Uses the table's key_equal_fn if defined, otherwise pointer equality. 12.346 + * 12.347 + * @param key1 key to compare 12.348 + * @param key2 key to compare 12.349 + * @return 1 if equal, 0 otherwise 12.350 + */ 12.351 +inline int HashTable_key_equal(HashTable *table, void *key1, void *key2){ 12.352 + return (table->key_equal_fn ? table->key_equal_fn(key1, key2) : key1==key2); 12.353 +} 12.354 + 12.355 +/** Compute the hashcode of a hashtable key. 12.356 + * The table's key_hash_fn is used if defined, otherwise the address of 12.357 + * the key is hashed. 12.358 + * 12.359 + * @param table hashtable 12.360 + * @param key to hash 12.361 + * @return hashcode 12.362 + */ 12.363 +inline Hashcode HashTable_key_hash(HashTable *table, void *key){ 12.364 + return (table->key_hash_fn ? table->key_hash_fn(key) : hash_ul((unsigned long)key)); 12.365 +} 12.366 + 12.367 +/** Test if an entry has a given key. 12.368 + * 12.369 + * @param arg containing key to test for 12.370 + * @param table the entry is in 12.371 + * @param entry to test 12.372 + * @return 1 if the entry has the key, 0 otherwise 12.373 + */ 12.374 +static inline int has_key(TableArg arg, HashTable *table, HTEntry *entry){ 12.375 + return HashTable_key_equal(table, arg.ptr, entry->key); 12.376 +} 12.377 + 12.378 +/** Get an entry with a given key. 12.379 + * 12.380 + * @param table to search 12.381 + * @param key to look for 12.382 + * @return entry if found, null otherwise 12.383 + */ 12.384 +#if 0 12.385 +inline HTEntry * HashTable_get_entry(HashTable *table, void *key){ 12.386 + TableArg arg = { ptr: key }; 12.387 + return HashTable_find_entry(table, HashTable_key_hash(table, key), has_key, arg); 12.388 +} 12.389 +#else 12.390 +inline HTEntry * HashTable_get_entry(HashTable *table, void *key){ 12.391 + Hashcode hashcode; 12.392 + HTBucket *bucket; 12.393 + HTEntry *entry = 0; 12.394 + HTEntry *next; 12.395 + 12.396 + hashcode = HashTable_key_hash(table, key); 12.397 + bucket = get_bucket(table, hashcode); 12.398 + for(entry = bucket->head; entry; entry = next){ 12.399 + next = entry->next; 12.400 + if(HashTable_key_equal(table, key, entry->key)){ 12.401 + break; 12.402 + } 12.403 + } 12.404 + return entry; 12.405 +} 12.406 +#endif 12.407 + 12.408 +/** Get the value of an entry with a given key. 12.409 + * 12.410 + * @param table to search 12.411 + * @param key to look for 12.412 + * @return value if an entry was found, null otherwise 12.413 + */ 12.414 +inline void * HashTable_get(HashTable *table, void *key){ 12.415 + HTEntry *entry = HashTable_get_entry(table, key); 12.416 + return (entry ? entry->value : 0); 12.417 +} 12.418 + 12.419 +/** Print the buckets in a table. 12.420 + * 12.421 + * @param table to print 12.422 + */ 12.423 +void show_buckets(HashTable *table, IOStream *io){ 12.424 + int i,j ; 12.425 + IOStream_print(io, "entry_count=%d buckets_n=%d\n", table->entry_count, table->buckets_n); 12.426 + for(i=0; i<table->buckets_n; i++){ 12.427 + if(0 || table->buckets[i].count>0){ 12.428 + IOStream_print(io, "bucket %3d %3d %10p ", i, 12.429 + table->buckets[i].count, 12.430 + table->buckets[i].head); 12.431 + for(j = table->buckets[i].count; j>0; j--){ 12.432 + IOStream_print(io, "+"); 12.433 + } 12.434 + IOStream_print(io, "\n"); 12.435 + } 12.436 + } 12.437 + HashTable_print(table, io); 12.438 +} 12.439 + 12.440 +/** Print an entry in a table. 12.441 + * 12.442 + * @param entry to print 12.443 + * @param arg a pointer to an IOStream to print to 12.444 + * @return 0 12.445 + */ 12.446 +static int print_entry(TableArg arg, HashTable *table, HTEntry *entry){ 12.447 + IOStream *io = (IOStream*)arg.ptr; 12.448 + IOStream_print(io, " b=%4lx h=%08lx i=%08lx |-> e=%8p k=%8p v=%8p\n", 12.449 + entry->hashcode % table->buckets_n, 12.450 + entry->hashcode, 12.451 + entry->index, 12.452 + entry, entry->key, entry->value); 12.453 + return 0; 12.454 +} 12.455 + 12.456 +/** Print a hash table. 12.457 + * 12.458 + * @param table to print 12.459 + */ 12.460 +void HashTable_print(HashTable *table, IOStream *io){ 12.461 + IOStream_print(io, "{\n"); 12.462 + HashTable_map(table, print_entry, (TableArg){ ptr: io }); 12.463 + IOStream_print(io, "}\n"); 12.464 +} 12.465 +/*==========================================================================*/ 12.466 + 12.467 +/** Get the next entry id to use for a table. 12.468 + * 12.469 + * @param table hash table 12.470 + * @return non-zero entry id 12.471 + */ 12.472 +static inline unsigned long get_next_id(HashTable *table){ 12.473 + unsigned long id; 12.474 + 12.475 + if(table->next_id == 0){ 12.476 + table->next_id = 1; 12.477 + } 12.478 + id = table->next_id++; 12.479 + return id; 12.480 +} 12.481 + 12.482 +/** Add an entry to the bucket for the 12.483 + * given hashcode. 12.484 + * 12.485 + * @param table to insert in 12.486 + * @param hashcode indicates the bucket 12.487 + * @param key to add an entry for 12.488 + * @param value to add an entry for 12.489 + * @return entry on success, 0 on failure 12.490 + */ 12.491 +inline HTEntry * HashTable_add_entry(HashTable *table, Hashcode hashcode, void *key, void *value){ 12.492 + HTEntry *entry = HTEntry_new(hashcode, key, value); 12.493 + if(entry){ 12.494 + entry->index = get_next_id(table); 12.495 + push_on_bucket(table, hashcode, entry); 12.496 + table->entry_count++; 12.497 + } 12.498 + return entry; 12.499 +} 12.500 + 12.501 +/** Move the front entry for a bucket to the correct point in the bucket order as 12.502 + * defined by the order function. If this is called every time a new entry is added 12.503 + * the bucket will be maintained in sorted order. 12.504 + * 12.505 + * @param table to modify 12.506 + * @param hashcode indicates the bucket 12.507 + * @param order entry comparison function 12.508 + * @return 0 if an entry was moved, 1 if not 12.509 + */ 12.510 +int HashTable_order_bucket(HashTable *table, Hashcode hashcode, TableOrderFn *order){ 12.511 + HTEntry *new_entry = NULL, *prev = NULL, *entry = NULL; 12.512 + HTBucket *bucket; 12.513 + int err = 1; 12.514 + 12.515 + bucket = get_bucket(table, hashcode); 12.516 + new_entry = bucket->head; 12.517 + if(!new_entry || !new_entry->next) goto exit; 12.518 + for(entry = new_entry->next; entry; prev = entry, entry = entry->next){ 12.519 + if(order(new_entry, entry) <= 0) break; 12.520 + } 12.521 + if(prev){ 12.522 + err = 0; 12.523 + bucket->head = new_entry->next; 12.524 + new_entry->next = entry; 12.525 + prev->next = new_entry; 12.526 + } 12.527 + exit: 12.528 + return err; 12.529 +} 12.530 + 12.531 +/** Add an entry to a hashtable. 12.532 + * The entry is added to the bucket for its key's hashcode. 12.533 + * 12.534 + * @param table to insert in 12.535 + * @param key to add an entry for 12.536 + * @param value to add an entry for 12.537 + * @return entry on success, 0 on failure 12.538 + */ 12.539 +inline HTEntry * HashTable_add(HashTable *table, void *key, void *value){ 12.540 + return HashTable_add_entry(table, HashTable_key_hash(table, key), key, value); 12.541 +} 12.542 + 12.543 + 12.544 +/** Remove entries satisfying a test from the bucket for the 12.545 + * given hashcode. 12.546 + * 12.547 + * @param table to remove from 12.548 + * @param hashcode indicates the bucket 12.549 + * @param test_fn test to apply to elements 12.550 + * @param arg first argument to calls to test_fn 12.551 + * @return number of entries removed 12.552 + */ 12.553 +inline int HashTable_remove_entry(HashTable *table, Hashcode hashcode, 12.554 + TableTestFn *test_fn, TableArg arg){ 12.555 + HTBucket *bucket; 12.556 + HTEntry *entry, *prev = 0, *next; 12.557 + int removed_count = 0; 12.558 + 12.559 + bucket = get_bucket(table, hashcode); 12.560 + for(entry = bucket->head; entry; entry = next){ 12.561 + next = entry->next; 12.562 + if(test_fn(arg, table, entry)){ 12.563 + if(prev){ 12.564 + prev->next = next; 12.565 + } else { 12.566 + bucket->head = next; 12.567 + } 12.568 + bucket->count--; 12.569 + table->entry_count--; 12.570 + removed_count++; 12.571 + HashTable_free_entry(table, entry); 12.572 + entry = 0; 12.573 + } 12.574 + prev = entry; 12.575 + } 12.576 + return removed_count; 12.577 +} 12.578 + 12.579 +/** Remove entries with a given key. 12.580 + * 12.581 + * @param table to remove from 12.582 + * @param key of entries to remove 12.583 + * @return number of entries removed 12.584 + */ 12.585 +inline int HashTable_remove(HashTable *table, void *key){ 12.586 +#if 1 12.587 + Hashcode hashcode; 12.588 + HTBucket *bucket; 12.589 + HTEntry *entry, *prev = 0, *next; 12.590 + int removed_count = 0; 12.591 + 12.592 + hashcode = HashTable_key_hash(table, key); 12.593 + bucket = get_bucket(table, hashcode); 12.594 + for(entry = bucket->head; entry; entry = next){ 12.595 + next = entry->next; 12.596 + if(HashTable_key_equal(table, key, entry->key)){ 12.597 + if(prev){ 12.598 + prev->next = next; 12.599 + } else { 12.600 + bucket->head = next; 12.601 + } 12.602 + bucket->count--; 12.603 + table->entry_count--; 12.604 + removed_count++; 12.605 + HashTable_free_entry(table, entry); 12.606 + entry = 0; 12.607 + } 12.608 + prev = entry; 12.609 + } 12.610 + return removed_count; 12.611 +#else 12.612 + return HashTable_remove_entry(table, HashTable_key_hash(table, key), 12.613 + has_key, (TableArg){ ptr: key}); 12.614 +#endif 12.615 +} 12.616 + 12.617 +/** Remove (and free) all the entries in a bucket. 12.618 + * 12.619 + * @param bucket to clear 12.620 + */ 12.621 +static inline void bucket_clear(HashTable *table, HTBucket *bucket){ 12.622 + HTEntry *entry, *next; 12.623 + 12.624 + for(entry = bucket->head; entry; entry = next){ 12.625 + next = entry->next; 12.626 + HashTable_free_entry(table, entry); 12.627 + } 12.628 + bucket->head = 0; 12.629 + table->entry_count -= bucket->count; 12.630 + bucket->count = 0; 12.631 +} 12.632 + 12.633 +/** Remove (and free) all the entries in a table. 12.634 + * 12.635 + * @param table to clear 12.636 + */ 12.637 +void HashTable_clear(HashTable *table){ 12.638 + int i, n = table->buckets_n; 12.639 + 12.640 + for(i=0; i<n; i++){ 12.641 + bucket_clear(table, table->buckets + i); 12.642 + } 12.643 +}
13.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 13.2 +++ b/tools/lib/hash_table.h Mon Jun 28 15:03:15 2004 +0000 13.3 @@ -0,0 +1,295 @@ 13.4 +/* $Id: hash_table.h,v 1.1 2004/03/30 16:21:26 mjw Exp $ */ 13.5 +/* 13.6 + * Copyright (C) 2001 - 2004 Mike Wray <mike.wray@hp.com> 13.7 + * 13.8 + * This library is free software; you can redistribute it and/or modify 13.9 + * it under the terms of the GNU Lesser General Public License as published by 13.10 + * the Free Software Foundation; either version 2.1 of the License, or 13.11 + * (at your option) any later version. 13.12 + * 13.13 + * This library is distributed in the hope that it will be useful, 13.14 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 13.15 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13.16 + * GNU Lesser General Public License for more details. 13.17 + * 13.18 + * You should have received a copy of the GNU Lesser General Public License 13.19 + * along with this library; if not, write to the Free Software 13.20 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 13.21 + */ 13.22 + 13.23 +#ifndef _XEN_LIB_HASH_TABLE_H_ 13.24 +#define _XEN_LIB_HASH_TABLE_H_ 13.25 + 13.26 +#include "iostream.h" 13.27 + 13.28 +typedef unsigned long Hashcode; 13.29 + 13.30 +/** Type used to pass parameters to table functions. */ 13.31 +typedef union TableArg { 13.32 + unsigned long ul; 13.33 + void *ptr; 13.34 +} TableArg; 13.35 + 13.36 +/** An entry in a bucket list. */ 13.37 +typedef struct HTEntry { 13.38 + /** Hashcode of the entry's key. */ 13.39 + Hashcode hashcode; 13.40 + /** Identifier for this entry in the table. */ 13.41 + int index; 13.42 + /** The key for this entry. */ 13.43 + void *key; 13.44 + /** The value in this entry. */ 13.45 + void *value; 13.46 + /** The next entry in the list. */ 13.47 + struct HTEntry *next; 13.48 +} HTEntry; 13.49 + 13.50 +/** A bucket in a rule table. */ 13.51 +typedef struct HTBucket { 13.52 + /** Number of entries in the bucket. */ 13.53 + int count; 13.54 + /** First entry in the bucket (may be null). */ 13.55 + HTEntry *head; 13.56 +} HTBucket; 13.57 + 13.58 +/** Default number of buckets in a hash table. 13.59 + * You want enough buckets so the lists in the buckets will typically be short. 13.60 + * It's a good idea if this is prime, since that will help to spread hashcodes 13.61 + * around the table. 13.62 + */ 13.63 +//#define HT_BUCKETS_N 1 13.64 +//#define HT_BUCKETS_N 3 13.65 +//#define HT_BUCKETS_N 7 13.66 +//#define HT_BUCKETS_N 17 13.67 +//#define HT_BUCKETS_N 97 13.68 +//#define HT_BUCKETS_N 211 13.69 +//#define HT_BUCKETS_N 401 13.70 +#define HT_BUCKETS_N 1021 13.71 + 13.72 +typedef struct HashTable HashTable; 13.73 + 13.74 +/** Type for a function used to select table entries. */ 13.75 +typedef int TableTestFn(TableArg arg, HashTable *table, HTEntry *entry); 13.76 + 13.77 +/** Type for a function to map over table entries. */ 13.78 +typedef int TableMapFn(TableArg arg, HashTable *table, HTEntry *entry); 13.79 + 13.80 +/** Type for a function to free table entries. */ 13.81 +typedef void TableFreeFn(HashTable *table, HTEntry *entry); 13.82 + 13.83 +/** Type for a function to hash table keys. */ 13.84 +typedef Hashcode TableHashFn(void *key); 13.85 + 13.86 +/** Type for a function to test table keys for equality. */ 13.87 +typedef int TableEqualFn(void *key1, void *key2); 13.88 + 13.89 +/** Type for a function to order table entries. */ 13.90 +typedef int TableOrderFn(HTEntry *e1, HTEntry *e2); 13.91 + 13.92 +/** General hash table. 13.93 + * A hash table with a list in each bucket. 13.94 + * Functions can be supplied for freeing entries, hashing keys, and comparing keys. 13.95 + * These all default to 0, when default behaviour treating keys as integers is used. 13.96 + */ 13.97 +struct HashTable { 13.98 + /** Flag indicating whether the table has been initialised. */ 13.99 + int init_done; 13.100 + /** Next value for the id field in inserted rules. */ 13.101 + unsigned long next_id; 13.102 + /** Number of buckets in the bucket array. */ 13.103 + int buckets_n; 13.104 + /** Array of buckets, each with its own list. */ 13.105 + HTBucket *buckets; 13.106 + /** Number of entries in the table. */ 13.107 + int entry_count; 13.108 + /** Function to free keys and values in entries. */ 13.109 + TableFreeFn *entry_free_fn; 13.110 + /** Function to hash keys. */ 13.111 + TableHashFn *key_hash_fn; 13.112 + /** Function to compare keys for equality. */ 13.113 + TableEqualFn *key_equal_fn; 13.114 + /** Place for the user of the table to hang extra data. */ 13.115 + void *user_data; 13.116 +}; 13.117 + 13.118 +extern HashTable *HashTable_new(int bucket_n); 13.119 +extern void HashTable_free(HashTable *table); 13.120 +extern HTEntry * HTEntry_new(Hashcode hashcode, void *key, void *value); 13.121 +extern void HTEntry_free(HTEntry *entry); 13.122 +extern int HashTable_set_bucket_n(HashTable *table, int bucket_n); 13.123 +extern void HashTable_clear(HashTable *table); 13.124 +extern HTEntry * HashTable_add_entry(HashTable *table, Hashcode hashcode, void *key, void *value); 13.125 +extern HTEntry * HashTable_get_entry(HashTable *table, void *key); 13.126 +extern HTEntry * HashTable_add(HashTable *table, void *key, void *value); 13.127 +extern void * HashTable_get(HashTable *table, void *key); 13.128 +extern int HashTable_remove(HashTable *table, void *key); 13.129 +extern HTEntry * HashTable_find_entry(HashTable *table, Hashcode hashcode, 13.130 + TableTestFn *test_fn, TableArg arg); 13.131 +extern int HashTable_remove_entry(HashTable *table, Hashcode hashcode, 13.132 + TableTestFn *test_fn, TableArg arg); 13.133 +//extern int HashTable_map(HashTable *table, TableMapFn *map_fn, TableArg arg); 13.134 +extern void HashTable_print(HashTable *table, IOStream *out); 13.135 +extern int HashTable_set_buckets_n(HashTable *table, int buckets_n); 13.136 +extern int HashTable_adjust(HashTable *table, int buckets_min); 13.137 +extern void pseudo_des(unsigned long *pleft, unsigned long *pright); 13.138 +extern Hashcode hash_string(char *s); 13.139 + 13.140 +extern int HashTable_order_bucket(HashTable *table, Hashcode hashcode, TableOrderFn *order); 13.141 + 13.142 +/** Control whether to use hashing based on DES or simple 13.143 + * hashing. DES hashing is `more random' but much more expensive. 13.144 + */ 13.145 +#define HASH_PSEUDO_DES 0 13.146 + 13.147 +/** Hash a long using a quick and dirty linear congruential random number generator. 13.148 + * See `Numerical Recipes in C', Chapter 7, "An Even Quicker Generator". 13.149 + * 13.150 + * @param a value to hash 13.151 + * @return hashed input 13.152 + */ 13.153 +static inline unsigned long lcrng_hash(unsigned long a){ 13.154 + return (1664525L * a + 1013904223L); 13.155 +} 13.156 + 13.157 +/** Hash an unsigned long. 13.158 + * 13.159 + * @param a input to hash 13.160 + * @return hashcode 13.161 + */ 13.162 +static inline Hashcode hash_ul(unsigned long a){ 13.163 +#if HASH_PSEUDO_DES 13.164 + unsigned long left = a; 13.165 + unsigned long right = 0L; 13.166 + pseudo_des(&left, &right); 13.167 + return right; 13.168 +#else 13.169 + a = lcrng_hash(a); 13.170 + a = lcrng_hash(a); 13.171 + return a; 13.172 +#endif 13.173 +} 13.174 + 13.175 +/** Hash two unsigned longs together. 13.176 + * 13.177 + * @param a input to hash 13.178 + * @param b input to hash 13.179 + * @return hashcode 13.180 + */ 13.181 +static inline Hashcode hash_2ul(unsigned long a, unsigned long b){ 13.182 +#if HASH_PSEUDO_DES 13.183 + unsigned long left = a; 13.184 + unsigned long right = b; 13.185 + pseudo_des(&left, &right); 13.186 + return right; 13.187 +#else 13.188 + a = lcrng_hash(a); 13.189 + a ^= b; 13.190 + a = lcrng_hash(a); 13.191 + return a; 13.192 +#endif 13.193 +} 13.194 + 13.195 +/** Hash a hashcode and an unsigned long together. 13.196 + * 13.197 + * @param a input hashcode 13.198 + * @param b input to hash 13.199 + * @return hashcode 13.200 + */ 13.201 +static inline Hashcode hash_hul(Hashcode a, unsigned long b){ 13.202 +#if HASH_PSEUDO_DES 13.203 + unsigned long left = a; 13.204 + unsigned long right = b; 13.205 + pseudo_des(&left, &right); 13.206 + return right; 13.207 +#else 13.208 + a ^= b; 13.209 + a = lcrng_hash(a); 13.210 + return a; 13.211 +#endif 13.212 +} 13.213 + 13.214 +/** Macro to declare variables for HashTable_for_each() to use. 13.215 + * 13.216 + * @param entry variable that is set to entries in the table 13.217 + */ 13.218 +#define HashTable_for_decl(entry) \ 13.219 + HashTable *_var_table; \ 13.220 + HTBucket *_var_bucket; \ 13.221 + HTBucket *_var_end; \ 13.222 + HTEntry *_var_next; \ 13.223 + HTEntry *entry 13.224 + 13.225 +/** Macro to iterate over the entries in a hashtable. 13.226 + * Must be in a scope where HashTable_for_decl() has been used to declare 13.227 + * variables for it to use. 13.228 + * The variable 'entry' is iterated over entries in the table. 13.229 + * The code produced is syntactically a loop, so it must be followed by 13.230 + * a loop body, typically some statements in braces: 13.231 + * HashTable_for_each(entry, table){ ...loop body... } 13.232 + * 13.233 + * HashTable_for_each() and HashTable_for_decl() cannot be used for nested 13.234 + * loops as variables will clash. 13.235 + * 13.236 + * @note The simplest way to code a direct loop over the entries in a hashtable 13.237 + * is to use a loop over the buckets, with a nested loop over the entries 13.238 + * in a bucket. Using this approach in a macro means the macro contains 13.239 + * an opening brace, and calls to it must be followed by 2 braces! 13.240 + * To avoid this the code has been restructured so that it is a for loop. 13.241 + * So that statements could be used in the test expression of the for loop, 13.242 + * we have used the gcc statement expression extension ({ ... }). 13.243 + * 13.244 + * @param entry variable to iterate over the entries 13.245 + * @param table to iterate over (non-null) 13.246 + */ 13.247 +#define HashTable_for_each(entry, table) \ 13.248 + _var_table = table; \ 13.249 + _var_bucket = _var_table->buckets; \ 13.250 + _var_end = _var_bucket + _var_table->buckets_n; \ 13.251 + for(entry=0, _var_next=0; \ 13.252 + ({ if(_var_next){ \ 13.253 + entry = _var_next; \ 13.254 + _var_next = entry->next; \ 13.255 + } else { \ 13.256 + while(_var_bucket < _var_end){ \ 13.257 + entry = _var_bucket->head; \ 13.258 + _var_bucket++; \ 13.259 + if(entry){ \ 13.260 + _var_next = entry->next; \ 13.261 + break; \ 13.262 + } \ 13.263 + } \ 13.264 + }; \ 13.265 + entry; }); \ 13.266 + entry = _var_next ) 13.267 + 13.268 +/** Map a function over the entries in a table. 13.269 + * Mapping stops when the function returns a non-zero value. 13.270 + * Uses the gcc statement expression extension ({ ... }). 13.271 + * 13.272 + * @param table to map over 13.273 + * @param fn function to apply to entries 13.274 + * @param arg first argument to call the function with 13.275 + * @return 0 if fn always returned 0, first non-zero value otherwise 13.276 + */ 13.277 +#define HashTable_map(table, fn, arg) \ 13.278 + ({ HashTable_for_decl(_var_entry); \ 13.279 + TableArg _var_arg = arg; \ 13.280 + int _var_value = 0; \ 13.281 + HashTable_for_each(_var_entry, table){ \ 13.282 + if((_var_value = fn(_var_arg, _var_table, _var_entry))) break; \ 13.283 + } \ 13.284 + _var_value; }) 13.285 + 13.286 +/** Cast x to the type for a key or value in a hash table. 13.287 + * This avoids compiler warnings when using short integers 13.288 + * as keys or values (especially on 64-bit platforms). 13.289 + */ 13.290 +#define HKEY(x) ((void*)(unsigned long)(x)) 13.291 + 13.292 +/** Cast x from the type for a key or value in a hash table. 13.293 + * to an unsigned long. This avoids compiler warnings when using 13.294 + * short integers as keys or values (especially on 64-bit platforms). 13.295 + */ 13.296 +#define HVAL(x) ((unsigned long)(x)) 13.297 + 13.298 +#endif /* !_XEN_LIB_HASH_TABLE_H_ */
14.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 14.2 +++ b/tools/lib/iostream.c Mon Jun 28 15:03:15 2004 +0000 14.3 @@ -0,0 +1,37 @@ 14.4 +#include "iostream.h" 14.5 +#include "sys_string.h" 14.6 + 14.7 +/** Print on a stream, like vfprintf(). 14.8 + * 14.9 + * @param stream to print to 14.10 + * @param format for the print (as fprintf()) 14.11 + * @param args arguments to print 14.12 + * @return result code from the print 14.13 + */ 14.14 +int IOStream_vprint(IOStream *stream, const char *format, va_list args){ 14.15 + char buffer[1024]; 14.16 + int k = sizeof(buffer), n; 14.17 + 14.18 + n = vsnprintf(buffer, k, (char*)format, args); 14.19 + if(n < 0 || n > k ){ 14.20 + n = k; 14.21 + } 14.22 + n = IOStream_write(stream, buffer, n); 14.23 + return n; 14.24 +} 14.25 + 14.26 +/** Print on a stream, like fprintf(). 14.27 + * 14.28 + * @param stream to print to 14.29 + * @param format for the print (as fprintf()) 14.30 + * @return result code from the print 14.31 + */ 14.32 +int IOStream_print(IOStream *stream, const char *format, ...){ 14.33 + va_list args; 14.34 + int result = -1; 14.35 + 14.36 + va_start(args, format); 14.37 + result = IOStream_vprint(stream, format, args); 14.38 + va_end(args); 14.39 + return result; 14.40 +}
15.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 15.2 +++ b/tools/lib/iostream.h Mon Jun 28 15:03:15 2004 +0000 15.3 @@ -0,0 +1,243 @@ 15.4 +#ifndef _XC_LINUX_SAVE_H_ 15.5 +#define _XC_LINUX_SAVE_H_ 15.6 + 15.7 +#include <stdarg.h> 15.8 +#include <stdint.h> 15.9 +#include <stddef.h> 15.10 + 15.11 +#ifdef __KERNEL__ 15.12 +#include <linux/errno.h> 15.13 +#else 15.14 +#include <errno.h> 15.15 +#endif 15.16 + 15.17 +#include "allocate.h" 15.18 + 15.19 +/** End of input return value. */ 15.20 +#define IOSTREAM_EOF -1 15.21 + 15.22 +/** An input/output abstraction. 15.23 + */ 15.24 +typedef struct IOStream IOStream; 15.25 + 15.26 +/** Record of the functions to use for operations on an 15.27 + * IOStream implementation. 15.28 + */ 15.29 +typedef struct IOMethods { 15.30 + /** Read function. Called with the user data, buffer to read into 15.31 + * and number of bytes to read. Must return number of bytes read 15.32 + * on success, less than zero on error. 15.33 + */ 15.34 + int (*read)(IOStream *stream, void *buf, size_t n); 15.35 + 15.36 + /** Write function. Called with user data, buffer to write and 15.37 + * number of bytes to write. Must return number of bytes written on 15.38 + * success, less than zero otherwise. 15.39 + */ 15.40 + int (*write)(IOStream *stream, const void *buf, size_t n); 15.41 + 15.42 + int (*flush)(IOStream *s); 15.43 + 15.44 + int (*error)(IOStream *s); 15.45 + 15.46 + int (*close)(IOStream *s); 15.47 + 15.48 + void (*free)(IOStream *s); 15.49 + 15.50 + void (*lock)(IOStream *s); 15.51 + void (*unlock)(IOStream *s); 15.52 + 15.53 +} IOMethods; 15.54 + 15.55 +/** Abstract i/o object. 15.56 + */ 15.57 +struct IOStream { 15.58 + /** Methods to use to implement operations. */ 15.59 + const IOMethods *methods; 15.60 + /** Private state for the implementation. */ 15.61 + const void *data; 15.62 + /** Flag indicating whether the stream is closed. */ 15.63 + int closed; 15.64 + /** Number of bytes written. */ 15.65 + int written; 15.66 + /** Number of bytes read. */ 15.67 + int read; 15.68 +}; 15.69 + 15.70 + 15.71 +/** IOStream version of stdin. */ 15.72 +extern IOStream *iostdin; 15.73 + 15.74 +/** IOStream version of stdout, */ 15.75 +extern IOStream *iostdout; 15.76 + 15.77 +/** IOStream version of stderr. */ 15.78 +extern IOStream *iostderr; 15.79 + 15.80 +extern int IOStream_print(IOStream *io, const char *format, ...); 15.81 +extern int IOStream_vprint(IOStream *io, const char *format, va_list args); 15.82 + 15.83 +/** Read from a stream. 15.84 + * 15.85 + * @param stream input 15.86 + * @param buf where to put input 15.87 + * @param n number of bytes to read 15.88 + * @return if ok, number of bytes read, otherwise negative error code 15.89 + */ 15.90 +static inline int IOStream_read(IOStream *stream, void *buf, size_t n){ 15.91 + int result = 0; 15.92 + if(stream->closed) goto exit; 15.93 + if(!stream->methods || !stream->methods->read){ 15.94 + result = -EINVAL; 15.95 + goto exit; 15.96 + } 15.97 + result = stream->methods->read(stream, buf, n); 15.98 + if(result > 0){ 15.99 + stream->read += result; 15.100 + } 15.101 + exit: 15.102 + return result; 15.103 +} 15.104 + 15.105 +/** Write to a stream. 15.106 + * 15.107 + * @param stream input 15.108 + * @param buf where to put input 15.109 + * @param n number of bytes to write 15.110 + * @return if ok, number of bytes read, otherwise negative error code 15.111 + */ 15.112 +static inline int IOStream_write(IOStream *stream, const void *buf, size_t n){ 15.113 + int result = 0; 15.114 + if(stream->closed) goto exit; 15.115 + if(!stream->methods || !stream->methods->write){ 15.116 + result = -EINVAL; 15.117 + goto exit; 15.118 + } 15.119 + result = stream->methods->write(stream, buf, n); 15.120 + if(result > 0){ 15.121 + stream->written += result; 15.122 + } 15.123 + exit: 15.124 + return result; 15.125 +} 15.126 + 15.127 +/** Flush the stream. 15.128 + * 15.129 + * @param stream stream 15.130 + * @return 0 on success, IOSTREAM_EOF otherwise 15.131 + */ 15.132 +static inline int IOStream_flush(IOStream *stream){ 15.133 + int result = 0; 15.134 + if(stream->closed){ 15.135 + result = IOSTREAM_EOF; 15.136 + } else if(stream->methods->flush){ 15.137 + result = stream->methods->flush(stream); 15.138 + if(result < 0) result = IOSTREAM_EOF; 15.139 + } 15.140 + return result; 15.141 +} 15.142 + 15.143 +/** Check whether the stream has an error. 15.144 + * 15.145 + * @param stream to check 15.146 + * @return 1 for error, 0 otherwise 15.147 + */ 15.148 +static inline int IOStream_error(IOStream *stream){ 15.149 + int err = 0; 15.150 + if(stream->methods && stream->methods->error){ 15.151 + err = stream->methods->error(stream); 15.152 + } 15.153 + return err; 15.154 +} 15.155 + 15.156 +/** Close the stream. 15.157 + * 15.158 + * @param stream to close 15.159 + * @return 1 for error, 0 otherwise 15.160 + */ 15.161 +static inline int IOStream_close(IOStream *stream){ 15.162 + int err = 1; 15.163 + if(stream->methods && stream->methods->close){ 15.164 + err = stream->methods->close(stream); 15.165 + } 15.166 + return err; 15.167 +} 15.168 + 15.169 +/** Test if the stream has been closed. 15.170 + * 15.171 + * @param stream to check 15.172 + * @return 1 if closed, 0 otherwise 15.173 + */ 15.174 +static inline int IOStream_is_closed(IOStream *stream){ 15.175 + return stream->closed; 15.176 +} 15.177 + 15.178 +/** Free the memory used by the stream. 15.179 + * 15.180 + * @param stream to free 15.181 + */ 15.182 +static inline void IOStream_free(IOStream *stream){ 15.183 + if(stream->methods && stream->methods->free){ 15.184 + stream->methods->free(stream); 15.185 + } 15.186 + *stream = (IOStream){}; 15.187 + deallocate(stream); 15.188 +} 15.189 + 15.190 + 15.191 +/** Print a character to a stream, like fputc(). 15.192 + * 15.193 + * @param stream to print to 15.194 + * @param c character to print 15.195 + * @return result code from the print 15.196 + */ 15.197 +static inline int IOStream_putc(IOStream *stream, int c){ 15.198 + int err; 15.199 + unsigned char b = (unsigned char)c; 15.200 + err = IOStream_write(stream, &b, 1); 15.201 + if(err < 1){ 15.202 + err = IOSTREAM_EOF; 15.203 + } else { 15.204 + err = b; 15.205 + } 15.206 + return err; 15.207 +} 15.208 + 15.209 +/** Read from a stream, like fgetc(). 15.210 + * 15.211 + * @param stream to read from 15.212 + * @return IOSTREAM_EOF on error, character read otherwise 15.213 + */ 15.214 +static inline int IOStream_getc(IOStream *stream){ 15.215 + int err, rc; 15.216 + unsigned char b; 15.217 + 15.218 + err = IOStream_read(stream, &b, 1); 15.219 + if(err < 1){ 15.220 + rc = IOSTREAM_EOF; 15.221 + } else { 15.222 + rc = b; 15.223 + } 15.224 + return rc; 15.225 +} 15.226 + 15.227 +/** Get number of bytes read. 15.228 + * 15.229 + * @param stream to get from 15.230 + * @return number of bytes read 15.231 + */ 15.232 +static inline int IOStream_get_read(IOStream *stream){ 15.233 + return stream->read; 15.234 +} 15.235 + 15.236 +/** Get number of bytes written. 15.237 + * 15.238 + * @param stream to get from 15.239 + * @return number of bytes written 15.240 + */ 15.241 +static inline int IOStream_get_written(IOStream *stream){ 15.242 + return stream->written; 15.243 +} 15.244 + 15.245 + 15.246 +#endif /* ! _XC_LINUX_SAVE_H_ */
16.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 16.2 +++ b/tools/lib/kernel_stream.c Mon Jun 28 15:03:15 2004 +0000 16.3 @@ -0,0 +1,177 @@ 16.4 +/* 16.5 + * Copyright (C) 2001 - 2004 Mike Wray <mike.wray@hp.com> 16.6 + * 16.7 + * This library is free software; you can redistribute it and/or modify 16.8 + * it under the terms of the GNU Lesser General Public License as published by 16.9 + * the Free Software Foundation; either version 2.1 of the License, or 16.10 + * (at your option) any later version. 16.11 + * 16.12 + * This library is distributed in the hope that it will be useful, 16.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 16.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16.15 + * GNU Lesser General Public License for more details. 16.16 + * 16.17 + * You should have received a copy of the GNU Lesser General Public License 16.18 + * along with this library; if not, write to the Free Software 16.19 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 16.20 + */ 16.21 + 16.22 +/** @file 16.23 + * An IOStream implementation using printk() for output. 16.24 + * Input is not implemented. 16.25 + */ 16.26 +#ifdef __KERNEL__ 16.27 + 16.28 +#include <linux/config.h> 16.29 +#include <linux/module.h> 16.30 +#include <linux/kernel.h> 16.31 +#include <linux/types.h> 16.32 +#include <linux/errno.h> 16.33 +#include <linux/slab.h> 16.34 +#include <linux/spinlock.h> 16.35 + 16.36 +#include "kernel_stream.h" 16.37 +#include "allocate.h" 16.38 + 16.39 +/** Number of characters in the output buffer. 16.40 + * The kernel uses 1024 for printk, so that should suffice. 16.41 + */ 16.42 +#define BUF_N 1024 16.43 + 16.44 +/** State for a kernel stream. */ 16.45 +typedef struct KernelData { 16.46 + /** Stream lock. We need a lock to serialize access to the stream. */ 16.47 + spinlock_t lock; 16.48 + /** Saved flags for locking. */ 16.49 + unsigned long flags; 16.50 + /** Size of the output buffer. */ 16.51 + int buf_n; 16.52 + /** Output buffer. */ 16.53 + char buf[BUF_N]; 16.54 +} KernelData; 16.55 + 16.56 +static int kernel_write(IOStream *s, const char *msg, int n); 16.57 +static void kernel_free(IOStream *s); 16.58 +static void kernel_stream_lock(IOStream *s); 16.59 +static void kernel_stream_unlock(IOStream *s); 16.60 + 16.61 +/** Methods for a kernel stream. Output only. */ 16.62 +static const IOMethods kernel_methods = { 16.63 + write: kernel_write, 16.64 + free: kernel_free, 16.65 + lock: kernel_stream_lock, 16.66 + unlock: kernel_stream_unlock, 16.67 +}; 16.68 + 16.69 +/** Shared state for kernel streams. 16.70 + * All implementations write using printk, so we can use 16.71 + * shared state and avoid allocating it. 16.72 + */ 16.73 +static const KernelData kernel_data = { 16.74 + lock: SPIN_LOCK_UNLOCKED, 16.75 + flags: 0, 16.76 + buf_n: BUF_N, 16.77 +}; 16.78 + 16.79 +/** Stream for kernel printk. */ 16.80 +static IOStream iokernel = { 16.81 + methods: &kernel_methods, 16.82 + data: &kernel_data, 16.83 +}; 16.84 + 16.85 +/** Stream for kernel printk. */ 16.86 +IOStream *iostdout = &iokernel; 16.87 + 16.88 +/** Stream for kernel printk. */ 16.89 +IOStream *iostdin = &iokernel; 16.90 + 16.91 +/** Stream for kernel printk. */ 16.92 +IOStream *iostderr = &iokernel; 16.93 + 16.94 +/** Get an output-only stream implementation using 16.95 + * printk(). The stream uses static storage, and must not be freed. 16.96 + * 16.97 + * @return kernel stream 16.98 + */ 16.99 +IOStream get_stream_kernel(void){ 16.100 + return iokernel; 16.101 +} 16.102 + 16.103 +/** Obtain the lock on the stream state. 16.104 + * 16.105 + * @param kdata stream state 16.106 + */ 16.107 +static inline void KernelData_lock(KernelData *kdata){ 16.108 + spin_lock_irqsave(&kdata->lock, kdata->flags); 16.109 +} 16.110 + 16.111 +/** Release the lock on the stream state. 16.112 + * 16.113 + * @param kdata stream state 16.114 + */ 16.115 +static inline void KernelData_unlock(KernelData *kdata){ 16.116 + spin_unlock_irqrestore(&kdata->lock, kdata->flags); 16.117 +} 16.118 + 16.119 +/** Get the stream state. 16.120 + * 16.121 + * @param s kernel stream 16.122 + * @return stream state 16.123 + */ 16.124 +static inline KernelData *get_kernel_data(IOStream *s){ 16.125 + return (KernelData*)s->data; 16.126 +} 16.127 + 16.128 +/** Obtain the lock on the stream state. 16.129 + * 16.130 + * @param s stream 16.131 + */ 16.132 +void kernel_stream_lock(IOStream *s){ 16.133 + KernelData_lock(get_kernel_data(s)); 16.134 +} 16.135 + 16.136 +/** Release the lock on the stream state. 16.137 + * 16.138 + * @param s stream 16.139 + */ 16.140 +void kernel_stream_unlock(IOStream *s){ 16.141 + KernelData_unlock(get_kernel_data(s)); 16.142 +} 16.143 + 16.144 +/** Write to a kernel stream. 16.145 + * 16.146 + * @param stream kernel stream 16.147 + * @param format print format 16.148 + * @param args print arguments 16.149 + * @return result of the print 16.150 + */ 16.151 +static int kernel_write(IOStream *stream, const char *buf, int n){ 16.152 + KernelData *kdata = get_kernel_data(stream); 16.153 + int k; 16.154 + k = kdata->buf_n - 1; 16.155 + if(n < k) k = n; 16.156 + memcpy(kdata->buf, buf, k); 16.157 + kdata->buf[k] = '\0' 16.158 + printk(kdata->buf); 16.159 + return k; 16.160 +} 16.161 + 16.162 +/** Free a kernel stream. 16.163 + * Frees the internal state of the stream. 16.164 + * Do not call this unless the stream was dynamically allocated. 16.165 + * Do not call this on a stream returned from get_stream_kernel(). 16.166 + * 16.167 + * @param io stream to free 16.168 + */ 16.169 +static void kernel_free(IOStream *io){ 16.170 + KernelData *kdata; 16.171 + if(io == &iokernel) return; 16.172 + kdata = get_kernel_data(io); 16.173 + zero(kdata, sizeof(*kdata)); 16.174 + deallocate(kdata); 16.175 +} 16.176 +#endif /* __KERNEL__ */ 16.177 + 16.178 + 16.179 + 16.180 +
17.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 17.2 +++ b/tools/lib/kernel_stream.h Mon Jun 28 15:03:15 2004 +0000 17.3 @@ -0,0 +1,29 @@ 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 +#ifndef _XEN_LIB_KERNEL_STREAM_H_ 17.23 +#define _XEN_LIB_KERNEL_STREAM_H_ 17.24 + 17.25 +#ifdef __KERNEL__ 17.26 +#include "iostream.h" 17.27 + 17.28 +extern IOStream get_stream_kernel(void); 17.29 +#define get_stream_stdout get_stream_kernel 17.30 + 17.31 +#endif /* __KERNEL__ */ 17.32 +#endif /* !_XEN_LIB_KERNEL_STREAM_H_ */
18.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 18.2 +++ b/tools/lib/lexis.c Mon Jun 28 15:03:15 2004 +0000 18.3 @@ -0,0 +1,93 @@ 18.4 +/* 18.5 + * 18.6 + * This library is free software; you can redistribute it and/or modify 18.7 + * it under the terms of the GNU Lesser General Public License as 18.8 + * published by the Free Software Foundation; either version 2.1 of the 18.9 + * License, or (at your option) any later version. This library is 18.10 + * distributed in the hope that it will be useful, but WITHOUT ANY 18.11 + * WARRANTY; without even the implied warranty of MERCHANTABILITY or 18.12 + * FITNESS FOR A PARTICULAR PURPOSE. 18.13 + * See the GNU Lesser General Public License for more details. 18.14 + * 18.15 + * You should have received a copy of the GNU Lesser General Public License 18.16 + * along with this library; if not, write to the Free Software Foundation, 18.17 + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 18.18 + */ 18.19 + 18.20 +/** @file 18.21 + * Lexical analysis. 18.22 + */ 18.23 + 18.24 +#include "sys_string.h" 18.25 +#include "lexis.h" 18.26 +#include <errno.h> 18.27 + 18.28 +/** Check if a value lies in a (closed) range. 18.29 + * 18.30 + * @param x value to test 18.31 + * @param lo low end of the range 18.32 + * @param hi high end of the range 18.33 + * @return 1 if x is in the interval [lo, hi], 0 otherwise 18.34 + */ 18.35 +inline static int in_range(int x, int lo, int hi){ 18.36 + return (lo <= x) && (x <= hi); 18.37 +} 18.38 + 18.39 +/** Determine if a string is an (unsigned) decimal number. 18.40 + * 18.41 + * @param s pointer to characters to test 18.42 + * @param n length of string 18.43 + * @return 1 if s is a decimal number, 0 otherwise. 18.44 + */ 18.45 +int is_decimal_number(const char *s, int n){ 18.46 + int i; 18.47 + if(n <= 0)return 0; 18.48 + for(i = 0; i < n; i++){ 18.49 + if(!in_decimal_digit_class(s[i])) return 0; 18.50 + } 18.51 + return 1; 18.52 +} 18.53 + 18.54 +/** Determine if a string is a hex number. 18.55 + * Hex numbers are 0, or start with 0x or 0X followed 18.56 + * by a non-zero number of hex digits (0-9,a-f,A-F). 18.57 + * 18.58 + * @param s pointer to characters to test 18.59 + * @param n length of string 18.60 + * @return 1 if s is a hex number, 0 otherwise. 18.61 + */ 18.62 +int is_hex_number(const char *s, int n){ 18.63 + int i; 18.64 + if(n <= 0) return 0; 18.65 + if(n == 1){ 18.66 + return s[0]=='0'; 18.67 + } 18.68 + if(n <= 3) return 0; 18.69 + if(s[0] != '0' || (s[1] != 'x' && s[1] != 'X')) return 0; 18.70 + for(i = 2; i < n; i++){ 18.71 + if(!in_hex_digit_class(s[i])) return 0; 18.72 + } 18.73 + return 1; 18.74 +} 18.75 + 18.76 +/** Test if a string matches a keyword. 18.77 + * The comparison is case-insensitive. 18.78 + * The comparison fails if either argument is null. 18.79 + * 18.80 + * @param s string 18.81 + * @param k keyword 18.82 + * @return 1 if they match, 0 otherwise 18.83 + */ 18.84 +int is_keyword(const char *s, const char *k){ 18.85 + return s && k && !strcasecmp(s, k); 18.86 +} 18.87 + 18.88 +/** Test if a string matches a character. 18.89 + * 18.90 + * @param s string 18.91 + * @param c character (non-null) 18.92 + * @return 1 if s contains exactly c, 0 otherwise 18.93 + */ 18.94 +int is_keychar(const char *s, char c){ 18.95 + return c && (s[0] == c) && !s[1]; 18.96 +}
19.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 19.2 +++ b/tools/lib/lexis.h Mon Jun 28 15:03:15 2004 +0000 19.3 @@ -0,0 +1,122 @@ 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 +#ifndef _SP_LEXIS_H_ 19.21 +#define _SP_LEXIS_H_ 19.22 + 19.23 +#include "sys_string.h" 19.24 +#include "sys_ctype.h" 19.25 + 19.26 +/** @file 19.27 + * Lexical analysis. 19.28 + */ 19.29 + 19.30 +/** Class of characters treated as space. */ 19.31 +#define space_class ((char []){ '\n', '\r', '\t', ' ', '\f' , 0 }) 19.32 + 19.33 +/** Class of separator characters. */ 19.34 +#define sep_class "{}()<>[]@!;" 19.35 + 19.36 +#define comment_class "#" 19.37 + 19.38 +/** Determine if a character is in a given class. 19.39 + * 19.40 + * @param c character to test 19.41 + * @param s null-terminated string of characters in the class 19.42 + * @return 1 if c is in the class, 0 otherwise. 19.43 + */ 19.44 +static inline int in_class(int c, const char *s){ 19.45 + return s && (strchr(s, c) != 0); 19.46 +} 19.47 + 19.48 +/** Determine if a character is in the space class. 19.49 + * 19.50 + * @param c character to test 19.51 + * @return 1 if c is in the class, 0 otherwise. 19.52 + */ 19.53 +static inline int in_space_class(int c){ 19.54 + return in_class(c, space_class); 19.55 +} 19.56 + 19.57 +static inline int in_comment_class(int c){ 19.58 + return in_class(c, comment_class); 19.59 +} 19.60 + 19.61 +/** Determine if a character is in the separator class. 19.62 + * Separator characters terminate tokens, and do not need space 19.63 + * to separate them. 19.64 + * 19.65 + * @param c character to test 19.66 + * @return 1 if c is in the class, 0 otherwise. 19.67 + */ 19.68 +static inline int in_sep_class(int c){ 19.69 + return in_class(c, sep_class); 19.70 +} 19.71 + 19.72 +/** Determine if a character is in the alpha class. 19.73 + * 19.74 + * @param c character to test 19.75 + * @return 1 if c is in the class, 0 otherwise. 19.76 + */ 19.77 +static inline int in_alpha_class(int c){ 19.78 + return isalpha(c); 19.79 +} 19.80 + 19.81 +/** Determine if a character is in the octal digit class. 19.82 + * 19.83 + * @param c character to test 19.84 + * @return 1 if c is in the class, 0 otherwise. 19.85 + */ 19.86 +static inline int in_octal_digit_class(int c){ 19.87 + return '0' <= c && c <= '7'; 19.88 +} 19.89 + 19.90 +/** Determine if a character is in the decimal digit class. 19.91 + * 19.92 + * @param c character to test 19.93 + * @return 1 if c is in the class, 0 otherwise. 19.94 + */ 19.95 +static inline int in_decimal_digit_class(int c){ 19.96 + return isdigit(c); 19.97 +} 19.98 + 19.99 +/** Determine if a character is in the hex digit class. 19.100 + * 19.101 + * @param c character to test 19.102 + * @return 1 if c is in the class, 0 otherwise. 19.103 + */ 19.104 +static inline int in_hex_digit_class(int c){ 19.105 + return isdigit(c) || in_class(c, "abcdefABCDEF"); 19.106 +} 19.107 + 19.108 + 19.109 +static inline int in_string_quote_class(int c){ 19.110 + return in_class(c, "'\""); 19.111 +} 19.112 + 19.113 +static inline int in_printable_class(int c){ 19.114 + return ('A' <= c && c <= 'Z') 19.115 + || ('a' <= c && c <= 'z') 19.116 + || ('0' <= c && c <= '9') 19.117 + || in_class(c, "!$%&*+,-./:;<=>?@^_`{|}~"); 19.118 +} 19.119 + 19.120 +extern int is_decimal_number(const char *s, int n); 19.121 +extern int is_hex_number(const char *s, int n); 19.122 +extern int is_keyword(const char *s, const char *k); 19.123 +extern int is_keychar(const char *s, char c); 19.124 + 19.125 +#endif /* !_SP_LEXIS_H_ */
20.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 20.2 +++ b/tools/lib/lzi_stream.c Mon Jun 28 15:03:15 2004 +0000 20.3 @@ -0,0 +1,590 @@ 20.4 +/* $Id: lzi_stream.c,v 1.4 2003/09/30 15:22:53 mjw Exp $ */ 20.5 +#define __FILE_ID_INFO "$Id: lzi_stream.c,v 1.4 2003/09/30 15:22:53 mjw Exp $" 20.6 +#include <what.h> 20.7 +static char __rcsid[] __attribute__((unused)) = WHAT_ID __FILE_ID_INFO; 20.8 +/* 20.9 + * Copyright (C) 2003 Hewlett-Packard Company. 20.10 + * 20.11 + * This library is free software; you can redistribute it and/or modify 20.12 + * it under the terms of the GNU Lesser General Public License as published by 20.13 + * the Free Software Foundation; either version 2.1 of the License, or 20.14 + * (at your option) any later version. 20.15 + * 20.16 + * This library is distributed in the hope that it will be useful, 20.17 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 20.18 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 20.19 + * GNU Lesser General Public License for more details. 20.20 + * 20.21 + * You should have received a copy of the GNU Lesser General Public License 20.22 + * along with this library; if not, write to the Free Software 20.23 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 20.24 + */ 20.25 + 20.26 +/** @file 20.27 + * An IOStream implementation using LZI to provide compression and decompression. 20.28 + * This is designed to provide compression without output latency. 20.29 + * Flushing an LZI stream flushes all pending data to the underlying stream. 20.30 + * This is essential for stream-based (e.g. networked) applications. 20.31 + * 20.32 + * A compressed data stream is a sequence of blocks. 20.33 + * Each block is the block size followed by the compressed data. 20.34 + * The last block has size zero. 20.35 + * Sizes are 4-byte unsigned in network order. 20.36 + * 20.37 + * This format allows compressed data to be read from a stream without reading 20.38 + * past the logical end of compressed data. 20.39 + * 20.40 + * @author Mike Wray <mike.wray@hpl.hp.com> 20.41 + */ 20.42 +#ifndef __KERNEL__ 20.43 + 20.44 +#include <stdio.h> 20.45 +#include <stdlib.h> 20.46 +#include <errno.h> 20.47 +#include <string.h> 20.48 + 20.49 +#include "zlib.h" 20.50 + 20.51 +#include "allocate.h" 20.52 +#include "lzi_stream.h" 20.53 +#include "file_stream.h" 20.54 +#include "marshal.h" 20.55 + 20.56 +#define dprintf(fmt, args...) fprintf(stdout, "[DEBUG] LZI>%s" fmt, __FUNCTION__, ##args) 20.57 +#define wprintf(fmt, args...) fprintf(stderr, "[WARN] LZI>%s" fmt, __FUNCTION__, ##args) 20.58 +#define iprintf(fmt, args...) fprintf(stdout, "[INFO] LZI>%s" fmt, __FUNCTION__, ##args) 20.59 +#define eprintf(fmt, args...) fprintf(stderr, "[ERROR] LZI>%s" fmt, __FUNCTION__, ##args) 20.60 + 20.61 +static int lzi_read(IOStream *s, void *buf, size_t size, size_t count); 20.62 +static int lzi_write(IOStream *s, const void *buf, size_t size, size_t count); 20.63 +static int lzi_print(IOStream *s, const char *msg, va_list args); 20.64 +static int lzi_getc(IOStream *s); 20.65 +static int lzi_error(IOStream *s); 20.66 +static int lzi_close(IOStream *s); 20.67 +static void lzi_free(IOStream *s); 20.68 +static int lzi_flush(IOStream *s); 20.69 + 20.70 +enum { 20.71 + LZI_WRITE = 1, 20.72 + LZI_READ = 2, 20.73 +}; 20.74 + 20.75 +/** Methods used by a gzFile* IOStream. */ 20.76 +static const IOMethods lzi_methods = { 20.77 + read: lzi_read, 20.78 + write: lzi_write, 20.79 + print: lzi_print, 20.80 + getc: lzi_getc, 20.81 + error: lzi_error, 20.82 + close: lzi_close, 20.83 + free: lzi_free, 20.84 + flush: lzi_flush, 20.85 +}; 20.86 + 20.87 +#define BUFFER_SIZE (512 * 1024) 20.88 + 20.89 +typedef struct LZIState { 20.90 + z_stream zstream; 20.91 + void *inbuf; 20.92 + uint32_t inbuf_size; 20.93 + void *outbuf; 20.94 + uint32_t outbuf_size; 20.95 + /** Underlying stream for I/O. */ 20.96 + IOStream *io; 20.97 + /** Flags. */ 20.98 + int flags; 20.99 + /** Error indicator. */ 20.100 + int error; 20.101 + int eof; 20.102 + int plain_bytes; 20.103 + int comp_bytes; 20.104 + int zstream_initialized; 20.105 + int flushed; 20.106 +} LZIState; 20.107 + 20.108 +static inline int LZIState_writeable(LZIState *s){ 20.109 + return (s->flags & LZI_WRITE) != 0; 20.110 +} 20.111 + 20.112 +static inline int LZIState_readable(LZIState *s){ 20.113 + return (s->flags & LZI_READ) != 0; 20.114 +} 20.115 + 20.116 +void LZIState_free(LZIState *z){ 20.117 + if(!z) return; 20.118 + if(z->zstream_initialized){ 20.119 + if(LZIState_writeable(z)){ 20.120 + deflateEnd(&z->zstream); 20.121 + } else if(LZIState_readable(z)){ 20.122 + inflateEnd(&z->zstream); 20.123 + } 20.124 + } 20.125 + deallocate(z->inbuf); 20.126 + deallocate(z->outbuf); 20.127 + deallocate(z); 20.128 +} 20.129 + 20.130 +static int mode_flags(const char *mode, int *flags){ 20.131 + int err = 0; 20.132 + int r=0, w=0; 20.133 + if(!mode){ 20.134 + err = -EINVAL; 20.135 + goto exit; 20.136 + } 20.137 + for(; *mode; mode++){ 20.138 + if(*mode == 'w') w = 1; 20.139 + if(*mode == 'r') r = 1; 20.140 + } 20.141 + if(r + w != 1){ 20.142 + err = -EINVAL; 20.143 + goto exit; 20.144 + } 20.145 + if(r) *flags |= LZI_READ; 20.146 + if(w) *flags |= LZI_WRITE; 20.147 + exit: 20.148 + return err; 20.149 +} 20.150 + 20.151 +/** Get the stream state. 20.152 + * 20.153 + * @param s lzi stream 20.154 + * @return stream state. 20.155 + */ 20.156 +static inline LZIState * lzi_state(IOStream *io){ 20.157 + return io->data; 20.158 +} 20.159 + 20.160 +IOStream *lzi_stream_io(IOStream *io){ 20.161 + LZIState *s = lzi_state(io); 20.162 + return s->io; 20.163 +} 20.164 + 20.165 +static inline void set_error(LZIState *s, int err){ 20.166 + if(err < 0 && !s->error){ 20.167 + s->error = err; 20.168 + } 20.169 +} 20.170 + 20.171 +static int zerror(LZIState *s, int err){ 20.172 + if(err){ 20.173 + //dprintf("> err=%d\n", err); 20.174 + if(err < 0) set_error(s, -EIO); 20.175 + } 20.176 + return s->error; 20.177 +} 20.178 + 20.179 +int lzi_stream_plain_bytes(IOStream *io){ 20.180 + LZIState *s = lzi_state(io); 20.181 + return s->plain_bytes; 20.182 +} 20.183 + 20.184 +int lzi_stream_comp_bytes(IOStream *io){ 20.185 + LZIState *s = lzi_state(io); 20.186 + return s->comp_bytes; 20.187 +} 20.188 + 20.189 +float lzi_stream_ratio(IOStream *io){ 20.190 + LZIState *s = lzi_state(io); 20.191 + float ratio = 0.0; 20.192 + if(s->comp_bytes){ 20.193 + ratio = ((float) s->comp_bytes)/((float) s->plain_bytes); 20.194 + } 20.195 + return ratio; 20.196 +} 20.197 + 20.198 +static int alloc(void **p, int n){ 20.199 + *p = allocate(n); 20.200 + return (p ? 0 : -ENOMEM); 20.201 +} 20.202 + 20.203 +LZIState * LZIState_new(IOStream *io, int flags){ 20.204 + int err = -ENOMEM; 20.205 + int zlevel = Z_BEST_SPEED; // Level 1 compression - fastest. 20.206 + int zstrategy = Z_DEFAULT_STRATEGY; 20.207 + int zwindow = MAX_WBITS; 20.208 + int zmemory = 8; 20.209 + LZIState *z = ALLOCATE(LZIState); 20.210 + 20.211 + //dprintf(">\n"); 20.212 + if(!z) goto exit; 20.213 + z->io = io; 20.214 + z->flags = flags; 20.215 + 20.216 + if(LZIState_writeable(z)){ 20.217 + z->outbuf_size = BUFFER_SIZE; 20.218 + /* windowBits is passed < 0 to suppress zlib header */ 20.219 + err = deflateInit2(&z->zstream, zlevel, Z_DEFLATED, -zwindow, zmemory, zstrategy); 20.220 + if (err != Z_OK) goto exit; 20.221 + z->zstream_initialized = 1; 20.222 + err = alloc(&z->outbuf, z->outbuf_size); 20.223 + if(err) goto exit; 20.224 + z->zstream.next_out = z->outbuf; 20.225 + z->zstream.avail_out = z->outbuf_size; 20.226 + } else { 20.227 + z->inbuf_size = BUFFER_SIZE; 20.228 + err = alloc(&z->inbuf, z->inbuf_size); 20.229 + if(err) goto exit; 20.230 + ///z->zstream.next_in = z->inbuf; 20.231 + 20.232 + /* windowBits is passed < 0 to tell that there is no zlib header. 20.233 + * Note that in this case inflate *requires* an extra "dummy" byte 20.234 + * after the compressed stream in order to complete decompression and 20.235 + * return Z_STREAM_END. Here the gzip CRC32 ensures that 4 bytes are 20.236 + * present after the compressed stream. 20.237 + */ 20.238 + err = inflateInit2(&z->zstream, -zwindow); 20.239 + if(err != Z_OK) goto exit; 20.240 + z->zstream_initialized = 1; 20.241 + } 20.242 + 20.243 + exit: 20.244 + if(err){ 20.245 + LZIState_free(z); 20.246 + z = NULL; 20.247 + } 20.248 + //dprintf("< z=%p\n", z); 20.249 + return z; 20.250 +} 20.251 + 20.252 +int read_block(LZIState *s){ 20.253 + int err = 0, k = 0; 20.254 + //dprintf(">\n"); 20.255 + if(s->eof) goto exit; 20.256 + err = unmarshal_uint32(s->io, &k); 20.257 + if(err) goto exit; 20.258 + if(k > s->inbuf_size){ 20.259 + err = -EINVAL; 20.260 + goto exit; 20.261 + } 20.262 + if(k){ 20.263 + err = unmarshal_bytes(s->io, s->inbuf, k); 20.264 + if(err) goto exit; 20.265 + } else { 20.266 + s->eof = 1; 20.267 + } 20.268 + s->zstream.avail_in = k; 20.269 + s->zstream.next_in = s->inbuf; 20.270 + s->comp_bytes += 4; 20.271 + s->comp_bytes += k; 20.272 + exit: 20.273 + //dprintf("< err=%d\n", err); 20.274 + return err; 20.275 +} 20.276 + 20.277 +int write_block(LZIState *s){ 20.278 + int err = 0; 20.279 + int k = ((char*)s->zstream.next_out) - ((char*)s->outbuf); 20.280 + int k2 = s->outbuf_size - s->zstream.avail_out; 20.281 + //dprintf("> k=%d k2=%d\n", k, k2); 20.282 + if(!k) goto exit; 20.283 + err = marshal_uint32(s->io, k); 20.284 + if(err) goto exit; 20.285 + err = marshal_bytes(s->io, s->outbuf, k); 20.286 + if(err) goto exit; 20.287 + s->zstream.next_out = s->outbuf; 20.288 + s->zstream.avail_out = s->outbuf_size; 20.289 + s->comp_bytes += 4; 20.290 + s->comp_bytes += k; 20.291 + exit: 20.292 + //dprintf("< err=%d\n", err); 20.293 + return err; 20.294 +} 20.295 + 20.296 +int write_terminator(LZIState *s){ 20.297 + int err = 0; 20.298 + char c = 0; 20.299 + err = marshal_uint32(s->io, 1); 20.300 + if(err) goto exit; 20.301 + err = marshal_bytes(s->io, &c, 1); 20.302 + if(err) goto exit; 20.303 + err = marshal_uint32(s->io, 0); 20.304 + if(err) goto exit; 20.305 + s->comp_bytes += 9; 20.306 + exit: 20.307 + return err; 20.308 +} 20.309 + 20.310 +/** Write to the underlying stream using fwrite(); 20.311 + * 20.312 + * @param io destination 20.313 + * @param buf data 20.314 + * @param size size of data elements 20.315 + * @param count number of data elements to write 20.316 + * @return number of data elements written 20.317 + */ 20.318 +static int lzi_write(IOStream *io, const void *buf, size_t size, size_t count){ 20.319 + int err = 0; 20.320 + int n = size * count; 20.321 + LZIState *s = lzi_state(io); 20.322 + 20.323 + //dprintf("> buf=%p size=%d count=%d n=%d\n", buf, size, count, n); 20.324 + if(!LZIState_writeable(s)){ 20.325 + err = -EINVAL; 20.326 + goto exit; 20.327 + } 20.328 + s->flushed = 0; 20.329 + s->zstream.next_in = (void*)buf; 20.330 + s->zstream.avail_in = n; 20.331 + while(s->zstream.avail_in){ 20.332 + if(s->zstream.avail_out == 0){ 20.333 + err = write_block(s); 20.334 + if(err) goto exit; 20.335 + } 20.336 + //dprintf("> 1 deflate avail_in=%d avail_out=%d\n", s->zstream.avail_in, s->zstream.avail_out); 20.337 + //dprintf("> 1 deflate next_in=%p next_out=%p\n", s->zstream.next_in, s->zstream.next_out); 20.338 + err = zerror(s, deflate(&s->zstream, Z_NO_FLUSH)); 20.339 + //dprintf("> 2 deflate avail_in=%d avail_out=%d\n", s->zstream.avail_in, s->zstream.avail_out); 20.340 + //dprintf("> 2 deflate next_in=%p next_out=%p\n", s->zstream.next_in, s->zstream.next_out); 20.341 + if(err) goto exit; 20.342 + } 20.343 + err = n; 20.344 + s->plain_bytes += n; 20.345 + if(size != 1) err /= size; 20.346 + exit: 20.347 + //dprintf("< err=%d\n", err); 20.348 + return err; 20.349 +} 20.350 + 20.351 + 20.352 +/** Read from the underlying stream. 20.353 + * 20.354 + * @param io input 20.355 + * @param buf where to put input 20.356 + * @param size size of data elements 20.357 + * @param count number of data elements to read 20.358 + * @return number of data elements read 20.359 + */ 20.360 +static int lzi_read(IOStream *io, void *buf, size_t size, size_t count){ 20.361 + int err, zerr; 20.362 + int n = size * count; 20.363 + LZIState *s = lzi_state(io); 20.364 + 20.365 + //dprintf("> size=%d count=%d n=%d\n", size, count, n); 20.366 + if(!LZIState_readable(s)){ 20.367 + err = -EINVAL; 20.368 + goto exit; 20.369 + } 20.370 + s->zstream.next_out = buf; 20.371 + s->zstream.avail_out = n; 20.372 + while(s->zstream.avail_out){ 20.373 + if(s->zstream.avail_in == 0){ 20.374 + err = read_block(s); 20.375 + } 20.376 + //dprintf("> 1 deflate avail_in=%d avail_out=%d\n", s->zstream.avail_in, s->zstream.avail_out); 20.377 + zerr = inflate(&s->zstream, Z_NO_FLUSH); 20.378 + //dprintf("> 2 deflate avail_in=%d avail_out=%d\n", s->zstream.avail_in, s->zstream.avail_out); 20.379 + if(zerr == Z_STREAM_END) break; 20.380 + //dprintf("> zerr=%d\n", zerr); 20.381 + err = zerror(s, zerr); 20.382 + if(err) goto exit; 20.383 + } 20.384 + err = n - s->zstream.avail_out; 20.385 + s->plain_bytes += err; 20.386 + if(size != 1) err /= size; 20.387 + exit: 20.388 + set_error(s, err); 20.389 + //dprintf("< err=%d\n", err); 20.390 + return err; 20.391 +} 20.392 + 20.393 +/** Print to the underlying stream. 20.394 + * Returns 0 if the formatted output is too big for the internal buffer. 20.395 + * 20.396 + * @param io lzi stream 20.397 + * @param msg format to use 20.398 + * @param args arguments 20.399 + * @return result of the print 20.400 + */ 20.401 +static int lzi_print(IOStream *io, const char *msg, va_list args){ 20.402 + char buf[1024]; 20.403 + int buf_n = sizeof(buf); 20.404 + int n; 20.405 + LZIState *s = lzi_state(io); 20.406 + if(!LZIState_writeable(s)){ 20.407 + n = -EINVAL; 20.408 + goto exit; 20.409 + } 20.410 + n = vsnprintf(buf, buf_n, (char*)msg, args); 20.411 + if(n < 0) goto exit; 20.412 + if(n > buf_n){ 20.413 + n = 0; 20.414 + } else { 20.415 + n = lzi_write(io, buf, 1, n); 20.416 + } 20.417 + exit: 20.418 + return n; 20.419 +} 20.420 + 20.421 +/** Read a character from the underlying stream 20.422 + * 20.423 + * @param io lzi stream 20.424 + * @return character read, IOSTREAM_EOF on end of file (or error) 20.425 + */ 20.426 +static int lzi_getc(IOStream *io){ 20.427 + int err; 20.428 + char c; 20.429 + err = lzi_read(io, &c, 1, 1); 20.430 + if(err < 1) c = EOF; 20.431 + err = (c==EOF ? IOSTREAM_EOF : c); 20.432 + return err; 20.433 +} 20.434 + 20.435 +static int flush_output(LZIState *s, int mode){ 20.436 + int err = 0, zerr; 20.437 + int done = 0; 20.438 + int avail_out_old; 20.439 + int count = 10; 20.440 + 20.441 + //dprintf("> avail_in=%d avail_out=%d\n", s->zstream.avail_in, s->zstream.avail_out); 20.442 + if(s->flushed == 1 + mode) goto exit; 20.443 + //s->zstream.avail_in = 0; /* should be zero already anyway */ 20.444 + for(;;){ 20.445 + // Write any available output. 20.446 + if(done || s->zstream.avail_out == 0){ 20.447 + err = write_block(s); 20.448 + if(err) goto exit; 20.449 + if(done) break; 20.450 + } 20.451 + //dprintf("> 1 deflate avail_in=%d avail_out=%d\n", s->zstream.avail_in, s->zstream.avail_out); 20.452 + avail_out_old = s->zstream.avail_out; 20.453 + zerr = deflate(&s->zstream, mode); 20.454 + err = zerror(s, zerr); 20.455 + //dprintf("> 2 deflate avail_in=%d avail_out=%d\n", s->zstream.avail_in, s->zstream.avail_out); 20.456 + //dprintf("> deflate=%d\n", err); 20.457 + //done = (s->zstream.avail_out != 0); 20.458 + //done = (s->zstream.avail_in == 0) && (s->zstream.avail_out == avail_out_old); 20.459 + if(0 && mode == Z_FINISH){ 20.460 + done = (zerr == Z_STREAM_END); 20.461 + } else { 20.462 + done = (s->zstream.avail_in == 0) 20.463 + //&& (s->zstream.avail_out == avail_out_old) 20.464 + && (s->zstream.avail_out != 0); 20.465 + } 20.466 + } 20.467 + s->flushed = 1 + mode; 20.468 + exit: 20.469 + //dprintf("< err=%d\n", err); 20.470 + return err; 20.471 +} 20.472 + 20.473 +/** Flush any pending input to the underlying stream. 20.474 + * 20.475 + * @param s lzi stream 20.476 + * @return 0 on success, error code otherwise 20.477 + */ 20.478 +static int lzi_flush(IOStream *io){ 20.479 + int err = 0; 20.480 + LZIState *s = lzi_state(io); 20.481 + //dprintf(">\n"); 20.482 + if(!LZIState_writeable(s)){ 20.483 + err = -EINVAL; 20.484 + goto exit; 20.485 + } 20.486 + err = flush_output(s, Z_SYNC_FLUSH); 20.487 + if(err) goto exit; 20.488 + err = IOStream_flush(s->io); 20.489 + exit: 20.490 + set_error(s, err); 20.491 + //dprintf("< err=%d\n", err); 20.492 + return (err < 0 ? err : 0); 20.493 +} 20.494 + 20.495 +/** Check if a stream has an error. 20.496 + * 20.497 + * @param s lzi stream 20.498 + * @return code if has an error, 0 otherwise 20.499 + */ 20.500 +static int lzi_error(IOStream *s){ 20.501 + int err = 0; 20.502 + LZIState *state = lzi_state(s); 20.503 + err = state->error; 20.504 + if(err) goto exit; 20.505 + err = IOStream_error(state->io); 20.506 + exit: 20.507 + return err; 20.508 +} 20.509 + 20.510 +/** Close an lzi stream. 20.511 + * 20.512 + * @param s lzi stream to close 20.513 + * @return result of the close 20.514 + */ 20.515 +static int lzi_close(IOStream *io){ 20.516 + int err = 0; 20.517 + LZIState *s = lzi_state(io); 20.518 + if(LZIState_writeable(s)){ 20.519 + err = flush_output(s, Z_FINISH); 20.520 + if(err) goto exit; 20.521 + err = write_terminator(s); 20.522 + if(err) goto exit; 20.523 + err = IOStream_flush(s->io); 20.524 + } 20.525 + exit: 20.526 + err = IOStream_close(s->io); 20.527 + set_error(s, err); 20.528 + return err; 20.529 +} 20.530 + 20.531 +/** Free an lzi stream. 20.532 + * 20.533 + * @param s lzi stream 20.534 + */ 20.535 +static void lzi_free(IOStream *s){ 20.536 + LZIState *state = lzi_state(s); 20.537 + IOStream_free(state->io); 20.538 + LZIState_free(state); 20.539 + s->data = NULL; 20.540 +} 20.541 + 20.542 +/** Create an lzi stream for an IOStream. 20.543 + * 20.544 + * @param io stream to wrap 20.545 + * @return new IOStream using f for i/o 20.546 + */ 20.547 +IOStream *lzi_stream_new(IOStream *io, const char *mode){ 20.548 + int err = -ENOMEM; 20.549 + int flags = 0; 20.550 + IOStream *zio = NULL; 20.551 + LZIState *state = NULL; 20.552 + 20.553 + zio = ALLOCATE(IOStream); 20.554 + if(!zio) goto exit; 20.555 + err = mode_flags(mode, &flags); 20.556 + if(err) goto exit; 20.557 + state = LZIState_new(io, flags); 20.558 + if(!state) goto exit; 20.559 + err = 0; 20.560 + zio->data = state; 20.561 + zio->methods = &lzi_methods; 20.562 + exit: 20.563 + if(err){ 20.564 + if(state) LZIState_free(state); 20.565 + if(zio) deallocate(zio); 20.566 + zio = NULL; 20.567 + } 20.568 + return zio; 20.569 +} 20.570 + 20.571 +/** IOStream version of fdopen(). 20.572 + * 20.573 + * @param fd file descriptor 20.574 + * @param flags giving the mode to open in (as for fdopen()) 20.575 + * @return new stream for the open file, or NULL if failed 20.576 + */ 20.577 +IOStream *lzi_stream_fdopen(int fd, const char *mode){ 20.578 + int err = -ENOMEM; 20.579 + IOStream *io = NULL, *zio = NULL; 20.580 + io = file_stream_fdopen(fd, mode); 20.581 + if(!io) goto exit; 20.582 + zio = lzi_stream_new(io, mode); 20.583 + if(!io) goto exit; 20.584 + err = 0; 20.585 + exit: 20.586 + if(err){ 20.587 + IOStream_free(io); 20.588 + IOStream_free(zio); 20.589 + zio = NULL; 20.590 + } 20.591 + return zio; 20.592 +} 20.593 +#endif
21.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 21.2 +++ b/tools/lib/lzi_stream.h Mon Jun 28 15:03:15 2004 +0000 21.3 @@ -0,0 +1,36 @@ 21.4 +#/* $Id: lzi_stream.h,v 1.3 2003/09/30 15:22:53 mjw Exp $ */ 21.5 +/* 21.6 + * Copyright (C) 2003 Hewlett-Packard Company. 21.7 + * 21.8 + * This library is free software; you can redistribute it and/or modify 21.9 + * it under the terms of the GNU Lesser General Public License as published by 21.10 + * the Free Software Foundation; either version 2.1 of the License, or 21.11 + * (at your option) any later version. 21.12 + * 21.13 + * This library is distributed in the hope that it will be useful, 21.14 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 21.15 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 21.16 + * GNU Lesser General Public License for more details. 21.17 + * 21.18 + * You should have received a copy of the GNU Lesser General Public License 21.19 + * along with this library; if not, write to the Free Software 21.20 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 21.21 + */ 21.22 + 21.23 +#ifndef _SP_LZI_STREAM_H_ 21.24 +#define _SP_LZI_STREAM_H_ 21.25 + 21.26 +#ifndef __KERNEL__ 21.27 +#include "iostream.h" 21.28 + 21.29 +extern IOStream *lzi_stream_new(IOStream *io, const char *mode); 21.30 +extern IOStream *lzi_stream_fopen(const char *file, const char *mode); 21.31 +extern IOStream *lzi_stream_fdopen(int fd, const char *mode); 21.32 +extern IOStream *lzi_stream_io(IOStream *zio); 21.33 + 21.34 +extern int lzi_stream_plain_bytes(IOStream *io); 21.35 +extern int lzi_stream_comp_bytes(IOStream *io); 21.36 +extern float lzi_stream_ratio(IOStream *io); 21.37 + 21.38 +#endif 21.39 +#endif /* !_SP_FILE_STREAM_H_ */
22.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 22.2 +++ b/tools/lib/lzo_stream.c Mon Jun 28 15:03:15 2004 +0000 22.3 @@ -0,0 +1,596 @@ 22.4 +/* $Id: lzo_stream.c,v 1.4 2003/09/30 15:22:53 mjw Exp $ */ 22.5 +#define __FILE_ID_INFO "$Id: lzo_stream.c,v 1.4 2003/09/30 15:22:53 mjw Exp $" 22.6 +#include <what.h> 22.7 +static char __rcsid[] __attribute__((unused)) = WHAT_ID __FILE_ID_INFO; 22.8 +/* 22.9 + * Copyright (C) 2003 Hewlett-Packard Company. 22.10 + * 22.11 + * This library is free software; you can redistribute it and/or modify 22.12 + * it under the terms of the GNU Lesser General Public License as published by 22.13 + * the Free Software Foundation; either version 2.1 of the License, or 22.14 + * (at your option) any later version. 22.15 + * 22.16 + * This library is distributed in the hope that it will be useful, 22.17 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 22.18 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 22.19 + * GNU Lesser General Public License for more details. 22.20 + * 22.21 + * You should have received a copy of the GNU Lesser General Public License 22.22 + * along with this library; if not, write to the Free Software 22.23 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 22.24 + */ 22.25 + 22.26 +/** @file 22.27 + * An IOStream implementation using LZO to provide compression and decompression. 22.28 + * This is designed to provide reasonable compression without output latency. 22.29 + * Flushing an LZO stream flushes all pending data to the underlying stream. 22.30 + * This is essential for stream-based (e.g. networked) applications. 22.31 + * 22.32 + * A compressed data stream is a sequence of blocks. 22.33 + * Each block except the last is the plain data size followed by the compressed data size 22.34 + * and the compressed data. The last block has plain data size zero and omits the rest. 22.35 + * Sizes are 4-byte unsigned in network order. If the compressed size is smaller than 22.36 + * the plain size the block data is compressed, otherwise it is plain (uncompressed). 22.37 + * 22.38 + * This format allows compressed data to be read from a stream without reading 22.39 + * past the logical end of compressed data. 22.40 + * 22.41 + * @author Mike Wray <mike.wray@hpl.hp.com> 22.42 + */ 22.43 +#ifndef __KERNEL__ 22.44 + 22.45 +#include <stdio.h> 22.46 +#include <stdlib.h> 22.47 +#include <errno.h> 22.48 +#include <string.h> 22.49 + 22.50 +#include "lzo1x.h" 22.51 + 22.52 +#include "allocate.h" 22.53 +#include "lzo_stream.h" 22.54 +#include "file_stream.h" 22.55 +#include "marshal.h" 22.56 + 22.57 +#define dprintf(fmt, args...) fprintf(stdout, "[DEBUG] LZO>%s" fmt, __FUNCTION__, ##args) 22.58 +#define wprintf(fmt, args...) fprintf(stderr, "[WARN] LZO>%s" fmt, __FUNCTION__, ##args) 22.59 +#define iprintf(fmt, args...) fprintf(stdout, "[INFO] LZO>%s" fmt, __FUNCTION__, ##args) 22.60 +#define eprintf(fmt, args...) fprintf(stderr, "[ERROR] LZO>%s" fmt, __FUNCTION__, ##args) 22.61 + 22.62 +static int lzo_read(IOStream *s, void *buf, size_t size, size_t count); 22.63 +static int lzo_write(IOStream *s, const void *buf, size_t size, size_t count); 22.64 +static int lzo_print(IOStream *s, const char *msg, va_list args); 22.65 +static int lzo_getc(IOStream *s); 22.66 +static int lzo_error(IOStream *s); 22.67 +static int lzo_close(IOStream *s); 22.68 +static void lzo_free(IOStream *s); 22.69 +static int lzo_flush(IOStream *s); 22.70 + 22.71 +enum { 22.72 + LZO_WRITE = 1, 22.73 + LZO_READ = 2, 22.74 +}; 22.75 + 22.76 +/** Methods used by a gzFile* IOStream. */ 22.77 +static const IOMethods lzo_methods = { 22.78 + read: lzo_read, 22.79 + write: lzo_write, 22.80 + print: lzo_print, 22.81 + getc: lzo_getc, 22.82 + error: lzo_error, 22.83 + close: lzo_close, 22.84 + free: lzo_free, 22.85 + flush: lzo_flush, 22.86 +}; 22.87 + 22.88 +//#define PLAIN_SIZE (64 * 1024) 22.89 +//#define PLAIN_SIZE (128 * 1024) 22.90 +#define PLAIN_SIZE (512 * 1024) 22.91 + 22.92 +//#define NOCOMPRESS 22.93 + 22.94 +typedef struct LZOState { 22.95 + /** Flags. */ 22.96 + int flags; 22.97 + /** Error indicator. */ 22.98 + int error; 22.99 + /** Underlying stream for I/O. */ 22.100 + IOStream *io; 22.101 + /** Working memory (only needed for compression, not decompression). */ 22.102 + lzo_byte *memory; 22.103 + /** Buffer for plain (uncompressed) data. */ 22.104 + lzo_byte *plain; 22.105 + /** Size of the plain buffer. */ 22.106 + lzo_uint plain_size; 22.107 + /** Pointer into the plain buffer. */ 22.108 + lzo_byte *plain_ptr; 22.109 + /** Number of bytes of plain data available. */ 22.110 + lzo_uint plain_n; 22.111 + /** Buffer for compressed data. */ 22.112 + lzo_byte *comp; 22.113 + /** Size of the compressed buffer. */ 22.114 + lzo_uint comp_size; 22.115 + 22.116 + int plain_bytes; 22.117 + int comp_bytes; 22.118 +} LZOState; 22.119 + 22.120 +void LZOState_free(LZOState *z){ 22.121 + if(!z) return; 22.122 + deallocate(z->memory); 22.123 + deallocate(z->plain); 22.124 + deallocate(z->comp); 22.125 + deallocate(z); 22.126 +} 22.127 + 22.128 +/** Maximum size of compressed data for the given plain data size. 22.129 + * 22.130 + * @param plain_size size of plain data 22.131 + * @return maximum size of compressed data 22.132 + */ 22.133 +static int comp_size(int plain_size){ 22.134 + return plain_size + (plain_size / 64) + 16 + 3; 22.135 +} 22.136 + 22.137 +static int mode_flags(const char *mode, int *flags){ 22.138 + int err = 0; 22.139 + int r=0, w=0; 22.140 + if(!mode){ 22.141 + err = -EINVAL; 22.142 + goto exit; 22.143 + } 22.144 + for(; *mode; mode++){ 22.145 + if(*mode == 'w') w = 1; 22.146 + if(*mode == 'r') r = 1; 22.147 + } 22.148 + if(r + w != 1){ 22.149 + err = -EINVAL; 22.150 + goto exit; 22.151 + } 22.152 + if(r) *flags |= LZO_READ; 22.153 + if(w) *flags |= LZO_WRITE; 22.154 + exit: 22.155 + return err; 22.156 +} 22.157 + 22.158 +/** Get the stream state. 22.159 + * 22.160 + * @param s lzo stream 22.161 + * @return stream state. 22.162 + */ 22.163 +static inline LZOState * lzo_state(IOStream *s){ 22.164 + return s->data; 22.165 +} 22.166 + 22.167 +IOStream *lzo_stream_io(IOStream *s){ 22.168 + LZOState *state = lzo_state(s); 22.169 + return state->io; 22.170 +} 22.171 + 22.172 +static inline void set_error(LZOState *state, int err){ 22.173 + if(err < 0 && !state->error){ 22.174 + state->error = err; 22.175 + } 22.176 +} 22.177 + 22.178 +int lzo_stream_plain_bytes(IOStream *s){ 22.179 + LZOState *state = lzo_state(s); 22.180 + return state->plain_bytes; 22.181 +} 22.182 + 22.183 +int lzo_stream_comp_bytes(IOStream *s){ 22.184 + LZOState *state = lzo_state(s); 22.185 + return state->comp_bytes; 22.186 +} 22.187 + 22.188 +float lzo_stream_ratio(IOStream *s){ 22.189 + LZOState *state = lzo_state(s); 22.190 + float ratio = 0.0; 22.191 + if(state->comp_bytes){ 22.192 + ratio = ((float) state->comp_bytes)/((float) state->plain_bytes); 22.193 + } 22.194 + return ratio; 22.195 +} 22.196 + 22.197 +static inline int LZOState_writeable(LZOState *state){ 22.198 + return (state->flags & LZO_WRITE) != 0; 22.199 +} 22.200 + 22.201 +static inline int LZOState_readable(LZOState *state){ 22.202 + return (state->flags & LZO_READ) != 0; 22.203 +} 22.204 + 22.205 +LZOState * LZOState_new(IOStream *io, int flags){ 22.206 + int err = -ENOMEM; 22.207 + LZOState *z = ALLOCATE(LZOState); 22.208 + //dprintf(">\n"); 22.209 + if(!z) goto exit; 22.210 + z->io = io; 22.211 + z->flags = flags; 22.212 + if(LZOState_writeable(z)){ 22.213 + z->memory = allocate(LZO1X_1_MEM_COMPRESS); 22.214 + if(!z->memory) goto exit; 22.215 + } 22.216 + z->plain_size = PLAIN_SIZE; 22.217 + z->plain = allocate(z->plain_size); 22.218 + if(!z->plain) goto exit; 22.219 + z->plain_ptr = z->plain; 22.220 + z->comp_size = comp_size(z->plain_size); 22.221 + z->comp = allocate(z->comp_size); 22.222 + if(!z->comp) goto exit; 22.223 + err = 0; 22.224 + exit: 22.225 + if(err){ 22.226 + LZOState_free(z); 22.227 + z = NULL; 22.228 + } 22.229 + //dprintf("< z=%p\n", z); 22.230 + return z; 22.231 +} 22.232 + 22.233 +static int lzo_compress(LZOState *state){ 22.234 + int err = 0; 22.235 + int k, comp_n; 22.236 + //dprintf(">\n"); 22.237 + //dprintf(">plain=%p plain_n=%d comp=%p memory=%p\n", state->plain, state->plain_n, state->comp, state->memory); 22.238 + // Compress the plain buffer. 22.239 + err = lzo1x_1_compress(state->plain, state->plain_n, 22.240 + state->comp, &comp_n, 22.241 + state->memory); 22.242 + //dprintf("> err=%d plain_n=%d comp_n=%d\n", err, state->plain_n, comp_n); 22.243 + // Write plain size, compressed size. 22.244 + err = marshal_uint32(state->io, state->plain_n); 22.245 + if(err) goto exit; 22.246 + err = marshal_uint32(state->io, comp_n); 22.247 + if(err) goto exit; 22.248 + //dprintf("> write data...\n"); 22.249 + // Write the smaller of the compressed and plain data. 22.250 + if(state->plain_n < comp_n){ 22.251 + k = state->plain_n; 22.252 + err = marshal_bytes(state->io, state->plain, state->plain_n); 22.253 + } else { 22.254 + k = comp_n; 22.255 + err = marshal_bytes(state->io, state->comp, comp_n); 22.256 + } 22.257 + if(err) goto exit; 22.258 + // Total output bytes. 22.259 + k+= 8; 22.260 + //dprintf("> wrote %d bytes\n", k); 22.261 + state->plain_bytes += state->plain_n; 22.262 + state->comp_bytes += k; 22.263 + //dprintf("> plain=%d, comp=%d, ratio=%3.2f\n", 22.264 + // state->plain_bytes, state->comp_bytes, 22.265 + // ((float)state->comp_bytes)/((float)state->plain_bytes)); 22.266 + // Reset the plain buffer. 22.267 + state->plain_ptr = state->plain; 22.268 + state->plain_n = 0; 22.269 + err = k; 22.270 + exit: 22.271 + //dprintf("< err=%d\n", err); 22.272 + return err; 22.273 +} 22.274 + 22.275 +static int lzo_decompress(LZOState *state){ 22.276 + int plain_n, comp_n; 22.277 + int err, k; 22.278 + //dprintf(">\n"); 22.279 + err = unmarshal_uint32(state->io, &plain_n); 22.280 + //dprintf("> err=%d plain_n=%d\n", err, plain_n); 22.281 + if(err) goto exit; 22.282 + state->comp_bytes += 4; 22.283 + if(plain_n == 0) goto exit; 22.284 + err = unmarshal_uint32(state->io, &comp_n); 22.285 + //dprintf("> err=%d comp_n=%d\n", err, comp_n); 22.286 + if(err) goto exit; 22.287 + state->comp_bytes += 4; 22.288 + if(plain_n > state->plain_size){ 22.289 + err = -EINVAL; 22.290 + goto exit; 22.291 + } 22.292 + if(comp_n > plain_n){ 22.293 + //dprintf("> reading plain data %d...\n", plain_n); 22.294 + k = plain_n; 22.295 + err = unmarshal_bytes(state->io, state->plain, plain_n); 22.296 + state->plain_n = plain_n; 22.297 + } else { 22.298 + //dprintf("> reading comp data %d...\n", comp_n); 22.299 + k = comp_n; 22.300 + err = unmarshal_bytes(state->io, state->comp, comp_n); 22.301 + //dprintf("> decompress comp_n=%d\n", comp_n); 22.302 + err = lzo1x_decompress(state->comp, comp_n, 22.303 + state->plain, &state->plain_n, 22.304 + state->memory); 22.305 + //dprintf("> err=%d plain=%d state->plain_n=%d\n", err, plain_n, state->plain_n); 22.306 + if(err != LZO_E_OK || state->plain_n != plain_n){ 22.307 + // Bad. Corrupted input. 22.308 + err = -EINVAL; 22.309 + eprintf("> Corrupted!\n"); 22.310 + goto exit; 22.311 + } 22.312 + } 22.313 + state->comp_bytes += k; 22.314 + state->plain_bytes += state->plain_n; 22.315 + state->plain_ptr = state->plain; 22.316 + err = k; 22.317 + exit: 22.318 + //dprintf("< err=%d\n", err); 22.319 + return err; 22.320 +} 22.321 + 22.322 +/** Write to the underlying stream using fwrite(); 22.323 + * 22.324 + * @param stream destination 22.325 + * @param buf data 22.326 + * @param size size of data elements 22.327 + * @param count number of data elements to write 22.328 + * @return number of data elements written 22.329 + */ 22.330 +static int lzo_write(IOStream *s, const void *buf, size_t size, size_t count){ 22.331 + int err = 0; 22.332 + int n = size * count; // Total number of bytes to write. 22.333 + int chunk; // Size of chunk to write. 22.334 + int remaining; // Number of bytes remaining to write. 22.335 + int space; // Amount of space left in plain buffer. 22.336 + LZOState *state = lzo_state(s); 22.337 +#ifdef NOCOMPRESS 22.338 + //dprintf("> buf=%p size=%d count=%d\n", buf, size, count); 22.339 + err = IOStream_write(state->io, buf, size, count); 22.340 + //dprintf("< err=%d\n", err); 22.341 +#else 22.342 + //dprintf("> buf=%p size=%d count=%d n=%d\n", buf, size, count, n); 22.343 + remaining = n; 22.344 + space = state->plain_size - state->plain_n; 22.345 + //dprintf("> plain=%p plain_ptr=%p plain_n=%d space=%d\n", 22.346 + // state->plain, state->plain_ptr, state->plain_n, space); 22.347 + while(remaining){ 22.348 + chunk = remaining; 22.349 + if(chunk > space) chunk = space; 22.350 + //dprintf("> memcpy %p %p %d\n", state->plain_ptr, buf, chunk); 22.351 + memcpy(state->plain_ptr, buf, chunk); 22.352 + remaining -= chunk; 22.353 + space -= chunk; 22.354 + state->plain_ptr += chunk; 22.355 + state->plain_n += chunk; 22.356 + if(space == 0){ 22.357 + // Input buffer is full. Compress and write it. 22.358 + err = lzo_compress(state); 22.359 + if(err < 0) goto exit; 22.360 + space = state->plain_size - state->plain_n; 22.361 + } 22.362 + } 22.363 + err = (size > 1 ? n / size : n); 22.364 + exit: 22.365 + set_error(state, err); 22.366 +#endif 22.367 + return err; 22.368 +} 22.369 + 22.370 + 22.371 +/** Read from the underlying stream. 22.372 + * 22.373 + * @param stream input 22.374 + * @param buf where to put input 22.375 + * @param size size of data elements 22.376 + * @param count number of data elements to read 22.377 + * @return number of data elements read 22.378 + */ 22.379 +static int lzo_read(IOStream *s, void *buf, size_t size, size_t count){ 22.380 + int err = 0; 22.381 + int k = 0; // Number of (plain) bytes read. 22.382 + int remaining = size * count; // Number of bytes remaining to read. 22.383 + int chunk; // Size of chunk to read. 22.384 + LZOState *state = lzo_state(s); 22.385 +#ifdef NOCOMPRESS 22.386 + //dprintf("> buf=%p size=%d count=%d\n", buf, size, count); 22.387 + err = IOStream_read(state->io, buf, size, count); 22.388 + //dprintf("< err=%d\n", err); 22.389 +#else 22.390 + if(!(state->flags & LZO_READ)){ 22.391 + err = -EINVAL; 22.392 + goto exit; 22.393 + } 22.394 + while(remaining){ 22.395 + if(state->plain_n == 0){ 22.396 + // No more plain input, decompress some more. 22.397 + err = lzo_decompress(state); 22.398 + if(err < 0) goto exit; 22.399 + // Stop reading if there is no more input. 22.400 + if(err == 0 || state->plain_n == 0) break; 22.401 + } 22.402 + chunk = remaining; 22.403 + if(chunk > state->plain_n) chunk = state->plain_n; 22.404 + memcpy(buf, state->plain_ptr, chunk); 22.405 + k += chunk; 22.406 + buf += chunk; 22.407 + state->plain_ptr += chunk; 22.408 + state->plain_n -= chunk; 22.409 + remaining -= chunk; 22.410 + } 22.411 + err = k; 22.412 + exit: 22.413 + set_error(state, err); 22.414 +#endif 22.415 + return err; 22.416 +} 22.417 + 22.418 +/** Print to the underlying stream. 22.419 + * Returns 0 if the formatted output is too big for the internal buffer. 22.420 + * 22.421 + * @param s lzo stream 22.422 + * @param msg format to use 22.423 + * @param args arguments 22.424 + * @return result of the print 22.425 + */ 22.426 +static int lzo_print(IOStream *s, const char *msg, va_list args){ 22.427 + char buf[1024]; 22.428 + int buf_n = sizeof(buf); 22.429 + int n; 22.430 + LZOState *state = lzo_state(s); 22.431 + if(!LZOState_writeable(state)){ 22.432 + n = -EINVAL; 22.433 + goto exit; 22.434 + } 22.435 + n = vsnprintf(buf, buf_n, (char*)msg, args); 22.436 + if(n < 0) goto exit; 22.437 + if(n > buf_n){ 22.438 + n = 0; 22.439 + } else { 22.440 + n = lzo_write(s, buf, 1, n); 22.441 + } 22.442 + exit: 22.443 + return n; 22.444 +} 22.445 + 22.446 +/** Read a character from the underlying stream 22.447 + * 22.448 + * @param s lzo stream 22.449 + * @return character read, IOSTREAM_EOF on end of file (or error) 22.450 + */ 22.451 +static int lzo_getc(IOStream *s){ 22.452 + int err; 22.453 + char c; 22.454 + err = lzo_read(s, &c, 1, 1); 22.455 + if(err < 1) c = EOF; 22.456 + err = (c==EOF ? IOSTREAM_EOF : c); 22.457 + return err; 22.458 +} 22.459 + 22.460 +/** Flush any pending input to the underlying stream. 22.461 + * 22.462 + * @param s lzo stream 22.463 + * @return 0 on success, error code otherwise 22.464 + */ 22.465 +static int lzo_flush(IOStream *s){ 22.466 + int err = 0; 22.467 + LZOState *state = lzo_state(s); 22.468 + //dprintf(">\n"); 22.469 +#ifdef NOCOMPRESS 22.470 + err = IOStream_flush(state->io); 22.471 +#else 22.472 + if(!LZOState_writeable(state)){ 22.473 + err = -EINVAL; 22.474 + goto exit; 22.475 + } 22.476 + if(state->plain_n){ 22.477 + err = lzo_compress(state); 22.478 + if(err < 0) goto exit; 22.479 + } 22.480 + err = IOStream_flush(state->io); 22.481 + exit: 22.482 + set_error(state, err); 22.483 +#endif 22.484 + //dprintf("< err=%d\n", err); 22.485 + return (err < 0 ? err : 0); 22.486 +} 22.487 + 22.488 +/** Check if a stream has an error. 22.489 + * 22.490 + * @param s lzo stream 22.491 + * @return code if has an error, 0 otherwise 22.492 + */ 22.493 +static int lzo_error(IOStream *s){ 22.494 + int err = 0; 22.495 + LZOState *state = lzo_state(s); 22.496 + err = state->error; 22.497 + if(err) goto exit; 22.498 + err = IOStream_error(state->io); 22.499 + exit: 22.500 + return err; 22.501 +} 22.502 + 22.503 +int lzo_stream_finish(IOStream *s){ 22.504 + int err = 0; 22.505 + LZOState *state = lzo_state(s); 22.506 + if(!LZOState_writeable(state)){ 22.507 + err = -EINVAL; 22.508 + goto exit; 22.509 + } 22.510 + err = lzo_flush(s); 22.511 + if(err < 0) goto exit; 22.512 + err = marshal_int32(state->io, 0); 22.513 + exit: 22.514 + return err; 22.515 +} 22.516 + 22.517 +/** Close an lzo stream. 22.518 + * 22.519 + * @param s lzo stream to close 22.520 + * @return result of the close 22.521 + */ 22.522 +static int lzo_close(IOStream *s){ 22.523 + int err = 0; 22.524 + LZOState *state = lzo_state(s); 22.525 +#ifdef NOCOMPRESS 22.526 + err = IOStream_close(state->io); 22.527 +#else 22.528 + if(LZOState_writeable(state)){ 22.529 + err = lzo_stream_finish(s); 22.530 + } 22.531 + err = IOStream_close(state->io); 22.532 + set_error(state, err); 22.533 +#endif 22.534 + return err; 22.535 +} 22.536 + 22.537 +/** Free an lzo stream. 22.538 + * 22.539 + * @param s lzo stream 22.540 + */ 22.541 +static void lzo_free(IOStream *s){ 22.542 + LZOState *state = lzo_state(s); 22.543 + IOStream_free(state->io); 22.544 + LZOState_free(state); 22.545 + s->data = NULL; 22.546 +} 22.547 + 22.548 +/** Create an lzo stream for an IOStream. 22.549 + * 22.550 + * @param io stream to wrap 22.551 + * @return new IOStream using f for i/o 22.552 + */ 22.553 +IOStream *lzo_stream_new(IOStream *io, const char *mode){ 22.554 + int err = -ENOMEM; 22.555 + int flags = 0; 22.556 + IOStream *zio = NULL; 22.557 + LZOState *state = NULL; 22.558 + 22.559 + zio = ALLOCATE(IOStream); 22.560 + if(!zio) goto exit; 22.561 + err = mode_flags(mode, &flags); 22.562 + if(err) goto exit; 22.563 + state = LZOState_new(io, flags); 22.564 + if(!state) goto exit; 22.565 + err = 0; 22.566 + zio->data = state; 22.567 + zio->methods = &lzo_methods; 22.568 + exit: 22.569 + if(err){ 22.570 + if(state) LZOState_free(state); 22.571 + if(zio) deallocate(zio); 22.572 + zio = NULL; 22.573 + } 22.574 + return zio; 22.575 +} 22.576 + 22.577 +/** IOStream version of fdopen(). 22.578 + * 22.579 + * @param fd file descriptor 22.580 + * @param flags giving the mode to open in (as for fdopen()) 22.581 + * @return new stream for the open file, or NULL if failed 22.582 + */ 22.583 +IOStream *lzo_stream_fdopen(int fd, const char *mode){ 22.584 + int err = -ENOMEM; 22.585 + IOStream *io = NULL, *zio = NULL; 22.586 + io = file_stream_fdopen(fd, mode); 22.587 + if(!io) goto exit; 22.588 + zio = lzo_stream_new(io, mode); 22.589 + if(!io) goto exit; 22.590 + err = 0; 22.591 + exit: 22.592 + if(err){ 22.593 + IOStream_free(io); 22.594 + IOStream_free(zio); 22.595 + zio = NULL; 22.596 + } 22.597 + return zio; 22.598 +} 22.599 +#endif
23.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 23.2 +++ b/tools/lib/lzo_stream.h Mon Jun 28 15:03:15 2004 +0000 23.3 @@ -0,0 +1,36 @@ 23.4 +#/* $Id: lzo_stream.h,v 1.3 2003/09/30 15:22:53 mjw Exp $ */ 23.5 +/* 23.6 + * Copyright (C) 2003 Hewlett-Packard Company. 23.7 + * 23.8 + * This library is free software; you can redistribute it and/or modify 23.9 + * it under the terms of the GNU Lesser General Public License as published by 23.10 + * the Free Software Foundation; either version 2.1 of the License, or 23.11 + * (at your option) any later version. 23.12 + * 23.13 + * This library is distributed in the hope that it will be useful, 23.14 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 23.15 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 23.16 + * GNU Lesser General Public License for more details. 23.17 + * 23.18 + * You should have received a copy of the GNU Lesser General Public License 23.19 + * along with this library; if not, write to the Free Software 23.20 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 23.21 + */ 23.22 + 23.23 +#ifndef _SP_LZO_STREAM_H_ 23.24 +#define _SP_LZO_STREAM_H_ 23.25 + 23.26 +#ifndef __KERNEL__ 23.27 +#include "iostream.h" 23.28 + 23.29 +extern IOStream *lzo_stream_new(IOStream *io, const char *mode); 23.30 +extern IOStream *lzo_stream_fopen(const char *file, const char *mode); 23.31 +extern IOStream *lzo_stream_fdopen(int fd, const char *mode); 23.32 +extern IOStream *lzo_stream_io(IOStream *zio); 23.33 + 23.34 +extern int lzo_stream_plain_bytes(IOStream *io); 23.35 +extern int lzo_stream_comp_bytes(IOStream *io); 23.36 +extern float lzo_stream_ratio(IOStream *io); 23.37 + 23.38 +#endif 23.39 +#endif /* !_SP_FILE_STREAM_H_ */
24.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 24.2 +++ b/tools/lib/marshal.c Mon Jun 28 15:03:15 2004 +0000 24.3 @@ -0,0 +1,207 @@ 24.4 +#include <errno.h> 24.5 +#include "sys_net.h" 24.6 +#include "allocate.h" 24.7 +#include "marshal.h" 24.8 + 24.9 +#define dprintf(fmt, args...) IOStream_print(iostdout, "[DEBUG] %s" fmt, __FUNCTION__, ##args) 24.10 +#define wprintf(fmt, args...) IOStream_print(iostderr, "[WARN] %s" fmt, __FUNCTION__, ##args) 24.11 +#define iprintf(fmt, args...) IOStream_print(iostdout, "[INFO] %s" fmt, __FUNCTION__, ##args) 24.12 +#define eprintf(fmt, args...) IOStream_print(iostderr, "[ERROR] %s" fmt, __FUNCTION__, ##args) 24.13 + 24.14 + 24.15 +#define ARRAY_SIZE(ary) (sizeof(ary)/sizeof((ary)[0])) 24.16 + 24.17 +/* Messages are coded as msgid followed by message fields. 24.18 + * Initial message on any channel is hello - so can check version 24.19 + * compatibility. 24.20 + * 24.21 + * char* -> uint16_t:n <n bytes> 24.22 + * ints/uints go as suitable number of bytes (e.g. uint16_t is 2 bytes). 24.23 + * optional fields go as '1' <val> or '0' (the 0/1 is 1 byte). 24.24 + * lists go as ('1' <elt>)* '0' 24.25 + */ 24.26 + 24.27 +int marshal_flush(IOStream *io){ 24.28 + int err = 0; 24.29 + err = IOStream_flush(io); 24.30 + return err; 24.31 +} 24.32 + 24.33 +int marshal_bytes(IOStream *io, void *s, uint32_t s_n){ 24.34 + int err = 0; 24.35 + int n; 24.36 + n = IOStream_write(io, s, s_n); 24.37 + if(n < 0){ 24.38 + err = n; 24.39 + } else if (n < s_n){ 24.40 + wprintf("> Wanted %d, got %d\n", s_n, n); 24.41 + err = -EIO; 24.42 + } 24.43 + return err; 24.44 +} 24.45 + 24.46 +int unmarshal_bytes(IOStream *io, void *s, uint32_t s_n){ 24.47 + int err = 0; 24.48 + int n; 24.49 + //dprintf("> s_n=%d\n", s_n); 24.50 + n = IOStream_read(io, s, s_n); 24.51 + //dprintf("> n=%d\n", n); 24.52 + if(n < 0){ 24.53 + err = n; 24.54 + } else if(n < s_n){ 24.55 + wprintf("> Wanted %d, got %d\n", s_n, n); 24.56 + err = -EIO; 24.57 + } 24.58 + //dprintf("< err=%d\n", err); 24.59 + return err; 24.60 +} 24.61 + 24.62 +int marshal_uint8(IOStream *io, uint8_t x){ 24.63 + return marshal_bytes(io, &x, sizeof(x)); 24.64 +} 24.65 + 24.66 +int unmarshal_uint8(IOStream *io, uint8_t *x){ 24.67 + return unmarshal_bytes(io, x, sizeof(*x)); 24.68 +} 24.69 + 24.70 +int marshal_uint16(IOStream *io, uint16_t x){ 24.71 + x = htons(x); 24.72 + return marshal_bytes(io, &x, sizeof(x)); 24.73 +} 24.74 + 24.75 +int unmarshal_uint16(IOStream *io, uint16_t *x){ 24.76 + int err = 0; 24.77 + err = unmarshal_bytes(io, x, sizeof(*x)); 24.78 + *x = ntohs(*x); 24.79 + return err; 24.80 +} 24.81 + 24.82 +int marshal_int32(IOStream *io, int32_t x){ 24.83 + int err = 0; 24.84 + //dprintf("> x=%d\n", x); 24.85 + x = htonl(x); 24.86 + err = marshal_bytes(io, &x, sizeof(x)); 24.87 + //dprintf("< err=%d\n", err); 24.88 + return err; 24.89 +} 24.90 + 24.91 +int unmarshal_int32(IOStream *io, int32_t *x){ 24.92 + int err = 0; 24.93 + //dprintf(">\n"); 24.94 + err = unmarshal_bytes(io, x, sizeof(*x)); 24.95 + *x = ntohl(*x); 24.96 + //dprintf("< err=%d x=%d\n", err, *x); 24.97 + return err; 24.98 +} 24.99 + 24.100 +int marshal_uint32(IOStream *io, uint32_t x){ 24.101 + int err = 0; 24.102 + //dprintf("> x=%u\n", x); 24.103 + x = htonl(x); 24.104 + err = marshal_bytes(io, &x, sizeof(x)); 24.105 + //dprintf("< err=%d\n", err); 24.106 + return err; 24.107 +} 24.108 + 24.109 +int unmarshal_uint32(IOStream *io, uint32_t *x){ 24.110 + int err = 0; 24.111 + //dprintf(">\n"); 24.112 + err = unmarshal_bytes(io, x, sizeof(*x)); 24.113 + *x = ntohl(*x); 24.114 + //dprintf("< err=%d x=%u\n", err, *x); 24.115 + return err; 24.116 +} 24.117 + 24.118 +int marshal_uint64(IOStream *io, uint64_t x){ 24.119 + int err; 24.120 + err = marshal_uint32(io, (uint32_t) ((x >> 32) & 0xffffffff)); 24.121 + if(err) goto exit; 24.122 + err = marshal_uint32(io, (uint32_t) ( x & 0xffffffff)); 24.123 + exit: 24.124 + return err; 24.125 +} 24.126 + 24.127 +int unmarshal_uint64(IOStream *io, uint64_t *x){ 24.128 + int err = 0; 24.129 + uint32_t hi, lo; 24.130 + err = unmarshal_uint32(io, &hi); 24.131 + if(err) goto exit; 24.132 + err = unmarshal_uint32(io, &lo); 24.133 + *x = (((uint64_t) hi) << 32) | lo; 24.134 + exit: 24.135 + return err; 24.136 +} 24.137 + 24.138 +int marshal_net16(IOStream *io, net16_t x){ 24.139 + return marshal_bytes(io, &x, sizeof(x)); 24.140 +} 24.141 + 24.142 +int unmarshal_net16(IOStream *io, net16_t *x){ 24.143 + int err = 0; 24.144 + err = unmarshal_bytes(io, x, sizeof(*x)); 24.145 + return err; 24.146 +} 24.147 + 24.148 +int marshal_net32(IOStream *io, net32_t x){ 24.149 + return marshal_bytes(io, &x, sizeof(x)); 24.150 +} 24.151 + 24.152 +int unmarshal_net32(IOStream *io, net32_t *x){ 24.153 + int err = 0; 24.154 + err = unmarshal_bytes(io, x, sizeof(*x)); 24.155 + return err; 24.156 +} 24.157 + 24.158 +int marshal_string(IOStream *io, char *s, uint32_t s_n){ 24.159 + int err; 24.160 + //dprintf("> s=%s\n", s); 24.161 + err = marshal_uint32(io, s_n); 24.162 + if(err) goto exit; 24.163 + err = marshal_bytes(io, s, s_n); 24.164 + exit: 24.165 + //dprintf("< err=%d\n", err); 24.166 + return err; 24.167 +} 24.168 + 24.169 +int unmarshal_string(IOStream *io, char *s, uint32_t s_n){ 24.170 + int err = 0, val_n = 0; 24.171 + //dprintf(">\n"); 24.172 + err = unmarshal_uint32(io, &val_n); 24.173 + if(err) goto exit; 24.174 + if(val_n >= s_n){ 24.175 + err = -EINVAL; 24.176 + goto exit; 24.177 + } 24.178 + err = unmarshal_bytes(io, s, val_n); 24.179 + if(err) goto exit; 24.180 + s[val_n] = '\0'; 24.181 + exit: 24.182 + //dprintf("< err=%d s=%s\n", err, s); 24.183 + return err; 24.184 +} 24.185 + 24.186 +int unmarshal_new_string(IOStream *io, char **s, uint32_t *s_n){ 24.187 + int err = 0, val_n = 0; 24.188 + char *val = NULL; 24.189 + //dprintf(">\n"); 24.190 + err = unmarshal_uint32(io, &val_n); 24.191 + if(err) goto exit; 24.192 + val = allocate(val_n + 1); 24.193 + if(!val){ 24.194 + err = -ENOMEM; 24.195 + goto exit; 24.196 + } 24.197 + err = unmarshal_bytes(io, val, val_n); 24.198 + if(err) goto exit; 24.199 + val[val_n] = '\0'; 24.200 + exit: 24.201 + if(err){ 24.202 + if(val) deallocate(val); 24.203 + val = NULL; 24.204 + val_n = 0; 24.205 + } 24.206 + *s = val; 24.207 + if(s_n) *s_n = val_n; 24.208 + //dprintf("< err=%d s=%s\n", err, *s); 24.209 + return err; 24.210 +}
25.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 25.2 +++ b/tools/lib/marshal.h Mon Jun 28 15:03:15 2004 +0000 25.3 @@ -0,0 +1,43 @@ 25.4 +/* $Id: marshal.h,v 1.1 2003/10/17 15:48:43 mjw Exp $ */ 25.5 +#ifndef _SP_MARSHAL_H_ 25.6 +#define _SP_MARSHAL_H_ 25.7 + 25.8 +#include "iostream.h" 25.9 + 25.10 +/** A 16-bit uint in network order, e.g. a port number. */ 25.11 +typedef uint16_t net16_t; 25.12 + 25.13 +/** A 32-bit uint in network order, e.g. an IP address. */ 25.14 +typedef uint32_t net32_t; 25.15 + 25.16 +extern int marshal_flush(IOStream *io); 25.17 + 25.18 +extern int marshal_bytes(IOStream *io, void *s, uint32_t s_n); 25.19 +extern int unmarshal_bytes(IOStream *io, void *s, uint32_t s_n); 25.20 + 25.21 +extern int marshal_uint8(IOStream *io, uint8_t x); 25.22 +extern int unmarshal_uint8(IOStream *io, uint8_t *x); 25.23 + 25.24 +extern int marshal_uint16(IOStream *io, uint16_t x); 25.25 +extern int unmarshal_uint16(IOStream *io, uint16_t *x); 25.26 + 25.27 +extern int marshal_uint32(IOStream *io, uint32_t x); 25.28 +extern int unmarshal_uint32(IOStream *io, uint32_t *x); 25.29 + 25.30 +extern int marshal_int32(IOStream *io, int32_t x); 25.31 +extern int unmarshal_int32(IOStream *io, int32_t *x); 25.32 + 25.33 +extern int marshal_uint64(IOStream *io, uint64_t x); 25.34 +extern int unmarshal_uint64(IOStream *io, uint64_t *x); 25.35 + 25.36 +extern int marshal_net16(IOStream *io, net16_t x); 25.37 +extern int unmarshal_net16(IOStream *io, net16_t *x); 25.38 + 25.39 +extern int marshal_net32(IOStream *io, net32_t x); 25.40 +extern int unmarshal_net32(IOStream *io, net32_t *x); 25.41 + 25.42 +extern int marshal_string(IOStream *io, char *s, uint32_t s_n); 25.43 +extern int unmarshal_string(IOStream *io, char *s, uint32_t s_n); 25.44 +extern int unmarshal_new_string(IOStream *io, char **s, uint32_t *s_n); 25.45 + 25.46 +#endif /* ! _SP_MARSHAL_H_ */
26.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 26.2 +++ b/tools/lib/socket_stream.c Mon Jun 28 15:03:15 2004 +0000 26.3 @@ -0,0 +1,259 @@ 26.4 +/* $Id: socket_stream.c,v 1.9 2004/03/05 14:45:34 mjw Exp $ */ 26.5 +/* 26.6 + * Copyright (C) 2004 Mike Wray <mike.wray@hp.com> 26.7 + * 26.8 + * This library is free software; you can redistribute it and/or modify 26.9 + * it under the terms of the GNU Lesser General Public License as published by 26.10 + * the Free Software Foundation; either version 2.1 of the License, or 26.11 + * (at your option) any later version. 26.12 + * 26.13 + * This library is distributed in the hope that it will be useful, 26.14 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 26.15 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 26.16 + * GNU Lesser General Public License for more details. 26.17 + * 26.18 + * You should have received a copy of the GNU Lesser General Public License 26.19 + * along with this library; if not, write to the Free Software 26.20 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 26.21 + */ 26.22 + 26.23 +/** @file 26.24 + * An IOStream implementation using sockets. 26.25 + */ 26.26 + 26.27 +#include <stdio.h> 26.28 +#include <stdlib.h> 26.29 +#include <string.h> 26.30 +#include <unistd.h> 26.31 +#include <errno.h> 26.32 +#include "allocate.h" 26.33 +#include "socket_stream.h" 26.34 + 26.35 +#define MODULE_NAME "sock" 26.36 +#define DEBUG 0 26.37 +//#undef DEBUG 26.38 +#include "debug.h" 26.39 + 26.40 +static int socket_read(IOStream *s, void *buf, size_t n); 26.41 +static int socket_write(IOStream *s, const void *buf, size_t n); 26.42 +static int socket_error(IOStream *s); 26.43 +static int socket_close(IOStream *s); 26.44 +static void socket_free(IOStream *s); 26.45 +static int socket_flush(IOStream *s); 26.46 + 26.47 +/** Methods used by a socket IOStream. */ 26.48 +static const IOMethods socket_methods = { 26.49 + read: socket_read, 26.50 + write: socket_write, 26.51 + error: socket_error, 26.52 + close: socket_close, 26.53 + free: socket_free, 26.54 + flush: socket_flush, 26.55 +}; 26.56 + 26.57 +/** Get the socket data. 26.58 + * 26.59 + * @param io socket stream 26.60 + * @return data 26.61 + */ 26.62 +static inline SocketData * socket_data(IOStream *io){ 26.63 + return (SocketData *)io->data; 26.64 +} 26.65 + 26.66 +/** Test if a stream is a socket stream. 26.67 + * 26.68 + * @param io stream 26.69 + * @return 0 if a socket stream, -EINVAL if not 26.70 + */ 26.71 +int socket_stream_check(IOStream *io){ 26.72 + return (io && io->methods == &socket_methods ? 0 : -EINVAL); 26.73 +} 26.74 + 26.75 +/** Get the data for a socket stream. 26.76 + * 26.77 + * @param io stream 26.78 + * @param data return value for the data 26.79 + * @return 0 if a socket stream, -EINVAL if not 26.80 + */ 26.81 +int socket_stream_data(IOStream *io, SocketData **data){ 26.82 + int err = socket_stream_check(io); 26.83 + if(err){ 26.84 + *data = NULL; 26.85 + } else { 26.86 + *data = socket_data(io); 26.87 + } 26.88 + return err; 26.89 +} 26.90 + 26.91 +/** Set the destination address for a socket stream. 26.92 + * 26.93 + * @param io stream 26.94 + * @param addr address 26.95 + * @return 0 if a socket stream, -EINVAL if not 26.96 + */ 26.97 +int socket_stream_set_addr(IOStream *io, struct sockaddr_in *addr){ 26.98 + int err = 0; 26.99 + SocketData *data = NULL; 26.100 + err = socket_stream_data(io, &data); 26.101 + if(!err){ 26.102 + data->daddr = *addr; 26.103 + } 26.104 + return err; 26.105 +} 26.106 + 26.107 +/** Set the send flags for a socket stream. 26.108 + * 26.109 + * @param io stream 26.110 + * @param flags flags 26.111 + * @return 0 if a socket stream, -EINVAL if not 26.112 + */ 26.113 +int socket_stream_set_flags(IOStream *io, int flags){ 26.114 + int err = 0; 26.115 + SocketData *data = NULL; 26.116 + err = socket_stream_data(io, &data); 26.117 + if(!err){ 26.118 + data->flags = flags; 26.119 + } 26.120 + return err; 26.121 +} 26.122 + 26.123 +/** Write to the underlying socket using sendto. 26.124 + * 26.125 + * @param stream input 26.126 + * @param buf where to put input 26.127 + * @param n number of bytes to write 26.128 + * @return number of bytes written 26.129 + */ 26.130 +static int socket_write(IOStream *s, const void *buf, size_t n){ 26.131 + SocketData *data = socket_data(s); 26.132 + struct sockaddr *daddr = (struct sockaddr *)&data->daddr; 26.133 + socklen_t daddr_n = sizeof(data->daddr); 26.134 + int k; 26.135 + dprintf("> sock=%d addr=%s:%d n=%d\n", 26.136 + data->fd, inet_ntoa(data->daddr.sin_addr), ntohs(data->daddr.sin_port), n); 26.137 + if(0){ 26.138 + struct sockaddr_in self = {}; 26.139 + socklen_t self_n; 26.140 + getsockname(data->fd, (struct sockaddr *)&self, &self_n); 26.141 + dprintf("> sockname sock=%d %s:%d\n", 26.142 + data->fd, inet_ntoa(self.sin_addr), ntohs(self.sin_port)); 26.143 + } 26.144 + k = sendto(data->fd, buf, n, data->flags, daddr, daddr_n); 26.145 + dprintf("> sendto=%d\n", k); 26.146 + return k; 26.147 +} 26.148 + 26.149 +/** Read from the underlying stream using recv(); 26.150 + * 26.151 + * @param stream input 26.152 + * @param buf where to put input 26.153 + * @param n number of bytes to read 26.154 + * @return number of bytes read 26.155 + */ 26.156 +static int socket_read(IOStream *s, void *buf, size_t n){ 26.157 + SocketData *data = socket_data(s); 26.158 + int k; 26.159 + struct sockaddr *saddr = (struct sockaddr *)&data->saddr; 26.160 + socklen_t saddr_n = sizeof(data->saddr); 26.161 + k = recvfrom(data->fd, buf, n, data->flags, saddr, &saddr_n); 26.162 + return k; 26.163 +} 26.164 + 26.165 +/** Print to the underlying socket. 26.166 + * 26.167 + * @param s socket stream 26.168 + * @param msg format to use 26.169 + * @param args arguments 26.170 + * @return result of the print 26.171 + */ 26.172 +static int socket_print(IOStream *s, const char *msg, va_list args){ 26.173 + SocketData *data = socket_data(s); 26.174 + int n; 26.175 + n = vsnprintf(data->buf, data->buf_n - 1, msg, args); 26.176 + if(0 < n && n < data->buf_n){ 26.177 + socket_write(s, data->buf, n); 26.178 + } 26.179 + return n; 26.180 +} 26.181 + 26.182 +/** Read a character from the underlying socket 26.183 + * 26.184 + * @param s socket stream 26.185 + * @return character read, IOSTREAM_EOF on end of socket (or error) 26.186 + */ 26.187 +static int socket_getc(IOStream *s){ 26.188 + char b; 26.189 + int n, c; 26.190 + n = socket_read(s, &b, 1); 26.191 + c = (n <= 0 ? IOSTREAM_EOF : b); 26.192 + return c; 26.193 +} 26.194 + 26.195 +/** Flush the socket (no-op). 26.196 + * 26.197 + * @param s socket stream 26.198 + * @return 0 on success, error code otherwise 26.199 + */ 26.200 +static int socket_flush(IOStream *s){ 26.201 + return 0; 26.202 +} 26.203 + 26.204 +/** Check if a socket stream has an error (no-op). 26.205 + * 26.206 + * @param s socket stream 26.207 + * @return 1 if has an error, 0 otherwise 26.208 + */ 26.209 +static int socket_error(IOStream *s){ 26.210 + // Read SOL_SOCKET/SO_ERROR ? 26.211 + return 0; 26.212 +} 26.213 + 26.214 +/** Close a socket stream. 26.215 + * 26.216 + * @param s socket stream to close 26.217 + * @return result of the close 26.218 + */ 26.219 +static int socket_close(IOStream *s){ 26.220 + SocketData *data = socket_data(s); 26.221 + return close(data->fd); 26.222 +} 26.223 + 26.224 +/** Free a socket stream. 26.225 + * 26.226 + * @param s socket stream 26.227 + */ 26.228 +static void socket_free(IOStream *s){ 26.229 + SocketData *data = socket_data(s); 26.230 + deallocate(data); 26.231 +} 26.232 + 26.233 +/** Create an IOStream for a socket. 26.234 + * 26.235 + * @param fd socket to wtap 26.236 + * @return new IOStream using fd for i/o 26.237 + */ 26.238 +IOStream *socket_stream_new(int fd){ 26.239 + int err = -ENOMEM; 26.240 + IOStream *io = NULL; 26.241 + SocketData *data = NULL; 26.242 + 26.243 + io = ALLOCATE(IOStream); 26.244 + if(!io) goto exit; 26.245 + io->methods = &socket_methods; 26.246 + data = ALLOCATE(SocketData); 26.247 + if(!data) goto exit; 26.248 + io->data = data; 26.249 + data->fd = fd; 26.250 + data->buf_n = sizeof(data->buf); 26.251 + err = 0; 26.252 + exit: 26.253 + if(err){ 26.254 + if(io){ 26.255 + if(data) deallocate(data); 26.256 + deallocate(io); 26.257 + io = NULL; 26.258 + } 26.259 + } 26.260 + return io; 26.261 +} 26.262 +
27.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 27.2 +++ b/tools/lib/socket_stream.h Mon Jun 28 15:03:15 2004 +0000 27.3 @@ -0,0 +1,54 @@ 27.4 +/* $Id: socket_stream.h,v 1.2 2004/03/04 17:38:13 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 +#ifndef _XEN_LIB_SOCKET_STREAM_H_ 27.24 +#define _XEN_LIB_SOCKET_STREAM_H_ 27.25 + 27.26 +#ifndef __KERNEL__ 27.27 +#include "iostream.h" 27.28 +#include <stdio.h> 27.29 + 27.30 +#include <sys/socket.h> 27.31 +#include <netinet/in.h> 27.32 +#include <arpa/inet.h> 27.33 + 27.34 +/** Data associated with a socket stream. */ 27.35 +typedef struct SocketData { 27.36 + /** The socket file descriptor. */ 27.37 + int fd; 27.38 + /** Source address from last read (recvfrom). */ 27.39 + struct sockaddr_in saddr; 27.40 + /** Destination address for writes (sendto). */ 27.41 + struct sockaddr_in daddr; 27.42 + /** Write flags (sendto). */ 27.43 + int flags; 27.44 + /** Buffer size. */ 27.45 + int buf_n; 27.46 + /** Buffer for formatted printing. */ 27.47 + char buf[1024]; 27.48 +} SocketData; 27.49 + 27.50 +extern IOStream *socket_stream_new(int fd); 27.51 +extern int socket_stream_data(IOStream *io, SocketData **data); 27.52 +extern int socket_stream_check(IOStream *io); 27.53 +extern int socket_stream_set_addr(IOStream *io, struct sockaddr_in *addr); 27.54 +extern int socket_stream_set_flags(IOStream *io, int flags); 27.55 + 27.56 +#endif 27.57 +#endif /* !_XEN_LIB_SOCKET_STREAM_H_ */
28.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 28.2 +++ b/tools/lib/string_stream.c Mon Jun 28 15:03:15 2004 +0000 28.3 @@ -0,0 +1,174 @@ 28.4 +/* 28.5 + * Copyright (C) 2001, 2002 Hewlett-Packard Company. 28.6 + * 28.7 + * This library is free software; you can redistribute it and/or modify 28.8 + * it under the terms of the GNU Lesser General Public License as published by 28.9 + * the Free Software Foundation; either version 2.1 of the License, or 28.10 + * (at your option) any later version. 28.11 + * 28.12 + * This library is distributed in the hope that it will be useful, 28.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 28.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 28.15 + * GNU Lesser General Public License for more details. 28.16 + * 28.17 + * You should have received a copy of the GNU Lesser General Public License 28.18 + * along with this library; if not, write to the Free Software 28.19 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 28.20 + */ 28.21 + 28.22 +/** @file 28.23 + * IOStream subtype for input and output to strings. 28.24 + * Usable from user or kernel code (with __KERNEL__ defined). 28.25 + */ 28.26 + 28.27 +#include "sys_string.h" 28.28 +#include "string_stream.h" 28.29 +#include "allocate.h" 28.30 + 28.31 +static int string_print(IOStream *io, const char *msg, va_list args); 28.32 +static int string_getc(IOStream *io); 28.33 +static int string_error(IOStream *io); 28.34 +static int string_close(IOStream *io); 28.35 +static void string_free(IOStream *io); 28.36 + 28.37 +/** Methods for a string stream. */ 28.38 +static IOMethods string_methods = { 28.39 + //print: string_print, 28.40 + //getc: string_getc, 28.41 + error: string_error, 28.42 + close: string_close, 28.43 + free: string_free, 28.44 +}; 28.45 + 28.46 +/** Get the string stream state. 28.47 + * 28.48 + * @param io string stream 28.49 + * @return state 28.50 + */ 28.51 +static inline StringData *get_string_data(IOStream *io){ 28.52 + return (StringData*)io->data; 28.53 +} 28.54 + 28.55 +/** Read a character from a string stream. 28.56 + * 28.57 + * @param io string stream 28.58 + * @return character read, IOSTREAM_EOF if no more input 28.59 + */ 28.60 +static int string_getc(IOStream *io){ 28.61 + StringData *data = get_string_data(io); 28.62 + int c = IOSTREAM_EOF; 28.63 + char *s = data->in; 28.64 + 28.65 + if(s && s < data->end){ 28.66 + c = (unsigned)*s; 28.67 + data->in = s+1; 28.68 + } 28.69 + return c; 28.70 +} 28.71 + 28.72 +/** Print to a string stream. 28.73 + * Formats the data to an internal buffer and prints it. 28.74 + * The formatted data must fit into the internal buffer. 28.75 + * 28.76 + * @param io string stream 28.77 + * @param format print format 28.78 + * @param args print arguments 28.79 + * @return result of the print 28.80 + */ 28.81 +static int string_print(IOStream *io, const char *msg, va_list args){ 28.82 + StringData *data = get_string_data(io); 28.83 + int k = data->end - data->out; 28.84 + int n = vsnprintf(data->out, k, (char*)msg, args); 28.85 + if(n < 0 || n > k ){ 28.86 + n = k; 28.87 + IOStream_close(io); 28.88 + } else { 28.89 + data->out += n; 28.90 + } 28.91 + return n; 28.92 +} 28.93 + 28.94 +/** Test if a string stream has an error. 28.95 + * 28.96 + * @param io string stream 28.97 + * @return 0 if ok, error code otherwise 28.98 + */ 28.99 +static int string_error(IOStream *io){ 28.100 + StringData *data = get_string_data(io); 28.101 + return data->out == NULL; 28.102 +} 28.103 + 28.104 +/** Close a string stream. 28.105 + * 28.106 + * @param io string stream 28.107 + * @return 0 28.108 + */ 28.109 +static int string_close(IOStream *io){ 28.110 + StringData *data = get_string_data(io); 28.111 + data->in = NULL; 28.112 + data->out = NULL; 28.113 + return 0; 28.114 +} 28.115 + 28.116 +/** Free a string stream. 28.117 + * The stream must have been allocated, not statically created. 28.118 + * The stream state is freed, but the underlying string is not. 28.119 + * 28.120 + * @param io string stream 28.121 + */ 28.122 +static void string_free(IOStream *io){ 28.123 + StringData *data = get_string_data(io); 28.124 + zero(data, sizeof(*data)); 28.125 + deallocate(data); 28.126 +} 28.127 + 28.128 +/** Get the methods to use for a string stream. 28.129 + * 28.130 + * @return methods 28.131 + */ 28.132 +IOMethods *string_stream_get_methods(void){ 28.133 + return &string_methods; 28.134 +} 28.135 + 28.136 +/** Initialise a string stream, usually from static data. 28.137 + * 28.138 + * @param io address of IOStream to fill in 28.139 + * @param data address of StringData to fill in 28.140 + * @param s string to use 28.141 + * @param n length of the string 28.142 + */ 28.143 +void string_stream_init(IOStream *io, StringData *data, char *s, int n){ 28.144 + if(data && io){ 28.145 + zero(data, sizeof(*data)); 28.146 + data->string = (char*)s; 28.147 + data->in = data->string; 28.148 + data->out = data->string; 28.149 + data->size = n; 28.150 + data->end = data->string + n; 28.151 + zero(io, sizeof(*io)); 28.152 + io->methods = &string_methods; 28.153 + io->data = data; 28.154 + } 28.155 +} 28.156 + 28.157 +/** Allocate and initialise a string stream. 28.158 + * 28.159 + * @param s string to use 28.160 + * @param n length of the string 28.161 + * @return new stream (free using IOStream_free) 28.162 + */ 28.163 +IOStream *string_stream_new(char *s, int n){ 28.164 + int ok = 0; 28.165 + StringData *data = ALLOCATE(StringData); 28.166 + IOStream *io = ALLOCATE(IOStream); 28.167 + if(data && io){ 28.168 + ok = 1; 28.169 + string_stream_init(io, data, s, n); 28.170 + } 28.171 + if(!ok){ 28.172 + deallocate(data); 28.173 + deallocate(io); 28.174 + io = NULL; 28.175 + } 28.176 + return io; 28.177 +}
29.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 29.2 +++ b/tools/lib/string_stream.h Mon Jun 28 15:03:15 2004 +0000 29.3 @@ -0,0 +1,46 @@ 29.4 +/* $Id: string_stream.h,v 1.1 2003/08/22 14:25:48 mjw Exp $ */ 29.5 +/* 29.6 + * Copyright (C) 2001, 2002 Hewlett-Packard Company. 29.7 + * 29.8 + * This library is free software; you can redistribute it and/or modify 29.9 + * it under the terms of the GNU Lesser General Public License as published by 29.10 + * the Free Software Foundation; either version 2.1 of the License, or 29.11 + * (at your option) any later version. 29.12 + * 29.13 + * This library is distributed in the hope that it will be useful, 29.14 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 29.15 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 29.16 + * GNU Lesser General Public License for more details. 29.17 + * 29.18 + * You should have received a copy of the GNU Lesser General Public License 29.19 + * along with this library; if not, write to the Free Software 29.20 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 29.21 + */ 29.22 + 29.23 +#ifndef _SP_STRING_STREAM_H_ 29.24 +#define _SP_STRING_STREAM_H_ 29.25 + 29.26 +#include "iostream.h" 29.27 + 29.28 +/** Internal state for a string stream. 29.29 + * Exposed here so that string streams can be statically created, using 29.30 + * string_stream_init(). 29.31 + */ 29.32 +typedef struct { 29.33 + /** The string used for input and ouput. */ 29.34 + char *string; 29.35 + /** Output pointer. */ 29.36 + char *out; 29.37 + /** Input pointer. */ 29.38 + char *in; 29.39 + /** Length of string. */ 29.40 + int size; 29.41 + /** End marker. */ 29.42 + char *end; 29.43 +} StringData; 29.44 + 29.45 +extern IOMethods *string_stream_get_methods(void); 29.46 +extern IOStream *string_stream_new(char *s, int n); 29.47 +extern void string_stream_init(IOStream *stream, StringData *data, char *s, int n); 29.48 + 29.49 +#endif /* !_SP_STRING_STREAM_H_ */
30.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 30.2 +++ b/tools/lib/sxpr.c Mon Jun 28 15:03:15 2004 +0000 30.3 @@ -0,0 +1,935 @@ 30.4 +/* 30.5 + * 30.6 + * This library is free software; you can redistribute it and/or modify 30.7 + * it under the terms of the GNU Lesser General Public License as 30.8 + * published by the Free Software Foundation; either version 2.1 of the 30.9 + * License, or (at your option) any later version. This library is 30.10 + * distributed in the hope that it will be useful, but WITHOUT ANY 30.11 + * WARRANTY; without even the implied warranty of MERCHANTABILITY or 30.12 + * FITNESS FOR A PARTICULAR PURPOSE. 30.13 + * See the GNU Lesser General Public License for more details. 30.14 + * 30.15 + * You should have received a copy of the GNU Lesser General Public License 30.16 + * along with this library; if not, write to the Free Software Foundation, 30.17 + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 30.18 + */ 30.19 + 30.20 +#include <stdarg.h> 30.21 +#include "sys_string.h" 30.22 +#include "lexis.h" 30.23 +#include "sys_net.h" 30.24 +#include "hash_table.h" 30.25 +#include "sxpr.h" 30.26 + 30.27 +#include <errno.h> 30.28 +#undef free 30.29 + 30.30 +/** @file 30.31 + * General representation of sxprs. 30.32 + * Includes print, equal, and free functions for the sxpr types. 30.33 + * 30.34 + * Zero memory containing an Sxpr will have the value ONONE - this is intentional. 30.35 + * When a function returning an sxpr cannot allocate memory we return ONOMEM. 30.36 + * 30.37 + */ 30.38 + 30.39 +static int atom_print(IOStream *io, Sxpr obj, unsigned flags); 30.40 +static int atom_equal(Sxpr x, Sxpr y); 30.41 +static void atom_free(Sxpr obj); 30.42 + 30.43 +static int string_print(IOStream *io, Sxpr obj, unsigned flags); 30.44 +static int string_equal(Sxpr x, Sxpr y); 30.45 +static void string_free(Sxpr obj); 30.46 + 30.47 +static int cons_print(IOStream *io, Sxpr obj, unsigned flags); 30.48 +static int cons_equal(Sxpr x, Sxpr y); 30.49 +static void cons_free(Sxpr obj); 30.50 + 30.51 +static int null_print(IOStream *io, Sxpr obj, unsigned flags); 30.52 +static int none_print(IOStream *io, Sxpr obj, unsigned flags); 30.53 +static int int_print(IOStream *io, Sxpr obj, unsigned flags); 30.54 +static int bool_print(IOStream *io, Sxpr obj, unsigned flags); 30.55 + 30.56 +/** Type definitions. */ 30.57 +static SxprType types[1024] = { 30.58 + [T_NONE] { type: T_NONE, name: "none", print: none_print }, 30.59 + [T_NULL] { type: T_NULL, name: "null", print: null_print }, 30.60 + [T_UINT] { type: T_UINT, name: "int", print: int_print, }, 30.61 + [T_BOOL] { type: T_BOOL, name: "bool", print: bool_print, }, 30.62 + [T_ATOM] { type: T_ATOM, name: "atom", print: atom_print, 30.63 + pointer: TRUE, 30.64 + free: atom_free, 30.65 + equal: atom_equal, 30.66 + }, 30.67 + [T_STRING] { type: T_STRING, name: "string", print: string_print, 30.68 + pointer: TRUE, 30.69 + free: string_free, 30.70 + equal: string_equal, 30.71 + }, 30.72 + [T_CONS] { type: T_CONS, name: "cons", print: cons_print, 30.73 + pointer: TRUE, 30.74 + free: cons_free, 30.75 + equal: cons_equal, 30.76 + }, 30.77 +}; 30.78 + 30.79 +/** Number of entries in the types array. */ 30.80 +static int type_sup = sizeof(types)/sizeof(types[0]); 30.81 + 30.82 +/** Get the type definition for a given type code. 30.83 + * 30.84 + * @param ty type code 30.85 + * @return type definition or null 30.86 + */ 30.87 +SxprType *get_sxpr_type(int ty){ 30.88 + if(0 <= ty && ty < type_sup){ 30.89 + return types+ty; 30.90 + } 30.91 + return NULL; 30.92 +} 30.93 + 30.94 +/** The default print function. 30.95 + * 30.96 + * @param io stream to print to 30.97 + * @param x sxpr to print 30.98 + * @param flags print flags 30.99 + * @return number of bytes written on success 30.100 + */ 30.101 +int default_print(IOStream *io, Sxpr x, unsigned flags){ 30.102 + return IOStream_print(io, "#<%u %lu>\n", get_type(x), get_ul(x)); 30.103 +} 30.104 + 30.105 +/** The default equal function. 30.106 + * Uses eq(). 30.107 + * 30.108 + * @param x sxpr to compare 30.109 + * @param y sxpr to compare 30.110 + * @return 1 if equal, 0 otherwise 30.111 + */ 30.112 +int default_equal(Sxpr x, Sxpr y){ 30.113 + return eq(x, y); 30.114 +} 30.115 + 30.116 +/** General sxpr print function. 30.117 + * Prints an sxpr on a stream using the print function for the sxpr type. 30.118 + * Printing is controlled by flags from the PrintFlags enum. 30.119 + * If PRINT_TYPE is in the flags the sxpr type is printed before the sxpr 30.120 + * (for debugging). 30.121 + * 30.122 + * @param io stream to print to 30.123 + * @param x sxpr to print 30.124 + * @param flags print flags 30.125 + * @return number of bytes written 30.126 + */ 30.127 +int objprint(IOStream *io, Sxpr x, unsigned flags){ 30.128 + SxprType *def = get_sxpr_type(get_type(x)); 30.129 + ObjPrintFn *print_fn = (def && def->print ? def->print : default_print); 30.130 + int k = 0; 30.131 + if(!io) return k; 30.132 + if(flags & PRINT_TYPE){ 30.133 + k += IOStream_print(io, "%s:", def->name); 30.134 + } 30.135 + k += print_fn(io, x, flags); 30.136 + return k; 30.137 +} 30.138 + 30.139 +/** General sxpr free function. 30.140 + * Frees an sxpr using the free function for its type. 30.141 + * Free functions must recursively free any subsxprs. 30.142 + * If no function is defined then the default is to 30.143 + * free sxprs whose type has pointer true. 30.144 + * Sxprs must not be used after freeing. 30.145 + * 30.146 + * @param x sxpr to free 30.147 + */ 30.148 +void objfree(Sxpr x){ 30.149 + SxprType *def = get_sxpr_type(get_type(x)); 30.150 + 30.151 + if(def){ 30.152 + if(def->free){ 30.153 + def->free(x); 30.154 + } else if (def->pointer){ 30.155 + hfree(x); 30.156 + } 30.157 + } 30.158 +} 30.159 + 30.160 +/** General sxpr equality function. 30.161 + * Compares x and y using the equal function for x. 30.162 + * Uses default_equal() if x has no equal function. 30.163 + * 30.164 + * @param x sxpr to compare 30.165 + * @param y sxpr to compare 30.166 + * @return 1 if equal, 0 otherwise 30.167 + */ 30.168 +int objequal(Sxpr x, Sxpr y){ 30.169 + SxprType *def = get_sxpr_type(get_type(x)); 30.170 + ObjEqualFn *equal_fn = (def && def->equal ? def->equal : default_equal); 30.171 + return equal_fn(x, y); 30.172 +} 30.173 + 30.174 +/** Search for a key in an alist. 30.175 + * An alist is a list of conses, where the cars 30.176 + * of the conses are the keys. Compares keys using equality. 30.177 + * 30.178 + * @param k key 30.179 + * @param l alist to search 30.180 + * @return first element of l with car k, or ONULL 30.181 + */ 30.182 +Sxpr assoc(Sxpr k, Sxpr l){ 30.183 + for( ; CONSP(l) ; l = CDR(l)){ 30.184 + Sxpr x = CAR(l); 30.185 + if(CONSP(x) && objequal(k, CAR(x))){ 30.186 + return x; 30.187 + } 30.188 + } 30.189 + return ONULL; 30.190 +} 30.191 + 30.192 +/** Search for a key in an alist. 30.193 + * An alist is a list of conses, where the cars 30.194 + * of the conses are the keys. Compares keys using eq. 30.195 + * 30.196 + * @param k key 30.197 + * @param l alist to search 30.198 + * @return first element of l with car k, or ONULL 30.199 + */ 30.200 +Sxpr assocq(Sxpr k, Sxpr l){ 30.201 + for( ; CONSP(l); l = CDR(l)){ 30.202 + Sxpr x = CAR(l); 30.203 + if(CONSP(x) && eq(k, CAR(x))){ 30.204 + return x; 30.205 + } 30.206 + } 30.207 + return ONULL; 30.208 +} 30.209 + 30.210 +/** Add a new key and value to an alist. 30.211 + * 30.212 + * @param k key 30.213 + * @param l value 30.214 + * @param l alist 30.215 + * @return l with the new cell added to the front 30.216 + */ 30.217 +Sxpr acons(Sxpr k, Sxpr v, Sxpr l){ 30.218 + Sxpr x, y; 30.219 + x = cons_new(k, v); 30.220 + if(NOMEMP(x)) return x; 30.221 + y = cons_new(x, l); 30.222 + if(NOMEMP(y)) cons_free_cells(x); 30.223 + return y; 30.224 +} 30.225 + 30.226 +/** Test if a list contains an element. 30.227 + * Uses sxpr equality. 30.228 + * 30.229 + * @param l list 30.230 + * @param x element to look for 30.231 + * @return a tail of l with x as car, or ONULL 30.232 + */ 30.233 +Sxpr cons_member(Sxpr l, Sxpr x){ 30.234 + for( ; CONSP(l) && !eq(x, CAR(l)); l = CDR(l)){} 30.235 + return l; 30.236 +} 30.237 + 30.238 +/** Test if a list contains an element satisfying a test. 30.239 + * The test function is called with v and an element of the list. 30.240 + * 30.241 + * @param l list 30.242 + * @param test_fn test function to use 30.243 + * @param v value for first argument to the test 30.244 + * @return a tail of l with car satisfying the test, or 0 30.245 + */ 30.246 +Sxpr cons_member_if(Sxpr l, ObjEqualFn *test_fn, Sxpr v){ 30.247 + for( ; CONSP(l) && !test_fn(v, CAR(l)); l = CDR(l)){ } 30.248 + return l; 30.249 +} 30.250 + 30.251 +/** Test if the elements of list 't' are a subset of the elements 30.252 + * of list 's'. Element order is not significant. 30.253 + * 30.254 + * @param s element list to check subset of 30.255 + * @param t element list to check if is a subset 30.256 + * @return 1 if is a subset, 0 otherwise 30.257 + */ 30.258 +int cons_subset(Sxpr s, Sxpr t){ 30.259 + for( ; CONSP(t); t = CDR(t)){ 30.260 + if(!CONSP(cons_member(s, CAR(t)))){ 30.261 + return 0; 30.262 + } 30.263 + } 30.264 + return 1; 30.265 +} 30.266 + 30.267 +/** Test if two lists have equal sets of elements. 30.268 + * Element order is not significant. 30.269 + * 30.270 + * @param s list to check 30.271 + * @param t list to check 30.272 + * @return 1 if equal, 0 otherwise 30.273 + */ 30.274 +int cons_set_equal(Sxpr s, Sxpr t){ 30.275 + return cons_subset(s, t) && cons_subset(t, s); 30.276 +} 30.277 + 30.278 +#ifdef USE_GC 30.279 +/*============================================================================*/ 30.280 +/* The functions inside this ifdef are only safe if GC is used. 30.281 + * Otherwise they may leak memory. 30.282 + */ 30.283 + 30.284 +/** Remove an element from a list (GC only). 30.285 + * Uses sxpr equality and removes all instances, even 30.286 + * if there are more than one. 30.287 + * 30.288 + * @param l list to remove elements from 30.289 + * @param x element to remove 30.290 + * @return modified input list 30.291 + */ 30.292 +Sxpr cons_remove(Sxpr l, Sxpr x){ 30.293 + return cons_remove_if(l, eq, x); 30.294 +} 30.295 + 30.296 +/** Remove elements satisfying a test (GC only). 30.297 + * The test function is called with v and an element of the set. 30.298 + * 30.299 + * @param l list to remove elements from 30.300 + * @param test_fn function to use to decide if an element should be removed 30.301 + * @return modified input list 30.302 + */ 30.303 +Sxpr cons_remove_if(Sxpr l, ObjEqualFn *test_fn, Sxpr v){ 30.304 + Sxpr prev = ONULL, elt, next; 30.305 + 30.306 + for(elt = l; CONSP(elt); elt = next){ 30.307 + next = CDR(elt); 30.308 + if(test_fn(v, CAR(elt))){ 30.309 + if(NULLP(prev)){ 30.310 + l = next; 30.311 + } else { 30.312 + CDR(prev) = next; 30.313 + } 30.314 + } 30.315 + } 30.316 + return l; 30.317 +} 30.318 + 30.319 +/** Set the value for a key in an alist (GC only). 30.320 + * If the key is present, changes the value, otherwise 30.321 + * adds a new cell. 30.322 + * 30.323 + * @param k key 30.324 + * @param v value 30.325 + * @param l alist 30.326 + * @return modified or extended list 30.327 + */ 30.328 +Sxpr setf(Sxpr k, Sxpr v, Sxpr l){ 30.329 + Sxpr e = assoc(k, l); 30.330 + if(NULLP(e)){ 30.331 + l = acons(k, v, l); 30.332 + } else { 30.333 + CAR(CDR(e)) = v; 30.334 + } 30.335 + return l; 30.336 +} 30.337 +/*============================================================================*/ 30.338 +#endif /* USE_GC */ 30.339 + 30.340 +/** Create a new atom with the given name. 30.341 + * 30.342 + * @param name the name 30.343 + * @return new atom 30.344 + */ 30.345 +Sxpr atom_new(char *name){ 30.346 + Sxpr n, obj = ONOMEM; 30.347 + 30.348 + n = string_new(name); 30.349 + if(NOMEMP(n)) goto exit; 30.350 + obj = HALLOC(ObjAtom, T_ATOM); 30.351 + if(NOMEMP(obj)) goto exit; 30.352 + OBJ_ATOM(obj)->name = n; 30.353 + exit: 30.354 + return obj; 30.355 +} 30.356 + 30.357 +/** Free an atom. 30.358 + * 30.359 + * @param obj to free 30.360 + */ 30.361 +void atom_free(Sxpr obj){ 30.362 + // Interned atoms are shared, so do not free. 30.363 + if(OBJ_ATOM(obj)->interned) return; 30.364 + objfree(OBJ_ATOM(obj)->name); 30.365 + hfree(obj); 30.366 +} 30.367 + 30.368 +/** Print an atom. Prints the atom name. 30.369 + * 30.370 + * @param io stream to print to 30.371 + * @param obj to print 30.372 + * @param flags print flags 30.373 + * @return number of bytes printed 30.374 + */ 30.375 +int atom_print(IOStream *io, Sxpr obj, unsigned flags){ 30.376 + //return string_print(io, OBJ_ATOM(obj)->name, (flags | PRINT_RAW)); 30.377 + return string_print(io, OBJ_ATOM(obj)->name, flags); 30.378 +} 30.379 + 30.380 +/** Atom equality. 30.381 + * 30.382 + * @param x to compare 30.383 + * @param y to compare 30.384 + * @return 1 if equal, 0 otherwise 30.385 + */ 30.386 +int atom_equal(Sxpr x, Sxpr y){ 30.387 + int ok; 30.388 + ok = eq(x, y); 30.389 + if(ok) goto exit; 30.390 + ok = ATOMP(y) && string_equal(OBJ_ATOM(x)->name, OBJ_ATOM(y)->name); 30.391 + if(ok) goto exit; 30.392 + ok = STRINGP(y) && string_equal(OBJ_ATOM(x)->name, y); 30.393 + exit: 30.394 + return ok; 30.395 +} 30.396 + 30.397 +/** Get the name of an atom. 30.398 + * 30.399 + * @param obj atom 30.400 + * @return name 30.401 + */ 30.402 +char * atom_name(Sxpr obj){ 30.403 + return string_string(OBJ_ATOM(obj)->name); 30.404 +} 30.405 + 30.406 +/** Get the C string from a string sxpr. 30.407 + * 30.408 + * @param obj string sxpr 30.409 + * @return string 30.410 + */ 30.411 +char * string_string(Sxpr obj){ 30.412 + return OBJ_STRING(obj); 30.413 +} 30.414 + 30.415 +/** Get the length of a string. 30.416 + * 30.417 + * @param obj string 30.418 + * @return length 30.419 + */ 30.420 +int string_length(Sxpr obj){ 30.421 + return strlen(OBJ_STRING(obj)); 30.422 +} 30.423 + 30.424 +/** Create a new string. The input string is copied, 30.425 + * and must be null-terminated. 30.426 + * 30.427 + * @param s characters to put in the string 30.428 + * @return new sxpr 30.429 + */ 30.430 +Sxpr string_new(char *s){ 30.431 + int n = (s ? strlen(s) : 0); 30.432 + Sxpr obj; 30.433 + obj = halloc(n+1, T_STRING); 30.434 + if(!NOMEMP(obj)){ 30.435 + char *str = OBJ_STRING(obj); 30.436 + strncpy(str, s, n); 30.437 + str[n] = '\0'; 30.438 + } 30.439 + return obj; 30.440 +} 30.441 + 30.442 +/** Free a string. 30.443 + * 30.444 + * @param obj to free 30.445 + */ 30.446 +void string_free(Sxpr obj){ 30.447 + hfree(obj); 30.448 +} 30.449 + 30.450 +/** Determine if a string needs escapes when printed 30.451 + * using the given flags. 30.452 + * 30.453 + * @param str string to check 30.454 + * @param flags print flags 30.455 + * @return 1 if needs escapes, 0 otherwise 30.456 + */ 30.457 +int needs_escapes(char *str, unsigned flags){ 30.458 + char *c; 30.459 + int val = 0; 30.460 + 30.461 + if(str){ 30.462 + for(c=str; *c; c++){ 30.463 + if(in_alpha_class(*c)) continue; 30.464 + if(in_decimal_digit_class(*c)) continue; 30.465 + if(in_class(*c, "/._+:@~-")) continue; 30.466 + val = 1; 30.467 + break; 30.468 + } 30.469 + } 30.470 + //printf("\n> val=%d str=|%s|\n", val, str); 30.471 + return val; 30.472 +} 30.473 + 30.474 +/** Print a string to a stream, with escapes if necessary. 30.475 + * 30.476 + * @param io stream to print to 30.477 + * @param str string 30.478 + * @param flags print flags 30.479 + * @return number of bytes written 30.480 + */ 30.481 +int _string_print(IOStream *io, char *str, unsigned flags){ 30.482 + int k = 0; 30.483 + if((flags & PRINT_RAW) || !needs_escapes(str, flags)){ 30.484 + k += IOStream_print(io, str); 30.485 + } else { 30.486 + k += IOStream_print(io, "\""); 30.487 + if(str){ 30.488 + char *s; 30.489 + for(s = str; *s; s++){ 30.490 + if(*s < ' ' || *s >= 127 ){ 30.491 + switch(*s){ 30.492 + case '\a': k += IOStream_print(io, "\\a"); break; 30.493 + case '\b': k += IOStream_print(io, "\\b"); break; 30.494 + case '\f': k += IOStream_print(io, "\\f"); break; 30.495 + case '\n': k += IOStream_print(io, "\\n"); break; 30.496 + case '\r': k += IOStream_print(io, "\\r"); break; 30.497 + case '\t': k += IOStream_print(io, "\\t"); break; 30.498 + case '\v': k += IOStream_print(io, "\\v"); break; 30.499 + default: 30.500 + // Octal escape; 30.501 + k += IOStream_print(io, "\\%o", *s); 30.502 + break; 30.503 + } 30.504 + } else if(*s == c_double_quote || 30.505 + *s == c_single_quote || 30.506 + *s == c_escape){ 30.507 + k += IOStream_print(io, "\\%c", *s); 30.508 + } else { 30.509 + k+= IOStream_print(io, "%c", *s); 30.510 + } 30.511 + } 30.512 + } 30.513 + k += IOStream_print(io, "\""); 30.514 + } 30.515 + return k; 30.516 +} 30.517 + 30.518 +/** Print a string to a stream, with escapes if necessary. 30.519 + * 30.520 + * @param io stream to print to 30.521 + * @param obj string 30.522 + * @param flags print flags 30.523 + * @return number of bytes written 30.524 + */ 30.525 +int string_print(IOStream *io, Sxpr obj, unsigned flags){ 30.526 + return _string_print(io, OBJ_STRING(obj), flags); 30.527 +} 30.528 + 30.529 +/** Compare an sxpr with a string for equality. 30.530 + * 30.531 + * @param x string to compare with 30.532 + * @param y sxpr to compare 30.533 + * @return 1 if equal, 0 otherwise 30.534 + */ 30.535 +int string_equal(Sxpr x, Sxpr y){ 30.536 + int ok = 0; 30.537 + ok = eq(x,y); 30.538 + if(ok) goto exit; 30.539 + ok = has_type(y, T_STRING) && !strcmp(OBJ_STRING(x), OBJ_STRING(y)); 30.540 + if(ok) goto exit; 30.541 + ok = has_type(y, T_ATOM) && !strcmp(OBJ_STRING(x), atom_name(y)); 30.542 + exit: 30.543 + return ok; 30.544 +} 30.545 + 30.546 +/** Create a new cons cell. 30.547 + * The cell is ONOMEM if either argument is. 30.548 + * 30.549 + * @param car sxpr for the car 30.550 + * @param cdr sxpr for the cdr 30.551 + * @return new cons 30.552 + */ 30.553 +Sxpr cons_new(Sxpr car, Sxpr cdr){ 30.554 + Sxpr obj; 30.555 + if(NOMEMP(car) || NOMEMP(cdr)){ 30.556 + obj = ONOMEM; 30.557 + } else { 30.558 + obj = HALLOC(ObjCons, T_CONS); 30.559 + if(!NOMEMP(obj)){ 30.560 + ObjCons *z = OBJ_CONS(obj); 30.561 + z->car = car; 30.562 + z->cdr = cdr; 30.563 + } 30.564 + } 30.565 + return obj; 30.566 +} 30.567 + 30.568 +/** Push a new element onto a list. 30.569 + * 30.570 + * @param list list to add to 30.571 + * @param elt element to add 30.572 + * @return 0 if successful, error code otherwise 30.573 + */ 30.574 +int cons_push(Sxpr *list, Sxpr elt){ 30.575 + Sxpr l; 30.576 + l = cons_new(elt, *list); 30.577 + if(NOMEMP(l)) return -ENOMEM; 30.578 + *list = l; 30.579 + return 0; 30.580 +} 30.581 + 30.582 +/** Free a cons. Recursively frees the car and cdr. 30.583 + * 30.584 + * @param obj to free 30.585 + */ 30.586 +void cons_free(Sxpr obj){ 30.587 + Sxpr next; 30.588 + for(; CONSP(obj); obj = next){ 30.589 + next = CDR(obj); 30.590 + objfree(CAR(obj)); 30.591 + hfree(obj); 30.592 + } 30.593 + if(!NULLP(obj)){ 30.594 + objfree(obj); 30.595 + } 30.596 +} 30.597 + 30.598 +/** Free a cons and its cdr cells, but not the car sxprs. 30.599 + * Does nothing if called on something that is not a cons. 30.600 + * 30.601 + * @param obj to free 30.602 + */ 30.603 +void cons_free_cells(Sxpr obj){ 30.604 + Sxpr next; 30.605 + for(; CONSP(obj); obj = next){ 30.606 + next = CDR(obj); 30.607 + hfree(obj); 30.608 + } 30.609 +} 30.610 + 30.611 +/** Print a cons. 30.612 + * Prints the cons in list format if the cdrs are conses. 30.613 + * uses pair (dot) format if the last cdr is not a cons (or null). 30.614 + * 30.615 + * @param io stream to print to 30.616 + * @param obj to print 30.617 + * @param flags print flags 30.618 + * @return number of bytes written 30.619 + */ 30.620 +int cons_print(IOStream *io, Sxpr obj, unsigned flags){ 30.621 + int first = 1; 30.622 + int k = 0; 30.623 + k += IOStream_print(io, "("); 30.624 + for( ; CONSP(obj) ; obj = CDR(obj)){ 30.625 + if(first){ 30.626 + first = 0; 30.627 + } else { 30.628 + k += IOStream_print(io, " "); 30.629 + } 30.630 + k += objprint(io, CAR(obj), flags); 30.631 + } 30.632 + if(!NULLP(obj)){ 30.633 + k += IOStream_print(io, " . "); 30.634 + k += objprint(io, obj, flags); 30.635 + } 30.636 + k += IOStream_print(io, ")"); 30.637 + return (IOStream_error(io) ? -1 : k); 30.638 +} 30.639 + 30.640 +/** Compare a cons with another sxpr for equality. 30.641 + * If y is a cons, compares the cars and cdrs recursively. 30.642 + * 30.643 + * @param x cons to compare 30.644 + * @param y sxpr to compare 30.645 + * @return 1 if equal, 0 otherwise 30.646 + */ 30.647 +int cons_equal(Sxpr x, Sxpr y){ 30.648 + return CONSP(y) && 30.649 + objequal(CAR(x), CAR(y)) && 30.650 + objequal(CDR(x), CDR(y)); 30.651 +} 30.652 + 30.653 +/** Return the length of a cons list. 30.654 + * 30.655 + * @param obj list 30.656 + * @return length 30.657 + */ 30.658 +int cons_length(Sxpr obj){ 30.659 + int count = 0; 30.660 + for( ; CONSP(obj); obj = CDR(obj)){ 30.661 + count++; 30.662 + } 30.663 + return count; 30.664 +} 30.665 + 30.666 +/** Destructively reverse a cons list in-place. 30.667 + * If the argument is not a cons it is returned unchanged. 30.668 + * 30.669 + * @param l to reverse 30.670 + * @return reversed list 30.671 + */ 30.672 +Sxpr nrev(Sxpr l){ 30.673 + if(CONSP(l)){ 30.674 + // Iterate down the cells in the list making the cdr of 30.675 + // each cell point to the previous cell. The last cell 30.676 + // is the head of the reversed list. 30.677 + Sxpr prev = ONULL; 30.678 + Sxpr cell = l; 30.679 + Sxpr next; 30.680 + 30.681 + while(1){ 30.682 + next = CDR(cell); 30.683 + CDR(cell) = prev; 30.684 + if(!CONSP(next)) break; 30.685 + prev = cell; 30.686 + cell = next; 30.687 + } 30.688 + l = cell; 30.689 + } 30.690 + return l; 30.691 +} 30.692 + 30.693 +/** Print the null sxpr. 30.694 + * 30.695 + * @param io stream to print to 30.696 + * @param obj to print 30.697 + * @param flags print flags 30.698 + * @return number of bytes written 30.699 + */ 30.700 +static int null_print(IOStream *io, Sxpr obj, unsigned flags){ 30.701 + return IOStream_print(io, "()"); 30.702 +} 30.703 + 30.704 +/** Print the `unspecified' sxpr none. 30.705 + * 30.706 + * @param io stream to print to 30.707 + * @param obj to print 30.708 + * @param flags print flags 30.709 + * @return number of bytes written 30.710 + */ 30.711 +static int none_print(IOStream *io, Sxpr obj, unsigned flags){ 30.712 + return IOStream_print(io, "<none>"); 30.713 +} 30.714 + 30.715 +/** Print an integer. 30.716 + * 30.717 + * @param io stream to print to 30.718 + * @param obj to print 30.719 + * @param flags print flags 30.720 + * @return number of bytes written 30.721 + */ 30.722 +static int int_print(IOStream *io, Sxpr obj, unsigned flags){ 30.723 + return IOStream_print(io, "%d", OBJ_INT(obj)); 30.724 +} 30.725 + 30.726 +/** Print a boolean. 30.727 + * 30.728 + * @param io stream to print to 30.729 + * @param obj to print 30.730 + * @param flags print flags 30.731 + * @return number of bytes written 30.732 + */ 30.733 +static int bool_print(IOStream *io, Sxpr obj, unsigned flags){ 30.734 + return IOStream_print(io, (OBJ_UINT(obj) ? k_true : k_false)); 30.735 +} 30.736 + 30.737 +int sxprp(Sxpr obj, Sxpr name){ 30.738 + return CONSP(obj) && objequal(CAR(obj), name); 30.739 +} 30.740 + 30.741 +/** Get the name of an element. 30.742 + * 30.743 + * @param obj element 30.744 + * @return name 30.745 + */ 30.746 +Sxpr sxpr_name(Sxpr obj){ 30.747 + Sxpr val = ONONE; 30.748 + if(CONSP(obj)){ 30.749 + val = CAR(obj); 30.750 + } else if(STRINGP(obj) || ATOMP(obj)){ 30.751 + val = obj; 30.752 + } 30.753 + return val; 30.754 +} 30.755 + 30.756 +int sxpr_is(Sxpr obj, char *s){ 30.757 + if(ATOMP(obj)) return !strcmp(atom_name(obj), s); 30.758 + if(STRINGP(obj)) return !strcmp(string_string(obj), s); 30.759 + return 0; 30.760 +} 30.761 + 30.762 +int sxpr_elementp(Sxpr obj, Sxpr name){ 30.763 + return CONSP(obj) && objequal(CAR(obj), name); 30.764 +} 30.765 + 30.766 +/** Get the attributes of an sxpr. 30.767 + * 30.768 + * @param obj sxpr 30.769 + * @return attributes 30.770 + */ 30.771 +Sxpr sxpr_attributes(Sxpr obj){ 30.772 + Sxpr val = ONULL; 30.773 + if(CONSP(obj)){ 30.774 + obj = CDR(obj); 30.775 + if(CONSP(obj)){ 30.776 + obj = CAR(obj); 30.777 + if(sxprp(obj, intern("@"))){ 30.778 + val = CDR(obj); 30.779 + } 30.780 + } 30.781 + } 30.782 + return val; 30.783 +} 30.784 + 30.785 +Sxpr sxpr_attribute(Sxpr obj, Sxpr key, Sxpr def){ 30.786 + Sxpr val = ONONE; 30.787 + val = assoc(sxpr_attributes(obj), key); 30.788 + if(CONSP(val) && CONSP(CDR(val))){ 30.789 + val = CADR(def); 30.790 + } else { 30.791 + val = def; 30.792 + } 30.793 + return val; 30.794 +} 30.795 + 30.796 +/** Get the children of an sxpr. 30.797 + * 30.798 + * @param obj sxpr 30.799 + * @return children 30.800 + */ 30.801 +Sxpr sxpr_children(Sxpr obj){ 30.802 + Sxpr val = ONULL; 30.803 + if(CONSP(obj)){ 30.804 + val = CDR(obj); 30.805 + if(CONSP(val) && sxprp(CAR(val), intern("@"))){ 30.806 + val = CDR(val); 30.807 + } 30.808 + } 30.809 + return val; 30.810 +} 30.811 + 30.812 +Sxpr sxpr_child(Sxpr obj, Sxpr name, Sxpr def){ 30.813 + Sxpr val = ONONE; 30.814 + Sxpr l; 30.815 + for(l = sxpr_children(obj); CONSP(l); l = CDR(l)){ 30.816 + if(sxprp(CAR(l), name)){ 30.817 + val = CAR(l); 30.818 + break; 30.819 + } 30.820 + } 30.821 + if(NONEP(val)) val = def; 30.822 + return val; 30.823 +} 30.824 + 30.825 +Sxpr sxpr_child0(Sxpr obj, Sxpr def){ 30.826 + Sxpr val = ONONE; 30.827 + Sxpr l = sxpr_children(obj); 30.828 + if(CONSP(l)){ 30.829 + val = CAR(l); 30.830 + } else { 30.831 + val = def; 30.832 + } 30.833 + return val; 30.834 +} 30.835 + 30.836 +Sxpr sxpr_child_value(Sxpr obj, Sxpr name, Sxpr def){ 30.837 + Sxpr val = ONONE; 30.838 + val = sxpr_child(obj, name, ONONE); 30.839 + if(NONEP(val)){ 30.840 + val = def; 30.841 + } else { 30.842 + val = sxpr_child0(val, def); 30.843 + } 30.844 + return val; 30.845 +} 30.846 + 30.847 +/** Table of interned symbols. Indexed by symbol name. */ 30.848 +static HashTable *symbols = NULL; 30.849 + 30.850 +/** Hash function for entries in the symbol table. 30.851 + * 30.852 + * @param key to hash 30.853 + * @return hashcode 30.854 + */ 30.855 +static Hashcode sym_hash_fn(void *key){ 30.856 + return hash_string((char*)key); 30.857 +} 30.858 + 30.859 +/** Key equality function for the symbol table. 30.860 + * 30.861 + * @param x to compare 30.862 + * @param y to compare 30.863 + * @return 1 if equal, 0 otherwise 30.864 + */ 30.865 +static int sym_equal_fn(void *x, void *y){ 30.866 + return !strcmp((char*)x, (char*)y); 30.867 +} 30.868 + 30.869 +/** Entry free function for the symbol table. 30.870 + * 30.871 + * @param table the entry is in 30.872 + * @param entry being freed 30.873 + */ 30.874 +static void sym_free_fn(HashTable *table, HTEntry *entry){ 30.875 + if(entry){ 30.876 + objfree(((ObjAtom*)entry->value)->name); 30.877 + HTEntry_free(entry); 30.878 + } 30.879 +} 30.880 + 30.881 +/** Initialize the symbol table. 30.882 + * 30.883 + * @return 0 on sucess, error code otherwise 30.884 + */ 30.885 +static int init_symbols(void){ 30.886 + symbols = HashTable_new(100); 30.887 + if(symbols){ 30.888 + symbols->key_hash_fn = sym_hash_fn; 30.889 + symbols->key_equal_fn = sym_equal_fn; 30.890 + symbols->entry_free_fn = sym_free_fn; 30.891 + return 0; 30.892 + } 30.893 + return -1; 30.894 +} 30.895 + 30.896 +/** Cleanup the symbol table. Frees the table and all its symbols. 30.897 + */ 30.898 +void cleanup_symbols(void){ 30.899 + HashTable_free(symbols); 30.900 + symbols = NULL; 30.901 +} 30.902 + 30.903 +/** Get the interned symbol with the given name. 30.904 + * No new symbol is created. 30.905 + * 30.906 + * @return symbol or null 30.907 + */ 30.908 +Sxpr get_symbol(char *sym){ 30.909 + HTEntry *entry; 30.910 + if(!symbols){ 30.911 + if(init_symbols()) return ONOMEM; 30.912 + return ONULL; 30.913 + } 30.914 + entry = HashTable_get_entry(symbols, sym); 30.915 + if(entry){ 30.916 + return OBJP(T_ATOM, entry->value); 30.917 + } else { 30.918 + return ONULL; 30.919 + } 30.920 +} 30.921 + 30.922 +/** Get the interned symbol with the given name. 30.923 + * Creates a new symbol if necessary. 30.924 + * 30.925 + * @return symbol 30.926 + */ 30.927 +Sxpr intern(char *sym){ 30.928 + Sxpr symbol = get_symbol(sym); 30.929 + if(NULLP(symbol)){ 30.930 + if(!symbols) return ONOMEM; 30.931 + symbol = atom_new(sym); 30.932 + if(!NOMEMP(symbol)){ 30.933 + OBJ_ATOM(symbol)->interned = TRUE; 30.934 + HashTable_add(symbols, atom_name(symbol), get_ptr(symbol)); 30.935 + } 30.936 + } 30.937 + return symbol; 30.938 +}
31.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 31.2 +++ b/tools/lib/sxpr.h Mon Jun 28 15:03:15 2004 +0000 31.3 @@ -0,0 +1,413 @@ 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 +#ifndef _XEN_LIB_SXPR_H_ 31.20 +#define _XEN_LIB_SXPR_H_ 31.21 + 31.22 +#include <stdint.h> 31.23 + 31.24 +#include "hash_table.h" 31.25 +#include "iostream.h" 31.26 +#include "allocate.h" 31.27 + 31.28 +/** @file 31.29 + * Definitions for rules and sxprs. 31.30 + */ 31.31 + 31.32 +#ifndef NULL 31.33 +#define NULL 0 31.34 +#endif 31.35 + 31.36 +#ifndef TRUE 31.37 +#define TRUE 1 31.38 +#endif 31.39 + 31.40 +#ifndef FALSE 31.41 +#define FALSE 0 31.42 +#endif 31.43 + 31.44 +/** Sxpr type. */ 31.45 +typedef int16_t TypeCode; 31.46 + 31.47 +/** A typed sxpr handle.*/ 31.48 +typedef struct Sxpr { 31.49 + /** Sxpr type. */ 31.50 + TypeCode type; 31.51 + union { 31.52 + /** Sxpr value. */ 31.53 + unsigned long ul; 31.54 + /** Pointer. */ 31.55 + void *ptr; 31.56 + } v; 31.57 +} Sxpr; 31.58 + 31.59 +/** Sxpr type to indicate out of memory. */ 31.60 +#define T_NOMEM ((TypeCode)-1) 31.61 +/** The 'unspecified' sxpr. */ 31.62 +#define T_NONE ((TypeCode)0) 31.63 +/** The empty list. */ 31.64 +#define T_NULL ((TypeCode)1) 31.65 +/** Unsigned integer. */ 31.66 +#define T_UINT ((TypeCode)2) 31.67 +/** A string. */ 31.68 +#define T_STRING ((TypeCode)3) 31.69 +/** An atom. */ 31.70 +#define T_ATOM ((TypeCode)4) 31.71 +/** A boolean. */ 31.72 +#define T_BOOL ((TypeCode)5) 31.73 + 31.74 +/** A cons (pair or list). */ 31.75 +#define T_CONS ((TypeCode)10) 31.76 + 31.77 +/** An error. */ 31.78 +#define T_ERR ((TypeCode)40) 31.79 + 31.80 +/** An atom. */ 31.81 +typedef struct ObjAtom { 31.82 + Sxpr name; 31.83 + Hashcode hashcode; 31.84 + int interned; 31.85 +} ObjAtom; 31.86 + 31.87 +/** A cons (pair). */ 31.88 +typedef struct ObjCons { 31.89 + Sxpr car; 31.90 + Sxpr cdr; 31.91 +} ObjCons; 31.92 + 31.93 +/** A vector. */ 31.94 +typedef struct ObjVector { 31.95 + int n; 31.96 + Sxpr data[0]; 31.97 +} ObjVector; 31.98 + 31.99 +/** Flags for sxpr printing. */ 31.100 +enum PrintFlags { 31.101 + PRINT_RAW = 0x001, 31.102 + PRINT_TYPE = 0x002, 31.103 + PRINT_PRETTY = 0x004, 31.104 + PRINT_NUM = 0x008, 31.105 +}; 31.106 + 31.107 +/** An integer sxpr. 31.108 + * 31.109 + * @param ty type 31.110 + * @param val integer value 31.111 + */ 31.112 +#define OBJI(ty, val) (Sxpr){ type: (ty), v: { ul: (val) }} 31.113 + 31.114 +/** A pointer sxpr. 31.115 + * If the pointer is non-null, returns an sxpr containing it. 31.116 + * If the pointer is null, returns ONOMEM. 31.117 + * 31.118 + * @param ty type 31.119 + * @param val pointer 31.120 + */ 31.121 +#define OBJP(ty, val) ((val) ? (Sxpr){ type: (ty), v: { ptr: (val) }} : ONOMEM) 31.122 + 31.123 +/** Make an integer sxpr containing a pointer. 31.124 + * 31.125 + * @param val pointer 31.126 + */ 31.127 +#define PTR(val) OBJP(T_UINT, (void*)(val)) 31.128 + 31.129 +/** Make an integer sxpr. 31.130 + * @param x value 31.131 + */ 31.132 +#define OINT(x) OBJI(T_UINT, x) 31.133 + 31.134 +/** Make an error sxpr. 31.135 + * 31.136 + * @param x value 31.137 + */ 31.138 +#define OERR(x) OBJI(T_ERR, x) 31.139 + 31.140 +/** Out of memory constant. */ 31.141 +#define ONOMEM OBJI(T_NOMEM, 0) 31.142 + 31.143 +/** The `unspecified' constant. */ 31.144 +#define ONONE OBJI(T_NONE, 0) 31.145 + 31.146 +/** Empty list constant. */ 31.147 +#define ONULL OBJI(T_NULL, 0) 31.148 + 31.149 +/** False constant. */ 31.150 +#define OFALSE OBJI(T_BOOL, 0) 31.151 + 31.152 +/** True constant. */ 31.153 +#define OTRUE OBJI(T_BOOL, 1) 31.154 + 31.155 +/* Recognizers for the various sxpr types. */ 31.156 +#define ATOMP(obj) has_type(obj, T_ATOM) 31.157 +#define BOOLP(obj) has_type(obj, T_BOOL) 31.158 +#define CONSP(obj) has_type(obj, T_CONS) 31.159 +#define ERRP(obj) has_type(obj, T_ERR) 31.160 +#define INTP(obj) has_type(obj, T_UINT) 31.161 +#define NOMEMP(obj) has_type(obj, T_NOMEM) 31.162 +#define NONEP(obj) has_type(obj, T_NONE) 31.163 +#define NULLP(obj) has_type(obj, T_NULL) 31.164 +#define STRINGP(obj) has_type(obj, T_STRING) 31.165 + 31.166 +#define TRUEP(obj) get_ul(obj) 31.167 + 31.168 +/** Convert an sxpr to an unsigned integer. */ 31.169 +#define OBJ_UINT(x) get_ul(x) 31.170 +/** Convert an sxpr to an integer. */ 31.171 +#define OBJ_INT(x) (int)get_ul(x) 31.172 + 31.173 +/* Conversions of sxprs to their values. 31.174 + * No checking is done. 31.175 + */ 31.176 +#define OBJ_STRING(x) ((char*)get_ptr(x)) 31.177 +#define OBJ_CONS(x) ((ObjCons*)get_ptr(x)) 31.178 +#define OBJ_ATOM(x) ((ObjAtom*)get_ptr(x)) 31.179 +#define OBJ_SET(x) ((ObjSet*)get_ptr(x)) 31.180 +#define CAR(x) (OBJ_CONS(x)->car) 31.181 +#define CDR(x) (OBJ_CONS(x)->cdr) 31.182 + 31.183 +#define CAAR(x) (CAR(CAR(x))) 31.184 +#define CADR(x) (CAR(CDR(x))) 31.185 +#define CDAR(x) (CDR(CAR(x))) 31.186 +#define CDDR(x) (CDR(CDR(x))) 31.187 + 31.188 +/** Get the integer value from an sxpr. 31.189 + * 31.190 + * @param obj sxpr 31.191 + * @return value 31.192 + */ 31.193 +static inline unsigned long get_ul(Sxpr obj){ 31.194 + return obj.v.ul; 31.195 +} 31.196 + 31.197 +/** Get the pointer value from an sxpr. 31.198 + * 31.199 + * @param obj sxpr 31.200 + * @return value 31.201 + */ 31.202 +static inline void * get_ptr(Sxpr obj){ 31.203 + return obj.v.ptr; 31.204 +} 31.205 + 31.206 +/** Create an sxpr containing a pointer. 31.207 + * 31.208 + * @param type typecode 31.209 + * @param val pointer 31.210 + * @return sxpr 31.211 + */ 31.212 +static inline Sxpr obj_ptr(TypeCode type, void *val){ 31.213 + return (Sxpr){ type: type, v: { ptr: val } }; 31.214 +} 31.215 + 31.216 +/** Create an sxpr containing an integer. 31.217 + * 31.218 + * @param type typecode 31.219 + * @param val integer 31.220 + * @return sxpr 31.221 + */ 31.222 +static inline Sxpr obj_ul(TypeCode type, unsigned long val){ 31.223 + return (Sxpr){ type: type, v: { ul: val } }; 31.224 +} 31.225 + 31.226 +/** Get the type of an sxpr. 31.227 + * 31.228 + * @param obj sxpr 31.229 + * @return type 31.230 + */ 31.231 +static inline TypeCode get_type(Sxpr obj){ 31.232 + return obj.type; 31.233 +} 31.234 + 31.235 +/** Check the type of an sxpr. 31.236 + * 31.237 + * @param obj sxpr 31.238 + * @param type to check 31.239 + * @return 1 if has the type, 0 otherwise 31.240 + */ 31.241 +static inline int has_type(Sxpr obj, TypeCode type){ 31.242 + return get_type(obj) == type; 31.243 +} 31.244 + 31.245 +/** Compare sxprs for literal equality of type and value. 31.246 + * 31.247 + * @param x sxpr to compare 31.248 + * @param y sxpr to compare 31.249 + * @return 1 if equal, 0 otherwise 31.250 + */ 31.251 +static inline int eq(Sxpr x, Sxpr y){ 31.252 + return ((get_type(x) == get_type(y)) && (get_ul(x) == get_ul(y))); 31.253 +} 31.254 + 31.255 +/** Checked version of CAR 31.256 + * 31.257 + * @param x sxpr 31.258 + * @return CAR if a cons, x otherwise 31.259 + */ 31.260 +static inline Sxpr car(Sxpr x){ 31.261 + return (CONSP(x) ? CAR(x) : x); 31.262 +} 31.263 + 31.264 +/** Checked version of CDR. 31.265 + * 31.266 + * @param x sxpr 31.267 + * @return CDR if a cons, null otherwise 31.268 + */ 31.269 +static inline Sxpr cdr(Sxpr x){ 31.270 + return (CONSP(x) ? CDR(x) : ONULL); 31.271 +} 31.272 + 31.273 +/** Allocate some memory and return an sxpr containing it. 31.274 + * Returns ONOMEM if allocation failed. 31.275 + * 31.276 + * @param n number of bytes to allocate 31.277 + * @param ty typecode 31.278 + * @return sxpr 31.279 + */ 31.280 +static inline Sxpr halloc(size_t n, TypeCode ty){ 31.281 + return OBJP(ty, allocate(n)); 31.282 +} 31.283 + 31.284 +/** Allocate an sxpr containing a pointer to the given type. 31.285 + * 31.286 + * @param ty type (uses sizeof to determine how many bytes to allocate) 31.287 + * @param code typecode 31.288 + * @return sxpr, ONOMEM if allocation failed 31.289 + */ 31.290 +#define HALLOC(ty, code) halloc(sizeof(ty), code) 31.291 + 31.292 +typedef int ObjPrintFn(IOStream *io, Sxpr obj, unsigned flags); 31.293 +typedef int ObjEqualFn(Sxpr obj, Sxpr other); 31.294 +typedef void ObjFreeFn(Sxpr obj); 31.295 + 31.296 +/** An sxpr type definition. */ 31.297 +typedef struct SxprType { 31.298 + TypeCode type; 31.299 + char *name; 31.300 + int pointer; 31.301 + ObjPrintFn *print; 31.302 + ObjEqualFn *equal; 31.303 + ObjFreeFn *free; 31.304 +} SxprType; 31.305 + 31.306 + 31.307 +extern SxprType *get_sxpr_type(int ty); 31.308 + 31.309 +/** Free the pointer in an sxpr. 31.310 + * 31.311 + * @param x sxpr containing a pointer 31.312 + */ 31.313 +static inline void hfree(Sxpr x){ 31.314 + deallocate(get_ptr(x)); 31.315 +} 31.316 + 31.317 +extern int objprint(IOStream *io, Sxpr x, unsigned flags); 31.318 +extern int objequal(Sxpr x, Sxpr y); 31.319 +extern void objfree(Sxpr x); 31.320 + 31.321 +extern void cons_free_cells(Sxpr obj); 31.322 +extern Sxpr intern(char *s); 31.323 + 31.324 +extern Sxpr assoc(Sxpr k, Sxpr l); 31.325 +extern Sxpr assocq(Sxpr k, Sxpr l); 31.326 +extern Sxpr acons(Sxpr k, Sxpr v, Sxpr l); 31.327 +extern Sxpr nrev(Sxpr l); 31.328 +extern Sxpr cons_member(Sxpr l, Sxpr x); 31.329 +extern Sxpr cons_member_if(Sxpr l, ObjEqualFn *test_fn, Sxpr v); 31.330 +extern int cons_subset(Sxpr s, Sxpr t); 31.331 +extern int cons_set_equal(Sxpr s, Sxpr t); 31.332 + 31.333 +#ifdef USE_GC 31.334 +extern Sxpr cons_remove(Sxpr l, Sxpr x); 31.335 +extern Sxpr cons_remove_if(Sxpr l, ObjEqualFn *test_fn, Sxpr v); 31.336 +#endif 31.337 + 31.338 +extern Sxpr atom_new(char *name); 31.339 +extern char * atom_name(Sxpr obj); 31.340 + 31.341 +extern Sxpr string_new(char *s); 31.342 +extern char * string_string(Sxpr obj); 31.343 +extern int string_length(Sxpr obj); 31.344 + 31.345 +extern Sxpr cons_new(Sxpr car, Sxpr cdr); 31.346 +extern int cons_push(Sxpr *list, Sxpr elt); 31.347 +extern int cons_length(Sxpr obj); 31.348 + 31.349 +Sxpr sxpr_name(Sxpr obj); 31.350 +int sxpr_is(Sxpr obj, char *s); 31.351 +int sxpr_elementp(Sxpr obj, Sxpr name); 31.352 +Sxpr sxpr_attributes(Sxpr obj); 31.353 +Sxpr sxpr_attribute(Sxpr obj, Sxpr key, Sxpr def); 31.354 +Sxpr sxpr_children(Sxpr obj); 31.355 +Sxpr sxpr_child(Sxpr obj, Sxpr name, Sxpr def); 31.356 +Sxpr sxpr_child0(Sxpr obj, Sxpr def); 31.357 +Sxpr sxpr_child_value(Sxpr obj, Sxpr name, Sxpr def); 31.358 + 31.359 +/** Create a new atom. 31.360 + * 31.361 + * @param s atom name 31.362 + * @return new atom 31.363 + */ 31.364 +static inline Sxpr mkatom(char *s){ 31.365 + return atom_new(s); 31.366 +} 31.367 + 31.368 +/** Create a new string sxpr. 31.369 + * 31.370 + * @param s string bytes (copied) 31.371 + * @return new string 31.372 + */ 31.373 +static inline Sxpr mkstring(char *s){ 31.374 + return string_new(s); 31.375 +} 31.376 + 31.377 +/** Create an integer sxpr. 31.378 + * 31.379 + * @param i value 31.380 + * @return sxpr 31.381 + */ 31.382 +static inline Sxpr mkint(int i){ 31.383 + return OBJI(T_UINT, i); 31.384 +} 31.385 + 31.386 +/** Create a boolean sxpr. 31.387 + * 31.388 + * @param b value 31.389 + * @return sxpr 31.390 + */ 31.391 +static inline Sxpr mkbool(int b){ 31.392 + return OBJI(T_BOOL, (b ? 1 : 0)); 31.393 +} 31.394 + 31.395 +/* Constants used in parsing and printing. */ 31.396 +#define k_list_open "(" 31.397 +#define c_list_open '(' 31.398 +#define k_list_close ")" 31.399 +#define c_list_close ')' 31.400 +#define k_true "true" 31.401 +#define k_false "false" 31.402 + 31.403 +#define c_var '$' 31.404 +#define c_escape '\\' 31.405 +#define c_single_quote '\'' 31.406 +#define c_double_quote '"' 31.407 +#define c_string_open c_double_quote 31.408 +#define c_string_close c_double_quote 31.409 +#define c_data_open '[' 31.410 +#define c_data_close ']' 31.411 +#define c_binary '*' 31.412 +#define c_eval '!' 31.413 +#define c_concat_open '{' 31.414 +#define c_concat_close '}' 31.415 + 31.416 +#endif /* ! _XEN_LIB_SXPR_H_ */
32.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 32.2 +++ b/tools/lib/sxpr_parser.c Mon Jun 28 15:03:15 2004 +0000 32.3 @@ -0,0 +1,897 @@ 32.4 + 32.5 +#ifdef __KERNEL__ 32.6 +# include <linux/config.h> 32.7 +# include <linux/module.h> 32.8 +# include <linux/kernel.h> 32.9 +# include <linux/string.h> 32.10 +# include <linux/errno.h> 32.11 +#else 32.12 +# include <stdlib.h> 32.13 +# include <errno.h> 32.14 +#endif 32.15 + 32.16 +#include "iostream.h" 32.17 +#include "lexis.h" 32.18 +#include "sxpr_parser.h" 32.19 +#include "sys_string.h" 32.20 + 32.21 +/** @file 32.22 + * Sxpr parsing. 32.23 + * 32.24 + * So that the parser does not leak memory, all sxprs constructed by 32.25 + * the parser must be freed on error. On successful parse the sxpr 32.26 + * returned becomes the responsibility of the caller. 32.27 + * 32.28 + * @author Mike Wray <mike.wray@hpl.hp.com> 32.29 + */ 32.30 + 32.31 +#define dprintf(fmt, args...) IOStream_print(iostdout, "[DEBUG] %s" fmt, __FUNCTION__, ##args) 32.32 +#define printf(fmt, args...) IOStream_print(iostdout, fmt, ##args) 32.33 + 32.34 +static void reset(Parser *z); 32.35 +static int inputchar(Parser *p, char c); 32.36 +static int savechar(Parser *p, char c); 32.37 +extern void parse_error(Parser *in); 32.38 +extern void parse_error_id(Parser *in, ParseErrorId id); 32.39 + 32.40 +static int begin_start(Parser *p, char c); 32.41 +static int state_start(Parser *p, char c); 32.42 +static int end_start(Parser *p); 32.43 + 32.44 +static int begin_comment(Parser *p, char c); 32.45 +static int state_comment(Parser *p, char c); 32.46 +static int end_comment(Parser *p); 32.47 + 32.48 +static int begin_string(Parser *p, char c); 32.49 +static int state_string(Parser *p, char c); 32.50 +static int end_string(Parser *p); 32.51 +static int state_escape(Parser *p, char c); 32.52 +static int state_octal(Parser *p, char c); 32.53 +static int state_hex(Parser *p, char c); 32.54 + 32.55 +static int begin_atom(Parser *p, char c); 32.56 +static int state_atom(Parser *p, char c); 32.57 +static int end_atom(Parser *p); 32.58 + 32.59 +static int state_list(Parser *p, char c); 32.60 +static int begin_list(Parser *p, char c); 32.61 +static int end_list(Parser *p); 32.62 + 32.63 +/** Print a parse error. 32.64 + * 32.65 + * @param in parser 32.66 + * @param msg format followed by printf arguments 32.67 + */ 32.68 +void eprintf(Parser *in, char *msg, ...){ 32.69 + va_list args; 32.70 + if(in->error_out){ 32.71 + va_start(args, msg); 32.72 + IOStream_vprint(in->error_out, msg, args); 32.73 + va_end(args); 32.74 + } 32.75 +} 32.76 + 32.77 +/** Print a parse warning. 32.78 + * 32.79 + * @param in parser 32.80 + * @param msg format followed by printf arguments 32.81 + */ 32.82 +void wprintf(Parser *in, char *msg, ...){ 32.83 + va_list args; 32.84 + if(in->error_out){ 32.85 + va_start(args, msg); 32.86 + IOStream_vprint(in->error_out, msg, args); 32.87 + va_end(args); 32.88 + } 32.89 +} 32.90 + 32.91 +/*============================================================================*/ 32.92 + 32.93 +/** Record defining the message for a parse error. */ 32.94 +typedef struct { 32.95 + ParseErrorId id; 32.96 + char *message; 32.97 +} ParseError; 32.98 + 32.99 +/** Format for printing parse error messages. */ 32.100 +#define PARSE_ERR_FMT "parse error> line %3d, column %2d: %s" 32.101 + 32.102 +/** Message catalog for the parse error codes. */ 32.103 +static ParseError catalog[] = { 32.104 + { PARSE_ERR_UNSPECIFIED, "unspecified error" }, 32.105 + { PARSE_ERR_NOMEM, "out of memory" }, 32.106 + { PARSE_ERR_UNEXPECTED_EOF, "unexpected end of input" }, 32.107 + { PARSE_ERR_TOKEN_TOO_LONG, "token too long" }, 32.108 + { PARSE_ERR_INVALID_SYNTAX, "syntax error" }, 32.109 + { PARSE_ERR_INVALID_ESCAPE, "invalid escape" }, 32.110 + { 0, NULL } 32.111 +}; 32.112 + 32.113 +/** Number of entries in the message catalog. */ 32.114 +const static int catalog_n = sizeof(catalog)/sizeof(ParseError); 32.115 + 32.116 +void ParserState_free(ParserState *z){ 32.117 + if(!z) return; 32.118 + objfree(z->val); 32.119 + deallocate(z); 32.120 +} 32.121 + 32.122 +int ParserState_new(ParserStateFn *fn, ParserState *parent, ParserState **val){ 32.123 + int err = 0; 32.124 + ParserState *z; 32.125 + z = ALLOCATE(ParserState); 32.126 + if(z){ 32.127 + z->fn = fn; 32.128 + z->parent = parent; 32.129 + z->val = ONULL; 32.130 + } else { 32.131 + err = -ENOMEM; 32.132 + } 32.133 + if(!err) *val = z; 32.134 + return err; 32.135 +} 32.136 + 32.137 +/** Free a parser. 32.138 + * No-op if the parser is null. 32.139 + * 32.140 + * @param z parser 32.141 + */ 32.142 +void Parser_free(Parser *z){ 32.143 + if(!z) return; 32.144 + objfree(z->val); 32.145 + z->val = ONONE; 32.146 + deallocate(z); 32.147 +} 32.148 + 32.149 +/** Create a new parser. The error stream defaults to null. 32.150 + */ 32.151 +Parser * Parser_new(void){ 32.152 + Parser *z = ALLOCATE(Parser); 32.153 + int err = -ENOMEM; 32.154 + 32.155 + if(!z) goto exit; 32.156 + err = 0; 32.157 + reset(z); 32.158 + exit: 32.159 + if(err){ 32.160 + Parser_free(z); 32.161 + z = NULL; 32.162 + } 32.163 + return z; 32.164 +} 32.165 + 32.166 +/** Get the next character. 32.167 + * Records the character read in the parser, 32.168 + * and sets the line and character counts. 32.169 + * 32.170 + * @param p parser 32.171 + * @return error flag: 0 on success, non-zero on error 32.172 + */ 32.173 +static int inputchar(Parser *p, char c){ 32.174 + int err = 0; 32.175 + if(c=='\n'){ 32.176 + p->line_no++; 32.177 + p->char_no = 0; 32.178 + } else { 32.179 + p->char_no++; 32.180 + } 32.181 + return err; 32.182 +} 32.183 + 32.184 +static int savechar(Parser *p, char c){ 32.185 + int err = 0; 32.186 + if(p->buf_i >= p->buf_n){ 32.187 + err = -ENOMEM; 32.188 + goto exit; 32.189 + } 32.190 + p->buf[p->buf_i] = c; 32.191 + p->buf_i++; 32.192 + exit: 32.193 + return err; 32.194 +} 32.195 + 32.196 +int Parser_input_char(Parser *p, char c){ 32.197 + int err = 0; 32.198 + if(at_eof(p)){ 32.199 + //skip; 32.200 + } else { 32.201 + inputchar(p, c); 32.202 + } 32.203 + if(!p->state){ 32.204 + err = begin_start(p, c); 32.205 + if(err) goto exit; 32.206 + } 32.207 + err = p->state->fn(p, c); 32.208 + exit: 32.209 + return err; 32.210 +} 32.211 + 32.212 +int Parser_input_eof(Parser *p){ 32.213 + int err = 0; 32.214 + p->eof = 1; 32.215 + err = Parser_input_char(p, IOSTREAM_EOF); 32.216 + return err; 32.217 +} 32.218 + 32.219 +int Parser_input(Parser *p, char *buf, int buf_n){ 32.220 + int err = 0; 32.221 + int i = 0; 32.222 + if(buf_n <= 0){ 32.223 + err = Parser_input_eof(p); 32.224 + goto exit; 32.225 + } 32.226 + for(i = 0; i<buf_n; i++){ 32.227 + err = Parser_input_char(p, buf[i]); 32.228 + if(err) goto exit; 32.229 + } 32.230 + exit: 32.231 + err = (err < 0 ? err : buf_n); 32.232 + return err; 32.233 +} 32.234 + 32.235 +int Parser_push(Parser *p, ParserStateFn *fn){ 32.236 + int err = 0; 32.237 + err = ParserState_new(fn, p->state, &p->state); 32.238 + return err; 32.239 +} 32.240 + 32.241 +int Parser_pop(Parser *p){ 32.242 + int err = 0; 32.243 + ParserState *s = p->state; 32.244 + p->state = s->parent; 32.245 + ParserState_free(s); 32.246 + return err; 32.247 +} 32.248 + 32.249 +int Parser_return(Parser *p){ 32.250 + int err = 0; 32.251 + Sxpr val = ONONE; 32.252 + if(!p->state){ 32.253 + err = -EINVAL; 32.254 + goto exit; 32.255 + } 32.256 + val = p->state->val; 32.257 + p->state->val = ONONE; 32.258 + err = Parser_pop(p); 32.259 + if(err) goto exit; 32.260 + if(p->state){ 32.261 + err = cons_push(&p->state->val, val); 32.262 + } else { 32.263 + val = nrev(val); 32.264 + p->val = val; 32.265 + } 32.266 + exit: 32.267 + if(err){ 32.268 + objfree(val); 32.269 + } 32.270 + return err; 32.271 +} 32.272 + 32.273 +/** Determine if a character is a separator. 32.274 + * 32.275 + * @param p parser 32.276 + * @param c character to test 32.277 + * @return 1 if a separator, 0 otherwise 32.278 + */ 32.279 +static int is_separator(Parser *p, char c){ 32.280 + return in_sep_class(c); 32.281 +} 32.282 + 32.283 +/** Return the current token. 32.284 + * The return value points at the internal buffer, so 32.285 + * it must not be modified (or freed). Use copy_token() if you need a copy. 32.286 + * 32.287 + * @param p parser 32.288 + * @return token 32.289 + */ 32.290 +char *peek_token(Parser *p){ 32.291 + return p->buf; 32.292 +} 32.293 + 32.294 +/** Return a copy of the current token. 32.295 + * The returned value should be freed when finished with. 32.296 + * 32.297 + * @param p parser 32.298 + * @return copy of token 32.299 + */ 32.300 +char *copy_token(Parser *p){ 32.301 + return strdup(peek_token(p)); 32.302 +} 32.303 + 32.304 +static int do_intern(Parser *p){ 32.305 + int err = 0; 32.306 + Sxpr obj = intern(peek_token(p)); 32.307 + if(NOMEMP(obj)){ 32.308 + err = -ENOMEM; 32.309 + } else { 32.310 + p->state->val = obj; 32.311 + } 32.312 + return err; 32.313 +} 32.314 + 32.315 +static int do_string(Parser *p){ 32.316 + int err = 0; 32.317 + Sxpr obj; 32.318 + obj = string_new(peek_token(p)); 32.319 + if(NOMEMP(obj)){ 32.320 + err = -ENOMEM; 32.321 + } else { 32.322 + p->state->val = obj; 32.323 + } 32.324 + return err; 32.325 +} 32.326 + 32.327 +void newtoken(Parser *p){ 32.328 + memset(p->buf, 0, p->buf_n); 32.329 + p->buf_i = 0; 32.330 + p->tok_begin_line = p->line_no; 32.331 + p->tok_begin_char = p->char_no; 32.332 +} 32.333 + 32.334 +int get_escape(char c, char *d){ 32.335 + int err = 0; 32.336 + switch(c){ 32.337 + case 'a': *d = '\a'; break; 32.338 + case 'b': *d = '\b'; break; 32.339 + case 'f': *d = '\f'; break; 32.340 + case 'n': *d = '\n'; break; 32.341 + case 'r': *d = '\r'; break; 32.342 + case 't': *d = '\t'; break; 32.343 + case 'v': *d = '\v'; break; 32.344 + case c_escape: *d = c_escape; break; 32.345 + case c_single_quote: *d = c_single_quote; break; 32.346 + case c_double_quote: *d = c_double_quote; break; 32.347 + default: 32.348 + err = -EINVAL; 32.349 + } 32.350 + return err; 32.351 +} 32.352 + 32.353 + 32.354 +int begin_start(Parser *p, char c){ 32.355 + return Parser_push(p, state_start); 32.356 +} 32.357 + 32.358 +int state_start(Parser *p, char c){ 32.359 + int err = 0; 32.360 + if(at_eof(p)){ 32.361 + err = end_start(p); 32.362 + } else if(in_space_class(c)){ 32.363 + //skip 32.364 + } else if(in_comment_class(c)){ 32.365 + begin_comment(p, c); 32.366 + } else if(c == c_list_open){ 32.367 + begin_list(p, c); 32.368 + } else if(c == c_list_close){ 32.369 + parse_error(p); 32.370 + err = -EINVAL; 32.371 + } else if(in_string_quote_class(c)){ 32.372 + begin_string(p, c); 32.373 + } else if(in_printable_class(c)){ 32.374 + begin_atom(p, c); 32.375 + } else if(c == 0x04){ 32.376 + //ctrl-D, EOT: end-of-text. 32.377 + Parser_input_eof(p); 32.378 + } else { 32.379 + parse_error(p); 32.380 + err = -EINVAL; 32.381 + } 32.382 + return err; 32.383 +} 32.384 + 32.385 +int end_start(Parser *p){ 32.386 + int err = 0; 32.387 + err = Parser_return(p); 32.388 + return err; 32.389 +} 32.390 + 32.391 +int begin_comment(Parser *p, char c){ 32.392 + int err = 0; 32.393 + err = Parser_push(p, state_comment); 32.394 + if(err) goto exit; 32.395 + err = inputchar(p, c); 32.396 + exit: 32.397 + return err; 32.398 +} 32.399 + 32.400 +int state_comment(Parser *p, char c){ 32.401 + int err = 0; 32.402 + if(c == '\n' || at_eof(p)){ 32.403 + err = end_comment(p); 32.404 + } else { 32.405 + err = inputchar(p, c); 32.406 + } 32.407 + return err; 32.408 +} 32.409 + 32.410 +int end_comment(Parser *p){ 32.411 + return Parser_pop(p); 32.412 +} 32.413 + 32.414 +int begin_string(Parser *p, char c){ 32.415 + int err = 0; 32.416 + err = Parser_push(p, state_string); 32.417 + if(err) goto exit; 32.418 + newtoken(p); 32.419 + p->state->delim = c; 32.420 + exit: 32.421 + return err; 32.422 +} 32.423 + 32.424 +int state_string(Parser *p, char c){ 32.425 + int err = 0; 32.426 + if(at_eof(p)){ 32.427 + parse_error_id(p, PARSE_ERR_UNEXPECTED_EOF); 32.428 + err = -EINVAL; 32.429 + } else if(c == p->state->delim){ 32.430 + err = end_string(p); 32.431 + } else if(c == '\\'){ 32.432 + err = Parser_push(p, state_escape); 32.433 + } else { 32.434 + err = savechar(p, c); 32.435 + } 32.436 + return err; 32.437 +} 32.438 + 32.439 +int end_string(Parser *p){ 32.440 + int err = 0; 32.441 + err = do_string(p); 32.442 + if(err) goto exit; 32.443 + err = Parser_return(p); 32.444 + exit: 32.445 + return err; 32.446 +} 32.447 + 32.448 +int state_escape(Parser *p, char c){ 32.449 + int err = 0; 32.450 + char d; 32.451 + if(at_eof(p)){ 32.452 + parse_error_id(p, PARSE_ERR_UNEXPECTED_EOF); 32.453 + err = -EINVAL; 32.454 + goto exit; 32.455 + } 32.456 + if(get_escape(c, &d) == 0){ 32.457 + err = savechar(p, d); 32.458 + if(err) goto exit; 32.459 + err = Parser_pop(p); 32.460 + } else if(c == 'x'){ 32.461 + p->state->fn = state_hex; 32.462 + p->state->ival = 0; 32.463 + p->state->count = 0; 32.464 + } else { 32.465 + p->state->fn = state_octal; 32.466 + p->state->ival = 0; 32.467 + p->state->count = 0; 32.468 + err = Parser_input_char(p, c); 32.469 + } 32.470 + exit: 32.471 + return err; 32.472 +} 32.473 + 32.474 +int octaldone(Parser *p){ 32.475 + int err = 0; 32.476 + char d = (char)(p->state->ival & 0xff); 32.477 + err = Parser_pop(p); 32.478 + if(err) goto exit; 32.479 + err = Parser_input_char(p, d); 32.480 + exit: 32.481 + return err; 32.482 +} 32.483 + 32.484 +int octaldigit(Parser *p, char c){ 32.485 + int err = 0; 32.486 + p->state->ival *= 8; 32.487 + p->state->ival += c - '0'; 32.488 + p->state->count++; 32.489 + if(err) goto exit; 32.490 + if(p->state->ival < 0 || p->state->ival > 0xff){ 32.491 + parse_error(p); 32.492 + err = -EINVAL; 32.493 + goto exit; 32.494 + } 32.495 + if(p->state->count == 3){ 32.496 + err = octaldone(p); 32.497 + } 32.498 + exit: 32.499 + return err; 32.500 +} 32.501 + 32.502 +int state_octal(Parser *p, char c){ 32.503 + int err = 0; 32.504 + if(at_eof(p)){ 32.505 + parse_error_id(p, PARSE_ERR_UNEXPECTED_EOF); 32.506 + err = -EINVAL; 32.507 + goto exit; 32.508 + } else if('0' <= c && c <= '7'){ 32.509 + err = octaldigit(p, c); 32.510 + } else { 32.511 + err = octaldone(p); 32.512 + if(err) goto exit; 32.513 + Parser_input_char(p, c); 32.514 + } 32.515 + exit: 32.516 + return err; 32.517 +} 32.518 + 32.519 +int hexdone(Parser *p){ 32.520 + int err = 0; 32.521 + char d = (char)(p->state->ival & 0xff); 32.522 + err = Parser_pop(p); 32.523 + if(err) goto exit; 32.524 + err = Parser_input_char(p, d); 32.525 + exit: 32.526 + return err; 32.527 +} 32.528 + 32.529 +int hexdigit(Parser *p, char c, char d){ 32.530 + int err = 0; 32.531 + p->state->ival *= 16; 32.532 + p->state->ival += c - d; 32.533 + p->state->count++; 32.534 + if(err) goto exit; 32.535 + if(p->state->ival < 0 || p->state->ival > 0xff){ 32.536 + parse_error(p); 32.537 + err = -EINVAL; 32.538 + goto exit; 32.539 + } 32.540 + if(p->state->count == 2){ 32.541 + err = hexdone(p); 32.542 + } 32.543 + exit: 32.544 + return err; 32.545 +} 32.546 + 32.547 +int state_hex(Parser *p, char c){ 32.548 + int err = 0; 32.549 + if(at_eof(p)){ 32.550 + parse_error_id(p, PARSE_ERR_UNEXPECTED_EOF); 32.551 + err = -EINVAL; 32.552 + goto exit; 32.553 + } else if('0' <= c && c <= '9'){ 32.554 + err = hexdigit(p, c, '0'); 32.555 + } else if('A' <= c && c <= 'F'){ 32.556 + err = hexdigit(p, c, 'A'); 32.557 + } else if('a' <= c && c <= 'f'){ 32.558 + err = hexdigit(p, c, 'a'); 32.559 + } else if(p->state->count){ 32.560 + err =hexdone(p); 32.561 + if(err) goto exit; 32.562 + Parser_input_char(p, c); 32.563 + } 32.564 + exit: 32.565 + return err; 32.566 +} 32.567 + 32.568 +int begin_atom(Parser *p, char c){ 32.569 + int err = 0; 32.570 + err = Parser_push(p, state_atom); 32.571 + if(err) goto exit; 32.572 + newtoken(p); 32.573 + err = savechar(p, c); 32.574 + exit: 32.575 + return err; 32.576 +} 32.577 + 32.578 +int state_atom(Parser *p, char c){ 32.579 + int err = 0; 32.580 + if(at_eof(p)){ 32.581 + err = end_atom(p); 32.582 + } else if(is_separator(p, c) || 32.583 + in_space_class(c) || 32.584 + in_comment_class(c)){ 32.585 + err = end_atom(p); 32.586 + if(err) goto exit; 32.587 + err = Parser_input_char(p, c); 32.588 + } else { 32.589 + err = savechar(p, c); 32.590 + } 32.591 + exit: 32.592 + return err; 32.593 +} 32.594 + 32.595 +int end_atom(Parser *p){ 32.596 + int err = 0; 32.597 + err = do_intern(p); 32.598 + if(err) goto exit; 32.599 + err = Parser_return(p); 32.600 + exit: 32.601 + return err; 32.602 +} 32.603 + 32.604 +int state_list(Parser *p, char c){ 32.605 + int err = 0; 32.606 + if(at_eof(p)){ 32.607 + parse_error_id(p, PARSE_ERR_UNEXPECTED_EOF); 32.608 + err = -EINVAL; 32.609 + } else if(c == c_list_close){ 32.610 + p->state->val = nrev(p->state->val); 32.611 + err = end_list(p); 32.612 + } else { 32.613 + err = state_start(p, c); 32.614 + } 32.615 + return err; 32.616 + 32.617 +} 32.618 + 32.619 +int begin_list(Parser *p, char c){ 32.620 + return Parser_push(p, state_list); 32.621 +} 32.622 + 32.623 +int end_list(Parser *p){ 32.624 + return Parser_return(p); 32.625 +} 32.626 + 32.627 +/** Reset the fields of a parser to initial values. 32.628 + * 32.629 + * @param z parser 32.630 + */ 32.631 +static void reset(Parser *z){ 32.632 + IOStream *error_out = z->error_out; 32.633 + int flags = z->flags; 32.634 + zero(z, sizeof(Parser)); 32.635 + z->buf_n = sizeof(z->buf) - 1; 32.636 + z->buf_i = 0; 32.637 + z->line_no = 1; 32.638 + z->char_no = 0; 32.639 + z->error_out = error_out; 32.640 + z->flags = flags; 32.641 +} 32.642 + 32.643 +/** Set the parser error stream. 32.644 + * Parse errors are reported on the the error stream if it is non-null. 32.645 + * 32.646 + * @param z parser 32.647 + * @param error_out error stream 32.648 + */ 32.649 +void set_error_stream(Parser *z, IOStream *error_out){ 32.650 + if(z){ 32.651 + z->error_out = error_out; 32.652 + } 32.653 +} 32.654 + 32.655 +/** Get the parser error message for an error code. 32.656 + * 32.657 + * @param id error code 32.658 + * @return error message (empty string if the code is unknown) 32.659 + */ 32.660 +static char *get_message(ParseErrorId id){ 32.661 + int i; 32.662 + for(i=0; i<catalog_n; i++){ 32.663 + if(id == catalog[i].id){ 32.664 + return catalog[i].message; 32.665 + } 32.666 + } 32.667 + return ""; 32.668 +} 32.669 + 32.670 +/** Get the line number. 32.671 + * 32.672 + * @param in parser 32.673 + */ 32.674 +int get_line(Parser *in){ 32.675 + return in->line_no; 32.676 +} 32.677 + 32.678 +/** Get the column number. 32.679 + * 32.680 + * @param in parser 32.681 + */ 32.682 +int get_column(Parser *in){ 32.683 + return in->char_no; 32.684 +} 32.685 + 32.686 +/** Get the line number the current token started on. 32.687 + * 32.688 + * @param in parser 32.689 + */ 32.690 +int get_tok_line(Parser *in){ 32.691 + return in->tok_begin_line; 32.692 +} 32.693 + 32.694 +/** Get the column number the current token started on. 32.695 + * 32.696 + * @param in parser 32.697 + */ 32.698 +int get_tok_column(Parser *in){ 32.699 + return in->tok_begin_char; 32.700 +} 32.701 + 32.702 +/** Report a parse error. 32.703 + * Does nothing if the error stream is null or there is no error. 32.704 + * 32.705 + * @param in parser 32.706 + */ 32.707 +static void report_error(Parser *in){ 32.708 + if(in->error_out && in->err){ 32.709 + char *msg = get_message(in->err); 32.710 + char *tok = peek_token(in); 32.711 + IOStream_print(in->error_out, PARSE_ERR_FMT, 32.712 + get_tok_line(in), get_tok_column(in), msg); 32.713 + if(tok && tok[0]){ 32.714 + IOStream_print(in->error_out, " '%s'", tok); 32.715 + } 32.716 + IOStream_print(in->error_out, "\n"); 32.717 + } 32.718 +} 32.719 + 32.720 +/** Get the error message for the current parse error code. 32.721 + * Does nothing if there is no error. 32.722 + * 32.723 + * @param in parser 32.724 + * @param buf where to place the message 32.725 + * @param n maximum number of characters to place in buf 32.726 + * @return current error code (zero for no error) 32.727 + */ 32.728 +int parse_error_message(Parser *in, char *buf, int n){ 32.729 + if(in->err){ 32.730 + char *msg = get_message(in->err); 32.731 + snprintf(buf, n, PARSE_ERR_FMT, get_tok_line(in), get_tok_column(in), msg); 32.732 + } 32.733 + return in->err; 32.734 +} 32.735 + 32.736 +/** Flag an unspecified parse error. All subsequent reads will fail. 32.737 + * 32.738 + * @param in parser 32.739 + */ 32.740 +void parse_error(Parser *in){ 32.741 + parse_error_id(in, PARSE_ERR_INVALID_SYNTAX); 32.742 +} 32.743 + 32.744 +/** Flag a parse error. All subsequent reads will fail. 32.745 + * Does not change the parser error code if it is already set. 32.746 + * 32.747 + * @param in parser 32.748 + * @param id error code 32.749 + */ 32.750 +void parse_error_id(Parser *in, ParseErrorId id){ 32.751 + if(!in->err){ 32.752 + in->err = id; 32.753 + report_error(in); 32.754 + } 32.755 +} 32.756 + 32.757 +/** Test if the parser's error flag is set. 32.758 + * 32.759 + * @param in parser 32.760 + * @return 1 if set, 0 otherwise 32.761 + */ 32.762 +int has_error(Parser *in){ 32.763 + return (in->err > 0); 32.764 +} 32.765 + 32.766 +/** Test if the parser is at end of input. 32.767 + * 32.768 + * @param in parser 32.769 + * @return 1 if at EOF, 0 otherwise 32.770 + */ 32.771 +int at_eof(Parser *p){ 32.772 + return p->eof; 32.773 +} 32.774 + 32.775 +#ifdef SXPR_PARSER_MAIN 32.776 +/* Stuff for standalone testing. */ 32.777 + 32.778 +#include "file_stream.h" 32.779 +#include "string_stream.h" 32.780 + 32.781 +int stringof(Sxpr exp, char **s){ 32.782 + int err = 0; 32.783 + if(ATOMP(exp)){ 32.784 + *s = atom_name(exp); 32.785 + } else if(STRINGP(exp)){ 32.786 + *s = string_string(exp); 32.787 + } else { 32.788 + err = -EINVAL; 32.789 + *s = NULL; 32.790 + } 32.791 + return err; 32.792 +} 32.793 + 32.794 +int child_string(Sxpr exp, Sxpr key, char **s){ 32.795 + int err = 0; 32.796 + Sxpr val = sxpr_child_value(exp, key, ONONE); 32.797 + err = stringof(val, s); 32.798 + return err; 32.799 +} 32.800 + 32.801 +int intof(Sxpr exp, int *v){ 32.802 + int err = 0; 32.803 + char *s; 32.804 + unsigned long l; 32.805 + if(INTP(exp)){ 32.806 + *v = OBJ_INT(exp); 32.807 + } else { 32.808 + err = stringof(exp, &s); 32.809 + if(err) goto exit; 32.810 + err = convert_atoul(s, &l); 32.811 + *v = (int)l; 32.812 + } 32.813 + exit: 32.814 + return err; 32.815 +} 32.816 + 32.817 +int child_int(Sxpr exp, Sxpr key, int *v){ 32.818 + int err = 0; 32.819 + Sxpr val = sxpr_child_value(exp, key, ONONE); 32.820 + err = intof(val, v); 32.821 + return err; 32.822 +} 32.823 + 32.824 +int eval_vnet(Sxpr exp){ 32.825 + int err = 0; 32.826 + Sxpr oid = intern("id"); 32.827 + int id; 32.828 + err = child_int(exp, oid, &id); 32.829 + if(err) goto exit; 32.830 + dprintf("> vnet id=%d\n", id); 32.831 + exit: 32.832 + dprintf("< err=%d\n", err); 32.833 + return err; 32.834 +} 32.835 + 32.836 +int eval_connect(Sxpr exp){ 32.837 + int err = 0; 32.838 + Sxpr ovif = intern("vif"); 32.839 + Sxpr ovnet = intern("vnet"); 32.840 + char *vif; 32.841 + int vnet; 32.842 + 32.843 + err = child_string(exp, ovif, &vif); 32.844 + if(err) goto exit; 32.845 + err = child_int(exp, ovnet, &vnet); 32.846 + if(err) goto exit; 32.847 + dprintf("> connect vif=%s vnet=%d\n", vif, vnet); 32.848 + exit: 32.849 + dprintf("< err=%d\n", err); 32.850 + return err; 32.851 +} 32.852 + 32.853 +int eval(Sxpr exp){ 32.854 + int err = 0; 32.855 + Sxpr oconnect = intern("connect"); 32.856 + Sxpr ovnet = intern("vnet"); 32.857 + 32.858 + if(sxpr_elementp(exp, ovnet)){ 32.859 + err = eval_vnet(exp); 32.860 + } else if(sxpr_elementp(exp, oconnect)){ 32.861 + err = eval_connect(exp); 32.862 + } else { 32.863 + err = -EINVAL; 32.864 + } 32.865 + return err; 32.866 +} 32.867 + 32.868 +/** Main program for testing. 32.869 + * Parses input and prints it. 32.870 + * 32.871 + * @param argc number of arguments 32.872 + * @param argv arguments 32.873 + * @return error code 32.874 + */ 32.875 +int main(int argc, char *argv[]){ 32.876 + Parser *pin; 32.877 + int err = 0; 32.878 + char buf[1024]; 32.879 + int k; 32.880 + Sxpr obj, l, x; 32.881 + 32.882 + pin = Parser_new(); 32.883 + set_error_stream(pin, iostdout); 32.884 + dprintf("> parse...\n"); 32.885 + while(1){ 32.886 + k = fread(buf, 1, 1024, stdin); 32.887 + err = Parser_input(pin, buf, k); 32.888 + dprintf("> Parser_input=%d\n", err); 32.889 + if(k <= 0) break; 32.890 + } 32.891 + obj = pin->val; 32.892 + for(l = obj ; CONSP(l); l = CDR(l)){ 32.893 + x = CAR(l); 32.894 + objprint(iostdout, x, 0); printf("\n"); 32.895 + eval(x); 32.896 + } 32.897 + dprintf("> err=%d\n", err); 32.898 + return 0; 32.899 +} 32.900 +#endif
33.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 33.2 +++ b/tools/lib/sxpr_parser.h Mon Jun 28 15:03:15 2004 +0000 33.3 @@ -0,0 +1,125 @@ 33.4 +/* 33.5 + * 33.6 + * This library is free software; you can redistribute it and/or modify 33.7 + * it under the terms of the GNU Lesser General Public License as 33.8 + * published by the Free Software Foundation; either version 2.1 of the 33.9 + * License, or (at your option) any later version. This library is 33.10 + * distributed in the hope that it will be useful, but WITHOUT ANY 33.11 + * WARRANTY; without even the implied warranty of MERCHANTABILITY or 33.12 + * FITNESS FOR A PARTICULAR PURPOSE. 33.13 + * See the GNU Lesser General Public License for more details. 33.14 + * 33.15 + * You should have received a copy of the GNU Lesser General Public License 33.16 + * along with this library; if not, write to the Free Software Foundation, 33.17 + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 33.18 + */ 33.19 + 33.20 +#ifndef _XEN_LIB_SXPR_PARSER_H_ 33.21 +#define _XEN_LIB_SXPR_PARSER_H_ 33.22 + 33.23 +#include "sxpr.h" 33.24 +#include "iostream.h" 33.25 + 33.26 +/** @file 33.27 + * Sxpr parsing definitions. 33.28 + */ 33.29 + 33.30 +/** Size of a parser input buffer. 33.31 + * Tokens read must fit into this size (including trailing null). 33.32 + */ 33.33 +#define PARSER_BUF_SIZE 1024 33.34 + 33.35 +struct Parser; 33.36 +typedef int ParserStateFn(struct Parser *, char c); 33.37 + 33.38 +typedef struct ParserState { 33.39 + struct ParserState *parent; 33.40 + Sxpr val; 33.41 + int ival; 33.42 + int count; 33.43 + char delim; 33.44 + ParserStateFn *fn; 33.45 +} ParserState; 33.46 + 33.47 +/** Structure representing an input source for the parser. 33.48 + * Can read from any IOStream implementation. 33.49 + */ 33.50 +typedef struct Parser { 33.51 + Sxpr val; 33.52 + /** Error reporting stream (null for no reports). */ 33.53 + IOStream *error_out; 33.54 + int eof; 33.55 + /** Error flag. Non-zero if there has been a read error. */ 33.56 + int err; 33.57 + /** Line number on input (from 1). */ 33.58 + int line_no; 33.59 + /** Column number of input (reset on new line). */ 33.60 + int char_no; 33.61 + /** Lookahead character. */ 33.62 + char c; 33.63 + /** Buffer for reading tokens. */ 33.64 + char buf[PARSER_BUF_SIZE]; 33.65 + /** Size of token buffer. */ 33.66 + int buf_n; 33.67 + int buf_i; 33.68 + /** Line the last token started on. */ 33.69 + int tok_begin_line; 33.70 + /** Character number the last token started on. */ 33.71 + int tok_begin_char; 33.72 + /** Parsing flags. */ 33.73 + int flags; 33.74 + ParserState *state; 33.75 +} Parser; 33.76 + 33.77 +/** Parser error codes. */ 33.78 +typedef enum { 33.79 + PARSE_ERR_NONE=0, 33.80 + PARSE_ERR_UNSPECIFIED, 33.81 + PARSE_ERR_NOMEM, 33.82 + PARSE_ERR_UNEXPECTED_EOF, 33.83 + PARSE_ERR_TOKEN_TOO_LONG, 33.84 + PARSE_ERR_INVALID_SYNTAX, 33.85 + PARSE_ERR_INVALID_ESCAPE, 33.86 +} ParseErrorId; 33.87 + 33.88 + 33.89 +/** Parser flags. */ 33.90 +//enum { 33.91 +//}; 33.92 + 33.93 +/** Raise some parser flags. 33.94 + * 33.95 + * @param in parser 33.96 + * @param flags flags mask 33.97 + */ 33.98 +inline static void parser_flags_raise(Parser *in, int flags){ 33.99 + in->flags |= flags; 33.100 +} 33.101 + 33.102 +/** Lower some parser flags. 33.103 + * 33.104 + * @param in parser 33.105 + * @param flags flags mask 33.106 + */ 33.107 +inline static void parser_flags_lower(Parser *in, int flags){ 33.108 + in->flags &= ~flags; 33.109 +} 33.110 + 33.111 +/** Clear all parser flags. 33.112 + * 33.113 + * @param in parser 33.114 + */ 33.115 +inline static void parser_flags_clear(Parser *in){ 33.116 + in->flags = 0; 33.117 +} 33.118 + 33.119 +extern void Parser_free(Parser *z); 33.120 +extern Parser * Parser_new(void); 33.121 +extern int Parser_input(Parser *p, char *buf, int buf_n); 33.122 +extern int Parser_input_eof(Parser *p); 33.123 + 33.124 +extern int parse_error_message(Parser *in, char *buf, int n); 33.125 +extern int has_error(Parser *in); 33.126 +extern int at_eof(Parser *in); 33.127 + 33.128 +#endif /* ! _XEN_LIB_SXPR_PARSER_H_ */
34.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 34.2 +++ b/tools/lib/sys_ctype.h Mon Jun 28 15:03:15 2004 +0000 34.3 @@ -0,0 +1,12 @@ 34.4 +#ifndef _XENO_SYS_CTYPE_H_ 34.5 +#define _XENO_SYS_CTYPE_H_ 34.6 +/** @file 34.7 + ** Replacement for ctype include that can be used 34.8 + * from user or kernel code. 34.9 + */ 34.10 +#ifdef __KERNEL__ 34.11 +# include <linux/ctype.h> 34.12 +#else 34.13 +# include <ctype.h> 34.14 +#endif 34.15 +#endif /* ! _XENO_SYS_CTYPE_H_ */
35.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 35.2 +++ b/tools/lib/sys_net.c Mon Jun 28 15:03:15 2004 +0000 35.3 @@ -0,0 +1,309 @@ 35.4 +/* 35.5 + * Copyright (C) 2001 - 2004 Mike Wray <mike.wray@hp.com> 35.6 + * 35.7 + * This library is free software; you can redistribute it and/or modify 35.8 + * it under the terms of the GNU Lesser General Public License as 35.9 + * published by the Free Software Foundation; either version 2.1 of the 35.10 + * License, or (at your option) any later version. This library is 35.11 + * distributed in the hope that it will be useful, but WITHOUT ANY 35.12 + * WARRANTY; without even the implied warranty of MERCHANTABILITY or 35.13 + * FITNESS FOR A PARTICULAR PURPOSE. 35.14 + * See the GNU Lesser General Public License for more details. 35.15 + * 35.16 + * You should have received a copy of the GNU Lesser General Public License 35.17 + * along with this library; if not, write to the Free Software Foundation, 35.18 + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 35.19 + */ 35.20 + 35.21 +#include "sys_net.h" 35.22 +#include "sys_string.h" 35.23 + 35.24 +/** @file 35.25 + * All network data are kept in network order and only converted to 35.26 + * host order for display. Network data includes IP addresses, port numbers and 35.27 + * network masks. 35.28 + */ 35.29 + 35.30 +/** Maximum value for a port. */ 35.31 +#define PORT_MAX 0xffff 35.32 + 35.33 +/** Convert a number of bits to a network mask 35.34 + * for IP addresses. The number of bits must 35.35 + * be in the range 1-31. 35.36 + * 35.37 + * @param n number of bits to set in the mask 35.38 + * @return value with n high bits set (in network order) 35.39 + */ 35.40 +unsigned long bits_to_mask(int n){ 35.41 + unsigned long mask = (n ? (1 << 31) : 0); 35.42 + int i; 35.43 + for(i=1; i<n; i++){ 35.44 + mask |= (mask >> 1); 35.45 + } 35.46 + return htonl(mask); 35.47 +} 35.48 + 35.49 +/** Convert a network mask to a number of bits. 35.50 + * 35.51 + * @param mask network mask in network order 35.52 + * @return number of bits in mask 35.53 + */ 35.54 +int mask_to_bits(unsigned long mask){ 35.55 + // Start with n set to the number of bits in the mask. Then reduce n by 35.56 + // the number of low zero bits in the mask. 35.57 + int n = 32; 35.58 + for(mask = ntohl(mask); 35.59 + (mask & 1)==0 && n>0; 35.60 + mask >>= 1){ 35.61 + n--; 35.62 + } 35.63 + return n; 35.64 +} 35.65 + 35.66 +/** Get the index of the first occurrence of a character in a string. 35.67 + * Stops at end of string or after n characters. 35.68 + * 35.69 + * @param s input string 35.70 + * @param n maximum number of charactes to search 35.71 + * @param c character to look for 35.72 + * @return index of first occurrence, -1 if not found 35.73 + */ 35.74 +inline static int indexof(const char *s, int n, char c){ 35.75 + int i; 35.76 + for(i=0; i<n && *s; i++, s++){ 35.77 + if(*s == c) return i; 35.78 + } 35.79 + return -1; 35.80 +} 35.81 + 35.82 +/** Convert an IPv4 address in dot notation into an unsigned long (in network order). 35.83 + * 35.84 + * @param s input string 35.85 + * @param address where to put the address 35.86 + * @return 0 on success, -1 on error 35.87 + */ 35.88 +int get_inet_addr(const char *s, unsigned long *address){ 35.89 + // Number of bits in a byte. 35.90 + const int BYTE_BITS = 8; 35.91 + // Number of bytes in a word. 35.92 + const int WORD_BYTES = 4; 35.93 + // Max value for a component of an address. 35.94 + const int ADDR_MAX = 255; 35.95 + // Separator for components of an address. 35.96 + const char dot = '.'; 35.97 + 35.98 + int n; 35.99 + unsigned long addr = 0; 35.100 + unsigned long v; 35.101 + int i; 35.102 + int err = -1; 35.103 + // Bit shift for the current byte. 35.104 + int shift = BYTE_BITS * (WORD_BYTES - 1); 35.105 + char buf[64]; 35.106 + 35.107 + n = strlen(s); 35.108 + if(n >= sizeof(buf)){ 35.109 + goto exit; 35.110 + } 35.111 + for(i=0; i < WORD_BYTES; i++){ 35.112 + int idx = indexof(s, n, dot); 35.113 + idx = (idx < 0 ? strlen(s) : idx); 35.114 + strncpy(buf, s, idx); buf[idx]='\0'; 35.115 + if(convert_atoul(buf, &v)){ 35.116 + goto exit; 35.117 + } 35.118 + if(v < 0 || v > ADDR_MAX){ 35.119 + goto exit; 35.120 + } 35.121 + addr |= (v << shift); 35.122 + if(idx == n) break; 35.123 + shift -= BYTE_BITS; 35.124 + s += idx+1; 35.125 + } 35.126 + err = 0; 35.127 + exit: 35.128 + addr = htonl(addr); 35.129 + *address = (err ? 0 : addr); 35.130 + return err; 35.131 +} 35.132 + 35.133 +#ifdef __KERNEL__ 35.134 +/** Convert an address in network order to IPv4 dot notation. 35.135 + * The return value is a static buffer which is overwritten on each call. 35.136 + * 35.137 + * @param inaddr address (in network order) 35.138 + * @return address in dot notation 35.139 + */ 35.140 +char *inet_ntoa(struct in_addr inaddr){ 35.141 + static char address[16] = {}; 35.142 + uint32_t addr = ntohl(inaddr.s_addr); 35.143 + snprintf(address, sizeof(address), "%d.%d.%d.%d", 35.144 + (unsigned)((addr >> 24) & 0xff), 35.145 + (unsigned)((addr >> 16) & 0xff), 35.146 + (unsigned)((addr >> 8) & 0xff), 35.147 + (unsigned)((addr ) & 0xff)); 35.148 + return address; 35.149 +} 35.150 + 35.151 + 35.152 +/** Convert a string in IPv4 dot notation to an int in network order. 35.153 + * 35.154 + * @param address address in dot notation 35.155 + * @param inp result of conversion (in network order) 35.156 + * @return 0 on success, error code on error 35.157 + */ 35.158 +int inet_aton(const char *address, struct in_addr *inp){ 35.159 + int err = 0; 35.160 + unsigned long addr; 35.161 + 35.162 + err = get_inet_addr(address, &addr); 35.163 + if(err) goto exit; 35.164 + inp->s_addr = addr; 35.165 + exit: 35.166 + return err; 35.167 +} 35.168 +#endif 35.169 + 35.170 +/** Convert a hostname or IPv4 address string to an address in network order. 35.171 + * 35.172 + * @param name input hostname or address string 35.173 + * @param address where to put the address 35.174 + * @return 1 if address found OK, 0 otherwise 35.175 + */ 35.176 +int get_host_address(const char *name, unsigned long *address){ 35.177 +#ifdef __KERNEL__ 35.178 + return get_inet_addr(name, address) == 0; 35.179 +#else 35.180 + struct hostent *host = gethostbyname(name); 35.181 + if(!host){ 35.182 + return 0; 35.183 + } 35.184 + *address = ((struct in_addr *)(host->h_addr))->s_addr; 35.185 + return 1; 35.186 +#endif 35.187 +} 35.188 + 35.189 +/** Convert a service name to a port (in network order). 35.190 + * 35.191 + * @param name service name 35.192 + * @param port where to put the port 35.193 + * @return 1 if service port found OK, 0 otherwise 35.194 + */ 35.195 +int get_service_port(const char *name, unsigned long *port){ 35.196 +#ifdef __KERNEL__ 35.197 + return 0; 35.198 +#else 35.199 + struct servent *service; 35.200 + service = getservbyname(name, 0); 35.201 + if(!service){ 35.202 + return 0; 35.203 + } 35.204 + *port = service->s_port; 35.205 + return 1; 35.206 +#endif 35.207 +} 35.208 + 35.209 +/** Convert a port number (in network order) to a service name. 35.210 + * 35.211 + * @param port the port number 35.212 + * @return service name if found OK, 0 otherwise 35.213 + */ 35.214 +char *get_port_service(unsigned long port){ 35.215 +#ifdef __KERNEL__ 35.216 + return 0; 35.217 +#else 35.218 + struct servent *service = getservbyport(port, 0); 35.219 + return (service ? service->s_name : 0); 35.220 +#endif 35.221 +} 35.222 + 35.223 +/** Convert a decimal integer or service name to a port (in network order). 35.224 + * 35.225 + * @param s input to convert 35.226 + * @param port where to put the port 35.227 + * @return 1 if port found OK, 0 otherwise 35.228 + */ 35.229 +int convert_service_to_port(const char *s, unsigned long *port){ 35.230 + int ok = 0; 35.231 + unsigned long value; 35.232 + if(convert_atoul(s, &value)){ 35.233 + ok = get_service_port(s, &value); 35.234 + } else { 35.235 + ok = (0 <= value) && (value <= PORT_MAX); 35.236 + value = htons((unsigned short)value); 35.237 + } 35.238 + *port = (ok ? value : 0); 35.239 + return ok; 35.240 +} 35.241 + 35.242 +#define MAC_ELEMENT_N 6 // Number of elements in a MAC address. 35.243 +#define MAC_DIGIT_N 2 // Number of digits in an element in a MAC address. 35.244 +#define MAC_LENGTH 17 //((MAC_ELEMENT_N * MAC_DIGIT_N) + MAC_ELEMENT_N - 1) 35.245 + 35.246 +/** Convert a mac address from a string of the form 35.247 + * XX:XX:XX:XX:XX:XX to numerical form (an array of 6 unsigned chars). 35.248 + * Each X denotes a hex digit: 0..9, a..f, A..F. 35.249 + * Also supports using '-' as the separator instead of ':'. 35.250 + * 35.251 + * @param mac_in string to convert 35.252 + * @param mac destination for the value 35.253 + * @return 0 on success, -1 on error 35.254 + */ 35.255 +int mac_aton(const char *mac_in, unsigned char *mac){ 35.256 + int err = 0; 35.257 + int i, j; 35.258 + const char *p; 35.259 + char sep = 0; 35.260 + unsigned char d; 35.261 + if(!mac_in || strlen(mac_in) != MAC_LENGTH){ 35.262 + err = -1; 35.263 + goto exit; 35.264 + } 35.265 + for(i = 0, p = mac_in; i < MAC_ELEMENT_N; i++){ 35.266 + d = 0; 35.267 + if(i){ 35.268 + if(!sep){ 35.269 + if(*p == ':' || *p == '-') sep = *p; 35.270 + } 35.271 + if(sep && *p == sep){ 35.272 + p++; 35.273 + } else { 35.274 + err = -1; 35.275 + goto exit; 35.276 + } 35.277 + } 35.278 + for(j = 0; j < MAC_DIGIT_N; j++, p++){ 35.279 + if(j) d <<= 4; 35.280 + if(*p >= '0' && *p <= '9'){ 35.281 + d += (*p - '0'); 35.282 + } else if(*p >= 'A' && *p <= 'F'){ 35.283 + d += (*p - 'A') + 10; 35.284 + } else if(*p >= 'a' && *p <= 'f'){ 35.285 + d += (*p - 'a') + 10; 35.286 + } else { 35.287 + err = -1; 35.288 + goto exit; 35.289 + } 35.290 + } 35.291 + mac[i] = d; 35.292 + } 35.293 + exit: 35.294 + return err; 35.295 +} 35.296 + 35.297 +/** Convert a MAC address from numerical form to a string. 35.298 + * 35.299 + * @param mac address to convert 35.300 + * @return static string value 35.301 + */ 35.302 +char *mac_ntoa(const unsigned char *mac){ 35.303 + static char buf[MAC_LENGTH + 1]; 35.304 + int buf_n = sizeof(buf); 35.305 + 35.306 + memset(buf, buf_n, 0); 35.307 + snprintf(buf, buf_n, "%02x:%02x:%02x:%02x:%02x:%02x", 35.308 + mac[0], mac[1], mac[2], 35.309 + mac[3], mac[4], mac[5]); 35.310 + buf[buf_n - 1] = '\0'; 35.311 + return buf; 35.312 +}
36.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 36.2 +++ b/tools/lib/sys_net.h Mon Jun 28 15:03:15 2004 +0000 36.3 @@ -0,0 +1,78 @@ 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 published by 36.9 + * the Free Software Foundation; either version 2.1 of the License, or 36.10 + * (at your option) any later version. 36.11 + * 36.12 + * This library is distributed in the hope that it will be useful, 36.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 36.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 36.15 + * GNU Lesser General Public License for more details. 36.16 + * 36.17 + * You should have received a copy of the GNU Lesser General Public License 36.18 + * along with this library; if not, write to the Free Software 36.19 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 36.20 + */ 36.21 + 36.22 +#ifndef _XEN_LIB_SYS_NET_H_ 36.23 +#define _XEN_LIB_SYS_NET_H_ 36.24 +/** @file 36.25 + * 36.26 + * Replacement for standard network includes. 36.27 + * Works in user or kernel code. 36.28 + */ 36.29 + 36.30 +extern int get_inet_addr(const char *s, unsigned long *address); 36.31 +extern unsigned long bits_to_mask(int n); 36.32 +extern int mask_to_bits(unsigned long mask); 36.33 +extern int get_host_address(const char *name, unsigned long *address); 36.34 +extern int get_service_port(const char *name, unsigned long *port); 36.35 +extern char *get_port_service(unsigned long port); 36.36 +extern int convert_service_to_port(const char *s, unsigned long *port); 36.37 + 36.38 +#ifdef __KERNEL__ 36.39 +#include <linux/kernel.h> 36.40 +#include <linux/types.h> 36.41 +#include <linux/errno.h> 36.42 +#include <linux/slab.h> 36.43 +#include <asm/byteorder.h> 36.44 + 36.45 +#ifndef htonl 36.46 +#define htonl(x) __constant_htonl(x) 36.47 +#endif 36.48 + 36.49 +#ifndef ntohl 36.50 +#define ntohl(x) __constant_ntohl(x) 36.51 +#endif 36.52 + 36.53 +#ifndef htons 36.54 +#define htons(x) __constant_htons(x) 36.55 +#endif 36.56 + 36.57 +#ifndef ntohs 36.58 +#define ntohs(x) __constant_ntohs(x) 36.59 +#endif 36.60 + 36.61 +#include <linux/in.h> 36.62 +extern char *inet_ntoa(struct in_addr inaddr); 36.63 +extern int inet_aton(const char *address, struct in_addr *inp); 36.64 + 36.65 +#else 36.66 + 36.67 +#include <limits.h> 36.68 +#include <sys/socket.h> 36.69 +#include <netinet/in.h> 36.70 +#include <netdb.h> 36.71 +#include <arpa/inet.h> 36.72 + 36.73 +#endif 36.74 + 36.75 +extern char *mac_ntoa(const unsigned char *macaddr); 36.76 +extern int mac_aton(const char *addr, unsigned char *macaddr); 36.77 + 36.78 +#endif /* !_SP_SYS_NET_H_ */ 36.79 + 36.80 + 36.81 +
37.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 37.2 +++ b/tools/lib/sys_string.c Mon Jun 28 15:03:15 2004 +0000 37.3 @@ -0,0 +1,138 @@ 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 +#ifdef __KERNEL__ 37.23 +# include <linux/config.h> 37.24 +# include <linux/module.h> 37.25 +# include <linux/kernel.h> 37.26 +# include <linux/errno.h> 37.27 +#else 37.28 +# include <errno.h> 37.29 +#endif 37.30 + 37.31 +#include "allocate.h" 37.32 +#include "sys_string.h" 37.33 + 37.34 +/** Set the base to use for converting a string to a number. Base is 37.35 + * hex if starts with 0x, otherwise decimal. 37.36 + * 37.37 + * @param s input string 37.38 + * @param base where to put the base 37.39 + * @return rest of s to parse as a number 37.40 + */ 37.41 +inline static const char * convert_set_base(const char *s, int *base){ 37.42 + *base = 10; 37.43 + if(s){ 37.44 + if(*s=='0'){ 37.45 + s++; 37.46 + if(*s=='x' || *s=='X'){ 37.47 + *base = 16; 37.48 + s++; 37.49 + } 37.50 + } 37.51 + } 37.52 + return s; 37.53 +} 37.54 + 37.55 +/** Get the numerical value of a digit in the given base. 37.56 + * 37.57 + * @param c digit character 37.58 + * @param base to use 37.59 + * @return numerical value of digit in range 0..base-1 or 37.60 + * -1 if not in range for the base 37.61 + */ 37.62 +inline static int convert_get_digit(char c, int base){ 37.63 + int d; 37.64 + 37.65 + if('0'<=c && c<='9'){ 37.66 + d = c - '0'; 37.67 + } else if('a'<=c && c<='f'){ 37.68 + d = c - 'a' + 10; 37.69 + } else if('A'<=c && c<='F'){ 37.70 + d = c - 'A' + 10; 37.71 + } else { 37.72 + d = -1; 37.73 + } 37.74 + return (d < base ? d : -1); 37.75 +} 37.76 + 37.77 +/** Convert a string to an unsigned long by parsing it as a number. 37.78 + * Will accept hex or decimal in usual C syntax. 37.79 + * 37.80 + * @param str input string 37.81 + * @param val where to put the result 37.82 + * @return 0 if converted OK, negative otherwise 37.83 + */ 37.84 +int convert_atoul(const char *str, unsigned long *val){ 37.85 + int err = 0; 37.86 + unsigned long v = 0; 37.87 + int base; 37.88 + const char *s = str; 37.89 + 37.90 + if(!s) { 37.91 + err = -EINVAL; 37.92 + goto exit; 37.93 + } 37.94 + s = convert_set_base(s, &base); 37.95 + for( ; !err && *s; s++){ 37.96 + int digit = convert_get_digit(*s, base); 37.97 + if(digit<0){ 37.98 + err = -EINVAL; 37.99 + goto exit; 37.100 + } 37.101 + v *= base; 37.102 + v += digit; 37.103 + } 37.104 + exit: 37.105 + *val = (err ? 0 : v); 37.106 + return err; 37.107 +} 37.108 + 37.109 +/** Combine a directory path with a relative path to produce 37.110 + * a new path. 37.111 + * 37.112 + * @param s directory path 37.113 + * @param t relative path 37.114 + * @return new combined path s/t 37.115 + */ 37.116 +int path_concat(char *s, char *t, char **val){ 37.117 + int err = 0; 37.118 + int sn, tn, vn; 37.119 + char *v; 37.120 + sn = strlen(s); 37.121 + if(sn > 0 && s[sn-1] == '/'){ 37.122 + sn--; 37.123 + } 37.124 + tn = strlen(t); 37.125 + if(tn > 0 && t[0] == '/'){ 37.126 + tn--; 37.127 + } 37.128 + vn = sn+tn+1; 37.129 + v = (char*)allocate(vn+1); 37.130 + if(!v){ 37.131 + err = -ENOMEM; 37.132 + goto exit; 37.133 + } 37.134 + strncpy(v, s, sn); 37.135 + v[sn] = '/'; 37.136 + strncpy(v+sn+1, t, tn); 37.137 + v[vn] = '\0'; 37.138 + exit: 37.139 + *val = (err ? NULL : v); 37.140 + return err; 37.141 +}
38.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 38.2 +++ b/tools/lib/sys_string.h Mon Jun 28 15:03:15 2004 +0000 38.3 @@ -0,0 +1,91 @@ 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 +#ifndef _XEN_LIB_SYS_STRING_H_ 38.23 +#define _XEN_LIB_SYS_STRING_H_ 38.24 +/** @file 38.25 + * Replacement for standard string includes. 38.26 + * Works in user or kernel code. 38.27 + */ 38.28 +/*============================================================================*/ 38.29 +#ifdef __KERNEL__ 38.30 + 38.31 +#include <linux/config.h> 38.32 +#include <linux/kernel.h> 38.33 +#include <linux/string.h> 38.34 +#include <linux/types.h> 38.35 +#include <stdarg.h> 38.36 +#include "allocate.h" 38.37 + 38.38 +#if 0 38.39 +static inline int tolower(int c){ 38.40 + return (c>='A' && c<='Z' ? (c-'A')+'a' : c); 38.41 +} 38.42 +#endif 38.43 + 38.44 +static inline int isalpha(int c){ 38.45 + return (c>='A' && c<='Z') || (c>='a' && c<='z'); 38.46 +} 38.47 + 38.48 +static inline int isdigit(int c){ 38.49 + return (c>='0' && c<='9'); 38.50 +} 38.51 + 38.52 +#if 0 38.53 +static inline int strcasecmp(const char *s1, const char *s2){ 38.54 + int c1, c2; 38.55 + 38.56 + do { 38.57 + c1 = tolower(*s1++); 38.58 + c2 = tolower(*s2++); 38.59 + } while (c1 && c1 == c2); 38.60 + return c1 - c2; 38.61 +} 38.62 +#endif 38.63 + 38.64 +static inline char * strdup(const char *s){ 38.65 + int n = (s ? 1+strlen(s) : 0); 38.66 + char *copy = (n ? allocate(n) : NULL); 38.67 + if(copy){ 38.68 + strcpy(copy, s); 38.69 + } 38.70 + return copy; 38.71 +} 38.72 + 38.73 +/*============================================================================*/ 38.74 +#else 38.75 +#include <string.h> 38.76 +#include <stdio.h> 38.77 + 38.78 +#ifndef _GNU_SOURCE 38.79 +static inline size_t strnlen(const char *s, size_t n){ 38.80 + int k = 0; 38.81 + if(s){ 38.82 + for(k=0; *s && k<n; s++, k++){} 38.83 + } 38.84 + return k; 38.85 +} 38.86 +#endif 38.87 + 38.88 +#endif 38.89 +/*============================================================================*/ 38.90 + 38.91 +extern int convert_atoul(const char *s, unsigned long *v); 38.92 +extern int path_concat(char *s, char *t, char **val); 38.93 + 38.94 +#endif /* !_XEN_LIB_SYS_STRING_H_ */
39.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 39.2 +++ b/tools/lib/xdr.c Mon Jun 28 15:03:15 2004 +0000 39.3 @@ -0,0 +1,246 @@ 39.4 +/* $Id: xdr.c,v 1.3 2003/09/29 13:40:00 mjw Exp $ */ 39.5 +#include "xdr.h" 39.6 +#include <errno.h> 39.7 +/** @file 39.8 + * XDR packer/unpacker for elements. 39.9 + * 39.10 + * string -> [T_STRING] [len:u32] <len bytes> 39.11 + * atom -> [T_ATOM] [len:u32] <len bytes> 39.12 + * uint -> [T_UINT] [value] 39.13 + * cons -> [T_CONS] <car> <cdr> 39.14 + * null -> [T_NULL] 39.15 + * none -> [T_NONE] 39.16 + * bool -> [T_BOOL] { 0:u8 | 1:u8 } 39.17 + * 39.18 + * types packed as u16. 39.19 + * 39.20 + * So (a b c) -> [T_CONS] a [T_CONS] b [T_CONS] c [T_NULL] 39.21 + * () -> [T_NULL] 39.22 + */ 39.23 + 39.24 +int pack_bool(IOStream *io, int x){ 39.25 + int err=0; 39.26 + err = IOStream_print(io, "%c", 0xff & x); 39.27 + if(err > 0) err = 0; 39.28 + return err; 39.29 +} 39.30 + 39.31 +int unpack_bool(IOStream *io, int *x){ 39.32 + int err = 0; 39.33 + int c; 39.34 + c = IOStream_getc(io); 39.35 + *x = (c < 0 ? 0 : c); 39.36 + err = IOStream_error(io); 39.37 + if(c < 0 && !err) err = -EIO; 39.38 + return err; 39.39 +} 39.40 + 39.41 +int pack_ushort(IOStream *io, unsigned short x){ 39.42 + int err=0; 39.43 + err = IOStream_print(io, "%c%c", 39.44 + 0xff & (x >> 8), 39.45 + 0xff & (x )); 39.46 + if(err > 0) err = 0; 39.47 + return err; 39.48 +} 39.49 + 39.50 +int unpack_ushort(IOStream *io, unsigned short *x){ 39.51 + int err = 0; 39.52 + int i, c = 0; 39.53 + *x = 0; 39.54 + for(i = 0; i< 2; i++){ 39.55 + c = IOStream_getc(io); 39.56 + if(c < 0) break; 39.57 + *x <<= 8; 39.58 + *x |= (0xff & c); 39.59 + } 39.60 + err = IOStream_error(io); 39.61 + if(c < 0 && !err) err = -EIO; 39.62 + return err; 39.63 +} 39.64 + 39.65 +int pack_uint(IOStream *io, unsigned int x){ 39.66 + int err=0; 39.67 + err = IOStream_print(io, "%c%c%c%c", 39.68 + 0xff & (x >> 24), 39.69 + 0xff & (x >> 16), 39.70 + 0xff & (x >> 8), 39.71 + 0xff & (x )); 39.72 + if(err > 0) err = 0; 39.73 + return err; 39.74 +} 39.75 + 39.76 +int unpack_uint(IOStream *io, unsigned int *x){ 39.77 + int err = 0; 39.78 + int i, c = 0; 39.79 + *x = 0; 39.80 + for(i = 0; i< 4; i++){ 39.81 + c = IOStream_getc(io); 39.82 + if(c < 0) break; 39.83 + *x <<= 8; 39.84 + *x |= (0xff & c); 39.85 + } 39.86 + err = IOStream_error(io); 39.87 + if(c < 0 && !err) err = -EIO; 39.88 + return err; 39.89 +} 39.90 + 39.91 +int pack_string(IOStream *io, Sxpr x){ 39.92 + int err = 0; 39.93 + int n = string_length(x); 39.94 + char *s = string_string(x); 39.95 + int i; 39.96 + err = pack_uint(io, n); 39.97 + if(err) goto exit; 39.98 + for(i = 0; i < n; i++){ 39.99 + err = IOStream_print(io, "%c", s[i]); 39.100 + if(err < 0) break; 39.101 + } 39.102 + if(err > 0) err = 0; 39.103 + exit: 39.104 + return err; 39.105 +} 39.106 + 39.107 +int unpack_string(IOStream *io, Sxpr *x){ 39.108 + int err; 39.109 + unsigned int n; 39.110 + int i, c = 0; 39.111 + char *s; 39.112 + Sxpr val = ONONE; 39.113 + 39.114 + err = unpack_uint(io, &n); 39.115 + if(err) goto exit; 39.116 + val = halloc(n+1, T_STRING); 39.117 + if(NOMEMP(val)){ 39.118 + err = -ENOMEM; 39.119 + goto exit; 39.120 + } 39.121 + s = string_string(val); 39.122 + for(i=0; i<n; i++){ 39.123 + c = IOStream_getc(io); 39.124 + if(c < 0) break; 39.125 + s[i] = (char)c; 39.126 + } 39.127 + s[n] = '\0'; 39.128 + exit: 39.129 + err = IOStream_error(io); 39.130 + if(c < 0 && !err) err = -EIO; 39.131 + if(err){ 39.132 + objfree(val); 39.133 + val = ONONE; 39.134 + } 39.135 + *x = val; 39.136 + return err; 39.137 +} 39.138 + 39.139 +int pack_cons(IOStream *io, Sxpr x){ 39.140 + int err = 0; 39.141 + err = pack_sxpr(io, CAR(x)); 39.142 + if(err) goto exit; 39.143 + err = pack_sxpr(io, CDR(x)); 39.144 + exit: 39.145 + return err; 39.146 +} 39.147 + 39.148 +int unpack_cons(IOStream *io, Sxpr *x){ 39.149 + int err = 0; 39.150 + Sxpr u = ONONE, v = ONONE, val = ONONE; 39.151 + err = unpack_sxpr(io, &u); 39.152 + if(err) goto exit; 39.153 + err = unpack_sxpr(io, &v); 39.154 + if(err) goto exit; 39.155 + val = cons_new(u, v); 39.156 + if(NOMEMP(val)){ 39.157 + err = -ENOMEM; 39.158 + } 39.159 + exit: 39.160 + if(err){ 39.161 + objfree(u); 39.162 + objfree(v); 39.163 + val = ONONE; 39.164 + } 39.165 + *x = val; 39.166 + return err; 39.167 +} 39.168 + 39.169 +int pack_sxpr(IOStream *io, Sxpr x){ 39.170 + int err = 0; 39.171 + unsigned short type = get_type(x); 39.172 + err = pack_ushort(io, type); 39.173 + if(err) goto exit; 39.174 + switch(type){ 39.175 + case T_NULL: 39.176 + break; 39.177 + case T_NONE: 39.178 + break; 39.179 + break; 39.180 + case T_BOOL: 39.181 + err = pack_bool(io, get_ul(x)); 39.182 + break; 39.183 + case T_CONS: 39.184 + err = pack_cons(io, x); 39.185 + break; 39.186 + case T_ATOM: 39.187 + err = pack_string(io, OBJ_ATOM(x)->name); 39.188 + break; 39.189 + case T_STRING: 39.190 + err = pack_string(io, x); 39.191 + break; 39.192 + case T_UINT: 39.193 + err = pack_uint(io, get_ul(x)); 39.194 + break; 39.195 + default: 39.196 + err = -EINVAL; 39.197 + IOStream_print(iostderr, "%s> invalid type %d\n", __FUNCTION__, type); 39.198 + break; 39.199 + } 39.200 + exit: 39.201 + return err; 39.202 +} 39.203 + 39.204 +int unpack_sxpr(IOStream *io, Sxpr *x){ 39.205 + int err = 0; 39.206 + unsigned short type; 39.207 + unsigned int u; 39.208 + Sxpr val = ONONE, y; 39.209 + 39.210 + err = unpack_ushort(io, &type); 39.211 + if(err) goto exit; 39.212 + switch(type){ 39.213 + case T_NULL: 39.214 + val = ONULL; 39.215 + break; 39.216 + case T_NONE: 39.217 + val = ONONE; 39.218 + break; 39.219 + case T_CONS: 39.220 + err = unpack_cons(io, &val); 39.221 + break; 39.222 + case T_BOOL: 39.223 + err = unpack_bool(io, &u); 39.224 + if(err) goto exit; 39.225 + val = (u ? OTRUE : OFALSE); 39.226 + break; 39.227 + case T_ATOM: 39.228 + err = unpack_string(io, &y); 39.229 + if(err) goto exit; 39.230 + val = intern(string_string(y)); 39.231 + objfree(y); 39.232 + break; 39.233 + case T_STRING: 39.234 + err = unpack_string(io, &val); 39.235 + break; 39.236 + case T_UINT: 39.237 + err = unpack_uint(io, &u); 39.238 + if(err) goto exit; 39.239 + val = OBJI(type, u); 39.240 + break; 39.241 + default: 39.242 + err = -EINVAL; 39.243 + IOStream_print(iostderr, "%s> invalid type %d\n", __FUNCTION__, type); 39.244 + break; 39.245 + } 39.246 + exit: 39.247 + *x = (err ? ONONE : val); 39.248 + return err; 39.249 +}
40.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 40.2 +++ b/tools/lib/xdr.h Mon Jun 28 15:03:15 2004 +0000 40.3 @@ -0,0 +1,14 @@ 40.4 +/* $Id: xdr.h,v 1.2 2003/09/29 13:40:00 mjw Exp $ */ 40.5 +#ifndef _SP_XDR_H_ 40.6 +#define _SP_XDR_H_ 40.7 +#include "iostream.h" 40.8 +#include "sxpr.h" 40.9 +int pack_uint(IOStream *out, unsigned int x); 40.10 +int unpack_uint(IOStream *in, unsigned int *x); 40.11 +int pack_string(IOStream *out, Sxpr x); 40.12 +int unpack_string(IOStream *in, Sxpr *x); 40.13 +int pack_cons(IOStream *out, Sxpr x); 40.14 +int unpack_cons(IOStream *in, Sxpr *x); 40.15 +int pack_sxpr(IOStream *out, Sxpr x); 40.16 +int unpack_sxpr(IOStream *in, Sxpr *x); 40.17 +#endif /* _SP_XDR_H_ */
41.1 --- a/tools/xc/lib/Makefile Mon Jun 28 08:17:15 2004 +0000 41.2 +++ b/tools/xc/lib/Makefile Mon Jun 28 15:03:15 2004 +0000 41.3 @@ -4,13 +4,71 @@ MINOR = 0 41.4 SONAME = libxc.so.$(MAJOR) 41.5 41.6 CC = gcc 41.7 -CFLAGS = -c -Werror -O3 -fno-strict-aliasing 41.8 -CFLAGS += -I../../../xen/include/hypervisor-ifs 41.9 -CFLAGS += -I../../xu/lib 41.10 -CFLAGS += -I../../../linux-xen-sparse/include 41.11 + 41.12 +XEN_ROOT = ../../.. 41.13 + 41.14 +vpath %.h $(XEN_ROOT)/xen/include/hypervisor-ifs 41.15 +INCLUDES += -I $(XEN_ROOT)/xen/include/hypervisor-ifs 41.16 + 41.17 +vpath %.h $(XEN_ROOT)/tools/xu/lib 41.18 +INCLUDES += -I $(XEN_ROOT)/tools/xu/lib 41.19 + 41.20 +vpath %h $(XEN_ROOT)/linux-xen-sparse/include 41.21 +INCLUDES += -I $(XEN_ROOT)/linux-xen-sparse/include 41.22 + 41.23 +vpath %c $(XEN_ROOT)/tools/lib 41.24 +INCLUDES += -I $(XEN_ROOT)/tools/lib 41.25 41.26 -HDRS = $(wildcard *.h) 41.27 -OBJS = $(patsubst %.c,%.o,$(wildcard *.c)) 41.28 +LIB_SRCS := 41.29 +LIB_SRCS += allocate.c 41.30 +#LIB_SRCS += enum.c 41.31 +LIB_SRCS += file_stream.c 41.32 +LIB_SRCS += gzip_stream.c 41.33 +#LIB_SRCS += hash_table.c 41.34 +LIB_SRCS += iostream.c 41.35 +#LIB_SRCS += kernel_stream.c 41.36 +#LIB_SRCS += lexis.c 41.37 +#LIB_SRCS += lzi_stream.c 41.38 +#LIB_SRCS += lzo_stream.c 41.39 +#LIB_SRCS += marshal.c 41.40 +#LIB_SRCS += socket_stream.c 41.41 +#LIB_SRCS += string_stream.c 41.42 +#LIB_SRCS += sxpr.c 41.43 +#LIB_SRCS += sxpr_parser.c 41.44 +LIB_SRCS += sys_net.c 41.45 +LIB_SRCS += sys_string.c 41.46 +#LIB_SRCS += xdr.c 41.47 + 41.48 +SRCS := 41.49 +SRCS += xc_atropos.c 41.50 +SRCS += xc_bvtsched.c 41.51 +SRCS += xc_domain.c 41.52 +SRCS += xc_evtchn.c 41.53 +SRCS += xc_io.c 41.54 +SRCS += xc_linux_build.c 41.55 +SRCS += xc_linux_restore.c 41.56 +SRCS += xc_linux_save.c 41.57 +SRCS += xc_misc.c 41.58 +SRCS += xc_netbsd_build.c 41.59 +SRCS += xc_physdev.c 41.60 +SRCS += xc_private.c 41.61 +SRCS += $(LIB_SRCS) 41.62 + 41.63 +#CFLAGS += -I../../../xen/include/hypervisor-ifs 41.64 +#CFLAGS += -I../../xu/lib 41.65 +#CFLAGS += -I../../../linux-xen-sparse/include 41.66 + 41.67 +CFLAGS += -Wall 41.68 +CFLAGS += -Werror 41.69 +CFLAGS += -g 41.70 +CFLAGS += -O3 41.71 +CFLAGS += -fno-strict-aliasing 41.72 +CFLAGS += $(INCLUDES) 41.73 +# Get gcc to generate the dependencies for us. 41.74 +CFLAGS += -Wp,-MD,.$(@F).d 41.75 +DEPS = .*.d 41.76 + 41.77 +OBJS = $(patsubst %.c,%.o,$(SRCS)) 41.78 41.79 LIB = libxc.so libxc.so.$(MAJOR) libxc.so.$(MAJOR).$(MINOR) 41.80 41.81 @@ -32,6 +90,8 @@ install: all 41.82 41.83 clean: 41.84 $(RM) *.a *.so *.o *.rpm $(LIB) 41.85 + $(RM) *~ 41.86 + $(RM) $(DEPS) 41.87 41.88 rpm: all 41.89 rm -rf staging 41.90 @@ -49,5 +109,8 @@ libxc.so.$(MAJOR): 41.91 libxc.so.$(MAJOR).$(MINOR): $(OBJS) 41.92 $(CC) -Wl,-soname -Wl,$(SONAME) -shared -o $@ $^ -lz 41.93 41.94 -%.o: %.c $(HDRS) Makefile 41.95 - $(CC) $(CFLAGS) -o $@ $< 41.96 +%.o: %.c Makefile 41.97 + 41.98 +# $(CC) $(CFLAGS) -o $@ $< 41.99 + 41.100 +-include $(DEPS)
42.1 --- a/tools/xc/lib/xc.h Mon Jun 28 08:17:15 2004 +0000 42.2 +++ b/tools/xc/lib/xc.h Mon Jun 28 15:03:15 2004 +0000 42.3 @@ -68,18 +68,10 @@ int xc_shadow_control(int xc_handle, 42.4 #define XCFLAGS_LIVE 2 42.5 #define XCFLAGS_DEBUG 4 42.6 42.7 -int xc_linux_save(int xc_handle, 42.8 - u32 domid, 42.9 - unsigned int flags, 42.10 - int (*writerfn)(void *, const void *, size_t), 42.11 - void *writerst ); 42.12 +struct XcIOContext; 42.13 +int xc_linux_save(int xc_handle, struct XcIOContext *ioctxt); 42.14 42.15 -int xc_linux_restore(int xc_handle, 42.16 - u32 domid, 42.17 - unsigned int flags, 42.18 - int (*readerfn)(void *, void *, size_t), 42.19 - void *readerst, 42.20 - u32 *pdomid); 42.21 +int xc_linux_restore(int xc_handle, struct XcIOContext *ioctxt); 42.22 42.23 int xc_linux_build(int xc_handle, 42.24 u32 domid,
43.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 43.2 +++ b/tools/xc/lib/xc_io.c Mon Jun 28 15:03:15 2004 +0000 43.3 @@ -0,0 +1,27 @@ 43.4 +#include "xc_io.h" 43.5 + 43.6 +void xcio_error(XcIOContext *ctxt, const char *msg, ...){ 43.7 + va_list args; 43.8 + 43.9 + va_start(args, msg); 43.10 + IOStream_vprint(ctxt->info, msg, args); 43.11 + va_end(args); 43.12 +} 43.13 + 43.14 +void xcio_info(XcIOContext *ctxt, const char *msg, ...){ 43.15 + va_list args; 43.16 + 43.17 + if(!(ctxt->flags & XCFLAGS_VERBOSE)) return; 43.18 + va_start(args, msg); 43.19 + IOStream_vprint(ctxt->info, msg, args); 43.20 + va_end(args); 43.21 +} 43.22 + 43.23 +void xcio_debug(XcIOContext *ctxt, const char *msg, ...){ 43.24 + va_list args; 43.25 + 43.26 + if(!(ctxt->flags & XCFLAGS_DEBUG)) return; 43.27 + va_start(args, msg); 43.28 + IOStream_vprint(ctxt->info, msg, args); 43.29 + va_end(args); 43.30 +}
44.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 44.2 +++ b/tools/xc/lib/xc_io.h Mon Jun 28 15:03:15 2004 +0000 44.3 @@ -0,0 +1,44 @@ 44.4 +#ifndef __XC_XC_IO_H__ 44.5 +#define __XC_XC_IO_H__ 44.6 + 44.7 +#include "xc_private.h" 44.8 +#include <iostream.h> 44.9 + 44.10 +typedef struct XcIOContext { 44.11 + u32 domain; 44.12 + unsigned flags; 44.13 + IOStream *io; 44.14 + IOStream *info; 44.15 + IOStream *err; 44.16 + char *vmconfig; 44.17 + int vmconfig_n; 44.18 +} XcIOContext; 44.19 + 44.20 +static inline int xcio_read(XcIOContext *ctxt, void *buf, int n){ 44.21 + int rc; 44.22 + 44.23 + rc = IOStream_read(ctxt->io, buf, n); 44.24 + return (rc == n ? 0 : rc); 44.25 +} 44.26 + 44.27 +static inline int xcio_write(XcIOContext *ctxt, void *buf, int n){ 44.28 + int rc; 44.29 + 44.30 + rc = IOStream_write(ctxt->io, buf, n); 44.31 + return (rc == n ? 0 : rc); 44.32 +} 44.33 + 44.34 +static inline int xcio_flush(XcIOContext *ctxt){ 44.35 + return IOStream_flush(ctxt->io); 44.36 +} 44.37 + 44.38 +extern void xcio_error(XcIOContext *ctxt, const char *msg, ...); 44.39 +extern void xcio_info(XcIOContext *ctxt, const char *msg, ...); 44.40 + 44.41 +#define xcio_perror(_ctxt, _msg...) \ 44.42 +xcio_error(_ctxt, "(errno %d %s)" _msg, errno, strerror(errno), ## _msg) 44.43 + 44.44 +#endif /* ! __XC_XC_IO_H__ */ 44.45 + 44.46 + 44.47 +
45.1 --- a/tools/xc/lib/xc_linux_restore.c Mon Jun 28 08:17:15 2004 +0000 45.2 +++ b/tools/xc/lib/xc_linux_restore.c Mon Jun 28 15:03:15 2004 +0000 45.3 @@ -8,7 +8,6 @@ 45.4 45.5 #include "xc_private.h" 45.6 #include <asm-xen/suspend.h> 45.7 -#include <zlib.h> 45.8 45.9 #define MAX_BATCH_SIZE 1024 45.10 45.11 @@ -21,14 +20,6 @@ 45.12 #endif 45.13 45.14 45.15 -/* This may allow us to create a 'quiet' command-line option, if necessary. */ 45.16 -#define verbose_printf(_f, _a...) \ 45.17 - do { \ 45.18 - if ( !verbose ) break; \ 45.19 - printf( _f , ## _a ); \ 45.20 - fflush(stdout); \ 45.21 - } while ( 0 ) 45.22 - 45.23 static int get_pfn_list(int xc_handle, 45.24 u32 domain_id, 45.25 unsigned long *pfn_buf, 45.26 @@ -54,19 +45,44 @@ static int get_pfn_list(int xc_handle, 45.27 return (ret < 0) ? -1 : op.u.getmemlist.num_pfns; 45.28 } 45.29 45.30 +/** Read the vmconfig string from the state input. 45.31 + * It is stored as a 4-byte count 'n' followed by n bytes. 45.32 + * The config data is stored in a new string in 'ioctxt->vmconfig', 45.33 + * and is null-terminated. The count is stored in 'ioctxt->vmconfig_n'. 45.34 + * 45.35 + * @param ioctxt i/o context 45.36 + * @return 0 on success, non-zero on error. 45.37 + */ 45.38 +static int read_vmconfig(XcIOContext *ioctxt){ 45.39 + int err = -1; 45.40 + if(xcio_read(ioctxt, &ioctxt->vmconfig_n, sizeof(ioctxt->vmconfig_n))){ 45.41 + goto exit; 45.42 + } 45.43 + ioctxt->vmconfig = malloc(ioctxt->vmconfig_n + 1); 45.44 + if(!ioctxt->vmconfig) goto exit; 45.45 + if(xcio_read(ioctxt, ioctxt->vmconfig, ioctxt->vmconfig_n)){ 45.46 + goto exit; 45.47 + } 45.48 + ioctxt->vmconfig[ioctxt->vmconfig_n] = '\0'; 45.49 + err = 0; 45.50 + exit: 45.51 + if(err){ 45.52 + if(ioctxt->vmconfig){ 45.53 + free(ioctxt->vmconfig); 45.54 + } 45.55 + ioctxt->vmconfig = NULL; 45.56 + ioctxt->vmconfig_n = 0; 45.57 + } 45.58 + return err; 45.59 +} 45.60 45.61 -int xc_linux_restore(int xc_handle, 45.62 - u32 dom, 45.63 - unsigned int flags, 45.64 - int (*readerfn)(void *, void *, size_t), 45.65 - void *readerst, 45.66 - u32 *pdomid) 45.67 +int xc_linux_restore(int xc_handle, XcIOContext *ioctxt) 45.68 { 45.69 dom0_op_t op; 45.70 - int rc = 1, i, j, n, k; 45.71 + int rc = 1, i, n, k; 45.72 unsigned long mfn, pfn, xpfn; 45.73 unsigned int prev_pc, this_pc; 45.74 - int verbose = flags & XCFLAGS_VERBOSE; 45.75 + u32 dom = ioctxt->domain; 45.76 int verify = 0; 45.77 45.78 /* Number of page frames in use by this Linux session. */ 45.79 @@ -115,8 +131,7 @@ int xc_linux_restore(int xc_handle, 45.80 /* used by debug verify code */ 45.81 unsigned long buf[PAGE_SIZE/sizeof(unsigned long)]; 45.82 45.83 - if ( mlock(&ctxt, sizeof(ctxt) ) ) 45.84 - { 45.85 + if ( mlock(&ctxt, sizeof(ctxt) ) ) { 45.86 /* needed for when we do the build dom0 op, 45.87 but might as well do early */ 45.88 PERROR("Unable to mlock ctxt"); 45.89 @@ -124,35 +139,36 @@ int xc_linux_restore(int xc_handle, 45.90 } 45.91 45.92 /* Start writing out the saved-domain record. */ 45.93 - if ( (*readerfn)(readerst, signature, 16) || 45.94 - (memcmp(signature, "LinuxGuestRecord", 16) != 0) ) 45.95 - { 45.96 - ERROR("Unrecognised state format -- no signature found"); 45.97 + if ( xcio_read(ioctxt, signature, 16) || 45.98 + (memcmp(signature, "LinuxGuestRecord", 16) != 0) ) { 45.99 + xcio_error(ioctxt, "Unrecognised state format -- no signature found"); 45.100 goto out; 45.101 } 45.102 45.103 - if ( (*readerfn)(readerst, name, sizeof(name)) || 45.104 - (*readerfn)(readerst, &nr_pfns, sizeof(unsigned long)) || 45.105 - (*readerfn)(readerst, pfn_to_mfn_frame_list, PAGE_SIZE) ) 45.106 - { 45.107 - ERROR("Error when reading from state file"); 45.108 + if ( xcio_read(ioctxt, name, sizeof(name)) || 45.109 + xcio_read(ioctxt, &nr_pfns, sizeof(unsigned long)) || 45.110 + xcio_read(ioctxt, pfn_to_mfn_frame_list, PAGE_SIZE) ) { 45.111 + xcio_error(ioctxt, "Error reading header"); 45.112 goto out; 45.113 } 45.114 45.115 - for ( i = 0; i < MAX_DOMAIN_NAME; i++ ) 45.116 - { 45.117 + if(read_vmconfig(ioctxt)){ 45.118 + xcio_error(ioctxt, "Error writing vmconfig"); 45.119 + goto out; 45.120 + } 45.121 + 45.122 + for ( i = 0; i < MAX_DOMAIN_NAME; i++ ) { 45.123 if ( name[i] == '\0' ) break; 45.124 if ( name[i] & 0x80 ) 45.125 { 45.126 - ERROR("Random characters in domain name"); 45.127 + xcio_error(ioctxt, "Random characters in domain name"); 45.128 goto out; 45.129 } 45.130 } 45.131 name[MAX_DOMAIN_NAME-1] = '\0'; 45.132 45.133 - if ( nr_pfns > 1024*1024 ) 45.134 - { 45.135 - ERROR("Invalid state file -- pfn count out of range"); 45.136 + if ( nr_pfns > 1024*1024 ) { 45.137 + xcio_error(ioctxt, "Invalid state file -- pfn count out of range"); 45.138 goto out; 45.139 } 45.140 45.141 @@ -162,22 +178,19 @@ int xc_linux_restore(int xc_handle, 45.142 region_mfn = calloc(1, 4 * MAX_BATCH_SIZE); 45.143 45.144 if ( (pfn_to_mfn_table == NULL) || (pfn_type == NULL) || 45.145 - (region_mfn == NULL) ) 45.146 - { 45.147 + (region_mfn == NULL) ) { 45.148 errno = ENOMEM; 45.149 goto out; 45.150 } 45.151 45.152 - if ( mlock(region_mfn, 4 * MAX_BATCH_SIZE ) ) 45.153 - { 45.154 - ERROR("Could not mlock region_mfn"); 45.155 + if ( mlock(region_mfn, 4 * MAX_BATCH_SIZE ) ) { 45.156 + xcio_error(ioctxt, "Could not mlock region_mfn"); 45.157 goto out; 45.158 } 45.159 45.160 /* Set the domain's name to that from the restore file */ 45.161 - if ( xc_domain_setname( xc_handle, dom, name ) ) 45.162 - { 45.163 - ERROR("Could not set domain name"); 45.164 + if ( xc_domain_setname( xc_handle, dom, name ) ) { 45.165 + xcio_error(ioctxt, "Could not set domain name"); 45.166 goto out; 45.167 } 45.168 45.169 @@ -187,7 +200,7 @@ int xc_linux_restore(int xc_handle, 45.170 if ( xc_domain_setinitialmem(xc_handle, dom, 45.171 nr_pfns * (PAGE_SIZE / 1024)) ) 45.172 { 45.173 - ERROR("Could not set domain initial memory"); 45.174 + xcio_error(ioctxt, "Could not set domain initial memory"); 45.175 goto out; 45.176 } 45.177 45.178 @@ -195,9 +208,8 @@ int xc_linux_restore(int xc_handle, 45.179 op.cmd = DOM0_GETDOMAININFO; 45.180 op.u.getdomaininfo.domain = (domid_t)dom; 45.181 op.u.getdomaininfo.ctxt = NULL; 45.182 - if ( do_dom0_op(xc_handle, &op) < 0 ) 45.183 - { 45.184 - ERROR("Could not get information on new domain"); 45.185 + if ( do_dom0_op(xc_handle, &op) < 0 ) { 45.186 + xcio_error(ioctxt, "Could not get information on new domain"); 45.187 goto out; 45.188 } 45.189 shared_info_frame = op.u.getdomaininfo.shared_info_frame; 45.190 @@ -208,19 +220,17 @@ int xc_linux_restore(int xc_handle, 45.191 45.192 45.193 /* Build the pfn-to-mfn table. We choose MFN ordering returned by Xen. */ 45.194 - if ( get_pfn_list(xc_handle, dom, pfn_to_mfn_table, nr_pfns) != nr_pfns ) 45.195 - { 45.196 - ERROR("Did not read correct number of frame numbers for new dom"); 45.197 + if ( get_pfn_list(xc_handle, dom, pfn_to_mfn_table, nr_pfns) != nr_pfns ) { 45.198 + xcio_error(ioctxt, "Did not read correct number of frame numbers for new dom"); 45.199 goto out; 45.200 } 45.201 45.202 - if ( (mmu = init_mmu_updates(xc_handle, dom)) == NULL ) 45.203 - { 45.204 - ERROR("Could not initialise for MMU updates"); 45.205 + if ( (mmu = init_mmu_updates(xc_handle, dom)) == NULL ) { 45.206 + xcio_error(ioctxt, "Could not initialise for MMU updates"); 45.207 goto out; 45.208 } 45.209 45.210 - verbose_printf("Reloading memory pages: 0%%"); 45.211 + xcio_info(ioctxt, "Reloading memory pages: 0%%"); 45.212 45.213 /* 45.214 * Now simply read each saved frame into its new machine frame. 45.215 @@ -229,56 +239,45 @@ int xc_linux_restore(int xc_handle, 45.216 prev_pc = 0; 45.217 45.218 n=0; 45.219 - while(1) 45.220 - { 45.221 + while(1) { 45.222 int j; 45.223 unsigned long region_pfn_type[MAX_BATCH_SIZE]; 45.224 45.225 this_pc = (n * 100) / nr_pfns; 45.226 - if ( (this_pc - prev_pc) >= 5 ) 45.227 - { 45.228 - verbose_printf("\b\b\b\b%3d%%", this_pc); 45.229 + if ( (this_pc - prev_pc) >= 5 ) { 45.230 + xcio_info(ioctxt, "\b\b\b\b%3d%%", this_pc); 45.231 prev_pc = this_pc; 45.232 } 45.233 45.234 - if ( (*readerfn)(readerst, &j, sizeof(int)) ) 45.235 - { 45.236 - ERROR("Error when reading from state file"); 45.237 + if ( xcio_read(ioctxt, &j, sizeof(int)) ) { 45.238 + xcio_error(ioctxt, "Error when reading from state file"); 45.239 goto out; 45.240 } 45.241 45.242 DPRINTF("batch %d\n",j); 45.243 45.244 - if ( j == -1 ) 45.245 - { 45.246 + if ( j == -1 ) { 45.247 verify = 1; 45.248 printf("Entering page verify mode\n"); 45.249 continue; 45.250 } 45.251 45.252 - if ( j == 0 ) 45.253 - break; /* our work here is done */ 45.254 + if ( j == 0 ) break; /* our work here is done */ 45.255 45.256 - if( j > MAX_BATCH_SIZE ) 45.257 - { 45.258 - ERROR("Max batch size exceeded. Giving up."); 45.259 + if( j > MAX_BATCH_SIZE ) { 45.260 + xcio_error(ioctxt, "Max batch size exceeded. Giving up."); 45.261 goto out; 45.262 } 45.263 45.264 - if ( (*readerfn)(readerst, region_pfn_type, j*sizeof(unsigned long)) ) 45.265 - { 45.266 - ERROR("Error when reading from state file"); 45.267 + if ( xcio_read(ioctxt, region_pfn_type, j*sizeof(unsigned long)) ) { 45.268 + xcio_error(ioctxt, "Error when reading from state file"); 45.269 goto out; 45.270 } 45.271 45.272 - for(i=0;i<j;i++) 45.273 - { 45.274 - if ( (region_pfn_type[i] & LTAB_MASK) == XTAB) 45.275 - { 45.276 + for(i=0; i<j; i++) { 45.277 + if ( (region_pfn_type[i] & LTAB_MASK) == XTAB) { 45.278 region_mfn[i] = 0; /* we know map will fail, but don't care */ 45.279 - } 45.280 - else 45.281 - { 45.282 + } else { 45.283 pfn = region_pfn_type[i] & ~LTAB_MASK; 45.284 region_mfn[i] = pfn_to_mfn_table[pfn]; 45.285 } 45.286 @@ -287,24 +286,20 @@ int xc_linux_restore(int xc_handle, 45.287 if ( (region_base = mfn_mapper_map_batch( xc_handle, dom, 45.288 PROT_WRITE, 45.289 region_mfn, 45.290 - j )) == 0) 45.291 - { 45.292 - PERROR("map batch failed"); 45.293 + j )) == 0) { 45.294 + xcio_error(ioctxt, "map batch failed"); 45.295 goto out; 45.296 } 45.297 45.298 - for(i=0;i<j;i++) 45.299 - { 45.300 + for(i=0;i<j;i++) { 45.301 unsigned long *ppage; 45.302 45.303 pfn = region_pfn_type[i] & ~LTAB_MASK; 45.304 45.305 - if ( (region_pfn_type[i] & LTAB_MASK) == XTAB) 45.306 - continue; 45.307 + if ( (region_pfn_type[i] & LTAB_MASK) == XTAB) continue; 45.308 45.309 - if (pfn>nr_pfns) 45.310 - { 45.311 - ERROR("pfn out of range"); 45.312 + if (pfn>nr_pfns) { 45.313 + xcio_error(ioctxt, "pfn out of range"); 45.314 goto out; 45.315 } 45.316 45.317 @@ -314,36 +309,32 @@ int xc_linux_restore(int xc_handle, 45.318 45.319 mfn = pfn_to_mfn_table[pfn]; 45.320 45.321 - if ( verify ) 45.322 + if ( verify ) { 45.323 ppage = (unsigned long*) buf; /* debug case */ 45.324 - else 45.325 + } else { 45.326 ppage = (unsigned long*) (region_base + i*PAGE_SIZE); 45.327 + } 45.328 45.329 - if ( (*readerfn)(readerst, ppage, PAGE_SIZE) ) 45.330 - { 45.331 - ERROR("Error when reading from state file"); 45.332 + if ( xcio_read(ioctxt, ppage, PAGE_SIZE) ) { 45.333 + xcio_error(ioctxt, "Error when reading from state file"); 45.334 goto out; 45.335 } 45.336 45.337 - switch( region_pfn_type[i] ) 45.338 - { 45.339 + switch( region_pfn_type[i] ) { 45.340 case 0: 45.341 break; 45.342 45.343 case L1TAB: 45.344 { 45.345 - for ( k = 0; k < 1024; k++ ) 45.346 - { 45.347 - if ( ppage[k] & _PAGE_PRESENT ) 45.348 - { 45.349 + for ( k = 0; k < 1024; k++ ) { 45.350 + if ( ppage[k] & _PAGE_PRESENT ) { 45.351 xpfn = ppage[k] >> PAGE_SHIFT; 45.352 45.353 - if ( xpfn >= nr_pfns ) 45.354 - { 45.355 - ERROR("Frame number in type %d page table is " 45.356 - "out of range. i=%d k=%d pfn=0x%x " 45.357 - "nr_pfns=%d", region_pfn_type[i]>>28, i, 45.358 - k, xpfn,nr_pfns); 45.359 + if ( xpfn >= nr_pfns ) { 45.360 + xcio_error(ioctxt, "Frame number in type %lu page table is " 45.361 + "out of range. i=%d k=%d pfn=0x%lx " 45.362 + "nr_pfns=%lu", region_pfn_type[i]>>28, i, 45.363 + k, xpfn, nr_pfns); 45.364 goto out; 45.365 } 45.366 45.367 @@ -359,16 +350,13 @@ int xc_linux_restore(int xc_handle, 45.368 { 45.369 for ( k = 0; 45.370 k < (HYPERVISOR_VIRT_START>>L2_PAGETABLE_SHIFT); 45.371 - k++ ) 45.372 - { 45.373 - if ( ppage[k] & _PAGE_PRESENT ) 45.374 - { 45.375 + k++ ) { 45.376 + if ( ppage[k] & _PAGE_PRESENT ) { 45.377 xpfn = ppage[k] >> PAGE_SHIFT; 45.378 45.379 - if ( xpfn >= nr_pfns ) 45.380 - { 45.381 - ERROR("Frame number in type %d page table is " 45.382 - "out of range. i=%d k=%d pfn=%d nr_pfns=%d", 45.383 + if ( xpfn >= nr_pfns ) { 45.384 + xcio_error(ioctxt, "Frame number in type %lu page table is " 45.385 + "out of range. i=%d k=%d pfn=%lu nr_pfns=%lu", 45.386 region_pfn_type[i]>>28, i, k, xpfn, nr_pfns); 45.387 45.388 goto out; 45.389 @@ -383,24 +371,21 @@ int xc_linux_restore(int xc_handle, 45.390 break; 45.391 45.392 default: 45.393 - ERROR("Bogus page type %x page table is out of range." 45.394 - " i=%d nr_pfns=%d", region_pfn_type[i], i, nr_pfns); 45.395 + xcio_error(ioctxt, "Bogus page type %lx page table is out of range." 45.396 + " i=%d nr_pfns=%lu", region_pfn_type[i], i, nr_pfns); 45.397 goto out; 45.398 45.399 } /* end of page type switch statement */ 45.400 45.401 - if ( verify ) 45.402 - { 45.403 + if ( verify ) { 45.404 int res = memcmp(buf, (region_base + i*PAGE_SIZE), PAGE_SIZE ); 45.405 - if (res) 45.406 - { 45.407 + if (res) { 45.408 int v; 45.409 - printf("************** pfn=%x type=%x gotcs=%08lx " 45.410 + printf("************** pfn=%lx type=%lx gotcs=%08lx " 45.411 "actualcs=%08lx\n", pfn, pfn_type[pfn], 45.412 csum_page(region_base + i*PAGE_SIZE), 45.413 csum_page(buf)); 45.414 - for ( v = 0; v < 4; v++ ) 45.415 - { 45.416 + for ( v = 0; v < 4; v++ ) { 45.417 unsigned long *p = (unsigned long *) 45.418 (region_base + i*PAGE_SIZE); 45.419 if ( buf[v] != p[v] ) 45.420 @@ -411,8 +396,7 @@ int xc_linux_restore(int xc_handle, 45.421 } 45.422 45.423 if ( add_mmu_update(xc_handle, mmu, 45.424 - (mfn<<PAGE_SHIFT) | MMU_MACHPHYS_UPDATE, pfn) ) 45.425 - { 45.426 + (mfn<<PAGE_SHIFT) | MMU_MACHPHYS_UPDATE, pfn) ) { 45.427 printf("machpys mfn=%ld pfn=%ld\n",mfn,pfn); 45.428 goto out; 45.429 } 45.430 @@ -431,44 +415,36 @@ int xc_linux_restore(int xc_handle, 45.431 * Pin page tables. Do this after writing to them as otherwise Xen 45.432 * will barf when doing the type-checking. 45.433 */ 45.434 - for ( i = 0; i < nr_pfns; i++ ) 45.435 - { 45.436 - if ( pfn_type[i] == L1TAB ) 45.437 - { 45.438 + for ( i = 0; i < nr_pfns; i++ ) { 45.439 + if ( pfn_type[i] == L1TAB ) { 45.440 if ( add_mmu_update(xc_handle, mmu, 45.441 (pfn_to_mfn_table[i]<<PAGE_SHIFT) | 45.442 MMU_EXTENDED_COMMAND, 45.443 - MMUEXT_PIN_L1_TABLE) ) 45.444 - { 45.445 + MMUEXT_PIN_L1_TABLE) ) { 45.446 printf("ERR pin L1 pfn=%lx mfn=%lx\n", 45.447 - i, pfn_to_mfn_table[i]); 45.448 + (unsigned long)i, pfn_to_mfn_table[i]); 45.449 goto out; 45.450 } 45.451 - } 45.452 - else if ( pfn_type[i] == L2TAB ) 45.453 - { 45.454 + } else if ( pfn_type[i] == L2TAB ) { 45.455 if ( add_mmu_update(xc_handle, mmu, 45.456 (pfn_to_mfn_table[i]<<PAGE_SHIFT) | 45.457 MMU_EXTENDED_COMMAND, 45.458 - MMUEXT_PIN_L2_TABLE) ) 45.459 - { 45.460 + MMUEXT_PIN_L2_TABLE) ) { 45.461 printf("ERR pin L2 pfn=%lx mfn=%lx\n", 45.462 - i, pfn_to_mfn_table[i]); 45.463 + (unsigned long)i, pfn_to_mfn_table[i]); 45.464 goto out; 45.465 } 45.466 } 45.467 } 45.468 45.469 - if ( finish_mmu_updates(xc_handle, mmu) ) 45.470 - goto out; 45.471 + if ( finish_mmu_updates(xc_handle, mmu) ) goto out; 45.472 45.473 - verbose_printf("\b\b\b\b100%%\nMemory reloaded.\n"); 45.474 + xcio_info(ioctxt, "\b\b\b\b100%%\nMemory reloaded.\n"); 45.475 45.476 45.477 - if ( (*readerfn)(readerst, &ctxt, sizeof(ctxt)) || 45.478 - (*readerfn)(readerst, shared_info, PAGE_SIZE) ) 45.479 - { 45.480 - ERROR("Error when reading from state file"); 45.481 + if ( xcio_read(ioctxt, &ctxt, sizeof(ctxt)) || 45.482 + xcio_read(ioctxt, shared_info, PAGE_SIZE) ) { 45.483 + xcio_error(ioctxt, "Error when reading from state file"); 45.484 goto out; 45.485 } 45.486 45.487 @@ -476,7 +452,7 @@ int xc_linux_restore(int xc_handle, 45.488 pfn = ctxt.cpu_ctxt.esi; 45.489 if ( (pfn >= nr_pfns) || (pfn_type[pfn] != NOTAB) ) 45.490 { 45.491 - ERROR("Suspend record frame number is bad"); 45.492 + xcio_error(ioctxt, "Suspend record frame number is bad"); 45.493 goto out; 45.494 } 45.495 ctxt.cpu_ctxt.esi = mfn = pfn_to_mfn_table[pfn]; 45.496 @@ -487,17 +463,14 @@ int xc_linux_restore(int xc_handle, 45.497 unmap_pfn(pm_handle, p_srec); 45.498 45.499 /* Uncanonicalise each GDT frame number. */ 45.500 - if ( ctxt.gdt_ents > 8192 ) 45.501 - { 45.502 - ERROR("GDT entry count out of range"); 45.503 + if ( ctxt.gdt_ents > 8192 ) { 45.504 + xcio_error(ioctxt, "GDT entry count out of range"); 45.505 goto out; 45.506 } 45.507 - for ( i = 0; i < ctxt.gdt_ents; i += 512 ) 45.508 - { 45.509 + for ( i = 0; i < ctxt.gdt_ents; i += 512 ) { 45.510 pfn = ctxt.gdt_frames[i]; 45.511 - if ( (pfn >= nr_pfns) || (pfn_type[pfn] != NOTAB) ) 45.512 - { 45.513 - ERROR("GDT frame number is bad"); 45.514 + if ( (pfn >= nr_pfns) || (pfn_type[pfn] != NOTAB) ) { 45.515 + xcio_error(ioctxt, "GDT frame number is bad"); 45.516 goto out; 45.517 } 45.518 ctxt.gdt_frames[i] = pfn_to_mfn_table[pfn]; 45.519 @@ -505,11 +478,10 @@ int xc_linux_restore(int xc_handle, 45.520 45.521 /* Uncanonicalise the page table base pointer. */ 45.522 pfn = ctxt.pt_base >> PAGE_SHIFT; 45.523 - if ( (pfn >= nr_pfns) || (pfn_type[pfn] != L2TAB) ) 45.524 - { 45.525 - printf("PT base is bad. pfn=%d nr=%d type=%08lx %08lx\n", 45.526 - pfn, nr_pfns, pfn_type[pfn], L2TAB); 45.527 - ERROR("PT base is bad."); 45.528 + if ( (pfn >= nr_pfns) || (pfn_type[pfn] != L2TAB) ) { 45.529 + printf("PT base is bad. pfn=%lu nr=%lu type=%08lx %08lx\n", 45.530 + pfn, nr_pfns, pfn_type[pfn], (unsigned long)L2TAB); 45.531 + xcio_error(ioctxt, "PT base is bad."); 45.532 goto out; 45.533 } 45.534 ctxt.pt_base = pfn_to_mfn_table[pfn] << PAGE_SHIFT; 45.535 @@ -527,14 +499,12 @@ int xc_linux_restore(int xc_handle, 45.536 45.537 45.538 /* Uncanonicalise the pfn-to-mfn table frame-number list. */ 45.539 - for ( i = 0; i < (nr_pfns+1023)/1024; i++ ) 45.540 - { 45.541 + for ( i = 0; i < (nr_pfns+1023)/1024; i++ ) { 45.542 unsigned long pfn, mfn; 45.543 45.544 pfn = pfn_to_mfn_frame_list[i]; 45.545 - if ( (pfn >= nr_pfns) || (pfn_type[pfn] != NOTAB) ) 45.546 - { 45.547 - ERROR("PFN-to-MFN frame number is bad"); 45.548 + if ( (pfn >= nr_pfns) || (pfn_type[pfn] != NOTAB) ) { 45.549 + xcio_error(ioctxt, "PFN-to-MFN frame number is bad"); 45.550 goto out; 45.551 } 45.552 mfn = pfn_to_mfn_table[pfn]; 45.553 @@ -545,9 +515,8 @@ int xc_linux_restore(int xc_handle, 45.554 mfn_mapper_map_batch(xc_handle, dom, 45.555 PROT_WRITE, 45.556 pfn_to_mfn_frame_list, 45.557 - (nr_pfns+1023)/1024 )) == 0 ) 45.558 - { 45.559 - ERROR("Couldn't map pfn_to_mfn table"); 45.560 + (nr_pfns+1023)/1024 )) == 0 ) { 45.561 + xcio_error(ioctxt, "Couldn't map pfn_to_mfn table"); 45.562 goto out; 45.563 } 45.564 45.565 @@ -569,24 +538,26 @@ int xc_linux_restore(int xc_handle, 45.566 * 9. debugregs are checked by Xen. 45.567 * 10. callback code selectors need checking. 45.568 */ 45.569 - for ( i = 0; i < 256; i++ ) 45.570 - { 45.571 + for ( i = 0; i < 256; i++ ) { 45.572 ctxt.trap_ctxt[i].vector = i; 45.573 if ( (ctxt.trap_ctxt[i].cs & 3) == 0 ) 45.574 ctxt.trap_ctxt[i].cs = FLAT_GUESTOS_CS; 45.575 } 45.576 - if ( (ctxt.guestos_ss & 3) == 0 ) 45.577 + if ( (ctxt.guestos_ss & 3) == 0 ){ 45.578 ctxt.guestos_ss = FLAT_GUESTOS_DS; 45.579 - if ( (ctxt.event_callback_cs & 3) == 0 ) 45.580 + } 45.581 + if ( (ctxt.event_callback_cs & 3) == 0 ){ 45.582 ctxt.event_callback_cs = FLAT_GUESTOS_CS; 45.583 - if ( (ctxt.failsafe_callback_cs & 3) == 0 ) 45.584 + } 45.585 + if ( (ctxt.failsafe_callback_cs & 3) == 0 ){ 45.586 ctxt.failsafe_callback_cs = FLAT_GUESTOS_CS; 45.587 + } 45.588 if ( ((ctxt.ldt_base & (PAGE_SIZE - 1)) != 0) || 45.589 (ctxt.ldt_ents > 8192) || 45.590 (ctxt.ldt_base > HYPERVISOR_VIRT_START) || 45.591 ((ctxt.ldt_base + ctxt.ldt_ents*8) > HYPERVISOR_VIRT_START) ) 45.592 { 45.593 - ERROR("Bad LDT base or size"); 45.594 + xcio_error(ioctxt, "Bad LDT base or size"); 45.595 goto out; 45.596 } 45.597 45.598 @@ -597,34 +568,33 @@ int xc_linux_restore(int xc_handle, 45.599 45.600 /* don't start the domain as we have console etc to set up */ 45.601 45.602 - if( rc == 0 ) 45.603 - { 45.604 + if( rc == 0 ) { 45.605 /* Success: print the domain id. */ 45.606 - verbose_printf("DOM=%u\n", dom); 45.607 + xcio_info(ioctxt, "DOM=%lu\n", dom); 45.608 return 0; 45.609 } 45.610 45.611 45.612 out: 45.613 - if ( (rc != 0) && (dom != 0) ) 45.614 + if ( (rc != 0) && (dom != 0) ){ 45.615 xc_domain_destroy(xc_handle, dom); 45.616 - 45.617 - if ( mmu != NULL ) 45.618 + } 45.619 + if ( mmu != NULL ){ 45.620 free(mmu); 45.621 - 45.622 - if ( pm_handle >= 0 ) 45.623 + } 45.624 + if ( pm_handle >= 0 ){ 45.625 (void)close_pfn_mapper(pm_handle); 45.626 + } 45.627 + if ( pfn_to_mfn_table != NULL ){ 45.628 + free(pfn_to_mfn_table); 45.629 + } 45.630 + if ( pfn_type != NULL ){ 45.631 + free(pfn_type); 45.632 + } 45.633 45.634 - if ( pfn_to_mfn_table != NULL ) 45.635 - free(pfn_to_mfn_table); 45.636 - if ( pfn_type != NULL ) 45.637 - free(pfn_type); 45.638 - 45.639 - 45.640 - if ( rc == 0 ) 45.641 - *pdomid = dom; 45.642 - 45.643 + if ( rc == 0 ){ 45.644 + ioctxt->domain = dom; 45.645 + } 45.646 DPRINTF("Restore exit with rc=%d\n",rc); 45.647 - 45.648 return rc; 45.649 }
46.1 --- a/tools/xc/lib/xc_linux_save.c Mon Jun 28 08:17:15 2004 +0000 46.2 +++ b/tools/xc/lib/xc_linux_save.c Mon Jun 28 15:03:15 2004 +0000 46.3 @@ -6,6 +6,7 @@ 46.4 * Copyright (c) 2003, K A Fraser. 46.5 */ 46.6 46.7 +#include <sys/time.h> 46.8 #include "xc_private.h" 46.9 #include <asm-xen/suspend.h> 46.10 46.11 @@ -26,16 +27,6 @@ 46.12 #define DDPRINTF(_f, _a...) ((void)0) 46.13 #endif 46.14 46.15 - 46.16 - 46.17 -/* This may allow us to create a 'quiet' command-line option, if necessary. */ 46.18 -#define verbose_printf(_f, _a...) \ 46.19 - do { \ 46.20 - if ( !verbose ) break; \ 46.21 - printf( _f , ## _a ); \ 46.22 - fflush(stdout); \ 46.23 - } while ( 0 ) 46.24 - 46.25 /* 46.26 * Returns TRUE if the given machine frame number has a unique mapping 46.27 * in the guest's pseudophysical map. 46.28 @@ -197,20 +188,30 @@ static int track_cpu_usage( int xc_handl 46.29 return 0; 46.30 } 46.31 46.32 +/** Write the vmconfig string. 46.33 + * It is stored as a 4-byte count 'n' followed by n bytes. 46.34 + * 46.35 + * @param ioctxt i/o context 46.36 + * @return 0 on success, non-zero on error. 46.37 + */ 46.38 +static int write_vmconfig(XcIOContext *ioctxt){ 46.39 + int err = -1; 46.40 + if(xcio_write(ioctxt, &ioctxt->vmconfig_n, sizeof(ioctxt->vmconfig_n))) goto exit; 46.41 + if(xcio_write(ioctxt, ioctxt->vmconfig, ioctxt->vmconfig_n)) goto exit; 46.42 + err = 0; 46.43 + exit: 46.44 + return err; 46.45 +} 46.46 46.47 -int xc_linux_save(int xc_handle, 46.48 - u32 domid, 46.49 - unsigned int flags, 46.50 - int (*writerfn)(void *, const void *, size_t), 46.51 - void *writerst ) 46.52 +int xc_linux_save(int xc_handle, XcIOContext *ioctxt) 46.53 { 46.54 dom0_op_t op; 46.55 int rc = 1, i, j, k, last_iter, iter = 0; 46.56 unsigned long mfn; 46.57 - int verbose = flags & XCFLAGS_VERBOSE; 46.58 - int live = flags & XCFLAGS_LIVE; 46.59 - int debug = flags & XCFLAGS_DEBUG; 46.60 - int sent_last_iter, sent_this_iter, skip_this_iter; 46.61 + u32 domid = ioctxt->domain; 46.62 + int live = (ioctxt->flags & XCFLAGS_LIVE); 46.63 + int debug = (ioctxt->flags & XCFLAGS_DEBUG); 46.64 + int sent_last_iter, skip_this_iter; 46.65 unsigned long dirtied_this_iter, faults_this_iter; 46.66 46.67 /* Important tuning parameters */ 46.68 @@ -246,7 +247,7 @@ int xc_linux_save(int xc_handle, 46.69 unsigned long *live_shinfo; 46.70 46.71 /* base of the region in which domain memory is mapped */ 46.72 - unsigned char *region_base; 46.73 + unsigned char *region_base = NULL; 46.74 46.75 /* A temporary mapping, and a copy, of the guest's suspend record. */ 46.76 suspend_record_t *p_srec; 46.77 @@ -266,16 +267,14 @@ int xc_linux_save(int xc_handle, 46.78 int needed_to_fix = 0; 46.79 int total_sent = 0; 46.80 46.81 - if ( mlock(&ctxt, sizeof(ctxt) ) ) 46.82 - { 46.83 - PERROR("Unable to mlock ctxt"); 46.84 + if (mlock(&ctxt, sizeof(ctxt))) { 46.85 + xcio_perror(ioctxt, "Unable to mlock ctxt"); 46.86 return 1; 46.87 } 46.88 46.89 /* Ensure that the domain exists, and that it is stopped. */ 46.90 - if ( xc_domain_pause(xc_handle, domid) ) 46.91 - { 46.92 - PERROR("Could not pause domain"); 46.93 + if ( xc_domain_pause(xc_handle, domid) ){ 46.94 + xcio_perror(ioctxt, "Could not pause domain"); 46.95 goto out; 46.96 } 46.97 46.98 @@ -283,9 +282,8 @@ int xc_linux_save(int xc_handle, 46.99 shared_info_frame = op.u.getdomaininfo.shared_info_frame; 46.100 46.101 /* A cheesy test to see whether the domain contains valid state. */ 46.102 - if ( ctxt.pt_base == 0 ) 46.103 - { 46.104 - ERROR("Domain is not in a valid Linux guest OS state"); 46.105 + if ( ctxt.pt_base == 0 ){ 46.106 + xcio_error(ioctxt, "Domain is not in a valid Linux guest OS state"); 46.107 goto out; 46.108 } 46.109 46.110 @@ -293,20 +291,17 @@ int xc_linux_save(int xc_handle, 46.111 domid for this to succeed. */ 46.112 p_srec = mfn_mapper_map_single(xc_handle, domid, 46.113 sizeof(*p_srec), PROT_READ, 46.114 - ctxt.cpu_ctxt.esi ); 46.115 - 46.116 - if (!p_srec) 46.117 - { 46.118 - ERROR("Couldn't map state record"); 46.119 + ctxt.cpu_ctxt.esi); 46.120 + if (!p_srec){ 46.121 + xcio_error(ioctxt, "Couldn't map state record"); 46.122 goto out; 46.123 } 46.124 46.125 nr_pfns = p_srec->nr_pfns; 46.126 46.127 /* cheesy sanity check */ 46.128 - if ( nr_pfns > 1024*1024 ) 46.129 - { 46.130 - ERROR("Invalid state record -- pfn count out of range"); 46.131 + if ( nr_pfns > 1024*1024 ){ 46.132 + xcio_error(ioctxt, "Invalid state record -- pfn count out of range"); 46.133 goto out; 46.134 } 46.135 46.136 @@ -316,9 +311,8 @@ int xc_linux_save(int xc_handle, 46.137 PAGE_SIZE, PROT_READ, 46.138 p_srec->pfn_to_mfn_frame_list ); 46.139 46.140 - if (!live_pfn_to_mfn_frame_list) 46.141 - { 46.142 - ERROR("Couldn't map pfn_to_mfn_frame_list"); 46.143 + if (!live_pfn_to_mfn_frame_list){ 46.144 + xcio_error(ioctxt, "Couldn't map pfn_to_mfn_frame_list"); 46.145 goto out; 46.146 } 46.147 46.148 @@ -345,24 +339,21 @@ int xc_linux_save(int xc_handle, 46.149 (its not clear why it would want to change them, and we'll be OK 46.150 from a safety POV anyhow. */ 46.151 46.152 - live_pfn_to_mfn_table = mfn_mapper_map_batch( xc_handle, domid, 46.153 - PROT_READ, 46.154 - live_pfn_to_mfn_frame_list, 46.155 - (nr_pfns+1023)/1024 ); 46.156 - if( !live_pfn_to_mfn_table ) 46.157 - { 46.158 - PERROR("Couldn't map pfn_to_mfn table"); 46.159 + live_pfn_to_mfn_table = mfn_mapper_map_batch(xc_handle, domid, 46.160 + PROT_READ, 46.161 + live_pfn_to_mfn_frame_list, 46.162 + (nr_pfns+1023)/1024 ); 46.163 + if( !live_pfn_to_mfn_table ){ 46.164 + xcio_perror(ioctxt, "Couldn't map pfn_to_mfn table"); 46.165 goto out; 46.166 } 46.167 46.168 46.169 /* Canonicalise the pfn-to-mfn table frame-number list. */ 46.170 memcpy( pfn_to_mfn_frame_list, live_pfn_to_mfn_frame_list, PAGE_SIZE ); 46.171 - for ( i = 0; i < nr_pfns; i += 1024 ) 46.172 - { 46.173 - if ( !translate_mfn_to_pfn(&pfn_to_mfn_frame_list[i/1024]) ) 46.174 - { 46.175 - ERROR("Frame # in pfn-to-mfn frame list is not in pseudophys"); 46.176 + for ( i = 0; i < nr_pfns; i += 1024 ){ 46.177 + if ( !translate_mfn_to_pfn(&pfn_to_mfn_frame_list[i/1024]) ){ 46.178 + xcio_error(ioctxt, "Frame # in pfn-to-mfn frame list is not in pseudophys"); 46.179 goto out; 46.180 } 46.181 } 46.182 @@ -370,27 +361,24 @@ int xc_linux_save(int xc_handle, 46.183 /* At this point, we can start the domain again if we're doing a 46.184 live suspend */ 46.185 46.186 - if( live ) 46.187 - { 46.188 + if( live ){ 46.189 if ( xc_shadow_control( xc_handle, domid, 46.190 DOM0_SHADOW_CONTROL_OP_ENABLE_LOGDIRTY, 46.191 - NULL, 0, NULL, NULL ) < 0 ) 46.192 - { 46.193 - ERROR("Couldn't enable shadow mode"); 46.194 + NULL, 0, NULL, NULL ) < 0 ){ 46.195 + xcio_error(ioctxt, "Couldn't enable shadow mode"); 46.196 goto out; 46.197 } 46.198 46.199 - if ( xc_domain_unpause(xc_handle, domid) < 0 ) 46.200 - { 46.201 - ERROR("Couldn't unpause domain"); 46.202 + if ( xc_domain_unpause(xc_handle, domid) < 0 ){ 46.203 + xcio_error(ioctxt, "Couldn't unpause domain"); 46.204 goto out; 46.205 } 46.206 46.207 last_iter = 0; 46.208 sent_last_iter = 1<<20; /* 4GB's worth of pages */ 46.209 + } else{ 46.210 + last_iter = 1; 46.211 } 46.212 - else 46.213 - last_iter = 1; 46.214 46.215 46.216 /* Setup to_send bitmap */ 46.217 @@ -401,25 +389,22 @@ int xc_linux_save(int xc_handle, 46.218 to_fix = calloc( 1, sz ); 46.219 to_skip = malloc( sz ); 46.220 46.221 - if (!to_send || !to_fix || !to_skip) 46.222 - { 46.223 - ERROR("Couldn't allocate to_send array"); 46.224 + if (!to_send || !to_fix || !to_skip){ 46.225 + xcio_error(ioctxt, "Couldn't allocate to_send array"); 46.226 goto out; 46.227 } 46.228 46.229 memset( to_send, 0xff, sz ); 46.230 46.231 - if ( mlock( to_send, sz ) ) 46.232 - { 46.233 - PERROR("Unable to mlock to_send"); 46.234 + if ( mlock( to_send, sz ) ){ 46.235 + xcio_perror(ioctxt, "Unable to mlock to_send"); 46.236 return 1; 46.237 } 46.238 46.239 /* (to fix is local only) */ 46.240 46.241 - if ( mlock( to_skip, sz ) ) 46.242 - { 46.243 - PERROR("Unable to mlock to_skip"); 46.244 + if ( mlock( to_skip, sz ) ){ 46.245 + xcio_perror(ioctxt, "Unable to mlock to_skip"); 46.246 return 1; 46.247 } 46.248 46.249 @@ -429,21 +414,19 @@ int xc_linux_save(int xc_handle, 46.250 15->4 16->4 17->5 */ 46.251 for( i=nr_pfns-1, order_nr=0; i ; i>>=1, order_nr++ ); 46.252 46.253 - printf("nr_pfns=%d order_nr=%d\n",nr_pfns, order_nr); 46.254 + printf("nr_pfns=%lu order_nr=%d\n",nr_pfns, order_nr); 46.255 46.256 /* We want zeroed memory so use calloc rather than malloc. */ 46.257 pfn_type = calloc(BATCH_SIZE, sizeof(unsigned long)); 46.258 pfn_batch = calloc(BATCH_SIZE, sizeof(unsigned long)); 46.259 46.260 - if ( (pfn_type == NULL) || (pfn_batch == NULL) ) 46.261 - { 46.262 + if ( (pfn_type == NULL) || (pfn_batch == NULL) ){ 46.263 errno = ENOMEM; 46.264 goto out; 46.265 } 46.266 46.267 - if ( mlock( pfn_type, BATCH_SIZE * sizeof(unsigned long) ) ) 46.268 - { 46.269 - ERROR("Unable to mlock"); 46.270 + if ( mlock( pfn_type, BATCH_SIZE * sizeof(unsigned long) ) ){ 46.271 + xcio_error(ioctxt, "Unable to mlock"); 46.272 goto out; 46.273 } 46.274 46.275 @@ -452,8 +435,7 @@ int xc_linux_save(int xc_handle, 46.276 * Quick belt and braces sanity check. 46.277 */ 46.278 #if DEBUG 46.279 - for ( i = 0; i < nr_pfns; i++ ) 46.280 - { 46.281 + for ( i = 0; i < nr_pfns; i++ ){ 46.282 mfn = live_pfn_to_mfn_table[i]; 46.283 46.284 if( (live_mfn_to_pfn_table[mfn] != i) && (mfn != 0x80000004) ) 46.285 @@ -467,29 +449,30 @@ int xc_linux_save(int xc_handle, 46.286 PAGE_SIZE, PROT_READ, 46.287 shared_info_frame); 46.288 46.289 - if (!live_shinfo) 46.290 - { 46.291 - ERROR("Couldn't map live_shinfo"); 46.292 + if (!live_shinfo){ 46.293 + xcio_error(ioctxt, "Couldn't map live_shinfo"); 46.294 goto out; 46.295 } 46.296 46.297 /* Start writing out the saved-domain record. */ 46.298 46.299 - if ( (*writerfn)(writerst, "LinuxGuestRecord", 16) || 46.300 - (*writerfn)(writerst, name, sizeof(name)) || 46.301 - (*writerfn)(writerst, &nr_pfns, sizeof(unsigned long)) || 46.302 - (*writerfn)(writerst, pfn_to_mfn_frame_list, PAGE_SIZE) ) 46.303 - { 46.304 - ERROR("Error when writing to state file (1)"); 46.305 + if ( xcio_write(ioctxt, "LinuxGuestRecord", 16) || 46.306 + xcio_write(ioctxt, name, sizeof(name)) || 46.307 + xcio_write(ioctxt, &nr_pfns, sizeof(unsigned long)) || 46.308 + xcio_write(ioctxt, pfn_to_mfn_frame_list, PAGE_SIZE) ){ 46.309 + xcio_error(ioctxt, "Error writing header"); 46.310 + goto out; 46.311 + } 46.312 + if(write_vmconfig(ioctxt)){ 46.313 + xcio_error(ioctxt, "Error writing vmconfig"); 46.314 goto out; 46.315 } 46.316 46.317 - track_cpu_usage( xc_handle, domid, 0, 0, 0, 0 ); 46.318 + track_cpu_usage(xc_handle, domid, 0, 0, 0, 0 ); 46.319 46.320 /* Now write out each data page, canonicalising page tables as we go... */ 46.321 46.322 - while(1) 46.323 - { 46.324 + while(1){ 46.325 unsigned int prev_pc, sent_this_iter, N, batch; 46.326 46.327 iter++; 46.328 @@ -498,15 +481,13 @@ int xc_linux_save(int xc_handle, 46.329 prev_pc = 0; 46.330 N=0; 46.331 46.332 - verbose_printf("Saving memory pages: iter %d 0%%", iter); 46.333 + xcio_info(ioctxt, "Saving memory pages: iter %d 0%%", iter); 46.334 46.335 - while( N < nr_pfns ) 46.336 - { 46.337 + while( N < nr_pfns ){ 46.338 unsigned int this_pc = (N * 100) / nr_pfns; 46.339 46.340 - if ( (this_pc - prev_pc) >= 5 ) 46.341 - { 46.342 - verbose_printf("\b\b\b\b%3d%%", this_pc); 46.343 + if ( (this_pc - prev_pc) >= 5 ){ 46.344 + xcio_info(ioctxt, "\b\b\b\b%3d%%", this_pc); 46.345 prev_pc = this_pc; 46.346 } 46.347 46.348 @@ -516,9 +497,8 @@ int xc_linux_save(int xc_handle, 46.349 if ( !last_iter && 46.350 xc_shadow_control(xc_handle, domid, 46.351 DOM0_SHADOW_CONTROL_OP_PEEK, 46.352 - to_skip, nr_pfns, NULL, NULL) != nr_pfns ) 46.353 - { 46.354 - ERROR("Error peeking shadow bitmap"); 46.355 + to_skip, nr_pfns, NULL, NULL) != nr_pfns ){ 46.356 + xcio_error(ioctxt, "Error peeking shadow bitmap"); 46.357 goto out; 46.358 } 46.359 46.360 @@ -526,25 +506,26 @@ int xc_linux_save(int xc_handle, 46.361 /* load pfn_type[] with the mfn of all the pages we're doing in 46.362 this batch. */ 46.363 46.364 - for( batch = 0; batch < BATCH_SIZE && N < nr_pfns ; N++ ) 46.365 - { 46.366 + for( batch = 0; batch < BATCH_SIZE && N < nr_pfns ; N++ ){ 46.367 int n = permute(N, nr_pfns, order_nr ); 46.368 46.369 if(0 && debug) 46.370 fprintf(stderr,"%d pfn= %08lx mfn= %08lx %d " 46.371 "[mfn]= %08lx\n", 46.372 - iter, n, live_pfn_to_mfn_table[n], 46.373 + iter, (unsigned long)n, live_pfn_to_mfn_table[n], 46.374 test_bit(n,to_send), 46.375 live_mfn_to_pfn_table[ 46.376 live_pfn_to_mfn_table[n]&0xFFFFF]); 46.377 46.378 - if (!last_iter && test_bit(n, to_send) && test_bit(n, to_skip)) 46.379 + if (!last_iter && test_bit(n, to_send) && test_bit(n, to_skip)){ 46.380 skip_this_iter++; /* stats keeping */ 46.381 + } 46.382 46.383 if (! ( (test_bit(n, to_send) && !test_bit(n, to_skip)) || 46.384 (test_bit(n, to_send) && last_iter) || 46.385 - (test_bit(n, to_fix) && last_iter) ) ) 46.386 + (test_bit(n, to_fix) && last_iter) ) ){ 46.387 continue; 46.388 + } 46.389 46.390 /* we get here if: 46.391 1. page is marked to_send & hasn't already been re-dirtied 46.392 @@ -555,8 +536,7 @@ int xc_linux_save(int xc_handle, 46.393 pfn_batch[batch] = n; 46.394 pfn_type[batch] = live_pfn_to_mfn_table[n]; 46.395 46.396 - if( pfn_type[batch] == 0x80000004 ) 46.397 - { 46.398 + if( pfn_type[batch] == 0x80000004 ){ 46.399 /* not currently in pusedo-physical map -- set bit 46.400 in to_fix that we must send this page in last_iter 46.401 unless its sent sooner anyhow */ 46.402 @@ -570,8 +550,7 @@ int xc_linux_save(int xc_handle, 46.403 } 46.404 46.405 if ( last_iter && test_bit(n, to_fix) && 46.406 - !test_bit(n, to_send) ) 46.407 - { 46.408 + !test_bit(n, to_send) ){ 46.409 needed_to_fix++; 46.410 DPRINTF("Fix! iter %d, pfn %lx. mfn %lx\n", 46.411 iter,n,pfn_type[batch]); 46.412 @@ -584,33 +563,30 @@ int xc_linux_save(int xc_handle, 46.413 46.414 DDPRINTF("batch %d:%d (n=%d)\n",iter,batch,n); 46.415 46.416 - if ( batch == 0 ) 46.417 + if ( batch == 0 ){ 46.418 goto skip; /* very unlikely */ 46.419 + } 46.420 46.421 if ( (region_base = mfn_mapper_map_batch(xc_handle, domid, 46.422 PROT_READ, 46.423 pfn_type, 46.424 - batch)) == 0 ) 46.425 - { 46.426 - PERROR("map batch failed"); 46.427 + batch)) == 0 ){ 46.428 + xcio_perror(ioctxt, "map batch failed"); 46.429 goto out; 46.430 } 46.431 46.432 - if ( get_pfn_type_batch(xc_handle, domid, batch, pfn_type) ) 46.433 - { 46.434 - ERROR("get_pfn_type_batch failed"); 46.435 + if ( get_pfn_type_batch(xc_handle, domid, batch, pfn_type) ){ 46.436 + xcio_error(ioctxt, "get_pfn_type_batch failed"); 46.437 goto out; 46.438 } 46.439 46.440 - for ( j = 0; j < batch; j++ ) 46.441 - { 46.442 - if ( (pfn_type[j] & LTAB_MASK) == XTAB ) 46.443 - { 46.444 + for ( j = 0; j < batch; j++ ){ 46.445 + if ( (pfn_type[j] & LTAB_MASK) == XTAB ){ 46.446 DDPRINTF("type fail: page %i mfn %08lx\n",j,pfn_type[j]); 46.447 continue; 46.448 } 46.449 46.450 - if ( 0 && debug ) 46.451 + if ( 0 && debug ){ 46.452 fprintf(stderr,"%d pfn= %08lx mfn= %08lx " 46.453 "[mfn]= %08lx sum= %08lx\n", 46.454 iter, 46.455 @@ -619,6 +595,7 @@ int xc_linux_save(int xc_handle, 46.456 live_mfn_to_pfn_table[pfn_type[j]&(~LTAB_MASK)], 46.457 csum_page(region_base + (PAGE_SIZE*j)) 46.458 ); 46.459 + } 46.460 46.461 /* canonicalise mfn->pfn */ 46.462 pfn_type[j] = (pfn_type[j] & LTAB_MASK) | 46.463 @@ -626,32 +603,27 @@ int xc_linux_save(int xc_handle, 46.464 } 46.465 46.466 46.467 - if ( (*writerfn)(writerst, &batch, sizeof(int) ) ) 46.468 - { 46.469 - ERROR("Error when writing to state file (2)"); 46.470 + if ( xcio_write(ioctxt, &batch, sizeof(int) ) ){ 46.471 + xcio_error(ioctxt, "Error when writing to state file (2)"); 46.472 goto out; 46.473 } 46.474 46.475 - if ( (*writerfn)(writerst, pfn_type, sizeof(unsigned long)*j ) ) 46.476 - { 46.477 - ERROR("Error when writing to state file (3)"); 46.478 + if ( xcio_write(ioctxt, pfn_type, sizeof(unsigned long)*j ) ){ 46.479 + xcio_error(ioctxt, "Error when writing to state file (3)"); 46.480 goto out; 46.481 } 46.482 46.483 /* entering this loop, pfn_type is now in pfns (Not mfns) */ 46.484 - for( j = 0; j < batch; j++ ) 46.485 - { 46.486 + for( j = 0; j < batch; j++ ){ 46.487 /* write out pages in batch */ 46.488 46.489 - if( (pfn_type[j] & LTAB_MASK) == XTAB) 46.490 - { 46.491 + if( (pfn_type[j] & LTAB_MASK) == XTAB){ 46.492 DDPRINTF("SKIP BOGUS page %i mfn %08lx\n",j,pfn_type[j]); 46.493 continue; 46.494 } 46.495 46.496 if ( ((pfn_type[j] & LTAB_MASK) == L1TAB) || 46.497 - ((pfn_type[j] & LTAB_MASK) == L2TAB) ) 46.498 - { 46.499 + ((pfn_type[j] & LTAB_MASK) == L2TAB) ){ 46.500 46.501 memcpy(page, region_base + (PAGE_SIZE*j), PAGE_SIZE); 46.502 46.503 @@ -659,8 +631,7 @@ int xc_linux_save(int xc_handle, 46.504 k < (((pfn_type[j] & LTAB_MASK) == L2TAB) ? 46.505 (HYPERVISOR_VIRT_START >> L2_PAGETABLE_SHIFT) : 46.506 1024); 46.507 - k++ ) 46.508 - { 46.509 + k++ ){ 46.510 unsigned long pfn; 46.511 46.512 if ( !(page[k] & _PAGE_PRESENT) ) continue; 46.513 @@ -683,20 +654,16 @@ int xc_linux_save(int xc_handle, 46.514 page[k] |= pfn << PAGE_SHIFT; 46.515 } /* end of page table rewrite for loop */ 46.516 46.517 - if ( (*writerfn)(writerst, page, PAGE_SIZE) ) 46.518 - { 46.519 - ERROR("Error when writing to state file (4)"); 46.520 + if ( xcio_write(ioctxt, page, PAGE_SIZE) ){ 46.521 + xcio_error(ioctxt, "Error when writing to state file (4)"); 46.522 goto out; 46.523 } 46.524 46.525 - } /* end of it's a PT page */ 46.526 - else 46.527 - { /* normal page */ 46.528 + } /* end of it's a PT page */ else { /* normal page */ 46.529 46.530 - if ( (*writerfn)(writerst, region_base + (PAGE_SIZE*j), 46.531 - PAGE_SIZE) ) 46.532 - { 46.533 - ERROR("Error when writing to state file (5)"); 46.534 + if ( xcio_write(ioctxt, region_base + (PAGE_SIZE*j), 46.535 + PAGE_SIZE) ){ 46.536 + xcio_error(ioctxt, "Error when writing to state file (5)"); 46.537 goto out; 46.538 } 46.539 } 46.540 @@ -712,40 +679,35 @@ int xc_linux_save(int xc_handle, 46.541 46.542 total_sent += sent_this_iter; 46.543 46.544 - verbose_printf("\r %d: sent %d, skipped %d, ", 46.545 + xcio_info(ioctxt, "\r %d: sent %d, skipped %d, ", 46.546 iter, sent_this_iter, skip_this_iter ); 46.547 46.548 - if ( last_iter ) 46.549 - { 46.550 + if ( last_iter ){ 46.551 track_cpu_usage( xc_handle, domid, 0, sent_this_iter, 0, 1); 46.552 - 46.553 - verbose_printf("Total pages sent= %d (%.2fx)\n", 46.554 + xcio_info(ioctxt, "Total pages sent= %d (%.2fx)\n", 46.555 total_sent, ((float)total_sent)/nr_pfns ); 46.556 - verbose_printf("(of which %d were fixups)\n", needed_to_fix ); 46.557 + xcio_info(ioctxt, "(of which %d were fixups)\n", needed_to_fix ); 46.558 } 46.559 46.560 - if ( debug && last_iter ) 46.561 - { 46.562 + if (last_iter && debug){ 46.563 int minusone = -1; 46.564 memset( to_send, 0xff, nr_pfns/8 ); 46.565 debug = 0; 46.566 printf("Entering debug resend-all mode\n"); 46.567 46.568 /* send "-1" to put receiver into debug mode */ 46.569 - if ( (*writerfn)(writerst, &minusone, sizeof(int)) ) 46.570 + if ( xcio_write(ioctxt, &minusone, sizeof(int)) ) 46.571 { 46.572 - ERROR("Error when writing to state file (6)"); 46.573 + xcio_error(ioctxt, "Error when writing to state file (6)"); 46.574 goto out; 46.575 } 46.576 46.577 continue; 46.578 } 46.579 46.580 - if ( last_iter ) 46.581 - break; 46.582 + if ( last_iter ) break; 46.583 46.584 - if ( live ) 46.585 - { 46.586 + if ( live ) { 46.587 if ( (iter >= max_iters) || 46.588 (sent_this_iter+skip_this_iter < 50) || 46.589 (total_sent > nr_pfns*max_factor) ) 46.590 @@ -761,7 +723,7 @@ int xc_linux_save(int xc_handle, 46.591 to_send, nr_pfns, &faults_this_iter, 46.592 &dirtied_this_iter) != nr_pfns ) 46.593 { 46.594 - ERROR("Error flushing shadow PT"); 46.595 + xcio_error(ioctxt, "Error flushing shadow PT"); 46.596 goto out; 46.597 } 46.598 46.599 @@ -781,9 +743,9 @@ int xc_linux_save(int xc_handle, 46.600 rc = 0; 46.601 46.602 /* Zero terminate */ 46.603 - if ( (*writerfn)(writerst, &rc, sizeof(int)) ) 46.604 + if ( xcio_write(ioctxt, &rc, sizeof(int)) ) 46.605 { 46.606 - ERROR("Error when writing to state file (6)"); 46.607 + xcio_error(ioctxt, "Error when writing to state file (6)"); 46.608 goto out; 46.609 } 46.610 46.611 @@ -794,50 +756,42 @@ int xc_linux_save(int xc_handle, 46.612 if ( (do_dom0_op(xc_handle, &op) < 0) || 46.613 ((u32)op.u.getdomaininfo.domain != domid) ) 46.614 { 46.615 - PERROR("Could not get info on domain"); 46.616 + xcio_perror(ioctxt, "Could not get info on domain"); 46.617 goto out; 46.618 } 46.619 46.620 /* Canonicalise the suspend-record frame number. */ 46.621 - if ( !translate_mfn_to_pfn(&ctxt.cpu_ctxt.esi) ) 46.622 - { 46.623 - ERROR("State record is not in range of pseudophys map"); 46.624 + if ( !translate_mfn_to_pfn(&ctxt.cpu_ctxt.esi) ){ 46.625 + xcio_error(ioctxt, "State record is not in range of pseudophys map"); 46.626 goto out; 46.627 } 46.628 46.629 /* Canonicalise each GDT frame number. */ 46.630 - for ( i = 0; i < ctxt.gdt_ents; i += 512 ) 46.631 - { 46.632 - if ( !translate_mfn_to_pfn(&ctxt.gdt_frames[i]) ) 46.633 - { 46.634 - ERROR("GDT frame is not in range of pseudophys map"); 46.635 + for ( i = 0; i < ctxt.gdt_ents; i += 512 ) { 46.636 + if ( !translate_mfn_to_pfn(&ctxt.gdt_frames[i]) ) { 46.637 + xcio_error(ioctxt, "GDT frame is not in range of pseudophys map"); 46.638 goto out; 46.639 } 46.640 } 46.641 46.642 /* Canonicalise the page table base pointer. */ 46.643 - if ( !MFN_IS_IN_PSEUDOPHYS_MAP(ctxt.pt_base >> PAGE_SHIFT) ) 46.644 - { 46.645 - ERROR("PT base is not in range of pseudophys map"); 46.646 + if ( !MFN_IS_IN_PSEUDOPHYS_MAP(ctxt.pt_base >> PAGE_SHIFT) ) { 46.647 + xcio_error(ioctxt, "PT base is not in range of pseudophys map"); 46.648 goto out; 46.649 } 46.650 ctxt.pt_base = live_mfn_to_pfn_table[ctxt.pt_base >> PAGE_SHIFT] << 46.651 PAGE_SHIFT; 46.652 46.653 - if ( (*writerfn)(writerst, &ctxt, sizeof(ctxt)) || 46.654 - (*writerfn)(writerst, live_shinfo, PAGE_SIZE) ) 46.655 - { 46.656 - ERROR("Error when writing to state file (1)"); 46.657 + if ( xcio_write(ioctxt, &ctxt, sizeof(ctxt)) || 46.658 + xcio_write(ioctxt, live_shinfo, PAGE_SIZE) ) { 46.659 + xcio_error(ioctxt, "Error when writing to state file (1)"); 46.660 goto out; 46.661 } 46.662 munmap(live_shinfo, PAGE_SIZE); 46.663 46.664 out: 46.665 - if ( pfn_type != NULL ) 46.666 - free(pfn_type); 46.667 - 46.668 + if ( pfn_type != NULL ) free(pfn_type); 46.669 DPRINTF("Save exit rc=%d\n",rc); 46.670 - 46.671 return !!rc; 46.672 46.673 }
47.1 --- a/tools/xc/lib/xc_private.h Mon Jun 28 08:17:15 2004 +0000 47.2 +++ b/tools/xc/lib/xc_private.h Mon Jun 28 15:03:15 2004 +0000 47.3 @@ -136,6 +136,8 @@ int close_pfn_mapper(int pm_handle); 47.4 void *map_pfn_writeable(int pm_handle, unsigned long pfn); 47.5 void *map_pfn_readonly(int pm_handle, unsigned long pfn); 47.6 void unmap_pfn(int pm_handle, void *vaddr); 47.7 +int get_pfn_type_batch(int xc_handle, u32 dom, int num, unsigned long *arr); 47.8 +unsigned long csum_page (void * page); 47.9 47.10 /* 47.11 * MMU updates. 47.12 @@ -202,4 +204,5 @@ void * mfn_mapper_queue_entry(mfn_mapper 47.13 47.14 long long xc_domain_get_cpu_usage( int xc_handle, domid_t domid ); 47.15 47.16 +#include "xc_io.h" 47.17 #endif /* __XC_PRIVATE_H__ */
48.1 --- a/tools/xc/py/Xc.c Mon Jun 28 08:17:15 2004 +0000 48.2 +++ b/tools/xc/py/Xc.c Mon Jun 28 15:03:15 2004 +0000 48.3 @@ -14,6 +14,8 @@ 48.4 #include <sys/socket.h> 48.5 #include <netdb.h> 48.6 #include <arpa/inet.h> 48.7 +#include "xc_private.h" 48.8 +#include "gzip_stream.h" 48.9 48.10 /* Needed for Python versions earlier than 2.3. */ 48.11 #ifndef PyMODINIT_FUNC 48.12 @@ -189,115 +191,31 @@ static PyObject *pyxc_domain_getinfo(PyO 48.13 return list; 48.14 } 48.15 48.16 -static PyObject *tcp_save(XcObject *xc, u32 dom, char *url, unsigned flags){ 48.17 -#define max_namelen 64 48.18 - char server[max_namelen]; 48.19 - char *port_s; 48.20 - int port=777; 48.21 - int sd = -1; 48.22 - struct hostent *h; 48.23 - struct sockaddr_in s; 48.24 - int sockbufsize; 48.25 +static int file_save(XcObject *xc, XcIOContext *ctxt, char *state_file){ 48.26 int rc = -1; 48.27 - 48.28 - int writerfn(void *fd, const void *buf, size_t count) { 48.29 - int tot = 0, rc; 48.30 - do { 48.31 - rc = write( (int) fd, ((char*)buf)+tot, count-tot ); 48.32 - if ( rc < 0 ) { perror("WRITE"); return rc; }; 48.33 - tot += rc; 48.34 - } 48.35 - while ( tot < count ); 48.36 - return 0; 48.37 - } 48.38 - 48.39 - strncpy( server, url+strlen("tcp://"), max_namelen); 48.40 - server[max_namelen-1]='\0'; 48.41 - if ( (port_s = strchr(server,':')) != NULL ) { 48.42 - *port_s = '\0'; 48.43 - port = atoi(port_s+1); 48.44 - } 48.45 - printf("X server=%s port=%d\n",server,port); 48.46 - h = gethostbyname(server); 48.47 - sd = socket(AF_INET, SOCK_STREAM,0); 48.48 - if (sd < 0) goto serr; 48.49 - s.sin_family = AF_INET; 48.50 - bcopy ( h->h_addr, &(s.sin_addr.s_addr), h->h_length); 48.51 - s.sin_port = htons(port); 48.52 - if ( connect(sd, (struct sockaddr *) &s, sizeof(s)) ) goto serr; 48.53 - sockbufsize=128*1024; 48.54 - if ( setsockopt(sd, SOL_SOCKET, SO_SNDBUF, &sockbufsize, sizeof sockbufsize) < 0 ) goto serr; 48.55 - 48.56 - if ( xc_linux_save(xc->xc_handle, dom, flags, writerfn, (void*)sd) == 0 ) { 48.57 - if ( read( sd, &rc, sizeof(int) ) != sizeof(int) ) goto serr; 48.58 - 48.59 - if ( rc == 0 ) { 48.60 - printf("Migration succesful -- destroy local copy\n"); 48.61 - xc_domain_destroy(xc->xc_handle, dom); 48.62 - close(sd); 48.63 - Py_INCREF(zero); 48.64 - return zero; 48.65 - } else { 48.66 - errno = rc; 48.67 - } 48.68 - } 48.69 + int fd = -1; 48.70 + int open_flags = (O_CREAT | O_EXCL | O_WRONLY); 48.71 + int open_mode = 0644; 48.72 48.73 - serr: 48.74 - printf("Migration failed -- restart local copy\n"); 48.75 - xc_domain_unpause(xc->xc_handle, dom); 48.76 - PyErr_SetFromErrno(xc_error); 48.77 - if ( sd >= 0 ) close(sd); 48.78 - return NULL; 48.79 - 48.80 -} 48.81 - 48.82 -static PyObject *file_save(XcObject *xc, u32 dom, char *state_file, unsigned flags){ 48.83 - int fd = -1; 48.84 - gzFile gfd = NULL; 48.85 - 48.86 - int writerfn(void *fd, const void *buf, size_t count) { 48.87 - int rc; 48.88 - while ( ((rc = gzwrite( (gzFile*)fd, (void*)buf, count)) == -1) && 48.89 - (errno = EINTR) ) 48.90 - continue; 48.91 - return ! (rc == count); 48.92 - } 48.93 - 48.94 - if (strncmp(state_file,"file:",strlen("file:")) == 0){ 48.95 - state_file += strlen("file:"); 48.96 - } 48.97 - 48.98 - if ( (fd = open(state_file, O_CREAT|O_EXCL|O_WRONLY, 0644)) == -1 ) { 48.99 - perror("Could not open file for writing"); 48.100 - goto err; 48.101 - } 48.102 - /* 48.103 - * Compression rate 1: we want speed over compression. 48.104 - * We're mainly going for those zero pages, after all. 48.105 - */ 48.106 - if ( (gfd = gzdopen(fd, "wb1")) == NULL ) { 48.107 - perror("Could not allocate compression state for state file"); 48.108 - close(fd); 48.109 - goto err; 48.110 - } 48.111 - if ( xc_linux_save(xc->xc_handle, dom, flags, writerfn, gfd) == 0 ) { 48.112 - /* kill domain. We don't want to do this for checkpointing, but 48.113 - if we don't do it here I think people will hurt themselves 48.114 - by accident... */ 48.115 - xc_domain_destroy(xc->xc_handle, dom); 48.116 - gzclose(gfd); 48.117 - close(fd); 48.118 - 48.119 - Py_INCREF(zero); 48.120 - return zero; 48.121 - } 48.122 - 48.123 - err: 48.124 - PyErr_SetFromErrno(xc_error); 48.125 - if ( gfd != NULL ) gzclose(gfd); 48.126 - if ( fd >= 0 ) close(fd); 48.127 - unlink(state_file); 48.128 - return NULL; 48.129 + fd = open(state_file, open_flags, open_mode); 48.130 + if(fd < 0){ 48.131 + xcio_perror(ctxt, "Could not open file for writing"); 48.132 + goto exit; 48.133 + } 48.134 + /* Compression rate 1: we want speed over compression. 48.135 + * We're mainly going for those zero pages, after all. 48.136 + */ 48.137 + ctxt->io = gzip_stream_fdopen(fd, "wb1"); 48.138 + if(!ctxt->io){ 48.139 + xcio_perror(ctxt, "Could not allocate compression state"); 48.140 + goto exit; 48.141 + } 48.142 + rc = xc_linux_save(xc->xc_handle, ctxt); 48.143 + exit: 48.144 + if(ctxt->io) IOStream_close(ctxt->io); 48.145 + if(fd >= 0) close(fd); 48.146 + unlink(state_file); 48.147 + return rc; 48.148 } 48.149 48.150 static PyObject *pyxc_linux_save(PyObject *self, 48.151 @@ -306,195 +224,92 @@ static PyObject *pyxc_linux_save(PyObjec 48.152 { 48.153 XcObject *xc = (XcObject *)self; 48.154 48.155 - u32 dom; 48.156 + u32 dom; 48.157 char *state_file; 48.158 - int progress = 1, live = -1, debug = 0; 48.159 + int progress = 1, debug = 0; 48.160 unsigned int flags = 0; 48.161 PyObject *val = NULL; 48.162 - 48.163 - static char *kwd_list[] = { "dom", "state_file", "progress", 48.164 - "live", "debug", NULL }; 48.165 + int rc = -1; 48.166 + XcIOContext ioctxt = { .info = iostdout, .err = iostderr }; 48.167 48.168 - if ( !PyArg_ParseTupleAndKeywords(args, kwds, "is|iii", kwd_list, 48.169 - &dom, &state_file, &progress, 48.170 - &live, &debug) ) 48.171 - goto exit; 48.172 + static char *kwd_list[] = { "dom", "state_file", "vmconfig", "progress", "debug", NULL }; 48.173 48.174 - if (progress) flags |= XCFLAGS_VERBOSE; 48.175 - if (live == 1) flags |= XCFLAGS_LIVE; 48.176 - if (debug) flags |= XCFLAGS_DEBUG; 48.177 - 48.178 - if ( strncmp(state_file,"tcp:", strlen("tcp:")) == 0 ) { 48.179 - /* default to live for tcp */ 48.180 - if (live == -1) flags |= XCFLAGS_LIVE; 48.181 - val = tcp_save(xc, dom, state_file, flags); 48.182 - } else { 48.183 - val = file_save(xc, dom, state_file, flags); 48.184 + if (!PyArg_ParseTupleAndKeywords(args, kwds, "is|siii", kwd_list, 48.185 + &ioctxt.domain, 48.186 + &state_file, 48.187 + &ioctxt.vmconfig, 48.188 + &progress, 48.189 + &debug)){ 48.190 + goto exit; 48.191 } 48.192 + ioctxt.vmconfig_n = (ioctxt.vmconfig ? strlen(ioctxt.vmconfig) : 0); 48.193 + if (progress) ioctxt.flags |= XCFLAGS_VERBOSE; 48.194 + if (debug) ioctxt.flags |= XCFLAGS_DEBUG; 48.195 + if(!state_file || state_file[0] == '\0') goto exit; 48.196 + rc = file_save(xc, &ioctxt, state_file); 48.197 + if(rc){ 48.198 + PyErr_SetFromErrno(xc_error); 48.199 + goto exit; 48.200 + } 48.201 + //xc_domain_destroy(xc->xc_handle, dom); 48.202 + Py_INCREF(zero); 48.203 + val = zero; 48.204 exit: 48.205 return val; 48.206 } 48.207 48.208 + 48.209 +static int file_restore(XcObject *xc, XcIOContext *ioctxt, char *state_file){ 48.210 + int rc = -1; 48.211 + 48.212 + ioctxt->io = gzip_stream_fopen(state_file, "rb"); 48.213 + if (!ioctxt->io) { 48.214 + xcio_perror(ioctxt, "Could not open file for reading"); 48.215 + goto exit; 48.216 + } 48.217 + 48.218 + rc = xc_linux_restore(xc->xc_handle, ioctxt); 48.219 + exit: 48.220 + if(ioctxt->io) IOStream_close(ioctxt->io); 48.221 + return rc; 48.222 +} 48.223 + 48.224 static PyObject *pyxc_linux_restore(PyObject *self, 48.225 PyObject *args, 48.226 PyObject *kwds) 48.227 { 48.228 XcObject *xc = (XcObject *)self; 48.229 - 48.230 - char *state_file; 48.231 - int progress = 1; 48.232 - u32 dom; 48.233 - unsigned int flags = 0; 48.234 - 48.235 - static char *kwd_list[] = { "dom", "state_file", "progress", NULL }; 48.236 - 48.237 - if ( !PyArg_ParseTupleAndKeywords(args, kwds, "is|i", kwd_list, 48.238 - &dom, &state_file, &progress) ) 48.239 - return NULL; 48.240 - 48.241 - if ( progress ) 48.242 - flags |= XCFLAGS_VERBOSE; 48.243 - 48.244 - if ( strncmp(state_file,"tcp:", strlen("tcp:")) == 0 ) 48.245 - { 48.246 -#define max_namelen 64 48.247 - char server[max_namelen]; 48.248 - char *port_s; 48.249 - int port=777; 48.250 - int ld = -1, sd = -1; 48.251 - struct hostent *h; 48.252 - struct sockaddr_in s, d, p; 48.253 - socklen_t dlen, plen; 48.254 - int sockbufsize; 48.255 - int on = 1, rc = -1; 48.256 + char *state_file; 48.257 + int progress = 1, debug = 0; 48.258 + u32 dom; 48.259 + PyObject *val = NULL; 48.260 + XcIOContext ioctxt = { .info = iostdout, .err = iostderr }; 48.261 + int rc =-1; 48.262 48.263 - int readerfn(void *fd, void *buf, size_t count) 48.264 - { 48.265 - int rc, tot = 0; 48.266 - do { 48.267 - rc = read( (int) fd, ((char*)buf)+tot, count-tot ); 48.268 - if ( rc < 0 ) { perror("READ"); return rc; } 48.269 - if ( rc == 0 ) { printf("read: need %d, tot=%d got zero\n", 48.270 - count-tot, tot); return -1; } 48.271 - tot += rc; 48.272 - } 48.273 - while ( tot < count ); 48.274 - return 0; 48.275 - } 48.276 - 48.277 - strncpy( server, state_file+strlen("tcp://"), max_namelen); 48.278 - server[max_namelen-1]='\0'; 48.279 - if ( (port_s = strchr(server,':')) != NULL ) 48.280 - { 48.281 - *port_s = '\0'; 48.282 - port = atoi(port_s+1); 48.283 - } 48.284 - 48.285 - printf("X server=%s port=%d\n",server,port); 48.286 - 48.287 - h = gethostbyname(server); 48.288 - ld = socket (AF_INET,SOCK_STREAM,0); 48.289 - if ( ld < 0 ) goto serr; 48.290 - s.sin_family = AF_INET; 48.291 - s.sin_addr.s_addr = htonl(INADDR_ANY); 48.292 - s.sin_port = htons(port); 48.293 - 48.294 - if ( setsockopt(ld, SOL_SOCKET, SO_REUSEADDR, &on, sizeof (on)) < 0 ) 48.295 - goto serr; 48.296 - 48.297 - if ( bind(ld, (struct sockaddr *) &s, sizeof(s)) ) 48.298 - goto serr; 48.299 - 48.300 - if ( listen(ld, 1) ) 48.301 - goto serr; 48.302 - 48.303 - dlen=sizeof(struct sockaddr); 48.304 - if ( (sd = accept(ld, (struct sockaddr *) &d, &dlen )) < 0 ) 48.305 - goto serr; 48.306 - 48.307 - plen = sizeof(p); 48.308 - if ( getpeername(sd, (struct sockaddr_in *) &p, 48.309 - &plen) < 0 ) 48.310 - goto serr; 48.311 + static char *kwd_list[] = { "state_file", "progress", "debug", NULL }; 48.312 48.313 - printf("Accepted connection from %s\n", inet_ntoa(p.sin_addr)); 48.314 - 48.315 - sockbufsize=128*1024; 48.316 - if ( setsockopt(sd, SOL_SOCKET, SO_SNDBUF, &sockbufsize, 48.317 - sizeof sockbufsize) < 0 ) 48.318 - goto serr; 48.319 - 48.320 - rc = xc_linux_restore(xc->xc_handle, dom, flags, 48.321 - readerfn, (void*)sd, &dom); 48.322 - 48.323 - write( sd, &rc, sizeof(int) ); 48.324 - 48.325 - if (rc == 0) 48.326 - { 48.327 - close(sd); 48.328 - Py_INCREF(zero); 48.329 - return zero; 48.330 - } 48.331 - errno = rc; 48.332 - 48.333 - serr: 48.334 - PyErr_SetFromErrno(xc_error); 48.335 - if ( ld >= 0 ) close(ld); 48.336 - if ( sd >= 0 ) close(sd); 48.337 - return NULL; 48.338 - } 48.339 - else 48.340 - { 48.341 - int fd = -1; 48.342 - gzFile gfd = NULL; 48.343 + if (!PyArg_ParseTupleAndKeywords(args, kwds, "is|ii", kwd_list, 48.344 + &ioctxt.domain, 48.345 + &state_file, 48.346 + &progress, 48.347 + &debug)){ 48.348 + goto exit; 48.349 + } 48.350 + if (progress) ioctxt.flags |= XCFLAGS_VERBOSE; 48.351 + if (debug) ioctxt.flags |= XCFLAGS_DEBUG; 48.352 48.353 - int readerfn(void *fd, void *buf, size_t count) 48.354 - { 48.355 - int rc; 48.356 - while ( ((rc = gzread( (gzFile*)fd, (void*)buf, count)) == -1) && 48.357 - (errno = EINTR) ) 48.358 - continue; 48.359 - return ! (rc == count); 48.360 - } 48.361 - 48.362 - if ( strncmp(state_file,"file:",strlen("file:")) == 0 ) 48.363 - state_file += strlen("file:"); 48.364 - 48.365 - if ( (fd = open(state_file, O_RDONLY)) == -1 ) 48.366 - { 48.367 - perror("Could not open file for writing"); 48.368 - goto err; 48.369 - } 48.370 - 48.371 - /* 48.372 - * Compression rate 1: we want speed over compression. 48.373 - * We're mainly going for those zero pages, after all. 48.374 - */ 48.375 - if ( (gfd = gzdopen(fd, "rb")) == NULL ) 48.376 - { 48.377 - perror("Could not allocate compression state for state file"); 48.378 - close(fd); 48.379 - goto err; 48.380 - } 48.381 - 48.382 - 48.383 - if ( xc_linux_restore(xc->xc_handle, dom, flags, 48.384 - readerfn, gfd, &dom) == 0 ) 48.385 - { 48.386 - gzclose(gfd); 48.387 - close(fd); 48.388 - 48.389 - Py_INCREF(zero); 48.390 - return zero; 48.391 - } 48.392 - 48.393 - err: 48.394 + if(!state_file || state_file[0] == '\0') goto exit; 48.395 + rc = file_restore(xc, &ioctxt, state_file); 48.396 + if(rc){ 48.397 PyErr_SetFromErrno(xc_error); 48.398 - if ( gfd != NULL ) gzclose(gfd); 48.399 - if ( fd >= 0 ) close(fd); 48.400 - return NULL; 48.401 + goto exit; 48.402 } 48.403 - 48.404 + val = Py_BuildValue("{s:i,s:s}", 48.405 + "dom", ioctxt.domain, 48.406 + "vmconfig", ioctxt.vmconfig); 48.407 + //? free(ioctxt.vmconfig); 48.408 + exit: 48.409 + return val; 48.410 } 48.411 48.412 static PyObject *pyxc_linux_build(PyObject *self,
49.1 --- a/tools/xc/py/setup.py Mon Jun 28 08:17:15 2004 +0000 49.2 +++ b/tools/xc/py/setup.py Mon Jun 28 15:03:15 2004 +0000 49.3 @@ -3,12 +3,17 @@ from distutils.core import setup, Extens 49.4 49.5 module = Extension("xc", 49.6 extra_compile_args = ["-fno-strict-aliasing"], 49.7 - include_dirs = ["../lib"], 49.8 - library_dirs = ["../lib"], 49.9 + include_dirs = ["../lib", 49.10 + "../../../xen/include/hypervisor-ifs", 49.11 + "../../../linux-xen-sparse/include", 49.12 + "../../xu/lib", 49.13 + "../../lib" ], 49.14 + library_dirs = ["../lib", 49.15 + "../../lib" ], 49.16 libraries = ["xc"], 49.17 sources = ["Xc.c"]) 49.18 49.19 setup(name = "xc", 49.20 - version = "1.0", 49.21 + version = "2.0", 49.22 ext_package = "xen.ext", 49.23 ext_modules = [module])
50.1 --- a/tools/xen/lib/xend/XendDomain.py Mon Jun 28 08:17:15 2004 +0000 50.2 +++ b/tools/xen/lib/xend/XendDomain.py Mon Jun 28 15:03:15 2004 +0000 50.3 @@ -235,7 +235,7 @@ class XendDomain: 50.4 def domain_get(self, id): 50.5 id = str(id) 50.6 self.refresh_domain(id) 50.7 - return self.domain[id] 50.8 + return self.domain.get(id) 50.9 50.10 def domain_unpause(self, id): 50.11 """(Re)start domain running. 50.12 @@ -278,22 +278,26 @@ class XendDomain: 50.13 """ 50.14 # Need a cancel too? 50.15 pass 50.16 - 50.17 + 50.18 def domain_save(self, id, dst, progress=0): 50.19 """Save domain state to file, destroy domain. 50.20 """ 50.21 dom = int(id) 50.22 + dominfo = self.domain_get(id) 50.23 + if not dominfo: 50.24 + return -1 50.25 + vmconfig = sxp.to_string(dominfo.sxpr()) 50.26 self.domain_pause(id) 50.27 eserver.inject('xend.domain.save', id) 50.28 - rc = xc.linux_save(dom=dom, state_file=dst, progress=progress) 50.29 + rc = xc.linux_save(dom=dom, state_file=dst, vmconfig=vmconfig, progress=progress) 50.30 if rc == 0: 50.31 self.domain_destroy(id) 50.32 return rc 50.33 50.34 - def domain_restore(self, src, config, progress=0): 50.35 + def domain_restore(self, src, progress=0): 50.36 """Restore domain from file. 50.37 """ 50.38 - dominfo = XendDomainInfo.dom_restore(dom, config) 50.39 + dominfo = XendDomainInfo.vm_restore(src, progress=progress) 50.40 self._add_domain(dominfo.id, dominfo) 50.41 return dominfo 50.42
51.1 --- a/tools/xen/lib/xend/XendDomainInfo.py Mon Jun 28 08:17:15 2004 +0000 51.2 +++ b/tools/xen/lib/xend/XendDomainInfo.py Mon Jun 28 15:03:15 2004 +0000 51.3 @@ -272,22 +272,23 @@ def vm_recreate(config, info): 51.4 d.callback(vm) 51.5 return d 51.6 51.7 -def vm_restore(src, config, progress=0): 51.8 +def vm_restore(src, progress=0): 51.9 """Restore a VM from a disk image. 51.10 51.11 src saved state to restore 51.12 - config configuration 51.13 progress progress reporting flag 51.14 returns deferred 51.15 raises VmError for invalid configuration 51.16 """ 51.17 vm = XendDomainInfo() 51.18 - vm.config = config 51.19 - ostype = "linux" #todo set from config 51.20 + ostype = "linux" #todo Set from somewhere (store in the src?). 51.21 restorefn = getattr(xc, "%s_restore" % ostype) 51.22 - dom = restorefn(state_file=src, progress=progress) 51.23 + d = restorefn(state_file=src, progress=progress) 51.24 + dom = int(d['dom']) 51.25 if dom < 0: 51.26 raise VMError('restore failed') 51.27 + vmconfig = sxp.from_string(d['vmconfig']) 51.28 + vm.config = sxp.child_value(vmconfig, 'config') 51.29 deferred = vm.dom_configure(dom) 51.30 def vifs_cb(val, vm): 51.31 vif_up(vm.ipaddrs) 51.32 @@ -855,9 +856,7 @@ def vm_field_vfr(vm, config, val, index) 51.33 if not ip: 51.34 raise VmError('vfr: missing ip address') 51.35 ipaddrs.append(ip); 51.36 - #Don't do this in new i/o model. 51.37 - #print 'vm_field_vfr> add rule', 'dom=', vm.dom, 'vif=', vif, 'ip=', ip 51.38 - #xenctl.ip.setup_vfr_rules_for_vif(vm.dom, vif, ip) 51.39 + # todo: Configure the ipaddrs. 51.40 vm.ipaddrs = ipaddrs 51.41 51.42 def vnet_bridge(vnet, vmac, dom, idx):
52.1 --- a/tools/xen/lib/xend/server/SrvDomain.py Mon Jun 28 08:17:15 2004 +0000 52.2 +++ b/tools/xen/lib/xend/server/SrvDomain.py Mon Jun 28 15:03:15 2004 +0000 52.3 @@ -44,13 +44,6 @@ class SrvDomain(SrvDir): 52.4 val = fn(req.args, {'dom': self.dom.id}) 52.5 return val 52.6 52.7 - def op_restore(self, op, req): 52.8 - fn = FormFn(self.xd.domain_restore, 52.9 - [['dom', 'int'], 52.10 - ['file', 'str']]) 52.11 - val = fn(req.args, {'dom': self.dom.id}) 52.12 - return val 52.13 - 52.14 def op_migrate(self, op, req): 52.15 fn = FormFn(self.xd.domain_migrate, 52.16 [['dom', 'int'],
53.1 --- a/tools/xen/lib/xend/server/SrvDomainDir.py Mon Jun 28 08:17:15 2004 +0000 53.2 +++ b/tools/xen/lib/xend/server/SrvDomainDir.py Mon Jun 28 15:03:15 2004 +0000 53.3 @@ -7,6 +7,7 @@ from twisted.web import error 53.4 53.5 from xen.xend import sxp 53.6 from xen.xend import XendDomain 53.7 +from xen.xend.Args import FormFn 53.8 53.9 from SrvDir import SrvDir 53.10 from SrvDomain import SrvDomain 53.11 @@ -88,6 +89,12 @@ class SrvDomainDir(SrvDir): 53.12 out.close() 53.13 return val 53.14 53.15 + def op_restore(self, op, req): 53.16 + fn = FormFn(self.xd.domain_restore, 53.17 + [['file', 'str']]) 53.18 + val = fn(req.args) 53.19 + return val 53.20 + 53.21 def render_POST(self, req): 53.22 return self.perform(req) 53.23 53.24 @@ -129,3 +136,9 @@ class SrvDomainDir(SrvDir): 53.25 req.write('<button type="submit" name="op" value="create">Create Domain</button>') 53.26 req.write('Config <input type="file" name="config"><br>') 53.27 req.write('</form>') 53.28 + req.write('<form method="post" action="%s" enctype="multipart/form-data">' 53.29 + % req.prePathURL()) 53.30 + req.write('<button type="submit" name="op" value="create">Restore Domain</button>') 53.31 + req.write('State <input type="string" name="state"><br>') 53.32 + req.write('</form>') 53.33 +
54.1 --- a/tools/xen/lib/xend/sxp.py Mon Jun 28 08:17:15 2004 +0000 54.2 +++ b/tools/xen/lib/xend/sxp.py Mon Jun 28 15:03:15 2004 +0000 54.3 @@ -16,6 +16,7 @@ import sys 54.4 import types 54.5 import errno 54.6 import string 54.7 +from StringIO import StringIO 54.8 54.9 __all__ = [ 54.10 "mime_type", 54.11 @@ -521,6 +522,28 @@ def elements(sxpr, ctxt=None): 54.12 yield v 54.13 i += 1 54.14 54.15 +def to_string(sxpr): 54.16 + """Convert an sxpr to a string. 54.17 + 54.18 + sxpr sxpr 54.19 + returns string 54.20 + """ 54.21 + io = StringIO() 54.22 + sxp.show(sxpr, io) 54.23 + io.seek(0) 54.24 + val = io.getvalue() 54.25 + io.close() 54.26 + return val 54.27 + 54.28 +def from_string(str): 54.29 + """Create an sxpr by parsing a string. 54.30 + 54.31 + str string 54.32 + returns sxpr 54.33 + """ 54.34 + io = StringIO(str) 54.35 + return parse(io) 54.36 + 54.37 def parse(io): 54.38 """Completely parse all input from 'io'. 54.39
55.1 --- a/tools/xen/xend Mon Jun 28 08:17:15 2004 +0000 55.2 +++ b/tools/xen/xend Mon Jun 28 15:03:15 2004 +0000 55.3 @@ -13,8 +13,8 @@ 55.4 55.5 xend stop 55.6 55.7 - Unfortunately restarting it upsets the channel to dom0 and 55.8 - domain management stops working - needs a reboot to fix. 55.9 + The daemon should reconnect to device control interfaces 55.10 + and recover its state when restarted. 55.11 """ 55.12 import os 55.13 import sys