From 2e9eaedf8045d9e01f5041a3292bc5a951f801ff Mon Sep 17 00:00:00 2001 From: Thomas A Date: Sun, 26 Feb 2023 15:50:37 -0800 Subject: [PATCH] Move Source From Main Repo Based on xar-420 --- CMakeLists.txt | 55 + README | 11 + Revision.plist | Bin 0 -> 59 bytes patches/appleadditions.diff | 1170 +++ patches/context.diff | 2056 ++++++ patches/hash.diff | 551 ++ patches/noea.diff | 26 + patches/static-lib.diff | 39 + test_tools/xar.tcl | 69 + xar.plist | 26 + xar.txt | 35 + xar.xcconfig | 11 + xar.xcodeproj/project.pbxproj | 1397 ++++ .../contents.xcworkspacedata | 7 + xar/.cvsignore | 7 + xar/ChangeLog | 68 + xar/INSTALL | 160 + xar/LICENSE | 33 + xar/Makefile.in | 108 + xar/TODO | 2 + xar/autogen.sh | 21 + xar/cfghdrs.stamp | 2 + xar/cfghdrs.stamp.in | 1 + xar/cfgoutputs.stamp | 1 + xar/cfgoutputs.stamp.in | 1 + xar/config.guess | 1466 ++++ xar/config.status | 1068 +++ xar/config.sub | 1579 ++++ xar/configure | 6350 +++++++++++++++++ xar/configure.ac | 361 + xar/include/.cvsignore | 2 + xar/include/config.h | 37 + xar/include/config.h.in | 36 + xar/include/xar.h | 268 + xar/include/xar.h.in | 268 + xar/install-sh | 250 + xar/lib/.cvsignore | 4 + xar/lib/Makefile.inc | 205 + xar/lib/Makefile.inc.in | 205 + xar/lib/appledouble.h | 103 + xar/lib/archive.c | 1739 +++++ xar/lib/archive.h | 109 + xar/lib/arcmod.c | 148 + xar/lib/arcmod.h | 59 + xar/lib/asprintf.h | 92 + xar/lib/b64.c | 217 + xar/lib/b64.h | 12 + xar/lib/bzxar.c | 294 + xar/lib/bzxar.h | 47 + xar/lib/darwinattr.c | 814 +++ xar/lib/darwinattr.h | 43 + xar/lib/data.c | 273 + xar/lib/data.h | 57 + xar/lib/ea.c | 127 + xar/lib/ea.h | 15 + xar/lib/err.c | 101 + xar/lib/ext2.c | 257 + xar/lib/ext2.h | 42 + xar/lib/fbsdattr.c | 344 + xar/lib/fbsdattr.h | 41 + xar/lib/filetree.c | 1103 +++ xar/lib/filetree.h | 144 + xar/lib/hash.c | 407 ++ xar/lib/hash.h | 63 + xar/lib/io.c | 871 +++ xar/lib/io.h | 96 + xar/lib/libxar.la.in | 35 + xar/lib/libxar.la.in.in | 35 + xar/lib/linuxattr.c | 275 + xar/lib/linuxattr.h | 41 + xar/lib/lzmaxar.c | 357 + xar/lib/lzmaxar.h | 47 + xar/lib/macho.c | 407 ++ xar/lib/macho.h | 69 + xar/lib/script.c | 111 + xar/lib/script.h | 39 + xar/lib/signature.c | 558 ++ xar/lib/signature.h | 73 + xar/lib/stat.c | 825 +++ xar/lib/stat.h | 48 + xar/lib/strmode.h | 149 + xar/lib/subdoc.c | 218 + xar/lib/subdoc.h | 61 + xar/lib/util.c | 466 ++ xar/lib/util.h | 68 + xar/lib/zxar.c | 263 + xar/lib/zxar.h | 46 + xar/src/.cvsignore | 4 + xar/src/Makefile.inc | 65 + xar/src/Makefile.inc.in | 65 + xar/src/xar.1 | 158 + xar/src/xar.c | 1240 ++++ xar/test/attr.py | 139 + xar/test/buffer.c | 79 + xar/test/checksums.py | 225 + xar/test/compression.py | 74 + xar/test/data.py | 103 + xar/test/data.xsl | 8 + xar/test/hardlink.py | 69 + xar/test/heap.py | 78 + xar/test/heap1.xsl | 15 + xar/test/integrity.py | 88 + xar/test/util.py | 145 + xar/test/validate.c | 159 + xar/xar.spec | 98 + xar/xar.spec.in | 98 + xarsig/xar-sig.c | 1552 ++++ 107 files changed, 34227 insertions(+) create mode 100644 CMakeLists.txt create mode 100644 README create mode 100644 Revision.plist create mode 100644 patches/appleadditions.diff create mode 100644 patches/context.diff create mode 100644 patches/hash.diff create mode 100644 patches/noea.diff create mode 100644 patches/static-lib.diff create mode 100644 test_tools/xar.tcl create mode 100644 xar.plist create mode 100644 xar.txt create mode 100644 xar.xcconfig create mode 100644 xar.xcodeproj/project.pbxproj create mode 100644 xar.xcodeproj/project.xcworkspace/contents.xcworkspacedata create mode 100644 xar/.cvsignore create mode 100644 xar/ChangeLog create mode 100644 xar/INSTALL create mode 100644 xar/LICENSE create mode 100644 xar/Makefile.in create mode 100644 xar/TODO create mode 100644 xar/autogen.sh create mode 100644 xar/cfghdrs.stamp create mode 100644 xar/cfghdrs.stamp.in create mode 100644 xar/cfgoutputs.stamp create mode 100644 xar/cfgoutputs.stamp.in create mode 100644 xar/config.guess create mode 100755 xar/config.status create mode 100644 xar/config.sub create mode 100755 xar/configure create mode 100644 xar/configure.ac create mode 100644 xar/include/.cvsignore create mode 100644 xar/include/config.h create mode 100644 xar/include/config.h.in create mode 100644 xar/include/xar.h create mode 100644 xar/include/xar.h.in create mode 100644 xar/install-sh create mode 100644 xar/lib/.cvsignore create mode 100644 xar/lib/Makefile.inc create mode 100644 xar/lib/Makefile.inc.in create mode 100644 xar/lib/appledouble.h create mode 100644 xar/lib/archive.c create mode 100644 xar/lib/archive.h create mode 100644 xar/lib/arcmod.c create mode 100644 xar/lib/arcmod.h create mode 100644 xar/lib/asprintf.h create mode 100644 xar/lib/b64.c create mode 100644 xar/lib/b64.h create mode 100644 xar/lib/bzxar.c create mode 100644 xar/lib/bzxar.h create mode 100644 xar/lib/darwinattr.c create mode 100644 xar/lib/darwinattr.h create mode 100644 xar/lib/data.c create mode 100644 xar/lib/data.h create mode 100644 xar/lib/ea.c create mode 100644 xar/lib/ea.h create mode 100644 xar/lib/err.c create mode 100644 xar/lib/ext2.c create mode 100644 xar/lib/ext2.h create mode 100644 xar/lib/fbsdattr.c create mode 100644 xar/lib/fbsdattr.h create mode 100644 xar/lib/filetree.c create mode 100644 xar/lib/filetree.h create mode 100644 xar/lib/hash.c create mode 100644 xar/lib/hash.h create mode 100644 xar/lib/io.c create mode 100644 xar/lib/io.h create mode 100644 xar/lib/libxar.la.in create mode 100644 xar/lib/libxar.la.in.in create mode 100644 xar/lib/linuxattr.c create mode 100644 xar/lib/linuxattr.h create mode 100644 xar/lib/lzmaxar.c create mode 100644 xar/lib/lzmaxar.h create mode 100644 xar/lib/macho.c create mode 100644 xar/lib/macho.h create mode 100644 xar/lib/script.c create mode 100644 xar/lib/script.h create mode 100644 xar/lib/signature.c create mode 100644 xar/lib/signature.h create mode 100644 xar/lib/stat.c create mode 100644 xar/lib/stat.h create mode 100644 xar/lib/strmode.h create mode 100644 xar/lib/subdoc.c create mode 100644 xar/lib/subdoc.h create mode 100644 xar/lib/util.c create mode 100644 xar/lib/util.h create mode 100644 xar/lib/zxar.c create mode 100644 xar/lib/zxar.h create mode 100644 xar/src/.cvsignore create mode 100644 xar/src/Makefile.inc create mode 100644 xar/src/Makefile.inc.in create mode 100644 xar/src/xar.1 create mode 100644 xar/src/xar.c create mode 100644 xar/test/attr.py create mode 100644 xar/test/buffer.c create mode 100644 xar/test/checksums.py create mode 100644 xar/test/compression.py create mode 100644 xar/test/data.py create mode 100644 xar/test/data.xsl create mode 100644 xar/test/hardlink.py create mode 100644 xar/test/heap.py create mode 100644 xar/test/heap1.xsl create mode 100644 xar/test/integrity.py create mode 100644 xar/test/util.py create mode 100644 xar/test/validate.c create mode 100644 xar/xar.spec create mode 100644 xar/xar.spec.in create mode 100644 xarsig/xar-sig.c diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..7c39423 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,55 @@ +project(libxar) + +cmake_minimum_required(VERSION 3.10) + +if(COMMAND cmake_policy) + cmake_policy(SET CMP0003 NEW) +endif(COMMAND cmake_policy) + +set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -nostdinc -D__DARWIN_UNIX03 -fPIC -w") +set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -nostdlib") +include_directories( + ${CMAKE_CURRENT_SOURCE_DIR}/xar/include + ${CMAKE_CURRENT_SOURCE_DIR}/xar/lib +) + +set(xar_SRCS + xar/lib/archive.c + xar/lib/arcmod.c + xar/lib/b64.c + xar/lib/bzxar.c + xar/lib/darwinattr.c + xar/lib/data.c + xar/lib/ea.c + xar/lib/err.c + xar/lib/ext2.c + xar/lib/fbsdattr.c + xar/lib/filetree.c + xar/lib/hash.c + xar/lib/io.c + xar/lib/linuxattr.c + xar/lib/lzmaxar.c + xar/lib/script.c + xar/lib/signature.c + xar/lib/stat.c + xar/lib/subdoc.c + xar/lib/util.c + xar/lib/zxar.c +) + +set(DYLIB_INSTALL_NAME "/usr/lib/libxar.1.dylib") +set(DYLIB_COMPAT_VERSION "1.0.0") +set(DYLIB_CURRENT_VERSION "1.0.0") +add_darling_library(xar SHARED ${xar_SRCS}) +set_target_properties(xar PROPERTIES OUTPUT_NAME "xar.1") +target_link_libraries(xar system z bz2 xml2) +make_fat(xar) + +add_darling_executable(xarexe xar/src/xar.c) +set_target_properties(xarexe PROPERTIES OUTPUT_NAME "xar") +target_link_libraries(xarexe system xar) + +install(TARGETS xar DESTINATION libexec/darling/usr/lib) +install(TARGETS xarexe DESTINATION libexec/darling/usr/bin) +install(FILES xar/src/xar.1 DESTINATION libexec/darling/usr/share/man/man1) +InstallSymlink("libxar.1.dylib" "${CMAKE_INSTALL_PREFIX}/libexec/darling/usr/lib/libxar.dylib") diff --git a/README b/README new file mode 100644 index 0000000..e8b5114 --- /dev/null +++ b/README @@ -0,0 +1,11 @@ +######################################################################################### +# Project Created by Christopher Ryan (ryanc@apple.com) # +# Sources based on tot as of 7/12/06 # +# cvs -d :pserver:anonymous@anoncvs.opendarwin.org:/Volumes/src/cvs/od co -P xar # +# # +# Patched folder, included in the project contain some # +# patches on the original project xar-1.4.tar.gz. This # +# project was created because creating changes ontop of # +# the original open source project has become a serious # +# hassle. # +######################################################################################### diff --git a/Revision.plist b/Revision.plist new file mode 100644 index 0000000000000000000000000000000000000000..3a676f8488c8f3750a5318476294dde4eb44a730 GIT binary patch literal 59 ucmYc)$jK}&F)+Bu$P`hOT9#RynV%PIXkp61Ey4f>jEoSPff-7}Cheap_len += 20; + + xar_opt_set(ret, XAR_OPT_COMPRESSION, XAR_OPT_VAL_GZIP); ++ xar_opt_set(ret, XAR_OPT_FILECKSUM, XAR_OPT_VAL_SHA1); + } else { + unsigned char toccksum[EVP_MAX_MD_SIZE]; + unsigned char cval[EVP_MAX_MD_SIZE]; +@@ -455,6 +456,7 @@ + + if( XAR(x)->docksum ) { + unsigned int l = r; ++ + memset(chkstr, 0, sizeof(chkstr)); + EVP_DigestFinal(&XAR(x)->toc_ctx, chkstr, &l); + r = l; +@@ -588,19 +590,25 @@ + * x: archive the file should belong to + * f: parent node, possibly NULL + * name: name of the node to add ++ * realpath: real path to item, this is used if the item being archived is to be located at a different location in the tree ++ * then it is on the real filesystem. + * Returns: newly allocated and populated node + * Summary: helper function which adds a child of f and populates + * its properties. If f is NULL, the node will be added as a top + * level node of the archive, x. + */ +-static xar_file_t xar_add_node(xar_t x, xar_file_t f, const char *name, const char *prefix, int srcpath) { ++static xar_file_t xar_add_node(xar_t x, xar_file_t f, const char *name, const char *prefix, const char *realpath, int srcpath) { + xar_file_t ret; + const char *path; + char *tmp; + char idstr[32]; + + if( !f ) { +- asprintf(&tmp, "%s%s%s", XAR(x)->path_prefix, prefix, name); ++ if( realpath ) ++ asprintf(&tmp, "%s", realpath); ++ else ++ asprintf(&tmp, "%s%s%s", XAR(x)->path_prefix, prefix, name); ++ + if( lstat(tmp, &XAR(x)->sbcache) != 0 ) { + free(tmp); + return NULL; +@@ -631,7 +639,12 @@ + } + + } +- asprintf(&tmp, "%s/%s%s", path, prefix, name); ++ ++ if( realpath ){ ++ asprintf(&tmp, "%s", realpath); ++ }else ++ asprintf(&tmp, "%s/%s%s", path, prefix, name); ++ + if( lstat(tmp, &XAR(x)->sbcache) != 0 ) { + free(tmp); + return NULL; +@@ -648,7 +661,7 @@ + + xar_prop_set(ret, "name", name); + +- if( xar_arcmod_archive(x, ret, XAR_FILE(ret)->fspath) < 0 ) { ++ if( xar_arcmod_archive(x, ret, XAR_FILE(ret)->fspath, NULL, 0) < 0 ) { + xar_file_t i; + if( f ) { + for( i = XAR_FILE(f)->children; i && (XAR_FILE(i)->next != ret); i = XAR_FILE(i)->next ); +@@ -736,9 +749,9 @@ + + /* tmp3 was not found in children of start, so we add it */ + if( tmp2 ) { +- ret = xar_add_node(x, f, tmp3, prefix, 1); ++ ret = xar_add_node(x, f, tmp3, prefix, NULL, 1); + } else { +- ret = xar_add_node(x, f, tmp3, prefix, 0); ++ ret = xar_add_node(x, f, tmp3, prefix, NULL, 0); + } + + if( !ret ) { +@@ -783,18 +796,209 @@ + return xar_add_r(x, NULL, path, ""); + } + ++/* xar_add_frombuffer ++* x: archive to add the file to ++* parent: parent node, possibly NULL ++* name: name of file ++* buffer: buffer for file contents ++* length: length of buffer ++* Returns: allocated an populated xar_file_t representing the ++* specified file. ++* Summary: Use this to add chunks of named data to a xar without ++* using the filesystem. ++*/ ++ ++xar_file_t xar_add_frombuffer(xar_t x, xar_file_t parent, const char *name, char *buffer, size_t length) { ++ xar_file_t ret; ++ char *tmp; ++ char idstr[32]; ++ ++ if( !parent ) { ++ ret = xar_file_new(NULL); ++ if( !ret ) ++ return NULL; ++ memset(idstr, 0, sizeof(idstr)); ++ snprintf(idstr, sizeof(idstr)-1, "%"PRIu64, ++XAR(x)->last_fileid); ++ xar_attr_set(ret, NULL, "id", idstr); ++ XAR_FILE(ret)->parent = NULL; ++ if( XAR(x)->files == NULL ) ++ XAR(x)->files = ret; ++ else { ++ XAR_FILE(ret)->next = XAR(x)->files; ++ XAR(x)->files = ret; ++ } ++ } else { ++ ret = xar_file_new(parent); ++ if( !ret ) ++ return NULL; ++ memset(idstr, 0, sizeof(idstr)); ++ snprintf(idstr, sizeof(idstr)-1, "%"PRIu64, ++XAR(x)->last_fileid); ++ xar_attr_set(ret, NULL, "id", idstr); ++ XAR_FILE(ret)->fspath = tmp; ++ } ++ ++ xar_prop_set(ret, "name", name); ++ ++ //int32_t xar_arcmod_archive(xar_t x, xar_file_t f, const char *file, const char *buffer, size_t len) ++ if( xar_arcmod_archive(x, ret, NULL , buffer , length) < 0 ) { ++ xar_file_t i; ++ if( parent ) { ++ for( i = XAR_FILE(parent)->children; i && (XAR_FILE(i)->next != ret); i = XAR_FILE(i)->next ); ++ } else { ++ for( i = XAR(x)->files; i && (XAR_FILE(i)->next != ret); i = XAR_FILE(i)->next ); ++ } ++ if( i ) ++ XAR_FILE(i)->next = XAR_FILE(ret)->next; ++ xar_file_free(ret); ++ return NULL; ++ } ++ ++ return ret; ++} ++ ++xar_file_t xar_add_folder(xar_t x, xar_file_t f, const char *name, struct stat *info) ++{ ++ xar_file_t ret; ++ char idstr[32]; ++ ++ if( info ) ++ memcpy(&XAR(x)->sbcache,info,sizeof(struct stat)); ++ ++ ret = xar_file_new(f); ++ if( !ret ) ++ return NULL; ++ ++ memset(idstr, 0, sizeof(idstr)); ++ snprintf(idstr, sizeof(idstr)-1, "%"PRIu64, ++XAR(x)->last_fileid); ++ xar_attr_set(ret, NULL, "id", idstr); ++ XAR_FILE(ret)->fspath = NULL; ++ ++ if( !f ) { ++ XAR_FILE(ret)->parent = NULL; ++ ++ if( XAR(x)->files == NULL ) ++ XAR(x)->files = ret; ++ else { ++ XAR_FILE(ret)->next = XAR(x)->files; ++ XAR(x)->files = ret; ++ } ++ } ++ ++ xar_prop_set(ret, "name", name); ++ ++ if( xar_arcmod_archive(x, ret, XAR_FILE(ret)->fspath, NULL, 0) < 0 ) { ++ xar_file_t i; ++ if( f ) { ++ for( i = XAR_FILE(f)->children; i && (XAR_FILE(i)->next != ret); i = XAR_FILE(i)->next ); ++ } else { ++ for( i = XAR(x)->files; i && (XAR_FILE(i)->next != ret); i = XAR_FILE(i)->next ); ++ } ++ if( i ) ++ XAR_FILE(i)->next = XAR_FILE(ret)->next; ++ xar_file_free(ret); ++ return NULL; ++ } ++ ++ return ret; ++} ++ ++xar_file_t xar_add_frompath(xar_t x, xar_file_t parent, const char *name, const char *realpath) ++{ ++ return xar_add_node(x, parent, name , "" , realpath, 1); ++} ++ ++xar_file_t xar_add_from_archive(xar_t x, xar_file_t parent, const char *name, xar_t sourcearchive, xar_file_t sourcefile) ++{ ++ xar_file_t ret; ++ char idstr[32]; ++ ++ ret = xar_file_replicate(sourcefile, parent); ++ ++ if( !ret ) ++ return NULL; ++ ++ memset(idstr, 0, sizeof(idstr)); ++ snprintf(idstr, sizeof(idstr)-1, "%"PRIu64, ++XAR(x)->last_fileid); ++ xar_attr_set(ret, NULL, "id", idstr); ++ XAR_FILE(ret)->fspath = NULL; ++ ++ if( !parent ) { ++ XAR_FILE(ret)->parent = NULL; ++ ++ if( XAR(x)->files == NULL ) ++ XAR(x)->files = ret; ++ else { ++ XAR_FILE(ret)->next = XAR(x)->files; ++ XAR(x)->files = ret; ++ } ++ } ++ ++ xar_prop_set(ret, "name", name); ++ ++ /* iterate through all the properties, see if any of them have an offset */ ++ xar_iter_t iter = xar_iter_new(); ++ const char *attr = xar_prop_first(ret , iter); ++ char *tmpstr = NULL; ++ ++ do{ ++ asprintf(&tmpstr, "%s/offset", attr); ++ if(0 == xar_prop_get(ret, tmpstr, NULL) ){ ++ if( 0 != xar_attrcopy_from_heap_to_heap(sourcearchive, sourcefile, attr, x, ret)){ ++ xar_file_free(ret); ++ ret = NULL; ++ break; ++ } ++ } ++ free(tmpstr); ++ ++ }while( (attr = xar_prop_next(iter)) ); ++ ++ xar_iter_free(iter); ++ ++ return ret; ++} ++ + /* xar_extract_tofile +- * x: archive to extract from +- * f: file associated with x +- * Returns 0 on success, -1 on failure +- * Summary: This actually does the file extraction. +- * No traversal is performed, it is assumed all directory paths +- * leading up to f already exist. +- */ ++* x: archive to extract from ++* f: file associated with x ++* Returns 0 on success, -1 on failure ++* Summary: This actually does the file extraction. ++* No traversal is performed, it is assumed all directory paths ++* leading up to f already exist. ++*/ + int32_t xar_extract_tofile(xar_t x, xar_file_t f, const char *path) { +- return xar_arcmod_extract(x, f, path); ++ return xar_arcmod_extract(x, f, path,NULL, 0); + } + ++ ++/* xar_extract_tobuffer ++* x: archive to extract from ++* buffer: buffer to extract to ++* Returns 0 on success, -1 on failure. ++* Summary: This is the entry point for extraction to a buffer. ++* On success, a buffer is allocated with the contents of the file ++* specified. The caller is responsible for freeing the returend buffer. ++* Example: xar_extract_tobuffer(x, "foo/bar/blah",&buffer) ++*/ ++int32_t xar_extract_tobuffer(xar_t x, xar_file_t f, char **buffer) { ++ size_t size; ++ const char *sizestring = NULL; ++ ++ if(0 != xar_prop_get(f,"data/size",&sizestring)){ ++ return -1; ++ } ++ ++ size = strtoull(sizestring, (char **)NULL, 10); ++ *buffer = malloc(size); ++ ++ if(!(*buffer)){ ++ return -1; ++ } ++ ++ return xar_arcmod_extract(x,f,NULL,*buffer,size); ++} ++ ++ + /* xar_extract + * x: archive to extract from + * path: path to file to extract +@@ -828,6 +1032,18 @@ + return xar_extract_tofile(x, f, XAR_FILE(f)->fspath); + } + ++/* xar_extract ++* x: archive to extract from ++* f: file to verify ++* Returns 0 on success, -1 on failure. ++* Summary: This function allows for verification of ++* an entry without extraction. If there is no checksum ++* the verification will pass. ++*/ ++int32_t xar_verify(xar_t x, xar_file_t f) { ++ return xar_arcmod_verify(x,f); ++} ++ + /* read_callback + * context: context passed through from the reader + * buffer: buffer to read into +diff -urN xar.hash/lib/archive.h xar.final/lib/archive.h +--- xar.hash/lib/archive.h 2006-03-17 11:19:16.000000000 -0800 ++++ xar.final/lib/archive.h 2006-03-17 10:35:14.000000000 -0800 +@@ -55,28 +55,28 @@ + const char *ns; + const char *filler1; + const char *filler2; +- xar_file_t files; /* file forest */ +- const char *filename; /* name of the archive we are operating on */ +- char *dirname; /* directory of the archive, used in creation */ +- int fd; /* open file descriptor for the archive */ +- int heap_fd; /* fd for tmp heap archive, used in creation */ +- off_t heap_offset; /* current offset within the heap */ +- off_t heap_len; /* current length of the heap */ +- xar_header_t header; /* header of the xar archive */ +- void *readbuf; /* buffer for reading/writing compressed toc */ +- size_t readbuf_len; /* length of readbuf */ +- size_t offset; /* offset into readbuf for keeping track +- * between callbacks. */ +- size_t toc_count; /* current bytes read of the toc */ +- z_stream zs; /* gz state for compressing/decompressing toc */ +- char *path_prefix; /* used for distinguishing absolute paths */ +- err_handler ercallback; /* callback for errors/warnings */ +- struct errctx errctx; /* error callback context */ +- xar_subdoc_t subdocs; /* linked list of subdocs */ +- uint64_t last_fileid; /* unique fileid's in the archive */ +- xmlHashTablePtr ino_hash;/* Hash for looking up hardlinked files (add)*/ +- xmlHashTablePtr link_hash;/* Hash for looking up hardlinked files (extract)*/ +- xmlHashTablePtr csum_hash;/* Hash for looking up checksums of files */ ++ xar_file_t files; /* file forest */ ++ const char *filename; /* name of the archive we are operating on */ ++ char *dirname; /* directory of the archive, used in creation */ ++ int fd; /* open file descriptor for the archive */ ++ int heap_fd; /* fd for tmp heap archive, used in creation */ ++ off_t heap_offset; /* current offset within the heap */ ++ off_t heap_len; /* current length of the heap */ ++ xar_header_t header; /* header of the xar archive */ ++ void *readbuf; /* buffer for reading/writing compressed toc */ ++ size_t readbuf_len; /* length of readbuf */ ++ size_t offset; /* offset into readbuf for keeping track ++ * between callbacks. */ ++ size_t toc_count; /* current bytes read of the toc */ ++ z_stream zs; /* gz state for compressing/decompressing toc */ ++ char *path_prefix; /* used for distinguishing absolute paths */ ++ err_handler ercallback; /* callback for errors/warnings */ ++ struct errctx errctx; /* error callback context */ ++ xar_subdoc_t subdocs; /* linked list of subdocs */ ++ uint64_t last_fileid; /* unique fileid's in the archive */ ++ xmlHashTablePtr ino_hash; /* Hash for looking up hardlinked files (add)*/ ++ xmlHashTablePtr link_hash; /* Hash for looking up hardlinked files (extract)*/ ++ xmlHashTablePtr csum_hash; /* Hash for looking up checksums of files */ + EVP_MD_CTX toc_ctx; + int docksum; + int skipwarn; +diff -urN xar.hash/lib/arcmod.c xar.final/lib/arcmod.c +--- xar.hash/lib/arcmod.c 2006-03-17 11:19:16.000000000 -0800 ++++ xar.final/lib/arcmod.c 2006-03-17 10:35:14.000000000 -0800 +@@ -57,12 +57,12 @@ + * Returns: 0 on success + * Summary: This is the entry point to actual file archival. + */ +-int32_t xar_arcmod_archive(xar_t x, xar_file_t f, const char *file) { ++int32_t xar_arcmod_archive(xar_t x, xar_file_t f, const char *file, const char *buffer, size_t len) { + int i; + int32_t ret; + for(i = 0; i < (sizeof(xar_arcmods)/sizeof(struct arcmod)); i++) { + if( xar_arcmods[i].archive ) { +- ret = xar_arcmods[i].archive(x, f, file); ++ ret = xar_arcmods[i].archive(x, f, file, buffer, len); + if( ret < 0 ) { + return ret; + } +@@ -81,12 +81,12 @@ + * Returns: 0 on success + * Summary: This is the entry point to actual file archival. + */ +-int32_t xar_arcmod_extract(xar_t x, xar_file_t f, const char *file) { ++int32_t xar_arcmod_extract(xar_t x, xar_file_t f, const char *file, char *buffer, size_t len) { + int i; + int32_t ret; + for(i = 0; i < (sizeof(xar_arcmods)/sizeof(struct arcmod)); i++) { + if( xar_arcmods[i].extract ) { +- ret = xar_arcmods[i].extract(x, f, file); ++ ret = xar_arcmods[i].extract(x, f, file, buffer, len); + if( ret < 0 ) { + return ret; + } +@@ -97,3 +97,8 @@ + } + return 0; + } ++ ++ ++int32_t xar_arcmod_verify(xar_t x, xar_file_t f){ ++ return xar_data_verify(x,f); ++} +diff -urN xar.hash/lib/arcmod.h xar.final/lib/arcmod.h +--- xar.hash/lib/arcmod.h 2006-03-17 11:19:16.000000000 -0800 ++++ xar.final/lib/arcmod.h 2006-03-17 10:35:14.000000000 -0800 +@@ -37,15 +37,17 @@ + #include "filetree.h" + + +-typedef int32_t (*arcmod_archive)(xar_t x, xar_file_t f, const char* file); +-typedef int32_t (*arcmod_extract)(xar_t x, xar_file_t f, const char* file); ++typedef int32_t (*arcmod_archive)(xar_t x, xar_file_t f, const char* file, const char *buffer, size_t len); ++typedef int32_t (*arcmod_extract)(xar_t x, xar_file_t f, const char* file, char *buffer, size_t len); + + struct arcmod { + arcmod_archive archive; + arcmod_extract extract; + }; + +-int32_t xar_arcmod_archive(xar_t x, xar_file_t f, const char *file); +-int32_t xar_arcmod_extract(xar_t x, xar_file_t f, const char *file); ++int32_t xar_arcmod_archive(xar_t x, xar_file_t f, const char *file, const char *buffer, size_t len); ++int32_t xar_arcmod_extract(xar_t x, xar_file_t f, const char *file, char *buffer, size_t len); ++ ++int32_t xar_arcmod_verify(xar_t x, xar_file_t f); + + #endif /* _XAR_ARCMOD_H_ */ +diff -urN xar.hash/lib/darwinattr.c xar.final/lib/darwinattr.c +--- xar.hash/lib/darwinattr.c 2006-03-17 11:26:55.000000000 -0800 ++++ xar.final/lib/darwinattr.c 2006-03-17 10:35:14.000000000 -0800 +@@ -554,19 +554,21 @@ + + DARWINATTR_CONTEXT(context)->fd = 0; + +- xar_set_perm(x, f, underbarname ); ++ xar_set_perm(x, f, underbarname, NULL, 0 ); + + return 0; + } + + +-int32_t xar_darwinattr_archive(xar_t x, xar_file_t f, const char* file) ++int32_t xar_darwinattr_archive(xar_t x, xar_file_t f, const char* file, const char *buffer, size_t len) + { + struct _darwinattr_context context; + + memset(&context,0,sizeof(struct _darwinattr_context)); + + #if defined(__APPLE__) ++ if( len ) ++ return 0; + #if defined(HAVE_GETXATTR) + if( ea_archive(x, f, file, (void *)&context) == 0 ) + return 0; +@@ -578,13 +580,15 @@ + return 0; + } + +-int32_t xar_darwinattr_extract(xar_t x, xar_file_t f, const char* file) ++int32_t xar_darwinattr_extract(xar_t x, xar_file_t f, const char* file, char *buffer, size_t len) + { + struct _darwinattr_context context; + + memset(&context,0,sizeof(struct _darwinattr_context)); + + #if defined(__APPLE__) ++ if( len ) ++ return 0; + #if defined(HAVE_GETXATTR) + if( ea_extract(x, f, file, (void *)&context) == 0 ) + return 0; +diff -urN xar.hash/lib/darwinattr.h xar.final/lib/darwinattr.h +--- xar.hash/lib/darwinattr.h 2006-03-17 11:19:16.000000000 -0800 ++++ xar.final/lib/darwinattr.h 2006-03-17 10:35:14.000000000 -0800 +@@ -6,6 +6,6 @@ + #ifndef _XAR_DARWINATTR_H_ + #define _XAR_DARWINATTR_H_ + int32_t xar_underbar_check(xar_t x, xar_file_t f, const char* file); +-int32_t xar_darwinattr_archive(xar_t x, xar_file_t f, const char* file); +-int32_t xar_darwinattr_extract(xar_t x, xar_file_t f, const char* file); ++int32_t xar_darwinattr_archive(xar_t x, xar_file_t f, const char* file, const char *buffer, size_t len); ++int32_t xar_darwinattr_extract(xar_t x, xar_file_t f, const char* file, char *buffer, size_t len); + #endif /* _XAR_DARWINATTR_H_ */ +diff -urN xar.hash/lib/data.c xar.final/lib/data.c +--- xar.hash/lib/data.c 2006-03-17 11:19:16.000000000 -0800 ++++ xar.final/lib/data.c 2006-03-17 10:35:14.000000000 -0800 +@@ -99,7 +99,7 @@ + * This is the arcmod archival entry point for archiving the file's + * data into the heap file. + */ +-int32_t xar_data_archive(xar_t x, xar_file_t f, const char *file) { ++int32_t xar_data_archive(xar_t x, xar_file_t f, const char *file, const char *buffer, size_t len) { + const char *opt; + int32_t retval = 0; + struct _data_context context; +@@ -120,14 +120,20 @@ + return 0; + } + +- context.fd = open(file, O_RDONLY); +- if( context.fd < 0 ) { +- xar_err_new(x); +- xar_err_set_file(x, f); +- xar_err_set_string(x, "io: Could not open file"); +- xar_err_callback(x, XAR_SEVERITY_NONFATAL, XAR_ERR_ARCHIVE_CREATION); +- return -1; +- } ++ if( 0 == len ){ ++ context.fd = open(file, O_RDONLY); ++ if( context.fd < 0 ) { ++ xar_err_new(x); ++ xar_err_set_file(x, f); ++ xar_err_set_string(x, "io: Could not open file"); ++ xar_err_callback(x, XAR_SEVERITY_NONFATAL, XAR_ERR_ARCHIVE_CREATION); ++ return -1; ++ } ++ }else{ ++ context.buffer = (void *)buffer; ++ context.length = len; ++ context.offset = 0; ++ } + + retval = xar_attrcopy_to_heap(x, f, "data", xar_data_read,(void *)(&context)); + +@@ -137,7 +143,7 @@ + return retval; + } + +-int32_t xar_data_extract(xar_t x, xar_file_t f, const char *file) { ++int32_t xar_data_extract(xar_t x, xar_file_t f, const char *file, char *buffer, size_t len) { + const char *opt; + struct _data_context context; + +@@ -158,25 +164,32 @@ + return 0; + } + +- /* mode 600 since other modules may need to operate on the file +- * prior to the real permissions being set. +- */ ++ if ( len ){ ++ context.length = len; ++ context.buffer = buffer; ++ context.offset = 0; ++ }else{ ++ /* mode 600 since other modules may need to operate on the file ++ * prior to the real permissions being set. ++ */ + TRYAGAIN: +- context.fd = open(file, O_RDWR|O_TRUNC|O_EXLOCK, 0600); +- if( context.fd < 0 ) { +- if( errno == ENOENT ) { +- xar_file_t parent = XAR_FILE(f)->parent; +- if( parent && (xar_extract(x, parent) == 0) ) +- goto TRYAGAIN; ++ context.fd = open(file, O_RDWR|O_TRUNC|O_EXLOCK, 0600); ++ if( context.fd < 0 ) { ++ if( errno == ENOENT ) { ++ xar_file_t parent = XAR_FILE(f)->parent; ++ if( parent && (xar_extract(x, parent) == 0) ) ++ goto TRYAGAIN; ++ } ++ ++ xar_err_new(x); ++ xar_err_set_file(x, f); ++ xar_err_set_string(x, "io: Could not create file"); ++ xar_err_callback(x, XAR_SEVERITY_NONFATAL, XAR_ERR_ARCHIVE_EXTRACTION); ++ return -1; + } + +- xar_err_new(x); +- xar_err_set_file(x, f); +- xar_err_set_string(x, "io: Could not create file"); +- xar_err_callback(x, XAR_SEVERITY_NONFATAL, XAR_ERR_ARCHIVE_EXTRACTION); +- return -1; + } +- ++ + xar_attrcopy_from_heap(x, f, "data", xar_data_write, (void *)(&context)); + + if( context.fd > 0 ) +@@ -185,3 +198,19 @@ + return 0; + } + ++int32_t xar_data_verify(xar_t x, xar_file_t f) ++{ ++ const char *opt; ++ struct _data_context context; ++ ++ memset(&context,0,sizeof(struct _data_context)); ++ ++ /* Only regular files are copied in and out of the heap here */ ++ xar_prop_get(f, "type", &opt); ++ if( !opt ) return 0; ++ if( strcmp(opt, "directory") == 0 ) { ++ return 0; ++ } ++ ++ return xar_attrcopy_from_heap(x, f, "data", NULL , (void *)(&context)); ++} +diff -urN xar.hash/lib/data.h xar.final/lib/data.h +--- xar.hash/lib/data.h 2006-03-17 11:19:16.000000000 -0800 ++++ xar.final/lib/data.h 2006-03-17 10:35:14.000000000 -0800 +@@ -5,6 +5,8 @@ + */ + #ifndef _XAR_DATA_H_ + #define _XAR_DATA_H_ +-int32_t xar_data_archive(xar_t x, xar_file_t f, const char* file); +-int32_t xar_data_extract(xar_t x, xar_file_t f, const char* file); ++int32_t xar_data_archive(xar_t x, xar_file_t f, const char* file, const char *buffer, size_t len); ++int32_t xar_data_extract(xar_t x, xar_file_t f, const char* file, char *buffer, size_t len); ++ ++int32_t xar_data_verify(xar_t x, xar_file_t f); + #endif /* _XAR_DATA_H_ */ +diff -urN xar.hash/lib/ext2.c xar.final/lib/ext2.c +--- xar.hash/lib/ext2.c 2006-03-17 11:19:16.000000000 -0800 ++++ xar.final/lib/ext2.c 2006-03-17 10:35:14.000000000 -0800 +@@ -70,9 +70,14 @@ + } + #endif + +-int xar_ext2attr_archive(xar_t x, xar_file_t f, const char* file) ++int xar_ext2attr_archive(xar_t x, xar_file_t f, const char* file, const char *buffer, size_t len) + { + int ret = 0; ++ ++ /* if archiving from a buffer, then there is no place to get extattr */ ++ if ( len ) ++ return 0; ++ + #if defined(HAVE_EXT2FS_EXT2_FS_H) || defined(HAVE_LINUX_EXT2_FS_H) + int fd, flags=0, version; + char *vstr; +@@ -158,8 +163,12 @@ + } + #endif + +-int xar_ext2attr_extract(xar_t x, xar_file_t f, const char* file) ++int xar_ext2attr_extract(xar_t x, xar_file_t f, const char* file, char *buffer, size_t len) + { ++ /* if extracting to a buffer, then there is no place to write extattr */ ++ if ( len ) ++ return 0; ++ + #if defined(HAVE_EXT2FS_EXT2_FS_H) || defined(HAVE_LINUX_EXT2_FS_H) + int fd = -1, version, flags = 0; + char *tmp; +diff -urN xar.hash/lib/ext2.h xar.final/lib/ext2.h +--- xar.hash/lib/ext2.h 2006-03-17 11:19:16.000000000 -0800 ++++ xar.final/lib/ext2.h 2006-03-17 10:35:14.000000000 -0800 +@@ -6,6 +6,6 @@ + #ifndef _XAR_EXT2_H_ + #define _XAR_EXT2_H_ + #define XAR_ATTR_FORK "attribute" +-int xar_ext2attr_archive(xar_t x, xar_file_t f, const char* file); +-int xar_ext2attr_extract(xar_t x, xar_file_t f, const char* file); ++int xar_ext2attr_archive(xar_t x, xar_file_t f, const char* file, const char *buffer, size_t len); ++int xar_ext2attr_extract(xar_t x, xar_file_t f, const char* file, char *buffer, size_t len); + #endif /* _XAR_EXT2_H_ */ +diff -urN xar.hash/lib/fbsdattr.c xar.final/lib/fbsdattr.c +--- xar.hash/lib/fbsdattr.c 2006-03-17 11:19:16.000000000 -0800 ++++ xar.final/lib/fbsdattr.c 2006-03-17 10:54:53.000000000 -0800 +@@ -99,7 +99,7 @@ + } + #endif + +-int32_t xar_fbsdattr_archive(xar_t x, xar_file_t f, const char* file) ++int32_t xar_fbsdattr_archive(xar_t x, xar_file_t f, const char* file, const char *buffer, size_t len) + { + #ifdef HAVE_SYS_EXTATTR_H + char *buf = NULL; +@@ -110,6 +110,11 @@ + struct _fbsdattr_context context; + + memset(&context,0,sizeof(struct _fbsdattr_context)); ++ ++ /* no fbsdattr attributes for data to a buffer */ ++ if(len){ ++ return 0; ++ } + + TRYAGAIN: + /* extattr_list_link()'s man page does not define the return +@@ -218,7 +223,12 @@ + struct _fbsdattr_context context; + + memset(&context,0,sizeof(struct _fbsdattr_context)); +- ++ ++ /* no fbsdattr attributes for data to a buffer */ ++ if(len){ ++ return 0; ++ } ++ + statfs(file, &sfs); + fsname = sfs.f_fstypename; + +diff -urN xar.hash/lib/fbsdattr.h xar.final/lib/fbsdattr.h +--- xar.hash/lib/fbsdattr.h 2006-03-17 11:19:16.000000000 -0800 ++++ xar.final/lib/fbsdattr.h 2006-03-17 10:35:14.000000000 -0800 +@@ -5,6 +5,6 @@ + */ + #ifndef _XAR_FBSDATTR_H_ + #define _XAR_FBSDATTR_H_ +-int32_t xar_fbsdattr_archive(xar_t x, xar_file_t f, const char* file); +-int32_t xar_fbsdattr_extract(xar_t x, xar_file_t f, const char* file); ++int32_t xar_fbsdattr_archive(xar_t x, xar_file_t f, const char* file, const char *buffer, size_t len); ++int32_t xar_fbsdattr_extract(xar_t x, xar_file_t f, const char* file, char *buffer, size_t len); + #endif /* _XAR_FBSDATTR_H_ */ +diff -urN xar.hash/lib/filetree.c xar.final/lib/filetree.c +--- xar.hash/lib/filetree.c 2006-03-17 11:19:16.000000000 -0800 ++++ xar.final/lib/filetree.c 2006-03-17 10:35:14.000000000 -0800 +@@ -545,6 +545,51 @@ + return 0; + } + ++/* xar_prop_replicate_r ++* f: file to attach property ++* p: property (list) to iterate and add ++* parent: parent property ++* Summary: Recursivley adds property list (p) to file (f) and parent (parent). ++*/ ++ ++void xar_prop_replicate_r(xar_file_t f, xar_prop_t p, xar_prop_t parent ) ++{ ++ xar_prop_t property = p; ++ ++ /* look through properties */ ++ for( property = p; property; property = property->next ){ ++ xar_prop_t newprop = xar_prop_new( f, parent ); ++ ++ /* copy the key value for the property */ ++ XAR_PROP(newprop)->key = strdup(property->key); ++ if(property->value) ++ XAR_PROP(newprop)->value = strdup(property->value); ++ ++ /* loop through the attributes and copy them */ ++ xar_attr_t a = NULL; ++ xar_attr_t last = NULL; ++ ++ /* copy attributes for file */ ++ for(a = property->attrs; a; a = a->next) { ++ if( NULL == newprop->attrs ){ ++ last = xar_attr_new(); ++ XAR_PROP(newprop)->attrs = last; ++ }else{ ++ XAR_ATTR(last)->next = xar_attr_new(); ++ last = XAR_ATTR(last)->next; ++ } ++ ++ XAR_ATTR(last)->key = strdup(a->key); ++ if(a->value) ++ XAR_ATTR(last)->value = strdup(a->value); ++ } ++ ++ /* loop through the children properties and recursively add them */ ++ xar_prop_replicate_r(f, property->children, newprop ); ++ } ++ ++} ++ + /* xar_prop_free + * p: property to free + * Summary: frees the specified property and all its children. +@@ -621,6 +666,26 @@ + return ret; + } + ++xar_file_t xar_file_replicate(xar_file_t original, xar_file_t newparent) ++{ ++ xar_file_t ret = xar_file_new(newparent); ++ xar_attr_t a; ++ ++ /* copy attributes for file */ ++ for(a = XAR_FILE(original)->attrs; a; a = XAR_ATTR(a)->next) { ++ /* skip the id attribute */ ++ if( 0 == strcmp(a->key, "id" ) ) ++ continue; ++ ++ xar_attr_set(ret, NULL , a->key, a->value ); ++ } ++ ++ /* recursively copy properties */ ++ xar_prop_replicate_r(ret, XAR_FILE(original)->props, NULL); ++ ++ return ret; ++} ++ + /* xar_file_free + * f: file to free + * Summary: frees the specified file and all children, +diff -urN xar.hash/lib/filetree.h xar.final/lib/filetree.h +--- xar.hash/lib/filetree.h 2006-03-17 11:19:16.000000000 -0800 ++++ xar.final/lib/filetree.h 2006-03-17 10:35:14.000000000 -0800 +@@ -82,6 +82,7 @@ + xar_file_t xar_file_unserialize(xar_t x, xar_file_t parent, xmlTextReaderPtr reader); + xar_file_t xar_file_find(xar_file_t f, const char *path); + xar_file_t xar_file_new(xar_file_t f); ++xar_file_t xar_file_replicate(xar_file_t original, xar_file_t newparent); + void xar_file_free(xar_file_t f); + + void xar_prop_serialize(xar_prop_t p, xmlTextWriterPtr writer); +diff -urN xar.hash/lib/io.c xar.final/lib/io.c +--- xar.hash/lib/io.c 2006-03-17 11:20:06.000000000 -0800 ++++ xar.final/lib/io.c 2006-03-17 10:35:14.000000000 -0800 +@@ -415,6 +415,140 @@ + return 0; + } + ++/* xar_attrcopy_from_heap_to_heap ++* This does a simple copy of the heap data from one head (read-only) to another heap (write only). ++* This does not set any properties or attributes of the file, so this should not be used alone. ++*/ ++int32_t xar_attrcopy_from_heap_to_heap(xar_t xsource, xar_file_t fsource, const char *attr, xar_t xdest, xar_file_t fdest){ ++ int r, off; ++ size_t bsize; ++ int64_t fsize, inc = 0, seekoff, writesize=0; ++ off_t orig_heap_offset = XAR(xdest)->heap_offset; ++ void *inbuf; ++ const char *opt; ++ char *tmpstr = NULL, *tmpstr2 = NULL; ++ ++ opt = xar_opt_get(xsource, "rsize"); ++ if( !opt ) { ++ bsize = 4096; ++ } else { ++ bsize = strtol(opt, NULL, 0); ++ if( ((bsize == LONG_MAX) || (bsize == LONG_MIN)) && (errno == ERANGE) ) { ++ bsize = 4096; ++ } ++ } ++ ++ asprintf(&tmpstr, "%s/offset", attr); ++ xar_prop_get(fsource, tmpstr, &opt); ++ free(tmpstr); ++ ++ seekoff = strtoll(opt, NULL, 0); ++ ++ if( ((seekoff == LLONG_MAX) || (seekoff == LLONG_MIN)) && (errno == ERANGE) ) { ++ return -1; ++ } ++ ++ seekoff += XAR(xsource)->toc_count + sizeof(xar_header_t); ++ ++ if( XAR(xsource)->fd > 1 ) { ++ r = lseek(XAR(xsource)->fd, seekoff, SEEK_SET); ++ if( r == -1 ) { ++ if( errno == ESPIPE ) { ++ ssize_t rr; ++ char *buf; ++ unsigned int len; ++ ++ len = seekoff - XAR(xsource)->toc_count; ++ len -= sizeof(xar_header_t); ++ if( XAR(xsource)->heap_offset > len ) { ++ xar_err_new(xsource); ++ xar_err_set_file(xsource, fsource); ++ xar_err_set_string(xsource, "Unable to seek"); ++ xar_err_callback(xsource, XAR_SEVERITY_NONFATAL, XAR_ERR_ARCHIVE_EXTRACTION); ++ } else { ++ len -= XAR(xsource)->heap_offset; ++ buf = malloc(len); ++ assert(buf); ++ rr = read(XAR(xsource)->fd, buf, len); ++ if( rr < len ) { ++ xar_err_new(xsource); ++ xar_err_set_file(xsource, fsource); ++ xar_err_set_string(xsource, "Unable to seek"); ++ xar_err_callback(xsource, XAR_SEVERITY_NONFATAL, XAR_ERR_ARCHIVE_EXTRACTION); ++ } ++ free(buf); ++ } ++ } else { ++ xar_err_new(xsource); ++ xar_err_set_file(xsource, fsource); ++ xar_err_set_string(xsource, "Unable to seek"); ++ xar_err_callback(xsource, XAR_SEVERITY_NONFATAL, XAR_ERR_ARCHIVE_EXTRACTION); ++ } ++ } ++ } ++ ++ asprintf(&tmpstr, "%s/length", attr); ++ xar_prop_get(fsource, tmpstr, &opt); ++ free(tmpstr); ++ if( !opt ) { ++ return 0; ++ } else { ++ fsize = strtoll(opt, NULL, 10); ++ if( ((fsize == LLONG_MAX) || (fsize == LLONG_MIN)) && (errno == ERANGE) ) { ++ return -1; ++ } ++ } ++ ++ inbuf = malloc(bsize); ++ if( !inbuf ) { ++ return -1; ++ } ++ ++ ++ while(1) { ++ /* Size has been reached */ ++ if( fsize == inc ) ++ break; ++ if( (fsize - inc) < bsize ) ++ bsize = fsize - inc; ++ r = read(XAR(xsource)->fd, inbuf, bsize); ++ if( r == 0 ) ++ break; ++ if( (r < 0) && (errno == EINTR) ) ++ continue; ++ if( r < 0 ) { ++ free(inbuf); ++ return -1; ++ } ++ ++ XAR(xsource)->heap_offset += r; ++ inc += r; ++ bsize = r; ++ ++ off = 0; ++ ++ do { ++ r = write(XAR(xdest)->heap_fd, inbuf+off, r-off ); ++ off += r; ++ writesize += r; ++ } while( off < r ); ++ XAR(xdest)->heap_offset += off; ++ XAR(xdest)->heap_len += off; ++ } ++ ++ asprintf(&tmpstr, "%"PRIu64, (uint64_t)orig_heap_offset); ++ asprintf(&tmpstr2, "%s/offset", attr); ++ xar_prop_set(fdest, tmpstr2, tmpstr); ++ free(tmpstr); ++ free(tmpstr2); ++ ++ ++ free(inbuf); ++ ++ /* It is the caller's responsibility to copy the attributes of the file, etc, this only copies the data in the heap */ ++ ++ return 0; ++} + /* xar_heap_to_archive + * x: archive to operate on + * Returns 0 on success, -1 on error +diff -urN xar.hash/lib/io.h xar.final/lib/io.h +--- xar.hash/lib/io.h 2006-03-17 11:19:16.000000000 -0800 ++++ xar.final/lib/io.h 2006-03-17 10:35:14.000000000 -0800 +@@ -56,6 +56,7 @@ + + int32_t xar_attrcopy_to_heap(xar_t x, xar_file_t f, const char *attr, read_callback rcb, void *context); + int32_t xar_attrcopy_from_heap(xar_t x, xar_file_t f, const char *attr, write_callback wcb, void *context); ++int32_t xar_attrcopy_from_heap_to_heap(xar_t xsource, xar_file_t fsource, const char *attr, xar_t xdest, xar_file_t fdest); + int32_t xar_heap_to_archive(xar_t x); + + #endif /* _XAR_IO_H_ */ +diff -urN xar.hash/lib/linuxattr.c xar.final/lib/linuxattr.c +--- xar.hash/lib/linuxattr.c 2006-03-17 11:19:16.000000000 -0800 ++++ xar.final/lib/linuxattr.c 2006-03-17 13:38:53.000000000 -0800 +@@ -128,7 +128,7 @@ + } + #endif + +-int32_t xar_linuxattr_archive(xar_t x, xar_file_t f, const char* file) ++int32_t xar_linuxattr_archive(xar_t x, xar_file_t f, const char* file, const char *buffer, size_t len) + { + #if defined(HAVE_SYS_XATTR_H) && defined(HAVE_LGETXATTR) && !defined(__APPLE__) + char *i, *buf = NULL; +@@ -139,6 +139,11 @@ + + memset(&context,0,sizeof(struct _linuxattr_context)); + ++ /* data from buffers don't have linuxattr */ ++ if(len){ ++ return 0; ++ } ++ + TRYAGAIN: + buf = malloc(bufsz); + if(!buf) +@@ -188,7 +193,7 @@ + return 0; + } + +-int32_t xar_linuxattr_extract(xar_t x, xar_file_t f, const char* file) ++int32_t xar_linuxattr_extract(xar_t x, xar_file_t f, const char* file, char *buffer, size_t len) + { + #if defined HAVE_SYS_XATTR_H && defined(HAVE_LSETXATTR) && !defined(__APPLE__) + const char *fsname = "bogus"; +@@ -200,6 +205,11 @@ + + memset(&context,0,sizeof(struct _linuxattr_context)); + ++ /* data buffers, can't store linux attrs */ ++ if(len){ ++ return 0; ++ } ++ + /* Check for EA extraction behavior */ + + memset(&sfs, 0, sizeof(sfs)); +diff -urN xar.hash/lib/linuxattr.h xar.final/lib/linuxattr.h +--- xar.hash/lib/linuxattr.h 2006-03-17 11:19:16.000000000 -0800 ++++ xar.final/lib/linuxattr.h 2006-03-17 13:38:55.000000000 -0800 +@@ -5,6 +5,6 @@ + */ + #ifndef _XAR_LINUXATTR_H_ + #define _XAR_LINUXATTR_H_ +-int32_t xar_linuxattr_archive(xar_t x, xar_file_t f, const char* file); +-int32_t xar_linuxattr_extract(xar_t x, xar_file_t f, const char* file); ++int32_t xar_linuxattr_archive(xar_t x, xar_file_t f, const char* file, const char *buffer, size_t len); ++int32_t xar_linuxattr_extract(xar_t x, xar_file_t f, const char* file, char *buffer, size_t len); + #endif /* _XAR_LINUXATTR_H_ */ +diff -urN xar.hash/lib/stat.c xar.final/lib/stat.c +--- xar.hash/lib/stat.c 2006-03-17 11:19:16.000000000 -0800 ++++ xar.final/lib/stat.c 2006-03-17 10:35:14.000000000 -0800 +@@ -214,7 +214,7 @@ + return 0; + } + +-int32_t xar_stat_archive(xar_t x, xar_file_t f, const char *file) { ++int32_t xar_stat_archive(xar_t x, xar_file_t f, const char *file, const char *buffer, size_t len) { + char *tmpstr; + struct passwd *pw; + struct group *gr; +@@ -222,6 +222,12 @@ + struct tm t; + const char *type; + ++ /* no stat attributes for data from a buffer, it is just a file */ ++ if(len){ ++ xar_prop_set(f, "type", "file"); ++ return 0; ++ } ++ + if( S_ISREG(XAR(x)->sbcache.st_mode) && (XAR(x)->sbcache.st_nlink > 1) ) { + xar_file_t tmpf; + const char *id = xar_attr_get(f, NULL, "id"); +@@ -304,7 +310,7 @@ + return 0; + } + +-int32_t xar_set_perm(xar_t x, xar_file_t f, const char *file) { ++int32_t xar_set_perm(xar_t x, xar_file_t f, const char *file, char *buffer, size_t len) { + const char *opt; + int32_t m=0, mset=0; + uid_t u; +@@ -314,6 +320,10 @@ + enum {ATIME=0, MTIME}; + struct timeval tv[2]; + ++ /* when writing to a buffer, there are no permissions to set */ ++ if ( len ) ++ return 0; ++ + /* in case we don't find anything useful in the archive */ + u = geteuid(); + g = getegid(); +@@ -433,7 +443,7 @@ + return 0; + } + +-int32_t xar_stat_extract(xar_t x, xar_file_t f, const char *file) { ++int32_t xar_stat_extract(xar_t x, xar_file_t f, const char *file, char *buffer, size_t len) { + const char *opt; + int ret, fd; + +diff -urN xar.hash/lib/stat.h xar.final/lib/stat.h +--- xar.hash/lib/stat.h 2006-03-17 11:19:16.000000000 -0800 ++++ xar.final/lib/stat.h 2006-03-17 10:35:14.000000000 -0800 +@@ -36,8 +36,8 @@ + + #include "xar.h" + +-int32_t xar_stat_archive(xar_t x, xar_file_t f, const char *file); +-int32_t xar_stat_extract(xar_t x, xar_file_t f, const char *file); +-int32_t xar_set_perm(xar_t x, xar_file_t f, const char *file); ++int32_t xar_stat_archive(xar_t x, xar_file_t f, const char *file, const char *buffer, size_t len); ++int32_t xar_stat_extract(xar_t x, xar_file_t f, const char *file, char *buffer, size_t len); ++int32_t xar_set_perm(xar_t x, xar_file_t f, const char *file, char *buffer, size_t len); + + #endif /* _XAR_STAT_H_ */ +diff -urN xar.hash/lib/util.c xar.final/lib/util.c +--- xar.hash/lib/util.c 2006-03-17 11:19:16.000000000 -0800 ++++ xar.final/lib/util.c 2006-03-17 10:35:14.000000000 -0800 +@@ -30,6 +30,7 @@ + * 03-Apr-2005 + * DRI: Rob Braun + */ ++ + #include + #include + #include +@@ -42,6 +43,7 @@ + #include "asprintf.h" + #endif + #include "xar.h" ++#include "archive.h" + #include "filetree.h" + + uint64_t xar_ntoh64(uint64_t num) { +@@ -97,6 +99,10 @@ + return ret; + } + ++off_t xar_get_heap_offset(xar_t x) { ++ return XAR(x)->toc_count + sizeof(xar_header_t); ++} ++ + /* xar_read_fd + * Summary: Reads from a file descriptor a certain number of bytes to a specific + * buffer. This simple wrapper just handles certain retryable error situations. +diff -urN xar.hash/lib/util.h xar.final/lib/util.h +--- xar.hash/lib/util.h 2006-03-17 11:19:16.000000000 -0800 ++++ xar.final/lib/util.h 2006-03-17 10:35:14.000000000 -0800 +@@ -41,6 +41,7 @@ + uint64_t xar_ntoh64(uint64_t num); + uint32_t xar_swap32(uint32_t num); + char *xar_get_path(xar_file_t f); ++off_t xar_get_heap_offset(xar_t x); + ssize_t xar_read_fd(int fd, void * buffer, size_t nbytes); + ssize_t xar_write_fd(int fd, void * buffer, size_t nbytes); + diff --git a/patches/context.diff b/patches/context.diff new file mode 100644 index 0000000..13558df --- /dev/null +++ b/patches/context.diff @@ -0,0 +1,2056 @@ +diff -urN xar/lib/archive.c xar.context/lib/archive.c +--- xar/lib/archive.c 2006-02-23 23:05:04.000000000 -0800 ++++ xar.context/lib/archive.c 2006-03-17 11:24:36.000000000 -0800 +@@ -64,6 +64,13 @@ + #define O_SHLOCK 0 + #endif + ++#ifndef LONG_MAX ++#define LONG_MAX INT32_MAX ++#endif ++#ifndef LONG_MIN ++#define LONG_MIN INT32_MIN ++#endif ++ + static int32_t xar_unserialize(xar_t x); + void xar_serialize(xar_t x, const char *file); + +diff -urN xar/lib/bzxar.c xar.context/lib/bzxar.c +--- xar/lib/bzxar.c 2006-02-23 23:05:04.000000000 -0800 ++++ xar.context/lib/bzxar.c 2006-03-17 10:57:14.000000000 -0800 +@@ -47,13 +47,12 @@ + #include "io.h" + + #ifdef HAVE_LIBBZ2 +-static int initted = 0; +-static bz_stream zs; ++#define BZIP2_CONTEXT(x) ((bz_stream *)(*x)) + #endif + +-int xar_bzip_fromheap_done(xar_t x, xar_file_t f, const char *attr); ++int xar_bzip_fromheap_done(xar_t x, xar_file_t f, const char *attr, void **context); + +-int xar_bzip_fromheap_in(xar_t x, xar_file_t f, const char *attr, void **in, size_t *inlen) { ++int xar_bzip_fromheap_in(xar_t x, xar_file_t f, const char *attr, void **in, size_t *inlen, void **context) { + #ifdef HAVE_LIBBZ2 + const char *opt; + void *out = NULL; +@@ -67,31 +66,27 @@ + if( !opt ) return 0; + if( strcmp(opt, "application/x-bzip2") != 0 ) return 0; + +- if( !initted ) { +- zs.bzalloc = NULL; +- zs.bzfree = NULL; +- zs.opaque = NULL; +- +- BZ2_bzDecompressInit(&zs, 0, 0); +- initted = 1; ++ if( !BZIP2_CONTEXT(context) ) { ++ *context = calloc(1,sizeof(bz_stream)); ++ BZ2_bzDecompressInit(BZIP2_CONTEXT(context), 0, 0); + } + + outlen = *inlen; + +- zs.next_in = *in; +- zs.avail_in = *inlen; +- zs.next_out = out; +- zs.avail_out = 0; ++ BZIP2_CONTEXT(context)->next_in = *in; ++ BZIP2_CONTEXT(context)->avail_in = *inlen; ++ BZIP2_CONTEXT(context)->next_out = out; ++ BZIP2_CONTEXT(context)->avail_out = 0; + +- while( zs.avail_in != 0 ) { ++ while( BZIP2_CONTEXT(context)->avail_in != 0 ) { + outlen = outlen * 2; + out = realloc(out, outlen); + if( out == NULL ) abort(); + +- zs.next_out = out + offset; +- zs.avail_out = outlen - offset; ++ BZIP2_CONTEXT(context)->next_out = out + offset; ++ BZIP2_CONTEXT(context)->avail_out = outlen - offset; + +- r = BZ2_bzDecompress(&zs); ++ r = BZ2_bzDecompress(BZIP2_CONTEXT(context)); + if( (r != BZ_OK) && (r != BZ_STREAM_END) ) { + xar_err_new(x); + xar_err_set_file(x, f); +@@ -99,10 +94,10 @@ + xar_err_callback(x, XAR_SEVERITY_FATAL, XAR_ERR_ARCHIVE_EXTRACTION); + return -1; + } +- offset += outlen - offset - zs.avail_out; ++ offset += outlen - offset - BZIP2_CONTEXT(context)->avail_out; + if( (r == BZ_STREAM_END) && (offset == 0) ) { +- xar_bzip_fromheap_done(x, f, attr); +- offset += outlen - offset - zs.avail_out; ++ xar_bzip_fromheap_done(x, f, attr, context); ++ offset += outlen - offset - BZIP2_CONTEXT(context)->avail_out; + break; + } + } +@@ -114,14 +109,19 @@ + return 0; + } + +-int xar_bzip_fromheap_done(xar_t x, xar_file_t f, const char *attr) { ++int xar_bzip_fromheap_done(xar_t x, xar_file_t f, const char *attr, void **context) { + #ifdef HAVE_LIBBZ2 +- initted = 0; +- BZ2_bzDecompressEnd(&zs); ++ BZ2_bzDecompressEnd(BZIP2_CONTEXT(context)); ++ ++ if(BZIP2_CONTEXT(context)){ ++ free(BZIP2_CONTEXT(context)); ++ *context = NULL; ++ } ++ + #endif /* HAVE_LIBBZ2 */ + return 0; + } +-int xar_bzip_toheap_done(xar_t x, xar_file_t f, const char *attr) { ++int xar_bzip_toheap_done(xar_t x, xar_file_t f, const char *attr, void **context) { + #ifdef HAVE_LIBBZ2 + const char *opt; + char *tmpstr; +@@ -133,9 +133,13 @@ + if( strcmp(opt, XAR_OPT_VAL_BZIP) != 0 ) + return 0; + +- initted = 0; +- BZ2_bzCompressEnd(&zs); ++ BZ2_bzCompressEnd(BZIP2_CONTEXT(context)); + ++ if(BZIP2_CONTEXT(context)){ ++ free(BZIP2_CONTEXT(context)); ++ *context = NULL; ++ } ++ + asprintf(&tmpstr, "%s/encoding", attr); + if( f ) { + xar_prop_set(f, tmpstr, NULL); +@@ -147,7 +151,7 @@ + return 0; + } + +-int32_t xar_bzip_toheap_in(xar_t x, xar_file_t f, const char *attr, void **in, size_t *inlen) { ++int32_t xar_bzip_toheap_in(xar_t x, xar_file_t f, const char *attr, void **in, size_t *inlen, void **context) { + #ifdef HAVE_LIBBZ2 + void *out = NULL; + size_t outlen, offset = 0; +@@ -161,33 +165,32 @@ + if( strcmp(opt, XAR_OPT_VAL_BZIP) != 0 ) + return 0; + +- if( !initted ) { +- memset(&zs, 0, sizeof(zs)); +- BZ2_bzCompressInit(&zs, 9, 0, 30); +- initted = 1; ++ if( !BZIP2_CONTEXT(context) ) { ++ *context = calloc(1,sizeof(bz_stream)); ++ BZ2_bzCompressInit(BZIP2_CONTEXT(context), 9, 0, 30); + } + + outlen = *inlen/2; + if(outlen == 0) outlen = 1024; +- zs.next_in = *in; +- zs.avail_in = *inlen; +- zs.next_out = out; +- zs.avail_out = 0; ++ BZIP2_CONTEXT(context)->next_in = *in; ++ BZIP2_CONTEXT(context)->avail_in = *inlen; ++ BZIP2_CONTEXT(context)->next_out = out; ++ BZIP2_CONTEXT(context)->avail_out = 0; + + do { + outlen *= 2; + out = realloc(out, outlen); + if( out == NULL ) abort(); + +- zs.next_out = out + offset; +- zs.avail_out = outlen - offset; ++ BZIP2_CONTEXT(context)->next_out = out + offset; ++ BZIP2_CONTEXT(context)->avail_out = outlen - offset; + +- if( *inlen == 0 ) +- r = BZ2_bzCompress(&zs, BZ_FINISH); ++ if( (*inlen == 0) ) ++ r = BZ2_bzCompress(BZIP2_CONTEXT(context), BZ_FINISH); + else +- r = BZ2_bzCompress(&zs, BZ_RUN); +- offset = outlen - zs.avail_out; +- } while( zs.avail_in != 0 ); ++ r = BZ2_bzCompress(BZIP2_CONTEXT(context), BZ_RUN); ++ offset = outlen - BZIP2_CONTEXT(context)->avail_out; ++ } while( BZIP2_CONTEXT(context)->avail_in != 0 ); + + free(*in); + *in = out; +diff -urN xar/lib/bzxar.h xar.context/lib/bzxar.h +--- xar/lib/bzxar.h 2006-02-17 11:27:10.000000000 -0800 ++++ xar.context/lib/bzxar.h 2006-03-17 10:57:20.000000000 -0800 +@@ -34,10 +34,10 @@ + #ifndef _XAR_BZLIB_H_ + #define _XAR_BZLIB_H_ + +-int xar_bzip_fromheap_in(xar_t x, xar_file_t f, const char *, void **in, size_t *inlen); +-int xar_bzip_fromheap_done(xar_t x, xar_file_t f, const char *); ++int xar_bzip_fromheap_in(xar_t x, xar_file_t f, const char *, void **in, size_t *inlen, void **context); ++int xar_bzip_fromheap_done(xar_t x, xar_file_t f, const char *, void **context); + +-int32_t xar_bzip_toheap_in(xar_t x, xar_file_t f, const char *, void **in, size_t *inlen); +-int xar_bzip_toheap_done(xar_t x, xar_file_t f, const char *); ++int32_t xar_bzip_toheap_in(xar_t x, xar_file_t f, const char *, void **in, size_t *inlen, void **context); ++int xar_bzip_toheap_done(xar_t x, xar_file_t f, const char *, void **context); + + #endif /* _XAR_BZLIB_H_ */ +diff -urN xar/lib/darwinattr.c xar.context/lib/darwinattr.c +--- xar/lib/darwinattr.c 2006-02-23 23:05:04.000000000 -0800 ++++ xar.context/lib/darwinattr.c 2006-03-17 11:26:37.000000000 -0800 +@@ -54,8 +54,15 @@ + #include + #endif + +-static int Fd; ++struct _darwinattr_context{ ++ int fd; ++ char *finfo; ++ char *buf; ++ int len; ++ int off; ++}; + ++#define DARWINATTR_CONTEXT(x) ((struct _darwinattr_context *)(x)) + #if defined(__APPLE__) + #ifdef HAVE_GETATTRLIST + #include +@@ -66,21 +73,19 @@ + char finderinfo[32]; + }; + +-static char *Gfinfo = NULL; +- + /* finfo_read + * This is for archiving the finderinfo via the getattrlist method. + * This function is used from the nonea_archive() function. + */ +-static int32_t finfo_read(xar_t x, xar_file_t f, void *buf, size_t len) { ++static int32_t finfo_read(xar_t x, xar_file_t f, void *buf, size_t len, void *context) { + if( len < 32 ) + return -1; + +- if( Gfinfo == NULL ) ++ if( DARWINATTR_CONTEXT(context)->finfo == NULL ) + return 0; + +- memcpy(buf, Gfinfo, 32); +- Gfinfo = NULL; ++ memcpy(buf, DARWINATTR_CONTEXT(context)->finfo, 32); ++ DARWINATTR_CONTEXT(context)->finfo = NULL; + return 32; + } + +@@ -88,26 +93,26 @@ + * This is for extracting the finderinfo via the setattrlist method. + * This function is used from the nonea_extract() function. + */ +-static int32_t finfo_write(xar_t x, xar_file_t f, void *buf, size_t len) { ++static int32_t finfo_write(xar_t x, xar_file_t f, void *buf, size_t len, void *context) { + struct attrlist attrs; + struct fi finfo; + + if( len < 32 ) + return -1; +- if( Gfinfo == NULL ) ++ if( DARWINATTR_CONTEXT(context)->finfo == NULL ) + return 0; + + memset(&attrs, 0, sizeof(attrs)); + attrs.bitmapcount = ATTR_BIT_MAP_COUNT; + attrs.commonattr = ATTR_CMN_OBJTYPE | ATTR_CMN_FNDRINFO; + +- getattrlist(Gfinfo, &attrs, &finfo, sizeof(finfo), 0); ++ getattrlist(DARWINATTR_CONTEXT(context)->finfo, &attrs, &finfo, sizeof(finfo), 0); + + attrs.commonattr = ATTR_CMN_FNDRINFO; +- if( setattrlist(Gfinfo, &attrs, buf, 32, 0) != 0 ) ++ if( setattrlist(DARWINATTR_CONTEXT(context)->finfo, &attrs, buf, 32, 0) != 0 ) + return -1; + +- Gfinfo = NULL; ++ DARWINATTR_CONTEXT(context)->finfo = NULL; + return 32; + } + #endif /* HAVE_GETATTRLIST */ +@@ -116,11 +121,11 @@ + * This is the read callback function for archiving the resource fork via + * the ..namedfork method. This callback is used from nonea_archive() + */ +-static int32_t xar_rsrc_read(xar_t x, xar_file_t f, void *inbuf, size_t bsize) { ++static int32_t xar_rsrc_read(xar_t x, xar_file_t f, void *inbuf, size_t bsize, void *context) { + int32_t r; + + while(1) { +- r = read(Fd, inbuf, bsize); ++ r = read(DARWINATTR_CONTEXT(context)->fd, inbuf, bsize); + if( (r < 0) && (errno == EINTR) ) + continue; + return r; +@@ -133,11 +138,11 @@ + * back to the file via ..namedfork method. This is the callback used + * in nonea_extract() and underbar_extract(). + */ +-static int32_t xar_rsrc_write(xar_t x, xar_file_t f, void *buf, size_t len) { ++static int32_t xar_rsrc_write(xar_t x, xar_file_t f, void *buf, size_t len, void *context) { + int32_t r; + size_t off = 0; + do { +- r = write(Fd, buf+off, len-off); ++ r = write(DARWINATTR_CONTEXT(context)->fd, buf+off, len-off); + if( (r < 0) && (errno != EINTR) ) + return r; + off += r; +@@ -147,57 +152,54 @@ + + #ifdef __APPLE__ + #if defined(HAVE_GETXATTR) +-static char *Gbuf = NULL; +-static int Glen = 0; +-static int Goff = 0; +- +-static int32_t xar_ea_read(xar_t x, xar_file_t f, void *buf, size_t len) { +- if( Gbuf == NULL ) ++ ++static int32_t xar_ea_read(xar_t x, xar_file_t f, void *buf, size_t len, void *context) { ++ if( DARWINATTR_CONTEXT(context)->buf == NULL ) + return 0; + +- if( (Glen-Goff) <= len ) { +- int siz = Glen-Goff; +- memcpy(buf, Gbuf+Goff, siz); +- free(Gbuf); +- Gbuf = NULL; +- Goff = 0; +- Glen = 0; ++ if( ((DARWINATTR_CONTEXT(context)->len)-(DARWINATTR_CONTEXT(context)->off)) <= len ) { ++ int siz = (DARWINATTR_CONTEXT(context)->len)-(DARWINATTR_CONTEXT(context)->off); ++ memcpy(buf, DARWINATTR_CONTEXT(context)->buf+DARWINATTR_CONTEXT(context)->off, siz); ++ free(DARWINATTR_CONTEXT(context)->buf); ++ DARWINATTR_CONTEXT(context)->buf = NULL; ++ DARWINATTR_CONTEXT(context)->off = 0; ++ DARWINATTR_CONTEXT(context)->len = 0; + return siz; + } + +- memcpy(buf, Gbuf+Goff, len); +- Goff += len; ++ memcpy(buf, DARWINATTR_CONTEXT(context)->buf+DARWINATTR_CONTEXT(context)->off, len); ++ DARWINATTR_CONTEXT(context)->off += len; + +- if( Goff == Glen ) { +- free(Gbuf); +- Gbuf = NULL; +- Goff = 0; +- Glen = 0; ++ if( DARWINATTR_CONTEXT(context)->off == DARWINATTR_CONTEXT(context)->len ) { ++ free(DARWINATTR_CONTEXT(context)->buf); ++ DARWINATTR_CONTEXT(context)->buf = NULL; ++ DARWINATTR_CONTEXT(context)->off = 0; ++ DARWINATTR_CONTEXT(context)->len = 0; + } + + return len; + } + +-static int32_t xar_ea_write(xar_t x, xar_file_t f, void *buf, size_t len) { +- if( Gbuf == NULL ) ++static int32_t xar_ea_write(xar_t x, xar_file_t f, void *buf, size_t len, void *context) { ++ if( DARWINATTR_CONTEXT(context)->buf == NULL ) + return 0; + +- if( Goff == Glen ) ++ if( DARWINATTR_CONTEXT(context)->off == DARWINATTR_CONTEXT(context)->len ) + return 0; + +- if( (Glen-Goff) <= len ) { +- int siz = Glen-Goff; +- memcpy(Gbuf+Goff, buf, siz); ++ if( ((DARWINATTR_CONTEXT(context)->len)-(DARWINATTR_CONTEXT(context)->off)) <= len ) { ++ int siz = (DARWINATTR_CONTEXT(context)->len)-(DARWINATTR_CONTEXT(context)->off); ++ memcpy((DARWINATTR_CONTEXT(context)->buf)+(DARWINATTR_CONTEXT(context)->off), buf, siz); + return siz; + } + +- memcpy(Gbuf+Goff, buf, len); +- Goff += len; ++ memcpy((DARWINATTR_CONTEXT(context)->buf)+(DARWINATTR_CONTEXT(context)->off), buf, len); ++ DARWINATTR_CONTEXT(context)->off += len; + + return len; + } + +-static int32_t ea_archive(xar_t x, xar_file_t f, const char* file) { ++static int32_t ea_archive(xar_t x, xar_file_t f, const char* file, void *context) { + char *buf, *i; + int ret, bufsz; + int32_t retval = 0; +@@ -231,29 +233,29 @@ + ret = getxattr(file, i, NULL, 0, 0, XATTR_NOFOLLOW); + if( ret < 0 ) + continue; +- Glen = ret; +- Gbuf = malloc(Glen); +- if( !Gbuf ) ++ DARWINATTR_CONTEXT(context)->len = ret; ++ DARWINATTR_CONTEXT(context)->buf = malloc(DARWINATTR_CONTEXT(context)->len); ++ if( !DARWINATTR_CONTEXT(context)->buf ) + goto BAIL; + +- ret = getxattr(file, i, Gbuf, Glen, 0, XATTR_NOFOLLOW); ++ ret = getxattr(file, i, DARWINATTR_CONTEXT(context)->buf, DARWINATTR_CONTEXT(context)->len, 0, XATTR_NOFOLLOW); + if( ret < 0 ) { +- free(Gbuf); +- Gbuf = NULL; +- Glen = 0; ++ free(DARWINATTR_CONTEXT(context)->buf); ++ DARWINATTR_CONTEXT(context)->buf = NULL; ++ DARWINATTR_CONTEXT(context)->len = 0; + continue; + } + + memset(tempnam, 0, sizeof(tempnam)); + snprintf(tempnam, sizeof(tempnam)-1, "ea/%s", i); +- xar_attrcopy_to_heap(x, f, tempnam, xar_ea_read); ++ xar_attrcopy_to_heap(x, f, tempnam, xar_ea_read, context); + } + BAIL: + free(buf); + return retval; + } + +-static int32_t ea_extract(xar_t x, xar_file_t f, const char* file) { ++static int32_t ea_extract(xar_t x, xar_file_t f, const char* file, void *context) { + const char *prop; + xar_iter_t iter; + +@@ -275,18 +277,18 @@ + continue; + + len = strtol(opt, NULL, 10); +- Gbuf = malloc(len); +- if( !Gbuf ) ++ DARWINATTR_CONTEXT(context)->buf = malloc(len); ++ if( !DARWINATTR_CONTEXT(context)->buf ) + return -1; +- Glen = len; ++ DARWINATTR_CONTEXT(context)->len = len; + +- xar_attrcopy_from_heap(x, f, prop, xar_ea_write); ++ xar_attrcopy_from_heap(x, f, prop, xar_ea_write, context); + +- setxattr(file, prop+strlen(XAR_EA_FORK)+1, Gbuf, Glen, 0, XATTR_NOFOLLOW); +- free(Gbuf); +- Gbuf = NULL; +- Glen = 0; +- Goff = 0; ++ setxattr(file, prop+strlen(XAR_EA_FORK)+1, DARWINATTR_CONTEXT(context)->buf, DARWINATTR_CONTEXT(context)->len, 0, XATTR_NOFOLLOW); ++ free(DARWINATTR_CONTEXT(context)->buf); ++ DARWINATTR_CONTEXT(context)->buf = NULL; ++ DARWINATTR_CONTEXT(context)->len = 0; ++ DARWINATTR_CONTEXT(context)->off = 0; + } + + return 0; +@@ -298,7 +300,7 @@ + * ..namedfork methods rather than via EAs. This is mainly for 10.3 + * and earlier support + */ +-static int32_t nonea_archive(xar_t x, xar_file_t f, const char* file) { ++static int32_t nonea_archive(xar_t x, xar_file_t f, const char* file, void *context) { + char rsrcname[4096]; + struct stat sb; + #ifdef HAVE_GETATTRLIST +@@ -317,8 +319,8 @@ + + memset(z, 0, sizeof(z)); + if( memcmp(finfo.finderinfo, z, sizeof(finfo.finderinfo)) != 0 ) { +- Gfinfo = finfo.finderinfo; +- xar_attrcopy_to_heap(x, f, "ea/com.apple.FinderInfo", finfo_read); ++ DARWINATTR_CONTEXT(context)->finfo = finfo.finderinfo; ++ xar_attrcopy_to_heap(x, f, "ea/com.apple.FinderInfo", finfo_read, context); + } + #endif /* HAVE_GETATTRLIST */ + +@@ -331,12 +333,12 @@ + if( sb.st_size == 0 ) + return 0; + +- Fd = open(rsrcname, O_RDONLY, 0); +- if( Fd < 0 ) ++ DARWINATTR_CONTEXT(context)->fd = open(rsrcname, O_RDONLY, 0); ++ if( DARWINATTR_CONTEXT(context)->fd < 0 ) + return -1; + +- xar_attrcopy_to_heap(x, f, "ea/com.apple.ResourceFork", xar_rsrc_read); +- close(Fd); ++ xar_attrcopy_to_heap(x, f, "ea/com.apple.ResourceFork", xar_rsrc_read, context); ++ close(DARWINATTR_CONTEXT(context)->fd); + return 0; + } + +@@ -345,7 +347,7 @@ + * ..namedfork methods rather than via EAs. This is mainly for 10.3 + * and earlier support + */ +-static int32_t nonea_extract(xar_t x, xar_file_t f, const char* file) { ++static int32_t nonea_extract(xar_t x, xar_file_t f, const char* file, void *context) { + char rsrcname[4096]; + #ifdef HAVE_SETATTRLIST + struct attrlist attrs; +@@ -360,19 +362,19 @@ + if( ret != 0 ) + return -1; + +- Gfinfo = (char *)file; ++ DARWINATTR_CONTEXT(context)->finfo = (char *)file; + +- xar_attrcopy_from_heap(x, f, "ea/com.apple.FinderInfo", finfo_write); ++ xar_attrcopy_from_heap(x, f, "ea/com.apple.FinderInfo", finfo_write, context); + #endif /* HAVE_SETATTRLIST */ + + memset(rsrcname, 0, sizeof(rsrcname)); + snprintf(rsrcname, sizeof(rsrcname)-1, "%s/..namedfork/rsrc", file); +- Fd = open(rsrcname, O_RDWR|O_TRUNC); +- if( Fd < 0 ) ++ DARWINATTR_CONTEXT(context)->fd = open(rsrcname, O_RDWR|O_TRUNC); ++ if( DARWINATTR_CONTEXT(context)->fd < 0 ) + return 0; + +- xar_attrcopy_from_heap(x, f, "ea/com.apple.ResourceFork", xar_rsrc_write); +- close(Fd); ++ xar_attrcopy_from_heap(x, f, "ea/com.apple.ResourceFork", xar_rsrc_write, context); ++ close(DARWINATTR_CONTEXT(context)->fd); + return 0; + } + #endif /* __APPLE__ */ +@@ -381,13 +383,13 @@ + * Check to see if the file we're archiving is a ._ file. If so, + * stop the archival process. + */ +-int32_t xar_underbar_check(xar_t x, xar_file_t f, const char* file) { ++int32_t xar_underbar_check(xar_t x, xar_file_t f, const char* file, void *context) { + char *bname, *tmp; + + tmp = strdup(file); + bname = basename(tmp); + +- if(bname && (bname[0] == '.') && (bname[1] == '_')) { ++ if(bname && (bname[0] == '.') && (bname[1] == '_')){ + free(tmp); + return 1; + } +@@ -398,7 +400,7 @@ + + #ifdef __APPLE__ + /* This only really makes sense on OSX */ +-static int32_t underbar_archive(xar_t x, xar_file_t f, const char* file) { ++static int32_t underbar_archive(xar_t x, xar_file_t f, const char* file, void *context) { + struct stat sb; + char underbarname[4096], z[32]; + char *dname, *bname, *tmp, *tmp2; +@@ -407,6 +409,9 @@ + int num_entries = 0, i, r; + off_t off; + ++ if( !file ) ++ return 0; ++ + tmp = strdup(file); + tmp2 = strdup(file); + dname = dirname(tmp2); +@@ -420,13 +425,13 @@ + if( stat(underbarname, &sb) != 0 ) + return 0; + +- Fd = open(underbarname, O_RDONLY); +- if( Fd < 0 ) ++ DARWINATTR_CONTEXT(context)->fd = open(underbarname, O_RDONLY); ++ if( DARWINATTR_CONTEXT(context)->fd < 0 ) + return -1; + + memset(&ash, 0, sizeof(ash)); + memset(&ase, 0, sizeof(ase)); +- r = read(Fd, &ash, XAR_ASH_SIZE); ++ r = read(DARWINATTR_CONTEXT(context)->fd, &ash, XAR_ASH_SIZE); + if( r < XAR_ASH_SIZE ) + return -1; + +@@ -440,37 +445,38 @@ + + for(i = 0; i < num_entries; i++) { + off_t entoff; +- r = read(Fd, &ase, sizeof(ase)); ++ r = read(DARWINATTR_CONTEXT(context)->fd, &ase, sizeof(ase)); + if( r < sizeof(ase) ) + return -1; + off+=r; + + if( ntohl(ase.entry_id) == AS_ID_FINDER ) { + entoff = (off_t)ntohl(ase.offset); +- if( lseek(Fd, entoff, SEEK_SET) == -1 ) ++ if( lseek(DARWINATTR_CONTEXT(context)->fd, entoff, SEEK_SET) == -1 ) + return -1; +- r = read(Fd, z, sizeof(z)); ++ r = read(DARWINATTR_CONTEXT(context)->fd, z, sizeof(z)); + if( r < sizeof(z) ) + return -1; + +- Gfinfo = z; +- xar_attrcopy_to_heap(x, f, "ea/com.apple.FinderInfo", finfo_read); +- if( lseek(Fd, (off_t)off, SEEK_SET) == -1 ) ++ DARWINATTR_CONTEXT(context)->finfo = z; ++ xar_attrcopy_to_heap(x, f, "ea/com.apple.FinderInfo", finfo_read, context); ++ if( lseek(DARWINATTR_CONTEXT(context)->fd, (off_t)off, SEEK_SET) == -1 ) + return -1; + } + if( ntohl(ase.entry_id) == AS_ID_RESOURCE ) { + entoff = (off_t)ntohl(ase.offset); +- if( lseek(Fd, entoff, SEEK_SET) == -1 ) ++ if( lseek(DARWINATTR_CONTEXT(context)->fd, entoff, SEEK_SET) == -1 ) + return -1; + +- xar_attrcopy_to_heap(x, f, "ea/com.apple.ResourceFork", xar_rsrc_read); ++ xar_attrcopy_to_heap(x, f, "ea/com.apple.ResourceFork", xar_rsrc_read, context); + +- if( lseek(Fd, (off_t)off, SEEK_SET) == -1 ) ++ if( lseek(DARWINATTR_CONTEXT(context)->fd, (off_t)off, SEEK_SET) == -1 ) + return -1; + } + } + +- close(Fd); ++ close(DARWINATTR_CONTEXT(context)->fd); ++ DARWINATTR_CONTEXT(context)->fd = 0; + return 0; + } + #endif +@@ -479,7 +485,7 @@ + * Extract finderinfo and resource fork information to an appledouble + * ._ file. + */ +-static int32_t underbar_extract(xar_t x, xar_file_t f, const char* file) { ++static int32_t underbar_extract(xar_t x, xar_file_t f, const char* file, void *context) { + char underbarname[4096]; + char *dname, *bname, *tmp, *tmp2; + const char *rsrclenstr; +@@ -510,8 +516,8 @@ + free(tmp); + free(tmp2); + +- Fd = open(underbarname, O_RDWR | O_CREAT | O_TRUNC, 0); +- if( Fd < 0 ) ++ DARWINATTR_CONTEXT(context)->fd = open(underbarname, O_RDWR | O_CREAT | O_TRUNC, 0); ++ if( DARWINATTR_CONTEXT(context)->fd < 0 ) + return -1; + + xar_prop_get(f, "ea/com.apple.ResourceFork/size", &rsrclenstr); +@@ -524,29 +530,31 @@ + ash.version = htonl(APPLEDOUBLE_VERSION); + ash.entries = htons(num_entries); + +- write(Fd, &ash, XAR_ASH_SIZE); ++ write(DARWINATTR_CONTEXT(context)->fd, &ash, XAR_ASH_SIZE); + + ase.offset = htonl(XAR_ASH_SIZE + ntohs(ash.entries)*12); + if( have_fi ) { + ase.entry_id = htonl(AS_ID_FINDER); + ase.length = htonl(32); +- write(Fd, &ase, 12); ++ write(DARWINATTR_CONTEXT(context)->fd, &ase, 12); + } + + if( have_rsrc ) { + ase.entry_id = htonl(AS_ID_RESOURCE); + ase.offset = htonl(ntohl(ase.offset) + ntohl(ase.length)); + ase.length = htonl(rsrclen); +- write(Fd, &ase, 12); ++ write(DARWINATTR_CONTEXT(context)->fd, &ase, 12); + } + + if( have_fi ) +- xar_attrcopy_from_heap(x, f, "ea/com.apple.FinderInfo", xar_rsrc_write); ++ xar_attrcopy_from_heap(x, f, "ea/com.apple.FinderInfo", xar_rsrc_write, context); + if( have_rsrc ) +- xar_attrcopy_from_heap(x, f, "ea/com.apple.ResourceFork", xar_rsrc_write); +- close(Fd); ++ xar_attrcopy_from_heap(x, f, "ea/com.apple.ResourceFork", xar_rsrc_write, context); ++ close(DARWINATTR_CONTEXT(context)->fd); + +- xar_set_perm(x, f, underbarname); ++ DARWINATTR_CONTEXT(context)->fd = 0; ++ ++ xar_set_perm(x, f, underbarname ); + + return 0; + } +@@ -554,28 +562,36 @@ + + int32_t xar_darwinattr_archive(xar_t x, xar_file_t f, const char* file) + { ++ struct _darwinattr_context context; ++ ++ memset(&context,0,sizeof(struct _darwinattr_context)); ++ + #if defined(__APPLE__) + #if defined(HAVE_GETXATTR) +- if( ea_archive(x, f, file) == 0 ) ++ if( ea_archive(x, f, file, (void *)&context) == 0 ) + return 0; + #endif +- if( nonea_archive(x, f, file) == 0 ) ++ if( nonea_archive(x, f, file, (void *)&context) == 0 ) + return 0; +- return underbar_archive(x, f, file); ++ return underbar_archive(x, f, file, (void *)&context); + #endif /* __APPLE__ */ + return 0; + } + + int32_t xar_darwinattr_extract(xar_t x, xar_file_t f, const char* file) + { ++ struct _darwinattr_context context; ++ ++ memset(&context,0,sizeof(struct _darwinattr_context)); ++ + #if defined(__APPLE__) + #if defined(HAVE_GETXATTR) +- if( ea_extract(x, f, file) == 0 ) ++ if( ea_extract(x, f, file, (void *)&context) == 0 ) + return 0; + #endif + +- if( nonea_extract(x, f, file) == 0 ) ++ if( nonea_extract(x, f, file, (void *)&context) == 0 ) + return 0; + #endif /* __APPLE__ */ +- return underbar_extract(x, f, file); ++ return underbar_extract(x, f, file, (void *)&context); + } +diff -urN xar/lib/data.c xar.context/lib/data.c +--- xar/lib/data.c 2006-02-23 23:05:04.000000000 -0800 ++++ xar.context/lib/data.c 2006-03-17 11:00:28.000000000 -0800 +@@ -18,24 +18,76 @@ + #define O_EXLOCK 0 + #endif + +-static int Fd; ++struct _data_context{ ++ int fd; ++ void *buffer; ++ size_t length; ++ off_t offset; ++}; + +-int32_t xar_data_read(xar_t x, xar_file_t f, void *inbuf, size_t bsize) { ++#define DATA_CONTEXT(x) ((struct _data_context*)(x)) ++ ++int32_t xar_data_read(xar_t x, xar_file_t f, void *inbuf, size_t bsize, void *context) { + int32_t r; + ++ /* read from buffer, rather then fd,if available */ ++ if(DATA_CONTEXT(context)->length){ ++ char *readbuf = (char *)DATA_CONTEXT(context)->buffer; ++ size_t sizetoread = DATA_CONTEXT(context)->length - DATA_CONTEXT(context)->offset; ++ ++ if( !sizetoread){ ++ return 0; ++ } ++ ++ if( sizetoread > bsize ){ ++ sizetoread = bsize; ++ } ++ ++ /* dont read passed the end of the buffer */ ++ if((DATA_CONTEXT(context)->offset + sizetoread) > DATA_CONTEXT(context)->length){ ++ return -1; ++ } ++ ++ readbuf += DATA_CONTEXT(context)->offset; ++ memcpy(inbuf,readbuf,sizetoread); ++ ++ DATA_CONTEXT(context)->offset += sizetoread; ++ ++ return sizetoread; ++ } ++ + while(1) { +- r = read(Fd, inbuf, bsize); ++ r = read(DATA_CONTEXT(context)->fd, inbuf, bsize); + if( (r < 0) && (errno == EINTR) ) + continue; + return r; +- } ++ } ++ + } + +-int32_t xar_data_write(xar_t x, xar_file_t f, void *buf, size_t len) { ++int32_t xar_data_write(xar_t x, xar_file_t f, void *buf, size_t len, void *context) { + int32_t r; + size_t off = 0; ++ ++ /* read from buffer, rather then fd,if available */ ++ if(DATA_CONTEXT(context)->length){ ++ char *writebuf = (char *)DATA_CONTEXT(context)->buffer; ++ ++ /* dont write passed the end of the buffer */ ++ if((DATA_CONTEXT(context)->offset + len) > DATA_CONTEXT(context)->length){ ++ return -1; ++ } ++ ++ writebuf += DATA_CONTEXT(context)->offset; ++ memcpy(writebuf,buf,len); ++ ++ DATA_CONTEXT(context)->offset += len; ++ ++ return len; ++ } ++ + do { +- r = write(Fd, buf+off, len-off); ++ r = write(DATA_CONTEXT(context)->fd, buf+off, len-off); + if( (r < 0) && (errno != EINTR) ) + return r; + off += r; +@@ -50,6 +102,9 @@ + int32_t xar_data_archive(xar_t x, xar_file_t f, const char *file) { + const char *opt; + int32_t retval = 0; ++ struct _data_context context; ++ ++ memset(&context,0,sizeof(struct _data_context)); + + xar_prop_get(f, "type", &opt); + if(!opt) return 0; +@@ -65,60 +120,68 @@ + return 0; + } + +- Fd = open(file, O_RDONLY); +- if( Fd < 0 ) { ++ context.fd = open(file, O_RDONLY); ++ if( context.fd < 0 ) { + xar_err_new(x); + xar_err_set_file(x, f); + xar_err_set_string(x, "io: Could not open file"); + xar_err_callback(x, XAR_SEVERITY_NONFATAL, XAR_ERR_ARCHIVE_CREATION); + return -1; +- } ++ } + +- retval = xar_attrcopy_to_heap(x, f, "data", xar_data_read); ++ retval = xar_attrcopy_to_heap(x, f, "data", xar_data_read,(void *)(&context)); + +- close(Fd); ++ if(context.fd > 0) ++ close(context.fd); ++ + return retval; + } + + int32_t xar_data_extract(xar_t x, xar_file_t f, const char *file) { + const char *opt; +- +- /* Only regular files are copied in and out of the heap here */ +- xar_prop_get(f, "type", &opt); +- if( !opt ) return 0; +- if( strcmp(opt, "file") != 0 ) { +- if( strcmp(opt, "hardlink") == 0 ) { +- opt = xar_attr_get(f, "type", "link"); +- if( !opt ) +- return 0; +- if( strcmp(opt, "original") != 0 ) +- return 0; +- /* else, we're an original hardlink, so keep going */ +- } else +- return 0; +- } +- +- /* mode 600 since other modules may need to operate on the file +- * prior to the real permissions being set. +- */ ++ struct _data_context context; ++ ++ memset(&context,0,sizeof(struct _data_context)); ++ ++ /* Only regular files are copied in and out of the heap here */ ++ xar_prop_get(f, "type", &opt); ++ if( !opt ) return 0; ++ if( strcmp(opt, "file") != 0 ) { ++ if( strcmp(opt, "hardlink") == 0 ) { ++ opt = xar_attr_get(f, "type", "link"); ++ if( !opt ) ++ return 0; ++ if( strcmp(opt, "original") != 0 ) ++ return 0; ++ /* else, we're an original hardlink, so keep going */ ++ } else ++ return 0; ++ } ++ ++ /* mode 600 since other modules may need to operate on the file ++ * prior to the real permissions being set. ++ */ + TRYAGAIN: +- Fd = open(file, O_RDWR|O_TRUNC|O_EXLOCK, 0600); +- if( Fd < 0 ) { ++ context.fd = open(file, O_RDWR|O_TRUNC|O_EXLOCK, 0600); ++ if( context.fd < 0 ) { + if( errno == ENOENT ) { + xar_file_t parent = XAR_FILE(f)->parent; + if( parent && (xar_extract(x, parent) == 0) ) + goto TRYAGAIN; + } ++ ++ xar_err_new(x); ++ xar_err_set_file(x, f); ++ xar_err_set_string(x, "io: Could not create file"); ++ xar_err_callback(x, XAR_SEVERITY_NONFATAL, XAR_ERR_ARCHIVE_EXTRACTION); ++ return -1; ++ } + +- xar_err_new(x); +- xar_err_set_file(x, f); +- xar_err_set_string(x, "io: Could not create file"); +- xar_err_callback(x, XAR_SEVERITY_NONFATAL, XAR_ERR_ARCHIVE_EXTRACTION); +- return -1; +- } +- +- xar_attrcopy_from_heap(x, f, "data", xar_data_write); +- close(Fd); ++ xar_attrcopy_from_heap(x, f, "data", xar_data_write, (void *)(&context)); ++ ++ if( context.fd > 0 ) ++ close(context.fd); ++ + return 0; + } + +diff -urN xar/lib/fbsdattr.c xar.context/lib/fbsdattr.c +--- xar/lib/fbsdattr.c 2006-02-17 11:27:10.000000000 -0800 ++++ xar.context/lib/fbsdattr.c 2006-03-17 11:03:08.000000000 -0800 +@@ -57,41 +57,45 @@ + #endif + + #ifdef HAVE_SYS_EXTATTR_H +-static const char *Gfile = NULL; +-static const char *Gattr = NULL; +-static void *Gbuf = NULL; +-static int Goff = 0; +-static int Gbufsz = 0; +-static int Gns = 0; ++struct _fbsdattr_context{ ++ const char *file = NULL; ++ const char *attr = NULL; ++ void *buf = NULL; ++ int off = 0; ++ int bufsz = 0; ++ int ns = 0; ++}; ++ ++#define FBSDATTR_CONTEXT(x) ((struct _fbsdattr_context *)(x)) + + int32_t xar_fbsdattr_read(xar_t x, xar_file_t f, void *buf, size_t len) { +- if( !Gbuf ) { +- Gbufsz = extattr_get_link(Gfile, Gns, Gattr, NULL, 0); +- if( Gbufsz < 0 ) ++ if( !FBSDATTR_CONTEXT(context)->buf ) { ++ FBSDATTR_CONTEXT(context)->bufsz = extattr_get_link(FBSDATTR_CONTEXT(context)->file, FBSDATTR_CONTEXT(context)->ns, FBSDATTR_CONTEXT(context)->attr, NULL, 0); ++ if( FBSDATTR_CONTEXT(context)->bufsz < 0 ) + return -1; +- Gbuf = malloc(Gbufsz); +- if( !Gbuf ) ++ FBSDATTR_CONTEXT(context)->buf = malloc(FBSDATTR_CONTEXT(context)->bufsz); ++ if( !FBSDATTR_CONTEXT(context)->buf ) + return -1; + +- Gbufsz = extattr_get_link(Gfile, Gns, Gattr, Gbuf, Gbufsz); ++ FBSDATTR_CONTEXT(context)->bufsz = extattr_get_link(FBSDATTR_CONTEXT(context)->file, FBSDATTR_CONTEXT(context)->ns, FBSDATTR_CONTEXT(context)->attr, FBSDATTR_CONTEXT(context)->buf, FBSDATTR_CONTEXT(context)->bufsz); + } + +- if( (Gbufsz - Goff) <= len ) { ++ if( (FBSDATTR_CONTEXT(context)->bufsz - FBSDATTR_CONTEXT(context)->off) <= len ) { + int32_t ret; + +- ret = Gbufsz - Goff; +- memcpy(buf, Gbuf+Goff, ret); +- Goff += ret; ++ ret = FBSDATTR_CONTEXT(context)->bufsz - FBSDATTR_CONTEXT(context)->off; ++ memcpy(buf, FBSDATTR_CONTEXT(context)->buf+FBSDATTR_CONTEXT(context)->off, ret); ++ FBSDATTR_CONTEXT(context)->off += ret; + return(ret); + } else { +- memcpy(buf, Gbuf+Goff, len); +- Gbuf += len; ++ memcpy(buf, FBSDATTR_CONTEXT(context)->buf+FBSDATTR_CONTEXT(context)->off, len); ++ FBSDATTR_CONTEXT(context)->buf += len; + return(len); + } + + } + int32_t xar_fbsdattr_write(xar_t x, xar_file_t f, void *buf, size_t len) { +- return extattr_set_link(Gfile, Gns, Gattr, buf, len); ++ return extattr_set_link(FBSDATTR_CONTEXT(context)->file, FBSDATTR_CONTEXT(context)->ns, FBSDATTR_CONTEXT(context)->attr, buf, len); + } + #endif + +@@ -103,7 +107,10 @@ + struct statfs sfs; + char *fsname = NULL; + int namespace = EXTATTR_NAMESPACE_USER; +- ++ struct _fbsdattr_context context; ++ ++ memset(&context,0,sizeof(struct _fbsdattr_context)); ++ + TRYAGAIN: + /* extattr_list_link()'s man page does not define the return + * value. The kernel source comments say 0 for success, -1 for +@@ -174,16 +181,16 @@ + extattr_namespace_to_string(namespace, &ns); + memset(tempnam, 0, sizeof(tempnam)); + snprintf(tempnam, sizeof(tempnam)-1, "%s/%s.%s", XAR_EA_FORK, ns, key); +- Gns = namespace; +- Gfile = file; +- Gattr = key; ++ FBSDATTR_CONTEXT(context).ns = namespace; ++ FBSDATTR_CONTEXT(context).file = file; ++ FBSDATTR_CONTEXT(context).attr = key; + + xar_attr_set(f, tempnam, "fstype", fsname); + xar_attrcopy_to_heap(x, f, tempnam, xar_fbsdattr_read); + +- free(Gbuf); +- Gbuf = NULL; +- Goff = 0; ++ free(FBSDATTR_CONTEXT(context).buf); ++ FBSDATTR_CONTEXT(context).buf = NULL; ++ FBSDATTR_CONTEXT(context).off = 0; + } + + if( namespace == EXTATTR_NAMESPACE_USER ) { +@@ -200,7 +207,7 @@ + #endif + } + +-int32_t xar_fbsdattr_extract(xar_t x, xar_file_t f, const char* file) ++int32_t xar_fbsdattr_extract(xar_t x, xar_file_t f, const char* file, char *buffer, size_t len) + { + #ifdef HAVE_SYS_EXTATTR_H + char *fsname = "bogus"; +@@ -208,7 +215,10 @@ + struct statfs sfs; + int eaopt = 0; + xar_iter_t iter; +- ++ struct _fbsdattr_context context; ++ ++ memset(&context,0,sizeof(struct _fbsdattr_context)); ++ + statfs(file, &sfs); + fsname = sfs.f_fstypename; + +@@ -227,16 +237,16 @@ + + tmp = prop + strlen(XAR_EA_FORK) + 1; + if( strncmp(tmp, "user.", 5) == 0 ) { +- Gns = EXTATTR_NAMESPACE_USER; +- Gattr = tmp + 5; ++ FBSDATTR_CONTEXT(context).ns = EXTATTR_NAMESPACE_USER; ++ FBSDATTR_CONTEXT(context).attr = tmp + 5; + } else if( strncmp(tmp, "system.", 7) == 0 ) { +- Gns = EXTATTR_NAMESPACE_SYSTEM; +- Gattr = tmp + 7; ++ FBSDATTR_CONTEXT(context).ns = EXTATTR_NAMESPACE_SYSTEM; ++ FBSDATTR_CONTEXT(context).attr = tmp + 7; + } else { + continue; + } + +- Gfile = file; ++ FBSDATTR_CONTEXT(context).file = file; + xar_attrcopy_from_heap(x, f, prop, xar_fbsdattr_write); + } + +diff -urN xar/lib/io.c xar.context/lib/io.c +--- xar/lib/io.c 2006-02-23 23:05:04.000000000 -0800 ++++ xar.context/lib/io.c 2006-03-17 11:13:25.000000000 -0800 +@@ -104,7 +104,9 @@ + } + }; + +-int32_t xar_attrcopy_to_heap(xar_t x, xar_file_t f, const char *attr, read_callback rcb) { ++int32_t xar_attrcopy_to_heap(xar_t x, xar_file_t f, const char *attr, read_callback rcb, void *context) { ++ int modulecount = (sizeof(xar_datamods)/sizeof(struct datamod)); ++ void *modulecontext[modulecount]; + int r, off, i; + size_t bsize, rsize; + int64_t readsize=0, writesize=0, inc = 0; +@@ -114,6 +116,8 @@ + off_t orig_heap_offset = XAR(x)->heap_offset; + xar_file_t tmpf = NULL; + ++ memset(modulecontext, 0, sizeof(void*)*modulecount); ++ + opt = xar_opt_get(x, XAR_OPT_RSIZE); + if( !opt ) { + bsize = 4096; +@@ -130,7 +134,7 @@ + if( !inbuf ) + return -1; + +- r = rcb(x, f, inbuf, bsize); ++ r = rcb(x, f, inbuf, bsize, context); + if( r < 0 ) { + free(inbuf); + return -1; +@@ -141,16 +145,16 @@ + rsize = r; + + /* filter the data through the in modules */ +- for( i = 0; i < (sizeof(xar_datamods)/sizeof(struct datamod)); i++) { ++ for( i = 0; i < modulecount; i++) { + if( xar_datamods[i].th_in ) { +- xar_datamods[i].th_in(x, f, attr, &inbuf, &rsize); ++ xar_datamods[i].th_in(x, f, attr, &inbuf, &rsize, &modulecontext[i]); + } + } + + /* filter the data through the out modules */ +- for( i = 0; i < (sizeof(xar_datamods)/sizeof(struct datamod)); i++) { ++ for( i = 0; i < modulecount; i++) { + if( xar_datamods[i].th_out ) +- xar_datamods[i].th_out(x, f, attr, inbuf, rsize); ++ xar_datamods[i].th_out(x, f, attr, inbuf, rsize, &modulecontext[i]); + } + + off = 0; +@@ -165,7 +169,7 @@ + } + XAR(x)->heap_offset += off; + free(inbuf); +- ++ + } + + +@@ -173,16 +177,16 @@ + if( readsize == 0 ) { + XAR(x)->heap_offset = orig_heap_offset; + lseek(XAR(x)->heap_fd, -writesize, SEEK_CUR); +- for( i = 0; i < (sizeof(xar_datamods)/sizeof(struct datamod)); i++) { ++ for( i = 0; i < modulecount; i++) { + if( xar_datamods[i].th_done ) +- xar_datamods[i].th_done(x, NULL, attr); ++ xar_datamods[i].th_done(x, NULL, attr, &modulecontext[i]); + } + return 0; + } + /* finish up anything that still needs doing */ +- for( i = 0; i < (sizeof(xar_datamods)/sizeof(struct datamod)); i++) { ++ for( i = 0; i < modulecount; i++) { + if( xar_datamods[i].th_done ) +- xar_datamods[i].th_done(x, f, attr); ++ xar_datamods[i].th_done(x, f, attr, &modulecontext[i]); + } + + XAR(x)->heap_len += writesize; +@@ -257,7 +261,9 @@ + * data from the heap file. + * It is assumed the heap_fd is already positioned appropriately. + */ +-int32_t xar_attrcopy_from_heap(xar_t x, xar_file_t f, const char *attr, write_callback wcb) { ++int32_t xar_attrcopy_from_heap(xar_t x, xar_file_t f, const char *attr, write_callback wcb, void *context) { ++ int modulecount = (sizeof(xar_datamods)/sizeof(struct datamod)); ++ void *modulecontext[modulecount]; + int r, i; + size_t bsize, def_bsize; + int64_t fsize, inc = 0, seekoff; +@@ -265,6 +271,8 @@ + const char *opt; + char *tmpstr = NULL; + ++ memset(modulecontext, 0, sizeof(void*)*modulecount); ++ + opt = xar_opt_get(x, "rsize"); + if( !opt ) { + def_bsize = 4096; +@@ -279,7 +287,7 @@ + xar_prop_get(f, tmpstr, &opt); + free(tmpstr); + if( !opt ) { +- wcb(x, f, NULL, 0); ++ wcb(x, f, NULL, 0, context); + return 0; + } else { + seekoff = strtoll(opt, NULL, 0); +@@ -365,26 +373,30 @@ + bsize = r; + + /* filter the data through the in modules */ +- for( i = 0; i < (sizeof(xar_datamods)/sizeof(struct datamod)); i++) { ++ for( i = 0; i < modulecount; i++) { + if( xar_datamods[i].fh_in ) { + int32_t ret; +- ret = xar_datamods[i].fh_in(x, f, attr, &inbuf, &bsize); ++ ret = xar_datamods[i].fh_in(x, f, attr, &inbuf, &bsize, &modulecontext[i]); + if( ret < 0 ) + return -1; + } + } +- ++ ++ /* skip the write phase, if there is no write function to call */ ++ if(!wcb) ++ continue; ++ + /* filter the data through the out modules */ +- for( i = 0; i < (sizeof(xar_datamods)/sizeof(struct datamod)); i++) { ++ for( i = 0; i < modulecount; i++) { + if( xar_datamods[i].fh_out ) { + int32_t ret; +- ret = xar_datamods[i].fh_out(x, f, attr, inbuf, bsize); ++ ret = xar_datamods[i].fh_out(x, f, attr, inbuf, bsize, &modulecontext[i]); + if( ret < 0 ) + return -1; + } + } + +- wcb(x, f, inbuf, bsize); ++ wcb(x, f, inbuf, bsize, context); + free(inbuf); + bsize = def_bsize; + inbuf = malloc(bsize); +@@ -392,10 +404,10 @@ + + free(inbuf); + /* finish up anything that still needs doing */ +- for( i = 0; i < (sizeof(xar_datamods)/sizeof(struct datamod)); i++) { ++ for( i = 0; i < modulecount; i++) { + if( xar_datamods[i].fh_done ) { + int32_t ret; +- ret = xar_datamods[i].fh_done(x, f, attr); ++ ret = xar_datamods[i].fh_done(x, f, attr, &modulecontext[i]); + if( ret < 0 ) + return ret; + } +diff -urN xar/lib/io.h xar.context/lib/io.h +--- xar/lib/io.h 2006-02-17 11:27:10.000000000 -0800 ++++ xar.context/lib/io.h 2006-03-17 11:13:52.000000000 -0800 +@@ -34,16 +34,16 @@ + #ifndef _XAR_IO_H_ + #define _XAR_IO_H_ + +-typedef int (*read_callback)(xar_t, xar_file_t, void *, size_t); +-typedef int (*write_callback)(xar_t, xar_file_t, void *, size_t); ++typedef int (*read_callback)(xar_t, xar_file_t, void *, size_t, void *context); ++typedef int (*write_callback)(xar_t, xar_file_t, void *, size_t, void *context); + +-typedef int (*fromheap_in)(xar_t x, xar_file_t f, const char *attr, void **in, size_t *inlen); +-typedef int (*fromheap_out)(xar_t x, xar_file_t f, const char *attr, void *in, size_t inlen); +-typedef int (*fromheap_done)(xar_t x, xar_file_t f, const char *attr); +- +-typedef int (*toheap_in)(xar_t x, xar_file_t f, const char *attr, void **in, size_t *inlen); +-typedef int (*toheap_out)(xar_t x, xar_file_t f, const char *attr, void *in, size_t inlen); +-typedef int (*toheap_done)(xar_t x, xar_file_t f, const char *attr); ++typedef int (*fromheap_in)(xar_t x, xar_file_t f, const char *attr, void **in, size_t *inlen, void **context); ++typedef int (*fromheap_out)(xar_t x, xar_file_t f, const char *attr, void *in, size_t inlen, void **context); ++typedef int (*fromheap_done)(xar_t x, xar_file_t f, const char *attr, void **context); ++ ++typedef int (*toheap_in)(xar_t x, xar_file_t f, const char *attr, void **in, size_t *inlen, void **context); ++typedef int (*toheap_out)(xar_t x, xar_file_t f, const char *attr, void *in, size_t inlen, void **context); ++typedef int (*toheap_done)(xar_t x, xar_file_t f, const char *attr, void **context); + + struct datamod { + fromheap_in fh_in; +@@ -54,8 +54,8 @@ + toheap_done th_done; + }; + +-int32_t xar_attrcopy_to_heap(xar_t x, xar_file_t f, const char *attr, read_callback rcb); +-int32_t xar_attrcopy_from_heap(xar_t x, xar_file_t f, const char *attr, write_callback wcb); ++int32_t xar_attrcopy_to_heap(xar_t x, xar_file_t f, const char *attr, read_callback rcb, void *context); ++int32_t xar_attrcopy_from_heap(xar_t x, xar_file_t f, const char *attr, write_callback wcb, void *context); + int32_t xar_heap_to_archive(xar_t x); + + #endif /* _XAR_IO_H_ */ +diff -urN xar/lib/linuxattr.c xar.context/lib/linuxattr.c +--- xar/lib/linuxattr.c 2006-02-23 23:05:04.000000000 -0800 ++++ xar.context/lib/linuxattr.c 2006-03-17 11:14:35.000000000 -0800 +@@ -77,49 +77,54 @@ + #endif + + #if defined(HAVE_SYS_XATTR_H) && defined(HAVE_LGETXATTR) && !defined(__APPLE__) +-static const char *Gfile = NULL; +-static const char *Gattr = NULL; +-static void *Gbuf = NULL; +-static int Goff = 0; +-static int Gbufsz = 0; + +-int32_t xar_linuxattr_read(xar_t x, xar_file_t f, void * buf, size_t len) { +- +- if( !Gbuf ) { ++struct _linuxattr_context{ ++ const char *file; ++ const char *attr; ++ void *buf; ++ int off = 0; ++ int bufsz = 0; ++}; ++ ++#define LINUXATTR_CONTEXT(x) ((struct _linuxattr_context *)(x)) ++ ++int32_t xar_linuxattr_read(xar_t x, xar_file_t f, void * buf, size_t len, void *context) { ++ ++ if( !LINUXATTR_CONTEXT(context)->buf ) { + int r; +- Gbufsz = 1024; ++ LINUXATTR_CONTEXT(context)->bufsz = 1024; + AGAIN2: +- Gbuf = malloc(Gbufsz); +- if(!Gbuf) ++ LINUXATTR_CONTEXT(context)->buf = malloc(LINUXATTR_CONTEXT(context)->bufsz); ++ if(!LINUXATTR_CONTEXT(context)->buf) + goto AGAIN2; +- memset(Gbuf, 0, Gbufsz); +- r = lgetxattr(Gfile, Gattr+strlen(XAR_EA_FORK)+1, Gbuf, Gbufsz); ++ memset(LINUXATTR_CONTEXT(context)->buf, 0, LINUXATTR_CONTEXT(context)->bufsz); ++ r = lgetxattr(LINUXATTR_CONTEXT(context)->file, LINUXATTR_CONTEXT(context)->attr+strlen(XAR_EA_FORK)+1, LINUXATTR_CONTEXT(context)->buf, LINUXATTR_CONTEXT(context)->bufsz); + if( r < 0 ) { + switch(errno) { +- case ERANGE: Gbufsz *= 2; free(Gbuf); goto AGAIN2; +- case ENOTSUP: free(Gbuf); return 0; ++ case ERANGE: LINUXATTR_CONTEXT(context)->bufsz *= 2; free(LINUXATTR_CONTEXT(context)->buf); goto AGAIN2; ++ case ENOTSUP: free(LINUXATTR_CONTEXT(context)->buf); return 0; + default: break; + }; + return -1; + } +- Gbufsz = r; ++ LINUXATTR_CONTEXT(context)->bufsz = r; + } + +- if( (Gbufsz-Goff) <= len ) { ++ if( (LINUXATTR_CONTEXT(context)->bufsz-LINUXATTR_CONTEXT(context)->off) <= len ) { + int32_t ret; +- ret = Gbufsz - Goff; +- memcpy(buf, Gbuf+Goff, ret); +- Goff += ret; ++ ret = LINUXATTR_CONTEXT(context)->bufsz - LINUXATTR_CONTEXT(context)->off; ++ memcpy(buf, LINUXATTR_CONTEXT(context)->buf+LINUXATTR_CONTEXT(context)->off, ret); ++ LINUXATTR_CONTEXT(context)->off += ret; + return(ret); + } else { +- memcpy(buf, Gbuf+Goff, len); +- Gbuf += len; ++ memcpy(buf, LINUXATTR_CONTEXT(context)->buf+LINUXATTR_CONTEXT(context)->off, len); ++ LINUXATTR_CONTEXT(context)->buf += len; + return len; + } + } + +-int32_t xar_linuxattr_write(xar_t x, xar_file_t f, void *buf, size_t len) { +- return lsetxattr(Gfile, Gattr+strlen(XAR_EA_FORK)+1, buf, len, 0); ++int32_t xar_linuxattr_write(xar_t x, xar_file_t f, void *buf, size_t len, void *context) { ++ return lsetxattr(LINUXATTR_CONTEXT(context)->file, LINUXATTR_CONTEXT(context)->attr+strlen(XAR_EA_FORK)+1, buf, len, 0); + } + #endif + +@@ -130,7 +135,10 @@ + int ret, retval=0, bufsz = 1024; + struct statfs sfs; + char *fsname = NULL; +- ++ struct _linuxattr_context context; ++ ++ memset(&context,0,sizeof(struct _linuxattr_context)); ++ + TRYAGAIN: + buf = malloc(bufsz); + if(!buf) +@@ -159,18 +167,18 @@ + for( i=buf; (i-buf) < ret; i += strlen(i)+1 ) { + char tmpnam[1024]; + +- Gbufsz = 0; +- Goff = 0; +- Gbuf = NULL; +- Gfile = file; ++ LINUXATTR_CONTEXT(context)->bufsz = 0; ++ LINUXATTR_CONTEXT(context)->off = 0; ++ LINUXATTR_CONTEXT(context)->buf = NULL; ++ LINUXATTR_CONTEXT(context)->file = file; + memset(tmpnam, 0, sizeof(tmpnam)); + snprintf(tmpnam, sizeof(tmpnam)-1, "%s/%s", XAR_EA_FORK, i); + xar_prop_set(f, tmpnam, NULL); + xar_attr_set(f, tmpnam, "fstype", fsname); +- Gattr = tmpnam; ++ LINUXATTR_CONTEXT(context)->attr = tmpnam; + xar_attrcopy_to_heap(x, f, tmpnam, xar_linuxattr_read); +- free(Gbuf); +- Gattr = NULL; ++ free(LINUXATTR_CONTEXT(context)->buf); ++ LINUXATTR_CONTEXT(context)->attr = NULL; + } + + BAIL: +@@ -188,8 +196,10 @@ + struct statfs sfs; + int eaopt = 0; + xar_iter_t iter; +- +- ++ struct _linuxattr_context context; ++ ++ memset(&context,0,sizeof(struct _linuxattr_context)); ++ + /* Check for EA extraction behavior */ + + memset(&sfs, 0, sizeof(sfs)); +@@ -223,8 +233,8 @@ + if( !fs ) + continue; + +- Gfile = file; +- Gattr = prop; ++ LINUXATTR_CONTEXT(context)->file = file; ++ LINUXATTR_CONTEXT(context)->attr = prop; + xar_attrcopy_from_heap(x, f, prop, xar_linuxattr_write); + + } +diff -urN xar/lib/macho.c xar.context/lib/macho.c +--- xar/lib/macho.c 2006-02-23 23:05:04.000000000 -0800 ++++ xar.context/lib/macho.c 2006-03-17 11:15:23.000000000 -0800 +@@ -21,14 +21,17 @@ + int32_t offset; + }; + +-static int initted = 0; +-static struct arches *inflight = NULL; +-static int32_t numarches = 0; +-static int32_t curroffset = 0; ++struct _macho_context{ ++ struct arches *inflight; ++ int32_t numarches; ++ int32_t curroffset; ++}; ++ ++#define MACHO_CONTEXT(x) ((struct _macho_context *)(*x)) + + static int32_t parse_arch(xar_file_t f, struct mach_header *mh); + +-int32_t xar_macho_in(xar_t x, xar_file_t f, const char *attr, void **in, size_t *inlen) { ++int32_t xar_macho_in(xar_t x, xar_file_t f, const char *attr, void **in, size_t *inlen, void **context) { + struct mach_header *mh = *in; + struct fat_header *fh = *in; + uint32_t magic; +@@ -37,62 +40,69 @@ + if( strcmp(attr, "data") != 0 ) + return 0; + +- if( initted && (inflight != NULL) ) +- return 0; +- ++ if(!MACHO_CONTEXT(context)) ++ *context = calloc(1,sizeof(struct _macho_context)); ++ else ++ return 0; /*We only run for the first part of the data stream*/ ++ + /* First, check for fat */ + magic = htonl(fh->magic); + if( magic == 0xcafebabe ) { + struct fat_arch *fa = (struct fat_arch *)((unsigned char *)*in + sizeof(struct fat_header)); +- numarches = htonl(fh->nfat_arch); ++ MACHO_CONTEXT(context)->numarches = htonl(fh->nfat_arch); + + /* sanity check, arbitrary number */ +- if( numarches > 7 ) ++ if( MACHO_CONTEXT(context)->numarches > 7 ) + return 0; + + xar_prop_set(f, "contents/type", "Mach-O Fat File"); + +- inflight = malloc( numarches * sizeof(struct arches) ); +- if( !inflight ) ++ MACHO_CONTEXT(context)->inflight = malloc( MACHO_CONTEXT(context)->numarches * sizeof(struct arches) ); ++ if( !MACHO_CONTEXT(context)->inflight ){ ++ free(*context); + return -1; ++ } + +- for( i = 0; i < numarches; ++i ) { ++ for( i = 0; i < MACHO_CONTEXT(context)->numarches; ++i ) { + int32_t sz = htonl(fa[i].size); + int32_t off = htonl(fa[i].offset); + +- inflight[i].size = sz; +- inflight[i].offset = off; ++ MACHO_CONTEXT(context)->inflight[i].size = sz; ++ MACHO_CONTEXT(context)->inflight[i].offset = off; + } +- curroffset += *inlen; ++ MACHO_CONTEXT(context)->curroffset += *inlen; + return 0; + } + +- if( inflight ) { +- for(i = 0; i < numarches; ++i) { +- if( (inflight[i].offset >= curroffset) && (inflight[i].offset < (curroffset+*inlen)) ) { ++ if( MACHO_CONTEXT(context)->inflight ) { ++ for(i = 0; i < MACHO_CONTEXT(context)->numarches; ++i) { ++ if( (MACHO_CONTEXT(context)->inflight[i].offset >= MACHO_CONTEXT(context)->curroffset) && ++ (MACHO_CONTEXT(context)->inflight[i].offset < (MACHO_CONTEXT(context)->curroffset+*inlen)) ) { + +- mh = (struct mach_header *)((char *)*in + (inflight[i].offset - curroffset)); ++ mh = (struct mach_header *)((char *)*in + ++ (MACHO_CONTEXT(context)->inflight[i].offset - MACHO_CONTEXT(context)->curroffset)); + parse_arch(f, mh); + } + } +- curroffset += *inlen; ++ MACHO_CONTEXT(context)->curroffset += *inlen; + return 0; + } + + parse_arch(f, mh); + +- curroffset += *inlen; ++ MACHO_CONTEXT(context)->curroffset += *inlen; + + return 0; + } + +-int32_t xar_macho_done(xar_t x, xar_file_t f, const char *attr) { +- if( inflight ) +- free(inflight); +- inflight = NULL; +- curroffset = 0; +- numarches = 0; +- initted = 0; ++int32_t xar_macho_done(xar_t x, xar_file_t f, const char *attr, void **context) { ++ ++ if( MACHO_CONTEXT(context) ){ ++ if( MACHO_CONTEXT(context)->inflight ) ++ free(MACHO_CONTEXT(context)->inflight); ++ free(*context); ++ } ++ + return 0; + } + +diff -urN xar/lib/macho.h xar.context/lib/macho.h +--- xar/lib/macho.h 2006-02-23 23:05:04.000000000 -0800 ++++ xar.context/lib/macho.h 2006-03-17 11:15:27.000000000 -0800 +@@ -31,7 +31,7 @@ + uint32_t alighn; + }; + +-int32_t xar_macho_in(xar_t x, xar_file_t f, const char *attr, void **in, size_t *inlen); +-int32_t xar_macho_done(xar_t x, xar_file_t f, const char *attr); ++int32_t xar_macho_in(xar_t x, xar_file_t f, const char *attr, void **in, size_t *inlen, void **context); ++int32_t xar_macho_done(xar_t x, xar_file_t f, const char *attr, void **context); + + #endif /* _MACHO_H_ */ +diff -urN xar/lib/md5.c xar.context/lib/md5.c +--- xar/lib/md5.c 2006-02-23 23:05:04.000000000 -0800 ++++ xar.context/lib/md5.c 2006-03-17 11:38:29.000000000 -0800 +@@ -11,77 +11,112 @@ + #endif + #include "xar.h" + +-static EVP_MD_CTX src_ctx, dst_ctx; +-static int initted = 0; ++struct _md5_context{ ++ EVP_MD_CTX src_ctx; ++ EVP_MD_CTX dst_ctx; ++ uint8_t src; ++ uint8_t dst; ++}; ++ ++#define CONTEXT(x) ((struct _md5_context *)(*x)) + + static char* xar_format_md5(const unsigned char* m); + +-int32_t xar_md5_uncompressed(xar_t x, xar_file_t f, const char *attr, void **in, size_t *inlen) { ++int32_t xar_md5_uncompressed(xar_t x, xar_file_t f, const char *attr, void **in, size_t *inlen, void **context) { + const EVP_MD *md; +- +- if( !initted ) { ++ ++ if(!context) ++ return 0; ++ ++ if(!CONTEXT(context)){ ++ *context = calloc(1,sizeof(struct _md5_context)); + OpenSSL_add_all_digests(); ++ } ++ ++ if( !CONTEXT(context)->src ){ + md = EVP_get_digestbyname("md5"); + if( md == NULL ) return -1; +- EVP_DigestInit(&src_ctx, md); +- EVP_DigestInit(&dst_ctx, md); +- initted = 1; ++ EVP_DigestInit(&(CONTEXT(context)->src_ctx), md); ++ CONTEXT(context)->src = 1; + } +- ++ + if( *inlen == 0 ) + return 0; +- +- EVP_DigestUpdate(&src_ctx, *in, *inlen); ++ ++ EVP_DigestUpdate(&(CONTEXT(context)->src_ctx), *in, *inlen); + return 0; + } + +-int32_t xar_md5_compressed(xar_t x, xar_file_t f, const char *attr, void *in, size_t inlen) { ++int32_t xar_md5_compressed(xar_t x, xar_file_t f, const char *attr, void *in, size_t inlen, void **context) { + const EVP_MD *md; +- +- if( !initted ) { ++ ++ if(!context) ++ return 0; ++ ++ if(!CONTEXT(context)){ ++ *context = calloc(1,sizeof(struct _md5_context)); + OpenSSL_add_all_digests(); ++ } ++ ++ if( !CONTEXT(context)->dst ){ + md = EVP_get_digestbyname("md5"); + if( md == NULL ) return -1; +- EVP_DigestInit(&src_ctx, md); +- EVP_DigestInit(&dst_ctx, md); +- initted = 1; ++ EVP_DigestInit(&(CONTEXT(context)->dst_ctx), md); ++ CONTEXT(context)->dst = 1; + } +- ++ + if( inlen == 0 ) + return 0; +- +- EVP_DigestUpdate(&dst_ctx, in, inlen); ++ ++ EVP_DigestUpdate(&(CONTEXT(context)->src_ctx), in, inlen); + return 0; + } + +-int32_t xar_md5_done(xar_t x, xar_file_t f, const char *attr) { ++int32_t xar_md5_done(xar_t x, xar_file_t f, const char *attr, void **context) { + unsigned char md5str[EVP_MAX_MD_SIZE]; + char *str, *tmpstr; + unsigned int len; +- +- memset(md5str, 0, sizeof(md5str)); +- EVP_DigestFinal(&src_ctx, md5str, &len); +- str = xar_format_md5(md5str); +- asprintf(&tmpstr, "%s/extracted-checksum", attr); +- if( f ) { +- xar_prop_set(f, tmpstr, str); +- xar_attr_set(f, tmpstr, "style", "md5"); ++ ++ if(!CONTEXT(context)) ++ return 0; ++ ++ if( CONTEXT(context)->src ){ ++ EVP_MD_CTX *ctx = &CONTEXT(context)->src_ctx; ++ const EVP_MD *md = EVP_MD_CTX_md(ctx); ++ ++ memset(md5str, 0, sizeof(md5str)); ++ EVP_DigestFinal(&(CONTEXT(context)->src_ctx), md5str, &len); ++ str = xar_format_md5(md5str); ++ asprintf(&tmpstr, "%s/extracted-checksum", attr); ++ if( f ) { ++ xar_prop_set(f, tmpstr, str); ++ xar_attr_set(f, tmpstr, "style", "md5"); ++ } ++ free(tmpstr); ++ free(str); + } +- free(tmpstr); +- free(str); +- +- memset(md5str, 0, sizeof(md5str)); +- EVP_DigestFinal(&dst_ctx, md5str, &len); +- str = xar_format_md5(md5str); +- asprintf(&tmpstr, "%s/archived-checksum", attr); +- if( f ) { +- xar_prop_set(f, tmpstr, str); +- xar_attr_set(f, tmpstr, "style", "md5"); ++ ++ if( CONTEXT(context)->dst ){ ++ EVP_MD_CTX *ctx = &CONTEXT(context)->dst_ctx; ++ const EVP_MD *md = EVP_MD_CTX_md(ctx); ++ ++ memset(md5str, 0, sizeof(md5str)); ++ EVP_DigestFinal(&(CONTEXT(context)->dst_ctx), md5str, &len); ++ str = xar_format_md5(md5str); ++ asprintf(&tmpstr, "%s/archived-checksum", attr); ++ if( f ) { ++ xar_prop_set(f, tmpstr, str); ++ xar_attr_set(f, tmpstr, "style", "md5"); ++ } ++ free(tmpstr); ++ free(str); + } +- free(tmpstr); +- free(str); +- +- initted = 0; ++ ++ if(*context){ ++ free(*context); ++ *context = NULL; ++ } ++ + return 0; + } + +@@ -99,33 +134,46 @@ + return result; + } + +-int32_t xar_md5out_done(xar_t x, xar_file_t f, const char *attr) { ++int32_t xar_md5out_done(xar_t x, xar_file_t f, const char *attr, void **context) { + const char *uncomp, *uncompstyle; + unsigned char md5str[EVP_MAX_MD_SIZE]; + unsigned int len; + char *tmpstr; +- ++ ++ if(!CONTEXT(context)) ++ return 0; ++ ++ if( !(CONTEXT(context)->dst || CONTEXT(context)->src) ){ ++ return 0; ++ } ++ + asprintf(&tmpstr, "%s/extracted-checksum", attr); + xar_prop_get(f, tmpstr, &uncomp); + uncompstyle = xar_attr_get(f, tmpstr, "style"); + free(tmpstr); +- +- if( uncomp && uncompstyle && (strcmp(uncompstyle, "md5")==0) ) { ++ ++ if( uncomp && uncompstyle && CONTEXT(context)->dst ) { + char *str; + memset(md5str, 0, sizeof(md5str)); +- EVP_DigestFinal(&dst_ctx, md5str, &len); ++ EVP_DigestFinal(&(CONTEXT(context)->dst_ctx), md5str, &len); + str = xar_format_md5(md5str); + if(strcmp(uncomp, str) != 0) { + xar_err_new(x); + xar_err_set_file(x, f); +- xar_err_set_string(x, "extracted-checksum MD5's do not match"); ++ asprintf(&tmpstr, "extracted-checksum MD5's do not match"); + xar_err_callback(x, XAR_SEVERITY_FATAL, XAR_ERR_ARCHIVE_EXTRACTION); + } + free(str); + } +- +- EVP_DigestFinal(&src_ctx, md5str, &len); +- initted = 0; +- ++ ++ if( CONTEXT(context)->src ) ++ EVP_DigestFinal(&(CONTEXT(context)->src_ctx), md5str, &len); ++ ++ if(*context){ ++ free(*context); ++ *context = NULL; ++ } ++ + return 0; ++ + } +diff -urN xar/lib/md5.h xar.context/lib/md5.h +--- xar/lib/md5.h 2006-02-17 11:27:10.000000000 -0800 ++++ xar.context/lib/md5.h 2006-03-17 11:32:14.000000000 -0800 +@@ -34,9 +34,9 @@ + #ifndef _XAR_MD5_H_ + #define _XAR_MD5_H_ + +-int32_t xar_md5_compressed(xar_t x, xar_file_t f, const char *, void *in, size_t inlen); +-int32_t xar_md5_uncompressed(xar_t x, xar_file_t f, const char *, void **in, size_t *inlen); +-int32_t xar_md5_done(xar_t x, xar_file_t f, const char *); +-int32_t xar_md5out_done(xar_t x, xar_file_t f, const char *); ++int32_t xar_md5_compressed(xar_t x, xar_file_t f, const char *, void *in, size_t inlen, void **context); ++int32_t xar_md5_uncompressed(xar_t x, xar_file_t f, const char *, void **in, size_t *inlen, void **context); ++int32_t xar_md5_done(xar_t x, xar_file_t f, const char *, void **context); ++int32_t xar_md5out_done(xar_t x, xar_file_t f, const char *, void **context); + + #endif /* _XAR_MD5_H_ */ +diff -urN xar/lib/script.c xar.context/lib/script.c +--- xar/lib/script.c 2006-02-23 23:05:04.000000000 -0800 ++++ xar.context/lib/script.c 2006-03-17 11:15:45.000000000 -0800 +@@ -9,14 +9,25 @@ + #endif + #include "xar.h" + +-static int initted = 0; ++struct _script_context{ ++ int initted; ++}; + +-int32_t xar_script_in(xar_t x, xar_file_t f, const char *attr, void **in, size_t *inlen) { ++#define SCRIPT_CONTEXT(x) ((struct _script_context*)(*x)) ++ ++int32_t xar_script_in(xar_t x, xar_file_t f, const char *attr, void **in, size_t *inlen, void **context) { + char *buf = *in; + +- if( initted ) ++ if(!SCRIPT_CONTEXT(context)){ ++ *context = calloc(1,sizeof(struct _script_context)); ++ } ++ ++ if( SCRIPT_CONTEXT(context)->initted ) + return 0; + ++ /*We only run on the begining of the file, so once we init, we don't run again*/ ++ SCRIPT_CONTEXT(context)->initted = 1; ++ + if( (*inlen > 2) && (buf[0] == '#') && (buf[1] == '!') ) { + char *exe; + int i; +@@ -37,7 +48,16 @@ + return 0; + } + +-int32_t xar_script_done(xar_t x, xar_file_t f, const char *attr) { +- initted = 0; ++int32_t xar_script_done(xar_t x, xar_file_t f, const char *attr, void **context) { ++ ++ if(!SCRIPT_CONTEXT(context)){ ++ return 0; ++ } ++ ++ if( *context ){ ++ free(*context); ++ *context = NULL; ++ } ++ + return 0; + } +diff -urN xar/lib/script.h xar.context/lib/script.h +--- xar/lib/script.h 2006-02-23 23:05:04.000000000 -0800 ++++ xar.context/lib/script.h 2006-03-17 11:15:48.000000000 -0800 +@@ -1,7 +1,7 @@ + #ifndef _SCRIPT_H_ + #define _SCRIPT_H_ + +-int32_t xar_script_in(xar_t x, xar_file_t f, const char *attr, void **in, size_t *inlen); +-int32_t xar_script_done(xar_t x, xar_file_t f, const char *attr); ++int32_t xar_script_in(xar_t x, xar_file_t f, const char *attr, void **in, size_t *inlen, void **context); ++int32_t xar_script_done(xar_t x, xar_file_t f, const char *attr, void **context); + + #endif /* _SCRIPT_H_ */ +diff -urN xar/lib/zxar.c xar.context/lib/zxar.c +--- xar/lib/zxar.c 2006-02-17 11:27:10.000000000 -0800 ++++ xar.context/lib/zxar.c 2006-03-17 11:16:23.000000000 -0800 +@@ -44,12 +44,10 @@ + #include "filetree.h" + #include "io.h" + +-static int initted = 0; +-static z_stream zs; ++#define GZIP_CONTEXT(x) ((z_stream *)(*x)) ++int xar_gzip_fromheap_done(xar_t x, xar_file_t f, const char *attr, void **context); + +-int xar_gzip_fromheap_done(xar_t x, xar_file_t f, const char *attr); +- +-int xar_gzip_fromheap_in(xar_t x, xar_file_t f, const char *attr, void **in, size_t *inlen) { ++int xar_gzip_fromheap_in(xar_t x, xar_file_t f, const char *attr, void **in, size_t *inlen, void **context) { + const char *opt; + void *out = NULL; + size_t outlen, offset = 0; +@@ -62,31 +60,27 @@ + if( !opt ) return 0; + if( strcmp(opt, "application/x-gzip") != 0 ) return 0; + +- if( !initted ) { +- zs.zalloc = Z_NULL; +- zs.zfree = Z_NULL; +- zs.opaque = Z_NULL; +- +- inflateInit(&zs); +- initted = 1; ++ if( !GZIP_CONTEXT(context) ) { ++ *context = calloc(1,sizeof(z_stream)); ++ inflateInit(GZIP_CONTEXT(context)); + } + + outlen = *inlen; + +- zs.next_in = *in; +- zs.avail_in = *inlen; +- zs.next_out = out; +- zs.avail_out = 0; ++ GZIP_CONTEXT(context)->next_in = *in; ++ GZIP_CONTEXT(context)->avail_in = *inlen; ++ GZIP_CONTEXT(context)->next_out = out; ++ GZIP_CONTEXT(context)->avail_out = 0; + +- while( zs.avail_in != 0 ) { ++ while( GZIP_CONTEXT(context)->avail_in != 0 ) { + outlen = outlen * 2; + out = realloc(out, outlen); + if( out == NULL ) abort(); + +- zs.next_out = out + offset; +- zs.avail_out = outlen - offset; ++ GZIP_CONTEXT(context)->next_out = out + offset; ++ GZIP_CONTEXT(context)->avail_out = outlen - offset; + +- r = inflate(&zs, Z_SYNC_FLUSH); ++ r = inflate(GZIP_CONTEXT(context), Z_SYNC_FLUSH); + if( (r != Z_OK) && (r != Z_STREAM_END) ) { + xar_err_new(x); + xar_err_set_file(x, f); +@@ -94,11 +88,11 @@ + xar_err_callback(x, XAR_SEVERITY_FATAL, XAR_ERR_ARCHIVE_EXTRACTION); + return -1; + } +- offset += outlen - offset - zs.avail_out; ++ offset += outlen - offset - GZIP_CONTEXT(context)->avail_out; + if( (r == Z_STREAM_END) && (offset == 0) ) { +- //r = inflate(&zs, Z_FINISH); +- xar_gzip_fromheap_done(x, f, attr); +- offset += outlen - offset - zs.avail_out; ++ //r = inflate(GZIP_CONTEXT(context), Z_FINISH); ++ xar_gzip_fromheap_done(x, f, attr, context); ++ offset += outlen - offset - GZIP_CONTEXT(context)->avail_out; + break; + } + } +@@ -109,12 +103,17 @@ + return 0; + } + +-int xar_gzip_fromheap_done(xar_t x, xar_file_t f, const char *attr) { +- initted = 0; +- inflateEnd(&zs); ++int xar_gzip_fromheap_done(xar_t x, xar_file_t f, const char *attr, void **context) { ++ inflateEnd(GZIP_CONTEXT(context)); ++ ++ if(GZIP_CONTEXT(context)){ ++ free(GZIP_CONTEXT(context)); ++ *context = NULL; ++ } ++ + return 0; + } +-int xar_gzip_toheap_done(xar_t x, xar_file_t f, const char *attr) { ++int xar_gzip_toheap_done(xar_t x, xar_file_t f, const char *attr, void **context) { + const char *opt; + char *tmpstr; + +@@ -124,10 +123,14 @@ + + if( strcmp(opt, XAR_OPT_VAL_GZIP) != 0 ) + return 0; ++ ++ deflateEnd(GZIP_CONTEXT(context)); + +- initted = 0; +- deflateEnd(&zs); +- ++ if(GZIP_CONTEXT(context)){ ++ free(GZIP_CONTEXT(context)); ++ *context = NULL; ++ } ++ + asprintf(&tmpstr, "%s/encoding", attr); + if( f ) { + xar_prop_set(f, tmpstr, NULL); +@@ -138,7 +141,7 @@ + return 0; + } + +-int32_t xar_gzip_toheap_in(xar_t x, xar_file_t f, const char *attr, void **in, size_t *inlen) { ++int32_t xar_gzip_toheap_in(xar_t x, xar_file_t f, const char *attr, void **in, size_t *inlen, void **context) { + void *out = NULL; + size_t outlen, offset = 0; + int r; +@@ -151,33 +154,32 @@ + if( strcmp(opt, XAR_OPT_VAL_GZIP) != 0 ) + return 0; + +- if( !initted ) { +- memset(&zs, 0, sizeof(zs)); +- deflateInit(&zs, Z_BEST_COMPRESSION); +- initted = 1; ++ if( !GZIP_CONTEXT(context) ) { ++ *context = calloc(1,sizeof(z_stream)); ++ deflateInit(GZIP_CONTEXT(context), Z_BEST_COMPRESSION); + } +- ++ + outlen = *inlen/2; + if(outlen == 0) outlen = 1024; +- zs.next_in = *in; +- zs.avail_in = *inlen; +- zs.next_out = out; +- zs.avail_out = 0; ++ GZIP_CONTEXT(context)->next_in = *in; ++ GZIP_CONTEXT(context)->avail_in = *inlen; ++ GZIP_CONTEXT(context)->next_out = out; ++ GZIP_CONTEXT(context)->avail_out = 0; + + do { + outlen *= 2; + out = realloc(out, outlen); + if( out == NULL ) abort(); + +- zs.next_out = out + offset; +- zs.avail_out = outlen - offset; ++ GZIP_CONTEXT(context)->next_out = out + offset; ++ GZIP_CONTEXT(context)->avail_out = outlen - offset; + + if( *inlen == 0 ) +- r = deflate(&zs, Z_FINISH); ++ r = deflate(GZIP_CONTEXT(context), Z_FINISH); + else +- r = deflate(&zs, Z_SYNC_FLUSH); +- offset = outlen - zs.avail_out; +- } while( zs.avail_in != 0 ); ++ r = deflate(GZIP_CONTEXT(context), Z_SYNC_FLUSH); ++ offset = outlen - GZIP_CONTEXT(context)->avail_out; ++ } while( GZIP_CONTEXT(context)->avail_in != 0 ); + + free(*in); + *in = out; +diff -urN xar/lib/zxar.h xar.context/lib/zxar.h +--- xar/lib/zxar.h 2006-02-17 11:27:10.000000000 -0800 ++++ xar.context/lib/zxar.h 2006-03-17 11:16:27.000000000 -0800 +@@ -34,10 +34,10 @@ + #ifndef _XAR_ZLIB_H_ + #define _XAR_ZLIB_H_ + +-int xar_gzip_fromheap_in(xar_t x, xar_file_t f, const char *, void **in, size_t *inlen); +-int xar_gzip_fromheap_done(xar_t x, xar_file_t f, const char *); ++int xar_gzip_fromheap_in(xar_t x, xar_file_t f, const char *, void **in, size_t *inlen, void **context); ++int xar_gzip_fromheap_done(xar_t x, xar_file_t f, const char *, void **context); + +-int32_t xar_gzip_toheap_in(xar_t x, xar_file_t f, const char *, void **in, size_t *inlen); +-int xar_gzip_toheap_done(xar_t x, xar_file_t f, const char *); ++int32_t xar_gzip_toheap_in(xar_t x, xar_file_t f, const char *, void **in, size_t *inlen, void **context); ++int xar_gzip_toheap_done(xar_t x, xar_file_t f, const char *, void **context); + + #endif /* _XAR_ZLIB_H_ */ diff --git a/patches/hash.diff b/patches/hash.diff new file mode 100644 index 0000000..571936e --- /dev/null +++ b/patches/hash.diff @@ -0,0 +1,551 @@ +diff -urN xar/include/xar.h.in xar.hash/include/xar.h.in +--- xar/include/xar.h.in 2006-03-19 20:57:56.000000000 -0800 ++++ xar.hash/include/xar.h.in 2006-03-19 20:58:35.000000000 -0800 +@@ -38,6 +38,7 @@ + + #include + #include ++#include + + struct xar_header { + uint32_t magic; +@@ -71,7 +72,8 @@ + #define XAR_OPT_VAL_SYMBOLIC "symbolic" /* set owner/group based on names */ + #define XAR_OPT_VAL_NUMERIC "numeric" /* set owner/group based on uid/gid */ + +-#define XAR_OPT_TOCCKSUM "toc-cksum" /* set the toc checksum algorithm */ ++#define XAR_OPT_TOCCKSUM "toc-cksum" /* set the toc checksum algorithm */ ++#define XAR_OPT_FILECKSUM "file-chksum" /* set the file checksum algorithm */ + #define XAR_OPT_VAL_NONE "none" + #define XAR_OPT_VAL_SHA1 "sha1" + #define XAR_OPT_VAL_MD5 "md5" +diff -urN xar/lib/Makefile.inc.in xar.hash/lib/Makefile.inc.in +--- xar/lib/Makefile.inc.in 2006-03-19 20:57:56.000000000 -0800 ++++ xar.hash/lib/Makefile.inc.in 2006-03-19 20:58:35.000000000 -0800 +@@ -16,7 +16,7 @@ + + # Sources. + LIBXAR_SRCS := archive.c arcmod.c b64.c bzxar.c darwinattr.c data.c err.c +-LIBXAR_SRCS += ext2.c fbsdattr.c filetree.c io.c linuxattr.c md5.c stat.c ++LIBXAR_SRCS += ext2.c fbsdattr.c filetree.c io.c linuxattr.c hash.c stat.c + LIBXAR_SRCS += subdoc.c util.c zxar.c script.c macho.c + + LIBXAR_SRCS := $(patsubst %, @srcroot@lib/%, $(LIBXAR_SRCS)) +diff -urN xar/lib/hash.c xar.hash/lib/hash.c +--- xar/lib/hash.c 1969-12-31 16:00:00.000000000 -0800 ++++ xar.hash/lib/hash.c 2006-03-19 20:58:51.000000000 -0800 +@@ -0,0 +1,210 @@ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "config.h" ++#ifndef HAVE_ASPRINTF ++#include "asprintf.h" ++#endif ++#include "xar.h" ++ ++ ++struct _hash_context{ ++ EVP_MD_CTX src_ctx; ++ EVP_MD_CTX dst_ctx; ++ uint8_t src; ++ uint8_t dst; ++}; ++ ++#define CONTEXT(x) ((struct _hash_context *)(*x)) ++ ++static char* xar_format_hash(const unsigned char* m,unsigned int len); ++ ++int32_t xar_hash_uncompressed(xar_t x, xar_file_t f, const char *attr, void **in, size_t *inlen, void **context) { ++ const char *opt; ++ char *tmpstr; ++ const EVP_MD *md; ++ ++ if(!context) ++ return 0; ++ ++ asprintf(&tmpstr, "%s/extracted-checksum", attr); ++ opt = xar_attr_get(f, tmpstr, "style"); ++ free(tmpstr); ++ ++ if( !opt ) ++ opt = xar_opt_get(x, XAR_OPT_FILECKSUM); ++ ++ if( !opt || (0 == strcmp(opt, XAR_OPT_VAL_NONE) ) ) ++ return 0; ++ ++ if(!CONTEXT(context)){ ++ *context = calloc(1,sizeof(struct _hash_context)); ++ OpenSSL_add_all_digests(); ++ } ++ ++ if( !CONTEXT(context)->src ){ ++ md = EVP_get_digestbyname(opt); ++ if( md == NULL ) return -1; ++ EVP_DigestInit(&(CONTEXT(context)->src_ctx), md); ++ CONTEXT(context)->src = 1; ++ } ++ ++ if( *inlen == 0 ) ++ return 0; ++ ++ EVP_DigestUpdate(&(CONTEXT(context)->src_ctx), *in, *inlen); ++ return 0; ++} ++ ++int32_t xar_hash_compressed(xar_t x, xar_file_t f, const char *attr, void *in, size_t inlen, void **context) { ++ const char *opt; ++ const EVP_MD *md; ++ char *tmpstr; ++ ++ if(!context) ++ return 0; ++ ++ asprintf(&tmpstr, "%s/archived-checksum", attr); ++ opt = xar_attr_get(f, tmpstr, "style"); ++ free(tmpstr); ++ ++ if( !opt ) ++ opt = xar_opt_get(x, XAR_OPT_FILECKSUM); ++ ++ if( !opt || (0 == strcmp(opt, XAR_OPT_VAL_NONE) ) ) ++ return 0; ++ ++ if(!CONTEXT(context)){ ++ *context = calloc(1,sizeof(struct _hash_context)); ++ OpenSSL_add_all_digests(); ++ } ++ ++ if ( !CONTEXT(context)->dst ){ ++ md = EVP_get_digestbyname(opt); ++ if( md == NULL ) return -1; ++ EVP_DigestInit(&(CONTEXT(context)->dst_ctx), md); ++ CONTEXT(context)->dst = 1; ++ } ++ ++ if( inlen == 0 ) ++ return 0; ++ ++ EVP_DigestUpdate(&(CONTEXT(context)->dst_ctx), in, inlen); ++ return 0; ++} ++ ++int32_t xar_hash_done(xar_t x, xar_file_t f, const char *attr, void **context) { ++ unsigned char hashstr[EVP_MAX_MD_SIZE]; ++ char *str, *tmpstr; ++ unsigned int len; ++ ++ if(!CONTEXT(context)) ++ return 0; ++ ++ if( CONTEXT(context)->src ){ ++ EVP_MD_CTX *ctx = &CONTEXT(context)->src_ctx; ++ const EVP_MD *md = EVP_MD_CTX_md(ctx); ++ const char *type = EVP_MD_name(md); ++ ++ memset(hashstr, 0, sizeof(hashstr)); ++ EVP_DigestFinal(&(CONTEXT(context)->src_ctx), hashstr, &len); ++ str = xar_format_hash(hashstr,len); ++ asprintf(&tmpstr, "%s/extracted-checksum", attr); ++ if( f ) { ++ xar_prop_set(f, tmpstr, str); ++ xar_attr_set(f, tmpstr, "style", type); ++ } ++ free(tmpstr); ++ free(str); ++ } ++ ++ if( CONTEXT(context)->dst ){ ++ EVP_MD_CTX *ctx = &CONTEXT(context)->dst_ctx; ++ const EVP_MD *md = EVP_MD_CTX_md(ctx); ++ const char *type = EVP_MD_name(md); ++ ++ memset(hashstr, 0, sizeof(hashstr)); ++ EVP_DigestFinal(&(CONTEXT(context)->dst_ctx), hashstr, &len); ++ str = xar_format_hash(hashstr,len); ++ asprintf(&tmpstr, "%s/archived-checksum", attr); ++ if( f ) { ++ xar_prop_set(f, tmpstr, str); ++ xar_attr_set(f, tmpstr, "style", type); ++ } ++ free(tmpstr); ++ free(str); ++ } ++ ++ if(*context){ ++ free(*context); ++ *context = NULL; ++ } ++ ++ return 0; ++} ++ ++static char* xar_format_hash(const unsigned char* m,unsigned int len) { ++ char* result = malloc((2*len)+1); ++ char hexValue[3]; ++ unsigned int itr = 0; ++ ++ result[0] = '\0'; ++ ++ for(itr = 0;itr < len;itr++){ ++ sprintf(hexValue,"%02x",m[itr]); ++ strncat(result,hexValue,2); ++ } ++ ++ return result; ++} ++ ++int32_t xar_hash_out_done(xar_t x, xar_file_t f, const char *attr, void **context) { ++ const char *uncomp, *uncompstyle; ++ unsigned char hashstr[EVP_MAX_MD_SIZE]; ++ unsigned int len; ++ char *tmpstr; ++ const EVP_MD *md; ++ ++ if(!CONTEXT(context)) ++ return 0; ++ ++ if( !(CONTEXT(context)->dst || CONTEXT(context)->src) ){ ++ return 0; ++ } ++ ++ asprintf(&tmpstr, "%s/extracted-checksum", attr); ++ xar_prop_get(f, tmpstr, &uncomp); ++ uncompstyle = xar_attr_get(f, tmpstr, "style"); ++ free(tmpstr); ++ ++ md = EVP_get_digestbyname(uncompstyle); ++ ++ if( uncomp && uncompstyle && md && CONTEXT(context)->dst ) { ++ char *str; ++ memset(hashstr, 0, sizeof(hashstr)); ++ EVP_DigestFinal(&(CONTEXT(context)->dst_ctx), hashstr, &len); ++ str = xar_format_hash(hashstr,len); ++ if(strcmp(uncomp, str) != 0) { ++ xar_err_new(x); ++ xar_err_set_file(x, f); ++ asprintf(&tmpstr, "extracted-checksum %s's do not match",uncompstyle); ++ xar_err_set_string(x, tmpstr); ++ xar_err_callback(x, XAR_SEVERITY_FATAL, XAR_ERR_ARCHIVE_EXTRACTION); ++ } ++ free(str); ++ } ++ ++ if( CONTEXT(context)->src ) ++ EVP_DigestFinal(&(CONTEXT(context)->src_ctx), hashstr, &len); ++ ++ if(*context){ ++ free(*context); ++ *context = NULL; ++ } ++ ++ return 0; ++} +diff -urN xar/lib/hash.h xar.hash/lib/hash.h +--- xar/lib/hash.h 1969-12-31 16:00:00.000000000 -0800 ++++ xar.hash/lib/hash.h 2006-03-19 20:58:35.000000000 -0800 +@@ -0,0 +1,42 @@ ++/* ++ * Copyright (c) 2005 Rob Braun ++ * All rights reserved. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions ++ * are met: ++ * 1. Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * 2. Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in the ++ * documentation and/or other materials provided with the distribution. ++ * 3. Neither the name of Rob Braun nor the names of his contributors ++ * may be used to endorse or promote products derived from this software ++ * without specific prior written permission. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" ++ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE ++ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR ++ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF ++ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS ++ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN ++ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ++ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE ++ * POSSIBILITY OF SUCH DAMAGE. ++ */ ++/* ++ * 03-Apr-2005 ++ * DRI: Rob Braun ++ */ ++ ++#ifndef _XAR_HASH_H_ ++#define _XAR_HASH_H_ ++ ++int32_t xar_hash_compressed(xar_t x, xar_file_t f, const char *, void *in, size_t inlen, void **context); ++int32_t xar_hash_uncompressed(xar_t x, xar_file_t f, const char *, void **in, size_t *inlen, void **context); ++int32_t xar_hash_done(xar_t x, xar_file_t f, const char *, void **context); ++int32_t xar_hash_out_done(xar_t x, xar_file_t f, const char *, void **context); ++ ++#endif /* _XAR_HASH_H_ */ +diff -urN xar/lib/io.c xar.hash/lib/io.c +--- xar/lib/io.c 2006-03-19 20:58:13.000000000 -0800 ++++ xar.hash/lib/io.c 2006-03-19 20:58:35.000000000 -0800 +@@ -54,7 +54,7 @@ + #include "io.h" + #include "zxar.h" + #include "bzxar.h" +-#include "md5.h" ++#include "hash.h" + #include "script.h" + #include "macho.h" + +@@ -68,11 +68,11 @@ + + struct datamod xar_datamods[] = { + { (fromheap_in)NULL, +- xar_md5_compressed, +- xar_md5out_done, +- xar_md5_uncompressed, +- xar_md5_compressed, +- xar_md5_done ++ xar_hash_compressed, ++ xar_hash_out_done, ++ xar_hash_uncompressed, ++ xar_hash_compressed, ++ xar_hash_done + }, + { (fromheap_in)NULL, + (fromheap_out)NULL, +diff -urN xar/lib/md5.c xar.hash/lib/md5.c +--- xar/lib/md5.c 2006-03-19 20:58:13.000000000 -0800 ++++ xar.hash/lib/md5.c 1969-12-31 16:00:00.000000000 -0800 +@@ -1,179 +0,0 @@ +-#include +-#include +-#include +-#include +-#include +-#include +- +-#include "config.h" +-#ifndef HAVE_ASPRINTF +-#include "asprintf.h" +-#endif +-#include "xar.h" +- +-struct _md5_context{ +- EVP_MD_CTX src_ctx; +- EVP_MD_CTX dst_ctx; +- uint8_t src; +- uint8_t dst; +-}; +- +-#define CONTEXT(x) ((struct _md5_context *)(*x)) +- +-static char* xar_format_md5(const unsigned char* m); +- +-int32_t xar_md5_uncompressed(xar_t x, xar_file_t f, const char *attr, void **in, size_t *inlen, void **context) { +- const EVP_MD *md; +- +- if(!context) +- return 0; +- +- if(!CONTEXT(context)){ +- *context = calloc(1,sizeof(struct _md5_context)); +- OpenSSL_add_all_digests(); +- } +- +- if( !CONTEXT(context)->src ){ +- md = EVP_get_digestbyname("md5"); +- if( md == NULL ) return -1; +- EVP_DigestInit(&(CONTEXT(context)->src_ctx), md); +- CONTEXT(context)->src = 1; +- } +- +- if( *inlen == 0 ) +- return 0; +- +- EVP_DigestUpdate(&(CONTEXT(context)->src_ctx), *in, *inlen); +- return 0; +-} +- +-int32_t xar_md5_compressed(xar_t x, xar_file_t f, const char *attr, void *in, size_t inlen, void **context) { +- const EVP_MD *md; +- +- if(!context) +- return 0; +- +- if(!CONTEXT(context)){ +- *context = calloc(1,sizeof(struct _md5_context)); +- OpenSSL_add_all_digests(); +- } +- +- if( !CONTEXT(context)->dst ){ +- md = EVP_get_digestbyname("md5"); +- if( md == NULL ) return -1; +- EVP_DigestInit(&(CONTEXT(context)->dst_ctx), md); +- CONTEXT(context)->dst = 1; +- } +- +- if( inlen == 0 ) +- return 0; +- +- EVP_DigestUpdate(&(CONTEXT(context)->src_ctx), in, inlen); +- return 0; +-} +- +-int32_t xar_md5_done(xar_t x, xar_file_t f, const char *attr, void **context) { +- unsigned char md5str[EVP_MAX_MD_SIZE]; +- char *str, *tmpstr; +- unsigned int len; +- +- if(!CONTEXT(context)) +- return 0; +- +- if( CONTEXT(context)->src ){ +- EVP_MD_CTX *ctx = &CONTEXT(context)->src_ctx; +- const EVP_MD *md = EVP_MD_CTX_md(ctx); +- +- memset(md5str, 0, sizeof(md5str)); +- EVP_DigestFinal(&(CONTEXT(context)->src_ctx), md5str, &len); +- str = xar_format_md5(md5str); +- asprintf(&tmpstr, "%s/extracted-checksum", attr); +- if( f ) { +- xar_prop_set(f, tmpstr, str); +- xar_attr_set(f, tmpstr, "style", "md5"); +- } +- free(tmpstr); +- free(str); +- } +- +- if( CONTEXT(context)->dst ){ +- EVP_MD_CTX *ctx = &CONTEXT(context)->dst_ctx; +- const EVP_MD *md = EVP_MD_CTX_md(ctx); +- +- memset(md5str, 0, sizeof(md5str)); +- EVP_DigestFinal(&(CONTEXT(context)->dst_ctx), md5str, &len); +- str = xar_format_md5(md5str); +- asprintf(&tmpstr, "%s/archived-checksum", attr); +- if( f ) { +- xar_prop_set(f, tmpstr, str); +- xar_attr_set(f, tmpstr, "style", "md5"); +- } +- free(tmpstr); +- free(str); +- } +- +- if(*context){ +- free(*context); +- *context = NULL; +- } +- +- return 0; +-} +- +-static char* xar_format_md5(const unsigned char* m) { +- char* result = NULL; +- asprintf(&result, +- "%02x%02x%02x%02x" +- "%02x%02x%02x%02x" +- "%02x%02x%02x%02x" +- "%02x%02x%02x%02x", +- m[0], m[1], m[2], m[3], +- m[4], m[5], m[6], m[7], +- m[8], m[9], m[10], m[11], +- m[12], m[13], m[14], m[15]); +- return result; +-} +- +-int32_t xar_md5out_done(xar_t x, xar_file_t f, const char *attr, void **context) { +- const char *uncomp, *uncompstyle; +- unsigned char md5str[EVP_MAX_MD_SIZE]; +- unsigned int len; +- char *tmpstr; +- +- if(!CONTEXT(context)) +- return 0; +- +- if( !(CONTEXT(context)->dst || CONTEXT(context)->src) ){ +- return 0; +- } +- +- asprintf(&tmpstr, "%s/extracted-checksum", attr); +- xar_prop_get(f, tmpstr, &uncomp); +- uncompstyle = xar_attr_get(f, tmpstr, "style"); +- free(tmpstr); +- +- if( uncomp && uncompstyle && CONTEXT(context)->dst ) { +- char *str; +- memset(md5str, 0, sizeof(md5str)); +- EVP_DigestFinal(&(CONTEXT(context)->dst_ctx), md5str, &len); +- str = xar_format_md5(md5str); +- if(strcmp(uncomp, str) != 0) { +- xar_err_new(x); +- xar_err_set_file(x, f); +- asprintf(&tmpstr, "extracted-checksum MD5's do not match"); +- xar_err_callback(x, XAR_SEVERITY_FATAL, XAR_ERR_ARCHIVE_EXTRACTION); +- } +- free(str); +- } +- +- if( CONTEXT(context)->src ) +- EVP_DigestFinal(&(CONTEXT(context)->src_ctx), md5str, &len); +- +- if(*context){ +- free(*context); +- *context = NULL; +- } +- +- return 0; +- +-} +diff -urN xar/lib/md5.h xar.hash/lib/md5.h +--- xar/lib/md5.h 2006-03-19 20:58:13.000000000 -0800 ++++ xar.hash/lib/md5.h 1969-12-31 16:00:00.000000000 -0800 +@@ -1,42 +0,0 @@ +-/* +- * Copyright (c) 2005 Rob Braun +- * All rights reserved. +- * +- * Redistribution and use in source and binary forms, with or without +- * modification, are permitted provided that the following conditions +- * are met: +- * 1. Redistributions of source code must retain the above copyright +- * notice, this list of conditions and the following disclaimer. +- * 2. Redistributions in binary form must reproduce the above copyright +- * notice, this list of conditions and the following disclaimer in the +- * documentation and/or other materials provided with the distribution. +- * 3. Neither the name of Rob Braun nor the names of his contributors +- * may be used to endorse or promote products derived from this software +- * without specific prior written permission. +- * +- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +- * POSSIBILITY OF SUCH DAMAGE. +- */ +-/* +- * 03-Apr-2005 +- * DRI: Rob Braun +- */ +- +-#ifndef _XAR_MD5_H_ +-#define _XAR_MD5_H_ +- +-int32_t xar_md5_compressed(xar_t x, xar_file_t f, const char *, void *in, size_t inlen, void **context); +-int32_t xar_md5_uncompressed(xar_t x, xar_file_t f, const char *, void **in, size_t *inlen, void **context); +-int32_t xar_md5_done(xar_t x, xar_file_t f, const char *, void **context); +-int32_t xar_md5out_done(xar_t x, xar_file_t f, const char *, void **context); +- +-#endif /* _XAR_MD5_H_ */ diff --git a/patches/noea.diff b/patches/noea.diff new file mode 100644 index 0000000..d8a264a --- /dev/null +++ b/patches/noea.diff @@ -0,0 +1,26 @@ +diff -urN xar/lib/darwinattr.c xar.patch/lib/darwinattr.c +--- xar/lib/darwinattr.c 2006-03-16 11:45:21.000000000 -0800 ++++ xar.patch/lib/darwinattr.c 2006-03-16 11:48:27.000000000 -0800 +@@ -569,10 +569,6 @@ + #if defined(__APPLE__) + if( len ) + return 0; +-#if defined(HAVE_GETXATTR) +- if( ea_archive(x, f, file, (void *)&context) == 0 ) +- return 0; +-#endif + if( nonea_archive(x, f, file, (void *)&context) == 0 ) + return 0; + return underbar_archive(x, f, file, (void *)&context); +@@ -589,11 +585,6 @@ + #if defined(__APPLE__) + if( len ) + return 0; +-#if defined(HAVE_GETXATTR) +- if( ea_extract(x, f, file, (void *)&context) == 0 ) +- return 0; +-#endif +- + if( nonea_extract(x, f, file, (void *)&context) == 0 ) + return 0; + #endif /* __APPLE__ */ diff --git a/patches/static-lib.diff b/patches/static-lib.diff new file mode 100644 index 0000000..95a460e --- /dev/null +++ b/patches/static-lib.diff @@ -0,0 +1,39 @@ +diff -urN xar/lib/Makefile.inc.in xar.change/lib/Makefile.inc.in +--- xar/lib/Makefile.inc.in 2006-03-20 21:29:23.000000000 -0800 ++++ xar.change/lib/Makefile.inc.in 2006-03-20 21:29:08.000000000 -0800 +@@ -39,6 +39,12 @@ + LIBXAR_SNAME := libxar.@LIB_REV@.dylib + LIBXAR_LNAME := libxar.dylib + LIBXAR_L := @objroot@lib/$(LIBXAR_LNAME) ++ ++LIBXARSTATIC := libxar.a ++LIBXARSTATIC_L := @objroot@lib/$(LIBXARSTATIC) ++ ++ ++ + endif + ifeq (aout, @abi@) + LIBRXAR_SNAME := librxar.so.@LIB_REV@.0 +@@ -64,11 +70,13 @@ + + lib_all : $(LIBRXAR_S) $(LIBXAR_S) + +-lib_install : $(LIBXAR_S) ++lib_install : $(LIBXAR_S) $(LIBXARSTATIC) + @INSTALL@ -d $(DESTDIR)$(INCLUDEDIR)/xar + @INSTALL@ -m 0644 $(LIBXAR_INCS) $(DESTDIR)$(INCLUDEDIR)/xar + @INSTALL@ -d $(DESTDIR)$(LIBDIR) + @INSTALL@ -m 0444 $(LIBXAR_S) $(DESTDIR)$(LIBDIR) ++ @INSTALL@ -d $(DESTDIR)/usr/local/lib/ ++ @INSTALL@ -m 0444 $(LIBXARSTATIC) $(DESTDIR)/usr/local/lib/ + ifneq ($(words "" $(LIBXAR_LNAME)), 1) + rm -f $(DESTDIR)$(LIBDIR)/$(LIBXAR_LNAME) + ln -s $(LIBXAR_SNAME) $(DESTDIR)$(LIBDIR)/$(LIBXAR_LNAME) +@@ -125,6 +133,7 @@ + endif + ifeq (macho, @abi@) + $(CC) -dynamiclib -compatibility_version @LIB_REV@ -current_version @LIB_REV@ -install_name $(LIBDIR)/$(LIBXAR_SNAME) -o $@ $+ $(LDFLAGS) @LIBS@ ++ $(AR) cq $(LIBXARSTATIC) $+ + endif + ifeq (aout, @abi@) + $(CC) -shared -o $@ $+ diff --git a/test_tools/xar.tcl b/test_tools/xar.tcl new file mode 100644 index 0000000..76e0e28 --- /dev/null +++ b/test_tools/xar.tcl @@ -0,0 +1,69 @@ + +big_endian + +requires 0 "78617221" ;# xar! +ascii 4 "Signature" +set headersize [uint16 "Header Size"] +uint16 "Version" +set compressed_length [uint64 "TOC Compressed Length"] +uint64 "TOC Uncompressed Length" +uint32 "Checksum" +set compressed_data [bytes $compressed_length "TOC Data"] +set xml [zlib_uncompress $compressed_data] + +#puts "${xml}" +package require tdom +set doc [dom parse $xml] +set root [$doc documentElement] +set hashes [$root selectNodes "//checksum"] +set signatures [$root selectNodes "//signature"] + +section "Hashes" +foreach hash $hashes { + section [$hash getAttribute "style"] { + set lengthString [[lindex [$hash getElementsByTagName "size"] 0] text] + set offsetString [[lindex [$hash getElementsByTagName "offset"] 0] text] + scan $lengthString "%d" length + scan $offsetString "%d" heapoffset + set offset [expr { $heapoffset + $headersize + $compressed_length}] + entry "Checksum" "" $length $offset + } +} +endsection + +section "Signatures" +foreach signature $signatures { + section [$signature getAttribute "style"] { + set lengthString [[lindex [$signature getElementsByTagName "size"] 0] text] + set offsetString [[lindex [$signature getElementsByTagName "offset"] 0] text] + scan $lengthString "%d" length + scan $offsetString "%d" heapoffset + set offset [expr { $heapoffset + $headersize + $compressed_length}] + entry "Signature Blob" "" $length $offset + } +} +endsection + +set nodes [$root selectNodes "//file"] +section "Files" { + foreach node $nodes { + section [[lindex [$node getElementsByTagName "name"] 0] text] { + entry "ID" [$node getAttribute "id"] + entry "Type" [[lindex [$node getElementsByTagName "type"] 0] text] + + set dataNode [lindex [$node getElementsByTagName "data"] 0] + set compressedSizeString [[lindex [$dataNode getElementsByTagName "length"] 0] text] + set offsetString [[lindex [$dataNode getElementsByTagName "offset"] 0] text] + + scan $compressedSizeString "%d" compressedSize + scan $offsetString "%d" heapoffset + + set offset [expr { $heapoffset + $headersize + $compressed_length}] + + entry "Size" [[lindex [$dataNode getElementsByTagName "size"] 0] text] + entry "Compressed Size" $compressedSizeString + entry "Compressed Blob" "" $compressedSize $offset + + } + } +} \ No newline at end of file diff --git a/xar.plist b/xar.plist new file mode 100644 index 0000000..7a83acc --- /dev/null +++ b/xar.plist @@ -0,0 +1,26 @@ + + + + + + OpenSourceLicense + BSD + OpenSourceLicenseFile + xar.txt + OpenSourceMD5 + 7f3976664a426911eab93cdf367894bc + OpenSourceModifications + + 3397142 + + OpenSourceProject + xar + OpenSourceURL + http://www.opendarwin.org/projects/xar/xar-1.4.tar.gz + OpenSourceVersion + 1.4 + OpenSourceWebsiteURL + http://www.opendarwin.org/projects/xar/ + + + diff --git a/xar.txt b/xar.txt new file mode 100644 index 0000000..5d47df6 --- /dev/null +++ b/xar.txt @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2005 Rob Braun + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Rob Braun nor the names of his contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +/* + * 03-Apr-2005 + * DRI: Rob Braun + */ +/* + * Portions Copyright (c) 2006 Apple Computer, Inc. +*/ diff --git a/xar.xcconfig b/xar.xcconfig new file mode 100644 index 0000000..d73ebb4 --- /dev/null +++ b/xar.xcconfig @@ -0,0 +1,11 @@ +// +// xar.xcconfig +// xar +// +// Created by Lucy Zhang on 1/30/19. +// + +// Configuration settings file format documentation can be found at: +// https://help.apple.com/xcode/#/dev745c5c974 + +IS_ZIPPERED = YES diff --git a/xar.xcodeproj/project.pbxproj b/xar.xcodeproj/project.pbxproj new file mode 100644 index 0000000..a8664bd --- /dev/null +++ b/xar.xcodeproj/project.pbxproj @@ -0,0 +1,1397 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXAggregateTarget section */ + B41FC04F09F6B76200006FAE /* configure */ = { + isa = PBXAggregateTarget; + buildConfigurationList = B41FC05109F6B77E00006FAE /* Build configuration list for PBXAggregateTarget "configure" */; + buildPhases = ( + B41FC04E09F6B76200006FAE /* ShellScript */, + ); + dependencies = ( + ); + name = configure; + productName = configure; + }; + B41FC12109F6BEF900006FAE /* OpenSource */ = { + isa = PBXAggregateTarget; + buildConfigurationList = B41FC12709F6BF3300006FAE /* Build configuration list for PBXAggregateTarget "OpenSource" */; + buildPhases = ( + B41FC12009F6BEF900006FAE /* CopyFiles */, + B41FC12209F6BF1600006FAE /* CopyFiles */, + ); + dependencies = ( + ); + name = OpenSource; + productName = OpenSource; + }; + B41FC12F09F6BF5900006FAE /* All libraries */ = { + isa = PBXAggregateTarget; + buildConfigurationList = B41FC13709F6BF7900006FAE /* Build configuration list for PBXAggregateTarget "All libraries" */; + buildPhases = ( + ); + dependencies = ( + E9D7864E1D25A366006D5F7D /* PBXTargetDependency */, + B41FC13109F6BF6300006FAE /* PBXTargetDependency */, + B401A30309F6D71800B5C762 /* PBXTargetDependency */, + ); + name = "All libraries"; + productName = All; + }; + E9D659A31486FD650089C4DA /* All tools */ = { + isa = PBXAggregateTarget; + buildConfigurationList = E9D659A41486FD650089C4DA /* Build configuration list for PBXAggregateTarget "All tools" */; + buildPhases = ( + ); + dependencies = ( + E91435421497E100001AA5EF /* PBXTargetDependency */, + E9D659AA1486FD6D0089C4DA /* PBXTargetDependency */, + E9D659A81486FD6A0089C4DA /* PBXTargetDependency */, + ); + name = "All tools"; + productName = "All tools"; + }; + E9D659AB1486FFD10089C4DA /* All */ = { + isa = PBXAggregateTarget; + buildConfigurationList = E9D659AC1486FFD10089C4DA /* Build configuration list for PBXAggregateTarget "All" */; + buildPhases = ( + ); + dependencies = ( + E9D786501D25A4B1006D5F7D /* PBXTargetDependency */, + E9D659B01486FFED0089C4DA /* PBXTargetDependency */, + E9D659B21486FFED0089C4DA /* PBXTargetDependency */, + E9D659B61486FFED0089C4DA /* PBXTargetDependency */, + E9D659B81486FFED0089C4DA /* PBXTargetDependency */, + ); + name = All; + productName = All; + }; +/* End PBXAggregateTarget section */ + +/* Begin PBXBuildFile section */ + 98665C6F0EA83E36008193F1 /* ea.c in Sources */ = {isa = PBXBuildFile; fileRef = 98665C6E0EA83E36008193F1 /* ea.c */; }; + 98665C710EA83E44008193F1 /* lzmaxar.c in Sources */ = {isa = PBXBuildFile; fileRef = 98665C700EA83E44008193F1 /* lzmaxar.c */; }; + B41FC09C09F6BC2C00006FAE /* archive.c in Sources */ = {isa = PBXBuildFile; fileRef = B41FC07409F6BC2C00006FAE /* archive.c */; }; + B41FC09E09F6BC2C00006FAE /* arcmod.c in Sources */ = {isa = PBXBuildFile; fileRef = B41FC07609F6BC2C00006FAE /* arcmod.c */; }; + B41FC0A109F6BC2C00006FAE /* b64.c in Sources */ = {isa = PBXBuildFile; fileRef = B41FC07909F6BC2C00006FAE /* b64.c */; }; + B41FC0A309F6BC2C00006FAE /* bzxar.c in Sources */ = {isa = PBXBuildFile; fileRef = B41FC07B09F6BC2C00006FAE /* bzxar.c */; }; + B41FC0A609F6BC2C00006FAE /* darwinattr.c in Sources */ = {isa = PBXBuildFile; fileRef = B41FC07E09F6BC2C00006FAE /* darwinattr.c */; }; + B41FC0A809F6BC2C00006FAE /* data.c in Sources */ = {isa = PBXBuildFile; fileRef = B41FC08009F6BC2C00006FAE /* data.c */; }; + B41FC0AA09F6BC2C00006FAE /* err.c in Sources */ = {isa = PBXBuildFile; fileRef = B41FC08209F6BC2C00006FAE /* err.c */; }; + B41FC0AB09F6BC2C00006FAE /* ext2.c in Sources */ = {isa = PBXBuildFile; fileRef = B41FC08309F6BC2C00006FAE /* ext2.c */; }; + B41FC0AD09F6BC2C00006FAE /* fbsdattr.c in Sources */ = {isa = PBXBuildFile; fileRef = B41FC08509F6BC2C00006FAE /* fbsdattr.c */; }; + B41FC0AF09F6BC2C00006FAE /* filetree.c in Sources */ = {isa = PBXBuildFile; fileRef = B41FC08709F6BC2C00006FAE /* filetree.c */; }; + B41FC0B109F6BC2C00006FAE /* hash.c in Sources */ = {isa = PBXBuildFile; fileRef = B41FC08909F6BC2C00006FAE /* hash.c */; }; + B41FC0B309F6BC2C00006FAE /* io.c in Sources */ = {isa = PBXBuildFile; fileRef = B41FC08B09F6BC2C00006FAE /* io.c */; }; + B41FC0B509F6BC2C00006FAE /* linuxattr.c in Sources */ = {isa = PBXBuildFile; fileRef = B41FC08D09F6BC2C00006FAE /* linuxattr.c */; }; + B41FC0B909F6BC2C00006FAE /* script.c in Sources */ = {isa = PBXBuildFile; fileRef = B41FC09109F6BC2C00006FAE /* script.c */; }; + B41FC0BB09F6BC2C00006FAE /* stat.c in Sources */ = {isa = PBXBuildFile; fileRef = B41FC09309F6BC2C00006FAE /* stat.c */; }; + B41FC0BD09F6BC2C00006FAE /* subdoc.c in Sources */ = {isa = PBXBuildFile; fileRef = B41FC09509F6BC2C00006FAE /* subdoc.c */; }; + B41FC0BF09F6BC2C00006FAE /* util.c in Sources */ = {isa = PBXBuildFile; fileRef = B41FC09709F6BC2C00006FAE /* util.c */; }; + B41FC0C109F6BC2C00006FAE /* zxar.c in Sources */ = {isa = PBXBuildFile; fileRef = B41FC09909F6BC2C00006FAE /* zxar.c */; }; + B41FC0C809F6BC7A00006FAE /* libz.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = B41FC0C409F6BC7A00006FAE /* libz.dylib */; }; + B41FC0C909F6BC7A00006FAE /* libbz2.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = B41FC0C509F6BC7A00006FAE /* libbz2.dylib */; }; + B41FC0CB09F6BC7A00006FAE /* libxml2.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = B41FC0C709F6BC7A00006FAE /* libxml2.dylib */; }; + B41FC0E909F6BDAF00006FAE /* libxar.1.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = B41FC05F09F6B7C200006FAE /* libxar.1.dylib */; }; + B41FC0EC09F6BDD900006FAE /* xar.c in Sources */ = {isa = PBXBuildFile; fileRef = B41FC0EB09F6BDD900006FAE /* xar.c */; }; + B41FC0EF09F6BDF900006FAE /* xar.1 in CopyFiles */ = {isa = PBXBuildFile; fileRef = B41FC0EA09F6BDD900006FAE /* xar.1 */; }; + B41FC0F809F6BE9100006FAE /* archive.c in Sources */ = {isa = PBXBuildFile; fileRef = B41FC07409F6BC2C00006FAE /* archive.c */; }; + B41FC0F909F6BE9100006FAE /* arcmod.c in Sources */ = {isa = PBXBuildFile; fileRef = B41FC07609F6BC2C00006FAE /* arcmod.c */; }; + B41FC0FA09F6BE9100006FAE /* b64.c in Sources */ = {isa = PBXBuildFile; fileRef = B41FC07909F6BC2C00006FAE /* b64.c */; }; + B41FC0FB09F6BE9100006FAE /* bzxar.c in Sources */ = {isa = PBXBuildFile; fileRef = B41FC07B09F6BC2C00006FAE /* bzxar.c */; }; + B41FC0FC09F6BE9100006FAE /* darwinattr.c in Sources */ = {isa = PBXBuildFile; fileRef = B41FC07E09F6BC2C00006FAE /* darwinattr.c */; }; + B41FC0FD09F6BE9100006FAE /* data.c in Sources */ = {isa = PBXBuildFile; fileRef = B41FC08009F6BC2C00006FAE /* data.c */; }; + B41FC0FE09F6BE9100006FAE /* err.c in Sources */ = {isa = PBXBuildFile; fileRef = B41FC08209F6BC2C00006FAE /* err.c */; }; + B41FC0FF09F6BE9100006FAE /* ext2.c in Sources */ = {isa = PBXBuildFile; fileRef = B41FC08309F6BC2C00006FAE /* ext2.c */; }; + B41FC10009F6BE9100006FAE /* fbsdattr.c in Sources */ = {isa = PBXBuildFile; fileRef = B41FC08509F6BC2C00006FAE /* fbsdattr.c */; }; + B41FC10109F6BE9100006FAE /* filetree.c in Sources */ = {isa = PBXBuildFile; fileRef = B41FC08709F6BC2C00006FAE /* filetree.c */; }; + B41FC10209F6BE9100006FAE /* hash.c in Sources */ = {isa = PBXBuildFile; fileRef = B41FC08909F6BC2C00006FAE /* hash.c */; }; + B41FC10309F6BE9100006FAE /* io.c in Sources */ = {isa = PBXBuildFile; fileRef = B41FC08B09F6BC2C00006FAE /* io.c */; }; + B41FC10409F6BE9100006FAE /* linuxattr.c in Sources */ = {isa = PBXBuildFile; fileRef = B41FC08D09F6BC2C00006FAE /* linuxattr.c */; }; + B41FC10609F6BE9100006FAE /* script.c in Sources */ = {isa = PBXBuildFile; fileRef = B41FC09109F6BC2C00006FAE /* script.c */; }; + B41FC10709F6BE9100006FAE /* stat.c in Sources */ = {isa = PBXBuildFile; fileRef = B41FC09309F6BC2C00006FAE /* stat.c */; }; + B41FC10809F6BE9100006FAE /* subdoc.c in Sources */ = {isa = PBXBuildFile; fileRef = B41FC09509F6BC2C00006FAE /* subdoc.c */; }; + B41FC10909F6BE9100006FAE /* util.c in Sources */ = {isa = PBXBuildFile; fileRef = B41FC09709F6BC2C00006FAE /* util.c */; }; + B41FC10A09F6BE9100006FAE /* zxar.c in Sources */ = {isa = PBXBuildFile; fileRef = B41FC09909F6BC2C00006FAE /* zxar.c */; }; + B41FC10B09F6BE9B00006FAE /* libz.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = B41FC0C409F6BC7A00006FAE /* libz.dylib */; }; + B41FC10C09F6BE9B00006FAE /* libbz2.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = B41FC0C509F6BC7A00006FAE /* libbz2.dylib */; }; + B41FC10E09F6BE9B00006FAE /* libxml2.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = B41FC0C709F6BC7A00006FAE /* libxml2.dylib */; }; + B41FC12A09F6BF3700006FAE /* xar.plist in CopyFiles */ = {isa = PBXBuildFile; fileRef = B41FC12509F6BF3300006FAE /* xar.plist */; }; + B41FC12B09F6BF3C00006FAE /* xar.txt in CopyFiles */ = {isa = PBXBuildFile; fileRef = B41FC12609F6BF3300006FAE /* xar.txt */; }; + B476FACD0A49E68600BCD61F /* signature.c in Sources */ = {isa = PBXBuildFile; fileRef = B476FACC0A49E68600BCD61F /* signature.c */; }; + B476FACF0A49E68600BCD61F /* signature.c in Sources */ = {isa = PBXBuildFile; fileRef = B476FACC0A49E68600BCD61F /* signature.c */; }; + B4772CA30A003F7300E4205C /* xar.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = B4772CA20A003F6E00E4205C /* xar.h */; }; + E9C0E6741497DDAB00BF8F0F /* ea.h in Headers */ = {isa = PBXBuildFile; fileRef = E9C0E6731497DDAB00BF8F0F /* ea.h */; }; + E9D786581D260606006D5F7D /* lzmaxar.c in Sources */ = {isa = PBXBuildFile; fileRef = 98665C700EA83E44008193F1 /* lzmaxar.c */; }; + E9D7865D1D2606F9006D5F7D /* ea.c in Sources */ = {isa = PBXBuildFile; fileRef = 98665C6E0EA83E36008193F1 /* ea.c */; }; + E9E06B8B219E252E004DB0CA /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = E9E06B8A219E252E004DB0CA /* main.m */; }; + E9E06B90219E2542004DB0CA /* libxar.1.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = B41FC05F09F6B7C200006FAE /* libxar.1.dylib */; }; + E9E06B91219E257D004DB0CA /* b64.c in Sources */ = {isa = PBXBuildFile; fileRef = B41FC07909F6BC2C00006FAE /* b64.c */; }; + EEEFF3E60EFB700A00DBC955 /* xar-sig.c in Sources */ = {isa = PBXBuildFile; fileRef = EEEFF3DC0EFB6FC500DBC955 /* xar-sig.c */; }; + EEEFF40E0EFB715100DBC955 /* libxar.1.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = B41FC05F09F6B7C200006FAE /* libxar.1.dylib */; }; +/* End PBXBuildFile section */ + +/* Begin PBXContainerItemProxy section */ + B401A30209F6D71800B5C762 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = B41FC04109F6B74500006FAE /* Project object */; + proxyType = 1; + remoteGlobalIDString = B41FC12109F6BEF900006FAE; + remoteInfo = OpenSource; + }; + B41FC0D609F6BD0300006FAE /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = B41FC04109F6B74500006FAE /* Project object */; + proxyType = 1; + remoteGlobalIDString = B41FC04F09F6B76200006FAE; + remoteInfo = configure; + }; + B41FC11E09F6BEDE00006FAE /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = B41FC04109F6B74500006FAE /* Project object */; + proxyType = 1; + remoteGlobalIDString = B41FC04F09F6B76200006FAE; + remoteInfo = configure; + }; + B41FC13009F6BF6300006FAE /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = B41FC04109F6B74500006FAE /* Project object */; + proxyType = 1; + remoteGlobalIDString = B41FC05E09F6B7C200006FAE; + remoteInfo = xarLib; + }; + E914353F1497E0F6001AA5EF /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = B41FC04109F6B74500006FAE /* Project object */; + proxyType = 1; + remoteGlobalIDString = B41FC04F09F6B76200006FAE; + remoteInfo = configure; + }; + E91435411497E100001AA5EF /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = B41FC04109F6B74500006FAE /* Project object */; + proxyType = 1; + remoteGlobalIDString = B41FC04F09F6B76200006FAE; + remoteInfo = configure; + }; + E9C0E6761497DE6000BF8F0F /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = B41FC04109F6B74500006FAE /* Project object */; + proxyType = 1; + remoteGlobalIDString = B41FC04F09F6B76200006FAE; + remoteInfo = configure; + }; + E9D659A71486FD6A0089C4DA /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = B41FC04109F6B74500006FAE /* Project object */; + proxyType = 1; + remoteGlobalIDString = B41FC0E109F6BD6800006FAE; + remoteInfo = xarTool; + }; + E9D659A91486FD6D0089C4DA /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = B41FC04109F6B74500006FAE /* Project object */; + proxyType = 1; + remoteGlobalIDString = EEEFF3DF0EFB6FD500DBC955; + remoteInfo = xarsig; + }; + E9D659AF1486FFED0089C4DA /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = B41FC04109F6B74500006FAE /* Project object */; + proxyType = 1; + remoteGlobalIDString = B41FC05E09F6B7C200006FAE; + remoteInfo = xarLib; + }; + E9D659B11486FFED0089C4DA /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = B41FC04109F6B74500006FAE /* Project object */; + proxyType = 1; + remoteGlobalIDString = B41FC0E109F6BD6800006FAE; + remoteInfo = xarTool; + }; + E9D659B51486FFED0089C4DA /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = B41FC04109F6B74500006FAE /* Project object */; + proxyType = 1; + remoteGlobalIDString = B41FC12109F6BEF900006FAE; + remoteInfo = OpenSource; + }; + E9D659B71486FFED0089C4DA /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = B41FC04109F6B74500006FAE /* Project object */; + proxyType = 1; + remoteGlobalIDString = EEEFF3DF0EFB6FD500DBC955; + remoteInfo = xarsig; + }; + E9D7864D1D25A366006D5F7D /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = B41FC04109F6B74500006FAE /* Project object */; + proxyType = 1; + remoteGlobalIDString = B41FC0F309F6BE2F00006FAE; + remoteInfo = xarStatic; + }; + E9D7864F1D25A4B1006D5F7D /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = B41FC04109F6B74500006FAE /* Project object */; + proxyType = 1; + remoteGlobalIDString = B41FC0F309F6BE2F00006FAE; + remoteInfo = xarStatic; + }; +/* End PBXContainerItemProxy section */ + +/* Begin PBXCopyFilesBuildPhase section */ + B41FC0DC09F6BD2300006FAE /* CopyFiles */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 8; + dstPath = /usr/include/xar; + dstSubfolderSpec = 0; + files = ( + B4772CA30A003F7300E4205C /* xar.h in CopyFiles */, + ); + runOnlyForDeploymentPostprocessing = 1; + }; + B41FC0ED09F6BDE400006FAE /* CopyFiles */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 8; + dstPath = /usr/share/man/man1; + dstSubfolderSpec = 0; + files = ( + B41FC0EF09F6BDF900006FAE /* xar.1 in CopyFiles */, + ); + runOnlyForDeploymentPostprocessing = 1; + }; + B41FC12009F6BEF900006FAE /* CopyFiles */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 8; + dstPath = /usr/local/OpenSourceLicenses; + dstSubfolderSpec = 0; + files = ( + B41FC12B09F6BF3C00006FAE /* xar.txt in CopyFiles */, + ); + runOnlyForDeploymentPostprocessing = 1; + }; + B41FC12209F6BF1600006FAE /* CopyFiles */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 8; + dstPath = /usr/local/OpenSourceVersions; + dstSubfolderSpec = 0; + files = ( + B41FC12A09F6BF3700006FAE /* xar.plist in CopyFiles */, + ); + runOnlyForDeploymentPostprocessing = 1; + }; +/* End PBXCopyFilesBuildPhase section */ + +/* Begin PBXFileReference section */ + 7C7F76CC2202351600155C33 /* xar.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = xar.xcconfig; sourceTree = ""; }; + 98665C6E0EA83E36008193F1 /* ea.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = ea.c; path = xar/lib/ea.c; sourceTree = ""; }; + 98665C700EA83E44008193F1 /* lzmaxar.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = lzmaxar.c; path = xar/lib/lzmaxar.c; sourceTree = ""; }; + B41FC05F09F6B7C200006FAE /* libxar.1.dylib */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.dylib"; includeInIndex = 0; path = libxar.1.dylib; sourceTree = BUILT_PRODUCTS_DIR; }; + B41FC07309F6BC2C00006FAE /* appledouble.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = appledouble.h; path = xar/lib/appledouble.h; sourceTree = ""; }; + B41FC07409F6BC2C00006FAE /* archive.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; name = archive.c; path = xar/lib/archive.c; sourceTree = ""; }; + B41FC07509F6BC2C00006FAE /* archive.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = archive.h; path = xar/lib/archive.h; sourceTree = ""; }; + B41FC07609F6BC2C00006FAE /* arcmod.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; name = arcmod.c; path = xar/lib/arcmod.c; sourceTree = ""; }; + B41FC07709F6BC2C00006FAE /* arcmod.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = arcmod.h; path = xar/lib/arcmod.h; sourceTree = ""; }; + B41FC07809F6BC2C00006FAE /* asprintf.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = asprintf.h; path = xar/lib/asprintf.h; sourceTree = ""; }; + B41FC07909F6BC2C00006FAE /* b64.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; name = b64.c; path = xar/lib/b64.c; sourceTree = ""; }; + B41FC07A09F6BC2C00006FAE /* b64.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = b64.h; path = xar/lib/b64.h; sourceTree = ""; }; + B41FC07B09F6BC2C00006FAE /* bzxar.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; name = bzxar.c; path = xar/lib/bzxar.c; sourceTree = ""; }; + B41FC07C09F6BC2C00006FAE /* bzxar.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = bzxar.h; path = xar/lib/bzxar.h; sourceTree = ""; }; + B41FC07E09F6BC2C00006FAE /* darwinattr.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; name = darwinattr.c; path = xar/lib/darwinattr.c; sourceTree = ""; }; + B41FC07F09F6BC2C00006FAE /* darwinattr.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = darwinattr.h; path = xar/lib/darwinattr.h; sourceTree = ""; }; + B41FC08009F6BC2C00006FAE /* data.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; name = data.c; path = xar/lib/data.c; sourceTree = ""; }; + B41FC08109F6BC2C00006FAE /* data.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = data.h; path = xar/lib/data.h; sourceTree = ""; }; + B41FC08209F6BC2C00006FAE /* err.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; name = err.c; path = xar/lib/err.c; sourceTree = ""; }; + B41FC08309F6BC2C00006FAE /* ext2.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; name = ext2.c; path = xar/lib/ext2.c; sourceTree = ""; }; + B41FC08409F6BC2C00006FAE /* ext2.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = ext2.h; path = xar/lib/ext2.h; sourceTree = ""; }; + B41FC08509F6BC2C00006FAE /* fbsdattr.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; name = fbsdattr.c; path = xar/lib/fbsdattr.c; sourceTree = ""; }; + B41FC08609F6BC2C00006FAE /* fbsdattr.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = fbsdattr.h; path = xar/lib/fbsdattr.h; sourceTree = ""; }; + B41FC08709F6BC2C00006FAE /* filetree.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; name = filetree.c; path = xar/lib/filetree.c; sourceTree = ""; }; + B41FC08809F6BC2C00006FAE /* filetree.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = filetree.h; path = xar/lib/filetree.h; sourceTree = ""; }; + B41FC08909F6BC2C00006FAE /* hash.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; name = hash.c; path = xar/lib/hash.c; sourceTree = ""; }; + B41FC08A09F6BC2C00006FAE /* hash.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = hash.h; path = xar/lib/hash.h; sourceTree = ""; }; + B41FC08B09F6BC2C00006FAE /* io.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; name = io.c; path = xar/lib/io.c; sourceTree = ""; }; + B41FC08C09F6BC2C00006FAE /* io.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = io.h; path = xar/lib/io.h; sourceTree = ""; }; + B41FC08D09F6BC2C00006FAE /* linuxattr.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; name = linuxattr.c; path = xar/lib/linuxattr.c; sourceTree = ""; }; + B41FC08E09F6BC2C00006FAE /* linuxattr.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = linuxattr.h; path = xar/lib/linuxattr.h; sourceTree = ""; }; + B41FC09109F6BC2C00006FAE /* script.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; name = script.c; path = xar/lib/script.c; sourceTree = ""; }; + B41FC09209F6BC2C00006FAE /* script.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = script.h; path = xar/lib/script.h; sourceTree = ""; }; + B41FC09309F6BC2C00006FAE /* stat.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; name = stat.c; path = xar/lib/stat.c; sourceTree = ""; }; + B41FC09409F6BC2C00006FAE /* stat.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = stat.h; path = xar/lib/stat.h; sourceTree = ""; }; + B41FC09509F6BC2C00006FAE /* subdoc.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; name = subdoc.c; path = xar/lib/subdoc.c; sourceTree = ""; }; + B41FC09609F6BC2C00006FAE /* subdoc.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = subdoc.h; path = xar/lib/subdoc.h; sourceTree = ""; }; + B41FC09709F6BC2C00006FAE /* util.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; name = util.c; path = xar/lib/util.c; sourceTree = ""; }; + B41FC09809F6BC2C00006FAE /* util.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = util.h; path = xar/lib/util.h; sourceTree = ""; }; + B41FC09909F6BC2C00006FAE /* zxar.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; name = zxar.c; path = xar/lib/zxar.c; sourceTree = ""; }; + B41FC09A09F6BC2C00006FAE /* zxar.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = zxar.h; path = xar/lib/zxar.h; sourceTree = ""; }; + B41FC0C409F6BC7A00006FAE /* libz.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libz.dylib; path = /usr/lib/libz.dylib; sourceTree = ""; }; + B41FC0C509F6BC7A00006FAE /* libbz2.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libbz2.dylib; path = /usr/lib/libbz2.dylib; sourceTree = ""; }; + B41FC0C709F6BC7A00006FAE /* libxml2.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libxml2.dylib; path = /usr/lib/libxml2.dylib; sourceTree = ""; }; + B41FC0E209F6BD6800006FAE /* xar */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = xar; sourceTree = BUILT_PRODUCTS_DIR; }; + B41FC0EA09F6BDD900006FAE /* xar.1 */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text.man; name = xar.1; path = xar/src/xar.1; sourceTree = ""; }; + B41FC0EB09F6BDD900006FAE /* xar.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; name = xar.c; path = xar/src/xar.c; sourceTree = ""; }; + B41FC0F409F6BE2F00006FAE /* libxarstatic.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libxarstatic.a; sourceTree = BUILT_PRODUCTS_DIR; }; + B41FC12409F6BF3300006FAE /* README */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text; path = README; sourceTree = ""; }; + B41FC12509F6BF3300006FAE /* xar.plist */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text.plist.xml; path = xar.plist; sourceTree = ""; }; + B41FC12609F6BF3300006FAE /* xar.txt */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text; path = xar.txt; sourceTree = ""; }; + B41FC16309F6C56600006FAE /* config.h.in */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text; name = config.h.in; path = xar/include/config.h.in; sourceTree = ""; }; + B41FC16409F6C56600006FAE /* xar.h.in */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text; name = xar.h.in; path = xar/include/xar.h.in; sourceTree = ""; }; + B4657F1E0A49E6150074E45D /* signature.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = signature.h; path = xar/lib/signature.h; sourceTree = ""; }; + B476FACC0A49E68600BCD61F /* signature.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = signature.c; path = xar/lib/signature.c; sourceTree = ""; }; + B4772CA20A003F6E00E4205C /* xar.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = xar.h; path = include/xar.h; sourceTree = BUILT_PRODUCTS_DIR; }; + E9C0E6731497DDAB00BF8F0F /* ea.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ea.h; path = xar/lib/ea.h; sourceTree = ""; }; + E9E06B88219E252E004DB0CA /* test_xar */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = test_xar; sourceTree = BUILT_PRODUCTS_DIR; }; + E9E06B8A219E252E004DB0CA /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; + EEEFF3DC0EFB6FC500DBC955 /* xar-sig.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = "xar-sig.c"; path = "xarsig/xar-sig.c"; sourceTree = ""; }; + EEEFF3E00EFB6FD500DBC955 /* xarsig */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = xarsig; sourceTree = BUILT_PRODUCTS_DIR; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + B41FC05D09F6B7C200006FAE /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + B41FC0C809F6BC7A00006FAE /* libz.dylib in Frameworks */, + B41FC0C909F6BC7A00006FAE /* libbz2.dylib in Frameworks */, + B41FC0CB09F6BC7A00006FAE /* libxml2.dylib in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + B41FC0E009F6BD6800006FAE /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + B41FC0E909F6BDAF00006FAE /* libxar.1.dylib in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + B41FC0F209F6BE2F00006FAE /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + B41FC10B09F6BE9B00006FAE /* libz.dylib in Frameworks */, + B41FC10C09F6BE9B00006FAE /* libbz2.dylib in Frameworks */, + B41FC10E09F6BE9B00006FAE /* libxml2.dylib in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + E9E06B85219E252E004DB0CA /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + E9E06B90219E2542004DB0CA /* libxar.1.dylib in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + EEEFF3DE0EFB6FD500DBC955 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + EEEFF40E0EFB715100DBC955 /* libxar.1.dylib in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + B41FC03F09F6B74500006FAE = { + isa = PBXGroup; + children = ( + EEEFF3D60EFB6F5600DBC955 /* xarsig */, + B41FC12409F6BF3300006FAE /* README */, + B41FC12509F6BF3300006FAE /* xar.plist */, + B41FC12609F6BF3300006FAE /* xar.txt */, + B41FC07209F6BBD100006FAE /* tool */, + B41FC07109F6BBBD00006FAE /* lib */, + B41FC0C309F6BC6B00006FAE /* libraries */, + B4772CA00A003F3B00E4205C /* derived */, + E9E06B89219E252E004DB0CA /* test_xar */, + B41FC06009F6B7C200006FAE /* Products */, + E9E06B8F219E2542004DB0CA /* Frameworks */, + ); + sourceTree = ""; + usesTabs = 1; + }; + B41FC06009F6B7C200006FAE /* Products */ = { + isa = PBXGroup; + children = ( + B41FC05F09F6B7C200006FAE /* libxar.1.dylib */, + B41FC0E209F6BD6800006FAE /* xar */, + B41FC0F409F6BE2F00006FAE /* libxarstatic.a */, + EEEFF3E00EFB6FD500DBC955 /* xarsig */, + E9E06B88219E252E004DB0CA /* test_xar */, + ); + name = Products; + sourceTree = ""; + }; + B41FC07109F6BBBD00006FAE /* lib */ = { + isa = PBXGroup; + children = ( + E9C0E6731497DDAB00BF8F0F /* ea.h */, + 98665C700EA83E44008193F1 /* lzmaxar.c */, + 98665C6E0EA83E36008193F1 /* ea.c */, + B41FC16309F6C56600006FAE /* config.h.in */, + B41FC16409F6C56600006FAE /* xar.h.in */, + B41FC07309F6BC2C00006FAE /* appledouble.h */, + B41FC07409F6BC2C00006FAE /* archive.c */, + B41FC07509F6BC2C00006FAE /* archive.h */, + B41FC07609F6BC2C00006FAE /* arcmod.c */, + B41FC07709F6BC2C00006FAE /* arcmod.h */, + B41FC07809F6BC2C00006FAE /* asprintf.h */, + B41FC07909F6BC2C00006FAE /* b64.c */, + B41FC07A09F6BC2C00006FAE /* b64.h */, + B41FC07B09F6BC2C00006FAE /* bzxar.c */, + B41FC07C09F6BC2C00006FAE /* bzxar.h */, + B41FC07E09F6BC2C00006FAE /* darwinattr.c */, + B41FC07F09F6BC2C00006FAE /* darwinattr.h */, + B41FC08009F6BC2C00006FAE /* data.c */, + B41FC08109F6BC2C00006FAE /* data.h */, + B41FC08209F6BC2C00006FAE /* err.c */, + B41FC08309F6BC2C00006FAE /* ext2.c */, + B41FC08409F6BC2C00006FAE /* ext2.h */, + B41FC08509F6BC2C00006FAE /* fbsdattr.c */, + B41FC08609F6BC2C00006FAE /* fbsdattr.h */, + B41FC08709F6BC2C00006FAE /* filetree.c */, + B41FC08809F6BC2C00006FAE /* filetree.h */, + B41FC08909F6BC2C00006FAE /* hash.c */, + B41FC08A09F6BC2C00006FAE /* hash.h */, + B41FC08B09F6BC2C00006FAE /* io.c */, + B41FC08C09F6BC2C00006FAE /* io.h */, + B41FC08D09F6BC2C00006FAE /* linuxattr.c */, + B41FC08E09F6BC2C00006FAE /* linuxattr.h */, + B41FC09109F6BC2C00006FAE /* script.c */, + B41FC09209F6BC2C00006FAE /* script.h */, + B4657F1E0A49E6150074E45D /* signature.h */, + B476FACC0A49E68600BCD61F /* signature.c */, + B41FC09309F6BC2C00006FAE /* stat.c */, + B41FC09409F6BC2C00006FAE /* stat.h */, + B41FC09509F6BC2C00006FAE /* subdoc.c */, + B41FC09609F6BC2C00006FAE /* subdoc.h */, + B41FC09709F6BC2C00006FAE /* util.c */, + B41FC09809F6BC2C00006FAE /* util.h */, + B41FC09909F6BC2C00006FAE /* zxar.c */, + B41FC09A09F6BC2C00006FAE /* zxar.h */, + 7C7F76CC2202351600155C33 /* xar.xcconfig */, + ); + name = lib; + sourceTree = ""; + }; + B41FC07209F6BBD100006FAE /* tool */ = { + isa = PBXGroup; + children = ( + B41FC0EA09F6BDD900006FAE /* xar.1 */, + B41FC0EB09F6BDD900006FAE /* xar.c */, + ); + name = tool; + sourceTree = ""; + }; + B41FC0C309F6BC6B00006FAE /* libraries */ = { + isa = PBXGroup; + children = ( + B41FC0C409F6BC7A00006FAE /* libz.dylib */, + B41FC0C509F6BC7A00006FAE /* libbz2.dylib */, + B41FC0C709F6BC7A00006FAE /* libxml2.dylib */, + ); + name = libraries; + sourceTree = ""; + }; + B4772CA00A003F3B00E4205C /* derived */ = { + isa = PBXGroup; + children = ( + B4772CA20A003F6E00E4205C /* xar.h */, + ); + name = derived; + sourceTree = ""; + }; + E9E06B89219E252E004DB0CA /* test_xar */ = { + isa = PBXGroup; + children = ( + E9E06B8A219E252E004DB0CA /* main.m */, + ); + path = test_xar; + sourceTree = ""; + }; + E9E06B8F219E2542004DB0CA /* Frameworks */ = { + isa = PBXGroup; + children = ( + ); + name = Frameworks; + sourceTree = ""; + }; + EEEFF3D60EFB6F5600DBC955 /* xarsig */ = { + isa = PBXGroup; + children = ( + EEEFF3DC0EFB6FC500DBC955 /* xar-sig.c */, + ); + name = xarsig; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXHeadersBuildPhase section */ + B41FC05B09F6B7C200006FAE /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + E9C0E6741497DDAB00BF8F0F /* ea.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + B41FC0F009F6BE2F00006FAE /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXHeadersBuildPhase section */ + +/* Begin PBXNativeTarget section */ + B41FC05E09F6B7C200006FAE /* xarLib */ = { + isa = PBXNativeTarget; + buildConfigurationList = B41FC06109F6B7C300006FAE /* Build configuration list for PBXNativeTarget "xarLib" */; + buildPhases = ( + B41FC05B09F6B7C200006FAE /* Headers */, + B41FC05C09F6B7C200006FAE /* Sources */, + B41FC05D09F6B7C200006FAE /* Frameworks */, + B41FC0DC09F6BD2300006FAE /* CopyFiles */, + B401A30509F6D73200B5C762 /* ShellScript */, + ); + buildRules = ( + ); + dependencies = ( + B41FC0D709F6BD0300006FAE /* PBXTargetDependency */, + ); + name = xarLib; + productName = xarLib; + productReference = B41FC05F09F6B7C200006FAE /* libxar.1.dylib */; + productType = "com.apple.product-type.library.dynamic"; + }; + B41FC0E109F6BD6800006FAE /* xarTool */ = { + isa = PBXNativeTarget; + buildConfigurationList = B41FC0E609F6BD8C00006FAE /* Build configuration list for PBXNativeTarget "xarTool" */; + buildPhases = ( + B41FC0DF09F6BD6800006FAE /* Sources */, + B41FC0E009F6BD6800006FAE /* Frameworks */, + B41FC0ED09F6BDE400006FAE /* CopyFiles */, + ); + buildRules = ( + ); + dependencies = ( + E9C0E6771497DE6000BF8F0F /* PBXTargetDependency */, + ); + name = xarTool; + productName = xarTool; + productReference = B41FC0E209F6BD6800006FAE /* xar */; + productType = "com.apple.product-type.tool"; + }; + B41FC0F309F6BE2F00006FAE /* xarStatic */ = { + isa = PBXNativeTarget; + buildConfigurationList = B41FC0F509F6BE7F00006FAE /* Build configuration list for PBXNativeTarget "xarStatic" */; + buildPhases = ( + B41FC0F009F6BE2F00006FAE /* Headers */, + B41FC0F109F6BE2F00006FAE /* Sources */, + B41FC0F209F6BE2F00006FAE /* Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + B41FC11F09F6BEDE00006FAE /* PBXTargetDependency */, + ); + name = xarStatic; + productName = xarStatic; + productReference = B41FC0F409F6BE2F00006FAE /* libxarstatic.a */; + productType = "com.apple.product-type.library.static"; + }; + E9E06B87219E252E004DB0CA /* test_xar */ = { + isa = PBXNativeTarget; + buildConfigurationList = E9E06B8E219E252E004DB0CA /* Build configuration list for PBXNativeTarget "test_xar" */; + buildPhases = ( + E9E06B84219E252E004DB0CA /* Sources */, + E9E06B85219E252E004DB0CA /* Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = test_xar; + productName = test_xar; + productReference = E9E06B88219E252E004DB0CA /* test_xar */; + productType = "com.apple.product-type.tool"; + }; + EEEFF3DF0EFB6FD500DBC955 /* xarsig */ = { + isa = PBXNativeTarget; + buildConfigurationList = EEEFF3E50EFB6FDA00DBC955 /* Build configuration list for PBXNativeTarget "xarsig" */; + buildPhases = ( + EEEFF3DD0EFB6FD500DBC955 /* Sources */, + EEEFF3DE0EFB6FD500DBC955 /* Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + E91435401497E0F6001AA5EF /* PBXTargetDependency */, + ); + name = xarsig; + productName = xarsig; + productReference = EEEFF3E00EFB6FD500DBC955 /* xarsig */; + productType = "com.apple.product-type.tool"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + B41FC04109F6B74500006FAE /* Project object */ = { + isa = PBXProject; + attributes = { + LastUpgradeCheck = 0800; + TargetAttributes = { + E9E06B87219E252E004DB0CA = { + CreatedOnToolsVersion = 11.0; + ProvisioningStyle = Automatic; + }; + }; + }; + buildConfigurationList = B41FC04209F6B74500006FAE /* Build configuration list for PBXProject "xar" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = English; + hasScannedForEncodings = 0; + knownRegions = ( + English, + Japanese, + French, + German, + ); + mainGroup = B41FC03F09F6B74500006FAE; + productRefGroup = B41FC06009F6B7C200006FAE /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + E9D659AB1486FFD10089C4DA /* All */, + E9D659A31486FD650089C4DA /* All tools */, + B41FC12F09F6BF5900006FAE /* All libraries */, + B41FC04F09F6B76200006FAE /* configure */, + B41FC05E09F6B7C200006FAE /* xarLib */, + B41FC0E109F6BD6800006FAE /* xarTool */, + B41FC0F309F6BE2F00006FAE /* xarStatic */, + B41FC12109F6BEF900006FAE /* OpenSource */, + EEEFF3DF0EFB6FD500DBC955 /* xarsig */, + E9E06B87219E252E004DB0CA /* test_xar */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXShellScriptBuildPhase section */ + B401A30509F6D73200B5C762 /* ShellScript */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 8; + files = ( + ); + inputPaths = ( + ); + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 1; + shellPath = /bin/sh; + shellScript = "ln -s \"libxar.1.dylib\" \"$TARGET_BUILD_DIR/libxar.dylib\""; + }; + B41FC04E09F6B76200006FAE /* ShellScript */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + "$(SRCROOT)/xar/include/config.h.in", + "$(SRCROOT)/xar/include/xar.h.in", + ); + outputPaths = ( + "$(TARGET_BUILD_DIR)/include/config.h", + "$(TARGET_BUILD_DIR)/include/xar.h", + "$(TARGET_BUILD_DIR)/cfghdrs.stamp", + "$(TARGET_BUILD_DIR)/cfgoutputs.stamp", + "$(TARGET_BUILD_DIR)/config.log", + "$(TARGET_BUILD_DIR)/config.status", + "$(TARGET_BUILD_DIR)/lib/Makefile.inc", + "$(TARGET_BUILD_DIR)/Makefile", + "$(TARGET_BUILD_DIR)/Makefile.inc", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "# shell script goes here\n\nif [ ! -e \"$BUILT_PRODUCTS_DIR\" ]; then\n\tmkdir -p \"$BUILT_PRODUCTS_DIR\"\nfi\n\ncd \"$BUILT_PRODUCTS_DIR\"\n\n$SRCROOT/xar/configure\n\n\nexit 0"; + }; +/* End PBXShellScriptBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + B41FC05C09F6B7C200006FAE /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + B41FC09C09F6BC2C00006FAE /* archive.c in Sources */, + B41FC09E09F6BC2C00006FAE /* arcmod.c in Sources */, + B41FC0A109F6BC2C00006FAE /* b64.c in Sources */, + B41FC0A309F6BC2C00006FAE /* bzxar.c in Sources */, + B41FC0A609F6BC2C00006FAE /* darwinattr.c in Sources */, + B41FC0A809F6BC2C00006FAE /* data.c in Sources */, + B41FC0AA09F6BC2C00006FAE /* err.c in Sources */, + B41FC0AB09F6BC2C00006FAE /* ext2.c in Sources */, + B41FC0AD09F6BC2C00006FAE /* fbsdattr.c in Sources */, + B41FC0AF09F6BC2C00006FAE /* filetree.c in Sources */, + B41FC0B109F6BC2C00006FAE /* hash.c in Sources */, + B41FC0B309F6BC2C00006FAE /* io.c in Sources */, + B41FC0B509F6BC2C00006FAE /* linuxattr.c in Sources */, + B41FC0B909F6BC2C00006FAE /* script.c in Sources */, + B41FC0BB09F6BC2C00006FAE /* stat.c in Sources */, + B41FC0BD09F6BC2C00006FAE /* subdoc.c in Sources */, + B41FC0BF09F6BC2C00006FAE /* util.c in Sources */, + B41FC0C109F6BC2C00006FAE /* zxar.c in Sources */, + B476FACD0A49E68600BCD61F /* signature.c in Sources */, + 98665C6F0EA83E36008193F1 /* ea.c in Sources */, + 98665C710EA83E44008193F1 /* lzmaxar.c in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + B41FC0DF09F6BD6800006FAE /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + B41FC0EC09F6BDD900006FAE /* xar.c in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + B41FC0F109F6BE2F00006FAE /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + E9D7865D1D2606F9006D5F7D /* ea.c in Sources */, + E9D786581D260606006D5F7D /* lzmaxar.c in Sources */, + B41FC0F809F6BE9100006FAE /* archive.c in Sources */, + B41FC0F909F6BE9100006FAE /* arcmod.c in Sources */, + B41FC0FA09F6BE9100006FAE /* b64.c in Sources */, + B41FC0FB09F6BE9100006FAE /* bzxar.c in Sources */, + B41FC0FC09F6BE9100006FAE /* darwinattr.c in Sources */, + B41FC0FD09F6BE9100006FAE /* data.c in Sources */, + B41FC0FE09F6BE9100006FAE /* err.c in Sources */, + B41FC0FF09F6BE9100006FAE /* ext2.c in Sources */, + B41FC10009F6BE9100006FAE /* fbsdattr.c in Sources */, + B41FC10109F6BE9100006FAE /* filetree.c in Sources */, + B41FC10209F6BE9100006FAE /* hash.c in Sources */, + B41FC10309F6BE9100006FAE /* io.c in Sources */, + B41FC10409F6BE9100006FAE /* linuxattr.c in Sources */, + B41FC10609F6BE9100006FAE /* script.c in Sources */, + B41FC10709F6BE9100006FAE /* stat.c in Sources */, + B41FC10809F6BE9100006FAE /* subdoc.c in Sources */, + B41FC10909F6BE9100006FAE /* util.c in Sources */, + B41FC10A09F6BE9100006FAE /* zxar.c in Sources */, + B476FACF0A49E68600BCD61F /* signature.c in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + E9E06B84219E252E004DB0CA /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + E9E06B91219E257D004DB0CA /* b64.c in Sources */, + E9E06B8B219E252E004DB0CA /* main.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + EEEFF3DD0EFB6FD500DBC955 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + EEEFF3E60EFB700A00DBC955 /* xar-sig.c in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXTargetDependency section */ + B401A30309F6D71800B5C762 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = B41FC12109F6BEF900006FAE /* OpenSource */; + targetProxy = B401A30209F6D71800B5C762 /* PBXContainerItemProxy */; + }; + B41FC0D709F6BD0300006FAE /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = B41FC04F09F6B76200006FAE /* configure */; + targetProxy = B41FC0D609F6BD0300006FAE /* PBXContainerItemProxy */; + }; + B41FC11F09F6BEDE00006FAE /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = B41FC04F09F6B76200006FAE /* configure */; + targetProxy = B41FC11E09F6BEDE00006FAE /* PBXContainerItemProxy */; + }; + B41FC13109F6BF6300006FAE /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = B41FC05E09F6B7C200006FAE /* xarLib */; + targetProxy = B41FC13009F6BF6300006FAE /* PBXContainerItemProxy */; + }; + E91435401497E0F6001AA5EF /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = B41FC04F09F6B76200006FAE /* configure */; + targetProxy = E914353F1497E0F6001AA5EF /* PBXContainerItemProxy */; + }; + E91435421497E100001AA5EF /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = B41FC04F09F6B76200006FAE /* configure */; + targetProxy = E91435411497E100001AA5EF /* PBXContainerItemProxy */; + }; + E9C0E6771497DE6000BF8F0F /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = B41FC04F09F6B76200006FAE /* configure */; + targetProxy = E9C0E6761497DE6000BF8F0F /* PBXContainerItemProxy */; + }; + E9D659A81486FD6A0089C4DA /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = B41FC0E109F6BD6800006FAE /* xarTool */; + targetProxy = E9D659A71486FD6A0089C4DA /* PBXContainerItemProxy */; + }; + E9D659AA1486FD6D0089C4DA /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = EEEFF3DF0EFB6FD500DBC955 /* xarsig */; + targetProxy = E9D659A91486FD6D0089C4DA /* PBXContainerItemProxy */; + }; + E9D659B01486FFED0089C4DA /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = B41FC05E09F6B7C200006FAE /* xarLib */; + targetProxy = E9D659AF1486FFED0089C4DA /* PBXContainerItemProxy */; + }; + E9D659B21486FFED0089C4DA /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = B41FC0E109F6BD6800006FAE /* xarTool */; + targetProxy = E9D659B11486FFED0089C4DA /* PBXContainerItemProxy */; + }; + E9D659B61486FFED0089C4DA /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = B41FC12109F6BEF900006FAE /* OpenSource */; + targetProxy = E9D659B51486FFED0089C4DA /* PBXContainerItemProxy */; + }; + E9D659B81486FFED0089C4DA /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = EEEFF3DF0EFB6FD500DBC955 /* xarsig */; + targetProxy = E9D659B71486FFED0089C4DA /* PBXContainerItemProxy */; + }; + E9D7864E1D25A366006D5F7D /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = B41FC0F309F6BE2F00006FAE /* xarStatic */; + targetProxy = E9D7864D1D25A366006D5F7D /* PBXContainerItemProxy */; + }; + E9D786501D25A4B1006D5F7D /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = B41FC0F309F6BE2F00006FAE /* xarStatic */; + targetProxy = E9D7864F1D25A4B1006D5F7D /* PBXContainerItemProxy */; + }; +/* End PBXTargetDependency section */ + +/* Begin XCBuildConfiguration section */ + B41FC04309F6B74500006FAE /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + COPY_PHASE_STRIP = NO; + CURRENT_PROJECT_VERSION = 1; + DYLIB_COMPATIBILITY_VERSION = 1.0; + DYLIB_CURRENT_VERSION = 1.3; + ENABLE_TESTABILITY = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = macosx.internal; + STRIP_STYLE = debugging; + VALID_ARCHS = "i386 x86_64"; + VERSIONING_SYSTEM = "apple-generic"; + }; + name = Debug; + }; + B41FC04409F6B74500006FAE /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + COPY_PHASE_STRIP = YES; + CURRENT_PROJECT_VERSION = "$(RC_ProjectSourceVersion)"; + DYLIB_COMPATIBILITY_VERSION = 1.0; + DYLIB_CURRENT_VERSION = 1.3; + SDKROOT = macosx.internal; + VALID_ARCHS = "i386 x86_64"; + VERSIONING_SYSTEM = "apple-generic"; + }; + name = Release; + }; + B41FC05209F6B77E00006FAE /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + COPY_PHASE_STRIP = NO; + GCC_DYNAMIC_NO_PIC = NO; + GCC_GENERATE_DEBUGGING_SYMBOLS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + PRODUCT_NAME = configure; + }; + name = Debug; + }; + B41FC05309F6B77E00006FAE /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + COPY_PHASE_STRIP = YES; + GCC_ENABLE_FIX_AND_CONTINUE = NO; + GCC_GENERATE_DEBUGGING_SYMBOLS = NO; + PRODUCT_NAME = configure; + ZERO_LINK = NO; + }; + name = Release; + }; + B41FC06209F6B7C300006FAE /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 7C7F76CC2202351600155C33 /* xar.xcconfig */; + buildSettings = { + COMBINE_HIDPI_IMAGES = YES; + COPY_PHASE_STRIP = NO; + EXECUTABLE_PREFIX = lib; + GCC_DYNAMIC_NO_PIC = NO; + GCC_ENABLE_FIX_AND_CONTINUE = YES; + GCC_MODEL_TUNING = G5; + GCC_OPTIMIZATION_LEVEL = 0; + HEADER_SEARCH_PATHS = ( + "$(inherited)", + /usr/include/libxml2, + "$(TARGET_BUILD_DIR)/include", + ); + INSTALL_PATH = /usr/lib; + LIBRARY_SEARCH_PATHS = ( + "$(inherited)", + "$(SDKROOT)/usr/lib/system", + ); + PREBINDING = NO; + PRODUCT_NAME = xar.1; + VERSIONING_SYSTEM = "apple-generic"; + ZERO_LINK = YES; + }; + name = Debug; + }; + B41FC06309F6B7C300006FAE /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 7C7F76CC2202351600155C33 /* xar.xcconfig */; + buildSettings = { + COMBINE_HIDPI_IMAGES = YES; + COPY_PHASE_STRIP = YES; + EXECUTABLE_PREFIX = lib; + GCC_ENABLE_FIX_AND_CONTINUE = NO; + GCC_MODEL_TUNING = G5; + HEADER_SEARCH_PATHS = ( + "$(inherited)", + /usr/include/libxml2, + "$(TARGET_BUILD_DIR)/include", + ); + INSTALL_PATH = /usr/lib; + LIBRARY_SEARCH_PATHS = ( + "$(inherited)", + "$(SDKROOT)/usr/lib/system", + ); + PREBINDING = NO; + PRODUCT_NAME = xar.1; + VERSIONING_SYSTEM = "apple-generic"; + ZERO_LINK = NO; + }; + name = Release; + }; + B41FC0E709F6BD8C00006FAE /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + COPY_PHASE_STRIP = NO; + GCC_DYNAMIC_NO_PIC = NO; + GCC_ENABLE_FIX_AND_CONTINUE = YES; + GCC_MODEL_TUNING = G5; + GCC_OPTIMIZATION_LEVEL = 0; + HEADER_SEARCH_PATHS = ( + "$(inherited)", + /usr/include/libxml2, + "$(TARGET_BUILD_DIR)/include", + ); + INSTALL_PATH = /usr/bin; + PREBINDING = NO; + PRODUCT_NAME = xar; + ZERO_LINK = YES; + }; + name = Debug; + }; + B41FC0E809F6BD8C00006FAE /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + COPY_PHASE_STRIP = YES; + GCC_ENABLE_FIX_AND_CONTINUE = NO; + GCC_MODEL_TUNING = G5; + HEADER_SEARCH_PATHS = ( + "$(inherited)", + /usr/include/libxml2, + "$(TARGET_BUILD_DIR)/include", + ); + INSTALL_PATH = /usr/bin; + PREBINDING = NO; + PRODUCT_NAME = xar; + ZERO_LINK = NO; + }; + name = Release; + }; + B41FC0F609F6BE7F00006FAE /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + COMBINE_HIDPI_IMAGES = YES; + COPY_PHASE_STRIP = NO; + GCC_DYNAMIC_NO_PIC = NO; + GCC_ENABLE_FIX_AND_CONTINUE = YES; + GCC_MODEL_TUNING = G5; + GCC_OPTIMIZATION_LEVEL = 0; + HEADER_SEARCH_PATHS = ( + "$(inherited)", + /usr/include/libxml2, + "$(TARGET_BUILD_DIR)/include", + ); + INSTALL_PATH = /usr/local/lib; + MACOSX_DEPLOYMENT_TARGET = 10.8; + PREBINDING = NO; + PRODUCT_NAME = xarstatic; + VERSIONING_SYSTEM = "apple-generic"; + ZERO_LINK = YES; + }; + name = Debug; + }; + B41FC0F709F6BE7F00006FAE /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + COMBINE_HIDPI_IMAGES = YES; + COPY_PHASE_STRIP = YES; + GCC_ENABLE_FIX_AND_CONTINUE = NO; + GCC_MODEL_TUNING = G5; + HEADER_SEARCH_PATHS = ( + "$(inherited)", + /usr/include/libxml2, + "$(TARGET_BUILD_DIR)/include", + ); + INSTALL_PATH = /usr/local/lib; + MACOSX_DEPLOYMENT_TARGET = 10.8; + PREBINDING = NO; + PRODUCT_NAME = xarstatic; + VERSIONING_SYSTEM = "apple-generic"; + ZERO_LINK = NO; + }; + name = Release; + }; + B41FC12809F6BF3300006FAE /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + COPY_PHASE_STRIP = NO; + GCC_DYNAMIC_NO_PIC = NO; + GCC_OPTIMIZATION_LEVEL = 0; + PRODUCT_NAME = OpenSource; + }; + name = Debug; + }; + B41FC12909F6BF3300006FAE /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + COPY_PHASE_STRIP = YES; + GCC_ENABLE_FIX_AND_CONTINUE = NO; + PRODUCT_NAME = OpenSource; + ZERO_LINK = NO; + }; + name = Release; + }; + B41FC13809F6BF7900006FAE /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + COPY_PHASE_STRIP = NO; + GCC_DYNAMIC_NO_PIC = NO; + GCC_GENERATE_DEBUGGING_SYMBOLS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + PRODUCT_NAME = All; + }; + name = Debug; + }; + B41FC13909F6BF7900006FAE /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + COPY_PHASE_STRIP = YES; + GCC_ENABLE_FIX_AND_CONTINUE = NO; + GCC_GENERATE_DEBUGGING_SYMBOLS = NO; + PRODUCT_NAME = All; + ZERO_LINK = NO; + }; + name = Release; + }; + E9D659A51486FD650089C4DA /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Debug; + }; + E9D659A61486FD650089C4DA /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Release; + }; + E9D659AD1486FFD10089C4DA /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Debug; + }; + E9D659AE1486FFD10089C4DA /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Release; + }; + E9E06B8C219E252E004DB0CA /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = "-"; + CODE_SIGN_STYLE = Automatic; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.15; + MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; + MTL_FAST_MATH = YES; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = macosx; + }; + name = Debug; + }; + E9E06B8D219E252E004DB0CA /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = "-"; + CODE_SIGN_STYLE = Automatic; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.15; + MTL_ENABLE_DEBUG_INFO = NO; + MTL_FAST_MATH = YES; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = macosx; + }; + name = Release; + }; + EEEFF3E20EFB6FD600DBC955 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + COPY_PHASE_STRIP = NO; + GCC_DYNAMIC_NO_PIC = NO; + GCC_ENABLE_FIX_AND_CONTINUE = YES; + GCC_MODEL_TUNING = G5; + GCC_OPTIMIZATION_LEVEL = 0; + HEADER_SEARCH_PATHS = /usr/include/libxml2; + INSTALL_PATH = /usr/local/bin; + OTHER_CFLAGS = "-DXARSIG_BUILDING_WITH_XAR"; + PREBINDING = NO; + PRODUCT_NAME = xarsig; + }; + name = Debug; + }; + EEEFF3E30EFB6FD600DBC955 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + COPY_PHASE_STRIP = YES; + GCC_ENABLE_FIX_AND_CONTINUE = NO; + GCC_MODEL_TUNING = G5; + HEADER_SEARCH_PATHS = /usr/include/libxml2; + INSTALL_PATH = /usr/local/bin; + OTHER_CFLAGS = "-DXARSIG_BUILDING_WITH_XAR"; + PREBINDING = NO; + PRODUCT_NAME = xarsig; + ZERO_LINK = NO; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + B41FC04209F6B74500006FAE /* Build configuration list for PBXProject "xar" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + B41FC04309F6B74500006FAE /* Debug */, + B41FC04409F6B74500006FAE /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + B41FC05109F6B77E00006FAE /* Build configuration list for PBXAggregateTarget "configure" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + B41FC05209F6B77E00006FAE /* Debug */, + B41FC05309F6B77E00006FAE /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + B41FC06109F6B7C300006FAE /* Build configuration list for PBXNativeTarget "xarLib" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + B41FC06209F6B7C300006FAE /* Debug */, + B41FC06309F6B7C300006FAE /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + B41FC0E609F6BD8C00006FAE /* Build configuration list for PBXNativeTarget "xarTool" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + B41FC0E709F6BD8C00006FAE /* Debug */, + B41FC0E809F6BD8C00006FAE /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + B41FC0F509F6BE7F00006FAE /* Build configuration list for PBXNativeTarget "xarStatic" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + B41FC0F609F6BE7F00006FAE /* Debug */, + B41FC0F709F6BE7F00006FAE /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + B41FC12709F6BF3300006FAE /* Build configuration list for PBXAggregateTarget "OpenSource" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + B41FC12809F6BF3300006FAE /* Debug */, + B41FC12909F6BF3300006FAE /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + B41FC13709F6BF7900006FAE /* Build configuration list for PBXAggregateTarget "All libraries" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + B41FC13809F6BF7900006FAE /* Debug */, + B41FC13909F6BF7900006FAE /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + E9D659A41486FD650089C4DA /* Build configuration list for PBXAggregateTarget "All tools" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + E9D659A51486FD650089C4DA /* Debug */, + E9D659A61486FD650089C4DA /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + E9D659AC1486FFD10089C4DA /* Build configuration list for PBXAggregateTarget "All" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + E9D659AD1486FFD10089C4DA /* Debug */, + E9D659AE1486FFD10089C4DA /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + E9E06B8E219E252E004DB0CA /* Build configuration list for PBXNativeTarget "test_xar" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + E9E06B8C219E252E004DB0CA /* Debug */, + E9E06B8D219E252E004DB0CA /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + EEEFF3E50EFB6FDA00DBC955 /* Build configuration list for PBXNativeTarget "xarsig" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + EEEFF3E20EFB6FD600DBC955 /* Debug */, + EEEFF3E30EFB6FD600DBC955 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = B41FC04109F6B74500006FAE /* Project object */; +} diff --git a/xar.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/xar.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100644 index 0000000..fe264ae --- /dev/null +++ b/xar.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/xar/.cvsignore b/xar/.cvsignore new file mode 100644 index 0000000..34a72f4 --- /dev/null +++ b/xar/.cvsignore @@ -0,0 +1,7 @@ +Makefile +autom4te.cache +cfghdrs.stamp +cfgoutputs.stamp +configure +config.log +config.status diff --git a/xar/ChangeLog b/xar/ChangeLog new file mode 100644 index 0000000..41eea7b --- /dev/null +++ b/xar/ChangeLog @@ -0,0 +1,68 @@ +devel + 2008-08-19 Rob Braun bbraun@synack.net + * lib/lzmaxar.c: if lzma compression is specified but not compiled in, throw an error. + * src/xar.c: When extracting, save directories until the end. This lets timestamps get set correctly on directories and addresses issue #58. + 2008-08-17 Rob Braun bbraun@synack.net + * lib/archive.c: Make sure the binary header and toc checksum types match. Contributed by Apple. + 2008-08-15 Rob Braun bbraun@synack.net + * lib/Makefile.inc.in: Add the $(LDFLAGS) variable when creating libxar + * src/xar.c: Fix a typo in the usage statement. + * lib/io.c: Fix seeking on a pipe + 2008-08-14 Rob Braun bbraun@synack.net + * lib/bzxar.c: if bzip2 compression is specified but not compiled in, throw an error. + * src/xar.c src/xar.1: Add -C to chdir before extraction. + * lib/script.c: Perform some input checking. + * lib/b64.c lib/b64.h: xar_to_base64() was never used, so it is removed. + * lib/lzmaxar.c: Update the use of the lzma API to match 4.42 alpha 6 of the lzma library from Anders F Björklund. + 2007-12-14 Rob Braun bbraun@synack.net + * configure.ac: Fix a broken configure check for sys/acl.h and acl_t + 2007-12-09 Rob Braun bbraun@synack.net + * include/xar.h.in lib/filetree.c lib/stat.c test/validate.c: Make sure xar_iter_new() takes no parameters. From rpm5. + * lib/libxar.la.in.in: set the libxir to @LIBDIR@ from autoconf. From rpm5. + * configure.ac: Allow specifying the path to lzma with --with-lzma=PATH + * lib/lzmaxar.c: Use the global macro for compression level. + 2007-11-11 Rob Braun bbraun@synack.net + * lib/archive.c: Add a #define for a mising function in Mac OS X's old version of libxml2 from Anders F Björklund. + * lib/Makefile.inc.in: Be a little more gnu libtool friendly from Anders F Björklund. + 2007-11-11 Rob Braun bbraun@synack.net + * lib/archive.c: Some memory leak cleanups from Anders F Björklund. + 2007-11-1 Dave Leimbach leimy2k@gmail.com + * lib/data.c: fixed a file descriptor leak by adding a close before return + * src/xar.1: Added man page text for --extract-subdoc + 2007-10-22 Rob Braun bbraun@synack.net + * src/xar.c src/xar.1: Add -a as a synonym for --compression=lzma + * lib/darwinattr.c lib/fbsdattr.c: Add --prop-exclude support for darwin and fbsd EAs. + 2007-10-16 Rob Braun bbraun@synack.net + * include/xar.h.in src/xar.c lib/io.c lib/lzmaxar.c lib/bzxar.c lib/archive.c lib/zxar.c: Added an option to pass arguments to the compression code. This to allow specifying compression levels to gzip, bzip2, and lzma. + * lib/io.c: Issue 41, fixed a bug where rsize was being used uninitialized. + * lib/io.c: Issue 42, log a warning and continue if archived-checksum doesn't appear when archiving a file. + * lib/archive.c: Issue 43, free the buffer in xar_extract_tobuffersz() if there is an error extracting the file. + 2007-10-02 Rob Braun bbraun@synack.net + * test/compression test/data include/config.h.in include/xar.h.in src/xar.1 src/xar.c configure.ac lib/lzmaxar.c lib/lzmaxar.h lib/io.c lib/bzxar.c lib/Makefile.inc.in lib/zxar.c INSTALL: Incorporate a patch from anders.f.bjorklund for adding lzma compression support. + 2007-10-02 Rob Braun bbraun@synack.net + * include/xar.h.in lib/io.c lib/io.h lib/archive.c: Add a "streaming" API that allows for file data to be extracted incrementally, like the zlib decompression API, instead of requiring the entire file to fit in memory like xar_extract_tobuffer(). This is the inital commit of the API and may still change. This change is based on a patch from Charles Srstka. + 2007-09-26 Rob Braun bbraun@synack.net + * lib/io.c: Consolidate the lseek handling code into one function. + Contributed by Charles Srstka as part of Issue 2. + 2007-09-21 Rob Braun bbraun@synack.net + * include/xar.h.in src/xar.c src/xar.1 lib/stat.c: Only extract setuid/setgid bits if the user/group are the same as the archived file (if -p/-P are specified on the command line) OR if the newly added --keep-setuid flag is specified. + * configure.ac lib/stat.c: Fix the autoconf test for ino_t size, and switch the inode and device number printf's to use the autogenerated INO_STRING and DEV_STRING to get the correct formatting parameter. + 2007-09-20 Rob Braun bbraun@synack.net + * src/xar.c src/xar.1: Add -k as a synonym for --keep-existing for tar compatibility. + 2007-09-20 Rob Braun bbraun@synack.net + * src/xar.c src/xar.1: Add --keep-existing flag which prevents existing files from being extracted. + 2007-09-20 Rob Braun bbraun@synack.net + * lib/archive.c: Fix a bug in toc parsing where invalid tocs, particularly with mismatched closing tags, would still be processed. + 2007-09-20 Rob Braun bbraun@synack.net + * lib/filetree.c: Fix a minor memory leak with xar_iter_free() not freeing all memory associated with a xar_iter_t. + 2007-09-20 Rob Braun bbraun@synack.net + * ChangeLog: renamed from CHANGELOG. + 2007-09-19 Dave Leimbach leimy2k@gmail.com + * xar/xar.c xar/xar.1: Added support for -j and -z as shortcuts for --compression=bzip2 or --compression=zlib respectively. + 2007-09-19 Rob Braun bbraun@synack.net + * lib/zxar.c lib/bzxar.c: cleanup for more consistency between the two compression modules. Patch contributed by Anders Björklund from the rpm5 project. + 2007-09-19 Rob Braun bbraun@synack.net + * CHANGELOG: Added changelog + * include/xar.h.in src/xar.c lib/util.c: moved helper functions for retrieving and formating file properties such as size, mode, mtime, etc. from src/xar.c to lib/util.c and exported them in xar.h. + * lib/err.c lib/archive.h: Added the xar_t archive context to the error handler context to be able to retrieve archive level context within an error, such as archive level options, or being able to examine other files than the one the error occurred on. + * lib/strmode.h lib/util.c config.h.in configure.ac: Import strmode(3) from freebsd to handle the formatting of file mode in xar_get_mode(), used for displaying file mode from xar -tvf. configure will automatically detect whether to use the OS strmode(3) or the included copy. diff --git a/xar/INSTALL b/xar/INSTALL new file mode 100644 index 0000000..b126db1 --- /dev/null +++ b/xar/INSTALL @@ -0,0 +1,160 @@ +################################################################################ +# +# Building and installation instructions for the Xar source distribution. +# +################################################################################ + +Required: Xar's build system uses GNU make. + +Required: Xar depends on libxml2's XML functionality. For more information + about libxml2, see: + + http://www.xmlsoft.org/ + +Required: Xar depends on OpenSSL (libcrypto in particular) for MD5 and SHA1 + functionality. For more information about OpenSSL, see: + + http://www.openssl.org/ + +Required: Xar depends on zlib (libz) for data compression. For more information + about zlib, see: + + http://www.zlib.net/ + +Optional: Xar can optionally use libbzip2 for data compression. For more + information about libbzip2, see: + + http://www.bzip.org/ + +Optional: Xar can optionally use liblzma for data compression. For more + information about liblzma, see: + + http://tukaani.org/lzma/ + +Optional: Regenerating the configure script requires GNU autoconf. Doing so is + only necessary when making changes to the configuration system. + +################################################################################ + +Building Xar is in many cases as simple as typing the following commands while +in the root directory of the source tree: + + ./configure + make + +To install, do the above, then type: + + make install + +Additional build targets of finer granularity include: + + src_all + lib_all + +Additional install targets of finer granularity include: + + src_install + lib_install + +Uninstall targets include: + + uninstall + src_uninstall + lib_uninstall + +Cleanup targets include: + + clean + distclean + relclean + +Note that if you are using a development version of xar, configure is +not checked into the repository. You may replace the ./configure step +above with ./autogen.sh. + +################################################################################ + +The build system is capable of building in a different directory than the +source, so that no files are written to the source tree. In order to use this +feature, run 'configure' and 'make' while in the directory that you want to +build the software in. + +Optionally, pass any of the following arguments to 'configure' (run 'configure' +with the --help option for a full list): + +--prefix= + Set the base directory in which to install. For example: + + ./configure --prefix=/usr/local + + will cause files to be installed into /usr/local/bin, /usr/local/man, + /usr/local/include, /usr/local/lib, and /usr/local/share. + +--enable-autogen + Include dependency rules in the build system to automatically regenerate + files created by configure when their sources are newer. This is + only of interest when making modifications to the source code. + +--with-xml2-config= + If specified, use as the full path (including filename) to the + xml2-config program. This is useful when there is more than one copy of + xml2-config in your shell's path, or when you want to use a copy of + xml2-config that is not in your shell's path at all. + +Optionally, define environment variables when invoking configure, including (not +exclusively): + +CFLAGS="?" + Pass these flags to the compiler. + +CPPFLAGS="?" + Pass these flags to the C preprocessor. Note that CFLAGS is not passed + to 'cpp' when 'configure' is looking for include files, so you must use + CPPFLAGS instead if you need to help 'configure' find header files. + +LD_LIBRARY_PATH="?" + 'ld' uses this colon-separated list to find libraries. + +LDFLAGS="?" + Pass these flags when linking. + +PATH="?" + 'configure' uses this to find programs. + +################################################################################ + +Optionally, define make variables when invoking make, including (not +exclusively): + +PREFIX="?" + Use this as the installation prefix. + +BINDIR="?" + Use this as the installation prefix for programs. + +DATADIR="?" + Use this as the installation prefix for modules and documentation. + +LIBDIR="?" + Use this as the installation prefix for libraries. + +INCLUDEDIR="?" + Use this as the installation prefix for header files. + +MANDIR="?" + Use this as the installation prefix for man pages. + +CC="?" + Use this to specify the C compiler. + +CFLAGS="?" + Pass these flags to the compiler. + +CPPFLAGS="?" + Pass these flags to the C preprocessor. + +LDFLAGS="?" + Pass these flags when linking. + +PATH="?" + Use this to search for programs used during configuration and building. diff --git a/xar/LICENSE b/xar/LICENSE new file mode 100644 index 0000000..b8630ba --- /dev/null +++ b/xar/LICENSE @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2005-2007 Rob Braun + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Rob Braun nor the names of his contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +/* + * 03-Apr-2005 + * DRI: Rob Braun + */ + diff --git a/xar/Makefile.in b/xar/Makefile.in new file mode 100644 index 0000000..a6d6814 --- /dev/null +++ b/xar/Makefile.in @@ -0,0 +1,108 @@ +# Clear out all vpaths, then set just one (default vpath) for the main build +# directory. +vpath +vpath % . + +# Clear the default suffixes, so that built-in rules are not used. +.SUFFIXES : + +# +# Standard definitions. +# + +SHELL := /bin/sh +CC := @CC@ +LD := @LD@ +AR := @AR@ +RANLIB := @RANLIB@ +INSTALL := @INSTALL@ +AUTOCONF := @AUTOCONF@ + +# +# Build parameters. +# + +CPPFLAGS := @CPPFLAGS@ +CFLAGS := @CFLAGS@ +A_CFLAGS := $(CFLAGS) +S_CFLAGS := $(CFLAGS) -fPIC -DPIC +ifeq (macho, @abi@) +S_CFLAGS += -dynamic +endif +LDFLAGS := @LDFLAGS@ + +prefix := @PREFIX@ +bindir := @BINDIR@ +datadir := @DATADIR@ +libdir := @LIBDIR@ +includedir := @INCLUDEDIR@ +mandir := @MANDIR@ + +PREFIX := $(prefix) +BINDIR := $(bindir) +DATADIR := $(datadir) +LIBDIR := $(libdir) +INCLUDEDIR := $(includedir) +MANDIR := $(mandir) + +dir_names := lib src + +all : $(dir_names:%=%_all) + +install : $(dir_names:%=%_install) + +uninstall : $(dir_names:%=%_uninstall) + +clean : $(dir_names:%=%_clean) + +distclean : clean $(dir_names:%=%_distclean) + rm -f @objroot@config.log + rm -f @objroot@config.status + rm -f @objroot@cfghdrs.stamp + rm -f @objroot@cfgoutputs.stamp + rm -f @objroot@configure.lineno + rm -f @cfghdrs@ + rm -f @cfgoutputs@ + rm -rf @objroot@autom4te.cache + +relclean : distclean + rm -f @objroot@configure + +# Include Makefile.inc files in subdirectories. +include $(dir_names:%=%/Makefile.inc) + +# +# Re-configuration rules. +# +ifeq (@enable_autogen@, 1) +@srcroot@configure : @srcroot@configure.ac + cd ./@srcroot@ && $(AUTOCONF) + +@objroot@config.status : @srcroot@configure + ./@objroot@config.status --recheck + +# cfghdrs rules. +@srcroot@cfghdrs.stamp.in : @srcroot@configure.ac + echo stamp > @srcroot@cfghdrs.stamp.in + +$(patsubst %, @srcroot@%.in, @cfghdrs@) : @objroot@config.status + +@objroot@cfghdrs.stamp : $(patsubst %, @srcroot@%.in, @cfghdrs@) + ./@objroot@config.status + echo stamp > $@ + +$(filter-out @objroot@cfghdrs.stamp, @cfghdrs@) : @objroot@cfghdrs.stamp + +# cfgoutputs rules. +@srcroot@cfgoutputs.stamp.in : @srcroot@configure.ac + echo stamp > @srcroot@cfgoutputs.stamp.in + +$(patsubst %, @srcroot@%.in, @cfgoutputs@) : @objroot@config.status + +@objroot@cfgoutputs.stamp : $(patsubst %, @srcroot@%.in, @cfgoutputs@) + ./@objroot@config.status + +$(filter-out \ + @objroot@cfgoutputs.stamp, \ + $(patsubst %, @objroot@%, @cfgoutputs@)) : @objroot@cfgoutputs.stamp +endif diff --git a/xar/TODO b/xar/TODO new file mode 100644 index 0000000..19b82e3 --- /dev/null +++ b/xar/TODO @@ -0,0 +1,2 @@ +The xar TODO exists primarily on the wiki site at: +http://wiki.opendarwin.org/index.php/Xar:Todo diff --git a/xar/autogen.sh b/xar/autogen.sh new file mode 100644 index 0000000..a7e9085 --- /dev/null +++ b/xar/autogen.sh @@ -0,0 +1,21 @@ +#!/bin/sh + +for i in autoconf; do + echo "$i" + $i + if [ $? -ne 0 ]; then + echo "Error $? in $i" + exit 1 + fi +done + +if [ "$1" = "--noconfigure" ]; then + exit 0; +fi + +echo "./configure --enable-autogen $@" +./configure --enable-autogen $@ +if [ $? -ne 0 ]; then + echo "Error $? in ./configure" + exit 1 +fi diff --git a/xar/cfghdrs.stamp b/xar/cfghdrs.stamp new file mode 100644 index 0000000..b8ec342 --- /dev/null +++ b/xar/cfghdrs.stamp @@ -0,0 +1,2 @@ +/* cfghdrs.stamp. Generated from cfghdrs.stamp.in by configure. */ +stamp diff --git a/xar/cfghdrs.stamp.in b/xar/cfghdrs.stamp.in new file mode 100644 index 0000000..859afb1 --- /dev/null +++ b/xar/cfghdrs.stamp.in @@ -0,0 +1 @@ +stamp diff --git a/xar/cfgoutputs.stamp b/xar/cfgoutputs.stamp new file mode 100644 index 0000000..859afb1 --- /dev/null +++ b/xar/cfgoutputs.stamp @@ -0,0 +1 @@ +stamp diff --git a/xar/cfgoutputs.stamp.in b/xar/cfgoutputs.stamp.in new file mode 100644 index 0000000..859afb1 --- /dev/null +++ b/xar/cfgoutputs.stamp.in @@ -0,0 +1 @@ +stamp diff --git a/xar/config.guess b/xar/config.guess new file mode 100644 index 0000000..ad5281e --- /dev/null +++ b/xar/config.guess @@ -0,0 +1,1466 @@ +#! /bin/sh +# Attempt to guess a canonical system name. +# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, +# 2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc. + +timestamp='2005-08-03' + +# This file is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA +# 02110-1301, USA. +# +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + + +# Originally written by Per Bothner . +# Please send patches to . Submit a context +# diff and a properly formatted ChangeLog entry. +# +# This script attempts to guess a canonical system name similar to +# config.sub. If it succeeds, it prints the system name on stdout, and +# exits with 0. Otherwise, it exits with 1. +# +# The plan is that this can be called by configure scripts if you +# don't specify an explicit build system type. + +me=`echo "$0" | sed -e 's,.*/,,'` + +usage="\ +Usage: $0 [OPTION] + +Output the configuration name of the system \`$me' is run on. + +Operation modes: + -h, --help print this help, then exit + -t, --time-stamp print date of last modification, then exit + -v, --version print version number, then exit + +Report bugs and patches to ." + +version="\ +GNU config.guess ($timestamp) + +Originally written by Per Bothner. +Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005 +Free Software Foundation, Inc. + +This is free software; see the source for copying conditions. There is NO +warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." + +help=" +Try \`$me --help' for more information." + +# Parse command line +while test $# -gt 0 ; do + case $1 in + --time-stamp | --time* | -t ) + echo "$timestamp" ; exit ;; + --version | -v ) + echo "$version" ; exit ;; + --help | --h* | -h ) + echo "$usage"; exit ;; + -- ) # Stop option processing + shift; break ;; + - ) # Use stdin as input. + break ;; + -* ) + echo "$me: invalid option $1$help" >&2 + exit 1 ;; + * ) + break ;; + esac +done + +if test $# != 0; then + echo "$me: too many arguments$help" >&2 + exit 1 +fi + +trap 'exit 1' 1 2 15 + +# CC_FOR_BUILD -- compiler used by this script. Note that the use of a +# compiler to aid in system detection is discouraged as it requires +# temporary files to be created and, as you can see below, it is a +# headache to deal with in a portable fashion. + +# Historically, `CC_FOR_BUILD' used to be named `HOST_CC'. We still +# use `HOST_CC' if defined, but it is deprecated. + +# Portable tmp directory creation inspired by the Autoconf team. + +set_cc_for_build=' +trap "exitcode=\$?; (rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null) && exit \$exitcode" 0 ; +trap "rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null; exit 1" 1 2 13 15 ; +: ${TMPDIR=/tmp} ; + { tmp=`(umask 077 && mktemp -d -q "$TMPDIR/cgXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" ; } || + { test -n "$RANDOM" && tmp=$TMPDIR/cg$$-$RANDOM && (umask 077 && mkdir $tmp) ; } || + { tmp=$TMPDIR/cg-$$ && (umask 077 && mkdir $tmp) && echo "Warning: creating insecure temp directory" >&2 ; } || + { echo "$me: cannot create a temporary directory in $TMPDIR" >&2 ; exit 1 ; } ; +dummy=$tmp/dummy ; +tmpfiles="$dummy.c $dummy.o $dummy.rel $dummy" ; +case $CC_FOR_BUILD,$HOST_CC,$CC in + ,,) echo "int x;" > $dummy.c ; + for c in cc gcc c89 c99 ; do + if ($c -c -o $dummy.o $dummy.c) >/dev/null 2>&1 ; then + CC_FOR_BUILD="$c"; break ; + fi ; + done ; + if test x"$CC_FOR_BUILD" = x ; then + CC_FOR_BUILD=no_compiler_found ; + fi + ;; + ,,*) CC_FOR_BUILD=$CC ;; + ,*,*) CC_FOR_BUILD=$HOST_CC ;; +esac ; set_cc_for_build= ;' + +# This is needed to find uname on a Pyramid OSx when run in the BSD universe. +# (ghazi@noc.rutgers.edu 1994-08-24) +if (test -f /.attbin/uname) >/dev/null 2>&1 ; then + PATH=$PATH:/.attbin ; export PATH +fi + +UNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown +UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown +UNAME_SYSTEM=`(uname -s) 2>/dev/null` || UNAME_SYSTEM=unknown +UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown + +# Note: order is significant - the case branches are not exclusive. + +case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in + *:NetBSD:*:*) + # NetBSD (nbsd) targets should (where applicable) match one or + # more of the tupples: *-*-netbsdelf*, *-*-netbsdaout*, + # *-*-netbsdecoff* and *-*-netbsd*. For targets that recently + # switched to ELF, *-*-netbsd* would select the old + # object file format. This provides both forward + # compatibility and a consistent mechanism for selecting the + # object file format. + # + # Note: NetBSD doesn't particularly care about the vendor + # portion of the name. We always set it to "unknown". + sysctl="sysctl -n hw.machine_arch" + UNAME_MACHINE_ARCH=`(/sbin/$sysctl 2>/dev/null || \ + /usr/sbin/$sysctl 2>/dev/null || echo unknown)` + case "${UNAME_MACHINE_ARCH}" in + armeb) machine=armeb-unknown ;; + arm*) machine=arm-unknown ;; + sh3el) machine=shl-unknown ;; + sh3eb) machine=sh-unknown ;; + *) machine=${UNAME_MACHINE_ARCH}-unknown ;; + esac + # The Operating System including object format, if it has switched + # to ELF recently, or will in the future. + case "${UNAME_MACHINE_ARCH}" in + arm*|i386|m68k|ns32k|sh3*|sparc|vax) + eval $set_cc_for_build + if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \ + | grep __ELF__ >/dev/null + then + # Once all utilities can be ECOFF (netbsdecoff) or a.out (netbsdaout). + # Return netbsd for either. FIX? + os=netbsd + else + os=netbsdelf + fi + ;; + *) + os=netbsd + ;; + esac + # The OS release + # Debian GNU/NetBSD machines have a different userland, and + # thus, need a distinct triplet. However, they do not need + # kernel version information, so it can be replaced with a + # suitable tag, in the style of linux-gnu. + case "${UNAME_VERSION}" in + Debian*) + release='-gnu' + ;; + *) + release=`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'` + ;; + esac + # Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM: + # contains redundant information, the shorter form: + # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used. + echo "${machine}-${os}${release}" + exit ;; + *:OpenBSD:*:*) + UNAME_MACHINE_ARCH=`arch | sed 's/OpenBSD.//'` + echo ${UNAME_MACHINE_ARCH}-unknown-openbsd${UNAME_RELEASE} + exit ;; + *:ekkoBSD:*:*) + echo ${UNAME_MACHINE}-unknown-ekkobsd${UNAME_RELEASE} + exit ;; + macppc:MirBSD:*:*) + echo powerppc-unknown-mirbsd${UNAME_RELEASE} + exit ;; + *:MirBSD:*:*) + echo ${UNAME_MACHINE}-unknown-mirbsd${UNAME_RELEASE} + exit ;; + alpha:OSF1:*:*) + case $UNAME_RELEASE in + *4.0) + UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'` + ;; + *5.*) + UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $4}'` + ;; + esac + # According to Compaq, /usr/sbin/psrinfo has been available on + # OSF/1 and Tru64 systems produced since 1995. I hope that + # covers most systems running today. This code pipes the CPU + # types through head -n 1, so we only detect the type of CPU 0. + ALPHA_CPU_TYPE=`/usr/sbin/psrinfo -v | sed -n -e 's/^ The alpha \(.*\) processor.*$/\1/p' | head -n 1` + case "$ALPHA_CPU_TYPE" in + "EV4 (21064)") + UNAME_MACHINE="alpha" ;; + "EV4.5 (21064)") + UNAME_MACHINE="alpha" ;; + "LCA4 (21066/21068)") + UNAME_MACHINE="alpha" ;; + "EV5 (21164)") + UNAME_MACHINE="alphaev5" ;; + "EV5.6 (21164A)") + UNAME_MACHINE="alphaev56" ;; + "EV5.6 (21164PC)") + UNAME_MACHINE="alphapca56" ;; + "EV5.7 (21164PC)") + UNAME_MACHINE="alphapca57" ;; + "EV6 (21264)") + UNAME_MACHINE="alphaev6" ;; + "EV6.7 (21264A)") + UNAME_MACHINE="alphaev67" ;; + "EV6.8CB (21264C)") + UNAME_MACHINE="alphaev68" ;; + "EV6.8AL (21264B)") + UNAME_MACHINE="alphaev68" ;; + "EV6.8CX (21264D)") + UNAME_MACHINE="alphaev68" ;; + "EV6.9A (21264/EV69A)") + UNAME_MACHINE="alphaev69" ;; + "EV7 (21364)") + UNAME_MACHINE="alphaev7" ;; + "EV7.9 (21364A)") + UNAME_MACHINE="alphaev79" ;; + esac + # A Pn.n version is a patched version. + # A Vn.n version is a released version. + # A Tn.n version is a released field test version. + # A Xn.n version is an unreleased experimental baselevel. + # 1.2 uses "1.2" for uname -r. + echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[PVTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` + exit ;; + Alpha\ *:Windows_NT*:*) + # How do we know it's Interix rather than the generic POSIX subsystem? + # Should we change UNAME_MACHINE based on the output of uname instead + # of the specific Alpha model? + echo alpha-pc-interix + exit ;; + 21064:Windows_NT:50:3) + echo alpha-dec-winnt3.5 + exit ;; + Amiga*:UNIX_System_V:4.0:*) + echo m68k-unknown-sysv4 + exit ;; + *:[Aa]miga[Oo][Ss]:*:*) + echo ${UNAME_MACHINE}-unknown-amigaos + exit ;; + *:[Mm]orph[Oo][Ss]:*:*) + echo ${UNAME_MACHINE}-unknown-morphos + exit ;; + *:OS/390:*:*) + echo i370-ibm-openedition + exit ;; + *:z/VM:*:*) + echo s390-ibm-zvmoe + exit ;; + *:OS400:*:*) + echo powerpc-ibm-os400 + exit ;; + arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*) + echo arm-acorn-riscix${UNAME_RELEASE} + exit ;; + arm:riscos:*:*|arm:RISCOS:*:*) + echo arm-unknown-riscos + exit ;; + SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*) + echo hppa1.1-hitachi-hiuxmpp + exit ;; + Pyramid*:OSx*:*:* | MIS*:OSx*:*:* | MIS*:SMP_DC-OSx*:*:*) + # akee@wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE. + if test "`(/bin/universe) 2>/dev/null`" = att ; then + echo pyramid-pyramid-sysv3 + else + echo pyramid-pyramid-bsd + fi + exit ;; + NILE*:*:*:dcosx) + echo pyramid-pyramid-svr4 + exit ;; + DRS?6000:unix:4.0:6*) + echo sparc-icl-nx6 + exit ;; + DRS?6000:UNIX_SV:4.2*:7* | DRS?6000:isis:4.2*:7*) + case `/usr/bin/uname -p` in + sparc) echo sparc-icl-nx7; exit ;; + esac ;; + sun4H:SunOS:5.*:*) + echo sparc-hal-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*) + echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + i86pc:SunOS:5.*:*) + echo i386-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + sun4*:SunOS:6*:*) + # According to config.sub, this is the proper way to canonicalize + # SunOS6. Hard to guess exactly what SunOS6 will be like, but + # it's likely to be more like Solaris than SunOS4. + echo sparc-sun-solaris3`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + sun4*:SunOS:*:*) + case "`/usr/bin/arch -k`" in + Series*|S4*) + UNAME_RELEASE=`uname -v` + ;; + esac + # Japanese Language versions have a version number like `4.1.3-JL'. + echo sparc-sun-sunos`echo ${UNAME_RELEASE}|sed -e 's/-/_/'` + exit ;; + sun3*:SunOS:*:*) + echo m68k-sun-sunos${UNAME_RELEASE} + exit ;; + sun*:*:4.2BSD:*) + UNAME_RELEASE=`(sed 1q /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null` + test "x${UNAME_RELEASE}" = "x" && UNAME_RELEASE=3 + case "`/bin/arch`" in + sun3) + echo m68k-sun-sunos${UNAME_RELEASE} + ;; + sun4) + echo sparc-sun-sunos${UNAME_RELEASE} + ;; + esac + exit ;; + aushp:SunOS:*:*) + echo sparc-auspex-sunos${UNAME_RELEASE} + exit ;; + # The situation for MiNT is a little confusing. The machine name + # can be virtually everything (everything which is not + # "atarist" or "atariste" at least should have a processor + # > m68000). The system name ranges from "MiNT" over "FreeMiNT" + # to the lowercase version "mint" (or "freemint"). Finally + # the system name "TOS" denotes a system which is actually not + # MiNT. But MiNT is downward compatible to TOS, so this should + # be no problem. + atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*) + echo m68k-atari-mint${UNAME_RELEASE} + exit ;; + atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*) + echo m68k-atari-mint${UNAME_RELEASE} + exit ;; + *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*) + echo m68k-atari-mint${UNAME_RELEASE} + exit ;; + milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*) + echo m68k-milan-mint${UNAME_RELEASE} + exit ;; + hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*) + echo m68k-hades-mint${UNAME_RELEASE} + exit ;; + *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*) + echo m68k-unknown-mint${UNAME_RELEASE} + exit ;; + m68k:machten:*:*) + echo m68k-apple-machten${UNAME_RELEASE} + exit ;; + powerpc:machten:*:*) + echo powerpc-apple-machten${UNAME_RELEASE} + exit ;; + RISC*:Mach:*:*) + echo mips-dec-mach_bsd4.3 + exit ;; + RISC*:ULTRIX:*:*) + echo mips-dec-ultrix${UNAME_RELEASE} + exit ;; + VAX*:ULTRIX*:*:*) + echo vax-dec-ultrix${UNAME_RELEASE} + exit ;; + 2020:CLIX:*:* | 2430:CLIX:*:*) + echo clipper-intergraph-clix${UNAME_RELEASE} + exit ;; + mips:*:*:UMIPS | mips:*:*:RISCos) + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c +#ifdef __cplusplus +#include /* for printf() prototype */ + int main (int argc, char *argv[]) { +#else + int main (argc, argv) int argc; char *argv[]; { +#endif + #if defined (host_mips) && defined (MIPSEB) + #if defined (SYSTYPE_SYSV) + printf ("mips-mips-riscos%ssysv\n", argv[1]); exit (0); + #endif + #if defined (SYSTYPE_SVR4) + printf ("mips-mips-riscos%ssvr4\n", argv[1]); exit (0); + #endif + #if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD) + printf ("mips-mips-riscos%sbsd\n", argv[1]); exit (0); + #endif + #endif + exit (-1); + } +EOF + $CC_FOR_BUILD -o $dummy $dummy.c && + dummyarg=`echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` && + SYSTEM_NAME=`$dummy $dummyarg` && + { echo "$SYSTEM_NAME"; exit; } + echo mips-mips-riscos${UNAME_RELEASE} + exit ;; + Motorola:PowerMAX_OS:*:*) + echo powerpc-motorola-powermax + exit ;; + Motorola:*:4.3:PL8-*) + echo powerpc-harris-powermax + exit ;; + Night_Hawk:*:*:PowerMAX_OS | Synergy:PowerMAX_OS:*:*) + echo powerpc-harris-powermax + exit ;; + Night_Hawk:Power_UNIX:*:*) + echo powerpc-harris-powerunix + exit ;; + m88k:CX/UX:7*:*) + echo m88k-harris-cxux7 + exit ;; + m88k:*:4*:R4*) + echo m88k-motorola-sysv4 + exit ;; + m88k:*:3*:R3*) + echo m88k-motorola-sysv3 + exit ;; + AViiON:dgux:*:*) + # DG/UX returns AViiON for all architectures + UNAME_PROCESSOR=`/usr/bin/uname -p` + if [ $UNAME_PROCESSOR = mc88100 ] || [ $UNAME_PROCESSOR = mc88110 ] + then + if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx ] || \ + [ ${TARGET_BINARY_INTERFACE}x = x ] + then + echo m88k-dg-dgux${UNAME_RELEASE} + else + echo m88k-dg-dguxbcs${UNAME_RELEASE} + fi + else + echo i586-dg-dgux${UNAME_RELEASE} + fi + exit ;; + M88*:DolphinOS:*:*) # DolphinOS (SVR3) + echo m88k-dolphin-sysv3 + exit ;; + M88*:*:R3*:*) + # Delta 88k system running SVR3 + echo m88k-motorola-sysv3 + exit ;; + XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3) + echo m88k-tektronix-sysv3 + exit ;; + Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD) + echo m68k-tektronix-bsd + exit ;; + *:IRIX*:*:*) + echo mips-sgi-irix`echo ${UNAME_RELEASE}|sed -e 's/-/_/g'` + exit ;; + ????????:AIX?:[12].1:2) # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX. + echo romp-ibm-aix # uname -m gives an 8 hex-code CPU id + exit ;; # Note that: echo "'`uname -s`'" gives 'AIX ' + i*86:AIX:*:*) + echo i386-ibm-aix + exit ;; + ia64:AIX:*:*) + if [ -x /usr/bin/oslevel ] ; then + IBM_REV=`/usr/bin/oslevel` + else + IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} + fi + echo ${UNAME_MACHINE}-ibm-aix${IBM_REV} + exit ;; + *:AIX:2:3) + if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #include + + main() + { + if (!__power_pc()) + exit(1); + puts("powerpc-ibm-aix3.2.5"); + exit(0); + } +EOF + if $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` + then + echo "$SYSTEM_NAME" + else + echo rs6000-ibm-aix3.2.5 + fi + elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then + echo rs6000-ibm-aix3.2.4 + else + echo rs6000-ibm-aix3.2 + fi + exit ;; + *:AIX:*:[45]) + IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }'` + if /usr/sbin/lsattr -El ${IBM_CPU_ID} | grep ' POWER' >/dev/null 2>&1; then + IBM_ARCH=rs6000 + else + IBM_ARCH=powerpc + fi + if [ -x /usr/bin/oslevel ] ; then + IBM_REV=`/usr/bin/oslevel` + else + IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} + fi + echo ${IBM_ARCH}-ibm-aix${IBM_REV} + exit ;; + *:AIX:*:*) + echo rs6000-ibm-aix + exit ;; + ibmrt:4.4BSD:*|romp-ibm:BSD:*) + echo romp-ibm-bsd4.4 + exit ;; + ibmrt:*BSD:*|romp-ibm:BSD:*) # covers RT/PC BSD and + echo romp-ibm-bsd${UNAME_RELEASE} # 4.3 with uname added to + exit ;; # report: romp-ibm BSD 4.3 + *:BOSX:*:*) + echo rs6000-bull-bosx + exit ;; + DPX/2?00:B.O.S.:*:*) + echo m68k-bull-sysv3 + exit ;; + 9000/[34]??:4.3bsd:1.*:*) + echo m68k-hp-bsd + exit ;; + hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*) + echo m68k-hp-bsd4.4 + exit ;; + 9000/[34678]??:HP-UX:*:*) + HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` + case "${UNAME_MACHINE}" in + 9000/31? ) HP_ARCH=m68000 ;; + 9000/[34]?? ) HP_ARCH=m68k ;; + 9000/[678][0-9][0-9]) + if [ -x /usr/bin/getconf ]; then + sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null` + sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null` + case "${sc_cpu_version}" in + 523) HP_ARCH="hppa1.0" ;; # CPU_PA_RISC1_0 + 528) HP_ARCH="hppa1.1" ;; # CPU_PA_RISC1_1 + 532) # CPU_PA_RISC2_0 + case "${sc_kernel_bits}" in + 32) HP_ARCH="hppa2.0n" ;; + 64) HP_ARCH="hppa2.0w" ;; + '') HP_ARCH="hppa2.0" ;; # HP-UX 10.20 + esac ;; + esac + fi + if [ "${HP_ARCH}" = "" ]; then + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + + #define _HPUX_SOURCE + #include + #include + + int main () + { + #if defined(_SC_KERNEL_BITS) + long bits = sysconf(_SC_KERNEL_BITS); + #endif + long cpu = sysconf (_SC_CPU_VERSION); + + switch (cpu) + { + case CPU_PA_RISC1_0: puts ("hppa1.0"); break; + case CPU_PA_RISC1_1: puts ("hppa1.1"); break; + case CPU_PA_RISC2_0: + #if defined(_SC_KERNEL_BITS) + switch (bits) + { + case 64: puts ("hppa2.0w"); break; + case 32: puts ("hppa2.0n"); break; + default: puts ("hppa2.0"); break; + } break; + #else /* !defined(_SC_KERNEL_BITS) */ + puts ("hppa2.0"); break; + #endif + default: puts ("hppa1.0"); break; + } + exit (0); + } +EOF + (CCOPTS= $CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null) && HP_ARCH=`$dummy` + test -z "$HP_ARCH" && HP_ARCH=hppa + fi ;; + esac + if [ ${HP_ARCH} = "hppa2.0w" ] + then + eval $set_cc_for_build + + # hppa2.0w-hp-hpux* has a 64-bit kernel and a compiler generating + # 32-bit code. hppa64-hp-hpux* has the same kernel and a compiler + # generating 64-bit code. GNU and HP use different nomenclature: + # + # $ CC_FOR_BUILD=cc ./config.guess + # => hppa2.0w-hp-hpux11.23 + # $ CC_FOR_BUILD="cc +DA2.0w" ./config.guess + # => hppa64-hp-hpux11.23 + + if echo __LP64__ | (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | + grep __LP64__ >/dev/null + then + HP_ARCH="hppa2.0w" + else + HP_ARCH="hppa64" + fi + fi + echo ${HP_ARCH}-hp-hpux${HPUX_REV} + exit ;; + ia64:HP-UX:*:*) + HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` + echo ia64-hp-hpux${HPUX_REV} + exit ;; + 3050*:HI-UX:*:*) + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #include + int + main () + { + long cpu = sysconf (_SC_CPU_VERSION); + /* The order matters, because CPU_IS_HP_MC68K erroneously returns + true for CPU_PA_RISC1_0. CPU_IS_PA_RISC returns correct + results, however. */ + if (CPU_IS_PA_RISC (cpu)) + { + switch (cpu) + { + case CPU_PA_RISC1_0: puts ("hppa1.0-hitachi-hiuxwe2"); break; + case CPU_PA_RISC1_1: puts ("hppa1.1-hitachi-hiuxwe2"); break; + case CPU_PA_RISC2_0: puts ("hppa2.0-hitachi-hiuxwe2"); break; + default: puts ("hppa-hitachi-hiuxwe2"); break; + } + } + else if (CPU_IS_HP_MC68K (cpu)) + puts ("m68k-hitachi-hiuxwe2"); + else puts ("unknown-hitachi-hiuxwe2"); + exit (0); + } +EOF + $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` && + { echo "$SYSTEM_NAME"; exit; } + echo unknown-hitachi-hiuxwe2 + exit ;; + 9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* ) + echo hppa1.1-hp-bsd + exit ;; + 9000/8??:4.3bsd:*:*) + echo hppa1.0-hp-bsd + exit ;; + *9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*) + echo hppa1.0-hp-mpeix + exit ;; + hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* ) + echo hppa1.1-hp-osf + exit ;; + hp8??:OSF1:*:*) + echo hppa1.0-hp-osf + exit ;; + i*86:OSF1:*:*) + if [ -x /usr/sbin/sysversion ] ; then + echo ${UNAME_MACHINE}-unknown-osf1mk + else + echo ${UNAME_MACHINE}-unknown-osf1 + fi + exit ;; + parisc*:Lites*:*:*) + echo hppa1.1-hp-lites + exit ;; + C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*) + echo c1-convex-bsd + exit ;; + C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*) + if getsysinfo -f scalar_acc + then echo c32-convex-bsd + else echo c2-convex-bsd + fi + exit ;; + C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*) + echo c34-convex-bsd + exit ;; + C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*) + echo c38-convex-bsd + exit ;; + C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*) + echo c4-convex-bsd + exit ;; + CRAY*Y-MP:*:*:*) + echo ymp-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit ;; + CRAY*[A-Z]90:*:*:*) + echo ${UNAME_MACHINE}-cray-unicos${UNAME_RELEASE} \ + | sed -e 's/CRAY.*\([A-Z]90\)/\1/' \ + -e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ \ + -e 's/\.[^.]*$/.X/' + exit ;; + CRAY*TS:*:*:*) + echo t90-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit ;; + CRAY*T3E:*:*:*) + echo alphaev5-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit ;; + CRAY*SV1:*:*:*) + echo sv1-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit ;; + *:UNICOS/mp:*:*) + echo craynv-cray-unicosmp${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit ;; + F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*) + FUJITSU_PROC=`uname -m | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` + FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'` + FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'` + echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" + exit ;; + 5000:UNIX_System_V:4.*:*) + FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'` + FUJITSU_REL=`echo ${UNAME_RELEASE} | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/ /_/'` + echo "sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" + exit ;; + i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*) + echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE} + exit ;; + sparc*:BSD/OS:*:*) + echo sparc-unknown-bsdi${UNAME_RELEASE} + exit ;; + *:BSD/OS:*:*) + echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE} + exit ;; + *:FreeBSD:*:*) + echo ${UNAME_MACHINE}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` + exit ;; + i*:CYGWIN*:*) + echo ${UNAME_MACHINE}-pc-cygwin + exit ;; + i*:MINGW*:*) + echo ${UNAME_MACHINE}-pc-mingw32 + exit ;; + i*:windows32*:*) + # uname -m includes "-pc" on this system. + echo ${UNAME_MACHINE}-mingw32 + exit ;; + i*:PW*:*) + echo ${UNAME_MACHINE}-pc-pw32 + exit ;; + x86:Interix*:[34]*) + echo i586-pc-interix${UNAME_RELEASE}|sed -e 's/\..*//' + exit ;; + [345]86:Windows_95:* | [345]86:Windows_98:* | [345]86:Windows_NT:*) + echo i${UNAME_MACHINE}-pc-mks + exit ;; + i*:Windows_NT*:* | Pentium*:Windows_NT*:*) + # How do we know it's Interix rather than the generic POSIX subsystem? + # It also conflicts with pre-2.0 versions of AT&T UWIN. Should we + # UNAME_MACHINE based on the output of uname instead of i386? + echo i586-pc-interix + exit ;; + i*:UWIN*:*) + echo ${UNAME_MACHINE}-pc-uwin + exit ;; + amd64:CYGWIN*:*:* | x86_64:CYGWIN*:*:*) + echo x86_64-unknown-cygwin + exit ;; + p*:CYGWIN*:*) + echo powerpcle-unknown-cygwin + exit ;; + prep*:SunOS:5.*:*) + echo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + *:GNU:*:*) + # the GNU system + echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-gnu`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'` + exit ;; + *:GNU/*:*:*) + # other systems with GNU libc and userland + echo ${UNAME_MACHINE}-unknown-`echo ${UNAME_SYSTEM} | sed 's,^[^/]*/,,' | tr '[A-Z]' '[a-z]'``echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`-gnu + exit ;; + i*86:Minix:*:*) + echo ${UNAME_MACHINE}-pc-minix + exit ;; + arm*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + cris:Linux:*:*) + echo cris-axis-linux-gnu + exit ;; + crisv32:Linux:*:*) + echo crisv32-axis-linux-gnu + exit ;; + frv:Linux:*:*) + echo frv-unknown-linux-gnu + exit ;; + ia64:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + m32r*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + m68*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + mips:Linux:*:*) + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #undef CPU + #undef mips + #undef mipsel + #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL) + CPU=mipsel + #else + #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB) + CPU=mips + #else + CPU= + #endif + #endif +EOF + eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep ^CPU=` + test x"${CPU}" != x && { echo "${CPU}-unknown-linux-gnu"; exit; } + ;; + mips64:Linux:*:*) + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #undef CPU + #undef mips64 + #undef mips64el + #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL) + CPU=mips64el + #else + #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB) + CPU=mips64 + #else + CPU= + #endif + #endif +EOF + eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep ^CPU=` + test x"${CPU}" != x && { echo "${CPU}-unknown-linux-gnu"; exit; } + ;; + or32:Linux:*:*) + echo or32-unknown-linux-gnu + exit ;; + ppc:Linux:*:*) + echo powerpc-unknown-linux-gnu + exit ;; + ppc64:Linux:*:*) + echo powerpc64-unknown-linux-gnu + exit ;; + alpha:Linux:*:*) + case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in + EV5) UNAME_MACHINE=alphaev5 ;; + EV56) UNAME_MACHINE=alphaev56 ;; + PCA56) UNAME_MACHINE=alphapca56 ;; + PCA57) UNAME_MACHINE=alphapca56 ;; + EV6) UNAME_MACHINE=alphaev6 ;; + EV67) UNAME_MACHINE=alphaev67 ;; + EV68*) UNAME_MACHINE=alphaev68 ;; + esac + objdump --private-headers /bin/sh | grep ld.so.1 >/dev/null + if test "$?" = 0 ; then LIBC="libc1" ; else LIBC="" ; fi + echo ${UNAME_MACHINE}-unknown-linux-gnu${LIBC} + exit ;; + parisc:Linux:*:* | hppa:Linux:*:*) + # Look for CPU level + case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in + PA7*) echo hppa1.1-unknown-linux-gnu ;; + PA8*) echo hppa2.0-unknown-linux-gnu ;; + *) echo hppa-unknown-linux-gnu ;; + esac + exit ;; + parisc64:Linux:*:* | hppa64:Linux:*:*) + echo hppa64-unknown-linux-gnu + exit ;; + s390:Linux:*:* | s390x:Linux:*:*) + echo ${UNAME_MACHINE}-ibm-linux + exit ;; + sh64*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + sh*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + sparc:Linux:*:* | sparc64:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + x86_64:Linux:*:*) + echo x86_64-unknown-linux-gnu + exit ;; + i*86:Linux:*:*) + # The BFD linker knows what the default object file format is, so + # first see if it will tell us. cd to the root directory to prevent + # problems with other programs or directories called `ld' in the path. + # Set LC_ALL=C to ensure ld outputs messages in English. + ld_supported_targets=`cd /; LC_ALL=C ld --help 2>&1 \ + | sed -ne '/supported targets:/!d + s/[ ][ ]*/ /g + s/.*supported targets: *// + s/ .*// + p'` + case "$ld_supported_targets" in + elf32-i386) + TENTATIVE="${UNAME_MACHINE}-pc-linux-gnu" + ;; + a.out-i386-linux) + echo "${UNAME_MACHINE}-pc-linux-gnuaout" + exit ;; + coff-i386) + echo "${UNAME_MACHINE}-pc-linux-gnucoff" + exit ;; + "") + # Either a pre-BFD a.out linker (linux-gnuoldld) or + # one that does not give us useful --help. + echo "${UNAME_MACHINE}-pc-linux-gnuoldld" + exit ;; + esac + # Determine whether the default compiler is a.out or elf + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #include + #ifdef __ELF__ + # ifdef __GLIBC__ + # if __GLIBC__ >= 2 + LIBC=gnu + # else + LIBC=gnulibc1 + # endif + # else + LIBC=gnulibc1 + # endif + #else + #ifdef __INTEL_COMPILER + LIBC=gnu + #else + LIBC=gnuaout + #endif + #endif + #ifdef __dietlibc__ + LIBC=dietlibc + #endif +EOF + eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep ^LIBC=` + test x"${LIBC}" != x && { + echo "${UNAME_MACHINE}-pc-linux-${LIBC}" + exit + } + test x"${TENTATIVE}" != x && { echo "${TENTATIVE}"; exit; } + ;; + i*86:DYNIX/ptx:4*:*) + # ptx 4.0 does uname -s correctly, with DYNIX/ptx in there. + # earlier versions are messed up and put the nodename in both + # sysname and nodename. + echo i386-sequent-sysv4 + exit ;; + i*86:UNIX_SV:4.2MP:2.*) + # Unixware is an offshoot of SVR4, but it has its own version + # number series starting with 2... + # I am not positive that other SVR4 systems won't match this, + # I just have to hope. -- rms. + # Use sysv4.2uw... so that sysv4* matches it. + echo ${UNAME_MACHINE}-pc-sysv4.2uw${UNAME_VERSION} + exit ;; + i*86:OS/2:*:*) + # If we were able to find `uname', then EMX Unix compatibility + # is probably installed. + echo ${UNAME_MACHINE}-pc-os2-emx + exit ;; + i*86:XTS-300:*:STOP) + echo ${UNAME_MACHINE}-unknown-stop + exit ;; + i*86:atheos:*:*) + echo ${UNAME_MACHINE}-unknown-atheos + exit ;; + i*86:syllable:*:*) + echo ${UNAME_MACHINE}-pc-syllable + exit ;; + i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.0*:*) + echo i386-unknown-lynxos${UNAME_RELEASE} + exit ;; + i*86:*DOS:*:*) + echo ${UNAME_MACHINE}-pc-msdosdjgpp + exit ;; + i*86:*:4.*:* | i*86:SYSTEM_V:4.*:*) + UNAME_REL=`echo ${UNAME_RELEASE} | sed 's/\/MP$//'` + if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then + echo ${UNAME_MACHINE}-univel-sysv${UNAME_REL} + else + echo ${UNAME_MACHINE}-pc-sysv${UNAME_REL} + fi + exit ;; + i*86:*:5:[678]*) + # UnixWare 7.x, OpenUNIX and OpenServer 6. + case `/bin/uname -X | grep "^Machine"` in + *486*) UNAME_MACHINE=i486 ;; + *Pentium) UNAME_MACHINE=i586 ;; + *Pent*|*Celeron) UNAME_MACHINE=i686 ;; + esac + echo ${UNAME_MACHINE}-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}${UNAME_VERSION} + exit ;; + i*86:*:3.2:*) + if test -f /usr/options/cb.name; then + UNAME_REL=`sed -n 's/.*Version //p' /dev/null >/dev/null ; then + UNAME_REL=`(/bin/uname -X|grep Release|sed -e 's/.*= //')` + (/bin/uname -X|grep i80486 >/dev/null) && UNAME_MACHINE=i486 + (/bin/uname -X|grep '^Machine.*Pentium' >/dev/null) \ + && UNAME_MACHINE=i586 + (/bin/uname -X|grep '^Machine.*Pent *II' >/dev/null) \ + && UNAME_MACHINE=i686 + (/bin/uname -X|grep '^Machine.*Pentium Pro' >/dev/null) \ + && UNAME_MACHINE=i686 + echo ${UNAME_MACHINE}-pc-sco$UNAME_REL + else + echo ${UNAME_MACHINE}-pc-sysv32 + fi + exit ;; + pc:*:*:*) + # Left here for compatibility: + # uname -m prints for DJGPP always 'pc', but it prints nothing about + # the processor, so we play safe by assuming i386. + echo i386-pc-msdosdjgpp + exit ;; + Intel:Mach:3*:*) + echo i386-pc-mach3 + exit ;; + paragon:*:*:*) + echo i860-intel-osf1 + exit ;; + i860:*:4.*:*) # i860-SVR4 + if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then + echo i860-stardent-sysv${UNAME_RELEASE} # Stardent Vistra i860-SVR4 + else # Add other i860-SVR4 vendors below as they are discovered. + echo i860-unknown-sysv${UNAME_RELEASE} # Unknown i860-SVR4 + fi + exit ;; + mini*:CTIX:SYS*5:*) + # "miniframe" + echo m68010-convergent-sysv + exit ;; + mc68k:UNIX:SYSTEM5:3.51m) + echo m68k-convergent-sysv + exit ;; + M680?0:D-NIX:5.3:*) + echo m68k-diab-dnix + exit ;; + M68*:*:R3V[5678]*:*) + test -r /sysV68 && { echo 'm68k-motorola-sysv'; exit; } ;; + 3[345]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 3[34]??/*:*:4.0:3.0 | 4400:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*:4.0:3.0 | SDS2:*:4.0:3.0 | SHG2:*:4.0:3.0 | S7501*:*:4.0:3.0) + OS_REL='' + test -r /etc/.relid \ + && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid` + /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ + && { echo i486-ncr-sysv4.3${OS_REL}; exit; } + /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ + && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;; + 3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*) + /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ + && { echo i486-ncr-sysv4; exit; } ;; + m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*) + echo m68k-unknown-lynxos${UNAME_RELEASE} + exit ;; + mc68030:UNIX_System_V:4.*:*) + echo m68k-atari-sysv4 + exit ;; + TSUNAMI:LynxOS:2.*:*) + echo sparc-unknown-lynxos${UNAME_RELEASE} + exit ;; + rs6000:LynxOS:2.*:*) + echo rs6000-unknown-lynxos${UNAME_RELEASE} + exit ;; + PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.0*:*) + echo powerpc-unknown-lynxos${UNAME_RELEASE} + exit ;; + SM[BE]S:UNIX_SV:*:*) + echo mips-dde-sysv${UNAME_RELEASE} + exit ;; + RM*:ReliantUNIX-*:*:*) + echo mips-sni-sysv4 + exit ;; + RM*:SINIX-*:*:*) + echo mips-sni-sysv4 + exit ;; + *:SINIX-*:*:*) + if uname -p 2>/dev/null >/dev/null ; then + UNAME_MACHINE=`(uname -p) 2>/dev/null` + echo ${UNAME_MACHINE}-sni-sysv4 + else + echo ns32k-sni-sysv + fi + exit ;; + PENTIUM:*:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort + # says + echo i586-unisys-sysv4 + exit ;; + *:UNIX_System_V:4*:FTX*) + # From Gerald Hewes . + # How about differentiating between stratus architectures? -djm + echo hppa1.1-stratus-sysv4 + exit ;; + *:*:*:FTX*) + # From seanf@swdc.stratus.com. + echo i860-stratus-sysv4 + exit ;; + i*86:VOS:*:*) + # From Paul.Green@stratus.com. + echo ${UNAME_MACHINE}-stratus-vos + exit ;; + *:VOS:*:*) + # From Paul.Green@stratus.com. + echo hppa1.1-stratus-vos + exit ;; + mc68*:A/UX:*:*) + echo m68k-apple-aux${UNAME_RELEASE} + exit ;; + news*:NEWS-OS:6*:*) + echo mips-sony-newsos6 + exit ;; + R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*) + if [ -d /usr/nec ]; then + echo mips-nec-sysv${UNAME_RELEASE} + else + echo mips-unknown-sysv${UNAME_RELEASE} + fi + exit ;; + BeBox:BeOS:*:*) # BeOS running on hardware made by Be, PPC only. + echo powerpc-be-beos + exit ;; + BeMac:BeOS:*:*) # BeOS running on Mac or Mac clone, PPC only. + echo powerpc-apple-beos + exit ;; + BePC:BeOS:*:*) # BeOS running on Intel PC compatible. + echo i586-pc-beos + exit ;; + SX-4:SUPER-UX:*:*) + echo sx4-nec-superux${UNAME_RELEASE} + exit ;; + SX-5:SUPER-UX:*:*) + echo sx5-nec-superux${UNAME_RELEASE} + exit ;; + SX-6:SUPER-UX:*:*) + echo sx6-nec-superux${UNAME_RELEASE} + exit ;; + Power*:Rhapsody:*:*) + echo powerpc-apple-rhapsody${UNAME_RELEASE} + exit ;; + *:Rhapsody:*:*) + echo ${UNAME_MACHINE}-apple-rhapsody${UNAME_RELEASE} + exit ;; + *:Darwin:*:*) + UNAME_PROCESSOR=`uname -p` || UNAME_PROCESSOR=unknown + case $UNAME_PROCESSOR in + *86) UNAME_PROCESSOR=i686 ;; + unknown) UNAME_PROCESSOR=powerpc ;; + esac + echo ${UNAME_PROCESSOR}-apple-darwin${UNAME_RELEASE} + exit ;; + *:procnto*:*:* | *:QNX:[0123456789]*:*) + UNAME_PROCESSOR=`uname -p` + if test "$UNAME_PROCESSOR" = "x86"; then + UNAME_PROCESSOR=i386 + UNAME_MACHINE=pc + fi + echo ${UNAME_PROCESSOR}-${UNAME_MACHINE}-nto-qnx${UNAME_RELEASE} + exit ;; + *:QNX:*:4*) + echo i386-pc-qnx + exit ;; + NSE-?:NONSTOP_KERNEL:*:*) + echo nse-tandem-nsk${UNAME_RELEASE} + exit ;; + NSR-?:NONSTOP_KERNEL:*:*) + echo nsr-tandem-nsk${UNAME_RELEASE} + exit ;; + *:NonStop-UX:*:*) + echo mips-compaq-nonstopux + exit ;; + BS2000:POSIX*:*:*) + echo bs2000-siemens-sysv + exit ;; + DS/*:UNIX_System_V:*:*) + echo ${UNAME_MACHINE}-${UNAME_SYSTEM}-${UNAME_RELEASE} + exit ;; + *:Plan9:*:*) + # "uname -m" is not consistent, so use $cputype instead. 386 + # is converted to i386 for consistency with other x86 + # operating systems. + if test "$cputype" = "386"; then + UNAME_MACHINE=i386 + else + UNAME_MACHINE="$cputype" + fi + echo ${UNAME_MACHINE}-unknown-plan9 + exit ;; + *:TOPS-10:*:*) + echo pdp10-unknown-tops10 + exit ;; + *:TENEX:*:*) + echo pdp10-unknown-tenex + exit ;; + KS10:TOPS-20:*:* | KL10:TOPS-20:*:* | TYPE4:TOPS-20:*:*) + echo pdp10-dec-tops20 + exit ;; + XKL-1:TOPS-20:*:* | TYPE5:TOPS-20:*:*) + echo pdp10-xkl-tops20 + exit ;; + *:TOPS-20:*:*) + echo pdp10-unknown-tops20 + exit ;; + *:ITS:*:*) + echo pdp10-unknown-its + exit ;; + SEI:*:*:SEIUX) + echo mips-sei-seiux${UNAME_RELEASE} + exit ;; + *:DragonFly:*:*) + echo ${UNAME_MACHINE}-unknown-dragonfly`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` + exit ;; + *:*VMS:*:*) + UNAME_MACHINE=`(uname -p) 2>/dev/null` + case "${UNAME_MACHINE}" in + A*) echo alpha-dec-vms ; exit ;; + I*) echo ia64-dec-vms ; exit ;; + V*) echo vax-dec-vms ; exit ;; + esac ;; + *:XENIX:*:SysV) + echo i386-pc-xenix + exit ;; + i*86:skyos:*:*) + echo ${UNAME_MACHINE}-pc-skyos`echo ${UNAME_RELEASE}` | sed -e 's/ .*$//' + exit ;; +esac + +#echo '(No uname command or uname output not recognized.)' 1>&2 +#echo "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" 1>&2 + +eval $set_cc_for_build +cat >$dummy.c < +# include +#endif +main () +{ +#if defined (sony) +#if defined (MIPSEB) + /* BFD wants "bsd" instead of "newsos". Perhaps BFD should be changed, + I don't know.... */ + printf ("mips-sony-bsd\n"); exit (0); +#else +#include + printf ("m68k-sony-newsos%s\n", +#ifdef NEWSOS4 + "4" +#else + "" +#endif + ); exit (0); +#endif +#endif + +#if defined (__arm) && defined (__acorn) && defined (__unix) + printf ("arm-acorn-riscix\n"); exit (0); +#endif + +#if defined (hp300) && !defined (hpux) + printf ("m68k-hp-bsd\n"); exit (0); +#endif + +#if defined (NeXT) +#if !defined (__ARCHITECTURE__) +#define __ARCHITECTURE__ "m68k" +#endif + int version; + version=`(hostinfo | sed -n 's/.*NeXT Mach \([0-9]*\).*/\1/p') 2>/dev/null`; + if (version < 4) + printf ("%s-next-nextstep%d\n", __ARCHITECTURE__, version); + else + printf ("%s-next-openstep%d\n", __ARCHITECTURE__, version); + exit (0); +#endif + +#if defined (MULTIMAX) || defined (n16) +#if defined (UMAXV) + printf ("ns32k-encore-sysv\n"); exit (0); +#else +#if defined (CMU) + printf ("ns32k-encore-mach\n"); exit (0); +#else + printf ("ns32k-encore-bsd\n"); exit (0); +#endif +#endif +#endif + +#if defined (__386BSD__) + printf ("i386-pc-bsd\n"); exit (0); +#endif + +#if defined (sequent) +#if defined (i386) + printf ("i386-sequent-dynix\n"); exit (0); +#endif +#if defined (ns32000) + printf ("ns32k-sequent-dynix\n"); exit (0); +#endif +#endif + +#if defined (_SEQUENT_) + struct utsname un; + + uname(&un); + + if (strncmp(un.version, "V2", 2) == 0) { + printf ("i386-sequent-ptx2\n"); exit (0); + } + if (strncmp(un.version, "V1", 2) == 0) { /* XXX is V1 correct? */ + printf ("i386-sequent-ptx1\n"); exit (0); + } + printf ("i386-sequent-ptx\n"); exit (0); + +#endif + +#if defined (vax) +# if !defined (ultrix) +# include +# if defined (BSD) +# if BSD == 43 + printf ("vax-dec-bsd4.3\n"); exit (0); +# else +# if BSD == 199006 + printf ("vax-dec-bsd4.3reno\n"); exit (0); +# else + printf ("vax-dec-bsd\n"); exit (0); +# endif +# endif +# else + printf ("vax-dec-bsd\n"); exit (0); +# endif +# else + printf ("vax-dec-ultrix\n"); exit (0); +# endif +#endif + +#if defined (alliant) && defined (i860) + printf ("i860-alliant-bsd\n"); exit (0); +#endif + + exit (1); +} +EOF + +$CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null && SYSTEM_NAME=`$dummy` && + { echo "$SYSTEM_NAME"; exit; } + +# Apollos put the system type in the environment. + +test -d /usr/apollo && { echo ${ISP}-apollo-${SYSTYPE}; exit; } + +# Convex versions that predate uname can use getsysinfo(1) + +if [ -x /usr/convex/getsysinfo ] +then + case `getsysinfo -f cpu_type` in + c1*) + echo c1-convex-bsd + exit ;; + c2*) + if getsysinfo -f scalar_acc + then echo c32-convex-bsd + else echo c2-convex-bsd + fi + exit ;; + c34*) + echo c34-convex-bsd + exit ;; + c38*) + echo c38-convex-bsd + exit ;; + c4*) + echo c4-convex-bsd + exit ;; + esac +fi + +cat >&2 < in order to provide the needed +information to handle your system. + +config.guess timestamp = $timestamp + +uname -m = `(uname -m) 2>/dev/null || echo unknown` +uname -r = `(uname -r) 2>/dev/null || echo unknown` +uname -s = `(uname -s) 2>/dev/null || echo unknown` +uname -v = `(uname -v) 2>/dev/null || echo unknown` + +/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null` +/bin/uname -X = `(/bin/uname -X) 2>/dev/null` + +hostinfo = `(hostinfo) 2>/dev/null` +/bin/universe = `(/bin/universe) 2>/dev/null` +/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null` +/bin/arch = `(/bin/arch) 2>/dev/null` +/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null` +/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null` + +UNAME_MACHINE = ${UNAME_MACHINE} +UNAME_RELEASE = ${UNAME_RELEASE} +UNAME_SYSTEM = ${UNAME_SYSTEM} +UNAME_VERSION = ${UNAME_VERSION} +EOF + +exit 1 + +# Local variables: +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "timestamp='" +# time-stamp-format: "%:y-%02m-%02d" +# time-stamp-end: "'" +# End: diff --git a/xar/config.status b/xar/config.status new file mode 100755 index 0000000..38d4735 --- /dev/null +++ b/xar/config.status @@ -0,0 +1,1068 @@ +#! /bin/sh +# Generated by configure. +# Run this file to recreate the current configuration. +# Compiler output produced by configure, useful for debugging +# configure, is in config.log if it exists. + +debug=false +ac_cs_recheck=false +ac_cs_silent=false + +SHELL=${CONFIG_SHELL-/bin/sh} +export SHELL +## -------------------- ## +## M4sh Initialization. ## +## -------------------- ## + +# Be more Bourne compatible +DUALCASE=1; export DUALCASE # for MKS sh +if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then : + emulate sh + NULLCMD=: + # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which + # is contrary to our usage. Disable this feature. + alias -g '${1+"$@"}'='"$@"' + setopt NO_GLOB_SUBST +else + case `(set -o) 2>/dev/null` in #( + *posix*) : + set -o posix ;; #( + *) : + ;; +esac +fi + + +as_nl=' +' +export as_nl +# Printing a long string crashes Solaris 7 /usr/bin/printf. +as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' +as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo +as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo +# Prefer a ksh shell builtin over an external printf program on Solaris, +# but without wasting forks for bash or zsh. +if test -z "$BASH_VERSION$ZSH_VERSION" \ + && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then + as_echo='print -r --' + as_echo_n='print -rn --' +elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then + as_echo='printf %s\n' + as_echo_n='printf %s' +else + if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then + as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"' + as_echo_n='/usr/ucb/echo -n' + else + as_echo_body='eval expr "X$1" : "X\\(.*\\)"' + as_echo_n_body='eval + arg=$1; + case $arg in #( + *"$as_nl"*) + expr "X$arg" : "X\\(.*\\)$as_nl"; + arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;; + esac; + expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl" + ' + export as_echo_n_body + as_echo_n='sh -c $as_echo_n_body as_echo' + fi + export as_echo_body + as_echo='sh -c $as_echo_body as_echo' +fi + +# The user is always right. +if test "${PATH_SEPARATOR+set}" != set; then + PATH_SEPARATOR=: + (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { + (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || + PATH_SEPARATOR=';' + } +fi + + +# IFS +# We need space, tab and new line, in precisely that order. Quoting is +# there to prevent editors from complaining about space-tab. +# (If _AS_PATH_WALK were called with IFS unset, it would disable word +# splitting by setting IFS to empty value.) +IFS=" "" $as_nl" + +# Find who we are. Look in the path if we contain no directory separator. +as_myself= +case $0 in #(( + *[\\/]* ) as_myself=$0 ;; + *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break + done +IFS=$as_save_IFS + + ;; +esac +# We did not find ourselves, most probably we were run as `sh COMMAND' +# in which case we are not to be found in the path. +if test "x$as_myself" = x; then + as_myself=$0 +fi +if test ! -f "$as_myself"; then + $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 + exit 1 +fi + +# Unset variables that we do not need and which cause bugs (e.g. in +# pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1" +# suppresses any "Segmentation fault" message there. '((' could +# trigger a bug in pdksh 5.2.14. +for as_var in BASH_ENV ENV MAIL MAILPATH +do eval test x\${$as_var+set} = xset \ + && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : +done +PS1='$ ' +PS2='> ' +PS4='+ ' + +# NLS nuisances. +LC_ALL=C +export LC_ALL +LANGUAGE=C +export LANGUAGE + +# CDPATH. +(unset CDPATH) >/dev/null 2>&1 && unset CDPATH + + +# as_fn_error STATUS ERROR [LINENO LOG_FD] +# ---------------------------------------- +# Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are +# provided, also output the error to LOG_FD, referencing LINENO. Then exit the +# script with STATUS, using 1 if that was 0. +as_fn_error () +{ + as_status=$1; test $as_status -eq 0 && as_status=1 + if test "$4"; then + as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4 + fi + $as_echo "$as_me: error: $2" >&2 + as_fn_exit $as_status +} # as_fn_error + + +# as_fn_set_status STATUS +# ----------------------- +# Set $? to STATUS, without forking. +as_fn_set_status () +{ + return $1 +} # as_fn_set_status + +# as_fn_exit STATUS +# ----------------- +# Exit the shell with STATUS, even in a "trap 0" or "set -e" context. +as_fn_exit () +{ + set +e + as_fn_set_status $1 + exit $1 +} # as_fn_exit + +# as_fn_unset VAR +# --------------- +# Portably unset VAR. +as_fn_unset () +{ + { eval $1=; unset $1;} +} +as_unset=as_fn_unset +# as_fn_append VAR VALUE +# ---------------------- +# Append the text in VALUE to the end of the definition contained in VAR. Take +# advantage of any shell optimizations that allow amortized linear growth over +# repeated appends, instead of the typical quadratic growth present in naive +# implementations. +if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then : + eval 'as_fn_append () + { + eval $1+=\$2 + }' +else + as_fn_append () + { + eval $1=\$$1\$2 + } +fi # as_fn_append + +# as_fn_arith ARG... +# ------------------ +# Perform arithmetic evaluation on the ARGs, and store the result in the +# global $as_val. Take advantage of shells that can avoid forks. The arguments +# must be portable across $(()) and expr. +if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then : + eval 'as_fn_arith () + { + as_val=$(( $* )) + }' +else + as_fn_arith () + { + as_val=`expr "$@" || test $? -eq 1` + } +fi # as_fn_arith + + +if expr a : '\(a\)' >/dev/null 2>&1 && + test "X`expr 00001 : '.*\(...\)'`" = X001; then + as_expr=expr +else + as_expr=false +fi + +if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then + as_basename=basename +else + as_basename=false +fi + +if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then + as_dirname=dirname +else + as_dirname=false +fi + +as_me=`$as_basename -- "$0" || +$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ + X"$0" : 'X\(//\)$' \| \ + X"$0" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X/"$0" | + sed '/^.*\/\([^/][^/]*\)\/*$/{ + s//\1/ + q + } + /^X\/\(\/\/\)$/{ + s//\1/ + q + } + /^X\/\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + +# Avoid depending upon Character Ranges. +as_cr_letters='abcdefghijklmnopqrstuvwxyz' +as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' +as_cr_Letters=$as_cr_letters$as_cr_LETTERS +as_cr_digits='0123456789' +as_cr_alnum=$as_cr_Letters$as_cr_digits + +ECHO_C= ECHO_N= ECHO_T= +case `echo -n x` in #((((( +-n*) + case `echo 'xy\c'` in + *c*) ECHO_T=' ';; # ECHO_T is single tab character. + xy) ECHO_C='\c';; + *) echo `echo ksh88 bug on AIX 6.1` > /dev/null + ECHO_T=' ';; + esac;; +*) + ECHO_N='-n';; +esac + +rm -f conf$$ conf$$.exe conf$$.file +if test -d conf$$.dir; then + rm -f conf$$.dir/conf$$.file +else + rm -f conf$$.dir + mkdir conf$$.dir 2>/dev/null +fi +if (echo >conf$$.file) 2>/dev/null; then + if ln -s conf$$.file conf$$ 2>/dev/null; then + as_ln_s='ln -s' + # ... but there are two gotchas: + # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. + # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. + # In both cases, we have to default to `cp -pR'. + ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || + as_ln_s='cp -pR' + elif ln conf$$.file conf$$ 2>/dev/null; then + as_ln_s=ln + else + as_ln_s='cp -pR' + fi +else + as_ln_s='cp -pR' +fi +rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file +rmdir conf$$.dir 2>/dev/null + + +# as_fn_mkdir_p +# ------------- +# Create "$as_dir" as a directory, including parents if necessary. +as_fn_mkdir_p () +{ + + case $as_dir in #( + -*) as_dir=./$as_dir;; + esac + test -d "$as_dir" || eval $as_mkdir_p || { + as_dirs= + while :; do + case $as_dir in #( + *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( + *) as_qdir=$as_dir;; + esac + as_dirs="'$as_qdir' $as_dirs" + as_dir=`$as_dirname -- "$as_dir" || +$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$as_dir" : 'X\(//\)[^/]' \| \ + X"$as_dir" : 'X\(//\)$' \| \ + X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$as_dir" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + test -d "$as_dir" && break + done + test -z "$as_dirs" || eval "mkdir $as_dirs" + } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir" + + +} # as_fn_mkdir_p +if mkdir -p . 2>/dev/null; then + as_mkdir_p='mkdir -p "$as_dir"' +else + test -d ./-p && rmdir ./-p + as_mkdir_p=false +fi + + +# as_fn_executable_p FILE +# ----------------------- +# Test if FILE is an executable regular file. +as_fn_executable_p () +{ + test -f "$1" && test -x "$1" +} # as_fn_executable_p +as_test_x='test -x' +as_executable_p=as_fn_executable_p + +# Sed expression to map a string onto a valid CPP name. +as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" + +# Sed expression to map a string onto a valid variable name. +as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" + + +exec 6>&1 +## ----------------------------------- ## +## Main body of $CONFIG_STATUS script. ## +## ----------------------------------- ## +# Save the log message, to keep $0 and so on meaningful, and to +# report actual input values of CONFIG_FILES etc. instead of their +# values after options handling. +ac_log=" +This file was extended by Xar $as_me 1.8dev, which was +generated by GNU Autoconf 2.69. Invocation command line was + + CONFIG_FILES = $CONFIG_FILES + CONFIG_HEADERS = $CONFIG_HEADERS + CONFIG_LINKS = $CONFIG_LINKS + CONFIG_COMMANDS = $CONFIG_COMMANDS + $ $0 $@ + +on `(hostname || uname -n) 2>/dev/null | sed 1q` +" + +# Files that config.status was made for. +config_files=" cfgoutputs.stamp Makefile include/xar.h lib/Makefile.inc lib/libxar.la.in src/Makefile.inc xar.spec" +config_headers=" cfghdrs.stamp include/config.h" + +ac_cs_usage="\ +\`$as_me' instantiates files and other configuration actions +from templates according to the current configuration. Unless the files +and actions are specified as TAGs, all are instantiated by default. + +Usage: $0 [OPTION]... [TAG]... + + -h, --help print this help, then exit + -V, --version print version number and configuration settings, then exit + --config print configuration, then exit + -q, --quiet, --silent + do not print progress messages + -d, --debug don't remove temporary files + --recheck update $as_me by reconfiguring in the same conditions + --file=FILE[:TEMPLATE] + instantiate the configuration file FILE + --header=FILE[:TEMPLATE] + instantiate the configuration header FILE + +Configuration files: +$config_files + +Configuration headers: +$config_headers + +Report bugs to ." + +ac_cs_config="" +ac_cs_version="\ +Xar config.status 1.8dev +configured by ./configure, generated by GNU Autoconf 2.69, + with options \"$ac_cs_config\" + +Copyright (C) 2012 Free Software Foundation, Inc. +This config.status script is free software; the Free Software Foundation +gives unlimited permission to copy, distribute and modify it." + +ac_pwd='/Users/ariel/LinuxHome/code/darling/src/xar/xar' +srcdir='.' +INSTALL='./install-sh -c' +test -n "$AWK" || AWK=awk +# The default lists apply if the user does not specify any file. +ac_need_defaults=: +while test $# != 0 +do + case $1 in + --*=?*) + ac_option=`expr "X$1" : 'X\([^=]*\)='` + ac_optarg=`expr "X$1" : 'X[^=]*=\(.*\)'` + ac_shift=: + ;; + --*=) + ac_option=`expr "X$1" : 'X\([^=]*\)='` + ac_optarg= + ac_shift=: + ;; + *) + ac_option=$1 + ac_optarg=$2 + ac_shift=shift + ;; + esac + + case $ac_option in + # Handling of the options. + -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r) + ac_cs_recheck=: ;; + --version | --versio | --versi | --vers | --ver | --ve | --v | -V ) + $as_echo "$ac_cs_version"; exit ;; + --config | --confi | --conf | --con | --co | --c ) + $as_echo "$ac_cs_config"; exit ;; + --debug | --debu | --deb | --de | --d | -d ) + debug=: ;; + --file | --fil | --fi | --f ) + $ac_shift + case $ac_optarg in + *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;; + '') as_fn_error $? "missing file argument" ;; + esac + as_fn_append CONFIG_FILES " '$ac_optarg'" + ac_need_defaults=false;; + --header | --heade | --head | --hea ) + $ac_shift + case $ac_optarg in + *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;; + esac + as_fn_append CONFIG_HEADERS " '$ac_optarg'" + ac_need_defaults=false;; + --he | --h) + # Conflict between --help and --header + as_fn_error $? "ambiguous option: \`$1' +Try \`$0 --help' for more information.";; + --help | --hel | -h ) + $as_echo "$ac_cs_usage"; exit ;; + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil | --si | --s) + ac_cs_silent=: ;; + + # This is an error. + -*) as_fn_error $? "unrecognized option: \`$1' +Try \`$0 --help' for more information." ;; + + *) as_fn_append ac_config_targets " $1" + ac_need_defaults=false ;; + + esac + shift +done + +ac_configure_extra_args= + +if $ac_cs_silent; then + exec 6>/dev/null + ac_configure_extra_args="$ac_configure_extra_args --silent" +fi + +if $ac_cs_recheck; then + set X /bin/sh './configure' $ac_configure_extra_args --no-create --no-recursion + shift + $as_echo "running CONFIG_SHELL=/bin/sh $*" >&6 + CONFIG_SHELL='/bin/sh' + export CONFIG_SHELL + exec "$@" +fi + +exec 5>>config.log +{ + echo + sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX +## Running $as_me. ## +_ASBOX + $as_echo "$ac_log" +} >&5 + + +# Handling of arguments. +for ac_config_target in $ac_config_targets +do + case $ac_config_target in + "$cfghdrs") CONFIG_HEADERS="$CONFIG_HEADERS $cfghdrs" ;; + "$cfgoutputs") CONFIG_FILES="$CONFIG_FILES $cfgoutputs" ;; + + *) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5;; + esac +done + + +# If the user did not use the arguments to specify the items to instantiate, +# then the envvar interface is used. Set only those that are not. +# We use the long form for the default assignment because of an extremely +# bizarre bug on SunOS 4.1.3. +if $ac_need_defaults; then + test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files + test "${CONFIG_HEADERS+set}" = set || CONFIG_HEADERS=$config_headers +fi + +# Have a temporary directory for convenience. Make it in the build tree +# simply because there is no reason against having it here, and in addition, +# creating and moving files from /tmp can sometimes cause problems. +# Hook for its removal unless debugging. +# Note that there is a small window in which the directory will not be cleaned: +# after its creation but before its name has been assigned to `$tmp'. +$debug || +{ + tmp= ac_tmp= + trap 'exit_status=$? + : "${ac_tmp:=$tmp}" + { test ! -d "$ac_tmp" || rm -fr "$ac_tmp"; } && exit $exit_status +' 0 + trap 'as_fn_exit 1' 1 2 13 15 +} +# Create a (secure) tmp directory for tmp files. + +{ + tmp=`(umask 077 && mktemp -d "./confXXXXXX") 2>/dev/null` && + test -d "$tmp" +} || +{ + tmp=./conf$$-$RANDOM + (umask 077 && mkdir "$tmp") +} || as_fn_error $? "cannot create a temporary directory in ." "$LINENO" 5 +ac_tmp=$tmp + +# Set up the scripts for CONFIG_FILES section. +# No need to generate them if there are no CONFIG_FILES. +# This happens for instance with `./config.status config.h'. +if test -n "$CONFIG_FILES"; then + + +ac_cr=`echo X | tr X '\015'` +# On cygwin, bash can eat \r inside `` if the user requested igncr. +# But we know of no other shell where ac_cr would be empty at this +# point, so we can use a bashism as a fallback. +if test "x$ac_cr" = x; then + eval ac_cr=\$\'\\r\' +fi +ac_cs_awk_cr=`$AWK 'BEGIN { print "a\rb" }' /dev/null` +if test "$ac_cs_awk_cr" = "a${ac_cr}b"; then + ac_cs_awk_cr='\\r' +else + ac_cs_awk_cr=$ac_cr +fi + +echo 'BEGIN {' >"$ac_tmp/subs1.awk" && +cat >>"$ac_tmp/subs1.awk" <<\_ACAWK && +S["LTLIBOBJS"]="" +S["LIBOBJS"]="" +S["cfgoutputs"]="cfgoutputs.stamp Makefile include/xar.h lib/Makefile.inc lib/libxar.la.in src/Makefile.inc xar.spec" +S["cfghdrs"]="cfghdrs.stamp include/config.h" +S["XML2_CONFIG"]="/Users/ariel/LinuxHome/code/darling/src/xar/xar/../../../Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/bin/xml2-config" +S["EGREP"]="/bin/grep -E" +S["GREP"]="/bin/grep" +S["enable_autogen"]="0" +S["RPATH"]="" +S["abi"]="macho" +S["host_os"]="darwin16.0.0" +S["host_vendor"]="apple" +S["host_cpu"]="i686" +S["host"]="i686-apple-darwin16.0.0" +S["build_os"]="darwin16.0.0" +S["build_vendor"]="apple" +S["build_cpu"]="i686" +S["build"]="i686-apple-darwin16.0.0" +S["static"]="yes" +S["shared"]="yes" +S["AUTOCONF"]="" +S["RANLIB"]="/usr/bin/ranlib" +S["AR"]="/usr/bin/ar" +S["LD"]="/usr/bin/ld" +S["INSTALL_DATA"]="${INSTALL} -m 644" +S["INSTALL_SCRIPT"]="${INSTALL}" +S["INSTALL_PROGRAM"]="${INSTALL}" +S["CPP"]="gcc -E" +S["OBJEXT"]="o" +S["EXEEXT"]="" +S["ac_ct_CC"]="gcc" +S["CPPFLAGS"]=" -I/usr/include/libxml2" +S["LDFLAGS"]="" +S["CFLAGS"]="-Wall -g" +S["CC"]="gcc" +S["MANDIR"]="/usr/local/share/man" +S["INCLUDEDIR"]="/usr/local/include" +S["LIBDIR"]="/usr/local/lib" +S["DATADIR"]="/usr/local/share" +S["BINDIR"]="/usr/local/bin" +S["PREFIX"]="/usr/local" +S["abs_objroot"]="/Users/ariel/LinuxHome/code/darling/src/xar/xar/" +S["objroot"]="" +S["abs_srcroot"]="/Users/ariel/LinuxHome/code/darling/src/xar/xar/" +S["srcroot"]="" +S["XAR_VERSION"]="1.8dev" +S["XAR_MINOR_VERSION"]="8dev" +S["XAR_MAJOR_VERSION"]="1" +S["LIB_REV"]="1" +S["target_alias"]="" +S["host_alias"]="" +S["build_alias"]="" +S["LIBS"]="-lpthread -lbz2 -lz -lxml2 -lz -lpthread -licucore -lm" +S["ECHO_T"]="" +S["ECHO_N"]="-n" +S["ECHO_C"]="" +S["DEFS"]="-DHAVE_CONFIG_H" +S["mandir"]="${datarootdir}/man" +S["localedir"]="${datarootdir}/locale" +S["libdir"]="${exec_prefix}/lib" +S["psdir"]="${docdir}" +S["pdfdir"]="${docdir}" +S["dvidir"]="${docdir}" +S["htmldir"]="${docdir}" +S["infodir"]="${datarootdir}/info" +S["docdir"]="${datarootdir}/doc/${PACKAGE_TARNAME}" +S["oldincludedir"]="/usr/include" +S["includedir"]="${prefix}/include" +S["localstatedir"]="${prefix}/var" +S["sharedstatedir"]="${prefix}/com" +S["sysconfdir"]="${prefix}/etc" +S["datadir"]="${datarootdir}" +S["datarootdir"]="${prefix}/share" +S["libexecdir"]="${exec_prefix}/libexec" +S["sbindir"]="${exec_prefix}/sbin" +S["bindir"]="${exec_prefix}/bin" +S["program_transform_name"]="s,x,x," +S["prefix"]="/usr/local" +S["exec_prefix"]="/usr/local" +S["PACKAGE_URL"]="" +S["PACKAGE_BUGREPORT"]="xar-devel@googlegroups.com" +S["PACKAGE_STRING"]="Xar 1.8dev" +S["PACKAGE_VERSION"]="1.8dev" +S["PACKAGE_TARNAME"]="xar" +S["PACKAGE_NAME"]="Xar" +S["PATH_SEPARATOR"]=":" +S["SHELL"]="/bin/sh" +_ACAWK +cat >>"$ac_tmp/subs1.awk" <<_ACAWK && + for (key in S) S_is_set[key] = 1 + FS = "" + +} +{ + line = $ 0 + nfields = split(line, field, "@") + substed = 0 + len = length(field[1]) + for (i = 2; i < nfields; i++) { + key = field[i] + keylen = length(key) + if (S_is_set[key]) { + value = S[key] + line = substr(line, 1, len) "" value "" substr(line, len + keylen + 3) + len += length(value) + length(field[++i]) + substed = 1 + } else + len += 1 + keylen + } + + print line +} + +_ACAWK +if sed "s/$ac_cr//" < /dev/null > /dev/null 2>&1; then + sed "s/$ac_cr\$//; s/$ac_cr/$ac_cs_awk_cr/g" +else + cat +fi < "$ac_tmp/subs1.awk" > "$ac_tmp/subs.awk" \ + || as_fn_error $? "could not setup config files machinery" "$LINENO" 5 +fi # test -n "$CONFIG_FILES" + +# Set up the scripts for CONFIG_HEADERS section. +# No need to generate them if there are no CONFIG_HEADERS. +# This happens for instance with `./config.status Makefile'. +if test -n "$CONFIG_HEADERS"; then +cat >"$ac_tmp/defines.awk" <<\_ACAWK || +BEGIN { +D["PACKAGE_NAME"]=" \"Xar\"" +D["PACKAGE_TARNAME"]=" \"xar\"" +D["PACKAGE_VERSION"]=" \"1.8dev\"" +D["PACKAGE_STRING"]=" \"Xar 1.8dev\"" +D["PACKAGE_BUGREPORT"]=" \"xar-devel@googlegroups.com\"" +D["PACKAGE_URL"]=" \"\"" +D["HAVE_SYS_ACL_H"]=" 1" +D["STDC_HEADERS"]=" 1" +D["HAVE_SYS_TYPES_H"]=" 1" +D["HAVE_SYS_STAT_H"]=" 1" +D["HAVE_STDLIB_H"]=" 1" +D["HAVE_STRING_H"]=" 1" +D["HAVE_MEMORY_H"]=" 1" +D["HAVE_STRINGS_H"]=" 1" +D["HAVE_INTTYPES_H"]=" 1" +D["HAVE_STDINT_H"]=" 1" +D["HAVE_UNISTD_H"]=" 1" +D["HAVE_SYS_XATTR_H"]=" 1" +D["HAVE_SYS_PARAM_H"]=" 1" +D["HAVE_GETXATTR"]=" 1" +D["HAVE_SETXATTR"]=" 1" +D["HAVE_GETATTRLIST"]=" 1" +D["HAVE_SETATTRLIST"]=" 1" +D["HAVE_LCHMOD"]=" 1" +D["HAVE_LCHOWN"]=" 1" +D["HAVE_CHFLAGS"]=" 1" +D["HAVE_STATVFS"]=" 1" +D["HAVE_STATFS"]=" 1" +D["HAVE_STRMODE"]=" 1" +D["HAVE_STRUCT_STATFS_F_FSTYPENAME"]=" 1" +D["HAVE_STRUCT_STAT_ST_FLAGS"]=" 1" +D["SIZEOF_UID_T"]=" 4" +D["UID_STRING"]=" RId32" +D["UID_CAST"]=" (uint32_t)" +D["SIZEOF_GID_T"]=" 4" +D["GID_STRING"]=" PRId32" +D["GID_CAST"]=" (uint32_t)" +D["SIZEOF_INO_T"]=" 8" +D["INO_STRING"]=" PRId64" +D["INO_HEXSTRING"]=" PRIx64" +D["INO_CAST"]=" (uint64_t)" +D["SIZEOF_DEV_T"]=" 4" +D["DEV_STRING"]=" PRId32" +D["DEV_HEXSTRING"]=" PRIx32" +D["DEV_CAST"]=" (uint32_t)" +D["HAVE_ASPRINTF"]=" 1" +D["HAVE_ZLIB_H"]=" 1" +D["HAVE_LIBZ"]=" 1" +D["HAVE_BZLIB_H"]=" 1" +D["HAVE_LIBBZ2"]=" 1" +D["HAVE_LIBBZ2"]=" 1" +D["HAVE_PTHREAD_H"]=" 1" +D["HAVE_LIBPTHREAD"]=" 1" +D["HAVE_LIBPTHREAD"]=" 1" + for (key in D) D_is_set[key] = 1 + FS = "" +} +/^[\t ]*#[\t ]*(define|undef)[\t ]+[_abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ][_abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789]*([\t (]|$)/ { + line = $ 0 + split(line, arg, " ") + if (arg[1] == "#") { + defundef = arg[2] + mac1 = arg[3] + } else { + defundef = substr(arg[1], 2) + mac1 = arg[2] + } + split(mac1, mac2, "(") #) + macro = mac2[1] + prefix = substr(line, 1, index(line, defundef) - 1) + if (D_is_set[macro]) { + # Preserve the white space surrounding the "#". + print prefix "define", macro P[macro] D[macro] + next + } else { + # Replace #undef with comments. This is necessary, for example, + # in the case of _POSIX_SOURCE, which is predefined and required + # on some systems where configure will not decide to define it. + if (defundef == "undef") { + print "/*", prefix defundef, macro, "*/" + next + } + } +} +{ print } +_ACAWK + as_fn_error $? "could not setup config headers machinery" "$LINENO" 5 +fi # test -n "$CONFIG_HEADERS" + + +eval set X " :F $CONFIG_FILES :H $CONFIG_HEADERS " +shift +for ac_tag +do + case $ac_tag in + :[FHLC]) ac_mode=$ac_tag; continue;; + esac + case $ac_mode$ac_tag in + :[FHL]*:*);; + :L* | :C*:*) as_fn_error $? "invalid tag \`$ac_tag'" "$LINENO" 5;; + :[FH]-) ac_tag=-:-;; + :[FH]*) ac_tag=$ac_tag:$ac_tag.in;; + esac + ac_save_IFS=$IFS + IFS=: + set x $ac_tag + IFS=$ac_save_IFS + shift + ac_file=$1 + shift + + case $ac_mode in + :L) ac_source=$1;; + :[FH]) + ac_file_inputs= + for ac_f + do + case $ac_f in + -) ac_f="$ac_tmp/stdin";; + *) # Look for the file first in the build tree, then in the source tree + # (if the path is not absolute). The absolute path cannot be DOS-style, + # because $ac_f cannot contain `:'. + test -f "$ac_f" || + case $ac_f in + [\\/$]*) false;; + *) test -f "$srcdir/$ac_f" && ac_f="$srcdir/$ac_f";; + esac || + as_fn_error 1 "cannot find input file: \`$ac_f'" "$LINENO" 5;; + esac + case $ac_f in *\'*) ac_f=`$as_echo "$ac_f" | sed "s/'/'\\\\\\\\''/g"`;; esac + as_fn_append ac_file_inputs " '$ac_f'" + done + + # Let's still pretend it is `configure' which instantiates (i.e., don't + # use $as_me), people would be surprised to read: + # /* config.h. Generated by config.status. */ + configure_input='Generated from '` + $as_echo "$*" | sed 's|^[^:]*/||;s|:[^:]*/|, |g' + `' by configure.' + if test x"$ac_file" != x-; then + configure_input="$ac_file. $configure_input" + { $as_echo "$as_me:${as_lineno-$LINENO}: creating $ac_file" >&5 +$as_echo "$as_me: creating $ac_file" >&6;} + fi + # Neutralize special characters interpreted by sed in replacement strings. + case $configure_input in #( + *\&* | *\|* | *\\* ) + ac_sed_conf_input=`$as_echo "$configure_input" | + sed 's/[\\\\&|]/\\\\&/g'`;; #( + *) ac_sed_conf_input=$configure_input;; + esac + + case $ac_tag in + *:-:* | *:-) cat >"$ac_tmp/stdin" \ + || as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;; + esac + ;; + esac + + ac_dir=`$as_dirname -- "$ac_file" || +$as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$ac_file" : 'X\(//\)[^/]' \| \ + X"$ac_file" : 'X\(//\)$' \| \ + X"$ac_file" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$ac_file" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + as_dir="$ac_dir"; as_fn_mkdir_p + ac_builddir=. + +case "$ac_dir" in +.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; +*) + ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'` + # A ".." for each directory in $ac_dir_suffix. + ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` + case $ac_top_builddir_sub in + "") ac_top_builddir_sub=. ac_top_build_prefix= ;; + *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; + esac ;; +esac +ac_abs_top_builddir=$ac_pwd +ac_abs_builddir=$ac_pwd$ac_dir_suffix +# for backward compatibility: +ac_top_builddir=$ac_top_build_prefix + +case $srcdir in + .) # We are building in place. + ac_srcdir=. + ac_top_srcdir=$ac_top_builddir_sub + ac_abs_top_srcdir=$ac_pwd ;; + [\\/]* | ?:[\\/]* ) # Absolute name. + ac_srcdir=$srcdir$ac_dir_suffix; + ac_top_srcdir=$srcdir + ac_abs_top_srcdir=$srcdir ;; + *) # Relative name. + ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix + ac_top_srcdir=$ac_top_build_prefix$srcdir + ac_abs_top_srcdir=$ac_pwd/$srcdir ;; +esac +ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix + + + case $ac_mode in + :F) + # + # CONFIG_FILE + # + + case $INSTALL in + [\\/$]* | ?:[\\/]* ) ac_INSTALL=$INSTALL ;; + *) ac_INSTALL=$ac_top_build_prefix$INSTALL ;; + esac +# If the template does not know about datarootdir, expand it. +# FIXME: This hack should be removed a few years after 2.60. +ac_datarootdir_hack=; ac_datarootdir_seen= +ac_sed_dataroot=' +/datarootdir/ { + p + q +} +/@datadir@/p +/@docdir@/p +/@infodir@/p +/@localedir@/p +/@mandir@/p' +case `eval "sed -n \"\$ac_sed_dataroot\" $ac_file_inputs"` in +*datarootdir*) ac_datarootdir_seen=yes;; +*@datadir@*|*@docdir@*|*@infodir@*|*@localedir@*|*@mandir@*) + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5 +$as_echo "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;} + ac_datarootdir_hack=' + s&@datadir@&${datarootdir}&g + s&@docdir@&${datarootdir}/doc/${PACKAGE_TARNAME}&g + s&@infodir@&${datarootdir}/info&g + s&@localedir@&${datarootdir}/locale&g + s&@mandir@&${datarootdir}/man&g + s&\${datarootdir}&${prefix}/share&g' ;; +esac +ac_sed_extra="/^[ ]*VPATH[ ]*=[ ]*/{ +h +s/// +s/^/:/ +s/[ ]*$/:/ +s/:\$(srcdir):/:/g +s/:\${srcdir}:/:/g +s/:@srcdir@:/:/g +s/^:*// +s/:*$// +x +s/\(=[ ]*\).*/\1/ +G +s/\n// +s/^[^=]*=[ ]*$// +} + +:t +/@[a-zA-Z_][a-zA-Z_0-9]*@/!b +s|@configure_input@|$ac_sed_conf_input|;t t +s&@top_builddir@&$ac_top_builddir_sub&;t t +s&@top_build_prefix@&$ac_top_build_prefix&;t t +s&@srcdir@&$ac_srcdir&;t t +s&@abs_srcdir@&$ac_abs_srcdir&;t t +s&@top_srcdir@&$ac_top_srcdir&;t t +s&@abs_top_srcdir@&$ac_abs_top_srcdir&;t t +s&@builddir@&$ac_builddir&;t t +s&@abs_builddir@&$ac_abs_builddir&;t t +s&@abs_top_builddir@&$ac_abs_top_builddir&;t t +s&@INSTALL@&$ac_INSTALL&;t t +$ac_datarootdir_hack +" +eval sed \"\$ac_sed_extra\" "$ac_file_inputs" | $AWK -f "$ac_tmp/subs.awk" \ + >$ac_tmp/out || as_fn_error $? "could not create $ac_file" "$LINENO" 5 + +test -z "$ac_datarootdir_hack$ac_datarootdir_seen" && + { ac_out=`sed -n '/\${datarootdir}/p' "$ac_tmp/out"`; test -n "$ac_out"; } && + { ac_out=`sed -n '/^[ ]*datarootdir[ ]*:*=/p' \ + "$ac_tmp/out"`; test -z "$ac_out"; } && + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file contains a reference to the variable \`datarootdir' +which seems to be undefined. Please make sure it is defined" >&5 +$as_echo "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir' +which seems to be undefined. Please make sure it is defined" >&2;} + + rm -f "$ac_tmp/stdin" + case $ac_file in + -) cat "$ac_tmp/out" && rm -f "$ac_tmp/out";; + *) rm -f "$ac_file" && mv "$ac_tmp/out" "$ac_file";; + esac \ + || as_fn_error $? "could not create $ac_file" "$LINENO" 5 + ;; + :H) + # + # CONFIG_HEADER + # + if test x"$ac_file" != x-; then + { + $as_echo "/* $configure_input */" \ + && eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs" + } >"$ac_tmp/config.h" \ + || as_fn_error $? "could not create $ac_file" "$LINENO" 5 + if diff "$ac_file" "$ac_tmp/config.h" >/dev/null 2>&1; then + { $as_echo "$as_me:${as_lineno-$LINENO}: $ac_file is unchanged" >&5 +$as_echo "$as_me: $ac_file is unchanged" >&6;} + else + rm -f "$ac_file" + mv "$ac_tmp/config.h" "$ac_file" \ + || as_fn_error $? "could not create $ac_file" "$LINENO" 5 + fi + else + $as_echo "/* $configure_input */" \ + && eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs" \ + || as_fn_error $? "could not create -" "$LINENO" 5 + fi + ;; + + + esac + +done # for ac_tag + + +as_fn_exit 0 diff --git a/xar/config.sub b/xar/config.sub new file mode 100644 index 0000000..1c366df --- /dev/null +++ b/xar/config.sub @@ -0,0 +1,1579 @@ +#! /bin/sh +# Configuration validation subroutine script. +# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, +# 2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc. + +timestamp='2005-07-08' + +# This file is (in principle) common to ALL GNU software. +# The presence of a machine in this file suggests that SOME GNU software +# can handle that machine. It does not imply ALL GNU software can. +# +# This file is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA +# 02110-1301, USA. +# +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + + +# Please send patches to . Submit a context +# diff and a properly formatted ChangeLog entry. +# +# Configuration subroutine to validate and canonicalize a configuration type. +# Supply the specified configuration type as an argument. +# If it is invalid, we print an error message on stderr and exit with code 1. +# Otherwise, we print the canonical config type on stdout and succeed. + +# This file is supposed to be the same for all GNU packages +# and recognize all the CPU types, system types and aliases +# that are meaningful with *any* GNU software. +# Each package is responsible for reporting which valid configurations +# it does not support. The user should be able to distinguish +# a failure to support a valid configuration from a meaningless +# configuration. + +# The goal of this file is to map all the various variations of a given +# machine specification into a single specification in the form: +# CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM +# or in some cases, the newer four-part form: +# CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM +# It is wrong to echo any other type of specification. + +me=`echo "$0" | sed -e 's,.*/,,'` + +usage="\ +Usage: $0 [OPTION] CPU-MFR-OPSYS + $0 [OPTION] ALIAS + +Canonicalize a configuration name. + +Operation modes: + -h, --help print this help, then exit + -t, --time-stamp print date of last modification, then exit + -v, --version print version number, then exit + +Report bugs and patches to ." + +version="\ +GNU config.sub ($timestamp) + +Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005 +Free Software Foundation, Inc. + +This is free software; see the source for copying conditions. There is NO +warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." + +help=" +Try \`$me --help' for more information." + +# Parse command line +while test $# -gt 0 ; do + case $1 in + --time-stamp | --time* | -t ) + echo "$timestamp" ; exit ;; + --version | -v ) + echo "$version" ; exit ;; + --help | --h* | -h ) + echo "$usage"; exit ;; + -- ) # Stop option processing + shift; break ;; + - ) # Use stdin as input. + break ;; + -* ) + echo "$me: invalid option $1$help" + exit 1 ;; + + *local*) + # First pass through any local machine types. + echo $1 + exit ;; + + * ) + break ;; + esac +done + +case $# in + 0) echo "$me: missing argument$help" >&2 + exit 1;; + 1) ;; + *) echo "$me: too many arguments$help" >&2 + exit 1;; +esac + +# Separate what the user gave into CPU-COMPANY and OS or KERNEL-OS (if any). +# Here we must recognize all the valid KERNEL-OS combinations. +maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'` +case $maybe_os in + nto-qnx* | linux-gnu* | linux-dietlibc | linux-uclibc* | uclinux-uclibc* | uclinux-gnu* | \ + kfreebsd*-gnu* | knetbsd*-gnu* | netbsd*-gnu* | storm-chaos* | os2-emx* | rtmk-nova*) + os=-$maybe_os + basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'` + ;; + *) + basic_machine=`echo $1 | sed 's/-[^-]*$//'` + if [ $basic_machine != $1 ] + then os=`echo $1 | sed 's/.*-/-/'` + else os=; fi + ;; +esac + +### Let's recognize common machines as not being operating systems so +### that things like config.sub decstation-3100 work. We also +### recognize some manufacturers as not being operating systems, so we +### can provide default operating systems below. +case $os in + -sun*os*) + # Prevent following clause from handling this invalid input. + ;; + -dec* | -mips* | -sequent* | -encore* | -pc532* | -sgi* | -sony* | \ + -att* | -7300* | -3300* | -delta* | -motorola* | -sun[234]* | \ + -unicom* | -ibm* | -next | -hp | -isi* | -apollo | -altos* | \ + -convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\ + -c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \ + -harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \ + -apple | -axis | -knuth | -cray) + os= + basic_machine=$1 + ;; + -sim | -cisco | -oki | -wec | -winbond) + os= + basic_machine=$1 + ;; + -scout) + ;; + -wrs) + os=-vxworks + basic_machine=$1 + ;; + -chorusos*) + os=-chorusos + basic_machine=$1 + ;; + -chorusrdb) + os=-chorusrdb + basic_machine=$1 + ;; + -hiux*) + os=-hiuxwe2 + ;; + -sco5) + os=-sco3.2v5 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco4) + os=-sco3.2v4 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco3.2.[4-9]*) + os=`echo $os | sed -e 's/sco3.2./sco3.2v/'` + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco3.2v[4-9]*) + # Don't forget version if it is 3.2v4 or newer. + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco*) + os=-sco3.2v2 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -udk*) + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -isc) + os=-isc2.2 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -clix*) + basic_machine=clipper-intergraph + ;; + -isc*) + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -lynx*) + os=-lynxos + ;; + -ptx*) + basic_machine=`echo $1 | sed -e 's/86-.*/86-sequent/'` + ;; + -windowsnt*) + os=`echo $os | sed -e 's/windowsnt/winnt/'` + ;; + -psos*) + os=-psos + ;; + -mint | -mint[0-9]*) + basic_machine=m68k-atari + os=-mint + ;; +esac + +# Decode aliases for certain CPU-COMPANY combinations. +case $basic_machine in + # Recognize the basic CPU types without company name. + # Some are omitted here because they have special meanings below. + 1750a | 580 \ + | a29k \ + | alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \ + | alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \ + | am33_2.0 \ + | arc | arm | arm[bl]e | arme[lb] | armv[2345] | armv[345][lb] | avr \ + | bfin \ + | c4x | clipper \ + | d10v | d30v | dlx | dsp16xx \ + | fr30 | frv \ + | h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \ + | i370 | i860 | i960 | ia64 \ + | ip2k | iq2000 \ + | m32r | m32rle | m68000 | m68k | m88k | maxq | mcore \ + | mips | mipsbe | mipseb | mipsel | mipsle \ + | mips16 \ + | mips64 | mips64el \ + | mips64vr | mips64vrel \ + | mips64orion | mips64orionel \ + | mips64vr4100 | mips64vr4100el \ + | mips64vr4300 | mips64vr4300el \ + | mips64vr5000 | mips64vr5000el \ + | mips64vr5900 | mips64vr5900el \ + | mipsisa32 | mipsisa32el \ + | mipsisa32r2 | mipsisa32r2el \ + | mipsisa64 | mipsisa64el \ + | mipsisa64r2 | mipsisa64r2el \ + | mipsisa64sb1 | mipsisa64sb1el \ + | mipsisa64sr71k | mipsisa64sr71kel \ + | mipstx39 | mipstx39el \ + | mn10200 | mn10300 \ + | ms1 \ + | msp430 \ + | ns16k | ns32k \ + | or32 \ + | pdp10 | pdp11 | pj | pjl \ + | powerpc | powerpc64 | powerpc64le | powerpcle | ppcbe \ + | pyramid \ + | sh | sh[1234] | sh[24]a | sh[23]e | sh[34]eb | shbe | shle | sh[1234]le | sh3ele \ + | sh64 | sh64le \ + | sparc | sparc64 | sparc64b | sparc86x | sparclet | sparclite \ + | sparcv8 | sparcv9 | sparcv9b \ + | strongarm \ + | tahoe | thumb | tic4x | tic80 | tron \ + | v850 | v850e \ + | we32k \ + | x86 | xscale | xscalee[bl] | xstormy16 | xtensa \ + | z8k) + basic_machine=$basic_machine-unknown + ;; + m32c) + basic_machine=$basic_machine-unknown + ;; + m6811 | m68hc11 | m6812 | m68hc12) + # Motorola 68HC11/12. + basic_machine=$basic_machine-unknown + os=-none + ;; + m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65 | z8k) + ;; + + # We use `pc' rather than `unknown' + # because (1) that's what they normally are, and + # (2) the word "unknown" tends to confuse beginning users. + i*86 | x86_64) + basic_machine=$basic_machine-pc + ;; + # Object if more than one company name word. + *-*-*) + echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 + exit 1 + ;; + # Recognize the basic CPU types with company name. + 580-* \ + | a29k-* \ + | alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \ + | alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \ + | alphapca5[67]-* | alpha64pca5[67]-* | arc-* \ + | arm-* | armbe-* | armle-* | armeb-* | armv*-* \ + | avr-* \ + | bfin-* | bs2000-* \ + | c[123]* | c30-* | [cjt]90-* | c4x-* | c54x-* | c55x-* | c6x-* \ + | clipper-* | craynv-* | cydra-* \ + | d10v-* | d30v-* | dlx-* \ + | elxsi-* \ + | f30[01]-* | f700-* | fr30-* | frv-* | fx80-* \ + | h8300-* | h8500-* \ + | hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \ + | i*86-* | i860-* | i960-* | ia64-* \ + | ip2k-* | iq2000-* \ + | m32r-* | m32rle-* \ + | m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \ + | m88110-* | m88k-* | maxq-* | mcore-* \ + | mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \ + | mips16-* \ + | mips64-* | mips64el-* \ + | mips64vr-* | mips64vrel-* \ + | mips64orion-* | mips64orionel-* \ + | mips64vr4100-* | mips64vr4100el-* \ + | mips64vr4300-* | mips64vr4300el-* \ + | mips64vr5000-* | mips64vr5000el-* \ + | mips64vr5900-* | mips64vr5900el-* \ + | mipsisa32-* | mipsisa32el-* \ + | mipsisa32r2-* | mipsisa32r2el-* \ + | mipsisa64-* | mipsisa64el-* \ + | mipsisa64r2-* | mipsisa64r2el-* \ + | mipsisa64sb1-* | mipsisa64sb1el-* \ + | mipsisa64sr71k-* | mipsisa64sr71kel-* \ + | mipstx39-* | mipstx39el-* \ + | mmix-* \ + | ms1-* \ + | msp430-* \ + | none-* | np1-* | ns16k-* | ns32k-* \ + | orion-* \ + | pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \ + | powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* | ppcbe-* \ + | pyramid-* \ + | romp-* | rs6000-* \ + | sh-* | sh[1234]-* | sh[24]a-* | sh[23]e-* | sh[34]eb-* | shbe-* \ + | shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \ + | sparc-* | sparc64-* | sparc64b-* | sparc86x-* | sparclet-* \ + | sparclite-* \ + | sparcv8-* | sparcv9-* | sparcv9b-* | strongarm-* | sv1-* | sx?-* \ + | tahoe-* | thumb-* \ + | tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \ + | tron-* \ + | v850-* | v850e-* | vax-* \ + | we32k-* \ + | x86-* | x86_64-* | xps100-* | xscale-* | xscalee[bl]-* \ + | xstormy16-* | xtensa-* \ + | ymp-* \ + | z8k-*) + ;; + m32c-*) + ;; + # Recognize the various machine names and aliases which stand + # for a CPU type and a company and sometimes even an OS. + 386bsd) + basic_machine=i386-unknown + os=-bsd + ;; + 3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc) + basic_machine=m68000-att + ;; + 3b*) + basic_machine=we32k-att + ;; + a29khif) + basic_machine=a29k-amd + os=-udi + ;; + abacus) + basic_machine=abacus-unknown + ;; + adobe68k) + basic_machine=m68010-adobe + os=-scout + ;; + alliant | fx80) + basic_machine=fx80-alliant + ;; + altos | altos3068) + basic_machine=m68k-altos + ;; + am29k) + basic_machine=a29k-none + os=-bsd + ;; + amd64) + basic_machine=x86_64-pc + ;; + amd64-*) + basic_machine=x86_64-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + amdahl) + basic_machine=580-amdahl + os=-sysv + ;; + amiga | amiga-*) + basic_machine=m68k-unknown + ;; + amigaos | amigados) + basic_machine=m68k-unknown + os=-amigaos + ;; + amigaunix | amix) + basic_machine=m68k-unknown + os=-sysv4 + ;; + apollo68) + basic_machine=m68k-apollo + os=-sysv + ;; + apollo68bsd) + basic_machine=m68k-apollo + os=-bsd + ;; + aux) + basic_machine=m68k-apple + os=-aux + ;; + balance) + basic_machine=ns32k-sequent + os=-dynix + ;; + c90) + basic_machine=c90-cray + os=-unicos + ;; + convex-c1) + basic_machine=c1-convex + os=-bsd + ;; + convex-c2) + basic_machine=c2-convex + os=-bsd + ;; + convex-c32) + basic_machine=c32-convex + os=-bsd + ;; + convex-c34) + basic_machine=c34-convex + os=-bsd + ;; + convex-c38) + basic_machine=c38-convex + os=-bsd + ;; + cray | j90) + basic_machine=j90-cray + os=-unicos + ;; + craynv) + basic_machine=craynv-cray + os=-unicosmp + ;; + cr16c) + basic_machine=cr16c-unknown + os=-elf + ;; + crds | unos) + basic_machine=m68k-crds + ;; + crisv32 | crisv32-* | etraxfs*) + basic_machine=crisv32-axis + ;; + cris | cris-* | etrax*) + basic_machine=cris-axis + ;; + crx) + basic_machine=crx-unknown + os=-elf + ;; + da30 | da30-*) + basic_machine=m68k-da30 + ;; + decstation | decstation-3100 | pmax | pmax-* | pmin | dec3100 | decstatn) + basic_machine=mips-dec + ;; + decsystem10* | dec10*) + basic_machine=pdp10-dec + os=-tops10 + ;; + decsystem20* | dec20*) + basic_machine=pdp10-dec + os=-tops20 + ;; + delta | 3300 | motorola-3300 | motorola-delta \ + | 3300-motorola | delta-motorola) + basic_machine=m68k-motorola + ;; + delta88) + basic_machine=m88k-motorola + os=-sysv3 + ;; + djgpp) + basic_machine=i586-pc + os=-msdosdjgpp + ;; + dpx20 | dpx20-*) + basic_machine=rs6000-bull + os=-bosx + ;; + dpx2* | dpx2*-bull) + basic_machine=m68k-bull + os=-sysv3 + ;; + ebmon29k) + basic_machine=a29k-amd + os=-ebmon + ;; + elxsi) + basic_machine=elxsi-elxsi + os=-bsd + ;; + encore | umax | mmax) + basic_machine=ns32k-encore + ;; + es1800 | OSE68k | ose68k | ose | OSE) + basic_machine=m68k-ericsson + os=-ose + ;; + fx2800) + basic_machine=i860-alliant + ;; + genix) + basic_machine=ns32k-ns + ;; + gmicro) + basic_machine=tron-gmicro + os=-sysv + ;; + go32) + basic_machine=i386-pc + os=-go32 + ;; + h3050r* | hiux*) + basic_machine=hppa1.1-hitachi + os=-hiuxwe2 + ;; + h8300hms) + basic_machine=h8300-hitachi + os=-hms + ;; + h8300xray) + basic_machine=h8300-hitachi + os=-xray + ;; + h8500hms) + basic_machine=h8500-hitachi + os=-hms + ;; + harris) + basic_machine=m88k-harris + os=-sysv3 + ;; + hp300-*) + basic_machine=m68k-hp + ;; + hp300bsd) + basic_machine=m68k-hp + os=-bsd + ;; + hp300hpux) + basic_machine=m68k-hp + os=-hpux + ;; + hp3k9[0-9][0-9] | hp9[0-9][0-9]) + basic_machine=hppa1.0-hp + ;; + hp9k2[0-9][0-9] | hp9k31[0-9]) + basic_machine=m68000-hp + ;; + hp9k3[2-9][0-9]) + basic_machine=m68k-hp + ;; + hp9k6[0-9][0-9] | hp6[0-9][0-9]) + basic_machine=hppa1.0-hp + ;; + hp9k7[0-79][0-9] | hp7[0-79][0-9]) + basic_machine=hppa1.1-hp + ;; + hp9k78[0-9] | hp78[0-9]) + # FIXME: really hppa2.0-hp + basic_machine=hppa1.1-hp + ;; + hp9k8[67]1 | hp8[67]1 | hp9k80[24] | hp80[24] | hp9k8[78]9 | hp8[78]9 | hp9k893 | hp893) + # FIXME: really hppa2.0-hp + basic_machine=hppa1.1-hp + ;; + hp9k8[0-9][13679] | hp8[0-9][13679]) + basic_machine=hppa1.1-hp + ;; + hp9k8[0-9][0-9] | hp8[0-9][0-9]) + basic_machine=hppa1.0-hp + ;; + hppa-next) + os=-nextstep3 + ;; + hppaosf) + basic_machine=hppa1.1-hp + os=-osf + ;; + hppro) + basic_machine=hppa1.1-hp + os=-proelf + ;; + i370-ibm* | ibm*) + basic_machine=i370-ibm + ;; +# I'm not sure what "Sysv32" means. Should this be sysv3.2? + i*86v32) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-sysv32 + ;; + i*86v4*) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-sysv4 + ;; + i*86v) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-sysv + ;; + i*86sol2) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-solaris2 + ;; + i386mach) + basic_machine=i386-mach + os=-mach + ;; + i386-vsta | vsta) + basic_machine=i386-unknown + os=-vsta + ;; + iris | iris4d) + basic_machine=mips-sgi + case $os in + -irix*) + ;; + *) + os=-irix4 + ;; + esac + ;; + isi68 | isi) + basic_machine=m68k-isi + os=-sysv + ;; + m88k-omron*) + basic_machine=m88k-omron + ;; + magnum | m3230) + basic_machine=mips-mips + os=-sysv + ;; + merlin) + basic_machine=ns32k-utek + os=-sysv + ;; + mingw32) + basic_machine=i386-pc + os=-mingw32 + ;; + miniframe) + basic_machine=m68000-convergent + ;; + *mint | -mint[0-9]* | *MiNT | *MiNT[0-9]*) + basic_machine=m68k-atari + os=-mint + ;; + mips3*-*) + basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'` + ;; + mips3*) + basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown + ;; + monitor) + basic_machine=m68k-rom68k + os=-coff + ;; + morphos) + basic_machine=powerpc-unknown + os=-morphos + ;; + msdos) + basic_machine=i386-pc + os=-msdos + ;; + mvs) + basic_machine=i370-ibm + os=-mvs + ;; + ncr3000) + basic_machine=i486-ncr + os=-sysv4 + ;; + netbsd386) + basic_machine=i386-unknown + os=-netbsd + ;; + netwinder) + basic_machine=armv4l-rebel + os=-linux + ;; + news | news700 | news800 | news900) + basic_machine=m68k-sony + os=-newsos + ;; + news1000) + basic_machine=m68030-sony + os=-newsos + ;; + news-3600 | risc-news) + basic_machine=mips-sony + os=-newsos + ;; + necv70) + basic_machine=v70-nec + os=-sysv + ;; + next | m*-next ) + basic_machine=m68k-next + case $os in + -nextstep* ) + ;; + -ns2*) + os=-nextstep2 + ;; + *) + os=-nextstep3 + ;; + esac + ;; + nh3000) + basic_machine=m68k-harris + os=-cxux + ;; + nh[45]000) + basic_machine=m88k-harris + os=-cxux + ;; + nindy960) + basic_machine=i960-intel + os=-nindy + ;; + mon960) + basic_machine=i960-intel + os=-mon960 + ;; + nonstopux) + basic_machine=mips-compaq + os=-nonstopux + ;; + np1) + basic_machine=np1-gould + ;; + nsr-tandem) + basic_machine=nsr-tandem + ;; + op50n-* | op60c-*) + basic_machine=hppa1.1-oki + os=-proelf + ;; + openrisc | openrisc-*) + basic_machine=or32-unknown + ;; + os400) + basic_machine=powerpc-ibm + os=-os400 + ;; + OSE68000 | ose68000) + basic_machine=m68000-ericsson + os=-ose + ;; + os68k) + basic_machine=m68k-none + os=-os68k + ;; + pa-hitachi) + basic_machine=hppa1.1-hitachi + os=-hiuxwe2 + ;; + paragon) + basic_machine=i860-intel + os=-osf + ;; + pbd) + basic_machine=sparc-tti + ;; + pbb) + basic_machine=m68k-tti + ;; + pc532 | pc532-*) + basic_machine=ns32k-pc532 + ;; + pentium | p5 | k5 | k6 | nexgen | viac3) + basic_machine=i586-pc + ;; + pentiumpro | p6 | 6x86 | athlon | athlon_*) + basic_machine=i686-pc + ;; + pentiumii | pentium2 | pentiumiii | pentium3) + basic_machine=i686-pc + ;; + pentium4) + basic_machine=i786-pc + ;; + pentium-* | p5-* | k5-* | k6-* | nexgen-* | viac3-*) + basic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pentiumpro-* | p6-* | 6x86-* | athlon-*) + basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pentiumii-* | pentium2-* | pentiumiii-* | pentium3-*) + basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pentium4-*) + basic_machine=i786-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pn) + basic_machine=pn-gould + ;; + power) basic_machine=power-ibm + ;; + ppc) basic_machine=powerpc-unknown + ;; + ppc-*) basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + ppcle | powerpclittle | ppc-le | powerpc-little) + basic_machine=powerpcle-unknown + ;; + ppcle-* | powerpclittle-*) + basic_machine=powerpcle-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + ppc64) basic_machine=powerpc64-unknown + ;; + ppc64-*) basic_machine=powerpc64-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + ppc64le | powerpc64little | ppc64-le | powerpc64-little) + basic_machine=powerpc64le-unknown + ;; + ppc64le-* | powerpc64little-*) + basic_machine=powerpc64le-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + ps2) + basic_machine=i386-ibm + ;; + pw32) + basic_machine=i586-unknown + os=-pw32 + ;; + rom68k) + basic_machine=m68k-rom68k + os=-coff + ;; + rm[46]00) + basic_machine=mips-siemens + ;; + rtpc | rtpc-*) + basic_machine=romp-ibm + ;; + s390 | s390-*) + basic_machine=s390-ibm + ;; + s390x | s390x-*) + basic_machine=s390x-ibm + ;; + sa29200) + basic_machine=a29k-amd + os=-udi + ;; + sb1) + basic_machine=mipsisa64sb1-unknown + ;; + sb1el) + basic_machine=mipsisa64sb1el-unknown + ;; + sei) + basic_machine=mips-sei + os=-seiux + ;; + sequent) + basic_machine=i386-sequent + ;; + sh) + basic_machine=sh-hitachi + os=-hms + ;; + sh64) + basic_machine=sh64-unknown + ;; + sparclite-wrs | simso-wrs) + basic_machine=sparclite-wrs + os=-vxworks + ;; + sps7) + basic_machine=m68k-bull + os=-sysv2 + ;; + spur) + basic_machine=spur-unknown + ;; + st2000) + basic_machine=m68k-tandem + ;; + stratus) + basic_machine=i860-stratus + os=-sysv4 + ;; + sun2) + basic_machine=m68000-sun + ;; + sun2os3) + basic_machine=m68000-sun + os=-sunos3 + ;; + sun2os4) + basic_machine=m68000-sun + os=-sunos4 + ;; + sun3os3) + basic_machine=m68k-sun + os=-sunos3 + ;; + sun3os4) + basic_machine=m68k-sun + os=-sunos4 + ;; + sun4os3) + basic_machine=sparc-sun + os=-sunos3 + ;; + sun4os4) + basic_machine=sparc-sun + os=-sunos4 + ;; + sun4sol2) + basic_machine=sparc-sun + os=-solaris2 + ;; + sun3 | sun3-*) + basic_machine=m68k-sun + ;; + sun4) + basic_machine=sparc-sun + ;; + sun386 | sun386i | roadrunner) + basic_machine=i386-sun + ;; + sv1) + basic_machine=sv1-cray + os=-unicos + ;; + symmetry) + basic_machine=i386-sequent + os=-dynix + ;; + t3e) + basic_machine=alphaev5-cray + os=-unicos + ;; + t90) + basic_machine=t90-cray + os=-unicos + ;; + tic54x | c54x*) + basic_machine=tic54x-unknown + os=-coff + ;; + tic55x | c55x*) + basic_machine=tic55x-unknown + os=-coff + ;; + tic6x | c6x*) + basic_machine=tic6x-unknown + os=-coff + ;; + tx39) + basic_machine=mipstx39-unknown + ;; + tx39el) + basic_machine=mipstx39el-unknown + ;; + toad1) + basic_machine=pdp10-xkl + os=-tops20 + ;; + tower | tower-32) + basic_machine=m68k-ncr + ;; + tpf) + basic_machine=s390x-ibm + os=-tpf + ;; + udi29k) + basic_machine=a29k-amd + os=-udi + ;; + ultra3) + basic_machine=a29k-nyu + os=-sym1 + ;; + v810 | necv810) + basic_machine=v810-nec + os=-none + ;; + vaxv) + basic_machine=vax-dec + os=-sysv + ;; + vms) + basic_machine=vax-dec + os=-vms + ;; + vpp*|vx|vx-*) + basic_machine=f301-fujitsu + ;; + vxworks960) + basic_machine=i960-wrs + os=-vxworks + ;; + vxworks68) + basic_machine=m68k-wrs + os=-vxworks + ;; + vxworks29k) + basic_machine=a29k-wrs + os=-vxworks + ;; + w65*) + basic_machine=w65-wdc + os=-none + ;; + w89k-*) + basic_machine=hppa1.1-winbond + os=-proelf + ;; + xbox) + basic_machine=i686-pc + os=-mingw32 + ;; + xps | xps100) + basic_machine=xps100-honeywell + ;; + ymp) + basic_machine=ymp-cray + os=-unicos + ;; + z8k-*-coff) + basic_machine=z8k-unknown + os=-sim + ;; + none) + basic_machine=none-none + os=-none + ;; + +# Here we handle the default manufacturer of certain CPU types. It is in +# some cases the only manufacturer, in others, it is the most popular. + w89k) + basic_machine=hppa1.1-winbond + ;; + op50n) + basic_machine=hppa1.1-oki + ;; + op60c) + basic_machine=hppa1.1-oki + ;; + romp) + basic_machine=romp-ibm + ;; + mmix) + basic_machine=mmix-knuth + ;; + rs6000) + basic_machine=rs6000-ibm + ;; + vax) + basic_machine=vax-dec + ;; + pdp10) + # there are many clones, so DEC is not a safe bet + basic_machine=pdp10-unknown + ;; + pdp11) + basic_machine=pdp11-dec + ;; + we32k) + basic_machine=we32k-att + ;; + sh[1234] | sh[24]a | sh[34]eb | sh[1234]le | sh[23]ele) + basic_machine=sh-unknown + ;; + sparc | sparcv8 | sparcv9 | sparcv9b) + basic_machine=sparc-sun + ;; + cydra) + basic_machine=cydra-cydrome + ;; + orion) + basic_machine=orion-highlevel + ;; + orion105) + basic_machine=clipper-highlevel + ;; + mac | mpw | mac-mpw) + basic_machine=m68k-apple + ;; + pmac | pmac-mpw) + basic_machine=powerpc-apple + ;; + *-unknown) + # Make sure to match an already-canonicalized machine name. + ;; + *) + echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 + exit 1 + ;; +esac + +# Here we canonicalize certain aliases for manufacturers. +case $basic_machine in + *-digital*) + basic_machine=`echo $basic_machine | sed 's/digital.*/dec/'` + ;; + *-commodore*) + basic_machine=`echo $basic_machine | sed 's/commodore.*/cbm/'` + ;; + *) + ;; +esac + +# Decode manufacturer-specific aliases for certain operating systems. + +if [ x"$os" != x"" ] +then +case $os in + # First match some system type aliases + # that might get confused with valid system types. + # -solaris* is a basic system type, with this one exception. + -solaris1 | -solaris1.*) + os=`echo $os | sed -e 's|solaris1|sunos4|'` + ;; + -solaris) + os=-solaris2 + ;; + -svr4*) + os=-sysv4 + ;; + -unixware*) + os=-sysv4.2uw + ;; + -gnu/linux*) + os=`echo $os | sed -e 's|gnu/linux|linux-gnu|'` + ;; + # First accept the basic system types. + # The portable systems comes first. + # Each alternative MUST END IN A *, to match a version number. + # -sysv* is not here because it comes later, after sysvr4. + -gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \ + | -*vms* | -sco* | -esix* | -isc* | -aix* | -sunos | -sunos[34]*\ + | -hpux* | -unos* | -osf* | -luna* | -dgux* | -solaris* | -sym* \ + | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \ + | -aos* \ + | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \ + | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \ + | -hiux* | -386bsd* | -knetbsd* | -mirbsd* | -netbsd* | -openbsd* \ + | -ekkobsd* | -kfreebsd* | -freebsd* | -riscix* | -lynxos* \ + | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \ + | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \ + | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \ + | -chorusos* | -chorusrdb* \ + | -cygwin* | -pe* | -psos* | -moss* | -proelf* | -rtems* \ + | -mingw32* | -linux-gnu* | -linux-uclibc* | -uxpv* | -beos* | -mpeix* | -udk* \ + | -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \ + | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \ + | -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \ + | -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \ + | -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \ + | -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly* \ + | -skyos* | -haiku*) + # Remember, each alternative MUST END IN *, to match a version number. + ;; + -qnx*) + case $basic_machine in + x86-* | i*86-*) + ;; + *) + os=-nto$os + ;; + esac + ;; + -nto-qnx*) + ;; + -nto*) + os=`echo $os | sed -e 's|nto|nto-qnx|'` + ;; + -sim | -es1800* | -hms* | -xray | -os68k* | -none* | -v88r* \ + | -windows* | -osx | -abug | -netware* | -os9* | -beos* | -haiku* \ + | -macos* | -mpw* | -magic* | -mmixware* | -mon960* | -lnews*) + ;; + -mac*) + os=`echo $os | sed -e 's|mac|macos|'` + ;; + -linux-dietlibc) + os=-linux-dietlibc + ;; + -linux*) + os=`echo $os | sed -e 's|linux|linux-gnu|'` + ;; + -sunos5*) + os=`echo $os | sed -e 's|sunos5|solaris2|'` + ;; + -sunos6*) + os=`echo $os | sed -e 's|sunos6|solaris3|'` + ;; + -opened*) + os=-openedition + ;; + -os400*) + os=-os400 + ;; + -wince*) + os=-wince + ;; + -osfrose*) + os=-osfrose + ;; + -osf*) + os=-osf + ;; + -utek*) + os=-bsd + ;; + -dynix*) + os=-bsd + ;; + -acis*) + os=-aos + ;; + -atheos*) + os=-atheos + ;; + -syllable*) + os=-syllable + ;; + -386bsd) + os=-bsd + ;; + -ctix* | -uts*) + os=-sysv + ;; + -nova*) + os=-rtmk-nova + ;; + -ns2 ) + os=-nextstep2 + ;; + -nsk*) + os=-nsk + ;; + # Preserve the version number of sinix5. + -sinix5.*) + os=`echo $os | sed -e 's|sinix|sysv|'` + ;; + -sinix*) + os=-sysv4 + ;; + -tpf*) + os=-tpf + ;; + -triton*) + os=-sysv3 + ;; + -oss*) + os=-sysv3 + ;; + -svr4) + os=-sysv4 + ;; + -svr3) + os=-sysv3 + ;; + -sysvr4) + os=-sysv4 + ;; + # This must come after -sysvr4. + -sysv*) + ;; + -ose*) + os=-ose + ;; + -es1800*) + os=-ose + ;; + -xenix) + os=-xenix + ;; + -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) + os=-mint + ;; + -aros*) + os=-aros + ;; + -kaos*) + os=-kaos + ;; + -zvmoe) + os=-zvmoe + ;; + -none) + ;; + *) + # Get rid of the `-' at the beginning of $os. + os=`echo $os | sed 's/[^-]*-//'` + echo Invalid configuration \`$1\': system \`$os\' not recognized 1>&2 + exit 1 + ;; +esac +else + +# Here we handle the default operating systems that come with various machines. +# The value should be what the vendor currently ships out the door with their +# machine or put another way, the most popular os provided with the machine. + +# Note that if you're going to try to match "-MANUFACTURER" here (say, +# "-sun"), then you have to tell the case statement up towards the top +# that MANUFACTURER isn't an operating system. Otherwise, code above +# will signal an error saying that MANUFACTURER isn't an operating +# system, and we'll never get to this point. + +case $basic_machine in + *-acorn) + os=-riscix1.2 + ;; + arm*-rebel) + os=-linux + ;; + arm*-semi) + os=-aout + ;; + c4x-* | tic4x-*) + os=-coff + ;; + # This must come before the *-dec entry. + pdp10-*) + os=-tops20 + ;; + pdp11-*) + os=-none + ;; + *-dec | vax-*) + os=-ultrix4.2 + ;; + m68*-apollo) + os=-domain + ;; + i386-sun) + os=-sunos4.0.2 + ;; + m68000-sun) + os=-sunos3 + # This also exists in the configure program, but was not the + # default. + # os=-sunos4 + ;; + m68*-cisco) + os=-aout + ;; + mips*-cisco) + os=-elf + ;; + mips*-*) + os=-elf + ;; + or32-*) + os=-coff + ;; + *-tti) # must be before sparc entry or we get the wrong os. + os=-sysv3 + ;; + sparc-* | *-sun) + os=-sunos4.1.1 + ;; + *-be) + os=-beos + ;; + *-haiku) + os=-haiku + ;; + *-ibm) + os=-aix + ;; + *-knuth) + os=-mmixware + ;; + *-wec) + os=-proelf + ;; + *-winbond) + os=-proelf + ;; + *-oki) + os=-proelf + ;; + *-hp) + os=-hpux + ;; + *-hitachi) + os=-hiux + ;; + i860-* | *-att | *-ncr | *-altos | *-motorola | *-convergent) + os=-sysv + ;; + *-cbm) + os=-amigaos + ;; + *-dg) + os=-dgux + ;; + *-dolphin) + os=-sysv3 + ;; + m68k-ccur) + os=-rtu + ;; + m88k-omron*) + os=-luna + ;; + *-next ) + os=-nextstep + ;; + *-sequent) + os=-ptx + ;; + *-crds) + os=-unos + ;; + *-ns) + os=-genix + ;; + i370-*) + os=-mvs + ;; + *-next) + os=-nextstep3 + ;; + *-gould) + os=-sysv + ;; + *-highlevel) + os=-bsd + ;; + *-encore) + os=-bsd + ;; + *-sgi) + os=-irix + ;; + *-siemens) + os=-sysv4 + ;; + *-masscomp) + os=-rtu + ;; + f30[01]-fujitsu | f700-fujitsu) + os=-uxpv + ;; + *-rom68k) + os=-coff + ;; + *-*bug) + os=-coff + ;; + *-apple) + os=-macos + ;; + *-atari*) + os=-mint + ;; + *) + os=-none + ;; +esac +fi + +# Here we handle the case where we know the os, and the CPU type, but not the +# manufacturer. We pick the logical manufacturer. +vendor=unknown +case $basic_machine in + *-unknown) + case $os in + -riscix*) + vendor=acorn + ;; + -sunos*) + vendor=sun + ;; + -aix*) + vendor=ibm + ;; + -beos*) + vendor=be + ;; + -hpux*) + vendor=hp + ;; + -mpeix*) + vendor=hp + ;; + -hiux*) + vendor=hitachi + ;; + -unos*) + vendor=crds + ;; + -dgux*) + vendor=dg + ;; + -luna*) + vendor=omron + ;; + -genix*) + vendor=ns + ;; + -mvs* | -opened*) + vendor=ibm + ;; + -os400*) + vendor=ibm + ;; + -ptx*) + vendor=sequent + ;; + -tpf*) + vendor=ibm + ;; + -vxsim* | -vxworks* | -windiss*) + vendor=wrs + ;; + -aux*) + vendor=apple + ;; + -hms*) + vendor=hitachi + ;; + -mpw* | -macos*) + vendor=apple + ;; + -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) + vendor=atari + ;; + -vos*) + vendor=stratus + ;; + esac + basic_machine=`echo $basic_machine | sed "s/unknown/$vendor/"` + ;; +esac + +echo $basic_machine$os +exit + +# Local variables: +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "timestamp='" +# time-stamp-format: "%:y-%02m-%02d" +# time-stamp-end: "'" +# End: diff --git a/xar/configure b/xar/configure new file mode 100755 index 0000000..e2102d1 --- /dev/null +++ b/xar/configure @@ -0,0 +1,6350 @@ +#! /bin/sh +# Guess values for system-dependent variables and create Makefiles. +# Generated by GNU Autoconf 2.69 for Xar 1.8dev. +# +# Report bugs to . +# +# +# Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc. +# +# +# This configure script is free software; the Free Software Foundation +# gives unlimited permission to copy, distribute and modify it. +## -------------------- ## +## M4sh Initialization. ## +## -------------------- ## + +# Be more Bourne compatible +DUALCASE=1; export DUALCASE # for MKS sh +if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then : + emulate sh + NULLCMD=: + # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which + # is contrary to our usage. Disable this feature. + alias -g '${1+"$@"}'='"$@"' + setopt NO_GLOB_SUBST +else + case `(set -o) 2>/dev/null` in #( + *posix*) : + set -o posix ;; #( + *) : + ;; +esac +fi + + +as_nl=' +' +export as_nl +# Printing a long string crashes Solaris 7 /usr/bin/printf. +as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' +as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo +as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo +# Prefer a ksh shell builtin over an external printf program on Solaris, +# but without wasting forks for bash or zsh. +if test -z "$BASH_VERSION$ZSH_VERSION" \ + && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then + as_echo='print -r --' + as_echo_n='print -rn --' +elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then + as_echo='printf %s\n' + as_echo_n='printf %s' +else + if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then + as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"' + as_echo_n='/usr/ucb/echo -n' + else + as_echo_body='eval expr "X$1" : "X\\(.*\\)"' + as_echo_n_body='eval + arg=$1; + case $arg in #( + *"$as_nl"*) + expr "X$arg" : "X\\(.*\\)$as_nl"; + arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;; + esac; + expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl" + ' + export as_echo_n_body + as_echo_n='sh -c $as_echo_n_body as_echo' + fi + export as_echo_body + as_echo='sh -c $as_echo_body as_echo' +fi + +# The user is always right. +if test "${PATH_SEPARATOR+set}" != set; then + PATH_SEPARATOR=: + (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { + (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || + PATH_SEPARATOR=';' + } +fi + + +# IFS +# We need space, tab and new line, in precisely that order. Quoting is +# there to prevent editors from complaining about space-tab. +# (If _AS_PATH_WALK were called with IFS unset, it would disable word +# splitting by setting IFS to empty value.) +IFS=" "" $as_nl" + +# Find who we are. Look in the path if we contain no directory separator. +as_myself= +case $0 in #(( + *[\\/]* ) as_myself=$0 ;; + *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break + done +IFS=$as_save_IFS + + ;; +esac +# We did not find ourselves, most probably we were run as `sh COMMAND' +# in which case we are not to be found in the path. +if test "x$as_myself" = x; then + as_myself=$0 +fi +if test ! -f "$as_myself"; then + $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 + exit 1 +fi + +# Unset variables that we do not need and which cause bugs (e.g. in +# pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1" +# suppresses any "Segmentation fault" message there. '((' could +# trigger a bug in pdksh 5.2.14. +for as_var in BASH_ENV ENV MAIL MAILPATH +do eval test x\${$as_var+set} = xset \ + && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : +done +PS1='$ ' +PS2='> ' +PS4='+ ' + +# NLS nuisances. +LC_ALL=C +export LC_ALL +LANGUAGE=C +export LANGUAGE + +# CDPATH. +(unset CDPATH) >/dev/null 2>&1 && unset CDPATH + +# Use a proper internal environment variable to ensure we don't fall + # into an infinite loop, continuously re-executing ourselves. + if test x"${_as_can_reexec}" != xno && test "x$CONFIG_SHELL" != x; then + _as_can_reexec=no; export _as_can_reexec; + # We cannot yet assume a decent shell, so we have to provide a +# neutralization value for shells without unset; and this also +# works around shells that cannot unset nonexistent variables. +# Preserve -v and -x to the replacement shell. +BASH_ENV=/dev/null +ENV=/dev/null +(unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV +case $- in # (((( + *v*x* | *x*v* ) as_opts=-vx ;; + *v* ) as_opts=-v ;; + *x* ) as_opts=-x ;; + * ) as_opts= ;; +esac +exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"} +# Admittedly, this is quite paranoid, since all the known shells bail +# out after a failed `exec'. +$as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2 +as_fn_exit 255 + fi + # We don't want this to propagate to other subprocesses. + { _as_can_reexec=; unset _as_can_reexec;} +if test "x$CONFIG_SHELL" = x; then + as_bourne_compatible="if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then : + emulate sh + NULLCMD=: + # Pre-4.2 versions of Zsh do word splitting on \${1+\"\$@\"}, which + # is contrary to our usage. Disable this feature. + alias -g '\${1+\"\$@\"}'='\"\$@\"' + setopt NO_GLOB_SUBST +else + case \`(set -o) 2>/dev/null\` in #( + *posix*) : + set -o posix ;; #( + *) : + ;; +esac +fi +" + as_required="as_fn_return () { (exit \$1); } +as_fn_success () { as_fn_return 0; } +as_fn_failure () { as_fn_return 1; } +as_fn_ret_success () { return 0; } +as_fn_ret_failure () { return 1; } + +exitcode=0 +as_fn_success || { exitcode=1; echo as_fn_success failed.; } +as_fn_failure && { exitcode=1; echo as_fn_failure succeeded.; } +as_fn_ret_success || { exitcode=1; echo as_fn_ret_success failed.; } +as_fn_ret_failure && { exitcode=1; echo as_fn_ret_failure succeeded.; } +if ( set x; as_fn_ret_success y && test x = \"\$1\" ); then : + +else + exitcode=1; echo positional parameters were not saved. +fi +test x\$exitcode = x0 || exit 1 +test -x / || exit 1" + as_suggested=" as_lineno_1=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_1a=\$LINENO + as_lineno_2=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_2a=\$LINENO + eval 'test \"x\$as_lineno_1'\$as_run'\" != \"x\$as_lineno_2'\$as_run'\" && + test \"x\`expr \$as_lineno_1'\$as_run' + 1\`\" = \"x\$as_lineno_2'\$as_run'\"' || exit 1 +test \$(( 1 + 1 )) = 2 || exit 1" + if (eval "$as_required") 2>/dev/null; then : + as_have_required=yes +else + as_have_required=no +fi + if test x$as_have_required = xyes && (eval "$as_suggested") 2>/dev/null; then : + +else + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +as_found=false +for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + as_found=: + case $as_dir in #( + /*) + for as_base in sh bash ksh sh5; do + # Try only shells that exist, to save several forks. + as_shell=$as_dir/$as_base + if { test -f "$as_shell" || test -f "$as_shell.exe"; } && + { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$as_shell"; } 2>/dev/null; then : + CONFIG_SHELL=$as_shell as_have_required=yes + if { $as_echo "$as_bourne_compatible""$as_suggested" | as_run=a "$as_shell"; } 2>/dev/null; then : + break 2 +fi +fi + done;; + esac + as_found=false +done +$as_found || { if { test -f "$SHELL" || test -f "$SHELL.exe"; } && + { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$SHELL"; } 2>/dev/null; then : + CONFIG_SHELL=$SHELL as_have_required=yes +fi; } +IFS=$as_save_IFS + + + if test "x$CONFIG_SHELL" != x; then : + export CONFIG_SHELL + # We cannot yet assume a decent shell, so we have to provide a +# neutralization value for shells without unset; and this also +# works around shells that cannot unset nonexistent variables. +# Preserve -v and -x to the replacement shell. +BASH_ENV=/dev/null +ENV=/dev/null +(unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV +case $- in # (((( + *v*x* | *x*v* ) as_opts=-vx ;; + *v* ) as_opts=-v ;; + *x* ) as_opts=-x ;; + * ) as_opts= ;; +esac +exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"} +# Admittedly, this is quite paranoid, since all the known shells bail +# out after a failed `exec'. +$as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2 +exit 255 +fi + + if test x$as_have_required = xno; then : + $as_echo "$0: This script requires a shell more modern than all" + $as_echo "$0: the shells that I found on your system." + if test x${ZSH_VERSION+set} = xset ; then + $as_echo "$0: In particular, zsh $ZSH_VERSION has bugs and should" + $as_echo "$0: be upgraded to zsh 4.3.4 or later." + else + $as_echo "$0: Please tell bug-autoconf@gnu.org and +$0: xar-devel@googlegroups.com about your system, including +$0: any error possibly output before this message. Then +$0: install a modern shell, or manually run the script +$0: under such a shell if you do have one." + fi + exit 1 +fi +fi +fi +SHELL=${CONFIG_SHELL-/bin/sh} +export SHELL +# Unset more variables known to interfere with behavior of common tools. +CLICOLOR_FORCE= GREP_OPTIONS= +unset CLICOLOR_FORCE GREP_OPTIONS + +## --------------------- ## +## M4sh Shell Functions. ## +## --------------------- ## +# as_fn_unset VAR +# --------------- +# Portably unset VAR. +as_fn_unset () +{ + { eval $1=; unset $1;} +} +as_unset=as_fn_unset + +# as_fn_set_status STATUS +# ----------------------- +# Set $? to STATUS, without forking. +as_fn_set_status () +{ + return $1 +} # as_fn_set_status + +# as_fn_exit STATUS +# ----------------- +# Exit the shell with STATUS, even in a "trap 0" or "set -e" context. +as_fn_exit () +{ + set +e + as_fn_set_status $1 + exit $1 +} # as_fn_exit + +# as_fn_mkdir_p +# ------------- +# Create "$as_dir" as a directory, including parents if necessary. +as_fn_mkdir_p () +{ + + case $as_dir in #( + -*) as_dir=./$as_dir;; + esac + test -d "$as_dir" || eval $as_mkdir_p || { + as_dirs= + while :; do + case $as_dir in #( + *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( + *) as_qdir=$as_dir;; + esac + as_dirs="'$as_qdir' $as_dirs" + as_dir=`$as_dirname -- "$as_dir" || +$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$as_dir" : 'X\(//\)[^/]' \| \ + X"$as_dir" : 'X\(//\)$' \| \ + X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$as_dir" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + test -d "$as_dir" && break + done + test -z "$as_dirs" || eval "mkdir $as_dirs" + } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir" + + +} # as_fn_mkdir_p + +# as_fn_executable_p FILE +# ----------------------- +# Test if FILE is an executable regular file. +as_fn_executable_p () +{ + test -f "$1" && test -x "$1" +} # as_fn_executable_p +# as_fn_append VAR VALUE +# ---------------------- +# Append the text in VALUE to the end of the definition contained in VAR. Take +# advantage of any shell optimizations that allow amortized linear growth over +# repeated appends, instead of the typical quadratic growth present in naive +# implementations. +if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then : + eval 'as_fn_append () + { + eval $1+=\$2 + }' +else + as_fn_append () + { + eval $1=\$$1\$2 + } +fi # as_fn_append + +# as_fn_arith ARG... +# ------------------ +# Perform arithmetic evaluation on the ARGs, and store the result in the +# global $as_val. Take advantage of shells that can avoid forks. The arguments +# must be portable across $(()) and expr. +if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then : + eval 'as_fn_arith () + { + as_val=$(( $* )) + }' +else + as_fn_arith () + { + as_val=`expr "$@" || test $? -eq 1` + } +fi # as_fn_arith + + +# as_fn_error STATUS ERROR [LINENO LOG_FD] +# ---------------------------------------- +# Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are +# provided, also output the error to LOG_FD, referencing LINENO. Then exit the +# script with STATUS, using 1 if that was 0. +as_fn_error () +{ + as_status=$1; test $as_status -eq 0 && as_status=1 + if test "$4"; then + as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4 + fi + $as_echo "$as_me: error: $2" >&2 + as_fn_exit $as_status +} # as_fn_error + +if expr a : '\(a\)' >/dev/null 2>&1 && + test "X`expr 00001 : '.*\(...\)'`" = X001; then + as_expr=expr +else + as_expr=false +fi + +if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then + as_basename=basename +else + as_basename=false +fi + +if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then + as_dirname=dirname +else + as_dirname=false +fi + +as_me=`$as_basename -- "$0" || +$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ + X"$0" : 'X\(//\)$' \| \ + X"$0" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X/"$0" | + sed '/^.*\/\([^/][^/]*\)\/*$/{ + s//\1/ + q + } + /^X\/\(\/\/\)$/{ + s//\1/ + q + } + /^X\/\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + +# Avoid depending upon Character Ranges. +as_cr_letters='abcdefghijklmnopqrstuvwxyz' +as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' +as_cr_Letters=$as_cr_letters$as_cr_LETTERS +as_cr_digits='0123456789' +as_cr_alnum=$as_cr_Letters$as_cr_digits + + + as_lineno_1=$LINENO as_lineno_1a=$LINENO + as_lineno_2=$LINENO as_lineno_2a=$LINENO + eval 'test "x$as_lineno_1'$as_run'" != "x$as_lineno_2'$as_run'" && + test "x`expr $as_lineno_1'$as_run' + 1`" = "x$as_lineno_2'$as_run'"' || { + # Blame Lee E. McMahon (1931-1989) for sed's syntax. :-) + sed -n ' + p + /[$]LINENO/= + ' <$as_myself | + sed ' + s/[$]LINENO.*/&-/ + t lineno + b + :lineno + N + :loop + s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/ + t loop + s/-\n.*// + ' >$as_me.lineno && + chmod +x "$as_me.lineno" || + { $as_echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2; as_fn_exit 1; } + + # If we had to re-execute with $CONFIG_SHELL, we're ensured to have + # already done that, so ensure we don't try to do so again and fall + # in an infinite loop. This has already happened in practice. + _as_can_reexec=no; export _as_can_reexec + # Don't try to exec as it changes $[0], causing all sort of problems + # (the dirname of $[0] is not the place where we might find the + # original and so on. Autoconf is especially sensitive to this). + . "./$as_me.lineno" + # Exit status is that of the last command. + exit +} + +ECHO_C= ECHO_N= ECHO_T= +case `echo -n x` in #((((( +-n*) + case `echo 'xy\c'` in + *c*) ECHO_T=' ';; # ECHO_T is single tab character. + xy) ECHO_C='\c';; + *) echo `echo ksh88 bug on AIX 6.1` > /dev/null + ECHO_T=' ';; + esac;; +*) + ECHO_N='-n';; +esac + +rm -f conf$$ conf$$.exe conf$$.file +if test -d conf$$.dir; then + rm -f conf$$.dir/conf$$.file +else + rm -f conf$$.dir + mkdir conf$$.dir 2>/dev/null +fi +if (echo >conf$$.file) 2>/dev/null; then + if ln -s conf$$.file conf$$ 2>/dev/null; then + as_ln_s='ln -s' + # ... but there are two gotchas: + # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. + # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. + # In both cases, we have to default to `cp -pR'. + ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || + as_ln_s='cp -pR' + elif ln conf$$.file conf$$ 2>/dev/null; then + as_ln_s=ln + else + as_ln_s='cp -pR' + fi +else + as_ln_s='cp -pR' +fi +rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file +rmdir conf$$.dir 2>/dev/null + +if mkdir -p . 2>/dev/null; then + as_mkdir_p='mkdir -p "$as_dir"' +else + test -d ./-p && rmdir ./-p + as_mkdir_p=false +fi + +as_test_x='test -x' +as_executable_p=as_fn_executable_p + +# Sed expression to map a string onto a valid CPP name. +as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" + +# Sed expression to map a string onto a valid variable name. +as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" + + +test -n "$DJDIR" || exec 7<&0 &1 + +# Name of the host. +# hostname on some systems (SVR3.2, old GNU/Linux) returns a bogus exit status, +# so uname gets run too. +ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q` + +# +# Initializations. +# +ac_default_prefix=/usr/local +ac_clean_files= +ac_config_libobj_dir=. +LIBOBJS= +cross_compiling=no +subdirs= +MFLAGS= +MAKEFLAGS= + +# Identity of this package. +PACKAGE_NAME='Xar' +PACKAGE_TARNAME='xar' +PACKAGE_VERSION='1.8dev' +PACKAGE_STRING='Xar 1.8dev' +PACKAGE_BUGREPORT='xar-devel@googlegroups.com' +PACKAGE_URL='' + +ac_unique_file="LICENSE" +# Factoring default headers for most tests. +ac_includes_default="\ +#include +#ifdef HAVE_SYS_TYPES_H +# include +#endif +#ifdef HAVE_SYS_STAT_H +# include +#endif +#ifdef STDC_HEADERS +# include +# include +#else +# ifdef HAVE_STDLIB_H +# include +# endif +#endif +#ifdef HAVE_STRING_H +# if !defined STDC_HEADERS && defined HAVE_MEMORY_H +# include +# endif +# include +#endif +#ifdef HAVE_STRINGS_H +# include +#endif +#ifdef HAVE_INTTYPES_H +# include +#endif +#ifdef HAVE_STDINT_H +# include +#endif +#ifdef HAVE_UNISTD_H +# include +#endif" + +ac_default_prefix=/usr/local +ac_subst_vars='LTLIBOBJS +LIBOBJS +cfgoutputs +cfghdrs +XML2_CONFIG +EGREP +GREP +enable_autogen +RPATH +abi +host_os +host_vendor +host_cpu +host +build_os +build_vendor +build_cpu +build +static +shared +AUTOCONF +RANLIB +AR +LD +INSTALL_DATA +INSTALL_SCRIPT +INSTALL_PROGRAM +CPP +OBJEXT +EXEEXT +ac_ct_CC +CPPFLAGS +LDFLAGS +CFLAGS +CC +MANDIR +INCLUDEDIR +LIBDIR +DATADIR +BINDIR +PREFIX +abs_objroot +objroot +abs_srcroot +srcroot +XAR_VERSION +XAR_MINOR_VERSION +XAR_MAJOR_VERSION +LIB_REV +target_alias +host_alias +build_alias +LIBS +ECHO_T +ECHO_N +ECHO_C +DEFS +mandir +localedir +libdir +psdir +pdfdir +dvidir +htmldir +infodir +docdir +oldincludedir +includedir +localstatedir +sharedstatedir +sysconfdir +datadir +datarootdir +libexecdir +sbindir +bindir +program_transform_name +prefix +exec_prefix +PACKAGE_URL +PACKAGE_BUGREPORT +PACKAGE_STRING +PACKAGE_VERSION +PACKAGE_TARNAME +PACKAGE_NAME +PATH_SEPARATOR +SHELL' +ac_subst_files='' +ac_user_opts=' +enable_option_checking +enable_largefile +enable_shared +enable_static +enable_autogen +with_xml2_config +' + ac_precious_vars='build_alias +host_alias +target_alias +CC +CFLAGS +LDFLAGS +LIBS +CPPFLAGS +CPP' + + +# Initialize some variables set by options. +ac_init_help= +ac_init_version=false +ac_unrecognized_opts= +ac_unrecognized_sep= +# The variables have the same names as the options, with +# dashes changed to underlines. +cache_file=/dev/null +exec_prefix=NONE +no_create= +no_recursion= +prefix=NONE +program_prefix=NONE +program_suffix=NONE +program_transform_name=s,x,x, +silent= +site= +srcdir= +verbose= +x_includes=NONE +x_libraries=NONE + +# Installation directory options. +# These are left unexpanded so users can "make install exec_prefix=/foo" +# and all the variables that are supposed to be based on exec_prefix +# by default will actually change. +# Use braces instead of parens because sh, perl, etc. also accept them. +# (The list follows the same order as the GNU Coding Standards.) +bindir='${exec_prefix}/bin' +sbindir='${exec_prefix}/sbin' +libexecdir='${exec_prefix}/libexec' +datarootdir='${prefix}/share' +datadir='${datarootdir}' +sysconfdir='${prefix}/etc' +sharedstatedir='${prefix}/com' +localstatedir='${prefix}/var' +includedir='${prefix}/include' +oldincludedir='/usr/include' +docdir='${datarootdir}/doc/${PACKAGE_TARNAME}' +infodir='${datarootdir}/info' +htmldir='${docdir}' +dvidir='${docdir}' +pdfdir='${docdir}' +psdir='${docdir}' +libdir='${exec_prefix}/lib' +localedir='${datarootdir}/locale' +mandir='${datarootdir}/man' + +ac_prev= +ac_dashdash= +for ac_option +do + # If the previous option needs an argument, assign it. + if test -n "$ac_prev"; then + eval $ac_prev=\$ac_option + ac_prev= + continue + fi + + case $ac_option in + *=?*) ac_optarg=`expr "X$ac_option" : '[^=]*=\(.*\)'` ;; + *=) ac_optarg= ;; + *) ac_optarg=yes ;; + esac + + # Accept the important Cygnus configure options, so we can diagnose typos. + + case $ac_dashdash$ac_option in + --) + ac_dashdash=yes ;; + + -bindir | --bindir | --bindi | --bind | --bin | --bi) + ac_prev=bindir ;; + -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*) + bindir=$ac_optarg ;; + + -build | --build | --buil | --bui | --bu) + ac_prev=build_alias ;; + -build=* | --build=* | --buil=* | --bui=* | --bu=*) + build_alias=$ac_optarg ;; + + -cache-file | --cache-file | --cache-fil | --cache-fi \ + | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c) + ac_prev=cache_file ;; + -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \ + | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*) + cache_file=$ac_optarg ;; + + --config-cache | -C) + cache_file=config.cache ;; + + -datadir | --datadir | --datadi | --datad) + ac_prev=datadir ;; + -datadir=* | --datadir=* | --datadi=* | --datad=*) + datadir=$ac_optarg ;; + + -datarootdir | --datarootdir | --datarootdi | --datarootd | --dataroot \ + | --dataroo | --dataro | --datar) + ac_prev=datarootdir ;; + -datarootdir=* | --datarootdir=* | --datarootdi=* | --datarootd=* \ + | --dataroot=* | --dataroo=* | --dataro=* | --datar=*) + datarootdir=$ac_optarg ;; + + -disable-* | --disable-*) + ac_useropt=`expr "x$ac_option" : 'x-*disable-\(.*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && + as_fn_error $? "invalid feature name: $ac_useropt" + ac_useropt_orig=$ac_useropt + ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` + case $ac_user_opts in + *" +"enable_$ac_useropt" +"*) ;; + *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--disable-$ac_useropt_orig" + ac_unrecognized_sep=', ';; + esac + eval enable_$ac_useropt=no ;; + + -docdir | --docdir | --docdi | --doc | --do) + ac_prev=docdir ;; + -docdir=* | --docdir=* | --docdi=* | --doc=* | --do=*) + docdir=$ac_optarg ;; + + -dvidir | --dvidir | --dvidi | --dvid | --dvi | --dv) + ac_prev=dvidir ;; + -dvidir=* | --dvidir=* | --dvidi=* | --dvid=* | --dvi=* | --dv=*) + dvidir=$ac_optarg ;; + + -enable-* | --enable-*) + ac_useropt=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && + as_fn_error $? "invalid feature name: $ac_useropt" + ac_useropt_orig=$ac_useropt + ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` + case $ac_user_opts in + *" +"enable_$ac_useropt" +"*) ;; + *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--enable-$ac_useropt_orig" + ac_unrecognized_sep=', ';; + esac + eval enable_$ac_useropt=\$ac_optarg ;; + + -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \ + | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \ + | --exec | --exe | --ex) + ac_prev=exec_prefix ;; + -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \ + | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \ + | --exec=* | --exe=* | --ex=*) + exec_prefix=$ac_optarg ;; + + -gas | --gas | --ga | --g) + # Obsolete; use --with-gas. + with_gas=yes ;; + + -help | --help | --hel | --he | -h) + ac_init_help=long ;; + -help=r* | --help=r* | --hel=r* | --he=r* | -hr*) + ac_init_help=recursive ;; + -help=s* | --help=s* | --hel=s* | --he=s* | -hs*) + ac_init_help=short ;; + + -host | --host | --hos | --ho) + ac_prev=host_alias ;; + -host=* | --host=* | --hos=* | --ho=*) + host_alias=$ac_optarg ;; + + -htmldir | --htmldir | --htmldi | --htmld | --html | --htm | --ht) + ac_prev=htmldir ;; + -htmldir=* | --htmldir=* | --htmldi=* | --htmld=* | --html=* | --htm=* \ + | --ht=*) + htmldir=$ac_optarg ;; + + -includedir | --includedir | --includedi | --included | --include \ + | --includ | --inclu | --incl | --inc) + ac_prev=includedir ;; + -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \ + | --includ=* | --inclu=* | --incl=* | --inc=*) + includedir=$ac_optarg ;; + + -infodir | --infodir | --infodi | --infod | --info | --inf) + ac_prev=infodir ;; + -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*) + infodir=$ac_optarg ;; + + -libdir | --libdir | --libdi | --libd) + ac_prev=libdir ;; + -libdir=* | --libdir=* | --libdi=* | --libd=*) + libdir=$ac_optarg ;; + + -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \ + | --libexe | --libex | --libe) + ac_prev=libexecdir ;; + -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \ + | --libexe=* | --libex=* | --libe=*) + libexecdir=$ac_optarg ;; + + -localedir | --localedir | --localedi | --localed | --locale) + ac_prev=localedir ;; + -localedir=* | --localedir=* | --localedi=* | --localed=* | --locale=*) + localedir=$ac_optarg ;; + + -localstatedir | --localstatedir | --localstatedi | --localstated \ + | --localstate | --localstat | --localsta | --localst | --locals) + ac_prev=localstatedir ;; + -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \ + | --localstate=* | --localstat=* | --localsta=* | --localst=* | --locals=*) + localstatedir=$ac_optarg ;; + + -mandir | --mandir | --mandi | --mand | --man | --ma | --m) + ac_prev=mandir ;; + -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*) + mandir=$ac_optarg ;; + + -nfp | --nfp | --nf) + # Obsolete; use --without-fp. + with_fp=no ;; + + -no-create | --no-create | --no-creat | --no-crea | --no-cre \ + | --no-cr | --no-c | -n) + no_create=yes ;; + + -no-recursion | --no-recursion | --no-recursio | --no-recursi \ + | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) + no_recursion=yes ;; + + -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \ + | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \ + | --oldin | --oldi | --old | --ol | --o) + ac_prev=oldincludedir ;; + -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \ + | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \ + | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*) + oldincludedir=$ac_optarg ;; + + -prefix | --prefix | --prefi | --pref | --pre | --pr | --p) + ac_prev=prefix ;; + -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*) + prefix=$ac_optarg ;; + + -program-prefix | --program-prefix | --program-prefi | --program-pref \ + | --program-pre | --program-pr | --program-p) + ac_prev=program_prefix ;; + -program-prefix=* | --program-prefix=* | --program-prefi=* \ + | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*) + program_prefix=$ac_optarg ;; + + -program-suffix | --program-suffix | --program-suffi | --program-suff \ + | --program-suf | --program-su | --program-s) + ac_prev=program_suffix ;; + -program-suffix=* | --program-suffix=* | --program-suffi=* \ + | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*) + program_suffix=$ac_optarg ;; + + -program-transform-name | --program-transform-name \ + | --program-transform-nam | --program-transform-na \ + | --program-transform-n | --program-transform- \ + | --program-transform | --program-transfor \ + | --program-transfo | --program-transf \ + | --program-trans | --program-tran \ + | --progr-tra | --program-tr | --program-t) + ac_prev=program_transform_name ;; + -program-transform-name=* | --program-transform-name=* \ + | --program-transform-nam=* | --program-transform-na=* \ + | --program-transform-n=* | --program-transform-=* \ + | --program-transform=* | --program-transfor=* \ + | --program-transfo=* | --program-transf=* \ + | --program-trans=* | --program-tran=* \ + | --progr-tra=* | --program-tr=* | --program-t=*) + program_transform_name=$ac_optarg ;; + + -pdfdir | --pdfdir | --pdfdi | --pdfd | --pdf | --pd) + ac_prev=pdfdir ;; + -pdfdir=* | --pdfdir=* | --pdfdi=* | --pdfd=* | --pdf=* | --pd=*) + pdfdir=$ac_optarg ;; + + -psdir | --psdir | --psdi | --psd | --ps) + ac_prev=psdir ;; + -psdir=* | --psdir=* | --psdi=* | --psd=* | --ps=*) + psdir=$ac_optarg ;; + + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil) + silent=yes ;; + + -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb) + ac_prev=sbindir ;; + -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \ + | --sbi=* | --sb=*) + sbindir=$ac_optarg ;; + + -sharedstatedir | --sharedstatedir | --sharedstatedi \ + | --sharedstated | --sharedstate | --sharedstat | --sharedsta \ + | --sharedst | --shareds | --shared | --share | --shar \ + | --sha | --sh) + ac_prev=sharedstatedir ;; + -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \ + | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \ + | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \ + | --sha=* | --sh=*) + sharedstatedir=$ac_optarg ;; + + -site | --site | --sit) + ac_prev=site ;; + -site=* | --site=* | --sit=*) + site=$ac_optarg ;; + + -srcdir | --srcdir | --srcdi | --srcd | --src | --sr) + ac_prev=srcdir ;; + -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*) + srcdir=$ac_optarg ;; + + -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \ + | --syscon | --sysco | --sysc | --sys | --sy) + ac_prev=sysconfdir ;; + -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \ + | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*) + sysconfdir=$ac_optarg ;; + + -target | --target | --targe | --targ | --tar | --ta | --t) + ac_prev=target_alias ;; + -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*) + target_alias=$ac_optarg ;; + + -v | -verbose | --verbose | --verbos | --verbo | --verb) + verbose=yes ;; + + -version | --version | --versio | --versi | --vers | -V) + ac_init_version=: ;; + + -with-* | --with-*) + ac_useropt=`expr "x$ac_option" : 'x-*with-\([^=]*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && + as_fn_error $? "invalid package name: $ac_useropt" + ac_useropt_orig=$ac_useropt + ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` + case $ac_user_opts in + *" +"with_$ac_useropt" +"*) ;; + *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--with-$ac_useropt_orig" + ac_unrecognized_sep=', ';; + esac + eval with_$ac_useropt=\$ac_optarg ;; + + -without-* | --without-*) + ac_useropt=`expr "x$ac_option" : 'x-*without-\(.*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && + as_fn_error $? "invalid package name: $ac_useropt" + ac_useropt_orig=$ac_useropt + ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` + case $ac_user_opts in + *" +"with_$ac_useropt" +"*) ;; + *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--without-$ac_useropt_orig" + ac_unrecognized_sep=', ';; + esac + eval with_$ac_useropt=no ;; + + --x) + # Obsolete; use --with-x. + with_x=yes ;; + + -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \ + | --x-incl | --x-inc | --x-in | --x-i) + ac_prev=x_includes ;; + -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \ + | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*) + x_includes=$ac_optarg ;; + + -x-libraries | --x-libraries | --x-librarie | --x-librari \ + | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l) + ac_prev=x_libraries ;; + -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \ + | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*) + x_libraries=$ac_optarg ;; + + -*) as_fn_error $? "unrecognized option: \`$ac_option' +Try \`$0 --help' for more information" + ;; + + *=*) + ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='` + # Reject names that are not valid shell variable names. + case $ac_envvar in #( + '' | [0-9]* | *[!_$as_cr_alnum]* ) + as_fn_error $? "invalid variable name: \`$ac_envvar'" ;; + esac + eval $ac_envvar=\$ac_optarg + export $ac_envvar ;; + + *) + # FIXME: should be removed in autoconf 3.0. + $as_echo "$as_me: WARNING: you should use --build, --host, --target" >&2 + expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null && + $as_echo "$as_me: WARNING: invalid host type: $ac_option" >&2 + : "${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option}" + ;; + + esac +done + +if test -n "$ac_prev"; then + ac_option=--`echo $ac_prev | sed 's/_/-/g'` + as_fn_error $? "missing argument to $ac_option" +fi + +if test -n "$ac_unrecognized_opts"; then + case $enable_option_checking in + no) ;; + fatal) as_fn_error $? "unrecognized options: $ac_unrecognized_opts" ;; + *) $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2 ;; + esac +fi + +# Check all directory arguments for consistency. +for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \ + datadir sysconfdir sharedstatedir localstatedir includedir \ + oldincludedir docdir infodir htmldir dvidir pdfdir psdir \ + libdir localedir mandir +do + eval ac_val=\$$ac_var + # Remove trailing slashes. + case $ac_val in + */ ) + ac_val=`expr "X$ac_val" : 'X\(.*[^/]\)' \| "X$ac_val" : 'X\(.*\)'` + eval $ac_var=\$ac_val;; + esac + # Be sure to have absolute directory names. + case $ac_val in + [\\/$]* | ?:[\\/]* ) continue;; + NONE | '' ) case $ac_var in *prefix ) continue;; esac;; + esac + as_fn_error $? "expected an absolute directory name for --$ac_var: $ac_val" +done + +# There might be people who depend on the old broken behavior: `$host' +# used to hold the argument of --host etc. +# FIXME: To remove some day. +build=$build_alias +host=$host_alias +target=$target_alias + +# FIXME: To remove some day. +if test "x$host_alias" != x; then + if test "x$build_alias" = x; then + cross_compiling=maybe + elif test "x$build_alias" != "x$host_alias"; then + cross_compiling=yes + fi +fi + +ac_tool_prefix= +test -n "$host_alias" && ac_tool_prefix=$host_alias- + +test "$silent" = yes && exec 6>/dev/null + + +ac_pwd=`pwd` && test -n "$ac_pwd" && +ac_ls_di=`ls -di .` && +ac_pwd_ls_di=`cd "$ac_pwd" && ls -di .` || + as_fn_error $? "working directory cannot be determined" +test "X$ac_ls_di" = "X$ac_pwd_ls_di" || + as_fn_error $? "pwd does not report name of working directory" + + +# Find the source files, if location was not specified. +if test -z "$srcdir"; then + ac_srcdir_defaulted=yes + # Try the directory containing this script, then the parent directory. + ac_confdir=`$as_dirname -- "$as_myself" || +$as_expr X"$as_myself" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$as_myself" : 'X\(//\)[^/]' \| \ + X"$as_myself" : 'X\(//\)$' \| \ + X"$as_myself" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$as_myself" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + srcdir=$ac_confdir + if test ! -r "$srcdir/$ac_unique_file"; then + srcdir=.. + fi +else + ac_srcdir_defaulted=no +fi +if test ! -r "$srcdir/$ac_unique_file"; then + test "$ac_srcdir_defaulted" = yes && srcdir="$ac_confdir or .." + as_fn_error $? "cannot find sources ($ac_unique_file) in $srcdir" +fi +ac_msg="sources are in $srcdir, but \`cd $srcdir' does not work" +ac_abs_confdir=`( + cd "$srcdir" && test -r "./$ac_unique_file" || as_fn_error $? "$ac_msg" + pwd)` +# When building in place, set srcdir=. +if test "$ac_abs_confdir" = "$ac_pwd"; then + srcdir=. +fi +# Remove unnecessary trailing slashes from srcdir. +# Double slashes in file names in object file debugging info +# mess up M-x gdb in Emacs. +case $srcdir in +*/) srcdir=`expr "X$srcdir" : 'X\(.*[^/]\)' \| "X$srcdir" : 'X\(.*\)'`;; +esac +for ac_var in $ac_precious_vars; do + eval ac_env_${ac_var}_set=\${${ac_var}+set} + eval ac_env_${ac_var}_value=\$${ac_var} + eval ac_cv_env_${ac_var}_set=\${${ac_var}+set} + eval ac_cv_env_${ac_var}_value=\$${ac_var} +done + +# +# Report the --help message. +# +if test "$ac_init_help" = "long"; then + # Omit some internal or obsolete options to make the list less imposing. + # This message is too long to be a string in the A/UX 3.1 sh. + cat <<_ACEOF +\`configure' configures Xar 1.8dev to adapt to many kinds of systems. + +Usage: $0 [OPTION]... [VAR=VALUE]... + +To assign environment variables (e.g., CC, CFLAGS...), specify them as +VAR=VALUE. See below for descriptions of some of the useful variables. + +Defaults for the options are specified in brackets. + +Configuration: + -h, --help display this help and exit + --help=short display options specific to this package + --help=recursive display the short help of all the included packages + -V, --version display version information and exit + -q, --quiet, --silent do not print \`checking ...' messages + --cache-file=FILE cache test results in FILE [disabled] + -C, --config-cache alias for \`--cache-file=config.cache' + -n, --no-create do not create output files + --srcdir=DIR find the sources in DIR [configure dir or \`..'] + +Installation directories: + --prefix=PREFIX install architecture-independent files in PREFIX + [$ac_default_prefix] + --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX + [PREFIX] + +By default, \`make install' will install all the files in +\`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc. You can specify +an installation prefix other than \`$ac_default_prefix' using \`--prefix', +for instance \`--prefix=\$HOME'. + +For better control, use the options below. + +Fine tuning of the installation directories: + --bindir=DIR user executables [EPREFIX/bin] + --sbindir=DIR system admin executables [EPREFIX/sbin] + --libexecdir=DIR program executables [EPREFIX/libexec] + --sysconfdir=DIR read-only single-machine data [PREFIX/etc] + --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com] + --localstatedir=DIR modifiable single-machine data [PREFIX/var] + --libdir=DIR object code libraries [EPREFIX/lib] + --includedir=DIR C header files [PREFIX/include] + --oldincludedir=DIR C header files for non-gcc [/usr/include] + --datarootdir=DIR read-only arch.-independent data root [PREFIX/share] + --datadir=DIR read-only architecture-independent data [DATAROOTDIR] + --infodir=DIR info documentation [DATAROOTDIR/info] + --localedir=DIR locale-dependent data [DATAROOTDIR/locale] + --mandir=DIR man documentation [DATAROOTDIR/man] + --docdir=DIR documentation root [DATAROOTDIR/doc/xar] + --htmldir=DIR html documentation [DOCDIR] + --dvidir=DIR dvi documentation [DOCDIR] + --pdfdir=DIR pdf documentation [DOCDIR] + --psdir=DIR ps documentation [DOCDIR] +_ACEOF + + cat <<\_ACEOF + +System types: + --build=BUILD configure for building on BUILD [guessed] + --host=HOST cross-compile to build programs to run on HOST [BUILD] +_ACEOF +fi + +if test -n "$ac_init_help"; then + case $ac_init_help in + short | recursive ) echo "Configuration of Xar 1.8dev:";; + esac + cat <<\_ACEOF + +Optional Features: + --disable-option-checking ignore unrecognized --enable/--with options + --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no) + --enable-FEATURE[=ARG] include FEATURE [ARG=yes] + --disable-largefile omit support for large files + --enable-shared build shared libraries [default=yes] + --enable-static build static libraries [default=yes] + --enable-autogen Automatically regenerate configure output + +Optional Packages: + --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] + --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no) + --with-xml2-config libxml2 config program + +Some influential environment variables: + CC C compiler command + CFLAGS C compiler flags + LDFLAGS linker flags, e.g. -L if you have libraries in a + nonstandard directory + LIBS libraries to pass to the linker, e.g. -l + CPPFLAGS (Objective) C/C++ preprocessor flags, e.g. -I if + you have headers in a nonstandard directory + CPP C preprocessor + +Use these variables to override the choices made by `configure' or to help +it to find libraries and programs with nonstandard names/locations. + +Report bugs to . +_ACEOF +ac_status=$? +fi + +if test "$ac_init_help" = "recursive"; then + # If there are subdirs, report their specific --help. + for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue + test -d "$ac_dir" || + { cd "$srcdir" && ac_pwd=`pwd` && srcdir=. && test -d "$ac_dir"; } || + continue + ac_builddir=. + +case "$ac_dir" in +.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; +*) + ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'` + # A ".." for each directory in $ac_dir_suffix. + ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` + case $ac_top_builddir_sub in + "") ac_top_builddir_sub=. ac_top_build_prefix= ;; + *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; + esac ;; +esac +ac_abs_top_builddir=$ac_pwd +ac_abs_builddir=$ac_pwd$ac_dir_suffix +# for backward compatibility: +ac_top_builddir=$ac_top_build_prefix + +case $srcdir in + .) # We are building in place. + ac_srcdir=. + ac_top_srcdir=$ac_top_builddir_sub + ac_abs_top_srcdir=$ac_pwd ;; + [\\/]* | ?:[\\/]* ) # Absolute name. + ac_srcdir=$srcdir$ac_dir_suffix; + ac_top_srcdir=$srcdir + ac_abs_top_srcdir=$srcdir ;; + *) # Relative name. + ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix + ac_top_srcdir=$ac_top_build_prefix$srcdir + ac_abs_top_srcdir=$ac_pwd/$srcdir ;; +esac +ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix + + cd "$ac_dir" || { ac_status=$?; continue; } + # Check for guested configure. + if test -f "$ac_srcdir/configure.gnu"; then + echo && + $SHELL "$ac_srcdir/configure.gnu" --help=recursive + elif test -f "$ac_srcdir/configure"; then + echo && + $SHELL "$ac_srcdir/configure" --help=recursive + else + $as_echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2 + fi || ac_status=$? + cd "$ac_pwd" || { ac_status=$?; break; } + done +fi + +test -n "$ac_init_help" && exit $ac_status +if $ac_init_version; then + cat <<\_ACEOF +Xar configure 1.8dev +generated by GNU Autoconf 2.69 + +Copyright (C) 2012 Free Software Foundation, Inc. +This configure script is free software; the Free Software Foundation +gives unlimited permission to copy, distribute and modify it. +_ACEOF + exit +fi + +## ------------------------ ## +## Autoconf initialization. ## +## ------------------------ ## + +# ac_fn_c_try_compile LINENO +# -------------------------- +# Try to compile conftest.$ac_ext, and return whether this succeeded. +ac_fn_c_try_compile () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + rm -f conftest.$ac_objext + if { { ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_compile") 2>conftest.err + ac_status=$? + if test -s conftest.err; then + grep -v '^ *+' conftest.err >conftest.er1 + cat conftest.er1 >&5 + mv -f conftest.er1 conftest.err + fi + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then : + ac_retval=0 +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_retval=1 +fi + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + as_fn_set_status $ac_retval + +} # ac_fn_c_try_compile + +# ac_fn_c_try_cpp LINENO +# ---------------------- +# Try to preprocess conftest.$ac_ext, and return whether this succeeded. +ac_fn_c_try_cpp () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + if { { ac_try="$ac_cpp conftest.$ac_ext" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_cpp conftest.$ac_ext") 2>conftest.err + ac_status=$? + if test -s conftest.err; then + grep -v '^ *+' conftest.err >conftest.er1 + cat conftest.er1 >&5 + mv -f conftest.er1 conftest.err + fi + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } > conftest.i && { + test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || + test ! -s conftest.err + }; then : + ac_retval=0 +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_retval=1 +fi + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + as_fn_set_status $ac_retval + +} # ac_fn_c_try_cpp + +# ac_fn_c_check_header_mongrel LINENO HEADER VAR INCLUDES +# ------------------------------------------------------- +# Tests whether HEADER exists, giving a warning if it cannot be compiled using +# the include files in INCLUDES and setting the cache variable VAR +# accordingly. +ac_fn_c_check_header_mongrel () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + if eval \${$3+:} false; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 +$as_echo_n "checking for $2... " >&6; } +if eval \${$3+:} false; then : + $as_echo_n "(cached) " >&6 +fi +eval ac_res=\$$3 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } +else + # Is the header compilable? +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 usability" >&5 +$as_echo_n "checking $2 usability... " >&6; } +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$4 +#include <$2> +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_header_compiler=yes +else + ac_header_compiler=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_compiler" >&5 +$as_echo "$ac_header_compiler" >&6; } + +# Is the header present? +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 presence" >&5 +$as_echo_n "checking $2 presence... " >&6; } +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include <$2> +_ACEOF +if ac_fn_c_try_cpp "$LINENO"; then : + ac_header_preproc=yes +else + ac_header_preproc=no +fi +rm -f conftest.err conftest.i conftest.$ac_ext +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_preproc" >&5 +$as_echo "$ac_header_preproc" >&6; } + +# So? What about this header? +case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in #(( + yes:no: ) + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&5 +$as_echo "$as_me: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5 +$as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;} + ;; + no:yes:* ) + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: present but cannot be compiled" >&5 +$as_echo "$as_me: WARNING: $2: present but cannot be compiled" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: check for missing prerequisite headers?" >&5 +$as_echo "$as_me: WARNING: $2: check for missing prerequisite headers?" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: see the Autoconf documentation" >&5 +$as_echo "$as_me: WARNING: $2: see the Autoconf documentation" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&5 +$as_echo "$as_me: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5 +$as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;} +( $as_echo "## ----------------------------------------- ## +## Report this to xar-devel@googlegroups.com ## +## ----------------------------------------- ##" + ) | sed "s/^/$as_me: WARNING: /" >&2 + ;; +esac + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 +$as_echo_n "checking for $2... " >&6; } +if eval \${$3+:} false; then : + $as_echo_n "(cached) " >&6 +else + eval "$3=\$ac_header_compiler" +fi +eval ac_res=\$$3 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } +fi + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + +} # ac_fn_c_check_header_mongrel + +# ac_fn_c_try_run LINENO +# ---------------------- +# Try to link conftest.$ac_ext, and return whether this succeeded. Assumes +# that executables *can* be run. +ac_fn_c_try_run () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + if { { ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_link") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && { ac_try='./conftest$ac_exeext' + { { case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; }; then : + ac_retval=0 +else + $as_echo "$as_me: program exited with status $ac_status" >&5 + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_retval=$ac_status +fi + rm -rf conftest.dSYM conftest_ipa8_conftest.oo + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + as_fn_set_status $ac_retval + +} # ac_fn_c_try_run + +# ac_fn_c_check_header_compile LINENO HEADER VAR INCLUDES +# ------------------------------------------------------- +# Tests whether HEADER exists and can be compiled using the include files in +# INCLUDES, setting the cache variable VAR accordingly. +ac_fn_c_check_header_compile () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 +$as_echo_n "checking for $2... " >&6; } +if eval \${$3+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$4 +#include <$2> +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + eval "$3=yes" +else + eval "$3=no" +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +eval ac_res=\$$3 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + +} # ac_fn_c_check_header_compile + +# ac_fn_c_try_link LINENO +# ----------------------- +# Try to link conftest.$ac_ext, and return whether this succeeded. +ac_fn_c_try_link () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + rm -f conftest.$ac_objext conftest$ac_exeext + if { { ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_link") 2>conftest.err + ac_status=$? + if test -s conftest.err; then + grep -v '^ *+' conftest.err >conftest.er1 + cat conftest.er1 >&5 + mv -f conftest.er1 conftest.err + fi + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest$ac_exeext && { + test "$cross_compiling" = yes || + test -x conftest$ac_exeext + }; then : + ac_retval=0 +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_retval=1 +fi + # Delete the IPA/IPO (Inter Procedural Analysis/Optimization) information + # created by the PGI compiler (conftest_ipa8_conftest.oo), as it would + # interfere with the next link command; also delete a directory that is + # left behind by Apple's compiler. We do this before executing the actions. + rm -rf conftest.dSYM conftest_ipa8_conftest.oo + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + as_fn_set_status $ac_retval + +} # ac_fn_c_try_link + +# ac_fn_c_check_func LINENO FUNC VAR +# ---------------------------------- +# Tests whether FUNC exists, setting the cache variable VAR accordingly +ac_fn_c_check_func () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 +$as_echo_n "checking for $2... " >&6; } +if eval \${$3+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +/* Define $2 to an innocuous variant, in case declares $2. + For example, HP-UX 11i declares gettimeofday. */ +#define $2 innocuous_$2 + +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char $2 (); below. + Prefer to if __STDC__ is defined, since + exists even on freestanding compilers. */ + +#ifdef __STDC__ +# include +#else +# include +#endif + +#undef $2 + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char $2 (); +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined __stub_$2 || defined __stub___$2 +choke me +#endif + +int +main () +{ +return $2 (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + eval "$3=yes" +else + eval "$3=no" +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +fi +eval ac_res=\$$3 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + +} # ac_fn_c_check_func + +# ac_fn_c_check_member LINENO AGGR MEMBER VAR INCLUDES +# ---------------------------------------------------- +# Tries to find if the field MEMBER exists in type AGGR, after including +# INCLUDES, setting cache variable VAR accordingly. +ac_fn_c_check_member () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2.$3" >&5 +$as_echo_n "checking for $2.$3... " >&6; } +if eval \${$4+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$5 +int +main () +{ +static $2 ac_aggr; +if (ac_aggr.$3) +return 0; + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + eval "$4=yes" +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$5 +int +main () +{ +static $2 ac_aggr; +if (sizeof ac_aggr.$3) +return 0; + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + eval "$4=yes" +else + eval "$4=no" +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +eval ac_res=\$$4 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + +} # ac_fn_c_check_member + +# ac_fn_c_compute_int LINENO EXPR VAR INCLUDES +# -------------------------------------------- +# Tries to find the compile-time value of EXPR in a program that includes +# INCLUDES, setting VAR accordingly. Returns whether the value could be +# computed +ac_fn_c_compute_int () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + if test "$cross_compiling" = yes; then + # Depending upon the size, compute the lo and hi bounds. +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$4 +int +main () +{ +static int test_array [1 - 2 * !(($2) >= 0)]; +test_array [0] = 0; +return test_array [0]; + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_lo=0 ac_mid=0 + while :; do + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$4 +int +main () +{ +static int test_array [1 - 2 * !(($2) <= $ac_mid)]; +test_array [0] = 0; +return test_array [0]; + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_hi=$ac_mid; break +else + as_fn_arith $ac_mid + 1 && ac_lo=$as_val + if test $ac_lo -le $ac_mid; then + ac_lo= ac_hi= + break + fi + as_fn_arith 2 '*' $ac_mid + 1 && ac_mid=$as_val +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + done +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$4 +int +main () +{ +static int test_array [1 - 2 * !(($2) < 0)]; +test_array [0] = 0; +return test_array [0]; + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_hi=-1 ac_mid=-1 + while :; do + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$4 +int +main () +{ +static int test_array [1 - 2 * !(($2) >= $ac_mid)]; +test_array [0] = 0; +return test_array [0]; + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_lo=$ac_mid; break +else + as_fn_arith '(' $ac_mid ')' - 1 && ac_hi=$as_val + if test $ac_mid -le $ac_hi; then + ac_lo= ac_hi= + break + fi + as_fn_arith 2 '*' $ac_mid && ac_mid=$as_val +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + done +else + ac_lo= ac_hi= +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +# Binary search between lo and hi bounds. +while test "x$ac_lo" != "x$ac_hi"; do + as_fn_arith '(' $ac_hi - $ac_lo ')' / 2 + $ac_lo && ac_mid=$as_val + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$4 +int +main () +{ +static int test_array [1 - 2 * !(($2) <= $ac_mid)]; +test_array [0] = 0; +return test_array [0]; + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_hi=$ac_mid +else + as_fn_arith '(' $ac_mid ')' + 1 && ac_lo=$as_val +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +done +case $ac_lo in #(( +?*) eval "$3=\$ac_lo"; ac_retval=0 ;; +'') ac_retval=1 ;; +esac + else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$4 +static long int longval () { return $2; } +static unsigned long int ulongval () { return $2; } +#include +#include +int +main () +{ + + FILE *f = fopen ("conftest.val", "w"); + if (! f) + return 1; + if (($2) < 0) + { + long int i = longval (); + if (i != ($2)) + return 1; + fprintf (f, "%ld", i); + } + else + { + unsigned long int i = ulongval (); + if (i != ($2)) + return 1; + fprintf (f, "%lu", i); + } + /* Do not output a trailing newline, as this causes \r\n confusion + on some platforms. */ + return ferror (f) || fclose (f) != 0; + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_run "$LINENO"; then : + echo >>conftest.val; read $3 config.log <<_ACEOF +This file contains any messages produced by compilers while +running configure, to aid debugging if configure makes a mistake. + +It was created by Xar $as_me 1.8dev, which was +generated by GNU Autoconf 2.69. Invocation command line was + + $ $0 $@ + +_ACEOF +exec 5>>config.log +{ +cat <<_ASUNAME +## --------- ## +## Platform. ## +## --------- ## + +hostname = `(hostname || uname -n) 2>/dev/null | sed 1q` +uname -m = `(uname -m) 2>/dev/null || echo unknown` +uname -r = `(uname -r) 2>/dev/null || echo unknown` +uname -s = `(uname -s) 2>/dev/null || echo unknown` +uname -v = `(uname -v) 2>/dev/null || echo unknown` + +/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown` +/bin/uname -X = `(/bin/uname -X) 2>/dev/null || echo unknown` + +/bin/arch = `(/bin/arch) 2>/dev/null || echo unknown` +/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null || echo unknown` +/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown` +/usr/bin/hostinfo = `(/usr/bin/hostinfo) 2>/dev/null || echo unknown` +/bin/machine = `(/bin/machine) 2>/dev/null || echo unknown` +/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null || echo unknown` +/bin/universe = `(/bin/universe) 2>/dev/null || echo unknown` + +_ASUNAME + +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + $as_echo "PATH: $as_dir" + done +IFS=$as_save_IFS + +} >&5 + +cat >&5 <<_ACEOF + + +## ----------- ## +## Core tests. ## +## ----------- ## + +_ACEOF + + +# Keep a trace of the command line. +# Strip out --no-create and --no-recursion so they do not pile up. +# Strip out --silent because we don't want to record it for future runs. +# Also quote any args containing shell meta-characters. +# Make two passes to allow for proper duplicate-argument suppression. +ac_configure_args= +ac_configure_args0= +ac_configure_args1= +ac_must_keep_next=false +for ac_pass in 1 2 +do + for ac_arg + do + case $ac_arg in + -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;; + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil) + continue ;; + *\'*) + ac_arg=`$as_echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;; + esac + case $ac_pass in + 1) as_fn_append ac_configure_args0 " '$ac_arg'" ;; + 2) + as_fn_append ac_configure_args1 " '$ac_arg'" + if test $ac_must_keep_next = true; then + ac_must_keep_next=false # Got value, back to normal. + else + case $ac_arg in + *=* | --config-cache | -C | -disable-* | --disable-* \ + | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \ + | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \ + | -with-* | --with-* | -without-* | --without-* | --x) + case "$ac_configure_args0 " in + "$ac_configure_args1"*" '$ac_arg' "* ) continue ;; + esac + ;; + -* ) ac_must_keep_next=true ;; + esac + fi + as_fn_append ac_configure_args " '$ac_arg'" + ;; + esac + done +done +{ ac_configure_args0=; unset ac_configure_args0;} +{ ac_configure_args1=; unset ac_configure_args1;} + +# When interrupted or exit'd, cleanup temporary files, and complete +# config.log. We remove comments because anyway the quotes in there +# would cause problems or look ugly. +# WARNING: Use '\'' to represent an apostrophe within the trap. +# WARNING: Do not start the trap code with a newline, due to a FreeBSD 4.0 bug. +trap 'exit_status=$? + # Save into config.log some information that might help in debugging. + { + echo + + $as_echo "## ---------------- ## +## Cache variables. ## +## ---------------- ##" + echo + # The following way of writing the cache mishandles newlines in values, +( + for ac_var in `(set) 2>&1 | sed -n '\''s/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'\''`; do + eval ac_val=\$$ac_var + case $ac_val in #( + *${as_nl}*) + case $ac_var in #( + *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 +$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; + esac + case $ac_var in #( + _ | IFS | as_nl) ;; #( + BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( + *) { eval $ac_var=; unset $ac_var;} ;; + esac ;; + esac + done + (set) 2>&1 | + case $as_nl`(ac_space='\'' '\''; set) 2>&1` in #( + *${as_nl}ac_space=\ *) + sed -n \ + "s/'\''/'\''\\\\'\'''\''/g; + s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\''\\2'\''/p" + ;; #( + *) + sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" + ;; + esac | + sort +) + echo + + $as_echo "## ----------------- ## +## Output variables. ## +## ----------------- ##" + echo + for ac_var in $ac_subst_vars + do + eval ac_val=\$$ac_var + case $ac_val in + *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; + esac + $as_echo "$ac_var='\''$ac_val'\''" + done | sort + echo + + if test -n "$ac_subst_files"; then + $as_echo "## ------------------- ## +## File substitutions. ## +## ------------------- ##" + echo + for ac_var in $ac_subst_files + do + eval ac_val=\$$ac_var + case $ac_val in + *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; + esac + $as_echo "$ac_var='\''$ac_val'\''" + done | sort + echo + fi + + if test -s confdefs.h; then + $as_echo "## ----------- ## +## confdefs.h. ## +## ----------- ##" + echo + cat confdefs.h + echo + fi + test "$ac_signal" != 0 && + $as_echo "$as_me: caught signal $ac_signal" + $as_echo "$as_me: exit $exit_status" + } >&5 + rm -f core *.core core.conftest.* && + rm -f -r conftest* confdefs* conf$$* $ac_clean_files && + exit $exit_status +' 0 +for ac_signal in 1 2 13 15; do + trap 'ac_signal='$ac_signal'; as_fn_exit 1' $ac_signal +done +ac_signal=0 + +# confdefs.h avoids OS command line length limits that DEFS can exceed. +rm -f -r conftest* confdefs.h + +$as_echo "/* confdefs.h */" > confdefs.h + +# Predefined preprocessor variables. + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_NAME "$PACKAGE_NAME" +_ACEOF + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_TARNAME "$PACKAGE_TARNAME" +_ACEOF + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_VERSION "$PACKAGE_VERSION" +_ACEOF + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_STRING "$PACKAGE_STRING" +_ACEOF + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT" +_ACEOF + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_URL "$PACKAGE_URL" +_ACEOF + + +# Let the site file select an alternate cache file if it wants to. +# Prefer an explicitly selected file to automatically selected ones. +ac_site_file1=NONE +ac_site_file2=NONE +if test -n "$CONFIG_SITE"; then + # We do not want a PATH search for config.site. + case $CONFIG_SITE in #(( + -*) ac_site_file1=./$CONFIG_SITE;; + */*) ac_site_file1=$CONFIG_SITE;; + *) ac_site_file1=./$CONFIG_SITE;; + esac +elif test "x$prefix" != xNONE; then + ac_site_file1=$prefix/share/config.site + ac_site_file2=$prefix/etc/config.site +else + ac_site_file1=$ac_default_prefix/share/config.site + ac_site_file2=$ac_default_prefix/etc/config.site +fi +for ac_site_file in "$ac_site_file1" "$ac_site_file2" +do + test "x$ac_site_file" = xNONE && continue + if test /dev/null != "$ac_site_file" && test -r "$ac_site_file"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: loading site script $ac_site_file" >&5 +$as_echo "$as_me: loading site script $ac_site_file" >&6;} + sed 's/^/| /' "$ac_site_file" >&5 + . "$ac_site_file" \ + || { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "failed to load site script $ac_site_file +See \`config.log' for more details" "$LINENO" 5; } + fi +done + +if test -r "$cache_file"; then + # Some versions of bash will fail to source /dev/null (special files + # actually), so we avoid doing that. DJGPP emulates it as a regular file. + if test /dev/null != "$cache_file" && test -f "$cache_file"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: loading cache $cache_file" >&5 +$as_echo "$as_me: loading cache $cache_file" >&6;} + case $cache_file in + [\\/]* | ?:[\\/]* ) . "$cache_file";; + *) . "./$cache_file";; + esac + fi +else + { $as_echo "$as_me:${as_lineno-$LINENO}: creating cache $cache_file" >&5 +$as_echo "$as_me: creating cache $cache_file" >&6;} + >$cache_file +fi + +# Check that the precious variables saved in the cache have kept the same +# value. +ac_cache_corrupted=false +for ac_var in $ac_precious_vars; do + eval ac_old_set=\$ac_cv_env_${ac_var}_set + eval ac_new_set=\$ac_env_${ac_var}_set + eval ac_old_val=\$ac_cv_env_${ac_var}_value + eval ac_new_val=\$ac_env_${ac_var}_value + case $ac_old_set,$ac_new_set in + set,) + { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5 +$as_echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;} + ac_cache_corrupted=: ;; + ,set) + { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was not set in the previous run" >&5 +$as_echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;} + ac_cache_corrupted=: ;; + ,);; + *) + if test "x$ac_old_val" != "x$ac_new_val"; then + # differences in whitespace do not lead to failure. + ac_old_val_w=`echo x $ac_old_val` + ac_new_val_w=`echo x $ac_new_val` + if test "$ac_old_val_w" != "$ac_new_val_w"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' has changed since the previous run:" >&5 +$as_echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;} + ac_cache_corrupted=: + else + { $as_echo "$as_me:${as_lineno-$LINENO}: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&5 +$as_echo "$as_me: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&2;} + eval $ac_var=\$ac_old_val + fi + { $as_echo "$as_me:${as_lineno-$LINENO}: former value: \`$ac_old_val'" >&5 +$as_echo "$as_me: former value: \`$ac_old_val'" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: current value: \`$ac_new_val'" >&5 +$as_echo "$as_me: current value: \`$ac_new_val'" >&2;} + fi;; + esac + # Pass precious variables to config.status. + if test "$ac_new_set" = set; then + case $ac_new_val in + *\'*) ac_arg=$ac_var=`$as_echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;; + *) ac_arg=$ac_var=$ac_new_val ;; + esac + case " $ac_configure_args " in + *" '$ac_arg' "*) ;; # Avoid dups. Use of quotes ensures accuracy. + *) as_fn_append ac_configure_args " '$ac_arg'" ;; + esac + fi +done +if $ac_cache_corrupted; then + { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: error: changes in the environment can compromise the build" >&5 +$as_echo "$as_me: error: changes in the environment can compromise the build" >&2;} + as_fn_error $? "run \`make distclean' and/or \`rm $cache_file' and start over" "$LINENO" 5 +fi +## -------------------- ## +## Main body of script. ## +## -------------------- ## + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + + + +LIB_REV=1 + + +XAR_MAJOR_VERSION="1" +XAR_MINOR_VERSION="8dev" +XAR_VERSION="${XAR_MAJOR_VERSION}.${XAR_MINOR_VERSION}" + + + + +srcroot=$srcdir +if test "x${srcroot}" = "x." ; then + srcroot="" +else + srcroot="${srcroot}/" +fi + +abs_srcroot="`cd "$srcdir"; pwd`/" + + +objroot="" + +abs_objroot="`pwd`/" + + +if test "x$prefix" = "xNONE" ; then + prefix="/usr/local" +fi +if test "x$exec_prefix" = "xNONE" ; then + exec_prefix=$prefix +fi +PREFIX=$prefix + +BINDIR=`eval echo $bindir` +BINDIR=`eval echo $BINDIR` + +DATADIR=`eval echo $datadir` +DATADIR=`eval echo $DATADIR` + +LIBDIR=`eval echo $libdir` +LIBDIR=`eval echo $LIBDIR` + +INCLUDEDIR=`eval echo $includedir` +INCLUDEDIR=`eval echo $INCLUDEDIR` + +MANDIR=`eval echo $mandir` +MANDIR=`eval echo $MANDIR` + + +cfgoutputs="cfgoutputs.stamp" +cfgoutputs="${cfgoutputs} Makefile" +cfgoutputs="${cfgoutputs} include/xar.h" +cfgoutputs="${cfgoutputs} lib/Makefile.inc" +cfgoutputs="${cfgoutputs} lib/libxar.la.in" +cfgoutputs="${cfgoutputs} src/Makefile.inc" +cfgoutputs="${cfgoutputs} xar.spec" + +cfghdrs="${objroot}cfghdrs.stamp" +cfghdrs="${cfghdrs} ${objroot}include/config.h" + +CFLAGS=$CFLAGS +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu +if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args. +set dummy ${ac_tool_prefix}gcc; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_CC="${ac_tool_prefix}gcc" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 +$as_echo "$CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_CC"; then + ac_ct_CC=$CC + # Extract the first word of "gcc", so it can be a program name with args. +set dummy gcc; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_CC"; then + ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_CC="gcc" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_CC=$ac_cv_prog_ac_ct_CC +if test -n "$ac_ct_CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 +$as_echo "$ac_ct_CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_CC" = x; then + CC="" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + CC=$ac_ct_CC + fi +else + CC="$ac_cv_prog_CC" +fi + +if test -z "$CC"; then + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args. +set dummy ${ac_tool_prefix}cc; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_CC="${ac_tool_prefix}cc" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 +$as_echo "$CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + fi +fi +if test -z "$CC"; then + # Extract the first word of "cc", so it can be a program name with args. +set dummy cc; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else + ac_prog_rejected=no +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then + ac_prog_rejected=yes + continue + fi + ac_cv_prog_CC="cc" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +if test $ac_prog_rejected = yes; then + # We found a bogon in the path, so make sure we never use it. + set dummy $ac_cv_prog_CC + shift + if test $# != 0; then + # We chose a different compiler from the bogus one. + # However, it has the same basename, so the bogon will be chosen + # first if we set CC to just the basename; use the full file name. + shift + ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@" + fi +fi +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 +$as_echo "$CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$CC"; then + if test -n "$ac_tool_prefix"; then + for ac_prog in cl.exe + do + # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. +set dummy $ac_tool_prefix$ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_CC="$ac_tool_prefix$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 +$as_echo "$CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$CC" && break + done +fi +if test -z "$CC"; then + ac_ct_CC=$CC + for ac_prog in cl.exe +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_CC"; then + ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_CC="$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_CC=$ac_cv_prog_ac_ct_CC +if test -n "$ac_ct_CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 +$as_echo "$ac_ct_CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$ac_ct_CC" && break +done + + if test "x$ac_ct_CC" = x; then + CC="" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + CC=$ac_ct_CC + fi +fi + +fi + + +test -z "$CC" && { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "no acceptable C compiler found in \$PATH +See \`config.log' for more details" "$LINENO" 5; } + +# Provide some information about the compiler. +$as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5 +set X $ac_compile +ac_compiler=$2 +for ac_option in --version -v -V -qversion; do + { { ac_try="$ac_compiler $ac_option >&5" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_compiler $ac_option >&5") 2>conftest.err + ac_status=$? + if test -s conftest.err; then + sed '10a\ +... rest of stderr output deleted ... + 10q' conftest.err >conftest.er1 + cat conftest.er1 >&5 + fi + rm -f conftest.er1 conftest.err + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } +done + +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +ac_clean_files_save=$ac_clean_files +ac_clean_files="$ac_clean_files a.out a.out.dSYM a.exe b.out" +# Try to create an executable without -o first, disregard a.out. +# It will help us diagnose broken compilers, and finding out an intuition +# of exeext. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the C compiler works" >&5 +$as_echo_n "checking whether the C compiler works... " >&6; } +ac_link_default=`$as_echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'` + +# The possible output files: +ac_files="a.out conftest.exe conftest a.exe a_out.exe b.out conftest.*" + +ac_rmfiles= +for ac_file in $ac_files +do + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; + * ) ac_rmfiles="$ac_rmfiles $ac_file";; + esac +done +rm -f $ac_rmfiles + +if { { ac_try="$ac_link_default" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_link_default") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then : + # Autoconf-2.13 could set the ac_cv_exeext variable to `no'. +# So ignore a value of `no', otherwise this would lead to `EXEEXT = no' +# in a Makefile. We should not override ac_cv_exeext if it was cached, +# so that the user can short-circuit this test for compilers unknown to +# Autoconf. +for ac_file in $ac_files '' +do + test -f "$ac_file" || continue + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) + ;; + [ab].out ) + # We found the default executable, but exeext='' is most + # certainly right. + break;; + *.* ) + if test "${ac_cv_exeext+set}" = set && test "$ac_cv_exeext" != no; + then :; else + ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` + fi + # We set ac_cv_exeext here because the later test for it is not + # safe: cross compilers may not add the suffix if given an `-o' + # argument, so we may need to know it at that point already. + # Even if this section looks crufty: it has the advantage of + # actually working. + break;; + * ) + break;; + esac +done +test "$ac_cv_exeext" = no && ac_cv_exeext= + +else + ac_file='' +fi +if test -z "$ac_file"; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +$as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error 77 "C compiler cannot create executables +See \`config.log' for more details" "$LINENO" 5; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler default output file name" >&5 +$as_echo_n "checking for C compiler default output file name... " >&6; } +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_file" >&5 +$as_echo "$ac_file" >&6; } +ac_exeext=$ac_cv_exeext + +rm -f -r a.out a.out.dSYM a.exe conftest$ac_cv_exeext b.out +ac_clean_files=$ac_clean_files_save +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of executables" >&5 +$as_echo_n "checking for suffix of executables... " >&6; } +if { { ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_link") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then : + # If both `conftest.exe' and `conftest' are `present' (well, observable) +# catch `conftest.exe'. For instance with Cygwin, `ls conftest' will +# work properly (i.e., refer to `conftest.exe'), while it won't with +# `rm'. +for ac_file in conftest.exe conftest conftest.*; do + test -f "$ac_file" || continue + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; + *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` + break;; + * ) break;; + esac +done +else + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "cannot compute suffix of executables: cannot compile and link +See \`config.log' for more details" "$LINENO" 5; } +fi +rm -f conftest conftest$ac_cv_exeext +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_exeext" >&5 +$as_echo "$ac_cv_exeext" >&6; } + +rm -f conftest.$ac_ext +EXEEXT=$ac_cv_exeext +ac_exeext=$EXEEXT +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +int +main () +{ +FILE *f = fopen ("conftest.out", "w"); + return ferror (f) || fclose (f) != 0; + + ; + return 0; +} +_ACEOF +ac_clean_files="$ac_clean_files conftest.out" +# Check that the compiler produces executables we can run. If not, either +# the compiler is broken, or we cross compile. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are cross compiling" >&5 +$as_echo_n "checking whether we are cross compiling... " >&6; } +if test "$cross_compiling" != yes; then + { { ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_link") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } + if { ac_try='./conftest$ac_cv_exeext' + { { case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; }; then + cross_compiling=no + else + if test "$cross_compiling" = maybe; then + cross_compiling=yes + else + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "cannot run C compiled programs. +If you meant to cross compile, use \`--host'. +See \`config.log' for more details" "$LINENO" 5; } + fi + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $cross_compiling" >&5 +$as_echo "$cross_compiling" >&6; } + +rm -f conftest.$ac_ext conftest$ac_cv_exeext conftest.out +ac_clean_files=$ac_clean_files_save +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of object files" >&5 +$as_echo_n "checking for suffix of object files... " >&6; } +if ${ac_cv_objext+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.o conftest.obj +if { { ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_compile") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then : + for ac_file in conftest.o conftest.obj conftest.*; do + test -f "$ac_file" || continue; + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM ) ;; + *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'` + break;; + esac +done +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "cannot compute suffix of object files: cannot compile +See \`config.log' for more details" "$LINENO" 5; } +fi +rm -f conftest.$ac_cv_objext conftest.$ac_ext +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_objext" >&5 +$as_echo "$ac_cv_objext" >&6; } +OBJEXT=$ac_cv_objext +ac_objext=$OBJEXT +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C compiler" >&5 +$as_echo_n "checking whether we are using the GNU C compiler... " >&6; } +if ${ac_cv_c_compiler_gnu+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ +#ifndef __GNUC__ + choke me +#endif + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_compiler_gnu=yes +else + ac_compiler_gnu=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +ac_cv_c_compiler_gnu=$ac_compiler_gnu + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu" >&5 +$as_echo "$ac_cv_c_compiler_gnu" >&6; } +if test $ac_compiler_gnu = yes; then + GCC=yes +else + GCC= +fi +ac_test_CFLAGS=${CFLAGS+set} +ac_save_CFLAGS=$CFLAGS +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5 +$as_echo_n "checking whether $CC accepts -g... " >&6; } +if ${ac_cv_prog_cc_g+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_save_c_werror_flag=$ac_c_werror_flag + ac_c_werror_flag=yes + ac_cv_prog_cc_g=no + CFLAGS="-g" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_prog_cc_g=yes +else + CFLAGS="" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + +else + ac_c_werror_flag=$ac_save_c_werror_flag + CFLAGS="-g" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_prog_cc_g=yes +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + ac_c_werror_flag=$ac_save_c_werror_flag +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_g" >&5 +$as_echo "$ac_cv_prog_cc_g" >&6; } +if test "$ac_test_CFLAGS" = set; then + CFLAGS=$ac_save_CFLAGS +elif test $ac_cv_prog_cc_g = yes; then + if test "$GCC" = yes; then + CFLAGS="-g -O2" + else + CFLAGS="-g" + fi +else + if test "$GCC" = yes; then + CFLAGS="-O2" + else + CFLAGS= + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C89" >&5 +$as_echo_n "checking for $CC option to accept ISO C89... " >&6; } +if ${ac_cv_prog_cc_c89+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_cv_prog_cc_c89=no +ac_save_CC=$CC +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +#include +struct stat; +/* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */ +struct buf { int x; }; +FILE * (*rcsopen) (struct buf *, struct stat *, int); +static char *e (p, i) + char **p; + int i; +{ + return p[i]; +} +static char *f (char * (*g) (char **, int), char **p, ...) +{ + char *s; + va_list v; + va_start (v,p); + s = g (p, va_arg (v,int)); + va_end (v); + return s; +} + +/* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has + function prototypes and stuff, but not '\xHH' hex character constants. + These don't provoke an error unfortunately, instead are silently treated + as 'x'. The following induces an error, until -std is added to get + proper ANSI mode. Curiously '\x00'!='x' always comes out true, for an + array size at least. It's necessary to write '\x00'==0 to get something + that's true only with -std. */ +int osf4_cc_array ['\x00' == 0 ? 1 : -1]; + +/* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters + inside strings and character constants. */ +#define FOO(x) 'x' +int xlc6_cc_array[FOO(a) == 'x' ? 1 : -1]; + +int test (int i, double x); +struct s1 {int (*f) (int a);}; +struct s2 {int (*f) (double a);}; +int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int); +int argc; +char **argv; +int +main () +{ +return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1]; + ; + return 0; +} +_ACEOF +for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \ + -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__" +do + CC="$ac_save_CC $ac_arg" + if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_prog_cc_c89=$ac_arg +fi +rm -f core conftest.err conftest.$ac_objext + test "x$ac_cv_prog_cc_c89" != "xno" && break +done +rm -f conftest.$ac_ext +CC=$ac_save_CC + +fi +# AC_CACHE_VAL +case "x$ac_cv_prog_cc_c89" in + x) + { $as_echo "$as_me:${as_lineno-$LINENO}: result: none needed" >&5 +$as_echo "none needed" >&6; } ;; + xno) + { $as_echo "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5 +$as_echo "unsupported" >&6; } ;; + *) + CC="$CC $ac_cv_prog_cc_c89" + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5 +$as_echo "$ac_cv_prog_cc_c89" >&6; } ;; +esac +if test "x$ac_cv_prog_cc_c89" != xno; then : + +fi + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + +# Check whether --enable-largefile was given. +if test "${enable_largefile+set}" = set; then : + enableval=$enable_largefile; +fi + +if test "$enable_largefile" != no; then + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for special C compiler options needed for large files" >&5 +$as_echo_n "checking for special C compiler options needed for large files... " >&6; } +if ${ac_cv_sys_largefile_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_cv_sys_largefile_CC=no + if test "$GCC" != yes; then + ac_save_CC=$CC + while :; do + # IRIX 6.2 and later do not support large files by default, + # so use the C compiler's -n32 option if that helps. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include + /* Check that off_t can represent 2**63 - 1 correctly. + We can't simply define LARGE_OFF_T to be 9223372036854775807, + since some C++ compilers masquerading as C compilers + incorrectly reject 9223372036854775807. */ +#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62)) + int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721 + && LARGE_OFF_T % 2147483647 == 1) + ? 1 : -1]; +int +main () +{ + + ; + return 0; +} +_ACEOF + if ac_fn_c_try_compile "$LINENO"; then : + break +fi +rm -f core conftest.err conftest.$ac_objext + CC="$CC -n32" + if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_sys_largefile_CC=' -n32'; break +fi +rm -f core conftest.err conftest.$ac_objext + break + done + CC=$ac_save_CC + rm -f conftest.$ac_ext + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sys_largefile_CC" >&5 +$as_echo "$ac_cv_sys_largefile_CC" >&6; } + if test "$ac_cv_sys_largefile_CC" != no; then + CC=$CC$ac_cv_sys_largefile_CC + fi + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for _FILE_OFFSET_BITS value needed for large files" >&5 +$as_echo_n "checking for _FILE_OFFSET_BITS value needed for large files... " >&6; } +if ${ac_cv_sys_file_offset_bits+:} false; then : + $as_echo_n "(cached) " >&6 +else + while :; do + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include + /* Check that off_t can represent 2**63 - 1 correctly. + We can't simply define LARGE_OFF_T to be 9223372036854775807, + since some C++ compilers masquerading as C compilers + incorrectly reject 9223372036854775807. */ +#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62)) + int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721 + && LARGE_OFF_T % 2147483647 == 1) + ? 1 : -1]; +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_sys_file_offset_bits=no; break +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#define _FILE_OFFSET_BITS 64 +#include + /* Check that off_t can represent 2**63 - 1 correctly. + We can't simply define LARGE_OFF_T to be 9223372036854775807, + since some C++ compilers masquerading as C compilers + incorrectly reject 9223372036854775807. */ +#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62)) + int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721 + && LARGE_OFF_T % 2147483647 == 1) + ? 1 : -1]; +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_sys_file_offset_bits=64; break +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + ac_cv_sys_file_offset_bits=unknown + break +done +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sys_file_offset_bits" >&5 +$as_echo "$ac_cv_sys_file_offset_bits" >&6; } +case $ac_cv_sys_file_offset_bits in #( + no | unknown) ;; + *) +cat >>confdefs.h <<_ACEOF +#define _FILE_OFFSET_BITS $ac_cv_sys_file_offset_bits +_ACEOF +;; +esac +rm -rf conftest* + if test $ac_cv_sys_file_offset_bits = unknown; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for _LARGE_FILES value needed for large files" >&5 +$as_echo_n "checking for _LARGE_FILES value needed for large files... " >&6; } +if ${ac_cv_sys_large_files+:} false; then : + $as_echo_n "(cached) " >&6 +else + while :; do + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include + /* Check that off_t can represent 2**63 - 1 correctly. + We can't simply define LARGE_OFF_T to be 9223372036854775807, + since some C++ compilers masquerading as C compilers + incorrectly reject 9223372036854775807. */ +#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62)) + int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721 + && LARGE_OFF_T % 2147483647 == 1) + ? 1 : -1]; +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_sys_large_files=no; break +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#define _LARGE_FILES 1 +#include + /* Check that off_t can represent 2**63 - 1 correctly. + We can't simply define LARGE_OFF_T to be 9223372036854775807, + since some C++ compilers masquerading as C compilers + incorrectly reject 9223372036854775807. */ +#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62)) + int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721 + && LARGE_OFF_T % 2147483647 == 1) + ? 1 : -1]; +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_sys_large_files=1; break +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + ac_cv_sys_large_files=unknown + break +done +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sys_large_files" >&5 +$as_echo "$ac_cv_sys_large_files" >&6; } +case $ac_cv_sys_large_files in #( + no | unknown) ;; + *) +cat >>confdefs.h <<_ACEOF +#define _LARGE_FILES $ac_cv_sys_large_files +_ACEOF +;; +esac +rm -rf conftest* + fi + + +fi + +if test "x$CFLAGS" = "x" ; then + no_CFLAGS="yes" +fi +if test "x$no_CFLAGS" = "xyes" -a "x$GCC" = "xyes" ; then + CFLAGS="-Wall -g" +fi +if test "x$EXTRA_CFLAGS" != "x" ; then + CFLAGS="$CFLAGS $EXTRA_CFLAGS" +fi +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to run the C preprocessor" >&5 +$as_echo_n "checking how to run the C preprocessor... " >&6; } +# On Suns, sometimes $CPP names a directory. +if test -n "$CPP" && test -d "$CPP"; then + CPP= +fi +if test -z "$CPP"; then + if ${ac_cv_prog_CPP+:} false; then : + $as_echo_n "(cached) " >&6 +else + # Double quotes because CPP needs to be expanded + for CPP in "$CC -E" "$CC -E -traditional-cpp" "/lib/cpp" + do + ac_preproc_ok=false +for ac_c_preproc_warn_flag in '' yes +do + # Use a header file that comes with gcc, so configuring glibc + # with a fresh cross-compiler works. + # Prefer to if __STDC__ is defined, since + # exists even on freestanding compilers. + # On the NeXT, cc -E runs the code through the compiler's parser, + # not just through cpp. "Syntax error" is here to catch this case. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#ifdef __STDC__ +# include +#else +# include +#endif + Syntax error +_ACEOF +if ac_fn_c_try_cpp "$LINENO"; then : + +else + # Broken: fails on valid input. +continue +fi +rm -f conftest.err conftest.i conftest.$ac_ext + + # OK, works on sane cases. Now check whether nonexistent headers + # can be detected and how. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +_ACEOF +if ac_fn_c_try_cpp "$LINENO"; then : + # Broken: success on invalid input. +continue +else + # Passes both tests. +ac_preproc_ok=: +break +fi +rm -f conftest.err conftest.i conftest.$ac_ext + +done +# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. +rm -f conftest.i conftest.err conftest.$ac_ext +if $ac_preproc_ok; then : + break +fi + + done + ac_cv_prog_CPP=$CPP + +fi + CPP=$ac_cv_prog_CPP +else + ac_cv_prog_CPP=$CPP +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $CPP" >&5 +$as_echo "$CPP" >&6; } +ac_preproc_ok=false +for ac_c_preproc_warn_flag in '' yes +do + # Use a header file that comes with gcc, so configuring glibc + # with a fresh cross-compiler works. + # Prefer to if __STDC__ is defined, since + # exists even on freestanding compilers. + # On the NeXT, cc -E runs the code through the compiler's parser, + # not just through cpp. "Syntax error" is here to catch this case. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#ifdef __STDC__ +# include +#else +# include +#endif + Syntax error +_ACEOF +if ac_fn_c_try_cpp "$LINENO"; then : + +else + # Broken: fails on valid input. +continue +fi +rm -f conftest.err conftest.i conftest.$ac_ext + + # OK, works on sane cases. Now check whether nonexistent headers + # can be detected and how. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +_ACEOF +if ac_fn_c_try_cpp "$LINENO"; then : + # Broken: success on invalid input. +continue +else + # Passes both tests. +ac_preproc_ok=: +break +fi +rm -f conftest.err conftest.i conftest.$ac_ext + +done +# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. +rm -f conftest.i conftest.err conftest.$ac_ext +if $ac_preproc_ok; then : + +else + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "C preprocessor \"$CPP\" fails sanity check +See \`config.log' for more details" "$LINENO" 5; } +fi + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + +ac_aux_dir= +for ac_dir in "$srcdir" "$srcdir/.." "$srcdir/../.."; do + if test -f "$ac_dir/install-sh"; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/install-sh -c" + break + elif test -f "$ac_dir/install.sh"; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/install.sh -c" + break + elif test -f "$ac_dir/shtool"; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/shtool install -c" + break + fi +done +if test -z "$ac_aux_dir"; then + as_fn_error $? "cannot find install-sh, install.sh, or shtool in \"$srcdir\" \"$srcdir/..\" \"$srcdir/../..\"" "$LINENO" 5 +fi + +# These three variables are undocumented and unsupported, +# and are intended to be withdrawn in a future Autoconf release. +# They can cause serious problems if a builder's source tree is in a directory +# whose full name contains unusual characters. +ac_config_guess="$SHELL $ac_aux_dir/config.guess" # Please don't use this var. +ac_config_sub="$SHELL $ac_aux_dir/config.sub" # Please don't use this var. +ac_configure="$SHELL $ac_aux_dir/configure" # Please don't use this var. + + +# Find a good install program. We prefer a C program (faster), +# so one script is as good as another. But avoid the broken or +# incompatible versions: +# SysV /etc/install, /usr/sbin/install +# SunOS /usr/etc/install +# IRIX /sbin/install +# AIX /bin/install +# AmigaOS /C/install, which installs bootblocks on floppy discs +# AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag +# AFS /usr/afsws/bin/install, which mishandles nonexistent args +# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff" +# OS/2's system install, which has a completely different semantic +# ./install, which can be erroneously created by make from ./install.sh. +# Reject install programs that cannot install multiple files. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for a BSD-compatible install" >&5 +$as_echo_n "checking for a BSD-compatible install... " >&6; } +if test -z "$INSTALL"; then +if ${ac_cv_path_install+:} false; then : + $as_echo_n "(cached) " >&6 +else + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + # Account for people who put trailing slashes in PATH elements. +case $as_dir/ in #(( + ./ | .// | /[cC]/* | \ + /etc/* | /usr/sbin/* | /usr/etc/* | /sbin/* | /usr/afsws/bin/* | \ + ?:[\\/]os2[\\/]install[\\/]* | ?:[\\/]OS2[\\/]INSTALL[\\/]* | \ + /usr/ucb/* ) ;; + *) + # OSF1 and SCO ODT 3.0 have their own names for install. + # Don't use installbsd from OSF since it installs stuff as root + # by default. + for ac_prog in ginstall scoinst install; do + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_prog$ac_exec_ext"; then + if test $ac_prog = install && + grep dspmsg "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then + # AIX install. It has an incompatible calling convention. + : + elif test $ac_prog = install && + grep pwplus "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then + # program-specific install script used by HP pwplus--don't use. + : + else + rm -rf conftest.one conftest.two conftest.dir + echo one > conftest.one + echo two > conftest.two + mkdir conftest.dir + if "$as_dir/$ac_prog$ac_exec_ext" -c conftest.one conftest.two "`pwd`/conftest.dir" && + test -s conftest.one && test -s conftest.two && + test -s conftest.dir/conftest.one && + test -s conftest.dir/conftest.two + then + ac_cv_path_install="$as_dir/$ac_prog$ac_exec_ext -c" + break 3 + fi + fi + fi + done + done + ;; +esac + + done +IFS=$as_save_IFS + +rm -rf conftest.one conftest.two conftest.dir + +fi + if test "${ac_cv_path_install+set}" = set; then + INSTALL=$ac_cv_path_install + else + # As a last resort, use the slow shell script. Don't cache a + # value for INSTALL within a source directory, because that will + # break other packages using the cache if that directory is + # removed, or if the value is a relative name. + INSTALL=$ac_install_sh + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $INSTALL" >&5 +$as_echo "$INSTALL" >&6; } + +# Use test -z because SunOS4 sh mishandles braces in ${var-val}. +# It thinks the first close brace ends the variable substitution. +test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}' + +test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL}' + +test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644' + +# Extract the first word of "ld", so it can be a program name with args. +set dummy ld; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_path_LD+:} false; then : + $as_echo_n "(cached) " >&6 +else + case $LD in + [\\/]* | ?:[\\/]*) + ac_cv_path_LD="$LD" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_path_LD="$as_dir/$ac_word$ac_exec_ext" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + + ;; +esac +fi +LD=$ac_cv_path_LD +if test -n "$LD"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $LD" >&5 +$as_echo "$LD" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +# Extract the first word of "ar", so it can be a program name with args. +set dummy ar; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_path_AR+:} false; then : + $as_echo_n "(cached) " >&6 +else + case $AR in + [\\/]* | ?:[\\/]*) + ac_cv_path_AR="$AR" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_path_AR="$as_dir/$ac_word$ac_exec_ext" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + + ;; +esac +fi +AR=$ac_cv_path_AR +if test -n "$AR"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $AR" >&5 +$as_echo "$AR" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +# Extract the first word of "ranlib", so it can be a program name with args. +set dummy ranlib; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_path_RANLIB+:} false; then : + $as_echo_n "(cached) " >&6 +else + case $RANLIB in + [\\/]* | ?:[\\/]*) + ac_cv_path_RANLIB="$RANLIB" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_path_RANLIB="$as_dir/$ac_word$ac_exec_ext" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + + ;; +esac +fi +RANLIB=$ac_cv_path_RANLIB +if test -n "$RANLIB"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $RANLIB" >&5 +$as_echo "$RANLIB" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +# Extract the first word of "autoconf", so it can be a program name with args. +set dummy autoconf; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_path_AUTOCONF+:} false; then : + $as_echo_n "(cached) " >&6 +else + case $AUTOCONF in + [\\/]* | ?:[\\/]*) + ac_cv_path_AUTOCONF="$AUTOCONF" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_path_AUTOCONF="$as_dir/$ac_word$ac_exec_ext" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + + ;; +esac +fi +AUTOCONF=$ac_cv_path_AUTOCONF +if test -n "$AUTOCONF"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $AUTOCONF" >&5 +$as_echo "$AUTOCONF" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + +#AC_ENABLE_SHARED +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to build shared libraries" >&5 +$as_echo_n "checking whether to build shared libraries... " >&6; } +# Check whether --enable-shared was given. +if test "${enable_shared+set}" = set; then : + enableval=$enable_shared; shared=$enableval +else + shared=yes +fi + +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $shared" >&5 +$as_echo "$shared" >&6; } + +#AC_ENABLE_STATIC +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to build static libraries" >&5 +$as_echo_n "checking whether to build static libraries... " >&6; } +# Check whether --enable-static was given. +if test "${enable_static+set}" = set; then : + enableval=$enable_static; static=$enableval +else + static=yes +fi + +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $static" >&5 +$as_echo "$static" >&6; } + +# Make sure either enable_shared or enable_static is yes. +test "$shared" = "yes" || test "$static" = "yes" + +# Make sure we can run config.sub. +$SHELL "$ac_aux_dir/config.sub" sun4 >/dev/null 2>&1 || + as_fn_error $? "cannot run $SHELL $ac_aux_dir/config.sub" "$LINENO" 5 + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking build system type" >&5 +$as_echo_n "checking build system type... " >&6; } +if ${ac_cv_build+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_build_alias=$build_alias +test "x$ac_build_alias" = x && + ac_build_alias=`$SHELL "$ac_aux_dir/config.guess"` +test "x$ac_build_alias" = x && + as_fn_error $? "cannot guess build type; you must specify one" "$LINENO" 5 +ac_cv_build=`$SHELL "$ac_aux_dir/config.sub" $ac_build_alias` || + as_fn_error $? "$SHELL $ac_aux_dir/config.sub $ac_build_alias failed" "$LINENO" 5 + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_build" >&5 +$as_echo "$ac_cv_build" >&6; } +case $ac_cv_build in +*-*-*) ;; +*) as_fn_error $? "invalid value of canonical build" "$LINENO" 5;; +esac +build=$ac_cv_build +ac_save_IFS=$IFS; IFS='-' +set x $ac_cv_build +shift +build_cpu=$1 +build_vendor=$2 +shift; shift +# Remember, the first character of IFS is used to create $*, +# except with old shells: +build_os=$* +IFS=$ac_save_IFS +case $build_os in *\ *) build_os=`echo "$build_os" | sed 's/ /-/g'`;; esac + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking host system type" >&5 +$as_echo_n "checking host system type... " >&6; } +if ${ac_cv_host+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test "x$host_alias" = x; then + ac_cv_host=$ac_cv_build +else + ac_cv_host=`$SHELL "$ac_aux_dir/config.sub" $host_alias` || + as_fn_error $? "$SHELL $ac_aux_dir/config.sub $host_alias failed" "$LINENO" 5 +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_host" >&5 +$as_echo "$ac_cv_host" >&6; } +case $ac_cv_host in +*-*-*) ;; +*) as_fn_error $? "invalid value of canonical host" "$LINENO" 5;; +esac +host=$ac_cv_host +ac_save_IFS=$IFS; IFS='-' +set x $ac_cv_host +shift +host_cpu=$1 +host_vendor=$2 +shift; shift +# Remember, the first character of IFS is used to create $*, +# except with old shells: +host_os=$* +IFS=$ac_save_IFS +case $host_os in *\ *) host_os=`echo "$host_os" | sed 's/ /-/g'`;; esac + + +case "${host}" in + *-*-darwin*) + abi="macho" + RPATH="" + ;; + *-*-freebsd*) + CFLAGS="$CFLAGS" + abi="elf" + RPATH="-Wl,-rpath," + ;; + *-*-linux*) + CFLAGS="$CFLAGS" + abi="elf" + CPPFLAGS="$CPPFLAGS -D_GNU_SOURCE" + RPATH="-Wl,-rpath," + ;; + *-*-netbsd*) + { $as_echo "$as_me:${as_lineno-$LINENO}: checking ABI" >&5 +$as_echo_n "checking ABI... " >&6; } + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#ifdef __ELF__ +/* ELF */ +#else +#error aout +#endif + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + CFLAGS="$CFLAGS"; abi="elf" +else + abi="aout" +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $abi" >&5 +$as_echo "$abi" >&6; } + RPATH="-Wl,-rpath," + ;; + *-*-solaris2*) + CFLAGS="$CFLAGS" + abi="elf" + RPATH="-Wl,-R," + ;; + *) + { $as_echo "$as_me:${as_lineno-$LINENO}: result: Unsupported operating system: ${host}" >&5 +$as_echo "Unsupported operating system: ${host}" >&6; } + abi="elf" + RPATH="-Wl,-rpath," + ;; +esac + + + +# Check whether --enable-autogen was given. +if test "${enable_autogen+set}" = set; then : + enableval=$enable_autogen; if test "x$enable_autogen" = "xno" ; then + enable_autogen="0" +else + enable_autogen="1" +fi + +else + enable_autogen="0" + +fi + + + +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +#include +int +main () +{ +acl_t a + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + +$as_echo "#define HAVE_SYS_ACL_H 1" >>confdefs.h + +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for grep that handles long lines and -e" >&5 +$as_echo_n "checking for grep that handles long lines and -e... " >&6; } +if ${ac_cv_path_GREP+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -z "$GREP"; then + ac_path_GREP_found=false + # Loop through the user's path and test for each of PROGNAME-LIST + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_prog in grep ggrep; do + for ac_exec_ext in '' $ac_executable_extensions; do + ac_path_GREP="$as_dir/$ac_prog$ac_exec_ext" + as_fn_executable_p "$ac_path_GREP" || continue +# Check for GNU ac_path_GREP and select it if it is found. + # Check for GNU $ac_path_GREP +case `"$ac_path_GREP" --version 2>&1` in +*GNU*) + ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_found=:;; +*) + ac_count=0 + $as_echo_n 0123456789 >"conftest.in" + while : + do + cat "conftest.in" "conftest.in" >"conftest.tmp" + mv "conftest.tmp" "conftest.in" + cp "conftest.in" "conftest.nl" + $as_echo 'GREP' >> "conftest.nl" + "$ac_path_GREP" -e 'GREP$' -e '-(cannot match)-' < "conftest.nl" >"conftest.out" 2>/dev/null || break + diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break + as_fn_arith $ac_count + 1 && ac_count=$as_val + if test $ac_count -gt ${ac_path_GREP_max-0}; then + # Best one so far, save it but keep looking for a better one + ac_cv_path_GREP="$ac_path_GREP" + ac_path_GREP_max=$ac_count + fi + # 10*(2^10) chars as input seems more than enough + test $ac_count -gt 10 && break + done + rm -f conftest.in conftest.tmp conftest.nl conftest.out;; +esac + + $ac_path_GREP_found && break 3 + done + done + done +IFS=$as_save_IFS + if test -z "$ac_cv_path_GREP"; then + as_fn_error $? "no acceptable grep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 + fi +else + ac_cv_path_GREP=$GREP +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_GREP" >&5 +$as_echo "$ac_cv_path_GREP" >&6; } + GREP="$ac_cv_path_GREP" + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for egrep" >&5 +$as_echo_n "checking for egrep... " >&6; } +if ${ac_cv_path_EGREP+:} false; then : + $as_echo_n "(cached) " >&6 +else + if echo a | $GREP -E '(a|b)' >/dev/null 2>&1 + then ac_cv_path_EGREP="$GREP -E" + else + if test -z "$EGREP"; then + ac_path_EGREP_found=false + # Loop through the user's path and test for each of PROGNAME-LIST + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_prog in egrep; do + for ac_exec_ext in '' $ac_executable_extensions; do + ac_path_EGREP="$as_dir/$ac_prog$ac_exec_ext" + as_fn_executable_p "$ac_path_EGREP" || continue +# Check for GNU ac_path_EGREP and select it if it is found. + # Check for GNU $ac_path_EGREP +case `"$ac_path_EGREP" --version 2>&1` in +*GNU*) + ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_found=:;; +*) + ac_count=0 + $as_echo_n 0123456789 >"conftest.in" + while : + do + cat "conftest.in" "conftest.in" >"conftest.tmp" + mv "conftest.tmp" "conftest.in" + cp "conftest.in" "conftest.nl" + $as_echo 'EGREP' >> "conftest.nl" + "$ac_path_EGREP" 'EGREP$' < "conftest.nl" >"conftest.out" 2>/dev/null || break + diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break + as_fn_arith $ac_count + 1 && ac_count=$as_val + if test $ac_count -gt ${ac_path_EGREP_max-0}; then + # Best one so far, save it but keep looking for a better one + ac_cv_path_EGREP="$ac_path_EGREP" + ac_path_EGREP_max=$ac_count + fi + # 10*(2^10) chars as input seems more than enough + test $ac_count -gt 10 && break + done + rm -f conftest.in conftest.tmp conftest.nl conftest.out;; +esac + + $ac_path_EGREP_found && break 3 + done + done + done +IFS=$as_save_IFS + if test -z "$ac_cv_path_EGREP"; then + as_fn_error $? "no acceptable egrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 + fi +else + ac_cv_path_EGREP=$EGREP +fi + + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_EGREP" >&5 +$as_echo "$ac_cv_path_EGREP" >&6; } + EGREP="$ac_cv_path_EGREP" + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for ANSI C header files" >&5 +$as_echo_n "checking for ANSI C header files... " >&6; } +if ${ac_cv_header_stdc+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +#include +#include +#include + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_header_stdc=yes +else + ac_cv_header_stdc=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + +if test $ac_cv_header_stdc = yes; then + # SunOS 4.x string.h does not declare mem*, contrary to ANSI. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include + +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "memchr" >/dev/null 2>&1; then : + +else + ac_cv_header_stdc=no +fi +rm -f conftest* + +fi + +if test $ac_cv_header_stdc = yes; then + # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include + +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "free" >/dev/null 2>&1; then : + +else + ac_cv_header_stdc=no +fi +rm -f conftest* + +fi + +if test $ac_cv_header_stdc = yes; then + # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi. + if test "$cross_compiling" = yes; then : + : +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +#include +#if ((' ' & 0x0FF) == 0x020) +# define ISLOWER(c) ('a' <= (c) && (c) <= 'z') +# define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c)) +#else +# define ISLOWER(c) \ + (('a' <= (c) && (c) <= 'i') \ + || ('j' <= (c) && (c) <= 'r') \ + || ('s' <= (c) && (c) <= 'z')) +# define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c)) +#endif + +#define XOR(e, f) (((e) && !(f)) || (!(e) && (f))) +int +main () +{ + int i; + for (i = 0; i < 256; i++) + if (XOR (islower (i), ISLOWER (i)) + || toupper (i) != TOUPPER (i)) + return 2; + return 0; +} +_ACEOF +if ac_fn_c_try_run "$LINENO"; then : + +else + ac_cv_header_stdc=no +fi +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ + conftest.$ac_objext conftest.beam conftest.$ac_ext +fi + +fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_stdc" >&5 +$as_echo "$ac_cv_header_stdc" >&6; } +if test $ac_cv_header_stdc = yes; then + +$as_echo "#define STDC_HEADERS 1" >>confdefs.h + +fi + +# On IRIX 5.3, sys/types and inttypes.h are conflicting. +for ac_header in sys/types.h sys/stat.h stdlib.h string.h memory.h strings.h \ + inttypes.h stdint.h unistd.h +do : + as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` +ac_fn_c_check_header_compile "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default +" +if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + +fi + +done + + +for ac_header in ext2fs/ext2_fs.h sys/statfs.h sys/xattr.h sys/param.h sys/extattr.h libutil.h +do : + as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` +ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default" +if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + +fi + +done + +for ac_func in lgetxattr +do : + ac_fn_c_check_func "$LINENO" "lgetxattr" "ac_cv_func_lgetxattr" +if test "x$ac_cv_func_lgetxattr" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_LGETXATTR 1 +_ACEOF + +fi +done + +for ac_func in lsetxattr +do : + ac_fn_c_check_func "$LINENO" "lsetxattr" "ac_cv_func_lsetxattr" +if test "x$ac_cv_func_lsetxattr" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_LSETXATTR 1 +_ACEOF + +fi +done + +for ac_func in getxattr +do : + ac_fn_c_check_func "$LINENO" "getxattr" "ac_cv_func_getxattr" +if test "x$ac_cv_func_getxattr" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_GETXATTR 1 +_ACEOF + +fi +done + +for ac_func in setxattr +do : + ac_fn_c_check_func "$LINENO" "setxattr" "ac_cv_func_setxattr" +if test "x$ac_cv_func_setxattr" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_SETXATTR 1 +_ACEOF + +fi +done + +for ac_func in getattrlist +do : + ac_fn_c_check_func "$LINENO" "getattrlist" "ac_cv_func_getattrlist" +if test "x$ac_cv_func_getattrlist" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_GETATTRLIST 1 +_ACEOF + +fi +done + +for ac_func in setattrlist +do : + ac_fn_c_check_func "$LINENO" "setattrlist" "ac_cv_func_setattrlist" +if test "x$ac_cv_func_setattrlist" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_SETATTRLIST 1 +_ACEOF + +fi +done + +for ac_func in lchmod +do : + ac_fn_c_check_func "$LINENO" "lchmod" "ac_cv_func_lchmod" +if test "x$ac_cv_func_lchmod" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_LCHMOD 1 +_ACEOF + +fi +done + +for ac_func in lchown +do : + ac_fn_c_check_func "$LINENO" "lchown" "ac_cv_func_lchown" +if test "x$ac_cv_func_lchown" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_LCHOWN 1 +_ACEOF + +fi +done + +for ac_func in chflags +do : + ac_fn_c_check_func "$LINENO" "chflags" "ac_cv_func_chflags" +if test "x$ac_cv_func_chflags" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_CHFLAGS 1 +_ACEOF + +fi +done + +for ac_func in statvfs +do : + ac_fn_c_check_func "$LINENO" "statvfs" "ac_cv_func_statvfs" +if test "x$ac_cv_func_statvfs" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_STATVFS 1 +_ACEOF + +fi +done + +for ac_func in statfs +do : + ac_fn_c_check_func "$LINENO" "statfs" "ac_cv_func_statfs" +if test "x$ac_cv_func_statfs" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_STATFS 1 +_ACEOF + +fi +done + +for ac_func in strmode +do : + ac_fn_c_check_func "$LINENO" "strmode" "ac_cv_func_strmode" +if test "x$ac_cv_func_strmode" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_STRMODE 1 +_ACEOF + +fi +done + + +ac_fn_c_check_member "$LINENO" "struct statfs" "f_fstypename" "ac_cv_member_struct_statfs_f_fstypename" "#include +#include +#include +" +if test "x$ac_cv_member_struct_statfs_f_fstypename" = xyes; then : + +cat >>confdefs.h <<_ACEOF +#define HAVE_STRUCT_STATFS_F_FSTYPENAME 1 +_ACEOF + + +fi + +ac_fn_c_check_member "$LINENO" "struct statvfs" "f_fstypename" "ac_cv_member_struct_statvfs_f_fstypename" "#include +" +if test "x$ac_cv_member_struct_statvfs_f_fstypename" = xyes; then : + +cat >>confdefs.h <<_ACEOF +#define HAVE_STRUCT_STATVFS_F_FSTYPENAME 1 +_ACEOF + + +fi + +ac_fn_c_check_member "$LINENO" "struct stat" "st_flags" "ac_cv_member_struct_stat_st_flags" "$ac_includes_default" +if test "x$ac_cv_member_struct_stat_st_flags" = xyes; then : + +cat >>confdefs.h <<_ACEOF +#define HAVE_STRUCT_STAT_ST_FLAGS 1 +_ACEOF + + +fi + + +# The cast to long int works around a bug in the HP C Compiler +# version HP92453-01 B.11.11.23709.GP, which incorrectly rejects +# declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'. +# This bug is HP SR number 8606223364. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking size of uid_t" >&5 +$as_echo_n "checking size of uid_t... " >&6; } +if ${ac_cv_sizeof_uid_t+:} false; then : + $as_echo_n "(cached) " >&6 +else + if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (uid_t))" "ac_cv_sizeof_uid_t" "$ac_includes_default"; then : + +else + if test "$ac_cv_type_uid_t" = yes; then + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error 77 "cannot compute sizeof (uid_t) +See \`config.log' for more details" "$LINENO" 5; } + else + ac_cv_sizeof_uid_t=0 + fi +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof_uid_t" >&5 +$as_echo "$ac_cv_sizeof_uid_t" >&6; } + + + +cat >>confdefs.h <<_ACEOF +#define SIZEOF_UID_T $ac_cv_sizeof_uid_t +_ACEOF + + +if test $ac_cv_sizeof_uid_t = "4"; then +$as_echo "#define UID_STRING RId32" >>confdefs.h + +$as_echo "#define UID_CAST (uint32_t)" >>confdefs.h + +elif test $ac_cv_sizeof_uid_t = "8"; then +$as_echo "#define UID_STRING PRId64" >>confdefs.h + +$as_echo "#define UID_CAST (uint64_t)" >>confdefs.h + +else +as_fn_error $? "can not detect the size of your system's uid_t type" "$LINENO" 5 +fi + +# The cast to long int works around a bug in the HP C Compiler +# version HP92453-01 B.11.11.23709.GP, which incorrectly rejects +# declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'. +# This bug is HP SR number 8606223364. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking size of gid_t" >&5 +$as_echo_n "checking size of gid_t... " >&6; } +if ${ac_cv_sizeof_gid_t+:} false; then : + $as_echo_n "(cached) " >&6 +else + if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (gid_t))" "ac_cv_sizeof_gid_t" "$ac_includes_default"; then : + +else + if test "$ac_cv_type_gid_t" = yes; then + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error 77 "cannot compute sizeof (gid_t) +See \`config.log' for more details" "$LINENO" 5; } + else + ac_cv_sizeof_gid_t=0 + fi +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof_gid_t" >&5 +$as_echo "$ac_cv_sizeof_gid_t" >&6; } + + + +cat >>confdefs.h <<_ACEOF +#define SIZEOF_GID_T $ac_cv_sizeof_gid_t +_ACEOF + + +if test $ac_cv_sizeof_gid_t = "4"; then +$as_echo "#define GID_STRING PRId32" >>confdefs.h + +$as_echo "#define GID_CAST (uint32_t)" >>confdefs.h + +elif test $ac_cv_sizeof_gid_t = "8"; then +$as_echo "#define GID_STRING PRId64" >>confdefs.h + +$as_echo "#define GID_CAST (uint64_t)" >>confdefs.h + +else +as_fn_error $? "can not detect the size of your system's gid_t type" "$LINENO" 5 +fi + +# The cast to long int works around a bug in the HP C Compiler +# version HP92453-01 B.11.11.23709.GP, which incorrectly rejects +# declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'. +# This bug is HP SR number 8606223364. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking size of ino_t" >&5 +$as_echo_n "checking size of ino_t... " >&6; } +if ${ac_cv_sizeof_ino_t+:} false; then : + $as_echo_n "(cached) " >&6 +else + if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (ino_t))" "ac_cv_sizeof_ino_t" "$ac_includes_default"; then : + +else + if test "$ac_cv_type_ino_t" = yes; then + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error 77 "cannot compute sizeof (ino_t) +See \`config.log' for more details" "$LINENO" 5; } + else + ac_cv_sizeof_ino_t=0 + fi +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof_ino_t" >&5 +$as_echo "$ac_cv_sizeof_ino_t" >&6; } + + + +cat >>confdefs.h <<_ACEOF +#define SIZEOF_INO_T $ac_cv_sizeof_ino_t +_ACEOF + + +if test $ac_cv_sizeof_ino_t = "4"; then +$as_echo "#define INO_STRING PRId32" >>confdefs.h + +$as_echo "#define INO_HEXSTRING PRIx32" >>confdefs.h + +$as_echo "#define INO_CAST (uint32_t)" >>confdefs.h + +elif test $ac_cv_sizeof_ino_t = "8"; then +$as_echo "#define INO_STRING PRId64" >>confdefs.h + +$as_echo "#define INO_HEXSTRING PRIx64" >>confdefs.h + +$as_echo "#define INO_CAST (uint64_t)" >>confdefs.h + +else +as_fn_error $? "can not detect the size of your system's ino_t type" "$LINENO" 5 +fi + +# The cast to long int works around a bug in the HP C Compiler +# version HP92453-01 B.11.11.23709.GP, which incorrectly rejects +# declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'. +# This bug is HP SR number 8606223364. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking size of dev_t" >&5 +$as_echo_n "checking size of dev_t... " >&6; } +if ${ac_cv_sizeof_dev_t+:} false; then : + $as_echo_n "(cached) " >&6 +else + if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (dev_t))" "ac_cv_sizeof_dev_t" "$ac_includes_default"; then : + +else + if test "$ac_cv_type_dev_t" = yes; then + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error 77 "cannot compute sizeof (dev_t) +See \`config.log' for more details" "$LINENO" 5; } + else + ac_cv_sizeof_dev_t=0 + fi +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof_dev_t" >&5 +$as_echo "$ac_cv_sizeof_dev_t" >&6; } + + + +cat >>confdefs.h <<_ACEOF +#define SIZEOF_DEV_T $ac_cv_sizeof_dev_t +_ACEOF + + +if test $ac_cv_sizeof_dev_t = "4"; then +$as_echo "#define DEV_STRING PRId32" >>confdefs.h + +$as_echo "#define DEV_HEXSTRING PRIx32" >>confdefs.h + +$as_echo "#define DEV_CAST (uint32_t)" >>confdefs.h + +elif test $ac_cv_sizeof_dev_t = "8"; then +$as_echo "#define DEV_STRING PRId64" >>confdefs.h + +$as_echo "#define DEV_HEXSTRING PRIx64" >>confdefs.h + +$as_echo "#define DEV_CAST (uint64_t)" >>confdefs.h + +else +as_fn_error $? "can not detect the size of your system's dev_t type" "$LINENO" 5 +fi + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for acl_get_file in -lacl" >&5 +$as_echo_n "checking for acl_get_file in -lacl... " >&6; } +if ${ac_cv_lib_acl_acl_get_file+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lacl $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char acl_get_file (); +int +main () +{ +return acl_get_file (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_acl_acl_get_file=yes +else + ac_cv_lib_acl_acl_get_file=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_acl_acl_get_file" >&5 +$as_echo "$ac_cv_lib_acl_acl_get_file" >&6; } +if test "x$ac_cv_lib_acl_acl_get_file" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_LIBACL 1 +_ACEOF + + LIBS="-lacl $LIBS" + +fi + + + + +ac_fn_c_check_func "$LINENO" "asprintf" "ac_cv_func_asprintf" +if test "x$ac_cv_func_asprintf" = xyes; then : + $as_echo "#define HAVE_ASPRINTF 1" >>confdefs.h + +fi + + +LIBXML2_VERSION_MIN=2.6.11 + +have_libxml2="1" + + +# Check whether --with-xml2-config was given. +if test "${with_xml2_config+set}" = set; then : + withval=$with_xml2_config; if test "x${with_xml2_config}" = "xno" ; then + XML2_CONFIG= +else + XML2_CONFIG="${with_xml2_config}" +fi + +else + XML2_CONFIG= + +fi + +if test "x${XML2_CONFIG}" != "x" ; then + if test ! -x "${XML2_CONFIG}" ; then + as_fn_error $? "Unusable or missing xml2-config: ${XML2_CONFIG}" "$LINENO" 5 + fi +else + # Extract the first word of "xml2-config", so it can be a program name with args. +set dummy xml2-config; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_path_XML2_CONFIG+:} false; then : + $as_echo_n "(cached) " >&6 +else + case $XML2_CONFIG in + [\\/]* | ?:[\\/]*) + ac_cv_path_XML2_CONFIG="$XML2_CONFIG" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in ${PATH} +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_path_XML2_CONFIG="$as_dir/$ac_word$ac_exec_ext" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + + ;; +esac +fi +XML2_CONFIG=$ac_cv_path_XML2_CONFIG +if test -n "$XML2_CONFIG"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $XML2_CONFIG" >&5 +$as_echo "$XML2_CONFIG" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + if test "x${XML2_CONFIG}" = "x" ; then + as_fn_error $? "Cannot configure without xml2-config" "$LINENO" 5 + fi +fi + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for libxml >= ${LIBXML2_VERSION_MIN}" >&5 +$as_echo_n "checking for libxml >= ${LIBXML2_VERSION_MIN}... " >&6; } +LIBXML2_FOUND=`2>&1 ${XML2_CONFIG} --version` +LIBXML2_MAJOR=`echo ${LIBXML2_FOUND} | tr . " " | awk '{print $1}'` +LIBXML2_MINOR=`echo ${LIBXML2_FOUND} | tr . " " | awk '{print $2}' | tr a-z " " |awk '{print $1}'` +LIBXML2_BRANCH=`echo ${LIBXML2_FOUND} | tr . " " | awk '{print $3}' | tr a-z " " |awk '{print $1}'` +if test "x${LIBXML2_BRANCH}" = "x" ; then + LIBXML2_BRANCH=0 +fi +LIBXML2_MAJOR_MIN=`echo ${LIBXML2_VERSION_MIN} | tr . " " | awk '{print $1}'` +LIBXML2_MINOR_MIN=`echo ${LIBXML2_VERSION_MIN} | tr . " " | awk '{print $2}'` +LIBXML2_BRANCH_MIN=`echo ${LIBXML2_VERSION_MIN} | tr . " " | awk '{print $3}'` +if test ${LIBXML2_MAJOR} -gt ${LIBXML2_MAJOR_MIN} \ + -o ${LIBXML2_MAJOR} -eq ${LIBXML2_MAJOR_MIN} \ + -a ${LIBXML2_MINOR} -gt ${LIBXML2_MINOR_MIN} \ + -o ${LIBXML2_MAJOR} -eq ${LIBXML2_MAJOR_MIN} \ + -a ${LIBXML2_MINOR} -eq ${LIBXML2_MINOR_MIN} \ + -a ${LIBXML2_BRANCH} -ge $LIBXML2_BRANCH_MIN ; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: ${LIBXML2_MAJOR}.${LIBXML2_MINOR}.${LIBXML2_BRANCH}" >&5 +$as_echo "${LIBXML2_MAJOR}.${LIBXML2_MINOR}.${LIBXML2_BRANCH}" >&6; } + have_libxml2="1" + CPPFLAGS="${CPPFLAGS} `${XML2_CONFIG} --cflags`" + LIBS="${LIBS} `${XML2_CONFIG} --libs`" +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + have_libxml2="0" +fi +if test "x${have_libxml2}" = "x1" ; then + ac_fn_c_check_header_mongrel "$LINENO" "libxml/xmlwriter.h" "ac_cv_header_libxml_xmlwriter_h" "$ac_includes_default" +if test "x$ac_cv_header_libxml_xmlwriter_h" = xyes; then : + +else + have_libxml2="0" +fi + + +fi +if test "x${have_libxml2}" = "x0" ; then + as_fn_error $? "Cannot build without libxml2" "$LINENO" 5 +fi + +have_libz="1" +for ac_header in zlib.h +do : + ac_fn_c_check_header_mongrel "$LINENO" "zlib.h" "ac_cv_header_zlib_h" "$ac_includes_default" +if test "x$ac_cv_header_zlib_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_ZLIB_H 1 +_ACEOF + +else + have_libz="0" +fi + +done + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for deflate in -lz" >&5 +$as_echo_n "checking for deflate in -lz... " >&6; } +if ${ac_cv_lib_z_deflate+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lz $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char deflate (); +int +main () +{ +return deflate (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_z_deflate=yes +else + ac_cv_lib_z_deflate=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_z_deflate" >&5 +$as_echo "$ac_cv_lib_z_deflate" >&6; } +if test "x$ac_cv_lib_z_deflate" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_LIBZ 1 +_ACEOF + + LIBS="-lz $LIBS" + +else + have_libz="0" +fi + +if test "x${have_libz}" = "x0" ; then + as_fn_error $? "Cannot build without libz" "$LINENO" 5 +fi + +have_libbz2="1" +for ac_header in bzlib.h +do : + ac_fn_c_check_header_mongrel "$LINENO" "bzlib.h" "ac_cv_header_bzlib_h" "$ac_includes_default" +if test "x$ac_cv_header_bzlib_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_BZLIB_H 1 +_ACEOF + +else + have_libbz2="0" +fi + +done + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for BZ2_bzCompress in -lbz2" >&5 +$as_echo_n "checking for BZ2_bzCompress in -lbz2... " >&6; } +if ${ac_cv_lib_bz2_BZ2_bzCompress+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lbz2 $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char BZ2_bzCompress (); +int +main () +{ +return BZ2_bzCompress (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_bz2_BZ2_bzCompress=yes +else + ac_cv_lib_bz2_BZ2_bzCompress=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_bz2_BZ2_bzCompress" >&5 +$as_echo "$ac_cv_lib_bz2_BZ2_bzCompress" >&6; } +if test "x$ac_cv_lib_bz2_BZ2_bzCompress" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_LIBBZ2 1 +_ACEOF + + LIBS="-lbz2 $LIBS" + +else + have_libbz2="0" +fi + +if test "x${have_libbz2}" = "x1" ; then + $as_echo "#define HAVE_LIBBZ2 1" >>confdefs.h + +fi + +have_libpthread="1" +for ac_header in pthread.h +do : + ac_fn_c_check_header_mongrel "$LINENO" "pthread.h" "ac_cv_header_pthread_h" "$ac_includes_default" +if test "x$ac_cv_header_pthread_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_PTHREAD_H 1 +_ACEOF + +else + have_libpthread="0" +fi + +done + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for pthread_mutex_lock in -lpthread" >&5 +$as_echo_n "checking for pthread_mutex_lock in -lpthread... " >&6; } +if ${ac_cv_lib_pthread_pthread_mutex_lock+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lpthread $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char pthread_mutex_lock (); +int +main () +{ +return pthread_mutex_lock (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_pthread_pthread_mutex_lock=yes +else + ac_cv_lib_pthread_pthread_mutex_lock=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_pthread_pthread_mutex_lock" >&5 +$as_echo "$ac_cv_lib_pthread_pthread_mutex_lock" >&6; } +if test "x$ac_cv_lib_pthread_pthread_mutex_lock" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_LIBPTHREAD 1 +_ACEOF + + LIBS="-lpthread $LIBS" + +else + have_libpthread="0" +fi + +if test "x${have_libpthread}" = "x1" ; then + $as_echo "#define HAVE_LIBPTHREAD 1" >>confdefs.h + +fi + + +ac_config_headers="$ac_config_headers $cfghdrs" + + + +ac_config_files="$ac_config_files $cfgoutputs" + + +cat >confcache <<\_ACEOF +# This file is a shell script that caches the results of configure +# tests run on this system so they can be shared between configure +# scripts and configure runs, see configure's option --config-cache. +# It is not useful on other systems. If it contains results you don't +# want to keep, you may remove or edit it. +# +# config.status only pays attention to the cache file if you give it +# the --recheck option to rerun configure. +# +# `ac_cv_env_foo' variables (set or unset) will be overridden when +# loading this file, other *unset* `ac_cv_foo' will be assigned the +# following values. + +_ACEOF + +# The following way of writing the cache mishandles newlines in values, +# but we know of no workaround that is simple, portable, and efficient. +# So, we kill variables containing newlines. +# Ultrix sh set writes to stderr and can't be redirected directly, +# and sets the high bit in the cache file unless we assign to the vars. +( + for ac_var in `(set) 2>&1 | sed -n 's/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'`; do + eval ac_val=\$$ac_var + case $ac_val in #( + *${as_nl}*) + case $ac_var in #( + *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 +$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; + esac + case $ac_var in #( + _ | IFS | as_nl) ;; #( + BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( + *) { eval $ac_var=; unset $ac_var;} ;; + esac ;; + esac + done + + (set) 2>&1 | + case $as_nl`(ac_space=' '; set) 2>&1` in #( + *${as_nl}ac_space=\ *) + # `set' does not quote correctly, so add quotes: double-quote + # substitution turns \\\\ into \\, and sed turns \\ into \. + sed -n \ + "s/'/'\\\\''/g; + s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p" + ;; #( + *) + # `set' quotes correctly as required by POSIX, so do not add quotes. + sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" + ;; + esac | + sort +) | + sed ' + /^ac_cv_env_/b end + t clear + :clear + s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/ + t end + s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/ + :end' >>confcache +if diff "$cache_file" confcache >/dev/null 2>&1; then :; else + if test -w "$cache_file"; then + if test "x$cache_file" != "x/dev/null"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: updating cache $cache_file" >&5 +$as_echo "$as_me: updating cache $cache_file" >&6;} + if test ! -f "$cache_file" || test -h "$cache_file"; then + cat confcache >"$cache_file" + else + case $cache_file in #( + */* | ?:*) + mv -f confcache "$cache_file"$$ && + mv -f "$cache_file"$$ "$cache_file" ;; #( + *) + mv -f confcache "$cache_file" ;; + esac + fi + fi + else + { $as_echo "$as_me:${as_lineno-$LINENO}: not updating unwritable cache $cache_file" >&5 +$as_echo "$as_me: not updating unwritable cache $cache_file" >&6;} + fi +fi +rm -f confcache + +test "x$prefix" = xNONE && prefix=$ac_default_prefix +# Let make expand exec_prefix. +test "x$exec_prefix" = xNONE && exec_prefix='${prefix}' + +DEFS=-DHAVE_CONFIG_H + +ac_libobjs= +ac_ltlibobjs= +U= +for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue + # 1. Remove the extension, and $U if already installed. + ac_script='s/\$U\././;s/\.o$//;s/\.obj$//' + ac_i=`$as_echo "$ac_i" | sed "$ac_script"` + # 2. Prepend LIBOBJDIR. When used with automake>=1.10 LIBOBJDIR + # will be set to the directory where LIBOBJS objects are built. + as_fn_append ac_libobjs " \${LIBOBJDIR}$ac_i\$U.$ac_objext" + as_fn_append ac_ltlibobjs " \${LIBOBJDIR}$ac_i"'$U.lo' +done +LIBOBJS=$ac_libobjs + +LTLIBOBJS=$ac_ltlibobjs + + + +: "${CONFIG_STATUS=./config.status}" +ac_write_fail=0 +ac_clean_files_save=$ac_clean_files +ac_clean_files="$ac_clean_files $CONFIG_STATUS" +{ $as_echo "$as_me:${as_lineno-$LINENO}: creating $CONFIG_STATUS" >&5 +$as_echo "$as_me: creating $CONFIG_STATUS" >&6;} +as_write_fail=0 +cat >$CONFIG_STATUS <<_ASEOF || as_write_fail=1 +#! $SHELL +# Generated by $as_me. +# Run this file to recreate the current configuration. +# Compiler output produced by configure, useful for debugging +# configure, is in config.log if it exists. + +debug=false +ac_cs_recheck=false +ac_cs_silent=false + +SHELL=\${CONFIG_SHELL-$SHELL} +export SHELL +_ASEOF +cat >>$CONFIG_STATUS <<\_ASEOF || as_write_fail=1 +## -------------------- ## +## M4sh Initialization. ## +## -------------------- ## + +# Be more Bourne compatible +DUALCASE=1; export DUALCASE # for MKS sh +if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then : + emulate sh + NULLCMD=: + # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which + # is contrary to our usage. Disable this feature. + alias -g '${1+"$@"}'='"$@"' + setopt NO_GLOB_SUBST +else + case `(set -o) 2>/dev/null` in #( + *posix*) : + set -o posix ;; #( + *) : + ;; +esac +fi + + +as_nl=' +' +export as_nl +# Printing a long string crashes Solaris 7 /usr/bin/printf. +as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' +as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo +as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo +# Prefer a ksh shell builtin over an external printf program on Solaris, +# but without wasting forks for bash or zsh. +if test -z "$BASH_VERSION$ZSH_VERSION" \ + && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then + as_echo='print -r --' + as_echo_n='print -rn --' +elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then + as_echo='printf %s\n' + as_echo_n='printf %s' +else + if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then + as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"' + as_echo_n='/usr/ucb/echo -n' + else + as_echo_body='eval expr "X$1" : "X\\(.*\\)"' + as_echo_n_body='eval + arg=$1; + case $arg in #( + *"$as_nl"*) + expr "X$arg" : "X\\(.*\\)$as_nl"; + arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;; + esac; + expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl" + ' + export as_echo_n_body + as_echo_n='sh -c $as_echo_n_body as_echo' + fi + export as_echo_body + as_echo='sh -c $as_echo_body as_echo' +fi + +# The user is always right. +if test "${PATH_SEPARATOR+set}" != set; then + PATH_SEPARATOR=: + (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { + (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || + PATH_SEPARATOR=';' + } +fi + + +# IFS +# We need space, tab and new line, in precisely that order. Quoting is +# there to prevent editors from complaining about space-tab. +# (If _AS_PATH_WALK were called with IFS unset, it would disable word +# splitting by setting IFS to empty value.) +IFS=" "" $as_nl" + +# Find who we are. Look in the path if we contain no directory separator. +as_myself= +case $0 in #(( + *[\\/]* ) as_myself=$0 ;; + *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break + done +IFS=$as_save_IFS + + ;; +esac +# We did not find ourselves, most probably we were run as `sh COMMAND' +# in which case we are not to be found in the path. +if test "x$as_myself" = x; then + as_myself=$0 +fi +if test ! -f "$as_myself"; then + $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 + exit 1 +fi + +# Unset variables that we do not need and which cause bugs (e.g. in +# pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1" +# suppresses any "Segmentation fault" message there. '((' could +# trigger a bug in pdksh 5.2.14. +for as_var in BASH_ENV ENV MAIL MAILPATH +do eval test x\${$as_var+set} = xset \ + && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : +done +PS1='$ ' +PS2='> ' +PS4='+ ' + +# NLS nuisances. +LC_ALL=C +export LC_ALL +LANGUAGE=C +export LANGUAGE + +# CDPATH. +(unset CDPATH) >/dev/null 2>&1 && unset CDPATH + + +# as_fn_error STATUS ERROR [LINENO LOG_FD] +# ---------------------------------------- +# Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are +# provided, also output the error to LOG_FD, referencing LINENO. Then exit the +# script with STATUS, using 1 if that was 0. +as_fn_error () +{ + as_status=$1; test $as_status -eq 0 && as_status=1 + if test "$4"; then + as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4 + fi + $as_echo "$as_me: error: $2" >&2 + as_fn_exit $as_status +} # as_fn_error + + +# as_fn_set_status STATUS +# ----------------------- +# Set $? to STATUS, without forking. +as_fn_set_status () +{ + return $1 +} # as_fn_set_status + +# as_fn_exit STATUS +# ----------------- +# Exit the shell with STATUS, even in a "trap 0" or "set -e" context. +as_fn_exit () +{ + set +e + as_fn_set_status $1 + exit $1 +} # as_fn_exit + +# as_fn_unset VAR +# --------------- +# Portably unset VAR. +as_fn_unset () +{ + { eval $1=; unset $1;} +} +as_unset=as_fn_unset +# as_fn_append VAR VALUE +# ---------------------- +# Append the text in VALUE to the end of the definition contained in VAR. Take +# advantage of any shell optimizations that allow amortized linear growth over +# repeated appends, instead of the typical quadratic growth present in naive +# implementations. +if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then : + eval 'as_fn_append () + { + eval $1+=\$2 + }' +else + as_fn_append () + { + eval $1=\$$1\$2 + } +fi # as_fn_append + +# as_fn_arith ARG... +# ------------------ +# Perform arithmetic evaluation on the ARGs, and store the result in the +# global $as_val. Take advantage of shells that can avoid forks. The arguments +# must be portable across $(()) and expr. +if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then : + eval 'as_fn_arith () + { + as_val=$(( $* )) + }' +else + as_fn_arith () + { + as_val=`expr "$@" || test $? -eq 1` + } +fi # as_fn_arith + + +if expr a : '\(a\)' >/dev/null 2>&1 && + test "X`expr 00001 : '.*\(...\)'`" = X001; then + as_expr=expr +else + as_expr=false +fi + +if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then + as_basename=basename +else + as_basename=false +fi + +if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then + as_dirname=dirname +else + as_dirname=false +fi + +as_me=`$as_basename -- "$0" || +$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ + X"$0" : 'X\(//\)$' \| \ + X"$0" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X/"$0" | + sed '/^.*\/\([^/][^/]*\)\/*$/{ + s//\1/ + q + } + /^X\/\(\/\/\)$/{ + s//\1/ + q + } + /^X\/\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + +# Avoid depending upon Character Ranges. +as_cr_letters='abcdefghijklmnopqrstuvwxyz' +as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' +as_cr_Letters=$as_cr_letters$as_cr_LETTERS +as_cr_digits='0123456789' +as_cr_alnum=$as_cr_Letters$as_cr_digits + +ECHO_C= ECHO_N= ECHO_T= +case `echo -n x` in #((((( +-n*) + case `echo 'xy\c'` in + *c*) ECHO_T=' ';; # ECHO_T is single tab character. + xy) ECHO_C='\c';; + *) echo `echo ksh88 bug on AIX 6.1` > /dev/null + ECHO_T=' ';; + esac;; +*) + ECHO_N='-n';; +esac + +rm -f conf$$ conf$$.exe conf$$.file +if test -d conf$$.dir; then + rm -f conf$$.dir/conf$$.file +else + rm -f conf$$.dir + mkdir conf$$.dir 2>/dev/null +fi +if (echo >conf$$.file) 2>/dev/null; then + if ln -s conf$$.file conf$$ 2>/dev/null; then + as_ln_s='ln -s' + # ... but there are two gotchas: + # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. + # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. + # In both cases, we have to default to `cp -pR'. + ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || + as_ln_s='cp -pR' + elif ln conf$$.file conf$$ 2>/dev/null; then + as_ln_s=ln + else + as_ln_s='cp -pR' + fi +else + as_ln_s='cp -pR' +fi +rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file +rmdir conf$$.dir 2>/dev/null + + +# as_fn_mkdir_p +# ------------- +# Create "$as_dir" as a directory, including parents if necessary. +as_fn_mkdir_p () +{ + + case $as_dir in #( + -*) as_dir=./$as_dir;; + esac + test -d "$as_dir" || eval $as_mkdir_p || { + as_dirs= + while :; do + case $as_dir in #( + *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( + *) as_qdir=$as_dir;; + esac + as_dirs="'$as_qdir' $as_dirs" + as_dir=`$as_dirname -- "$as_dir" || +$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$as_dir" : 'X\(//\)[^/]' \| \ + X"$as_dir" : 'X\(//\)$' \| \ + X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$as_dir" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + test -d "$as_dir" && break + done + test -z "$as_dirs" || eval "mkdir $as_dirs" + } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir" + + +} # as_fn_mkdir_p +if mkdir -p . 2>/dev/null; then + as_mkdir_p='mkdir -p "$as_dir"' +else + test -d ./-p && rmdir ./-p + as_mkdir_p=false +fi + + +# as_fn_executable_p FILE +# ----------------------- +# Test if FILE is an executable regular file. +as_fn_executable_p () +{ + test -f "$1" && test -x "$1" +} # as_fn_executable_p +as_test_x='test -x' +as_executable_p=as_fn_executable_p + +# Sed expression to map a string onto a valid CPP name. +as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" + +# Sed expression to map a string onto a valid variable name. +as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" + + +exec 6>&1 +## ----------------------------------- ## +## Main body of $CONFIG_STATUS script. ## +## ----------------------------------- ## +_ASEOF +test $as_write_fail = 0 && chmod +x $CONFIG_STATUS || ac_write_fail=1 + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +# Save the log message, to keep $0 and so on meaningful, and to +# report actual input values of CONFIG_FILES etc. instead of their +# values after options handling. +ac_log=" +This file was extended by Xar $as_me 1.8dev, which was +generated by GNU Autoconf 2.69. Invocation command line was + + CONFIG_FILES = $CONFIG_FILES + CONFIG_HEADERS = $CONFIG_HEADERS + CONFIG_LINKS = $CONFIG_LINKS + CONFIG_COMMANDS = $CONFIG_COMMANDS + $ $0 $@ + +on `(hostname || uname -n) 2>/dev/null | sed 1q` +" + +_ACEOF + +case $ac_config_files in *" +"*) set x $ac_config_files; shift; ac_config_files=$*;; +esac + +case $ac_config_headers in *" +"*) set x $ac_config_headers; shift; ac_config_headers=$*;; +esac + + +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +# Files that config.status was made for. +config_files="$ac_config_files" +config_headers="$ac_config_headers" + +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +ac_cs_usage="\ +\`$as_me' instantiates files and other configuration actions +from templates according to the current configuration. Unless the files +and actions are specified as TAGs, all are instantiated by default. + +Usage: $0 [OPTION]... [TAG]... + + -h, --help print this help, then exit + -V, --version print version number and configuration settings, then exit + --config print configuration, then exit + -q, --quiet, --silent + do not print progress messages + -d, --debug don't remove temporary files + --recheck update $as_me by reconfiguring in the same conditions + --file=FILE[:TEMPLATE] + instantiate the configuration file FILE + --header=FILE[:TEMPLATE] + instantiate the configuration header FILE + +Configuration files: +$config_files + +Configuration headers: +$config_headers + +Report bugs to ." + +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" +ac_cs_version="\\ +Xar config.status 1.8dev +configured by $0, generated by GNU Autoconf 2.69, + with options \\"\$ac_cs_config\\" + +Copyright (C) 2012 Free Software Foundation, Inc. +This config.status script is free software; the Free Software Foundation +gives unlimited permission to copy, distribute and modify it." + +ac_pwd='$ac_pwd' +srcdir='$srcdir' +INSTALL='$INSTALL' +test -n "\$AWK" || AWK=awk +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +# The default lists apply if the user does not specify any file. +ac_need_defaults=: +while test $# != 0 +do + case $1 in + --*=?*) + ac_option=`expr "X$1" : 'X\([^=]*\)='` + ac_optarg=`expr "X$1" : 'X[^=]*=\(.*\)'` + ac_shift=: + ;; + --*=) + ac_option=`expr "X$1" : 'X\([^=]*\)='` + ac_optarg= + ac_shift=: + ;; + *) + ac_option=$1 + ac_optarg=$2 + ac_shift=shift + ;; + esac + + case $ac_option in + # Handling of the options. + -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r) + ac_cs_recheck=: ;; + --version | --versio | --versi | --vers | --ver | --ve | --v | -V ) + $as_echo "$ac_cs_version"; exit ;; + --config | --confi | --conf | --con | --co | --c ) + $as_echo "$ac_cs_config"; exit ;; + --debug | --debu | --deb | --de | --d | -d ) + debug=: ;; + --file | --fil | --fi | --f ) + $ac_shift + case $ac_optarg in + *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;; + '') as_fn_error $? "missing file argument" ;; + esac + as_fn_append CONFIG_FILES " '$ac_optarg'" + ac_need_defaults=false;; + --header | --heade | --head | --hea ) + $ac_shift + case $ac_optarg in + *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;; + esac + as_fn_append CONFIG_HEADERS " '$ac_optarg'" + ac_need_defaults=false;; + --he | --h) + # Conflict between --help and --header + as_fn_error $? "ambiguous option: \`$1' +Try \`$0 --help' for more information.";; + --help | --hel | -h ) + $as_echo "$ac_cs_usage"; exit ;; + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil | --si | --s) + ac_cs_silent=: ;; + + # This is an error. + -*) as_fn_error $? "unrecognized option: \`$1' +Try \`$0 --help' for more information." ;; + + *) as_fn_append ac_config_targets " $1" + ac_need_defaults=false ;; + + esac + shift +done + +ac_configure_extra_args= + +if $ac_cs_silent; then + exec 6>/dev/null + ac_configure_extra_args="$ac_configure_extra_args --silent" +fi + +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +if \$ac_cs_recheck; then + set X $SHELL '$0' $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion + shift + \$as_echo "running CONFIG_SHELL=$SHELL \$*" >&6 + CONFIG_SHELL='$SHELL' + export CONFIG_SHELL + exec "\$@" +fi + +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +exec 5>>config.log +{ + echo + sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX +## Running $as_me. ## +_ASBOX + $as_echo "$ac_log" +} >&5 + +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 + +# Handling of arguments. +for ac_config_target in $ac_config_targets +do + case $ac_config_target in + "$cfghdrs") CONFIG_HEADERS="$CONFIG_HEADERS $cfghdrs" ;; + "$cfgoutputs") CONFIG_FILES="$CONFIG_FILES $cfgoutputs" ;; + + *) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5;; + esac +done + + +# If the user did not use the arguments to specify the items to instantiate, +# then the envvar interface is used. Set only those that are not. +# We use the long form for the default assignment because of an extremely +# bizarre bug on SunOS 4.1.3. +if $ac_need_defaults; then + test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files + test "${CONFIG_HEADERS+set}" = set || CONFIG_HEADERS=$config_headers +fi + +# Have a temporary directory for convenience. Make it in the build tree +# simply because there is no reason against having it here, and in addition, +# creating and moving files from /tmp can sometimes cause problems. +# Hook for its removal unless debugging. +# Note that there is a small window in which the directory will not be cleaned: +# after its creation but before its name has been assigned to `$tmp'. +$debug || +{ + tmp= ac_tmp= + trap 'exit_status=$? + : "${ac_tmp:=$tmp}" + { test ! -d "$ac_tmp" || rm -fr "$ac_tmp"; } && exit $exit_status +' 0 + trap 'as_fn_exit 1' 1 2 13 15 +} +# Create a (secure) tmp directory for tmp files. + +{ + tmp=`(umask 077 && mktemp -d "./confXXXXXX") 2>/dev/null` && + test -d "$tmp" +} || +{ + tmp=./conf$$-$RANDOM + (umask 077 && mkdir "$tmp") +} || as_fn_error $? "cannot create a temporary directory in ." "$LINENO" 5 +ac_tmp=$tmp + +# Set up the scripts for CONFIG_FILES section. +# No need to generate them if there are no CONFIG_FILES. +# This happens for instance with `./config.status config.h'. +if test -n "$CONFIG_FILES"; then + + +ac_cr=`echo X | tr X '\015'` +# On cygwin, bash can eat \r inside `` if the user requested igncr. +# But we know of no other shell where ac_cr would be empty at this +# point, so we can use a bashism as a fallback. +if test "x$ac_cr" = x; then + eval ac_cr=\$\'\\r\' +fi +ac_cs_awk_cr=`$AWK 'BEGIN { print "a\rb" }' /dev/null` +if test "$ac_cs_awk_cr" = "a${ac_cr}b"; then + ac_cs_awk_cr='\\r' +else + ac_cs_awk_cr=$ac_cr +fi + +echo 'BEGIN {' >"$ac_tmp/subs1.awk" && +_ACEOF + + +{ + echo "cat >conf$$subs.awk <<_ACEOF" && + echo "$ac_subst_vars" | sed 's/.*/&!$&$ac_delim/' && + echo "_ACEOF" +} >conf$$subs.sh || + as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 +ac_delim_num=`echo "$ac_subst_vars" | grep -c '^'` +ac_delim='%!_!# ' +for ac_last_try in false false false false false :; do + . ./conf$$subs.sh || + as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 + + ac_delim_n=`sed -n "s/.*$ac_delim\$/X/p" conf$$subs.awk | grep -c X` + if test $ac_delim_n = $ac_delim_num; then + break + elif $ac_last_try; then + as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 + else + ac_delim="$ac_delim!$ac_delim _$ac_delim!! " + fi +done +rm -f conf$$subs.sh + +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +cat >>"\$ac_tmp/subs1.awk" <<\\_ACAWK && +_ACEOF +sed -n ' +h +s/^/S["/; s/!.*/"]=/ +p +g +s/^[^!]*!// +:repl +t repl +s/'"$ac_delim"'$// +t delim +:nl +h +s/\(.\{148\}\)..*/\1/ +t more1 +s/["\\]/\\&/g; s/^/"/; s/$/\\n"\\/ +p +n +b repl +:more1 +s/["\\]/\\&/g; s/^/"/; s/$/"\\/ +p +g +s/.\{148\}// +t nl +:delim +h +s/\(.\{148\}\)..*/\1/ +t more2 +s/["\\]/\\&/g; s/^/"/; s/$/"/ +p +b +:more2 +s/["\\]/\\&/g; s/^/"/; s/$/"\\/ +p +g +s/.\{148\}// +t delim +' >$CONFIG_STATUS || ac_write_fail=1 +rm -f conf$$subs.awk +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +_ACAWK +cat >>"\$ac_tmp/subs1.awk" <<_ACAWK && + for (key in S) S_is_set[key] = 1 + FS = "" + +} +{ + line = $ 0 + nfields = split(line, field, "@") + substed = 0 + len = length(field[1]) + for (i = 2; i < nfields; i++) { + key = field[i] + keylen = length(key) + if (S_is_set[key]) { + value = S[key] + line = substr(line, 1, len) "" value "" substr(line, len + keylen + 3) + len += length(value) + length(field[++i]) + substed = 1 + } else + len += 1 + keylen + } + + print line +} + +_ACAWK +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +if sed "s/$ac_cr//" < /dev/null > /dev/null 2>&1; then + sed "s/$ac_cr\$//; s/$ac_cr/$ac_cs_awk_cr/g" +else + cat +fi < "$ac_tmp/subs1.awk" > "$ac_tmp/subs.awk" \ + || as_fn_error $? "could not setup config files machinery" "$LINENO" 5 +_ACEOF + +# VPATH may cause trouble with some makes, so we remove sole $(srcdir), +# ${srcdir} and @srcdir@ entries from VPATH if srcdir is ".", strip leading and +# trailing colons and then remove the whole line if VPATH becomes empty +# (actually we leave an empty line to preserve line numbers). +if test "x$srcdir" = x.; then + ac_vpsub='/^[ ]*VPATH[ ]*=[ ]*/{ +h +s/// +s/^/:/ +s/[ ]*$/:/ +s/:\$(srcdir):/:/g +s/:\${srcdir}:/:/g +s/:@srcdir@:/:/g +s/^:*// +s/:*$// +x +s/\(=[ ]*\).*/\1/ +G +s/\n// +s/^[^=]*=[ ]*$// +}' +fi + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +fi # test -n "$CONFIG_FILES" + +# Set up the scripts for CONFIG_HEADERS section. +# No need to generate them if there are no CONFIG_HEADERS. +# This happens for instance with `./config.status Makefile'. +if test -n "$CONFIG_HEADERS"; then +cat >"$ac_tmp/defines.awk" <<\_ACAWK || +BEGIN { +_ACEOF + +# Transform confdefs.h into an awk script `defines.awk', embedded as +# here-document in config.status, that substitutes the proper values into +# config.h.in to produce config.h. + +# Create a delimiter string that does not exist in confdefs.h, to ease +# handling of long lines. +ac_delim='%!_!# ' +for ac_last_try in false false :; do + ac_tt=`sed -n "/$ac_delim/p" confdefs.h` + if test -z "$ac_tt"; then + break + elif $ac_last_try; then + as_fn_error $? "could not make $CONFIG_HEADERS" "$LINENO" 5 + else + ac_delim="$ac_delim!$ac_delim _$ac_delim!! " + fi +done + +# For the awk script, D is an array of macro values keyed by name, +# likewise P contains macro parameters if any. Preserve backslash +# newline sequences. + +ac_word_re=[_$as_cr_Letters][_$as_cr_alnum]* +sed -n ' +s/.\{148\}/&'"$ac_delim"'/g +t rset +:rset +s/^[ ]*#[ ]*define[ ][ ]*/ / +t def +d +:def +s/\\$// +t bsnl +s/["\\]/\\&/g +s/^ \('"$ac_word_re"'\)\(([^()]*)\)[ ]*\(.*\)/P["\1"]="\2"\ +D["\1"]=" \3"/p +s/^ \('"$ac_word_re"'\)[ ]*\(.*\)/D["\1"]=" \2"/p +d +:bsnl +s/["\\]/\\&/g +s/^ \('"$ac_word_re"'\)\(([^()]*)\)[ ]*\(.*\)/P["\1"]="\2"\ +D["\1"]=" \3\\\\\\n"\\/p +t cont +s/^ \('"$ac_word_re"'\)[ ]*\(.*\)/D["\1"]=" \2\\\\\\n"\\/p +t cont +d +:cont +n +s/.\{148\}/&'"$ac_delim"'/g +t clear +:clear +s/\\$// +t bsnlc +s/["\\]/\\&/g; s/^/"/; s/$/"/p +d +:bsnlc +s/["\\]/\\&/g; s/^/"/; s/$/\\\\\\n"\\/p +b cont +' >$CONFIG_STATUS || ac_write_fail=1 + +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 + for (key in D) D_is_set[key] = 1 + FS = "" +} +/^[\t ]*#[\t ]*(define|undef)[\t ]+$ac_word_re([\t (]|\$)/ { + line = \$ 0 + split(line, arg, " ") + if (arg[1] == "#") { + defundef = arg[2] + mac1 = arg[3] + } else { + defundef = substr(arg[1], 2) + mac1 = arg[2] + } + split(mac1, mac2, "(") #) + macro = mac2[1] + prefix = substr(line, 1, index(line, defundef) - 1) + if (D_is_set[macro]) { + # Preserve the white space surrounding the "#". + print prefix "define", macro P[macro] D[macro] + next + } else { + # Replace #undef with comments. This is necessary, for example, + # in the case of _POSIX_SOURCE, which is predefined and required + # on some systems where configure will not decide to define it. + if (defundef == "undef") { + print "/*", prefix defundef, macro, "*/" + next + } + } +} +{ print } +_ACAWK +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 + as_fn_error $? "could not setup config headers machinery" "$LINENO" 5 +fi # test -n "$CONFIG_HEADERS" + + +eval set X " :F $CONFIG_FILES :H $CONFIG_HEADERS " +shift +for ac_tag +do + case $ac_tag in + :[FHLC]) ac_mode=$ac_tag; continue;; + esac + case $ac_mode$ac_tag in + :[FHL]*:*);; + :L* | :C*:*) as_fn_error $? "invalid tag \`$ac_tag'" "$LINENO" 5;; + :[FH]-) ac_tag=-:-;; + :[FH]*) ac_tag=$ac_tag:$ac_tag.in;; + esac + ac_save_IFS=$IFS + IFS=: + set x $ac_tag + IFS=$ac_save_IFS + shift + ac_file=$1 + shift + + case $ac_mode in + :L) ac_source=$1;; + :[FH]) + ac_file_inputs= + for ac_f + do + case $ac_f in + -) ac_f="$ac_tmp/stdin";; + *) # Look for the file first in the build tree, then in the source tree + # (if the path is not absolute). The absolute path cannot be DOS-style, + # because $ac_f cannot contain `:'. + test -f "$ac_f" || + case $ac_f in + [\\/$]*) false;; + *) test -f "$srcdir/$ac_f" && ac_f="$srcdir/$ac_f";; + esac || + as_fn_error 1 "cannot find input file: \`$ac_f'" "$LINENO" 5;; + esac + case $ac_f in *\'*) ac_f=`$as_echo "$ac_f" | sed "s/'/'\\\\\\\\''/g"`;; esac + as_fn_append ac_file_inputs " '$ac_f'" + done + + # Let's still pretend it is `configure' which instantiates (i.e., don't + # use $as_me), people would be surprised to read: + # /* config.h. Generated by config.status. */ + configure_input='Generated from '` + $as_echo "$*" | sed 's|^[^:]*/||;s|:[^:]*/|, |g' + `' by configure.' + if test x"$ac_file" != x-; then + configure_input="$ac_file. $configure_input" + { $as_echo "$as_me:${as_lineno-$LINENO}: creating $ac_file" >&5 +$as_echo "$as_me: creating $ac_file" >&6;} + fi + # Neutralize special characters interpreted by sed in replacement strings. + case $configure_input in #( + *\&* | *\|* | *\\* ) + ac_sed_conf_input=`$as_echo "$configure_input" | + sed 's/[\\\\&|]/\\\\&/g'`;; #( + *) ac_sed_conf_input=$configure_input;; + esac + + case $ac_tag in + *:-:* | *:-) cat >"$ac_tmp/stdin" \ + || as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;; + esac + ;; + esac + + ac_dir=`$as_dirname -- "$ac_file" || +$as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$ac_file" : 'X\(//\)[^/]' \| \ + X"$ac_file" : 'X\(//\)$' \| \ + X"$ac_file" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$ac_file" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + as_dir="$ac_dir"; as_fn_mkdir_p + ac_builddir=. + +case "$ac_dir" in +.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; +*) + ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'` + # A ".." for each directory in $ac_dir_suffix. + ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` + case $ac_top_builddir_sub in + "") ac_top_builddir_sub=. ac_top_build_prefix= ;; + *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; + esac ;; +esac +ac_abs_top_builddir=$ac_pwd +ac_abs_builddir=$ac_pwd$ac_dir_suffix +# for backward compatibility: +ac_top_builddir=$ac_top_build_prefix + +case $srcdir in + .) # We are building in place. + ac_srcdir=. + ac_top_srcdir=$ac_top_builddir_sub + ac_abs_top_srcdir=$ac_pwd ;; + [\\/]* | ?:[\\/]* ) # Absolute name. + ac_srcdir=$srcdir$ac_dir_suffix; + ac_top_srcdir=$srcdir + ac_abs_top_srcdir=$srcdir ;; + *) # Relative name. + ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix + ac_top_srcdir=$ac_top_build_prefix$srcdir + ac_abs_top_srcdir=$ac_pwd/$srcdir ;; +esac +ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix + + + case $ac_mode in + :F) + # + # CONFIG_FILE + # + + case $INSTALL in + [\\/$]* | ?:[\\/]* ) ac_INSTALL=$INSTALL ;; + *) ac_INSTALL=$ac_top_build_prefix$INSTALL ;; + esac +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +# If the template does not know about datarootdir, expand it. +# FIXME: This hack should be removed a few years after 2.60. +ac_datarootdir_hack=; ac_datarootdir_seen= +ac_sed_dataroot=' +/datarootdir/ { + p + q +} +/@datadir@/p +/@docdir@/p +/@infodir@/p +/@localedir@/p +/@mandir@/p' +case `eval "sed -n \"\$ac_sed_dataroot\" $ac_file_inputs"` in +*datarootdir*) ac_datarootdir_seen=yes;; +*@datadir@*|*@docdir@*|*@infodir@*|*@localedir@*|*@mandir@*) + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5 +$as_echo "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;} +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 + ac_datarootdir_hack=' + s&@datadir@&$datadir&g + s&@docdir@&$docdir&g + s&@infodir@&$infodir&g + s&@localedir@&$localedir&g + s&@mandir@&$mandir&g + s&\\\${datarootdir}&$datarootdir&g' ;; +esac +_ACEOF + +# Neutralize VPATH when `$srcdir' = `.'. +# Shell code in configure.ac might set extrasub. +# FIXME: do we really want to maintain this feature? +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +ac_sed_extra="$ac_vpsub +$extrasub +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +:t +/@[a-zA-Z_][a-zA-Z_0-9]*@/!b +s|@configure_input@|$ac_sed_conf_input|;t t +s&@top_builddir@&$ac_top_builddir_sub&;t t +s&@top_build_prefix@&$ac_top_build_prefix&;t t +s&@srcdir@&$ac_srcdir&;t t +s&@abs_srcdir@&$ac_abs_srcdir&;t t +s&@top_srcdir@&$ac_top_srcdir&;t t +s&@abs_top_srcdir@&$ac_abs_top_srcdir&;t t +s&@builddir@&$ac_builddir&;t t +s&@abs_builddir@&$ac_abs_builddir&;t t +s&@abs_top_builddir@&$ac_abs_top_builddir&;t t +s&@INSTALL@&$ac_INSTALL&;t t +$ac_datarootdir_hack +" +eval sed \"\$ac_sed_extra\" "$ac_file_inputs" | $AWK -f "$ac_tmp/subs.awk" \ + >$ac_tmp/out || as_fn_error $? "could not create $ac_file" "$LINENO" 5 + +test -z "$ac_datarootdir_hack$ac_datarootdir_seen" && + { ac_out=`sed -n '/\${datarootdir}/p' "$ac_tmp/out"`; test -n "$ac_out"; } && + { ac_out=`sed -n '/^[ ]*datarootdir[ ]*:*=/p' \ + "$ac_tmp/out"`; test -z "$ac_out"; } && + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file contains a reference to the variable \`datarootdir' +which seems to be undefined. Please make sure it is defined" >&5 +$as_echo "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir' +which seems to be undefined. Please make sure it is defined" >&2;} + + rm -f "$ac_tmp/stdin" + case $ac_file in + -) cat "$ac_tmp/out" && rm -f "$ac_tmp/out";; + *) rm -f "$ac_file" && mv "$ac_tmp/out" "$ac_file";; + esac \ + || as_fn_error $? "could not create $ac_file" "$LINENO" 5 + ;; + :H) + # + # CONFIG_HEADER + # + if test x"$ac_file" != x-; then + { + $as_echo "/* $configure_input */" \ + && eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs" + } >"$ac_tmp/config.h" \ + || as_fn_error $? "could not create $ac_file" "$LINENO" 5 + if diff "$ac_file" "$ac_tmp/config.h" >/dev/null 2>&1; then + { $as_echo "$as_me:${as_lineno-$LINENO}: $ac_file is unchanged" >&5 +$as_echo "$as_me: $ac_file is unchanged" >&6;} + else + rm -f "$ac_file" + mv "$ac_tmp/config.h" "$ac_file" \ + || as_fn_error $? "could not create $ac_file" "$LINENO" 5 + fi + else + $as_echo "/* $configure_input */" \ + && eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs" \ + || as_fn_error $? "could not create -" "$LINENO" 5 + fi + ;; + + + esac + +done # for ac_tag + + +as_fn_exit 0 +_ACEOF +ac_clean_files=$ac_clean_files_save + +test $ac_write_fail = 0 || + as_fn_error $? "write failure creating $CONFIG_STATUS" "$LINENO" 5 + + +# configure is writing to config.log, and then calls config.status. +# config.status does its own redirection, appending to config.log. +# Unfortunately, on DOS this fails, as config.log is still kept open +# by configure, so config.status won't be able to write to it; its +# output is simply discarded. So we exec the FD to /dev/null, +# effectively closing config.log, so it can be properly (re)opened and +# appended to by config.status. When coming back to configure, we +# need to make the FD available again. +if test "$no_create" != yes; then + ac_cs_success=: + ac_config_status_args= + test "$silent" = yes && + ac_config_status_args="$ac_config_status_args --quiet" + exec 5>/dev/null + $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false + exec 5>>config.log + # Use ||, not &&, to avoid exiting from the if with $? = 1, which + # would make configure fail if this is the last instruction. + $ac_cs_success || as_fn_exit 1 +fi +if test -n "$ac_unrecognized_opts" && test "$enable_option_checking" != no; then + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: unrecognized options: $ac_unrecognized_opts" >&5 +$as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2;} +fi + diff --git a/xar/configure.ac b/xar/configure.ac new file mode 100644 index 0000000..3a36f42 --- /dev/null +++ b/xar/configure.ac @@ -0,0 +1,361 @@ +AC_PREREQ(2.59) +AC_INIT([Xar], [1.8dev], [xar-devel@googlegroups.com], [xar]) +AC_CONFIG_SRCDIR([LICENSE]) + +dnl Revision number for libxar. +LIB_REV=1 +AC_SUBST([LIB_REV]) + +dnl xar version variables. +XAR_MAJOR_VERSION="1" +XAR_MINOR_VERSION="8dev" +XAR_VERSION="${XAR_MAJOR_VERSION}.${XAR_MINOR_VERSION}" +AC_SUBST([XAR_MAJOR_VERSION]) +AC_SUBST([XAR_MINOR_VERSION]) +AC_SUBST([XAR_VERSION]) + +dnl +dnl Various paths. +dnl +srcroot=$srcdir +if test "x${srcroot}" = "x." ; then + srcroot="" +else + srcroot="${srcroot}/" +fi +AC_SUBST([srcroot]) +abs_srcroot="`cd "$srcdir"; pwd`/" +AC_SUBST([abs_srcroot]) + +objroot="" +AC_SUBST([objroot]) +abs_objroot="`pwd`/" +AC_SUBST([abs_objroot]) + +dnl Set install paths. +if test "x$prefix" = "xNONE" ; then + prefix="/usr/local" +fi +if test "x$exec_prefix" = "xNONE" ; then + exec_prefix=$prefix +fi +PREFIX=$prefix +AC_SUBST([PREFIX]) +BINDIR=`eval echo $bindir` +BINDIR=`eval echo $BINDIR` +AC_SUBST([BINDIR]) +DATADIR=`eval echo $datadir` +DATADIR=`eval echo $DATADIR` +AC_SUBST([DATADIR]) +LIBDIR=`eval echo $libdir` +LIBDIR=`eval echo $LIBDIR` +AC_SUBST([LIBDIR]) +INCLUDEDIR=`eval echo $includedir` +INCLUDEDIR=`eval echo $INCLUDEDIR` +AC_SUBST([INCLUDEDIR]) +MANDIR=`eval echo $mandir` +MANDIR=`eval echo $MANDIR` +AC_SUBST([MANDIR]) + +cfgoutputs="cfgoutputs.stamp" +cfgoutputs="${cfgoutputs} Makefile" +cfgoutputs="${cfgoutputs} include/xar.h" +cfgoutputs="${cfgoutputs} lib/Makefile.inc" +cfgoutputs="${cfgoutputs} lib/libxar.la.in" +cfgoutputs="${cfgoutputs} src/Makefile.inc" +cfgoutputs="${cfgoutputs} xar.spec" + +cfghdrs="${objroot}cfghdrs.stamp" +cfghdrs="${cfghdrs} ${objroot}include/config.h" + +dnl If CFLAGS isn't defined and using gcc, set CFLAGS to something reasonable. +dnl Otherwise, just prevent autoconf from molesting CFLAGS. +CFLAGS=$CFLAGS +AC_PROG_CC +AC_SYS_LARGEFILE +if test "x$CFLAGS" = "x" ; then + no_CFLAGS="yes" +fi +if test "x$no_CFLAGS" = "xyes" -a "x$GCC" = "xyes" ; then + CFLAGS="-Wall -g" +fi +dnl Append EXTRA_CFLAGS to CFLAGS, if defined. +if test "x$EXTRA_CFLAGS" != "x" ; then + CFLAGS="$CFLAGS $EXTRA_CFLAGS" +fi +AC_PROG_CPP + +AC_PROG_INSTALL +AC_PATH_PROG([LD], [ld], , [$PATH]) +AC_PATH_PROG([AR], [ar], , [$PATH]) +AC_PATH_PROG([RANLIB], [ranlib], , [$PATH]) +AC_PATH_PROG([AUTOCONF], [autoconf], , [$PATH]) + +dnl Some libtool envy +#AC_ENABLE_SHARED +AC_MSG_CHECKING([whether to build shared libraries]) +AC_ARG_ENABLE([shared], + [AC_HELP_STRING([--enable-shared], + [build shared libraries @<:@default=yes@:>@])], + [shared=$enableval],[shared=yes]) +AC_MSG_RESULT($shared) +AC_SUBST([shared]) +#AC_ENABLE_STATIC +AC_MSG_CHECKING([whether to build static libraries]) +AC_ARG_ENABLE([static], + [AC_HELP_STRING([--enable-static], + [build static libraries @<:@default=yes@:>@])], + [static=$enableval],[static=yes]) +AC_MSG_RESULT($static) +AC_SUBST([static]) +# Make sure either enable_shared or enable_static is yes. +test "$shared" = "yes" || test "$static" = "yes" + +dnl Platform-specific settings. abi and RPATH can probably be determined +dnl programmatically, but doing so is error-prone, which makes it generally +dnl not worth the trouble. +dnl +dnl Define cpp macros in CPPFLAGS, rather than doing AC_DEFINE(macro), since the +dnl definitions need to be seen before and headers are included, which is a pain +dnl to make happen otherwise. +AC_CANONICAL_HOST +case "${host}" in + *-*-darwin*) + abi="macho" + RPATH="" + ;; + *-*-freebsd*) + CFLAGS="$CFLAGS" + abi="elf" + RPATH="-Wl,-rpath," + ;; + *-*-linux*) + CFLAGS="$CFLAGS" + abi="elf" + dnl Linux needs this for things like asprintf() and poll() flags. + CPPFLAGS="$CPPFLAGS -D_GNU_SOURCE" + RPATH="-Wl,-rpath," + ;; + *-*-netbsd*) + AC_MSG_CHECKING([ABI]) + AC_COMPILE_IFELSE([AC_LANG_PROGRAM( +[[#ifdef __ELF__ +/* ELF */ +#else +#error aout +#endif +]])], + [CFLAGS="$CFLAGS"; abi="elf"], + [abi="aout"]) + AC_MSG_RESULT([$abi]) + RPATH="-Wl,-rpath," + ;; + *-*-solaris2*) + CFLAGS="$CFLAGS" + abi="elf" + RPATH="-Wl,-R," + dnl XXX Remove the following if it ends up not being useful. + dnl Solaris needs this for sigwait(). + dnl CPPFLAGS="$CPPFLAGS -D_POSIX_PTHREAD_SEMANTICS" + dnl LIBS="$LIBS -lposix4 -lsocket -lnsl" + ;; + *) + AC_MSG_RESULT([Unsupported operating system: ${host}]) + abi="elf" + RPATH="-Wl,-rpath," + ;; +esac +AC_SUBST([abi]) +AC_SUBST([RPATH]) + +dnl Disable rules that do automatic regeneration of configure output by default. +AC_ARG_ENABLE([autogen], + [ --enable-autogen Automatically regenerate configure output], +[if test "x$enable_autogen" = "xno" ; then + enable_autogen="0" +else + enable_autogen="1" +fi +], +[enable_autogen="0"] +) +AC_SUBST([enable_autogen]) + +AC_TRY_COMPILE([#include +#include ], [acl_t a], [AC_DEFINE([HAVE_SYS_ACL_H],[1], [define if you have sys/acl.h and it has a working acl_t type])]) +AC_CHECK_HEADERS(ext2fs/ext2_fs.h sys/statfs.h sys/xattr.h sys/param.h sys/extattr.h libutil.h) +AC_CHECK_FUNCS(lgetxattr) +AC_CHECK_FUNCS(lsetxattr) +AC_CHECK_FUNCS(getxattr) +AC_CHECK_FUNCS(setxattr) +AC_CHECK_FUNCS(getattrlist) +AC_CHECK_FUNCS(setattrlist) +AC_CHECK_FUNCS(lchmod) +AC_CHECK_FUNCS(lchown) +AC_CHECK_FUNCS(chflags) +AC_CHECK_FUNCS(statvfs) +AC_CHECK_FUNCS(statfs) +AC_CHECK_FUNCS(strmode) + +AC_CHECK_MEMBERS([struct statfs.f_fstypename],,,[#include +#include +#include ]) +AC_CHECK_MEMBERS([struct statvfs.f_fstypename],,,[#include ]) +AC_CHECK_MEMBERS([struct stat.st_flags]) + +AC_CHECK_SIZEOF(uid_t) +if test $ac_cv_sizeof_uid_t = "4"; then +AC_DEFINE(UID_STRING, RId32) +AC_DEFINE(UID_CAST, (uint32_t)) +elif test $ac_cv_sizeof_uid_t = "8"; then +AC_DEFINE(UID_STRING, PRId64) +AC_DEFINE(UID_CAST, (uint64_t)) +else +AC_ERROR(can not detect the size of your system's uid_t type) +fi + +AC_CHECK_SIZEOF(gid_t) +if test $ac_cv_sizeof_gid_t = "4"; then +AC_DEFINE(GID_STRING, PRId32) +AC_DEFINE(GID_CAST, (uint32_t)) +elif test $ac_cv_sizeof_gid_t = "8"; then +AC_DEFINE(GID_STRING, PRId64) +AC_DEFINE(GID_CAST, (uint64_t)) +else +AC_ERROR(can not detect the size of your system's gid_t type) +fi + +AC_CHECK_SIZEOF(ino_t) +if test $ac_cv_sizeof_ino_t = "4"; then +AC_DEFINE(INO_STRING, PRId32) +AC_DEFINE(INO_HEXSTRING, PRIx32) +AC_DEFINE(INO_CAST, (uint32_t)) +elif test $ac_cv_sizeof_ino_t = "8"; then +AC_DEFINE(INO_STRING, PRId64) +AC_DEFINE(INO_HEXSTRING, PRIx64) +AC_DEFINE(INO_CAST, (uint64_t)) +else +AC_ERROR(can not detect the size of your system's ino_t type) +fi + +AC_CHECK_SIZEOF(dev_t) +if test $ac_cv_sizeof_dev_t = "4"; then +AC_DEFINE(DEV_STRING, PRId32) +AC_DEFINE(DEV_HEXSTRING, PRIx32) +AC_DEFINE(DEV_CAST, (uint32_t)) +elif test $ac_cv_sizeof_dev_t = "8"; then +AC_DEFINE(DEV_STRING, PRId64) +AC_DEFINE(DEV_HEXSTRING, PRIx64) +AC_DEFINE(DEV_CAST, (uint64_t)) +else +AC_ERROR(can not detect the size of your system's dev_t type) +fi + +AC_CHECK_LIB(acl, acl_get_file) + +dnl Check for paths +AC_PREFIX_DEFAULT(/usr/local) + +AC_CHECK_FUNC([asprintf], AC_DEFINE([HAVE_ASPRINTF])) + +dnl +dnl Configure libxml2. +dnl +LIBXML2_VERSION_MIN=2.6.11 + +have_libxml2="1" + +AC_ARG_WITH([xml2-config], [ --with-xml2-config libxml2 config program], +if test "x${with_xml2_config}" = "xno" ; then + XML2_CONFIG= +else + XML2_CONFIG="${with_xml2_config}" +fi +, + XML2_CONFIG= +) +if test "x${XML2_CONFIG}" != "x" ; then + if test ! -x "${XML2_CONFIG}" ; then + AC_MSG_ERROR([Unusable or missing xml2-config: ${XML2_CONFIG}]) + fi +else + AC_PATH_PROG([XML2_CONFIG], [xml2-config], , [${PATH}]) + if test "x${XML2_CONFIG}" = "x" ; then + AC_MSG_ERROR([Cannot configure without xml2-config]) + fi +fi + +dnl Make sure the version of libxml2 found is sufficient. +AC_MSG_CHECKING([for libxml >= ${LIBXML2_VERSION_MIN}]) +LIBXML2_FOUND=`2>&1 ${XML2_CONFIG} --version` +LIBXML2_MAJOR=`echo ${LIBXML2_FOUND} | tr . " " | awk '{print $1}'` +LIBXML2_MINOR=`echo ${LIBXML2_FOUND} | tr . " " | awk '{print $2}' | tr a-z " " |awk '{print $1}'` +LIBXML2_BRANCH=`echo ${LIBXML2_FOUND} | tr . " " | awk '{print $3}' | tr a-z " " |awk '{print $1}'` +if test "x${LIBXML2_BRANCH}" = "x" ; then + LIBXML2_BRANCH=0 +fi +LIBXML2_MAJOR_MIN=`echo ${LIBXML2_VERSION_MIN} | tr . " " | awk '{print $1}'` +LIBXML2_MINOR_MIN=`echo ${LIBXML2_VERSION_MIN} | tr . " " | awk '{print $2}'` +LIBXML2_BRANCH_MIN=`echo ${LIBXML2_VERSION_MIN} | tr . " " | awk '{print $3}'` +if test ${LIBXML2_MAJOR} -gt ${LIBXML2_MAJOR_MIN} \ + -o ${LIBXML2_MAJOR} -eq ${LIBXML2_MAJOR_MIN} \ + -a ${LIBXML2_MINOR} -gt ${LIBXML2_MINOR_MIN} \ + -o ${LIBXML2_MAJOR} -eq ${LIBXML2_MAJOR_MIN} \ + -a ${LIBXML2_MINOR} -eq ${LIBXML2_MINOR_MIN} \ + -a ${LIBXML2_BRANCH} -ge $LIBXML2_BRANCH_MIN ; then + AC_MSG_RESULT([${LIBXML2_MAJOR}.${LIBXML2_MINOR}.${LIBXML2_BRANCH}]) + have_libxml2="1" + CPPFLAGS="${CPPFLAGS} `${XML2_CONFIG} --cflags`" + LIBS="${LIBS} `${XML2_CONFIG} --libs`" +else + AC_MSG_RESULT([no]) + have_libxml2="0" +fi +if test "x${have_libxml2}" = "x1" ; then + dnl Final sanity check, to make sure that xmlwriter is present. + AC_CHECK_HEADER([libxml/xmlwriter.h], , [have_libxml2="0"]) +fi +if test "x${have_libxml2}" = "x0" ; then + AC_MSG_ERROR([Cannot build without libxml2]) +fi + +dnl +dnl Configure libz. +dnl +have_libz="1" +AC_CHECK_HEADERS([zlib.h], , [have_libz="0"]) +AC_CHECK_LIB([z], [deflate], , [have_libz="0"]) +if test "x${have_libz}" = "x0" ; then + AC_MSG_ERROR([Cannot build without libz]) +fi + +dnl +dnl Configure libbz2. +dnl +have_libbz2="1" +AC_CHECK_HEADERS([bzlib.h], , [have_libbz2="0"]) +AC_CHECK_LIB([bz2], [BZ2_bzCompress], , [have_libbz2="0"]) +if test "x${have_libbz2}" = "x1" ; then + AC_DEFINE([HAVE_LIBBZ2]) +fi + +dnl +dnl Configure libpthread. +dnl +have_libpthread="1" +AC_CHECK_HEADERS([pthread.h], , [have_pthread="0"]) +AC_CHECK_LIB([pthread], [pthread_mutex_lock], , [have_pthread="0"]) +if test "x${have_pthread}" = "x1" ; then + AC_DEFINE([HAVE_PTHREAD]) +fi + +dnl +dnl Process .in files. +dnl +AC_SUBST([cfghdrs]) +AC_CONFIG_HEADER([$cfghdrs]) + +AC_SUBST([cfgoutputs]) +AC_CONFIG_FILES([$cfgoutputs]) + +AC_OUTPUT diff --git a/xar/include/.cvsignore b/xar/include/.cvsignore new file mode 100644 index 0000000..38cdfa7 --- /dev/null +++ b/xar/include/.cvsignore @@ -0,0 +1,2 @@ +config.h +xar.h diff --git a/xar/include/config.h b/xar/include/config.h new file mode 100644 index 0000000..efc9d1a --- /dev/null +++ b/xar/include/config.h @@ -0,0 +1,37 @@ +/* include/config.h. Generated from config.h.in by configure. */ +/* #undef HAVE_SYS_STATFS_H */ +#define HAVE_SYS_XATTR_H 1 +/* #undef HAVE_SYS_EXTATTR_H */ +#define HAVE_SYS_PARAM_H 1 +/* #undef HAVE_LGETXATTR */ +/* #undef HAVE_LSETXATTR */ +#define HAVE_GETXATTR 1 +#define HAVE_SETXATTR 1 +#define HAVE_GETATTRLIST 1 +#define HAVE_SETATTRLIST 1 +#define HAVE_CHFLAGS 1 +#define HAVE_STATVFS 1 +#define HAVE_STATFS 1 +/* #undef HAVE_EXT2FS_EXT2_FS_H */ +#define HAVE_STRUCT_STAT_ST_FLAGS 1 +/* #undef HAVE_STRUCT_STATVFS_F_FSTYPENAME */ +#define HAVE_STRUCT_STATFS_F_FSTYPENAME 1 +#define HAVE_SYS_ACL_H 1 +/* #undef HAVE_LIBUTIL_H */ +#define HAVE_LIBPTHREAD 1 +#define HAVE_ASPRINTF 1 +#define HAVE_LIBBZ2 1 +/* #undef HAVE_LIBLZMA */ +#define HAVE_LCHOWN 1 +#define HAVE_LCHMOD 1 +#define HAVE_STRMODE 1 +#define UID_STRING RId32 +#define UID_CAST (uint32_t) +#define GID_STRING PRId32 +#define GID_CAST (uint32_t) +#define INO_STRING PRId64 +#define INO_HEXSTRING PRIx64 +#define INO_CAST (uint64_t) +#define DEV_STRING PRId32 +#define DEV_HEXSTRING PRIx32 +#define DEV_CAST (uint32_t) diff --git a/xar/include/config.h.in b/xar/include/config.h.in new file mode 100644 index 0000000..2bb997b --- /dev/null +++ b/xar/include/config.h.in @@ -0,0 +1,36 @@ +#undef HAVE_SYS_STATFS_H +#undef HAVE_SYS_XATTR_H +#undef HAVE_SYS_EXTATTR_H +#undef HAVE_SYS_PARAM_H +#undef HAVE_LGETXATTR +#undef HAVE_LSETXATTR +#undef HAVE_GETXATTR +#undef HAVE_SETXATTR +#undef HAVE_GETATTRLIST +#undef HAVE_SETATTRLIST +#undef HAVE_CHFLAGS +#undef HAVE_STATVFS +#undef HAVE_STATFS +#undef HAVE_EXT2FS_EXT2_FS_H +#undef HAVE_STRUCT_STAT_ST_FLAGS +#undef HAVE_STRUCT_STATVFS_F_FSTYPENAME +#undef HAVE_STRUCT_STATFS_F_FSTYPENAME +#undef HAVE_SYS_ACL_H +#undef HAVE_LIBUTIL_H +#undef HAVE_LIBPTHREAD +#undef HAVE_ASPRINTF +#undef HAVE_LIBBZ2 +#undef HAVE_LIBLZMA +#undef HAVE_LCHOWN +#undef HAVE_LCHMOD +#undef HAVE_STRMODE +#undef UID_STRING +#undef UID_CAST +#undef GID_STRING +#undef GID_CAST +#undef INO_STRING +#undef INO_HEXSTRING +#undef INO_CAST +#undef DEV_STRING +#undef DEV_HEXSTRING +#undef DEV_CAST diff --git a/xar/include/xar.h b/xar/include/xar.h new file mode 100644 index 0000000..a0af6aa --- /dev/null +++ b/xar/include/xar.h @@ -0,0 +1,268 @@ +/* + * Copyright (c) 2005 Rob Braun + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Rob Braun nor the names of his contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +/* + * 03-Apr-2005 + * DRI: Rob Braun + */ +/* + * Portions Copyright 2006, Apple Computer, Inc. + * Christopher Ryan + */ + +#ifndef _XAR_H_ +#define _XAR_H_ + +#if __cplusplus +extern "C" { +#endif + +#define XAR_VERSION "1.8dev" + +#include +#include +#include + +#pragma pack(4) + +struct xar_header { + uint32_t magic; + uint16_t size; + uint16_t version; + uint64_t toc_length_compressed; + uint64_t toc_length_uncompressed; + uint32_t cksum_alg; +}; +#pragma pack() +typedef struct xar_header xar_header_t; + +#define XAR_HEADER_MAGIC 0x78617221 +#define XAR_EA_FORK "ea" + +/* NONE is not supported for security reasons, and may not be supported by all implementations */ +#define XAR_CKSUM_NONE 0 +#define XAR_CKSUM_SHA1 1 +/* MD5 is not supported for security reasons, and may not be supported by all implementations */ +#define XAR_CKSUM_MD5 2 +#define XAR_CKSUM_SHA256 3 +#define XAR_CKSUM_SHA512 4 + +typedef void *xar_errctx_t; +typedef const struct __xar_file_t *xar_file_t; +typedef const struct __xar_iter_t *xar_iter_t; +typedef const struct __xar_t *xar_t; +typedef const struct __xar_subdoc_t *xar_subdoc_t; +typedef const struct __xar_signature_t *xar_signature_t; + +typedef struct { + char *next_out; + unsigned int avail_out; + + unsigned long long total_in; + unsigned long long total_out; + + void *state; +} xar_stream; + +typedef int32_t (*err_handler)(int32_t severit, int32_t instance, xar_errctx_t ctx, void *usrctx); +/* the signed_data must be allocated durring the callback and will be released by the xar lib after the callback */ +typedef int32_t (*xar_signer_callback)(xar_signature_t sig, void *context, uint8_t *data, uint32_t length, uint8_t **signed_data, uint32_t *signed_len); +typedef void (*xar_progress_callback)(xar_t x, xar_file_t f, size_t sizeread); + +#define READ 0 +#define WRITE 1 + +/* xar stream return codes */ +#define XAR_STREAM_OK 0 +#define XAR_STREAM_END 1 +#define XAR_STREAM_ERR -1 + +/* Valid xar options & values */ +#define XAR_OPT_OWNERSHIP "ownership" /* setting owner/group behavior */ +#define XAR_OPT_VAL_SYMBOLIC "symbolic" /* set owner/group based on names */ +#define XAR_OPT_VAL_NUMERIC "numeric" /* set owner/group based on uid/gid */ + +#define XAR_OPT_TOCCKSUM "toc-cksum" /* set the toc checksum algorithm */ +#define XAR_OPT_FILECKSUM "file-chksum" /* set the file checksum algorithm */ +#define XAR_OPT_VAL_NONE "none" +#define XAR_OPT_VAL_SHA1 "sha1" +#define XAR_OPT_VAL_SHA256 "sha256" +#define XAR_OPT_VAL_SHA512 "sha512" +/* MD5 is not recommended for security reasons, and may not be supported by all implementations */ +#define XAR_OPT_VAL_MD5 "md5" + +#define XAR_OPT_COMPRESSION "compression" /* set the file compression type */ +#define XAR_OPT_COMPRESSIONARG "compression-arg" /* set the compression opts */ +#define XAR_OPT_VAL_GZIP "gzip" +#define XAR_OPT_VAL_BZIP "bzip2" +#define XAR_OPT_VAL_LZMA "lzma" + +#define XAR_OPT_RSIZE "rsize" /* Read io buffer size */ + +#define XAR_OPT_COALESCE "coalesce" /* Coalesce identical heap blocks */ +#define XAR_OPT_LINKSAME "linksame" /* Hardlink identical files */ + +#define XAR_OPT_PROPINCLUDE "prop-include" /* File property to include */ +#define XAR_OPT_PROPEXCLUDE "prop-exclude" /* File property to exclude */ + +#define XAR_OPT_SAVESUID "savesuid" /* Preserve setuid/setgid bits */ +#define XAR_OPT_VAL_TRUE "true" +#define XAR_OPT_VAL_FALSE "false" + +/* xar signing algorithms */ +#define XAR_SIG_SHA1RSA 1 + + +/* xar error handler macros */ +#define XAR_SEVERITY_DEBUG 1 +#define XAR_SEVERITY_INFO 2 +#define XAR_SEVERITY_NORMAL 3 +#define XAR_SEVERITY_WARNING 4 +#define XAR_SEVERITY_NONFATAL 5 +#define XAR_SEVERITY_FATAL 6 + +#define XAR_ERR_ARCHIVE_CREATION 1 +#define XAR_ERR_ARCHIVE_EXTRACTION 2 + +xar_t xar_open(const char *file, int32_t flags); +xar_t xar_open_digest_verify(const char *file, int32_t flags, void *expected_toc_digest, size_t expected_toc_digest_len); +int xar_close(xar_t x); + +xar_header_t xar_header_get(xar_t x); + +xar_file_t xar_add(xar_t x, const char *path); +xar_file_t xar_add_frombuffer(xar_t x, xar_file_t parent, const char *name, char *buffer, size_t length); +xar_file_t xar_add_folder(xar_t x, xar_file_t f, const char *name, struct stat *info); +xar_file_t xar_add_frompath(xar_t x, xar_file_t parent, const char *name, const char *realpath); + +xar_file_t xar_add_from_archive(xar_t x, xar_file_t parent, const char *name, xar_t sourcearchive, xar_file_t sourcefile); + +int32_t xar_extract(xar_t x, xar_file_t f); +int32_t xar_extract_tofile(xar_t x, xar_file_t f, const char *path); +int32_t xar_extract_tobuffer(xar_t x, xar_file_t f, char **buffer); +int32_t xar_extract_tobuffersz(xar_t x, xar_file_t f, char **buffer, size_t *size); +int32_t xar_extract_tostream_init(xar_t x, xar_file_t f, xar_stream *stream); +int32_t xar_extract_tostream(xar_stream *stream); +int32_t xar_extract_tostream_end(xar_stream *stream); + +int32_t xar_verify(xar_t x, xar_file_t f); +int32_t xar_verify_progress(xar_t x, xar_file_t f, xar_progress_callback progress); + +/* To get the checksum of the table of contents use this function. + * The function returns a alloced buffer that caller must free. */ +void* xar_get_toc_checksum(xar_t x, size_t* buffer_size); + +/* Returns XAR_CKSUM_* that maps to the type of the checksum. */ +int32_t xar_get_toc_checksum_type(xar_t x); + +const char *xar_opt_get(xar_t x, const char *option); +int32_t xar_opt_set(xar_t x, const char *option, const char *value); +int32_t xar_opt_unset(xar_t x, const char *option); + +int32_t xar_prop_set(xar_file_t f, const char *key, const char *value); +int32_t xar_prop_create(xar_file_t f, const char *key, const char *value); +int32_t xar_prop_get(xar_file_t f, const char *key, const char **value); + +xar_iter_t xar_iter_new(void); +void xar_iter_free(xar_iter_t i); + +const char *xar_prop_first(xar_file_t f, xar_iter_t i); +const char *xar_prop_next(xar_iter_t i); + +void xar_prop_unset(xar_file_t f, const char *key); +xar_file_t xar_file_first(xar_t x, xar_iter_t i); +xar_file_t xar_file_next(xar_iter_t i); + +const char *xar_attr_get(xar_file_t f, const char *prop, const char *key); +int32_t xar_attr_set(xar_file_t f, const char *prop, const char *key, const char *value); +const char *xar_attr_first(xar_file_t f, const char *prop, xar_iter_t i); +const char *xar_attr_next(xar_iter_t i); + +xar_subdoc_t xar_subdoc_new(xar_t x, const char *name); +int32_t xar_subdoc_prop_set(xar_subdoc_t s, const char *key, const char *value); +int32_t xar_subdoc_prop_get(xar_subdoc_t s, const char *key, const char **value); +int32_t xar_subdoc_attr_set(xar_subdoc_t s, const char *prop, const char *key, const char *value); +const char *xar_subdoc_attr_get(xar_subdoc_t s, const char *prop, const char *key); +xar_subdoc_t xar_subdoc_first(xar_t x); +xar_subdoc_t xar_subdoc_next(xar_subdoc_t s); +const char *xar_subdoc_name(xar_subdoc_t s); +int32_t xar_subdoc_copyout(xar_subdoc_t s, unsigned char **, unsigned int *); +int32_t xar_subdoc_copyin(xar_subdoc_t s, const unsigned char *, unsigned int); +void xar_subdoc_remove(xar_subdoc_t s); + +/* signature api for adding various signature types */ +xar_signature_t xar_signature_new(xar_t x,const char *type, int32_t length, xar_signer_callback callback, void *callback_context); +/* extended signatures are ignored by previous versions of xar */ +xar_signature_t xar_signature_new_extended(xar_t x,const char *type, int32_t length, xar_signer_callback callback, void *callback_context); + +const char *xar_signature_type(xar_signature_t s); + +xar_signature_t xar_signature_first(xar_t x); +xar_signature_t xar_signature_next(xar_signature_t s); + +int32_t xar_signature_add_x509certificate(xar_signature_t sig, const uint8_t *cert_data, uint32_t cert_len ); + +int32_t xar_signature_get_x509certificate_count(xar_signature_t sig); +int32_t xar_signature_get_x509certificate_data(xar_signature_t sig, int32_t index, const uint8_t **cert_data, uint32_t *cert_len); + +uint8_t xar_signature_copy_signed_data(xar_signature_t sig, uint8_t **data, uint32_t *length, uint8_t **signed_data, uint32_t *signed_length, off_t *signed_offset); + +/* Helper functions - caller must free returned memory */ +char *xar_get_size(xar_t x, xar_file_t f); +char *xar_get_type(xar_t x, xar_file_t f); +char *xar_get_mode(xar_t x, xar_file_t f); +char *xar_get_owner(xar_t x, xar_file_t f); +char *xar_get_group(xar_t x, xar_file_t f); +char *xar_get_mtime(xar_t x, xar_file_t f); + +/* For helping calling apps harden against hacked archives that attempt to escape their extraction roots. */ +int xar_path_issane(char* path); + +/* These are for xar modules and should never be needed from a calling app */ +void xar_register_errhandler(xar_t x, err_handler callback, void *usrctx); +xar_t xar_err_get_archive(xar_errctx_t ctx); +xar_file_t xar_err_get_file(xar_errctx_t ctx); +const char *xar_err_get_string(xar_errctx_t ctx); +int xar_err_get_errno(xar_errctx_t ctx); +void xar_err_set_file(xar_t x, xar_file_t f); +void xar_err_set_formatted_string(xar_t x, const char *format, ...); +void xar_err_set_string(xar_t x, const char *str); +void xar_err_set_errno(xar_t x, int e); +void xar_err_new(xar_t x); +int32_t xar_err_callback(xar_t x, int32_t sev, int32_t err); + +void xar_serialize(xar_t x, const char *file); +char *xar_get_path(xar_file_t f); +off_t xar_get_heap_offset(xar_t x); +uint64_t xar_ntoh64(uint64_t num); + +#if __cplusplus +} +#endif + +#endif /* _XAR_H_ */ diff --git a/xar/include/xar.h.in b/xar/include/xar.h.in new file mode 100644 index 0000000..2005db8 --- /dev/null +++ b/xar/include/xar.h.in @@ -0,0 +1,268 @@ +/* + * Copyright (c) 2005 Rob Braun + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Rob Braun nor the names of his contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +/* + * 03-Apr-2005 + * DRI: Rob Braun + */ +/* + * Portions Copyright 2006, Apple Computer, Inc. + * Christopher Ryan + */ + +#ifndef _XAR_H_ +#define _XAR_H_ + +#if __cplusplus +extern "C" { +#endif + +#define XAR_VERSION "@XAR_VERSION@" + +#include +#include +#include + +#pragma pack(4) + +struct xar_header { + uint32_t magic; + uint16_t size; + uint16_t version; + uint64_t toc_length_compressed; + uint64_t toc_length_uncompressed; + uint32_t cksum_alg; +}; +#pragma pack() +typedef struct xar_header xar_header_t; + +#define XAR_HEADER_MAGIC 0x78617221 +#define XAR_EA_FORK "ea" + +/* NONE is not supported for security reasons, and may not be supported by all implementations */ +#define XAR_CKSUM_NONE 0 +#define XAR_CKSUM_SHA1 1 +/* MD5 is not supported for security reasons, and may not be supported by all implementations */ +#define XAR_CKSUM_MD5 2 +#define XAR_CKSUM_SHA256 3 +#define XAR_CKSUM_SHA512 4 + +typedef void *xar_errctx_t; +typedef const struct __xar_file_t *xar_file_t; +typedef const struct __xar_iter_t *xar_iter_t; +typedef const struct __xar_t *xar_t; +typedef const struct __xar_subdoc_t *xar_subdoc_t; +typedef const struct __xar_signature_t *xar_signature_t; + +typedef struct { + char *next_out; + unsigned int avail_out; + + unsigned long long total_in; + unsigned long long total_out; + + void *state; +} xar_stream; + +typedef int32_t (*err_handler)(int32_t severit, int32_t instance, xar_errctx_t ctx, void *usrctx); +/* the signed_data must be allocated durring the callback and will be released by the xar lib after the callback */ +typedef int32_t (*xar_signer_callback)(xar_signature_t sig, void *context, uint8_t *data, uint32_t length, uint8_t **signed_data, uint32_t *signed_len); +typedef void (*xar_progress_callback)(xar_t x, xar_file_t f, size_t sizeread); + +#define READ 0 +#define WRITE 1 + +/* xar stream return codes */ +#define XAR_STREAM_OK 0 +#define XAR_STREAM_END 1 +#define XAR_STREAM_ERR -1 + +/* Valid xar options & values */ +#define XAR_OPT_OWNERSHIP "ownership" /* setting owner/group behavior */ +#define XAR_OPT_VAL_SYMBOLIC "symbolic" /* set owner/group based on names */ +#define XAR_OPT_VAL_NUMERIC "numeric" /* set owner/group based on uid/gid */ + +#define XAR_OPT_TOCCKSUM "toc-cksum" /* set the toc checksum algorithm */ +#define XAR_OPT_FILECKSUM "file-chksum" /* set the file checksum algorithm */ +#define XAR_OPT_VAL_NONE "none" +#define XAR_OPT_VAL_SHA1 "sha1" +#define XAR_OPT_VAL_SHA256 "sha256" +#define XAR_OPT_VAL_SHA512 "sha512" +/* MD5 is not recommended for security reasons, and may not be supported by all implementations */ +#define XAR_OPT_VAL_MD5 "md5" + +#define XAR_OPT_COMPRESSION "compression" /* set the file compression type */ +#define XAR_OPT_COMPRESSIONARG "compression-arg" /* set the compression opts */ +#define XAR_OPT_VAL_GZIP "gzip" +#define XAR_OPT_VAL_BZIP "bzip2" +#define XAR_OPT_VAL_LZMA "lzma" + +#define XAR_OPT_RSIZE "rsize" /* Read io buffer size */ + +#define XAR_OPT_COALESCE "coalesce" /* Coalesce identical heap blocks */ +#define XAR_OPT_LINKSAME "linksame" /* Hardlink identical files */ + +#define XAR_OPT_PROPINCLUDE "prop-include" /* File property to include */ +#define XAR_OPT_PROPEXCLUDE "prop-exclude" /* File property to exclude */ + +#define XAR_OPT_SAVESUID "savesuid" /* Preserve setuid/setgid bits */ +#define XAR_OPT_VAL_TRUE "true" +#define XAR_OPT_VAL_FALSE "false" + +/* xar signing algorithms */ +#define XAR_SIG_SHA1RSA 1 + + +/* xar error handler macros */ +#define XAR_SEVERITY_DEBUG 1 +#define XAR_SEVERITY_INFO 2 +#define XAR_SEVERITY_NORMAL 3 +#define XAR_SEVERITY_WARNING 4 +#define XAR_SEVERITY_NONFATAL 5 +#define XAR_SEVERITY_FATAL 6 + +#define XAR_ERR_ARCHIVE_CREATION 1 +#define XAR_ERR_ARCHIVE_EXTRACTION 2 + +xar_t xar_open(const char *file, int32_t flags); +xar_t xar_open_digest_verify(const char *file, int32_t flags, void *expected_toc_digest, size_t expected_toc_digest_len); +int xar_close(xar_t x); + +xar_header_t xar_header_get(xar_t x); + +xar_file_t xar_add(xar_t x, const char *path); +xar_file_t xar_add_frombuffer(xar_t x, xar_file_t parent, const char *name, char *buffer, size_t length); +xar_file_t xar_add_folder(xar_t x, xar_file_t f, const char *name, struct stat *info); +xar_file_t xar_add_frompath(xar_t x, xar_file_t parent, const char *name, const char *realpath); + +xar_file_t xar_add_from_archive(xar_t x, xar_file_t parent, const char *name, xar_t sourcearchive, xar_file_t sourcefile); + +int32_t xar_extract(xar_t x, xar_file_t f); +int32_t xar_extract_tofile(xar_t x, xar_file_t f, const char *path); +int32_t xar_extract_tobuffer(xar_t x, xar_file_t f, char **buffer); +int32_t xar_extract_tobuffersz(xar_t x, xar_file_t f, char **buffer, size_t *size); +int32_t xar_extract_tostream_init(xar_t x, xar_file_t f, xar_stream *stream); +int32_t xar_extract_tostream(xar_stream *stream); +int32_t xar_extract_tostream_end(xar_stream *stream); + +int32_t xar_verify(xar_t x, xar_file_t f); +int32_t xar_verify_progress(xar_t x, xar_file_t f, xar_progress_callback progress); + +/* To get the checksum of the table of contents use this function. + * The function returns a alloced buffer that caller must free. */ +void* xar_get_toc_checksum(xar_t x, size_t* buffer_size); + +/* Returns XAR_CKSUM_* that maps to the type of the checksum. */ +int32_t xar_get_toc_checksum_type(xar_t x); + +const char *xar_opt_get(xar_t x, const char *option); +int32_t xar_opt_set(xar_t x, const char *option, const char *value); +int32_t xar_opt_unset(xar_t x, const char *option); + +int32_t xar_prop_set(xar_file_t f, const char *key, const char *value); +int32_t xar_prop_create(xar_file_t f, const char *key, const char *value); +int32_t xar_prop_get(xar_file_t f, const char *key, const char **value); + +xar_iter_t xar_iter_new(void); +void xar_iter_free(xar_iter_t i); + +const char *xar_prop_first(xar_file_t f, xar_iter_t i); +const char *xar_prop_next(xar_iter_t i); + +void xar_prop_unset(xar_file_t f, const char *key); +xar_file_t xar_file_first(xar_t x, xar_iter_t i); +xar_file_t xar_file_next(xar_iter_t i); + +const char *xar_attr_get(xar_file_t f, const char *prop, const char *key); +int32_t xar_attr_set(xar_file_t f, const char *prop, const char *key, const char *value); +const char *xar_attr_first(xar_file_t f, const char *prop, xar_iter_t i); +const char *xar_attr_next(xar_iter_t i); + +xar_subdoc_t xar_subdoc_new(xar_t x, const char *name); +int32_t xar_subdoc_prop_set(xar_subdoc_t s, const char *key, const char *value); +int32_t xar_subdoc_prop_get(xar_subdoc_t s, const char *key, const char **value); +int32_t xar_subdoc_attr_set(xar_subdoc_t s, const char *prop, const char *key, const char *value); +const char *xar_subdoc_attr_get(xar_subdoc_t s, const char *prop, const char *key); +xar_subdoc_t xar_subdoc_first(xar_t x); +xar_subdoc_t xar_subdoc_next(xar_subdoc_t s); +const char *xar_subdoc_name(xar_subdoc_t s); +int32_t xar_subdoc_copyout(xar_subdoc_t s, unsigned char **, unsigned int *); +int32_t xar_subdoc_copyin(xar_subdoc_t s, const unsigned char *, unsigned int); +void xar_subdoc_remove(xar_subdoc_t s); + +/* signature api for adding various signature types */ +xar_signature_t xar_signature_new(xar_t x,const char *type, int32_t length, xar_signer_callback callback, void *callback_context); +/* extended signatures are ignored by previous versions of xar */ +xar_signature_t xar_signature_new_extended(xar_t x,const char *type, int32_t length, xar_signer_callback callback, void *callback_context); + +const char *xar_signature_type(xar_signature_t s); + +xar_signature_t xar_signature_first(xar_t x); +xar_signature_t xar_signature_next(xar_signature_t s); + +int32_t xar_signature_add_x509certificate(xar_signature_t sig, const uint8_t *cert_data, uint32_t cert_len ); + +int32_t xar_signature_get_x509certificate_count(xar_signature_t sig); +int32_t xar_signature_get_x509certificate_data(xar_signature_t sig, int32_t index, const uint8_t **cert_data, uint32_t *cert_len); + +uint8_t xar_signature_copy_signed_data(xar_signature_t sig, uint8_t **data, uint32_t *length, uint8_t **signed_data, uint32_t *signed_length, off_t *signed_offset); + +/* Helper functions - caller must free returned memory */ +char *xar_get_size(xar_t x, xar_file_t f); +char *xar_get_type(xar_t x, xar_file_t f); +char *xar_get_mode(xar_t x, xar_file_t f); +char *xar_get_owner(xar_t x, xar_file_t f); +char *xar_get_group(xar_t x, xar_file_t f); +char *xar_get_mtime(xar_t x, xar_file_t f); + +/* For helping calling apps harden against hacked archives that attempt to escape their extraction roots. */ +int xar_path_issane(char* path); + +/* These are for xar modules and should never be needed from a calling app */ +void xar_register_errhandler(xar_t x, err_handler callback, void *usrctx); +xar_t xar_err_get_archive(xar_errctx_t ctx); +xar_file_t xar_err_get_file(xar_errctx_t ctx); +const char *xar_err_get_string(xar_errctx_t ctx); +int xar_err_get_errno(xar_errctx_t ctx); +void xar_err_set_file(xar_t x, xar_file_t f); +void xar_err_set_formatted_string(xar_t x, const char *format, ...); +void xar_err_set_string(xar_t x, const char *str); +void xar_err_set_errno(xar_t x, int e); +void xar_err_new(xar_t x); +int32_t xar_err_callback(xar_t x, int32_t sev, int32_t err); + +void xar_serialize(xar_t x, const char *file); +char *xar_get_path(xar_file_t f); +off_t xar_get_heap_offset(xar_t x); +uint64_t xar_ntoh64(uint64_t num); + +#if __cplusplus +} +#endif + +#endif /* _XAR_H_ */ diff --git a/xar/install-sh b/xar/install-sh new file mode 100644 index 0000000..ebc6691 --- /dev/null +++ b/xar/install-sh @@ -0,0 +1,250 @@ +#! /bin/sh +# +# install - install a program, script, or datafile +# This comes from X11R5 (mit/util/scripts/install.sh). +# +# Copyright 1991 by the Massachusetts Institute of Technology +# +# Permission to use, copy, modify, distribute, and sell this software and its +# documentation for any purpose is hereby granted without fee, provided that +# the above copyright notice appear in all copies and that both that +# copyright notice and this permission notice appear in supporting +# documentation, and that the name of M.I.T. not be used in advertising or +# publicity pertaining to distribution of the software without specific, +# written prior permission. M.I.T. makes no representations about the +# suitability of this software for any purpose. It is provided "as is" +# without express or implied warranty. +# +# Calling this script install-sh is preferred over install.sh, to prevent +# `make' implicit rules from creating a file called install from it +# when there is no Makefile. +# +# This script is compatible with the BSD install script, but was written +# from scratch. It can only install one file at a time, a restriction +# shared with many OS's install programs. + + +# set DOITPROG to echo to test this script + +# Don't use :- since 4.3BSD and earlier shells don't like it. +doit="${DOITPROG-}" + + +# put in absolute paths if you don't have them in your path; or use env. vars. + +mvprog="${MVPROG-mv}" +cpprog="${CPPROG-cp}" +chmodprog="${CHMODPROG-chmod}" +chownprog="${CHOWNPROG-chown}" +chgrpprog="${CHGRPPROG-chgrp}" +stripprog="${STRIPPROG-strip}" +rmprog="${RMPROG-rm}" +mkdirprog="${MKDIRPROG-mkdir}" + +transformbasename="" +transform_arg="" +instcmd="$mvprog" +chmodcmd="$chmodprog 0755" +chowncmd="" +chgrpcmd="" +stripcmd="" +rmcmd="$rmprog -f" +mvcmd="$mvprog" +src="" +dst="" +dir_arg="" + +while [ x"$1" != x ]; do + case $1 in + -c) instcmd="$cpprog" + shift + continue;; + + -d) dir_arg=true + shift + continue;; + + -m) chmodcmd="$chmodprog $2" + shift + shift + continue;; + + -o) chowncmd="$chownprog $2" + shift + shift + continue;; + + -g) chgrpcmd="$chgrpprog $2" + shift + shift + continue;; + + -s) stripcmd="$stripprog" + shift + continue;; + + -t=*) transformarg=`echo $1 | sed 's/-t=//'` + shift + continue;; + + -b=*) transformbasename=`echo $1 | sed 's/-b=//'` + shift + continue;; + + *) if [ x"$src" = x ] + then + src=$1 + else + # this colon is to work around a 386BSD /bin/sh bug + : + dst=$1 + fi + shift + continue;; + esac +done + +if [ x"$src" = x ] +then + echo "install: no input file specified" + exit 1 +else + true +fi + +if [ x"$dir_arg" != x ]; then + dst=$src + src="" + + if [ -d $dst ]; then + instcmd=: + else + instcmd=mkdir + fi +else + +# Waiting for this to be detected by the "$instcmd $src $dsttmp" command +# might cause directories to be created, which would be especially bad +# if $src (and thus $dsttmp) contains '*'. + + if [ -f $src -o -d $src ] + then + true + else + echo "install: $src does not exist" + exit 1 + fi + + if [ x"$dst" = x ] + then + echo "install: no destination specified" + exit 1 + else + true + fi + +# If destination is a directory, append the input filename; if your system +# does not like double slashes in filenames, you may need to add some logic + + if [ -d $dst ] + then + dst="$dst"/`basename $src` + else + true + fi +fi + +## this sed command emulates the dirname command +dstdir=`echo $dst | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'` + +# Make sure that the destination directory exists. +# this part is taken from Noah Friedman's mkinstalldirs script + +# Skip lots of stat calls in the usual case. +if [ ! -d "$dstdir" ]; then +defaultIFS=' +' +IFS="${IFS-${defaultIFS}}" + +oIFS="${IFS}" +# Some sh's can't handle IFS=/ for some reason. +IFS='%' +set - `echo ${dstdir} | sed -e 's@/@%@g' -e 's@^%@/@'` +IFS="${oIFS}" + +pathcomp='' + +while [ $# -ne 0 ] ; do + pathcomp="${pathcomp}${1}" + shift + + if [ ! -d "${pathcomp}" ] ; + then + $mkdirprog "${pathcomp}" + else + true + fi + + pathcomp="${pathcomp}/" +done +fi + +if [ x"$dir_arg" != x ] +then + $doit $instcmd $dst && + + if [ x"$chowncmd" != x ]; then $doit $chowncmd $dst; else true ; fi && + if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dst; else true ; fi && + if [ x"$stripcmd" != x ]; then $doit $stripcmd $dst; else true ; fi && + if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dst; else true ; fi +else + +# If we're going to rename the final executable, determine the name now. + + if [ x"$transformarg" = x ] + then + dstfile=`basename $dst` + else + dstfile=`basename $dst $transformbasename | + sed $transformarg`$transformbasename + fi + +# don't allow the sed command to completely eliminate the filename + + if [ x"$dstfile" = x ] + then + dstfile=`basename $dst` + else + true + fi + +# Make a temp file name in the proper directory. + + dsttmp=$dstdir/#inst.$$# + +# Move or copy the file name to the temp name + + $doit $instcmd $src $dsttmp && + + trap "rm -f ${dsttmp}" 0 && + +# and set any options; do chmod last to preserve setuid bits + +# If any of these fail, we abort the whole thing. If we want to +# ignore errors from any of these, just make sure not to ignore +# errors from the above "$doit $instcmd $src $dsttmp" command. + + if [ x"$chowncmd" != x ]; then $doit $chowncmd $dsttmp; else true;fi && + if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dsttmp; else true;fi && + if [ x"$stripcmd" != x ]; then $doit $stripcmd $dsttmp; else true;fi && + if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dsttmp; else true;fi && + +# Now rename the file to the real destination. + + $doit $rmcmd -f $dstdir/$dstfile && + $doit $mvcmd $dsttmp $dstdir/$dstfile + +fi && + + +exit 0 diff --git a/xar/lib/.cvsignore b/xar/lib/.cvsignore new file mode 100644 index 0000000..69250f0 --- /dev/null +++ b/xar/lib/.cvsignore @@ -0,0 +1,4 @@ +Makefile.inc +librxar.* +libxar.* +*.d diff --git a/xar/lib/Makefile.inc b/xar/lib/Makefile.inc new file mode 100644 index 0000000..033a841 --- /dev/null +++ b/xar/lib/Makefile.inc @@ -0,0 +1,205 @@ +# +# File lists. +# + +# Internal headers. +LIBXAR_IINCS := asprintf.h + +LIBXAR_IINCS := $(patsubst %, include/%, $(LIBXAR_IINCS)) +LIBXAR_IINCS += include/config.h + +# Headers. +LIBXAR_INCS := + +LIBXAR_INCS := $(patsubst %, include/%, $(LIBXAR_INCS)) +LIBXAR_INCS += include/xar.h + +# Sources. +LIBXAR_SRCS := archive.c arcmod.c b64.c bzxar.c darwinattr.c data.c ea.c err.c +LIBXAR_SRCS += ext2.c fbsdattr.c filetree.c io.c lzmaxar.c linuxattr.c hash.c +LIBXAR_SRCS += signature.c stat.c subdoc.c util.c zxar.c script.c macho.c + +LIBXAR_SRCS := $(patsubst %, lib/%, $(LIBXAR_SRCS)) + +# Libraries. librxar is created such that it's possible to run xar without +# first installing libxar. + +LIBXAR_LANAME := libxar.la +LIBXAR_ANAME := libxar.a +ifeq (elf, macho) +LIBRXAR_SNAME := librxar.so.1 +LIBRXAR_LNAME := librxar.so +LIBRXAR_L := lib/$(LIBRXAR_LNAME) +LIBXAR_SNAME := libxar.so.1 +LIBXAR_LNAME := libxar.so +LIBXAR_L := lib/$(LIBXAR_LNAME) +endif +ifeq (macho, macho) +LIBRXAR_SNAME := librxar.1.dylib +LIBRXAR_LNAME := librxar.dylib +LIBRXAR_L := lib/$(LIBRXAR_LNAME) +LIBXAR_SNAME := libxar.1.dylib +LIBXAR_LNAME := libxar.dylib +LIBXAR_L := lib/$(LIBXAR_LNAME) +endif +ifeq (aout, macho) +LIBRXAR_SNAME := librxar.so.1.0 +LIBRXAR_LNAME := +LIBRXAR_L := +LIBXAR_SNAME := libxar.so.1.0 +LIBXAR_LNAME := +LIBXAR_L := +endif +LIBXAR_LA := lib/$(LIBXAR_LANAME) +LIBXAR_A := lib/$(LIBXAR_ANAME) +LIBRXAR_S := lib/$(LIBRXAR_SNAME) +LIBXAR_S := lib/$(LIBXAR_SNAME) + +# +# Include generated dependency files. +# +-include $(LIBXAR_SRCS:%.c=%.d) + +LDFLAGS := -Llib $(LDFLAGS) + +# +# User make'ables. +# + +lib_all : lib_shared lib_static $(LIBXAR_LA) +ifeq (yes, yes) +lib_shared : $(LIBRXAR_S) $(LIBXAR_S) +else +lib_shared : +endif +ifeq (yes, yes) +lib_static : $(LIBXAR_A) +else +lib_static : +endif + +lib_install : lib_shared lib_static + .././install-sh -c -d $(DESTDIR)$(INCLUDEDIR)/xar + .././install-sh -c -m 0644 $(LIBXAR_INCS) $(DESTDIR)$(INCLUDEDIR)/xar + .././install-sh -c -d $(DESTDIR)$(LIBDIR) +ifeq (yes, yes) + .././install-sh -c -m 0755 $(LIBXAR_S) $(DESTDIR)$(LIBDIR) +ifneq ($(words "" $(LIBXAR_LNAME)), 1) + rm -f $(DESTDIR)$(LIBDIR)/$(LIBXAR_LNAME) + ln -s $(LIBXAR_SNAME) $(DESTDIR)$(LIBDIR)/$(LIBXAR_LNAME) +endif +endif +ifeq (yes, yes) + .././install-sh -c -m 0644 $(LIBXAR_A) $(DESTDIR)$(LIBDIR) +endif + .././install-sh -c -m 0644 $(LIBXAR_LA) $(DESTDIR)$(LIBDIR) + +lib_uninstall : + rm -rf $(DESTDIR)$(INCLUDEDIR)/xar +ifeq (yes, yes) + rm -f $(DESTDIR)$(LIBDIR)/$(LIBXAR_SNAME) +ifneq ($(words "" $(LIBXAR_LNAME)), 1) + rm -f $(DESTDIR)$(LIBDIR)/$(LIBXAR_LNAME) +endif +endif +ifeq (yes, yes) + rm -f $(DESTDIR)$(LIBDIR)/$(LIBXAR_ANAME) +endif + rm -f $(DESTDIR)$(LIBDIR)/$(LIBXAR_LANAME) + +lib_clean : + rm -f $(LIBRXAR_S) $(LIBRXAR_L) + rm -f $(LIBXAR_S) $(LIBXAR_L) + rm -f $(LIBXAR_A) $(LIBXAR_LA) + @rm -f lib/.libs/$(LIBXAR_LNAME) + @rm -f lib/.libs/$(LIBXAR_ANAME) + @-rmdir lib/.libs + rm -f $(LIBXAR_SRCS:%.c=%.o) + rm -f $(LIBXAR_SRCS:%.c=%.d) + rm -f $(LIBXAR_SRCS:%.c=%.static.o) + rm -f $(LIBXAR_SRCS:%.c=%.static.d) + +lib_distclean : + +# +# Various flags. +# + +CPPFLAGS := -Iinclude $(CPPFLAGS) +CPPFLAGS := -Iinclude $(CPPFLAGS) + +# +# Build rules. +# + +# librxar is a version of the xar library that is usable without first +# installing libxar. +$(LIBRXAR_S) : $(LIBXAR_SRCS:%.c=%.o) + @mkdir -p $(@D) +ifeq (elf, macho) + $(CC) -shared -Wl,-soname,$(LIBXAR_SNAME) -o $@ $+ $(LDFLAGS) -lpthread -lbz2 -lz -lxml2 -lz -lpthread -licucore -lm +endif +ifeq (macho, macho) + $(CC) -dynamiclib -compatibility_version 1 -current_version 1 -install_name /Users/ariel/LinuxHome/code/darling/src/xar/xar/$(LIBRXAR_S) -o $@ $+ $(LDFLAGS) -lpthread -lbz2 -lz -lxml2 -lz -lpthread -licucore -lm +endif +ifeq (aout, macho) + $(CC) -shared -o $@ $+ +endif +ifneq ($(words "" $(LIBRXAR_L)), 1) + rm -f $(LIBRXAR_L) + ln -s $(LIBRXAR_SNAME) $(LIBRXAR_L) +endif + +$(LIBXAR_S) : $(LIBXAR_SRCS:%.c=%.o) + @mkdir -p $(@D) +ifeq (elf, macho) + $(CC) -shared -Wl,-soname,$(LIBXAR_SNAME) -o $@ $+ $(LDFLAGS) -lpthread -lbz2 -lz -lxml2 -lz -lpthread -licucore -lm +endif +ifeq (macho, macho) + $(CC) -dynamiclib -compatibility_version 1 -current_version 1 -install_name $(LIBDIR)/$(LIBXAR_SNAME) -o $@ $+ $(LDFLAGS) -lpthread -lbz2 -lz -lxml2 -lz -lpthread -licucore -lm +endif +ifeq (aout, macho) + $(CC) -shared -o $@ $+ +endif +ifneq ($(words "" $(LIBXAR_L)), 1) + rm -f $(LIBXAR_L) + ln -s $(LIBXAR_SNAME) $(LIBXAR_L) +endif + +ifeq (yes, yes) +LT_LIBXAR_SNAME := $(LIBXAR_SNAME) +LT_LIBXAR_LNAME := $(LIBXAR_LNAME) +else +LT_LIBXAR_SNAME := +LT_LIBXAR_LNAME := +endif +ifeq (yes, yes) +LT_LIBXAR_ANAME := $(LIBXAR_ANAME) +else +LT_LIBXAR_ANAME := +endif + +$(LIBXAR_LA) : $(LIBXAR_LA).in + @mkdir -p lib/.libs +ifeq (yes, yes) + @ln -sf ../$(LIBXAR_LNAME) lib/.libs/$(LIBXAR_LNAME) +endif +ifeq (yes, yes) + @ln -sf ../$(LIBXAR_ANAME) lib/.libs/$(LIBXAR_ANAME) +endif + sed -e s/@LIBXAR_SNAME@/$(LT_LIBXAR_SNAME)/ -e s/@LIBXAR_LNAME@/$(LT_LIBXAR_LNAME)/ -e s/@LIBXAR_ANAME@/$(LT_LIBXAR_ANAME)/ < $< > $@ + +$(LIBXAR_A) : $(LIBXAR_SRCS:%.c=%.static.o) + @mkdir -p $(@D) + $(AR) cvr $@ $+ + $(RANLIB) $@ + +lib/%.o : lib/%.c + @mkdir -p $(@D) + $(CC) $(S_CFLAGS) $(CPPFLAGS) -c $< -o $@ + @$(SHELL) -ec "$(CC) -MM $(CPPFLAGS) $< | sed \"s/\($(subst /,\/,$(notdir $(basename $@)))\)\.o\([ :]*\)/$(subst /,\/,$(strip $(dir $@)))\1.o \2/g\" > $(@:%.o=%.d)" + +lib/%.static.o : lib/%.c + @mkdir -p $(@D) + $(CC) $(A_CFLAGS) $(CPPFLAGS) -c $< -o $@ + @$(SHELL) -ec "$(CC) -MM $(CPPFLAGS) $< | sed \"s/\($(subst /,\/,$(notdir $(basename $@)))\)\.o\([ :]*\)/$(subst /,\/,$(strip $(dir $@)))\1.o \2/g\" > $(@:%.o=%.d)" diff --git a/xar/lib/Makefile.inc.in b/xar/lib/Makefile.inc.in new file mode 100644 index 0000000..c046b25 --- /dev/null +++ b/xar/lib/Makefile.inc.in @@ -0,0 +1,205 @@ +# +# File lists. +# + +# Internal headers. +LIBXAR_IINCS := asprintf.h + +LIBXAR_IINCS := $(patsubst %, @srcroot@include/%, $(LIBXAR_IINCS)) +LIBXAR_IINCS += @objroot@include/config.h + +# Headers. +LIBXAR_INCS := + +LIBXAR_INCS := $(patsubst %, @srcroot@include/%, $(LIBXAR_INCS)) +LIBXAR_INCS += @objroot@include/xar.h + +# Sources. +LIBXAR_SRCS := archive.c arcmod.c b64.c bzxar.c darwinattr.c data.c ea.c err.c +LIBXAR_SRCS += ext2.c fbsdattr.c filetree.c io.c lzmaxar.c linuxattr.c hash.c +LIBXAR_SRCS += signature.c stat.c subdoc.c util.c zxar.c script.c macho.c + +LIBXAR_SRCS := $(patsubst %, @srcroot@lib/%, $(LIBXAR_SRCS)) + +# Libraries. librxar is created such that it's possible to run xar without +# first installing libxar. + +LIBXAR_LANAME := libxar.la +LIBXAR_ANAME := libxar.a +ifeq (elf, @abi@) +LIBRXAR_SNAME := librxar.so.@LIB_REV@ +LIBRXAR_LNAME := librxar.so +LIBRXAR_L := @objroot@lib/$(LIBRXAR_LNAME) +LIBXAR_SNAME := libxar.so.@LIB_REV@ +LIBXAR_LNAME := libxar.so +LIBXAR_L := @objroot@lib/$(LIBXAR_LNAME) +endif +ifeq (macho, @abi@) +LIBRXAR_SNAME := librxar.@LIB_REV@.dylib +LIBRXAR_LNAME := librxar.dylib +LIBRXAR_L := @objroot@lib/$(LIBRXAR_LNAME) +LIBXAR_SNAME := libxar.@LIB_REV@.dylib +LIBXAR_LNAME := libxar.dylib +LIBXAR_L := @objroot@lib/$(LIBXAR_LNAME) +endif +ifeq (aout, @abi@) +LIBRXAR_SNAME := librxar.so.@LIB_REV@.0 +LIBRXAR_LNAME := +LIBRXAR_L := +LIBXAR_SNAME := libxar.so.@LIB_REV@.0 +LIBXAR_LNAME := +LIBXAR_L := +endif +LIBXAR_LA := @objroot@lib/$(LIBXAR_LANAME) +LIBXAR_A := @objroot@lib/$(LIBXAR_ANAME) +LIBRXAR_S := @objroot@lib/$(LIBRXAR_SNAME) +LIBXAR_S := @objroot@lib/$(LIBXAR_SNAME) + +# +# Include generated dependency files. +# +-include $(LIBXAR_SRCS:@srcroot@%.c=@objroot@%.d) + +LDFLAGS := -L@objroot@lib $(LDFLAGS) + +# +# User make'ables. +# + +lib_all : lib_shared lib_static $(LIBXAR_LA) +ifeq (yes, @shared@) +lib_shared : $(LIBRXAR_S) $(LIBXAR_S) +else +lib_shared : +endif +ifeq (yes, @static@) +lib_static : $(LIBXAR_A) +else +lib_static : +endif + +lib_install : lib_shared lib_static + @INSTALL@ -d $(DESTDIR)$(INCLUDEDIR)/xar + @INSTALL@ -m 0644 $(LIBXAR_INCS) $(DESTDIR)$(INCLUDEDIR)/xar + @INSTALL@ -d $(DESTDIR)$(LIBDIR) +ifeq (yes, @shared@) + @INSTALL@ -m 0755 $(LIBXAR_S) $(DESTDIR)$(LIBDIR) +ifneq ($(words "" $(LIBXAR_LNAME)), 1) + rm -f $(DESTDIR)$(LIBDIR)/$(LIBXAR_LNAME) + ln -s $(LIBXAR_SNAME) $(DESTDIR)$(LIBDIR)/$(LIBXAR_LNAME) +endif +endif +ifeq (yes, @static@) + @INSTALL@ -m 0644 $(LIBXAR_A) $(DESTDIR)$(LIBDIR) +endif + @INSTALL@ -m 0644 $(LIBXAR_LA) $(DESTDIR)$(LIBDIR) + +lib_uninstall : + rm -rf $(DESTDIR)$(INCLUDEDIR)/xar +ifeq (yes, @shared@) + rm -f $(DESTDIR)$(LIBDIR)/$(LIBXAR_SNAME) +ifneq ($(words "" $(LIBXAR_LNAME)), 1) + rm -f $(DESTDIR)$(LIBDIR)/$(LIBXAR_LNAME) +endif +endif +ifeq (yes, @static@) + rm -f $(DESTDIR)$(LIBDIR)/$(LIBXAR_ANAME) +endif + rm -f $(DESTDIR)$(LIBDIR)/$(LIBXAR_LANAME) + +lib_clean : + rm -f $(LIBRXAR_S) $(LIBRXAR_L) + rm -f $(LIBXAR_S) $(LIBXAR_L) + rm -f $(LIBXAR_A) $(LIBXAR_LA) + @rm -f @objroot@lib/.libs/$(LIBXAR_LNAME) + @rm -f @objroot@lib/.libs/$(LIBXAR_ANAME) + @-rmdir @objroot@lib/.libs + rm -f $(LIBXAR_SRCS:@srcroot@%.c=@objroot@%.o) + rm -f $(LIBXAR_SRCS:@srcroot@%.c=@objroot@%.d) + rm -f $(LIBXAR_SRCS:@srcroot@%.c=@objroot@%.static.o) + rm -f $(LIBXAR_SRCS:@srcroot@%.c=@objroot@%.static.d) + +lib_distclean : + +# +# Various flags. +# + +CPPFLAGS := -I@objroot@include $(CPPFLAGS) +CPPFLAGS := -I@srcroot@include $(CPPFLAGS) + +# +# Build rules. +# + +# librxar is a version of the xar library that is usable without first +# installing libxar. +$(LIBRXAR_S) : $(LIBXAR_SRCS:@srcroot@%.c=@objroot@%.o) + @mkdir -p $(@D) +ifeq (elf, @abi@) + $(CC) -shared -Wl,-soname,$(LIBXAR_SNAME) -o $@ $+ $(LDFLAGS) @LIBS@ +endif +ifeq (macho, @abi@) + $(CC) -dynamiclib -compatibility_version @LIB_REV@ -current_version @LIB_REV@ -install_name @abs_objroot@$(LIBRXAR_S) -o $@ $+ $(LDFLAGS) @LIBS@ +endif +ifeq (aout, @abi@) + $(CC) -shared -o $@ $+ +endif +ifneq ($(words "" $(LIBRXAR_L)), 1) + rm -f $(LIBRXAR_L) + ln -s $(LIBRXAR_SNAME) $(LIBRXAR_L) +endif + +$(LIBXAR_S) : $(LIBXAR_SRCS:@srcroot@%.c=@objroot@%.o) + @mkdir -p $(@D) +ifeq (elf, @abi@) + $(CC) -shared -Wl,-soname,$(LIBXAR_SNAME) -o $@ $+ $(LDFLAGS) @LIBS@ +endif +ifeq (macho, @abi@) + $(CC) -dynamiclib -compatibility_version @LIB_REV@ -current_version @LIB_REV@ -install_name $(LIBDIR)/$(LIBXAR_SNAME) -o $@ $+ $(LDFLAGS) @LIBS@ +endif +ifeq (aout, @abi@) + $(CC) -shared -o $@ $+ +endif +ifneq ($(words "" $(LIBXAR_L)), 1) + rm -f $(LIBXAR_L) + ln -s $(LIBXAR_SNAME) $(LIBXAR_L) +endif + +ifeq (yes, @shared@) +LT_LIBXAR_SNAME := $(LIBXAR_SNAME) +LT_LIBXAR_LNAME := $(LIBXAR_LNAME) +else +LT_LIBXAR_SNAME := +LT_LIBXAR_LNAME := +endif +ifeq (yes, @static@) +LT_LIBXAR_ANAME := $(LIBXAR_ANAME) +else +LT_LIBXAR_ANAME := +endif + +$(LIBXAR_LA) : $(LIBXAR_LA).in + @mkdir -p @objroot@lib/.libs +ifeq (yes, @shared@) + @ln -sf ../$(LIBXAR_LNAME) @objroot@lib/.libs/$(LIBXAR_LNAME) +endif +ifeq (yes, @static@) + @ln -sf ../$(LIBXAR_ANAME) @objroot@lib/.libs/$(LIBXAR_ANAME) +endif + sed -e s/@LIBXAR_SNAME@/$(LT_LIBXAR_SNAME)/ -e s/@LIBXAR_LNAME@/$(LT_LIBXAR_LNAME)/ -e s/@LIBXAR_ANAME@/$(LT_LIBXAR_ANAME)/ < $< > $@ + +$(LIBXAR_A) : $(LIBXAR_SRCS:@srcroot@%.c=@objroot@%.static.o) + @mkdir -p $(@D) + $(AR) cvr $@ $+ + $(RANLIB) $@ + +@objroot@lib/%.o : @srcroot@lib/%.c + @mkdir -p $(@D) + $(CC) $(S_CFLAGS) $(CPPFLAGS) -c $< -o $@ + @$(SHELL) -ec "$(CC) -MM $(CPPFLAGS) $< | sed \"s/\($(subst /,\/,$(notdir $(basename $@)))\)\.o\([ :]*\)/$(subst /,\/,$(strip $(dir $@)))\1.o \2/g\" > $(@:%.o=%.d)" + +@objroot@lib/%.static.o : @srcroot@lib/%.c + @mkdir -p $(@D) + $(CC) $(A_CFLAGS) $(CPPFLAGS) -c $< -o $@ + @$(SHELL) -ec "$(CC) -MM $(CPPFLAGS) $< | sed \"s/\($(subst /,\/,$(notdir $(basename $@)))\)\.o\([ :]*\)/$(subst /,\/,$(strip $(dir $@)))\1.o \2/g\" > $(@:%.o=%.d)" diff --git a/xar/lib/appledouble.h b/xar/lib/appledouble.h new file mode 100644 index 0000000..b1d9437 --- /dev/null +++ b/xar/lib/appledouble.h @@ -0,0 +1,103 @@ +/* Information pulled from: + * "AppleSingle/AppleDouble Formats for Foreign Files Developer's Note" + * (c) Apple Computer 1990 + * File assembled by Rob Braun (bbraun@synack.net) + */ + +#ifndef __APPLEDOUBLE__ +#define __APPLEDOUBLE__ + +#include +#include + +/* Structure of an AppleSingle file: + * ---------------------- + * | AppleSingleHeader | + * |--------------------| + * | ASH.entries # of | + * | AppleSingleEntry | + * | Descriptors | + * | 1 | + * | . | + * | . | + * | n | + * |--------------------| + * | Datablock 1 | + * |--------------------| + * | Datablock 2 | + * |--------------------| + * | Datablock n | + * ---------------------- + */ + +struct AppleSingleHeader { + uint32_t magic; /* Magic Number (0x00051600 for AS) */ + uint32_t version; /* Version #. 0x00020000 */ + char filler[16]; /* All zeros */ + uint16_t entries; /* Number of entries in the file */ +}; + +#define XAR_ASH_SIZE 26 /* sizeof(struct AppleSingleHeader) will be wrong + * due to padding. */ + +#define APPLESINGLE_MAGIC 0x00051600 +#define APPLEDOUBLE_MAGIC 0x00051607 + +#define APPLESINGLE_VERSION 0x00020000 +#define APPLEDOUBLE_VERSION 0x00020000 + +struct AppleSingleEntry { + uint32_t entry_id; /* What the entry is. See defines below */ + uint32_t offset; /* offset of data, offset beginning of file */ + uint32_t length; /* length of data. can be 0 */ +}; + +/* Valid entry_id values */ +/* Entries 1, 3, and 8 are typically created for all files. + * Macintosh Icon entries are rare, since those are typically in the resource + * fork. + */ +#define AS_ID_DATA 1 /* Data fork */ +#define AS_ID_RESOURCE 2 /* Resource fork */ +#define AS_ID_NAME 3 /* Name of the file */ +#define AS_ID_COMMENT 4 /* Standard Macintosh comment */ +#define AS_ID_BWICON 5 /* Standard Macintosh B&W icon */ +#define AS_ID_COLORICON 6 /* Standard Macintosh Color icon */ +/* There is no 7 */ +#define AS_ID_DATES 8 /* File creation date, modification date, etc. */ +#define AS_ID_FINDER 9 /* Finder Information */ +#define AS_ID_MAC 10 /* Macintosh File information, attributes, etc. */ +#define AS_ID_PRODOS 11 /* ProDOS file information */ +#define AS_ID_MSDOS 12 /* MS-DOS file information */ +#define AS_ID_SHORTNAME 13 /* AFP short name */ +#define AS_ID_AFPINFO 14 /* AFP file information */ +#define AS_ID_AFPDIR 15 /* AFP directory id */ +/* 1-0x7FFFFFFF are reserved by Apple */ + +/* File Dates are stored as the # of seconds before or after + * 12am Jan 1, 2000 GMT. The default value is 0x80000000. + */ +struct MacTimes { + uint32_t creation; + uint32_t modification; + uint32_t backup; + uint32_t access; +}; + +/* Finder Information is two 16 byte quantities. + * Newly created files have all 0's in both entries. + */ + +/* Macintosh File Info entry (10) a 32 bit bitmask. */ + +/* Entries can be placed in any order, although Apple recommends: + * Place the data block (1) last. + * Finder Info, File Dates Info, and Macintosh File Info first. + * Allocate resource for entries in 4K blocks. + */ + +/* AppleDouble files are simply AppleSingle files without the data fork. + * The magic number is different as a read optimization. + */ + +#endif /* __APPLEDOUBLE__ */ diff --git a/xar/lib/archive.c b/xar/lib/archive.c new file mode 100644 index 0000000..18ebc21 --- /dev/null +++ b/xar/lib/archive.c @@ -0,0 +1,1739 @@ +/* + * Copyright (c) 2005-2008 Rob Braun + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Rob Braun nor the names of his contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +/* + * 03-Apr-2005 + * DRI: Rob Braun + */ +/* + * Portions Copyright 2006, Apple Computer, Inc. + * Christopher Ryan + */ + +#define _FILE_OFFSET_BITS 64 + +#include "config.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include /* for ntoh{l,s} */ +#include /* for PRIu64 */ +#include +#include +#include +#include +#ifdef HAVE_LIBPTHREAD +#include +#endif // HAVE_LIBPTHREAD +#ifndef HAVE_ASPRINTF +#include "asprintf.h" +#endif +#include "xar.h" +#include "filetree.h" +#include "archive.h" +#include "signature.h" +#include "arcmod.h" +#include "io.h" +#include "util.h" +#include "subdoc.h" +#include "darwinattr.h" + +#ifndef O_EXLOCK +#define O_EXLOCK 0 +#endif +#ifndef O_SHLOCK +#define O_SHLOCK 0 +#endif + +#ifndef LONG_MAX +#define LONG_MAX INT32_MAX +#endif +#ifndef LONG_MIN +#define LONG_MIN INT32_MIN +#endif + +#if LIBXML_VERSION < 20618 +#define xmlDictCleanup() /* function doesn't exist in older API */ +#endif + +static int32_t xar_unserialize(xar_t x); +void xar_serialize(xar_t x, const char *file); + + +#ifdef HAVE_LIBPTHREAD +static pthread_mutex_t xar_new_mutex = PTHREAD_MUTEX_INITIALIZER; +#endif // HAVE_LIBPTHREAD + +/* xar_new + * Returns: newly allocated xar_t structure + * Summary: just does basicallocation and initialization of + * xar_t structure. + */ +static xar_t xar_new() { + xar_t ret; + ret = malloc(sizeof(struct __xar_t)); + if(!ret) return NULL; + memset(XAR(ret), 0, sizeof(struct __xar_t)); + XAR(ret)->readbuf_len = 4096; + XAR(ret)->readbuf = malloc(XAR(ret)->readbuf_len); + if(!XAR(ret)->readbuf) { + free((void *)ret); + return NULL; + } + XAR(ret)->offset = 0; + + XAR(ret)->zs.zalloc = Z_NULL; + XAR(ret)->zs.zfree = Z_NULL; + XAR(ret)->zs.opaque = Z_NULL; + + // xmlHashCreate() calls libxml2's random number generator, which is not thread- + // safe and can deadlock. Protecting this with a mutex permits multi-threaded use + // of xar_open(). +#ifdef HAVE_LIBPTHREAD + pthread_mutex_lock(&xar_new_mutex); +#else +#warning libpthread unavailable. Potential for deadlock with multithreaded xar_open() use. +#endif // HAVE_LIBPTHREAD + XAR(ret)->ino_hash = xmlHashCreate(0); + XAR(ret)->link_hash = xmlHashCreate(0); + XAR(ret)->csum_hash = xmlHashCreate(0); +#ifdef HAVE_LIBPTHREAD + pthread_mutex_unlock(&xar_new_mutex); +#endif // HAVE_LIBPTHREAD + + XAR(ret)->subdocs = NULL; + + XAR(ret)->attrcopy_to_heap = xar_attrcopy_to_heap; + XAR(ret)->attrcopy_from_heap = xar_attrcopy_from_heap; + XAR(ret)->heap_to_archive = xar_heap_to_archive; + + return ret; +} + +/* xar_parse_header + * x: archive to operate on. + * Returns: 0 on success, -1 on failure + * Summary: internal helper function to read in the xar header. + */ +static int32_t xar_parse_header(xar_t x) { + ssize_t r; + int off = 0; + int sz2read = 0; + + /* read just the magic, verify it, read the header length, + * then read in the size of the header according to the + * recorded header length, or the length of the structure + * we expect, whichever is smaller. Then seek forward + * if the recorded header length is greater than the + * expected header length. + */ + size_t size_to_read = sizeof(XAR(x)->header.magic)-off; + r = xar_read_fd(XAR(x)->fd, (char *)&XAR(x)->header.magic+off, size_to_read); + if ( r == -1 || size_to_read != r) + return -1; + + /* Verify the header. If the header doesn't match, exit without + * attempting to read any more. + */ + XAR(x)->header.magic = ntohl(XAR(x)->header.magic); + + if( XAR(x)->header.magic != XAR_HEADER_MAGIC ) { + return -1; + } + + size_to_read = sizeof(XAR(x)->header.size)-off; + r = xar_read_fd(XAR(x)->fd, (char *)&XAR(x)->header.size+off, size_to_read); + if ( r == -1 || size_to_read != r ) + return r; + + XAR(x)->header.size = ntohs(XAR(x)->header.size); + + if( XAR(x)->header.size > sizeof(xar_header_t) ) + sz2read = sizeof(xar_header_t); + else + sz2read = XAR(x)->header.size; + + off = sizeof(XAR(x)->header.magic) + sizeof(XAR(x)->header.size); + size_to_read = sizeof(xar_header_t)-off; + r = xar_read_fd(XAR(x)->fd, ((char *)&XAR(x)->header)+off, size_to_read); + if ( r == -1 || size_to_read != r) + return r; + + XAR(x)->header.version = ntohs(XAR(x)->header.version); + XAR(x)->header.toc_length_compressed = xar_ntoh64(XAR(x)->header.toc_length_compressed); + XAR(x)->header.toc_length_uncompressed = xar_ntoh64(XAR(x)->header.toc_length_uncompressed); + XAR(x)->header.cksum_alg = ntohl(XAR(x)->header.cksum_alg); + + off = XAR(x)->header.size - sz2read; + if( off > 0 ) + r = lseek(XAR(x)->fd, (off_t)off, SEEK_CUR); + + if ( (r == -1) && (errno != ESPIPE) ) + /* Some fatal error here perhaps? */ ; + + return 0; +} + +xar_t xar_open(const char *file, int32_t flags) +{ + return xar_open_digest_verify(file, flags, NULL, 0); +} + +/* xar_open + * file: filename to open + * flags: flags on how to open the file. 0 for readonly, !0 for read/write + * expected_toc_digest: Requires that the xar being opened matches the digest specified. + * expected_toc_digest_len: The length of the expected_toc_digest. + * Returns: allocated and initialized xar structure with an open + * file descriptor to the target xar file. If the xarchive is opened + * for writing, the file is created, and a heap file is opened. + */ +xar_t xar_open_digest_verify(const char *file, int32_t flags, void *expected_toc_digest, size_t expected_toc_digest_len) +{ + xar_t ret; + + ret = xar_new(); + if( !ret ) return NULL; + if( !file ) + file = "-"; + XAR(ret)->filename = strdup(file); + if( flags ) { // writing + char *tmp1, *tmp2, *tmp4; + tmp1 = tmp2 = strdup(file); + XAR(ret)->dirname = xar_safe_dirname(tmp2); + /* Create the heap file in the directory which will contain + * the target archive. /tmp or elsewhere may fill up. + */ + asprintf(&tmp4, "%s/xar.heap.XXXXXX", XAR(ret)->dirname); + free(tmp1); + if( strcmp(file, "-") == 0 ) + XAR(ret)->fd = 1; + else{ + XAR(ret)->fd = open(file, O_WRONLY | O_CREAT | O_TRUNC | O_EXLOCK, 0644); + if( (-1 == XAR(ret)->fd ) && (ENOTSUP == errno) ){ + XAR(ret)->fd = open(file, O_WRONLY | O_CREAT | O_TRUNC , 0644); + } + } + XAR(ret)->heap_fd = mkstemp(tmp4); + if( XAR(ret)->heap_fd < 0 ) { + close(XAR(ret)->fd); + free(XAR(ret)); + return NULL; + } + + unlink(tmp4); + free(tmp4); + + deflateInit(&XAR(ret)->zs, Z_BEST_COMPRESSION); + + if( XAR(ret)->fd < 0 ) { + xar_close(ret); + return NULL; + } + + /* default to using sha1, if nothing else is + * specified. + */ + XAR(ret)->heap_offset += 20; + XAR(ret)->heap_len += 20; + + xar_opt_set(ret, XAR_OPT_COMPRESSION, XAR_OPT_VAL_GZIP); + xar_opt_set(ret, XAR_OPT_FILECKSUM, XAR_OPT_VAL_SHA1); + xar_opt_set(ret, XAR_OPT_TOCCKSUM, XAR_OPT_VAL_SHA1); + } else { + if( strcmp(file, "-") == 0 ) + XAR(ret)->fd = 0; + else{ + XAR(ret)->fd = open(file, O_RDONLY | O_SHLOCK); + + if( (-1 == XAR(ret)->fd ) && (ENOTSUP == errno) ){ + XAR(ret)->fd = open(file, O_RDONLY); + } + + } + XAR(ret)->heap_fd = -1; + inflateInit(&XAR(ret)->zs); + if( XAR(ret)->fd < 0 ) { + xar_close(ret); + return NULL; + } + + if( xar_parse_header(ret) != 0 ) { + xar_close(ret); + return NULL; + } + + switch(XAR(ret)->header.cksum_alg) { + case XAR_CKSUM_NONE: + fprintf(stderr, "Archive uses no hashing algorithm, aborting\n"); + xar_close(ret); + return NULL; + break; + case XAR_CKSUM_SHA1: + XAR(ret)->toc_hash_ctx = xar_hash_new("sha1", (void *)ret); + break; + case XAR_CKSUM_SHA256: + XAR(ret)->toc_hash_ctx = xar_hash_new("sha256", (void *)ret); + break; + case XAR_CKSUM_SHA512: + XAR(ret)->toc_hash_ctx = xar_hash_new("sha512", (void *)ret); + break; + case XAR_CKSUM_MD5: +#ifdef XAR_SUPPORT_MD5 + XAR(ret)->toc_hash_ctx = xar_hash_new("md5", (void *)ret); + break; +#else + fprintf(stderr, "Archive uses unsafe hashing algorithm (MD5), aborting\n"); + xar_close(ret); + return NULL; +#endif // XAR_SUPPORT_MD5 + default: + fprintf(stderr, "Unknown hashing algorithm, skipping\n"); + break; + }; + + // deserialize the TOC + if( xar_unserialize(ret) != 0 ) { + xar_close(ret); + return NULL; + } + + /* check for inconsistency between checksum style in header, + * and the one described in the TOC; otherwise, you can flip + * the header bit to XAR_CKSUM_NONE, and nothing will ever + * verify that the TOC matches the checksum stored in the + * heap, and the signature check will pass on a modified + * file! + */ + int cksum_match = 0; + const char* cksum_style = xar_attr_get(XAR_FILE(ret), "checksum", "style"); + switch(XAR(ret)->header.cksum_alg) { + case XAR_CKSUM_NONE: + // Although we no longer support none, we are leaving this here to detect mismatches + cksum_match = (cksum_style == NULL || strcmp(cksum_style, XAR_OPT_VAL_NONE) == 0); + break; + case XAR_CKSUM_SHA1: + cksum_match = (cksum_style != NULL && strcmp(cksum_style, XAR_OPT_VAL_SHA1) == 0); + break; + case XAR_CKSUM_SHA256: + cksum_match = (cksum_style != NULL && strcmp(cksum_style, XAR_OPT_VAL_SHA256) == 0); + break; + case XAR_CKSUM_SHA512: + cksum_match = (cksum_style != NULL && strcmp(cksum_style, XAR_OPT_VAL_SHA512) == 0); + break; + case XAR_CKSUM_MD5: + // This is left in place regardless of XAR_SUPPORT_MD5 setting so we can still detect mismatches + cksum_match = (cksum_style != NULL && strcmp(cksum_style, XAR_OPT_VAL_MD5) == 0); + break; + default: + cksum_match = 0; + break; + } + if( !cksum_match ) { + fprintf(stderr, "Checksum style mismatch!\n"); + xar_close(ret); + return NULL; + } + + /* also check for consistency between the checksum style and + * the existence (or not) of signatures: since the signature + * is signing the checksum, we must have a checksum to verify + * that the TOC has not been modified + */ + if( xar_signature_first(ret) != NULL && XAR(ret)->header.cksum_alg == XAR_CKSUM_NONE ) { + fprintf(stderr, "Checksum/signature mismatch!\n"); + xar_close(ret); + return NULL; + } + + /* If we aren't checksumming the TOC, we're done */ + if( !XAR(ret)->toc_hash_ctx ) + return ret; + + /* if TOC specifies a location for the checksum, make sure that + * we read the checksum from there: this is required for an archive + * with a signature, because the signature will be checked against + * the checksum at the specified location + */ + const char *value; + uint64_t offset = 0; + uint64_t length = 0; + if( xar_prop_get( XAR_FILE(ret) , "checksum/offset", &value) == 0 ) { + errno = 0; + offset = strtoull( value, (char **)NULL, 10); + if( errno != 0 ) { + xar_close(ret); + return NULL; + } + } else if( xar_signature_first(ret) != NULL ) { + // All archives that have a signature also specify the location + // of the checksum. If the location isn't specified, error out. + xar_close(ret); + return NULL; + } + + XAR(ret)->heap_offset = xar_get_heap_offset(ret) + offset; + if( lseek(XAR(ret)->fd, XAR(ret)->heap_offset, SEEK_SET) == -1 ) { + xar_close(ret); + return NULL; + } + if( xar_prop_get( XAR_FILE(ret) , "checksum/size", &value) == 0 ) { + errno = 0; + length = strtoull( value, (char **)NULL, 10); + if( errno != 0 ) { + xar_close(ret); + return NULL; + } + } else if( xar_signature_first(ret) != NULL ) { + xar_close(ret); + return NULL; + } + + size_t tlen = 0; + void *toccksum = xar_hash_finish(XAR(ret)->toc_hash_ctx, &tlen); + + if( length != tlen ) { + free(toccksum); + xar_close(ret); + return NULL; + } + + // Store our toc hash upon archive open, so callers can determine if it + // has changed or been tampered with after archive open + XAR(ret)->toc_hash = malloc(tlen); + memcpy(XAR(ret)->toc_hash, toccksum, tlen); + XAR(ret)->toc_hash_size = tlen; + + void *cval = calloc(1, tlen); + if( ! cval ) { + free(toccksum); + xar_close(ret); + return NULL; + } + + ssize_t r = xar_read_fd(XAR(ret)->fd, cval, tlen); + + if (r < 0 || r != tlen) { + free(toccksum); + xar_close(ret); + return NULL; + } + + XAR(ret)->heap_offset += tlen; + if( memcmp(cval, toccksum, tlen) != 0 ) { + fprintf(stderr, "Checksums do not match!\n"); + free(toccksum); + free(cval); + xar_close(ret); + return NULL; + } + + free(toccksum); + free(cval); + } + + if ( expected_toc_digest ) + { + if ( ! XAR(ret)->toc_hash_ctx ) + { + fprintf(stderr, "xar_open_digest_verify: xar lacks a toc_hash_ctx.\n"); + xar_close(ret); + return NULL; + } + + if ( XAR(ret)->toc_hash_size != expected_toc_digest_len ) + { + fprintf(stderr, "xar_open_digest_verify: toc digest length does not match the expected digest length.\n"); + xar_close(ret); + return NULL; + } + + if ( memcmp(XAR(ret)->toc_hash, expected_toc_digest, expected_toc_digest_len) != 0 ) + { + fprintf(stderr, "xar_open_digest_verify: toc digest does not match the expected.\n"); + xar_close(ret); + return NULL; + } + } + + return ret; +} + +void* xar_get_toc_checksum(xar_t x, size_t* buffer_size) +{ + // Required in, missing. + if (!buffer_size) + return NULL; + + // Sanity set values + void* result = NULL; + *buffer_size = 0; + + // If we have a hash, return it. + if (XAR(x)->toc_hash) { + + *buffer_size = XAR(x)->toc_hash_size; + result = calloc(*buffer_size, 1); + + // Malloc fail? + if (!result) + return NULL; + + memcpy(result, XAR(x)->toc_hash, XAR(x)->toc_hash_size); + } + + return result; +} + +int32_t xar_get_toc_checksum_type(xar_t x) +{ + return XAR(x)->header.cksum_alg; +} + +/* xar_close + * x: the xar_t to close + * Summary: closes all open file descriptors, frees all + * file structures and options, deallocates the xar_t its self. + * Returns 0 for success, -1 for failure. + */ +int xar_close(xar_t x) { + xar_attr_t a; + xar_file_t f; + int ret, retval = 0; + + /* If we're creating an archive */ + if( XAR(x)->heap_fd != -1 ) { + char *tmpser; + void *rbuf, *wbuf = NULL; + int fd, r, off, wbytes, rbytes; + size_t rsize, wsize; + z_stream zs; + uint64_t ungztoc, gztoc; + int tocfd; + char timestr[128]; + struct tm tmptm; + time_t t; + + tmpser = (char *)xar_opt_get(x, XAR_OPT_TOCCKSUM); + /* If no checksum type is specified, default to sha1 */ + if( !tmpser ) tmpser = XAR_OPT_VAL_SHA1; + + if( (strcmp(tmpser, XAR_OPT_VAL_NONE) != 0) ) { + xar_prop_set(XAR_FILE(x), "checksum", NULL); + if( strcmp(tmpser, XAR_OPT_VAL_SHA1) == 0 ) { + XAR(x)->toc_hash_ctx = xar_hash_new("sha1", (void *)x); + XAR(x)->header.cksum_alg = htonl(XAR_CKSUM_SHA1); + xar_attr_set(XAR_FILE(x), "checksum", "style", XAR_OPT_VAL_SHA1); + xar_prop_set(XAR_FILE(x), "checksum/size", "20"); + } + if( strcmp(tmpser, XAR_OPT_VAL_SHA256) == 0 ) { + XAR(x)->toc_hash_ctx = xar_hash_new("sha256", (void *)x); + XAR(x)->header.cksum_alg = htonl(XAR_CKSUM_SHA256); + xar_attr_set(XAR_FILE(x), "checksum", "style", XAR_OPT_VAL_SHA256); + xar_prop_set(XAR_FILE(x), "checksum/size", "32"); + } + if( strcmp(tmpser, XAR_OPT_VAL_SHA512) == 0 ) { + XAR(x)->toc_hash_ctx = xar_hash_new("sha512", (void *)x); + XAR(x)->header.cksum_alg = htonl(XAR_CKSUM_SHA512); + xar_attr_set(XAR_FILE(x), "checksum", "style", XAR_OPT_VAL_SHA512); + xar_prop_set(XAR_FILE(x), "checksum/size", "64"); + } +#ifdef XAR_SUPPORT_MD5 + if( strcmp(tmpser, XAR_OPT_VAL_MD5) == 0 ) { + XAR(x)->toc_hash_ctx = xar_hash_new("md5", (void *)x); + XAR(x)->header.cksum_alg = htonl(XAR_CKSUM_MD5); + xar_attr_set(XAR_FILE(x), "checksum", "style", XAR_OPT_VAL_MD5); + xar_prop_set(XAR_FILE(x), "checksum/size", "16"); + } +#endif // XAR_SUPPORT_MD5 + + xar_prop_set(XAR_FILE(x), "checksum/offset", "0"); + } else { + XAR(x)->header.cksum_alg = XAR_CKSUM_NONE; + } + + t = time(NULL); + gmtime_r(&t, &tmptm); + memset(timestr, 0, sizeof(timestr)); + strftime(timestr, sizeof(timestr), "%FT%T", &tmptm); + xar_prop_set(XAR_FILE(x), "creation-time", timestr); + + /* serialize the toc to a tmp file */ + asprintf(&tmpser, "%s/xar.toc.XXXXXX", XAR(x)->dirname); + fd = mkstemp(tmpser); + xar_serialize(x, tmpser); + unlink(tmpser); + free(tmpser); + asprintf(&tmpser, "%s/xar.toc.XXXXXX", XAR(x)->dirname); + tocfd = mkstemp(tmpser); + unlink(tmpser); + free(tmpser); + + + /* read the toc from the tmp file, compress it, and write it + * out to the archive. + */ + rsize = wsize = 4096; + const char * opt = xar_opt_get(x, XAR_OPT_RSIZE); + if ( opt ) { + rsize = strtol(opt, NULL, 0); + if ( ((rsize == LONG_MAX) || (rsize == LONG_MIN)) && (errno == ERANGE) ) { + rsize = wsize; + } + } + + rbuf = malloc(rsize); + if( !rbuf ) { + retval = -1; + close(fd); + close(tocfd); + goto CLOSE_BAIL; + } + zs.zalloc = Z_NULL; + zs.zfree = Z_NULL; + zs.opaque = Z_NULL; + deflateInit(&zs, Z_BEST_COMPRESSION); + + ungztoc = gztoc = 0; + + while(1) { + r = read(fd, rbuf, rsize); + if( (r < 0) && (errno == EINTR) ) + continue; + if( r == 0 ) + break; + + ungztoc += r; + + zs.avail_in = r; + zs.next_in = (void *)rbuf; + zs.next_out = NULL; + zs.avail_out = 0; + + wsize = rsize/2; + + off = 0; + while( zs.avail_in != 0 ) { + size_t newlen = wsize * 2; + if (newlen > wsize) + wsize = newlen; + else + abort(); /* Someone has somehow malloced over 2^64 bits of ram. */ + + wbuf = realloc(wbuf, wsize); + + zs.next_out = ((unsigned char *)wbuf) + off; + zs.avail_out = wsize - off; + + ret = deflate(&zs, Z_SYNC_FLUSH); + off = wsize - zs.avail_out; + } + + wbytes = off; + off = 0; + do { + r = write(tocfd, ((char *)wbuf)+off, wbytes-off); + if( (r < 0) && (errno == EINTR) ) + continue; + if( r < 0 ) { + xar_err_new(x); + xar_err_set_string(x, "Error closing xar archive"); + retval = -1; + goto CLOSEEND; + } + if( XAR(x)->toc_hash_ctx ) + xar_hash_update(XAR(x)->toc_hash_ctx, ((char*)wbuf)+off, r); + off += r; + gztoc += r; + } while( off < wbytes ); + + } + + zs.next_in = NULL; + zs.avail_in = 0; + zs.next_out = wbuf; + zs.avail_out = wsize; + + deflate(&zs, Z_FINISH); + r = write(tocfd, wbuf, wsize - zs.avail_out); + gztoc += r; + if( XAR(x)->toc_hash_ctx ) + xar_hash_update(XAR(x)->toc_hash_ctx, wbuf, r); + + deflateEnd(&zs); + + /* populate the header and write it out */ + XAR(x)->header.magic = htonl(XAR_HEADER_MAGIC); + XAR(x)->header.size = ntohs(sizeof(xar_header_t)); + XAR(x)->header.version = ntohs(1); + XAR(x)->header.toc_length_uncompressed = xar_ntoh64(ungztoc); + XAR(x)->header.toc_length_compressed = xar_ntoh64(gztoc); + + write(XAR(x)->fd, &XAR(x)->header, sizeof(xar_header_t)); + + /* Copy the temp compressed toc file into the file */ + lseek(tocfd, (off_t)0, SEEK_SET); + while(1) { + r = read(tocfd, rbuf, rsize); + if( (r < 0) && (errno == EINTR) ) + continue; + if( r == 0 ) + break; + + wbytes = r; + off = 0; + do { + r = write(XAR(x)->fd, ((char *)rbuf)+off, wbytes-off); + if( (r < 0) && (errno == EINTR) ) + continue; + if( r < 0 ) { + xar_err_new(x); + xar_err_set_string(x, "Error closing xar archive"); + retval = -1; + goto CLOSEEND; + } + + off += r; + } while( off < wbytes ); + } + + if( XAR(x)->toc_hash_ctx ) { + size_t chklen = 0; + void *chkstr = xar_hash_finish(XAR(x)->toc_hash_ctx, &chklen); + write(XAR(x)->fd, chkstr, chklen); + + /* If there are any signatures, get the signed data a sign it */ + if( XAR(x)->signatures ) { + xar_signature_t sig; + uint32_t signed_len = 0; + uint8_t *signed_data = NULL; + + /* Loop through the signatures */ + for(sig = XAR(x)->signatures; sig; sig = XAR_SIGNATURE(sig)->next ){ + signed_len = XAR_SIGNATURE(sig)->len; + + /* If callback returns something other then 0, bail */ + if( 0 != sig->signer_callback( sig, sig->callback_context, chkstr, chklen, &signed_data, &signed_len ) ){ + fprintf(stderr, "Error signing data.\n"); + free(chkstr); + retval = -1; + close(fd); + close(tocfd); + goto CLOSE_BAIL; + } + + if( signed_len != XAR_SIGNATURE(sig)->len ){ + fprintf(stderr, "Signed data not the proper length. %i should be %i.\n",signed_len,XAR_SIGNATURE(sig)->len); + free(chkstr); + retval = -1; + close(fd); + close(tocfd); + goto CLOSE_BAIL; + } + + /* Write the signed data to the heap */ + write(XAR(x)->fd, signed_data,XAR_SIGNATURE(sig)->len); + + free(signed_data); + } + free(chkstr); + } + + xar_signature_remove( XAR(x)->signatures ); + XAR(x)->signatures = NULL; + } + + /* copy the heap from the temporary heap into the archive */ + if( 0 > XAR(x)->heap_to_archive(x) ) { + xar_err_new(x); + xar_err_set_string(x, "Error while copying heap contents into archive"); + xar_err_set_errno(x, errno); + xar_err_callback(x, XAR_SEVERITY_FATAL, XAR_ERR_ARCHIVE_CREATION); + retval = -1; + close(fd); + close(tocfd); + goto CLOSEEND; + } + +CLOSEEND: + close(fd); + close(tocfd); + free(rbuf); + free(wbuf); + deflateEnd(&XAR(x)->zs); + } else { + + xar_signature_remove( XAR(x)->signatures ); + XAR(x)->signatures = NULL; + + inflateEnd(&XAR(x)->zs); + } + +CLOSE_BAIL: + /* continue deallocating the archive and return */ + while(XAR(x)->subdocs) { + xar_subdoc_remove(XAR(x)->subdocs); + } + + while(XAR(x)->attrs) { + a = XAR(x)->attrs; + XAR(x)->attrs = XAR_ATTR(a)->next; + xar_attr_free(a); + } + + while(XAR(x)->props) { + xar_prop_t p; + p = XAR(x)->props; + XAR(x)->props = XAR_PROP(p)->next; + xar_prop_free(p); + } + + while(XAR(x)->files) { + f = XAR(x)->files; + XAR(x)->files = XAR_FILE(f)->next; + xar_file_free(f); + } + + xmlHashFree(XAR(x)->ino_hash, NULL); + xmlHashFree(XAR(x)->link_hash, NULL); + xmlHashFree(XAR(x)->csum_hash, NULL); + close(XAR(x)->fd); + if( XAR(x)->heap_fd >= 0 ) + close(XAR(x)->heap_fd); + free((char *)XAR(x)->filename); + free((char *)XAR(x)->dirname); + free(XAR(x)->readbuf); + free(XAR(x)->toc_hash); + free((void *)x); + + return retval; +} + +xar_header_t xar_header_get(xar_t x) +{ + return XAR(x)->header; +} + +/* xar_opt_get + * x: archive to get the option from + * option: name of the option + * Returns: a pointer to the value of the option + * In the case of more than one option with the same name, this will + * return the first match. + */ +const char *xar_opt_get(xar_t x, const char *option) { + xar_attr_t i; + for(i = XAR(x)->attrs; i && XAR_ATTR(i)->next; i = XAR_ATTR(i)->next) { + if(strcmp(XAR_ATTR(i)->key, option)==0) + return XAR_ATTR(i)->value; + } + if( i && (strcmp(XAR_ATTR(i)->key, option)==0) ) + return XAR_ATTR(i)->value; + return NULL; +} + +/* xar_opt_set + * x: the archive to set the option of + * option: the name of the option to set the value of + * value: the value to set the option to + * Returns: 0 for sucess, -1 for failure + */ +int32_t xar_opt_set(xar_t x, const char *option, const char *value) { + xar_attr_t currentAttr, a; + + if( (strcmp(option, XAR_OPT_TOCCKSUM) == 0) ) { + XAR(x)->heap_offset = xar_io_get_toc_checksum_length_for_type(value); + } + + /* This was an edit from xar-1.4 + Looks like we would only allow one definition for a particular key in this list + But xar_opt_unset is implemented to remove many pairs for the same key + + // if the attribute is already defined, find it and free its value, + // replace and return + for(currentAttr = XAR(x)->attrs; currentAttr ; currentAttr = XAR_ATTR(currentAttr)->next) { + if(strcmp(XAR_ATTR(currentAttr)->key, option)==0) { + free((char*)XAR_ATTR(currentAttr)->value); + XAR_ATTR(currentAttr)->value = strdup(value); + return 0; + } + } */ + + // otherwise create a new attribute + a = xar_attr_new(); + XAR_ATTR(a)->key = strdup(option); + XAR_ATTR(a)->value = strdup(value); + // and prepend it to the attrs list for the archive + XAR_ATTR(a)->next = XAR(x)->attrs; + XAR(x)->attrs = a; + return 0; +} + +/* xar_opt_unset + * x: the archive to set the option of + * option: the name of the option to delete + * This will delete ALL instances of the option name + */ +int32_t xar_opt_unset(xar_t x, const char *option) { + xar_attr_t currentAttr, previousAttr = NULL; + for(currentAttr = XAR(x)->attrs; + currentAttr ; + previousAttr = currentAttr, currentAttr = XAR_ATTR(currentAttr)->next) { + if(strcmp(XAR_ATTR(currentAttr)->key, option)==0) { + + // if this attribute match is the head of the attrs list + // promote the next list item to the head + if( previousAttr == NULL ) + XAR(previousAttr)->attrs = XAR_ATTR(currentAttr)->next; + + // otherwise splice the list around this attr + else + XAR_ATTR(previousAttr)->next = XAR_ATTR(currentAttr)->next; + xar_attr_free(currentAttr); + + // keep going to find other instances + currentAttr = previousAttr; + } + } + return 0; +} + +/* xar_add_node + * x: archive the file should belong to + * f: parent node, possibly NULL + * name: name of the node to add + * realpath: real path to item, this is used if the item being archived is to be located at a different location in the tree + * then it is on the real filesystem. + * Returns: newly allocated and populated node + * Summary: helper function which adds a child of f and populates + * its properties. If f is NULL, the node will be added as a top + * level node of the archive, x. + */ +static xar_file_t xar_add_node(xar_t x, xar_file_t f, const char *name, const char *prefix, const char *realpath, int srcpath) { + xar_file_t ret; + const char *path; + char *tmp; + char idstr[32]; + + if( !f ) { + if( realpath ) + asprintf(&tmp, "%s", realpath); + else + asprintf(&tmp, "%s%s%s", XAR(x)->path_prefix, prefix, name); + + if( lstat(tmp, &XAR(x)->sbcache) != 0 ) { + free(tmp); + return NULL; + } + + ret = xar_file_new(NULL); + if( !ret ) + return NULL; + memset(idstr, 0, sizeof(idstr)); + snprintf(idstr, sizeof(idstr)-1, "%"PRIu64, ++XAR(x)->last_fileid); + xar_attr_set(ret, NULL, "id", idstr); + XAR_FILE(ret)->parent = NULL; + XAR_FILE(ret)->fspath = tmp; + if( XAR(x)->files == NULL ) + XAR(x)->files = ret; + else { + XAR_FILE(ret)->next = XAR(x)->files; + XAR(x)->files = ret; + } + } else { + path = XAR_FILE(f)->fspath; + if( strcmp(prefix, "../") == 0 ) { + int len1, len2; + len1 = strlen(path); + len2 = strlen(name); + if( (len1>=len2) && (strcmp(path+(len1-len2), name) == 0) ) { + return f; + } + + } + + if( realpath ){ + asprintf(&tmp, "%s", realpath); + }else + asprintf(&tmp, "%s/%s%s", path, prefix, name); + + if( lstat(tmp, &XAR(x)->sbcache) != 0 ) { + free(tmp); + return NULL; + } + + ret = xar_file_new(f); + if( !ret ) + return NULL; + memset(idstr, 0, sizeof(idstr)); + snprintf(idstr, sizeof(idstr)-1, "%"PRIu64, ++XAR(x)->last_fileid); + xar_attr_set(ret, NULL, "id", idstr); + XAR_FILE(ret)->fspath = tmp; + } + + xar_prop_set(ret, "name", name); + + if( xar_arcmod_archive(x, ret, XAR_FILE(ret)->fspath, NULL, 0) < 0 ) { + xar_file_t i = NULL; + if( f ) { + if( ret == XAR_FILE(f)->children ) + XAR_FILE(f)->children = XAR_FILE(ret)->next; + else + for( i = XAR_FILE(f)->children; i && (XAR_FILE(i)->next != ret); i = XAR_FILE(i)->next ); + } else { + if( ret == XAR(x)->files ) + XAR(x)->files = XAR_FILE(ret)->next; + else + for( i = XAR(x)->files; i && (XAR_FILE(i)->next != ret); i = XAR_FILE(i)->next ); + } + if( i ) + XAR_FILE(i)->next = XAR_FILE(ret)->next; + xar_file_free(ret); + return NULL; + } + + return ret; +} + +/* xar_add_pseudodir + * Summary: Adds a placeholder directory when archiving a file prior + * to archiving its path. + */ +static xar_file_t xar_add_pseudodir(xar_t x, xar_file_t f, const char *name, const char *prefix, const char *realpath) +{ + xar_file_t ret; + const char *path; + char *tmp; + char idstr[32]; + + if( !f ) { + if( realpath ) + asprintf(&tmp, "%s", realpath); + else + asprintf(&tmp, "%s%s%s", XAR(x)->path_prefix, prefix, name); + + if( lstat(tmp, &XAR(x)->sbcache) != 0 ) { + free(tmp); + return NULL; + } + + ret = xar_file_new(NULL); + if( !ret ) + return NULL; + memset(idstr, 0, sizeof(idstr)); + snprintf(idstr, sizeof(idstr)-1, "%"PRIu64, ++XAR(x)->last_fileid); + xar_attr_set(ret, NULL, "id", idstr); + XAR_FILE(ret)->parent = NULL; + XAR_FILE(ret)->fspath = tmp; + if( XAR(x)->files == NULL ) + XAR(x)->files = ret; + else { + XAR_FILE(ret)->next = XAR(x)->files; + XAR(x)->files = ret; + } + } else { + path = XAR_FILE(f)->fspath; + if( strcmp(prefix, "../") == 0 ) { + int len1, len2; + len1 = strlen(path); + len2 = strlen(name); + if( (len1>=len2) && (strcmp(path+(len1-len2), name) == 0) ) { + return f; + } + + } + + if( realpath ){ + asprintf(&tmp, "%s", realpath); + }else + asprintf(&tmp, "%s/%s%s", path, prefix, name); + + if( lstat(tmp, &XAR(x)->sbcache) != 0 ) { + free(tmp); + return NULL; + } + + ret = xar_file_new(f); + if( !ret ) + return NULL; + memset(idstr, 0, sizeof(idstr)); + snprintf(idstr, sizeof(idstr)-1, "%"PRIu64, ++XAR(x)->last_fileid); + xar_attr_set(ret, NULL, "id", idstr); + XAR_FILE(ret)->fspath = tmp; + } + xar_prop_set(ret, "name", name); + xar_prop_set(ret, "type", "directory"); + + return ret; +} + +/* xar_add_r + * Summary: a recursive helper function for adding a node to the + * tree. This will search all children of node f, looking for + * the path component. If found, will recurse into it. If not, + * will add the path component to the tree, and recurse into it. + * If f is NULL, will start with x->files. + */ +static xar_file_t xar_add_r(xar_t x, xar_file_t f, const char *path, const char *prefix) { + xar_file_t i = NULL, ret, ret2, start = NULL; + char *tmp1, *tmp2, *tmp3; + + if( path && (path[0] == '\0') ) { + return f; + } + + tmp1 = tmp2 = strdup(path); + tmp3 = strsep(&tmp2, "/"); + + if( tmp3 && tmp2 && (tmp3[0] == '\0') ) { + ret2 = xar_add_r(x, f, tmp2, ""); + free(tmp1); + return ret2; + } + + if( strcmp(tmp3, "..") == 0 ) { + char *prefixstr; + if( !XAR(x)->skipwarn ) { + xar_err_new(x); + xar_err_set_string(x, "Skipping .. in path"); + xar_err_callback(x, XAR_SEVERITY_WARNING, XAR_ERR_ARCHIVE_CREATION); + XAR(x)->skipwarn = 1; + } + asprintf(&prefixstr, "%s../", prefix); + ret2 = xar_add_r(x, f, tmp2, prefixstr); + free(prefixstr); + free(tmp1); + return ret2; + } + + if( strcmp(tmp3, ".") == 0 ) { + if( tmp2 ) + ret2 = xar_add_r(x, f, tmp2, prefix); + else + ret2 = NULL; + free(tmp1); + return ret2; + } + + if( !f ) { + start = XAR(x)->files; + } else { + start = XAR_FILE(f)->children; + } + + /* Search all the siblings */ + for( i = start; i; i = XAR_FILE(i)->next ) { + const char *n; + xar_prop_get(i, "name", &n); + if( strcmp(n, tmp3) == 0 ) { + if( !tmp2 ) { + /* Node already exists, and it is i */ + free(tmp1); + return i; + } + ret2 = xar_add_r(x, i, tmp2, ""); + free(tmp1); + return ret2; + } + } + + /* tmp3 was not found in children of start, so we add it */ + if( tmp2 ) { + //ret = xar_add_node(x, f, tmp3, prefix, NULL, 1); + ret = xar_add_pseudodir(x, f, tmp3, prefix, NULL); + } else { + ret = xar_add_node(x, f, tmp3, prefix, NULL, 0); + } + + if( !ret ) { + free(tmp1); + return NULL; + } + + if( !tmp2 ) { + /* We've added the final piece, done, don't recurse */ + free(tmp1); + return ret; + } + + /* still more to add, recurse */ + ret2 = xar_add_r(x, ret, tmp2, ""); + free(tmp1); + return ret2; +} + +/* xar_add + * x: archive to add the file to + * path: path to file + * Returns: allocated an populated xar_file_t representing the + * specified file. + * Summary: if a full path "foo/bar/blah" is specified, then any + * directories not already existing in the archive will be added + * automagically. The returned xar_file_t represents the file + * specified, not the parent of the directory tree. + * For instance, if "foo/bar/blah" is specified, the xar_file_t + * representing "blah" will be returned. + */ +xar_file_t xar_add(xar_t x, const char *path) { +#ifdef __APPLE__ + xar_file_t ret; + if( (ret = xar_underbar_check(x, NULL, path)) ) + return ret; +#endif + + if( path[0] == '/' ) { + XAR(x)->path_prefix = "/"; + path++; + } else + XAR(x)->path_prefix = ""; + return xar_add_r(x, NULL, path, ""); +} + +/* xar_add_frombuffer +* x: archive to add the file to +* parent: parent node, possibly NULL +* name: name of file +* buffer: buffer for file contents +* length: length of buffer +* Returns: allocated an populated xar_file_t representing the +* specified file. +* Summary: Use this to add chunks of named data to a xar without +* using the filesystem. +*/ + +xar_file_t xar_add_frombuffer(xar_t x, xar_file_t parent, const char *name, char *buffer, size_t length) { + xar_file_t ret; + char idstr[32]; + + if( !parent ) { + ret = xar_file_new(NULL); + if( !ret ) + return NULL; + memset(idstr, 0, sizeof(idstr)); + snprintf(idstr, sizeof(idstr)-1, "%"PRIu64, ++XAR(x)->last_fileid); + xar_attr_set(ret, NULL, "id", idstr); + XAR_FILE(ret)->parent = NULL; + if( XAR(x)->files == NULL ) + XAR(x)->files = ret; + else { + XAR_FILE(ret)->next = XAR(x)->files; + XAR(x)->files = ret; + } + } else { + ret = xar_file_new(parent); + if( !ret ) + return NULL; + memset(idstr, 0, sizeof(idstr)); + snprintf(idstr, sizeof(idstr)-1, "%"PRIu64, ++XAR(x)->last_fileid); + xar_attr_set(ret, NULL, "id", idstr); + XAR_FILE(ret)->fspath = NULL; + } + + xar_prop_set(ret, "name", name); + + //int32_t xar_arcmod_archive(xar_t x, xar_file_t f, const char *file, const char *buffer, size_t len) + if( xar_arcmod_archive(x, ret, NULL , buffer , length) < 0 ) { + xar_file_t i; + if( parent ) { + for( i = XAR_FILE(parent)->children; i && (XAR_FILE(i)->next != ret); i = XAR_FILE(i)->next ); + } else { + for( i = XAR(x)->files; i && (XAR_FILE(i)->next != ret); i = XAR_FILE(i)->next ); + } + if( i ) + XAR_FILE(i)->next = XAR_FILE(ret)->next; + xar_file_free(ret); + return NULL; + } + + return ret; +} + +xar_file_t xar_add_folder(xar_t x, xar_file_t f, const char *name, struct stat *info) +{ + xar_file_t ret; + char idstr[32]; + + if( info ) + memcpy(&XAR(x)->sbcache,info,sizeof(struct stat)); + + ret = xar_file_new(f); + if( !ret ) + return NULL; + + memset(idstr, 0, sizeof(idstr)); + snprintf(idstr, sizeof(idstr)-1, "%"PRIu64, ++XAR(x)->last_fileid); + xar_attr_set(ret, NULL, "id", idstr); + XAR_FILE(ret)->fspath = NULL; + + if( !f ) { + XAR_FILE(ret)->parent = NULL; + + if( XAR(x)->files == NULL ) + XAR(x)->files = ret; + else { + XAR_FILE(ret)->next = XAR(x)->files; + XAR(x)->files = ret; + } + } + + xar_prop_set(ret, "name", name); + + if( xar_arcmod_archive(x, ret, XAR_FILE(ret)->fspath, NULL, 0) < 0 ) { + xar_file_t i; + if( f ) { + for( i = XAR_FILE(f)->children; i && (XAR_FILE(i)->next != ret); i = XAR_FILE(i)->next ); + } else { + for( i = XAR(x)->files; i && (XAR_FILE(i)->next != ret); i = XAR_FILE(i)->next ); + } + if( i ) + XAR_FILE(i)->next = XAR_FILE(ret)->next; + xar_file_free(ret); + return NULL; + } + + return ret; +} + +xar_file_t xar_add_frompath(xar_t x, xar_file_t parent, const char *name, const char *realpath) +{ + return xar_add_node(x, parent, name , "" , realpath, 1); +} + +xar_file_t xar_add_from_archive(xar_t x, xar_file_t parent, const char *name, xar_t sourcearchive, xar_file_t sourcefile) +{ + xar_file_t ret; + char idstr[32]; + + ret = xar_file_replicate(sourcefile, parent); + + if( !ret ) + return NULL; + + memset(idstr, 0, sizeof(idstr)); + snprintf(idstr, sizeof(idstr)-1, "%"PRIu64, ++XAR(x)->last_fileid); + xar_attr_set(ret, NULL, "id", idstr); + XAR_FILE(ret)->fspath = NULL; + + if( !parent ) { + XAR_FILE(ret)->parent = NULL; + + if( XAR(x)->files == NULL ) + XAR(x)->files = ret; + else { + XAR_FILE(ret)->next = XAR(x)->files; + XAR(x)->files = ret; + } + } + + xar_prop_set(ret, "name", name); + + /* iterate through all the properties, see if any of them have an offset */ + xar_prop_t p = xar_prop_pfirst(ret); + + do{ + xar_prop_t tmpp; + + tmpp = xar_prop_pget(p, "offset"); + if(tmpp) { + if( 0 != xar_attrcopy_from_heap_to_heap(sourcearchive, sourcefile, p, x, ret)){ + xar_file_free(ret); + ret = NULL; + break; + } + } + + }while( (p = xar_prop_pnext(p)) ); + + return ret; +} + +/* xar_extract_tofile +* x: archive to extract from +* f: file associated with x +* Returns 0 on success, -1 on failure +* Summary: This actually does the file extraction. +* No traversal is performed, it is assumed all directory paths +* leading up to f already exist. +*/ +int32_t xar_extract_tofile(xar_t x, xar_file_t f, const char *path) { + return xar_arcmod_extract(x, f, path,NULL, 0); +} + + +/* xar_extract_tobuffer +* x: archive to extract from +* buffer: buffer to extract to +* Returns 0 on success, -1 on failure. +* Summary: This is the entry point for extraction to a buffer. +* On success, a buffer is allocated with the contents of the file +* specified. The caller is responsible for freeing the returend buffer. +* Example: xar_extract_tobuffer(x, "foo/bar/blah",&buffer) +*/ +int32_t xar_extract_tobuffer(xar_t x, xar_file_t f, char **buffer) { + size_t size; + + return xar_extract_tobuffersz(x, f, buffer, &size); +} + +/* xar_extract_tobuffer +* x: archive to extract from +* buffer: buffer to extract to +* size: On return, this will contain the size of the memory pointed to by buffer +* Returns 0 on success, -1 on failure. +* Summary: This is the entry point for extraction to a buffer. +* On success, a buffer is allocated with the contents of the file +* specified. The caller is responsible for freeing the returend buffer. +* Example: xar_extract_tobuffer(x, "foo/bar/blah",&buffer) +*/ +int32_t xar_extract_tobuffersz(xar_t x, xar_file_t f, char **buffer, size_t *size) { + const char *sizestring = NULL; + int32_t ret; + + if(0 != xar_prop_get(f,"data/size",&sizestring)){ + if(0 != xar_prop_get(f, "type", &sizestring)) + return -1; + if(strcmp(sizestring, "file") == 0) { + *size = 0; + return 0; + } + return -1; + } + + *size = strtoull(sizestring, (char **)NULL, 10); + *buffer = malloc(*size); + + if(!(*buffer)){ + return -1; + } + + ret = xar_arcmod_extract(x,f,NULL,*buffer,*size); + if( ret ) { + *size = 0; + free(*buffer); + *buffer = NULL; + } + + return ret; +} + +int32_t xar_extract_tostream_init(xar_t x, xar_file_t f, xar_stream *stream) { + xar_prop_t tmpp; + + if( !xar_check_prop(x, "data") ) + return XAR_STREAM_OK; + + tmpp = xar_prop_pfirst(f); + if( tmpp ) + tmpp = xar_prop_find(tmpp, "data"); + if( !tmpp ) + return XAR_STREAM_OK; + + return xar_attrcopy_from_heap_to_stream_init(x, f, tmpp, stream); +} + +int32_t xar_extract_tostream(xar_stream *stream) { + return xar_attrcopy_from_heap_to_stream(stream); +} + +int32_t xar_extract_tostream_end(xar_stream *stream) { + return xar_attrcopy_from_heap_to_stream_end(stream); +} + +/* xar_extract + * x: archive to extract from + * path: path to file to extract + * Returns 0 on success, -1 on failure. + * Summary: This is the entry point for extraction. This will find + * the file node described by path, extract any directories needed + * to extract the node, and finally extract the file. + * Example: xar_extract(x, "foo/bar/blah") + * If foo does not exist, xar_extract will extract foo from the + * archive, extract bar from the archive, and then extract blah. + * Total extractions will be "foo", "foo/bar", and "foo/bar/blah". + */ +int32_t xar_extract(xar_t x, xar_file_t f) { + struct stat sb; + char *tmp1, *dname; + xar_file_t tmpf; + + if( (strstr(XAR_FILE(f)->fspath, "/") != NULL) && (stat(XAR_FILE(f)->fspath, &sb)) && (XAR_FILE(f)->parent_extracted == 0) ) { + tmp1 = strdup(XAR_FILE(f)->fspath); + dname = xar_safe_dirname(tmp1); + tmpf = xar_file_find(XAR(x)->files, dname); + if( !tmpf ) { + xar_err_set_string(x, "Unable to find file"); + xar_err_callback(x, XAR_SEVERITY_NONFATAL, XAR_ERR_ARCHIVE_EXTRACTION); + return -1; + } + free(dname); + free(tmp1); + XAR_FILE(f)->parent_extracted++; + int32_t result = xar_extract(x, tmpf); + + if (result < 0) + return result; + + } + + return xar_extract_tofile(x, f, XAR_FILE(f)->fspath); +} + +int32_t xar_verify_progress(xar_t x, xar_file_t f, xar_progress_callback p) { + return xar_arcmod_verify(x,f, p); +} + + +/* xar_verify +* x: archive to extract from +* f: file to verify +* Returns 0 on success, -1 on failure. +* Summary: This function allows for verification of +* an entry without extraction. If there is no checksum +* the verification will pass. +*/ +int32_t xar_verify(xar_t x, xar_file_t f) { + return xar_arcmod_verify(x,f, NULL); +} + +/* toc_read_callback + * context: context passed through from the reader + * buffer: buffer to read into + * len: size of buffer + * Returns: number of bytes read or -1 in case of error + * Summary: internal callback for xmlReaderForIO. + */ +static int toc_read_callback(void *context, char *buffer, int len) { + xar_t x = (xar_t)context; + int ret, off = 0; + + if ( ((!XAR(x)->offset) || (XAR(x)->offset == XAR(x)->readbuf_len)) && (XAR(x)->toc_count != XAR(x)->header.toc_length_compressed) ) { + XAR(x)->offset = 0; + size_t read_size = 0; + if( (XAR(x)->readbuf_len - off) + XAR(x)->toc_count > XAR(x)->header.toc_length_compressed ) { + read_size = XAR(x)->header.toc_length_compressed - XAR(x)->toc_count; + ret = xar_read_fd(XAR(x)->fd, XAR(x)->readbuf, read_size); + } + else { + read_size = XAR(x)->readbuf_len; + ret = read(XAR(x)->fd, XAR(x)->readbuf, read_size); + } + if ( ret == -1 || read_size != ret) + return ret; + + if ( XAR(x)->toc_hash_ctx ) + xar_hash_update(XAR(x)->toc_hash_ctx, XAR(x)->readbuf, ret); + + XAR(x)->toc_count += ret; + off += ret; + } + + if( off && (off < XAR(x)->readbuf_len) ) + XAR(x)->readbuf_len = off; + XAR(x)->zs.next_in = ((unsigned char *)XAR(x)->readbuf) + XAR(x)->offset; + XAR(x)->zs.avail_in = XAR(x)->readbuf_len - XAR(x)->offset; + XAR(x)->zs.next_out = (void *)buffer; + XAR(x)->zs.avail_out = len; + + ret = inflate(&XAR(x)->zs, Z_SYNC_FLUSH); + if( ret < 0 ) + return -1; + + XAR(x)->offset = XAR(x)->readbuf_len - XAR(x)->zs.avail_in; + + return len - XAR(x)->zs.avail_out; +} + +/* close_callback + * context: this will be a xar_t + * Returns: 0 or -1 in case of error + * Summary: this is the callback for xmlTextReaderForIO to close the IO + */ +static int close_callback(void *context) { + return 0; +} + +/* xar_serialize + * x: xar to serialize + * file: file to serialize to + * Summary: serializes the archive out to xml. + */ +void xar_serialize(xar_t x, const char *file) { + xmlTextWriterPtr writer; + xar_subdoc_t i; + + writer = xmlNewTextWriterFilename(file, 0); + xmlTextWriterStartDocument(writer, "1.0", "UTF-8", NULL); + xmlTextWriterSetIndent(writer, 4); + xmlTextWriterStartElement(writer, BAD_CAST("xar")); + + for( i = XAR(x)->subdocs; i; i = xar_subdoc_next(i) ) + xar_subdoc_serialize(i, writer, 1); + + xmlTextWriterStartElement(writer, BAD_CAST("toc")); + + if( XAR(x)->props ) + xar_prop_serialize(XAR(x)->props, writer); + + if( XAR(x)->signatures ) + xar_signature_serialize(XAR(x)->signatures,writer); + + if( XAR(x)->files ) + xar_file_serialize(XAR(x)->files, writer); + + xmlTextWriterEndDocument(writer); + xmlFreeTextWriter(writer); + return; +} + +/* xar_unserialize + * x: xar archive to unserialize to. Must have been allocated with xar_open + * file: the xml filename to unserialize from + * Summary: Takes the TOC representation from file and creates the + * corresponding in-memory representation. + */ +static int32_t xar_unserialize(xar_t x) { + xmlTextReaderPtr reader; + xar_file_t f = NULL; + const xmlChar *name, *prefix, *uri; + int type, noattr, ret; + + reader = xmlReaderForIO(toc_read_callback, close_callback, XAR(x), NULL, NULL, 0); + if( !reader ) return -1; + + while( (ret = xmlTextReaderRead(reader)) == 1 ) { + type = xmlTextReaderNodeType(reader); + noattr = xmlTextReaderAttributeCount(reader); + name = xmlTextReaderConstLocalName(reader); + if( type != XML_READER_TYPE_ELEMENT ) + continue; + if(strcmp((const char*)name, "xar") != 0) + continue; + while( (ret = xmlTextReaderRead(reader)) == 1 ) { + type = xmlTextReaderNodeType(reader); + noattr = xmlTextReaderAttributeCount(reader); + name = xmlTextReaderConstLocalName(reader); + if( type == XML_READER_TYPE_ELEMENT ) { + if(strcmp((const char*)name, "toc") == 0) { + while( (ret = xmlTextReaderRead(reader)) == 1 ) { + type = xmlTextReaderNodeType(reader); + noattr = xmlTextReaderAttributeCount(reader); + name = xmlTextReaderConstLocalName(reader); + if( type == XML_READER_TYPE_ELEMENT ) { + if(strcmp((const char*)name, "file") == 0) { + f = xar_file_unserialize(x, NULL, reader); + XAR_FILE(f)->next = XAR(x)->files; + XAR(x)->files = f; + } else if( strcmp((const char*)name, "signature") == 0 +#ifdef __APPLE__ + || strcmp((const char*)name, "x-signature") == 0 +#endif + ){ + xar_signature_t sig = NULL; + sig = xar_signature_unserialize(x, reader ); + + if( !sig ) { + xmlFreeTextReader(reader); + return -1; + } + + if( XAR(x)->signatures ) + XAR_SIGNATURE(XAR(x)->signatures)->next = XAR_SIGNATURE(sig); + else + XAR(x)->signatures = sig; + + } else { + xar_prop_unserialize(XAR_FILE(x), NULL, reader); + } + } + } + if( ret == -1 ) { + xmlFreeTextReader(reader); + return -1; + } + } else { + xar_subdoc_t s = NULL; + xar_attr_t a = NULL; + int i; + + prefix = xmlTextReaderPrefix(reader); + uri = xmlTextReaderNamespaceUri(reader); + + i = xmlTextReaderAttributeCount(reader); + if( i > 0 ) { + for(i = xmlTextReaderMoveToFirstAttribute(reader); i == 1; i = xmlTextReaderMoveToNextAttribute(reader)) { + const char *aname = (const char *)xmlTextReaderConstLocalName(reader); + const char *avalue = (const char *)xmlTextReaderConstValue(reader); + + if( aname && (strcmp("subdoc_name", aname) == 0) ) { + name = (const unsigned char *)avalue; + } else { + xar_attr_t next = a; + a = xar_attr_new(); + XAR_ATTR(a)->key = strdup(aname); + XAR_ATTR(a)->value = strdup(avalue); + XAR_ATTR(a)->next = next; + } + } + } + + s = xar_subdoc_new(x, (const char *)name); + if(s){ + if(a){ + XAR_SUBDOC(s)->attrs = XAR_ATTR(a); + } + xar_subdoc_unserialize(s, reader); + }else{ + xmlFreeTextReader(reader); + return -1; + } + } + } + if( (type == XML_READER_TYPE_END_ELEMENT) && (strcmp((const char *)name, "toc")==0) ) { + break; + } + } + if( ret == -1 ) { + xmlFreeTextReader(reader); + return -1; + } + } + + if( ret == -1 ) { + xmlFreeTextReader(reader); + return -1; + } + + xmlFreeTextReader(reader); + return 0; +} diff --git a/xar/lib/archive.h b/xar/lib/archive.h new file mode 100644 index 0000000..f926245 --- /dev/null +++ b/xar/lib/archive.h @@ -0,0 +1,109 @@ +/* + * Copyright (c) 2005-2007 Rob Braun + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Rob Braun nor the names of his contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +/* + * 03-Apr-2005 + * DRI: Rob Braun + */ +/* + * Portions Copyright 2006, Apple Computer, Inc. + * Christopher Ryan + */ + + +#ifndef _XAR_ARCHIVE_H_ +#define _XAR_ARCHIVE_H_ +#include +#include +#ifdef __APPLE__ +#include +#include +#else +#include +#endif +#include +#include +#include "xar.h" +#include "filetree.h" +#include "hash.h" + + +typedef int (*read_callback)(xar_t, xar_file_t, void *, size_t, void *context); +typedef int (*write_callback)(xar_t, xar_file_t, void *, size_t, void *context); + +struct errctx { + const char *str; + int saved_errno; + xar_file_t file; + void *usrctx; + xar_t x; +}; + +struct __xar_t { + xar_prop_t props; + xar_attr_t attrs; /* archive options, such as rsize */ + const char *prefix; + const char *ns; + const char *filler1; + const char *filler2; + xar_file_t files; /* file forest */ + const char *filename; /* name of the archive we are operating on */ + char *dirname; /* directory of the archive, used in creation */ + int fd; /* open file descriptor for the archive */ + int heap_fd; /* fd for tmp heap archive, used in creation */ + off_t heap_offset; /* current offset within the heap */ + off_t heap_len; /* current length of the heap */ + xar_header_t header; /* header of the xar archive */ + void *readbuf; /* buffer for reading/writing compressed toc */ + size_t readbuf_len; /* length of readbuf */ + size_t offset; /* offset into readbuf for keeping track + * between callbacks. */ + size_t toc_count; /* current bytes read of the toc */ + z_stream zs; /* gz state for compressing/decompressing toc */ + char *path_prefix; /* used for distinguishing absolute paths */ + err_handler ercallback; /* callback for errors/warnings */ + struct errctx errctx; /* error callback context */ + xar_subdoc_t subdocs; /* linked list of subdocs */ + xar_signature_t signatures; /* linked list of signatures */ + int32_t (*attrcopy_to_heap)(xar_t, xar_file_t, xar_prop_t, read_callback, void *); + int32_t (*attrcopy_from_heap)(xar_t, xar_file_t, xar_prop_t, write_callback, void *); + int32_t (*heap_to_archive)(xar_t); + uint64_t last_fileid; /* unique fileid's in the archive */ + xmlHashTablePtr ino_hash; /* Hash for looking up hardlinked files (add)*/ + xmlHashTablePtr link_hash; /* Hash for looking up hardlinked files (extract)*/ + xmlHashTablePtr csum_hash; /* Hash for looking up checksums of files */ + xar_hash_t toc_hash_ctx; + int toc_hash_size; /* size of toc hash that was copied during archive open */ + void *toc_hash; /* copy of the toc hash copied during archive open */ + int skipwarn; + struct stat sbcache; +}; + +#define XAR(x) ((struct __xar_t *)(x)) + +#endif /* _XAR_ARCHIVE_H_ */ diff --git a/xar/lib/arcmod.c b/xar/lib/arcmod.c new file mode 100644 index 0000000..e6be0c8 --- /dev/null +++ b/xar/lib/arcmod.c @@ -0,0 +1,148 @@ +/* + * Copyright (c) 2007 Rob Braun + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Rob Braun nor the names of his contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +/* + * 03-Apr-2005 + * DRI: Rob Braun + */ +/* + * Portions Copyright 2006, Apple Computer, Inc. + * Christopher Ryan + */ + +#include "arcmod.h" +#include "archive.h" +#include "stat.h" +#include "data.h" +#include "linuxattr.h" +#include "fbsdattr.h" +#include "darwinattr.h" +#include "ext2.h" +#include "xar.h" +#include + +struct arcmod xar_arcmods[] = { + { xar_stat_archive, xar_stat_extract }, /* must be first */ + { xar_linuxattr_archive, xar_linuxattr_extract }, + { xar_fbsdattr_archive, xar_fbsdattr_extract }, + { xar_darwinattr_archive, xar_darwinattr_extract }, + { xar_ext2attr_archive, xar_ext2attr_extract }, + { xar_data_archive, xar_data_extract }, + /* Add new modules here */ + { NULL, xar_set_perm }, + { NULL, xar_flags_extract } +}; + +/* xar_arcmod_archive + * x: archive to add the file to + * f: node representing the file + * file: the filesystem path to the file + * Returns: 0 on success + * Summary: This is the entry point to actual file archival. + */ +int32_t xar_arcmod_archive(xar_t x, xar_file_t f, const char *file, const char *buffer, size_t len) { + int i; + int32_t ret; + for(i = 0; i < (sizeof(xar_arcmods)/sizeof(struct arcmod)); i++) { + if( xar_arcmods[i].archive ) { + ret = xar_arcmods[i].archive(x, f, file, buffer, len); + if( ret < 0 ) { + return ret; + } + if( ret > 0 ) { + return 0; + } + } + } + return 0; +} + +/* xar_arcmod_extract + * x: archive to extract the file from + * f: node representing the file + * file: the filesystem path to the target file + * Returns: 0 on success + * Summary: This is the entry point to actual file archival. + */ +int32_t xar_arcmod_extract(xar_t x, xar_file_t f, const char *file, char *buffer, size_t len) { + int i; + int32_t ret; + for(i = 0; i < (sizeof(xar_arcmods)/sizeof(struct arcmod)); i++) { + if( xar_arcmods[i].extract ) { + ret = xar_arcmods[i].extract(x, f, file, buffer, len); + if( ret < 0 ) { + // If the extract failed we have corrupt asset on disk, remove, well try. + unlink(file); + return ret; + } + if( ret > 0 ) { + return 0; + } + } + } + return 0; +} + + +int32_t xar_arcmod_verify(xar_t x, xar_file_t f, xar_progress_callback p){ + return xar_data_verify(x,f, p); +} + +/* xar_check_prop + * x: xar archive + * name: name of property to check + * Description: If XAR_OPT_PROPINCLUDE is set at all, only properties + * specified for inclusion will be added. + * If XAR_OPT_PROPINCLUDE is not set, and XAR_OPT_PROPEXCLUDE is set, + * properies specified by XAR_OPT_PROPEXCLUDE will be omitted. + * Returns: 0 for not to include, 1 for include. + */ +int32_t xar_check_prop(xar_t x, const char *name) { + xar_attr_t i; + char includeset = 0; + + for(i = XAR(x)->attrs; i; i = XAR_ATTR(i)->next) { + if( strcmp(XAR_ATTR(i)->key, XAR_OPT_PROPINCLUDE) == 0 ) { + if( strcmp(XAR_ATTR(i)->value, name) == 0 ) + return 1; + includeset = 1; + } + } + + if( includeset ) + return 0; + + for(i = XAR(x)->attrs; i; i = XAR_ATTR(i)->next) { + if( strcmp(XAR_ATTR(i)->key, XAR_OPT_PROPEXCLUDE) == 0 ) { + if( strcmp(XAR_ATTR(i)->value, name) == 0 ) + return 0; + } + } + + return 1; +} diff --git a/xar/lib/arcmod.h b/xar/lib/arcmod.h new file mode 100644 index 0000000..28d9b73 --- /dev/null +++ b/xar/lib/arcmod.h @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2005-2007 Rob Braun + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Rob Braun nor the names of his contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +/* + * 03-Apr-2005 + * DRI: Rob Braun + */ +/* + * Portions Copyright 2006, Apple Computer, Inc. + * Christopher Ryan + */ + + +#ifndef _XAR_ARCMOD_H_ +#define _XAR_ARCMOD_H_ +#include "xar.h" +#include "filetree.h" + + +typedef int32_t (*arcmod_archive)(xar_t x, xar_file_t f, const char* file, const char *buffer, size_t len); +typedef int32_t (*arcmod_extract)(xar_t x, xar_file_t f, const char* file, char *buffer, size_t len); + +struct arcmod { + arcmod_archive archive; + arcmod_extract extract; +}; + +int32_t xar_arcmod_archive(xar_t x, xar_file_t f, const char *file, const char *buffer, size_t len); +int32_t xar_arcmod_extract(xar_t x, xar_file_t f, const char *file, char *buffer, size_t len); + +int32_t xar_arcmod_verify(xar_t x, xar_file_t f, xar_progress_callback p); +int32_t xar_check_prop(xar_t x, const char *name); + +#endif /* _XAR_ARCMOD_H_ */ diff --git a/xar/lib/asprintf.h b/xar/lib/asprintf.h new file mode 100644 index 0000000..c738b15 --- /dev/null +++ b/xar/lib/asprintf.h @@ -0,0 +1,92 @@ +//============================================================================== +// +// Copyright (C) 2005 Jason Evans . All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice(s), +// this list of conditions and the following disclaimer unmodified other than +// the allowable addition of one or more copyright notices. +// +// 2. Redistributions in binary form must reproduce the above copyright +// notice(s), this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) `AS IS' AND ANY EXPRESS +// OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN +// NO EVENT SHALL THE COPYRIGHT HOLDER(S) BE LIABLE FOR ANY DIRECT, INDIRECT, +// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, +// OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +// EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +//============================================================================== +// +// Emulate vasprintf() and asprintf(). +// +//============================================================================== + +#include +#include +#include + +static inline int +vasprintf(char **rResult, const char *aFormat, va_list aAp) +{ + int rVal; + char *result; + va_list ap; +#define XarAsprintfStartLen 16 + + result = (char *) malloc(XarAsprintfStartLen); + if (result == NULL) + { + rVal = -1; + goto RETURN; + } + + va_copy(ap, aAp); + rVal = vsnprintf(result, XarAsprintfStartLen, aFormat, ap); + va_end(ap); + + if (rVal == -1) + { + goto RETURN; + } + else if (rVal >= XarAsprintfStartLen) + { + free(result); + result = (char *) malloc(rVal + 1); + if (result == NULL) + { + rVal = -1; + goto RETURN; + } + + va_copy(ap, aAp); + rVal = vsnprintf(result, rVal + 1, aFormat, aAp); + va_end(ap); + } + + *rResult = result; + RETURN: +#undef XarAsprintfStartLen + return rVal; +} + +static int +asprintf(char **rResult, const char *aFormat, ...) +{ + int rVal; + va_list ap; + + va_start(ap, aFormat); + rVal = vasprintf(rResult, aFormat, ap); + va_end(ap); + + return rVal; +} diff --git a/xar/lib/b64.c b/xar/lib/b64.c new file mode 100644 index 0000000..6361acd --- /dev/null +++ b/xar/lib/b64.c @@ -0,0 +1,217 @@ +/* + * Copyright (c) 2004 Rob Braun + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Rob Braun nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +/* + * 1-Oct-2004 + * DRI: Rob Braun + */ + +#include +#include + +#ifdef _BTEST_ +int main(int argc, char* argv[]) { + unsigned char* enc = benc(argv[1], strlen(argv[1])); + printf("%s", enc); + printf("%s\n", bdec(enc, strlen(enc))); +} +#endif + + +/* + * The code below derives from "Secure Programming Cookbook for C and + * C++"* and adapted by Kogule, Ryo (kogule@opendarwin.org). + * + * *John Viega and Matt Messier, O'Reilly, 2003 + * http://www.secureprogramming.com/ + * + * Readability improvements by Luke Bellandi, 2007 (luke@apple.com) + */ + +typedef enum _B64CommandCodes { + B64_NullTerminator = -3, + B64_PaddingCharacter = -2, + B64_IgnorableCharacter = -1 +} B64CommandCodes; + +static char b64revtb[256] = { + -3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*0-15*/ + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*16-31*/ + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, -1, -1, 63, /*32-47*/ + 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -2, -1, -1, /*48-63*/ + -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, /*64-79*/ + 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1, /*80-95*/ + -1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, /*96-111*/ + 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1, -1, -1, -1, /*112-127*/ + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*128-143*/ + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*144-159*/ + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*160-175*/ + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*176-191*/ + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*192-207*/ + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*208-223*/ + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*224-239*/ + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 /*240-255*/ +}; + +typedef enum _B64CodecErrorCodes { + B64_noError = 0, + B64_decodeError = 1, + B64_bufferOverrun = 2 +} B64CodecErrorCodes; + +#define B64_INPUT_BLOCK_OFFSET ((inputIndex - 1 - ignorableCharacterCount) % 4) + +static unsigned int raw_base64_decode( + const unsigned char *input, unsigned char *output, size_t inLengthToDecode, + size_t *outputDecodedLength) +{ + int currentBase64Value; + unsigned int inputIndex = 0; + unsigned int ignorableCharacterCount = 0; + unsigned int i; + unsigned char decodedBuffer[3]; + unsigned char currentInputBlockPaddingCharacterCount = 0; + size_t *decodedCharacterCount; + size_t dummyValue; + + if (outputDecodedLength == NULL) { + // do this so that if caller passes in NULL for outputDecodedLength + // it can still be handled easily + decodedCharacterCount = &dummyValue; + } else { + decodedCharacterCount = outputDecodedLength; + } + *decodedCharacterCount = 0; + + while ( (inputIndex <= inLengthToDecode) && + (currentInputBlockPaddingCharacterCount == 0) ) + { + currentBase64Value = b64revtb[input[inputIndex]]; + inputIndex++; + + switch (currentBase64Value) { + // [1] Handle control characters + case B64_NullTerminator: + if (B64_INPUT_BLOCK_OFFSET != 0) return B64_decodeError; + // copy remaining characters with padding + if (currentInputBlockPaddingCharacterCount > 0) { + for (i = 0; i < (3 - currentInputBlockPaddingCharacterCount); i++) { + *output++ = decodedBuffer[i]; + (*decodedCharacterCount)++; + } + } + return B64_noError; + + case B64_PaddingCharacter: + if (B64_INPUT_BLOCK_OFFSET < 2) { + /* Invalid here -- only characters 3 and/or 4 of the + input block can be padding */ + return B64_decodeError; + } else if (B64_INPUT_BLOCK_OFFSET == 2) { + /* inputIndex points to the next byte in the input buffer. If this is the last byte the + inputIndex is dangling past the end of the array. If it is, then by definition = is not + the next char. Just throw overrun.*/ + if (inputIndex > inLengthToDecode) + { + return B64_bufferOverrun; + } + + /* Make sure there's appropriate padding */ + if (input[inputIndex] != '=') return B64_decodeError; + decodedBuffer[2] = 0; + currentInputBlockPaddingCharacterCount = 2; + break; + } else { + currentInputBlockPaddingCharacterCount = 1; + break; + } + return B64_noError; + + case B64_IgnorableCharacter: + ignorableCharacterCount++; + break; + + default: + // [2] Handle encoded data + switch (B64_INPUT_BLOCK_OFFSET) { + case 0: + decodedBuffer[0] = currentBase64Value << 2; + break; + case 1: + decodedBuffer[0] |= (currentBase64Value >> 4); + decodedBuffer[1] = currentBase64Value << 4; + break; + case 2: + decodedBuffer[1] |= (currentBase64Value >> 2); + decodedBuffer[2] = currentBase64Value << 6; + break; + case 3: + decodedBuffer[2] |= currentBase64Value; + for (i = 0; i < (3 - currentInputBlockPaddingCharacterCount); i++) { + *output++ = decodedBuffer[i]; + (*decodedCharacterCount)++; + } + break; + } + break; + } + } + + if (inputIndex > inLengthToDecode) + { + return B64_bufferOverrun; + } + + for (i = 0; i < (3 - currentInputBlockPaddingCharacterCount); i++) { + *output++ = decodedBuffer[i]; + (*decodedCharacterCount)++; + } + + return B64_noError; +} + +unsigned char* xar_from_base64(const unsigned char* input, size_t inputLength, size_t *outputLength) +{ + int err; + unsigned char *output; + + // N.B.: This is a conservative estimate of space needed. It is NOT + // an exact value -- the exact length of the decoded data will be + // calculated during the decode operation. + output = calloc(1, 3 * (inputLength / 4 + 1)); + if (output == NULL) return NULL; + + err = raw_base64_decode(input, output, inputLength, outputLength); + + if (err != B64_noError) { + free(output); + return NULL; + } + + return output; +} diff --git a/xar/lib/b64.h b/xar/lib/b64.h new file mode 100644 index 0000000..da0d04a --- /dev/null +++ b/xar/lib/b64.h @@ -0,0 +1,12 @@ +/* + * Rob Braun + * 1-Oct-2004 + * Copyright (c) 2004 Rob Braun. All rights reserved. + */ + +#ifndef _XAR_BASE64_H_ +#define _XAR_BASE64_H_ + +unsigned char* xar_from_base64(const unsigned char* input, size_t inputLength, size_t *outputLength); + +#endif /* _XAR_BASE64_H_ */ diff --git a/xar/lib/bzxar.c b/xar/lib/bzxar.c new file mode 100644 index 0000000..181763b --- /dev/null +++ b/xar/lib/bzxar.c @@ -0,0 +1,294 @@ +/* + * Copyright (c) 2005-2007 Rob Braun + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Rob Braun nor the names of his contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +/* + * 03-Apr-2005 + * DRI: Rob Braun + */ +/* + * Portions Copyright 2006, Apple Computer, Inc. + * Christopher Ryan +*/ + + +#include "config.h" +#ifndef HAVE_ASPRINTF +#include "asprintf.h" +#endif +#include +#include +#include +#include +#include +#ifdef HAVE_LIBBZ2 +#include +#endif +#include "xar.h" +#include "filetree.h" +#include "io.h" + +#ifdef HAVE_LIBBZ2 + +struct _bzip_context{ + uint8_t bzipcompressed; + bz_stream bz; +}; + + +#define BZIP2_CONTEXT(x) ((struct _bzip_context *)(*x)) +#endif + +int xar_bzip_fromheap_done(xar_t x, xar_file_t f, xar_prop_t p, void **context) { +#ifdef HAVE_LIBBZ2 + + if( !context || !BZIP2_CONTEXT(context) ) + return 0; + + if( BZIP2_CONTEXT(context)->bzipcompressed){ + BZ2_bzDecompressEnd(&BZIP2_CONTEXT(context)->bz); + } + + /* free the context */ + free(BZIP2_CONTEXT(context)); + *context = NULL; + +#endif /* HAVE_LIBBZ2 */ + return 0; +} + +int xar_bzip_fromheap_in(xar_t x, xar_file_t f, xar_prop_t p, void **in, size_t *inlen, void **context) { + const char *opt; + xar_prop_t tmpp; +#ifdef HAVE_LIBBZ2 + void *out = NULL; + size_t outlen, offset = 0; + int r; + + /* on first run, we init the context and check the compression type */ + if( !BZIP2_CONTEXT(context) ) { + *context = calloc(1,sizeof(struct _bzip_context)); + + opt = NULL; + tmpp = xar_prop_pget(p, "encoding"); + if( tmpp ) + opt = xar_attr_pget(f, tmpp, "style"); + if( !opt ) return 0; + if( strcmp(opt, "application/x-bzip2") != 0 ) return 0; + + BZ2_bzDecompressInit(&BZIP2_CONTEXT(context)->bz, 0, 0); + BZIP2_CONTEXT(context)->bzipcompressed = 1; + if( *inlen == 0 ) + return 0; + }else if( !(BZIP2_CONTEXT(context)->bzipcompressed) ){ + /* once the context has been initialized, then we have already + checked the compression type, so we need only check if we + actually are compressed */ + return 0; + } + + outlen = *inlen; + + BZIP2_CONTEXT(context)->bz.next_in = *in; + BZIP2_CONTEXT(context)->bz.avail_in = *inlen; + BZIP2_CONTEXT(context)->bz.next_out = out; + BZIP2_CONTEXT(context)->bz.avail_out = 0; + + while( BZIP2_CONTEXT(context)->bz.avail_in != 0 ) { + size_t newlen = outlen * 2; + if (newlen > outlen) + outlen = newlen; + else + abort(); /* Someone has somehow malloced over 2^64 bits of ram. */ + + out = realloc(out, outlen); + if( out == NULL ) abort(); + + BZIP2_CONTEXT(context)->bz.next_out = ((char *)out) + offset; + BZIP2_CONTEXT(context)->bz.avail_out = outlen - offset; + + r = BZ2_bzDecompress(&BZIP2_CONTEXT(context)->bz); + if( (r != BZ_OK) && (r != BZ_STREAM_END) ) { + xar_err_new(x); + xar_err_set_file(x, f); + xar_err_set_string(x, "Error decompressing file"); + xar_err_callback(x, XAR_SEVERITY_FATAL, XAR_ERR_ARCHIVE_EXTRACTION); + return -1; + } + offset += outlen - offset - BZIP2_CONTEXT(context)->bz.avail_out; + if( (r == BZ_STREAM_END) && (offset == 0) ) + break; + } + + free(*in); + *in = out; + *inlen = offset; +#else + opt = NULL; + tmpp = xar_prop_pget(p, "encoding"); + if( tmpp ) + opt = xar_attr_pget(f, tmpp, "style"); + if( !opt ) return 0; + if( strcmp(opt, "application/x-bzip2") != 0 ) return 0; + xar_err_new(x); + xar_err_set_file(x, f); + xar_err_set_errno(x, 0); + xar_err_set_string(x, "bzip2 support not compiled in."); + xar_err_callback(x, XAR_SEVERITY_FATAL, XAR_ERR_ARCHIVE_EXTRACTION); + +#endif /* HAVE_LIBBZ2 */ + return 0; +} + +int xar_bzip_toheap_done(xar_t x, xar_file_t f, xar_prop_t p, void **context) { +#ifdef HAVE_LIBBZ2 + xar_prop_t tmpp; + + if( BZIP2_CONTEXT(context)->bzipcompressed){ + BZ2_bzCompressEnd(&BZIP2_CONTEXT(context)->bz); + + tmpp = xar_prop_pset(f, p, "encoding", NULL); + if( tmpp ) + xar_attr_pset(f, tmpp, "style", "application/x-bzip2"); + } + + /* free the context */ + free(BZIP2_CONTEXT(context)); + *context = NULL; + +#endif /* HAVE_LIBBZ2 */ + return 0; +} + +int32_t xar_bzip_toheap_in(xar_t x, xar_file_t f, xar_prop_t p, void **in, size_t *inlen, void **context) { + const char *opt; +#ifdef HAVE_LIBBZ2 + void *out = NULL; + size_t outlen, offset = 0; + int r; + + /* on first run, we init the context and check the compression type */ + if( !BZIP2_CONTEXT(context) ) { + int level = 9; + *context = calloc(1,sizeof(struct _bzip_context)); + + opt = xar_opt_get(x, XAR_OPT_COMPRESSION); + if( !opt ) + return 0; + + if( strcmp(opt, XAR_OPT_VAL_BZIP) != 0 ) + return 0; + + opt = xar_opt_get(x, XAR_OPT_COMPRESSIONARG); + if( opt ) { + int tmp; + errno = 0; + tmp = strtol(opt, NULL, 10); + if( errno == 0 ) { + if( (level >= 0) && (level <= 9) ) + level = tmp; + } + } + + BZ2_bzCompressInit(&BZIP2_CONTEXT(context)->bz, level, 0, 30); + BZIP2_CONTEXT(context)->bzipcompressed = 1; + }else if( !BZIP2_CONTEXT(context)->bzipcompressed ){ + /* once the context has been initialized, then we have already + checked the compression type, so we need only check if we + actually are compressed */ + return 0; + } + + outlen = *inlen/2; + if(outlen == 0) outlen = 1024; + BZIP2_CONTEXT(context)->bz.next_in = *in; + BZIP2_CONTEXT(context)->bz.avail_in = *inlen; + BZIP2_CONTEXT(context)->bz.next_out = out; + BZIP2_CONTEXT(context)->bz.avail_out = 0; + + if( *inlen != 0 ) { + do { + size_t newlen = outlen * 2; + if (newlen > outlen) + outlen = newlen; + else + abort(); /* Someone has somehow malloced over 2^64 bits of ram. */ + + out = realloc(out, outlen); + if( out == NULL ) abort(); + + BZIP2_CONTEXT(context)->bz.next_out = ((char *)out) + offset; + BZIP2_CONTEXT(context)->bz.avail_out = outlen - offset; + + r = BZ2_bzCompress(&BZIP2_CONTEXT(context)->bz, BZ_RUN); + offset = outlen - BZIP2_CONTEXT(context)->bz.avail_out; + } while( r == BZ_RUN_OK && BZIP2_CONTEXT(context)->bz.avail_in != 0 ); + } else { + do { + size_t newlen = outlen * 2; + if (newlen > outlen) + outlen = newlen; + else + abort(); /* Someone has somehow malloced over 2^64 bits of ram. */ + + out = realloc(out, outlen); + if( out == NULL ) abort(); + + BZIP2_CONTEXT(context)->bz.next_out = ((char *)out) + offset; + BZIP2_CONTEXT(context)->bz.avail_out = outlen - offset; + + r = BZ2_bzCompress(&BZIP2_CONTEXT(context)->bz, BZ_FINISH); + offset = outlen - BZIP2_CONTEXT(context)->bz.avail_out; + } while( (r == BZ_FINISH_OK) && (r != BZ_STREAM_END /* no-op */) ); + } + + if( (r != BZ_RUN_OK && r != BZ_STREAM_END && r != BZ_SEQUENCE_ERROR) ) { + xar_err_new(x); + xar_err_set_file(x, f); + xar_err_set_string(x, "Error compressing file"); + xar_err_set_errno(x, r); + xar_err_callback(x, XAR_SEVERITY_FATAL, XAR_ERR_ARCHIVE_CREATION); + return -1; + } + + free(*in); + *in = out; + *inlen = offset; +#else + opt = xar_opt_get(x, XAR_OPT_COMPRESSION); + if( !opt ) + return 0; + if( strcmp(opt, XAR_OPT_VAL_BZIP) != 0 ) + return 0; + xar_err_new(x); + xar_err_set_file(x, f); + xar_err_set_errno(x, 0); + xar_err_set_string(x, "bzip2 support not compiled in."); + xar_err_callback(x, XAR_SEVERITY_FATAL, XAR_ERR_ARCHIVE_CREATION); +#endif /* HAVE_LIBBZ2 */ + return 0; +} diff --git a/xar/lib/bzxar.h b/xar/lib/bzxar.h new file mode 100644 index 0000000..f90f455 --- /dev/null +++ b/xar/lib/bzxar.h @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2005-2007 Rob Braun + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Rob Braun nor the names of his contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +/* + * 03-Apr-2005 + * DRI: Rob Braun + */ +/* + * Portions Copyright 2006, Apple Computer, Inc. + * Christopher Ryan +*/ + +#ifndef _XAR_BZLIB_H_ +#define _XAR_BZLIB_H_ + +int xar_bzip_fromheap_in(xar_t x, xar_file_t f, xar_prop_t p, void **in, size_t *inlen, void **context); +int xar_bzip_fromheap_done(xar_t x, xar_file_t f, xar_prop_t p, void **context); + +int32_t xar_bzip_toheap_in(xar_t x, xar_file_t f, xar_prop_t p, void **in, size_t *inlen, void **context); +int xar_bzip_toheap_done(xar_t x, xar_file_t f, xar_prop_t p, void **context); + +#endif /* _XAR_BZLIB_H_ */ diff --git a/xar/lib/darwinattr.c b/xar/lib/darwinattr.c new file mode 100644 index 0000000..4938965 --- /dev/null +++ b/xar/lib/darwinattr.c @@ -0,0 +1,814 @@ +/* + * Copyright (c) 2008 Rob Braun + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Rob Braun nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +/* + * 24-Apr-2005 + * DRI: Rob Braun + */ +/* + * Portions Copyright 2006, Apple Computer, Inc. + * Christopher Ryan +*/ + +#include "config.h" +#include +#include +#include +#include +#include +#include +#include +#include "xar.h" +#include "arcmod.h" +#include "b64.h" +#include +#include +#include "util.h" +#include "linuxattr.h" +#include "io.h" +#include "appledouble.h" +#include "stat.h" +#include "archive.h" + +#if defined(HAVE_SYS_XATTR_H) +#include +#endif + +struct _darwinattr_context{ + int fd; + char *finfo; + char *buf; + int len; + int off; +}; + +#define DARWINATTR_CONTEXT(x) ((struct _darwinattr_context *)(x)) +#if defined(__APPLE__) +#ifdef HAVE_GETATTRLIST +#include +#include +struct fi { + uint32_t length; + fsobj_type_t objtype; + char finderinfo[32]; +}; + +/* finfo_read + * This is for archiving the finderinfo via the getattrlist method. + * This function is used from the nonea_archive() function. + */ +static int32_t finfo_read(xar_t x, xar_file_t f, void *buf, size_t len, void *context) { + if( len < 32 ) + return -1; + + if( DARWINATTR_CONTEXT(context)->finfo == NULL ) + return 0; + + memcpy(buf, DARWINATTR_CONTEXT(context)->finfo, 32); + DARWINATTR_CONTEXT(context)->finfo = NULL; + return 32; +} + +/* finfo_write + * This is for extracting the finderinfo via the setattrlist method. + * This function is used from the nonea_extract() function. + */ +static int32_t finfo_write(xar_t x, xar_file_t f, void *buf, size_t len, void *context) { + struct attrlist attrs; + struct fi finfo; + + if( len < 32 ) + return -1; + if( DARWINATTR_CONTEXT(context)->finfo == NULL ) + return 0; + + memset(&attrs, 0, sizeof(attrs)); + attrs.bitmapcount = ATTR_BIT_MAP_COUNT; + attrs.commonattr = ATTR_CMN_OBJTYPE | ATTR_CMN_FNDRINFO; + + getattrlist(DARWINATTR_CONTEXT(context)->finfo, &attrs, &finfo, sizeof(finfo), 0); + + attrs.commonattr = ATTR_CMN_FNDRINFO; + if( setattrlist(DARWINATTR_CONTEXT(context)->finfo, &attrs, buf, 32, 0) != 0 ) + return -1; + + DARWINATTR_CONTEXT(context)->finfo = NULL; + return 32; +} +#endif /* HAVE_GETATTRLIST */ + +/* xar_rsrc_read + * This is the read callback function for archiving the resource fork via + * the ..namedfork method. This callback is used from nonea_archive() + */ +static int32_t xar_rsrc_read(xar_t x, xar_file_t f, void *inbuf, size_t bsize, void *context) { + int32_t r; + + while(1) { + r = read(DARWINATTR_CONTEXT(context)->fd, inbuf, bsize); + if( (r < 0) && (errno == EINTR) ) + continue; + return r; + } +} +#endif /* __APPLE__ */ + +/* xar_rsrc_write + * This is the write callback function for writing the resource fork + * back to the file via ..namedfork method. This is the callback used + * in nonea_extract() and underbar_extract(). + */ +static int32_t xar_rsrc_write(xar_t x, xar_file_t f, void *buf, size_t len, void *context) { + int32_t r; + size_t off = 0; + do { + r = write(DARWINATTR_CONTEXT(context)->fd, ((char *)buf)+off, len-off); + if( (r < 0) && (errno != EINTR) ) + return r; + off += r; + } while( off < len ); + return off; +} + +#ifdef __APPLE__ +#if defined(HAVE_GETXATTR) + +static int32_t xar_ea_read(xar_t x, xar_file_t f, void *buf, size_t len, void *context) { + if( DARWINATTR_CONTEXT(context)->buf == NULL ) + return 0; + + if( ((DARWINATTR_CONTEXT(context)->len)-(DARWINATTR_CONTEXT(context)->off)) <= len ) { + int siz = (DARWINATTR_CONTEXT(context)->len)-(DARWINATTR_CONTEXT(context)->off); + memcpy(buf, DARWINATTR_CONTEXT(context)->buf+DARWINATTR_CONTEXT(context)->off, siz); + free(DARWINATTR_CONTEXT(context)->buf); + DARWINATTR_CONTEXT(context)->buf = NULL; + DARWINATTR_CONTEXT(context)->off = 0; + DARWINATTR_CONTEXT(context)->len = 0; + return siz; + } + + memcpy(buf, DARWINATTR_CONTEXT(context)->buf+DARWINATTR_CONTEXT(context)->off, len); + DARWINATTR_CONTEXT(context)->off += len; + + if( DARWINATTR_CONTEXT(context)->off == DARWINATTR_CONTEXT(context)->len ) { + free(DARWINATTR_CONTEXT(context)->buf); + DARWINATTR_CONTEXT(context)->buf = NULL; + DARWINATTR_CONTEXT(context)->off = 0; + DARWINATTR_CONTEXT(context)->len = 0; + } + + return len; +} + +static int32_t xar_ea_write(xar_t x, xar_file_t f, void *buf, size_t len, void *context) { + if( DARWINATTR_CONTEXT(context)->buf == NULL ) + return 0; + + if( DARWINATTR_CONTEXT(context)->off == DARWINATTR_CONTEXT(context)->len ) + return 0; + + if( ((DARWINATTR_CONTEXT(context)->len)-(DARWINATTR_CONTEXT(context)->off)) <= len ) { + int siz = (DARWINATTR_CONTEXT(context)->len)-(DARWINATTR_CONTEXT(context)->off); + memcpy((DARWINATTR_CONTEXT(context)->buf)+(DARWINATTR_CONTEXT(context)->off), buf, siz); + return siz; + } + + memcpy((DARWINATTR_CONTEXT(context)->buf)+(DARWINATTR_CONTEXT(context)->off), buf, len); + DARWINATTR_CONTEXT(context)->off += len; + + return len; +} + +static int32_t ea_archive(xar_t x, xar_file_t f, const char* file, void *context) { + char *buf, *i; + int ret, bufsz, attrsz; + int32_t retval = 0; + + if( file == NULL ) + return 0; + + ret = listxattr(file, NULL, 0, XATTR_NOFOLLOW); + if( ret < 0 ) + return -1; + if( ret == 0 ) + return 0; + bufsz = ret; + +TRYAGAIN: + buf = malloc(bufsz); + if( !buf ) + goto TRYAGAIN; + ret = listxattr(file, buf, bufsz, XATTR_NOFOLLOW); + if( ret < 0 ) { + switch(errno) { + case ERANGE: bufsz = bufsz*2; free(buf); goto TRYAGAIN; + case ENOTSUP: retval = 0; goto BAIL; + default: retval = -1; goto BAIL; + }; + } + if( ret == 0 ) { + retval = 0; + goto BAIL; + } + + attrsz = ret; + for( i = buf; (i-buf) < attrsz; i += strlen(i)+1 ) { + xar_ea_t e; + + ret = getxattr(file, i, NULL, 0, 0, XATTR_NOFOLLOW); + if( ret < 0 ) + continue; + DARWINATTR_CONTEXT(context)->len = ret; + DARWINATTR_CONTEXT(context)->buf = malloc(DARWINATTR_CONTEXT(context)->len); + if( !DARWINATTR_CONTEXT(context)->buf ) + goto BAIL; + + ret = getxattr(file, i, DARWINATTR_CONTEXT(context)->buf, DARWINATTR_CONTEXT(context)->len, 0, XATTR_NOFOLLOW); + if( ret < 0 ) { + free(DARWINATTR_CONTEXT(context)->buf); + DARWINATTR_CONTEXT(context)->buf = NULL; + DARWINATTR_CONTEXT(context)->len = 0; + continue; + } + + e = xar_ea_new(f, i); + + if (XAR(x)->attrcopy_to_heap(x, f, xar_ea_root(e), xar_ea_read, context) < 0) { + retval = -1; + goto BAIL; + } + } +BAIL: + free(buf); + return retval; +} + +static int32_t ea_extract(xar_t x, xar_file_t f, const char* file, void *context) { + xar_prop_t p; + + for(p = xar_prop_pfirst(f); p; p = xar_prop_pnext(p)) { + const char *opt; + const char *name = NULL; + int len; + xar_prop_t tmpp; + + name = xar_prop_getkey(p); + if( strncmp(name, XAR_EA_FORK, strlen(XAR_EA_FORK)) ) + continue; + if( strlen(name) != strlen(XAR_EA_FORK) ) + continue; + + opt = NULL; + tmpp = xar_prop_pget(p, "size"); + if( tmpp ) + opt = xar_prop_getvalue(tmpp); + if( !opt ) + continue; + + len = strtol(opt, NULL, 10); + DARWINATTR_CONTEXT(context)->buf = malloc(len); + if( !DARWINATTR_CONTEXT(context)->buf ) + return -1; + DARWINATTR_CONTEXT(context)->len = len; + + if (XAR(x)->attrcopy_from_heap(x, f, p, xar_ea_write, context) < 0) + return -1; + + name = NULL; + tmpp = xar_prop_pget(p, "name"); + if( tmpp ) + name = xar_prop_getvalue(tmpp); + if( !name ) + continue; + + setxattr(file, name, DARWINATTR_CONTEXT(context)->buf, DARWINATTR_CONTEXT(context)->len, 0, XATTR_NOFOLLOW); + free(DARWINATTR_CONTEXT(context)->buf); + DARWINATTR_CONTEXT(context)->buf = NULL; + DARWINATTR_CONTEXT(context)->len = 0; + DARWINATTR_CONTEXT(context)->off = 0; + } + + return 0; +} +#endif /* HAVE_GETXATTR */ + +/* nonea_archive + * Archive the finderinfo and resource fork through getattrlist and + * ..namedfork methods rather than via EAs. This is mainly for 10.3 + * and earlier support + */ +static int32_t nonea_archive(xar_t x, xar_file_t f, const char* file, void *context) { + char rsrcname[4096]; + struct stat sb; + xar_ea_t e; +#ifdef HAVE_GETATTRLIST + struct attrlist attrs; + struct fi finfo; + int ret; + char z[32]; + + memset(&attrs, 0, sizeof(attrs)); + attrs.bitmapcount = ATTR_BIT_MAP_COUNT; + attrs.commonattr = ATTR_CMN_OBJTYPE | ATTR_CMN_FNDRINFO; + + ret = getattrlist(file, &attrs, &finfo, sizeof(finfo), 0); + if( ret != 0 ) + return -1; + + memset(z, 0, sizeof(z)); + if( memcmp(finfo.finderinfo, z, sizeof(finfo.finderinfo)) != 0 ) { + e = xar_ea_new(f, "com.apple.FinderInfo"); + DARWINATTR_CONTEXT(context)->finfo = finfo.finderinfo; + if (XAR(x)->attrcopy_to_heap(x, f, xar_ea_root(e), finfo_read, context) < 0) + return -1; + } + + +#endif /* HAVE_GETATTRLIST */ + + + memset(rsrcname, 0, sizeof(rsrcname)); + snprintf(rsrcname, sizeof(rsrcname)-1, "%s/..namedfork/rsrc", file); + if( lstat(rsrcname, &sb) != 0 ) + return 0; + + if( sb.st_size == 0 ) + return 0; + + DARWINATTR_CONTEXT(context)->fd = open(rsrcname, O_RDONLY, 0); + if( DARWINATTR_CONTEXT(context)->fd < 0 ) + return -1; + + e = xar_ea_new(f, "com.apple.ResourceFork"); + if (XAR(x)->attrcopy_to_heap(x, f, xar_ea_root(e), xar_rsrc_read, context) < 0) { + close(DARWINATTR_CONTEXT(context)->fd); + return -1; + } + + close(DARWINATTR_CONTEXT(context)->fd); + return 0; +} + +/* nonea_extract + * Extract the finderinfo and resource fork through setattrlist and + * ..namedfork methods rather than via EAs. This is mainly for 10.3 + * and earlier support + */ +static int32_t nonea_extract(xar_t x, xar_file_t f, const char* file, void *context) { + char rsrcname[4096]; + xar_prop_t p; +#ifdef HAVE_SETATTRLIST + struct attrlist attrs; + struct fi finfo; + int ret; + + memset(&attrs, 0, sizeof(attrs)); + attrs.bitmapcount = ATTR_BIT_MAP_COUNT; + attrs.commonattr = ATTR_CMN_OBJTYPE | ATTR_CMN_FNDRINFO; + + ret = getattrlist(file, &attrs, &finfo, sizeof(finfo), 0); + if( ret != 0 ) + return -1; + + DARWINATTR_CONTEXT(context)->finfo = (char *)file; + + p = xar_ea_find(f, "com.apple.ResourceFork"); + if( p ) { + if (XAR(x)->attrcopy_from_heap(x, f, p, finfo_write, context) < 0) { + return -1; + } + } +#endif /* HAVE_SETATTRLIST */ + + memset(rsrcname, 0, sizeof(rsrcname)); + snprintf(rsrcname, sizeof(rsrcname)-1, "%s/..namedfork/rsrc", file); + DARWINATTR_CONTEXT(context)->fd = open(rsrcname, O_RDWR|O_TRUNC); + if( DARWINATTR_CONTEXT(context)->fd < 0 ) + return 0; + + p = xar_ea_find(f, "com.apple.ResourceFork"); + if( p ) { + if (XAR(x)->attrcopy_from_heap(x, f, p, xar_rsrc_write, context) < 0) { + close(DARWINATTR_CONTEXT(context)->fd); + return -1; + } + } + + close(DARWINATTR_CONTEXT(context)->fd); + return 0; +} +#endif /* __APPLE__ */ + +/* xar_underbar_check + * Check to see if the file we're archiving is a ._ file. If so, + * stop the archival process. + */ +xar_file_t xar_underbar_check(xar_t x, xar_file_t f, const char* file, void *context) { + char *bname, *tmp; + + tmp = strdup(file); + bname = basename(tmp); + + if(bname && (bname[0] == '.') && (bname[1] == '_')) { + char *nonunderbar, *nupath, *tmp2, *dname; + struct stat sb; + + nonunderbar = bname+2; + tmp2 = strdup(file); + dname = xar_safe_dirname(tmp2); + asprintf(&nupath, "%s/%s", dname, nonunderbar); + free(dname); + free(tmp2); + + /* if there is no file that the ._ corresponds to, archive + * it like a normal file. + */ + if( stat(nupath, &sb) ) { + free(tmp); + free(nupath); + return NULL; + } + + asprintf(&tmp2, "%s/..namedfork/rsrc", nupath); + + /* If there is a file that the ._ file corresponds to, and + * there is no resource fork, assume the ._ file contains + * the file's resource fork, and skip it (to be picked up + * when the file is archived. + */ + if( stat(tmp2, &sb) ) { + xar_file_t tmpf; + tmpf = xar_file_find(XAR(x)->files, nupath); + if( !tmpf ) { + tmpf = xar_add(x, nupath); + } + free(nupath); + free(tmp2); + free(tmp); + return tmpf; + } + + /* otherwise, we have a corresponding file and it supports + * resource forks, so we assume this is a detached ._ file + * and archive it as a real file. + */ + free(nupath); + free(tmp2); + free(tmp); + return NULL; + } + + free(tmp); + return NULL; +} + +#ifdef __APPLE__ +/* This only really makes sense on OSX */ +static int32_t underbar_archive(xar_t x, xar_file_t f, const char* file, void *context) { + struct stat sb; + char underbarname[4096], z[32]; + char *dname, *bname, *tmp, *tmp2; + struct AppleSingleHeader ash; + struct AppleSingleEntry ase; + int num_entries = 0, i, r; + off_t off; + + if( !file ) + return 0; + + tmp = strdup(file); + tmp2 = strdup(file); + dname = xar_safe_dirname(tmp2); + bname = basename(tmp); + + memset(underbarname, 0, sizeof(underbarname)); + snprintf(underbarname, sizeof(underbarname)-1, "%s/._%s", dname, bname); + free(tmp); + free(tmp2); + free(dname); + + if( stat(underbarname, &sb) != 0 ) + return 0; + + DARWINATTR_CONTEXT(context)->fd = open(underbarname, O_RDONLY); + if( DARWINATTR_CONTEXT(context)->fd < 0 ) + return -1; + + memset(&ash, 0, sizeof(ash)); + memset(&ase, 0, sizeof(ase)); + r = read(DARWINATTR_CONTEXT(context)->fd, &ash, XAR_ASH_SIZE); + if( r < XAR_ASH_SIZE ) { + close(DARWINATTR_CONTEXT(context)->fd); + return -1; + } + + if( ntohl(ash.magic) != APPLEDOUBLE_MAGIC ) { + close(DARWINATTR_CONTEXT(context)->fd); + return -1; + } + if( ntohl(ash.version) != APPLEDOUBLE_VERSION ) { + close(DARWINATTR_CONTEXT(context)->fd); + return -1; + } + + off = XAR_ASH_SIZE; + num_entries = ntohs(ash.entries); + + for(i = 0; i < num_entries; i++) { + off_t entoff; + r = read(DARWINATTR_CONTEXT(context)->fd, &ase, sizeof(ase)); + if( r < sizeof(ase) ) { + close(DARWINATTR_CONTEXT(context)->fd); + return -1; + } + off+=r; + + if( ntohl(ase.entry_id) == AS_ID_FINDER ) { + xar_ea_t e; + entoff = (off_t)ntohl(ase.offset); + if( lseek(DARWINATTR_CONTEXT(context)->fd, entoff, SEEK_SET) == -1 ) { + close(DARWINATTR_CONTEXT(context)->fd); + return -1; + } + r = read(DARWINATTR_CONTEXT(context)->fd, z, sizeof(z)); + if( r < sizeof(z) ) { + close(DARWINATTR_CONTEXT(context)->fd); + return -1; + } + + DARWINATTR_CONTEXT(context)->finfo = z; + e = xar_ea_new(f, "com.apple.FinderInfo"); + + if (XAR(x)->attrcopy_to_heap(x, f, xar_ea_root(e), finfo_read, context) < 0) { + close(DARWINATTR_CONTEXT(context)->fd); + return -1; + } + + if( lseek(DARWINATTR_CONTEXT(context)->fd, (off_t)off, SEEK_SET) == -1 ) { + close(DARWINATTR_CONTEXT(context)->fd); + return -1; + } + } + if( ntohl(ase.entry_id) == AS_ID_RESOURCE ) { + xar_ea_t e; + entoff = (off_t)ntohl(ase.offset); + if( lseek(DARWINATTR_CONTEXT(context)->fd, entoff, SEEK_SET) == -1 ) { + close(DARWINATTR_CONTEXT(context)->fd); + return -1; + } + + e = xar_ea_new(f, "com.apple.ResourceFork"); + if (XAR(x)->attrcopy_to_heap(x, f, xar_ea_root(e), xar_rsrc_read, context) < 0) { + close(DARWINATTR_CONTEXT(context)->fd); + return -1; + } + + if( lseek(DARWINATTR_CONTEXT(context)->fd, (off_t)off, SEEK_SET) == -1 ) { + close(DARWINATTR_CONTEXT(context)->fd); + return -1; + } + } + } + + close(DARWINATTR_CONTEXT(context)->fd); + DARWINATTR_CONTEXT(context)->fd = 0; + return 0; +} +#endif + +/* underbar_extract + * Extract finderinfo and resource fork information to an appledouble + * ._ file. + */ +static int32_t underbar_extract(xar_t x, xar_file_t f, const char* file, void *context) { + char underbarname[4096]; + char *dname, *bname, *tmp, *tmp2; + const char *rsrclenstr; + struct AppleSingleHeader ash; + struct AppleSingleEntry ase; + int num_entries = 0, rsrclen = 0, have_rsrc = 0, have_fi = 0; + xar_prop_t p; + xar_prop_t rfprop = NULL, fiprop = NULL; + + fiprop = xar_ea_find(f, "com.apple.FinderInfo"); + if( fiprop ) { + have_fi = 1; + num_entries++; + } + + rfprop = xar_ea_find(f, "com.apple.ResourceFork"); + if( rfprop ) { + have_rsrc = 1; + num_entries++; + } + + if( num_entries == 0 ) + return 0; + + tmp = strdup(file); + tmp2 = strdup(file); + dname = xar_safe_dirname(tmp2); + bname = basename(tmp); + + memset(underbarname, 0, sizeof(underbarname)); + snprintf(underbarname, sizeof(underbarname)-1, "%s/._%s", dname, bname); + free(tmp); + free(tmp2); + free(dname); + + DARWINATTR_CONTEXT(context)->fd = open(underbarname, O_RDWR | O_CREAT | O_TRUNC, 0); + if( DARWINATTR_CONTEXT(context)->fd < 0 ) + return -1; + + rsrclenstr = NULL; + if( rfprop ) { + p = xar_prop_pget(rfprop, "size"); + if( p ) + rsrclenstr = xar_prop_getvalue(p); + if( rsrclenstr ) + rsrclen = strtol(rsrclenstr, NULL, 10); + } + + memset(&ash, 0, sizeof(ash)); + memset(&ase, 0, sizeof(ase)); + ash.magic = htonl(APPLEDOUBLE_MAGIC); + ash.version = htonl(APPLEDOUBLE_VERSION); + ash.entries = htons(num_entries); + + write(DARWINATTR_CONTEXT(context)->fd, &ash, XAR_ASH_SIZE); + + ase.offset = htonl(XAR_ASH_SIZE + ntohs(ash.entries)*12); + if( have_fi ) { + ase.entry_id = htonl(AS_ID_FINDER); + ase.length = htonl(32); + write(DARWINATTR_CONTEXT(context)->fd, &ase, 12); + } + + if( have_rsrc ) { + ase.entry_id = htonl(AS_ID_RESOURCE); + ase.offset = htonl(ntohl(ase.offset) + ntohl(ase.length)); + ase.length = htonl(rsrclen); + write(DARWINATTR_CONTEXT(context)->fd, &ase, 12); + } + + if( have_fi ) { + if (XAR(x)->attrcopy_from_heap(x, f, fiprop, xar_rsrc_write, context) < 0) { + close(DARWINATTR_CONTEXT(context)->fd); + DARWINATTR_CONTEXT(context)->fd = 0; + return -1; + } + } + + if( have_rsrc ) { + if (XAR(x)->attrcopy_from_heap(x, f, rfprop, xar_rsrc_write, context) < 0) { + close(DARWINATTR_CONTEXT(context)->fd); + DARWINATTR_CONTEXT(context)->fd = 0; + return -1; + } + } + + close(DARWINATTR_CONTEXT(context)->fd); + DARWINATTR_CONTEXT(context)->fd = 0; + + xar_set_perm(x, f, underbarname, NULL, 0 ); + + return 0; +} + +#if defined(__APPLE__) +static int32_t stragglers_archive(xar_t x, xar_file_t f, const char* file, void *context) { +#ifdef HAVE_GETATTRLIST + struct fits { + uint32_t length; + struct timespec ts; + }; + struct fits fts; + struct attrlist attrs; + int ret; + + if( !xar_check_prop(x, "FinderCreateTime") ) + return 0; + + memset(&attrs, 0, sizeof(attrs)); + attrs.bitmapcount = ATTR_BIT_MAP_COUNT; + attrs.commonattr = ATTR_CMN_CRTIME; + ret = getattrlist(file, &attrs, &fts, sizeof(fts), 0); + if( ret == 0 ) { + xar_prop_t tmpp; + + tmpp = xar_prop_new(f, NULL); + if( tmpp ) { + char tmpc[128]; + struct tm tm; + xar_prop_setkey(tmpp, "FinderCreateTime"); + xar_prop_setvalue(tmpp, NULL); + memset(tmpc, 0, sizeof(tmpc)); + gmtime_r(&fts.ts.tv_sec, &tm); + strftime(tmpc, sizeof(tmpc), "%FT%T", &tm); + xar_prop_pset(f, tmpp, "time", tmpc); + memset(tmpc, 0, sizeof(tmpc)); + sprintf(tmpc, "%ld", fts.ts.tv_nsec); + xar_prop_pset(f, tmpp, "nanoseconds", tmpc); + } + } +#endif + return 0; +} + +static int32_t stragglers_extract(xar_t x, xar_file_t f, const char* file, void *context) { +#ifdef HAVE_GETATTRLIST + const char *tmpc = NULL; + struct tm tm; + struct timespec ts; + struct attrlist attrs; + + xar_prop_get(f, "FinderCreateTime/time", &tmpc); + if( tmpc ) { + strptime(tmpc, "%FT%T", &tm); + ts.tv_sec = timegm(&tm); + xar_prop_get(f, "FinderCreateTime/nanoseconds", &tmpc); + if( tmpc ) { + ts.tv_nsec = strtol(tmpc, NULL, 10); + memset(&attrs, 0, sizeof(attrs)); + attrs.bitmapcount = ATTR_BIT_MAP_COUNT; + attrs.commonattr = ATTR_CMN_CRTIME; + setattrlist(file, &attrs, &ts, sizeof(ts), 0); + } + } + +#endif + return 0; +} +#endif /* __APPLE__ */ + +int32_t xar_darwinattr_archive(xar_t x, xar_file_t f, const char* file, const char *buffer, size_t len) +{ + struct _darwinattr_context context; + + memset(&context,0,sizeof(struct _darwinattr_context)); + +#if defined(__APPLE__) + if( len ) + return 0; + stragglers_archive(x, f, file, (void *)&context); + + /* From here on out, props are only EA's */ + if( !xar_check_prop(x, "ea") ) + return 0; + +#if defined(HAVE_GETXATTR) + if( ea_archive(x, f, file, (void *)&context) == 0 ) + return 0; +#endif + if( nonea_archive(x, f, file, (void *)&context) == 0 ) + return 0; + return underbar_archive(x, f, file, (void *)&context); +#endif /* __APPLE__ */ + return 0; +} + +int32_t xar_darwinattr_extract(xar_t x, xar_file_t f, const char* file, char *buffer, size_t len) +{ + struct _darwinattr_context context; + + memset(&context,0,sizeof(struct _darwinattr_context)); + +#if defined(__APPLE__) + if( len ) + return 0; + stragglers_extract(x, f, file, (void *)&context); + +#if defined(HAVE_GETXATTR) + if( ea_extract(x, f, file, (void *)&context) == 0 ) + return 0; +#endif + if( nonea_extract(x, f, file, (void *)&context) == 0 ) + return 0; +#endif /* __APPLE__ */ + return underbar_extract(x, f, file, (void *)&context); +} diff --git a/xar/lib/darwinattr.h b/xar/lib/darwinattr.h new file mode 100644 index 0000000..5cb45c1 --- /dev/null +++ b/xar/lib/darwinattr.h @@ -0,0 +1,43 @@ +/* + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Apple nor the names of any contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. +*/ +/* + * Rob Braun + * 23-Apr-2005 + * Copyright (c) 2004 Rob Braun. All rights reserved. + */ +/* + * Portions Copyright 2006, Apple Computer, Inc. + * Christopher Ryan +*/ + +#ifndef _XAR_DARWINATTR_H_ +#define _XAR_DARWINATTR_H_ +xar_file_t xar_underbar_check(xar_t x, xar_file_t f, const char* file); +int32_t xar_darwinattr_archive(xar_t x, xar_file_t f, const char* file, const char *buffer, size_t len); +int32_t xar_darwinattr_extract(xar_t x, xar_file_t f, const char* file, char *buffer, size_t len); +#endif /* _XAR_DARWINATTR_H_ */ diff --git a/xar/lib/data.c b/xar/lib/data.c new file mode 100644 index 0000000..dcb5783 --- /dev/null +++ b/xar/lib/data.c @@ -0,0 +1,273 @@ +/* + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Apple nor the names of any contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. +*/ +/* + * Portions Copyright 2006, Apple Computer, Inc. + * Christopher Ryan +*/ + +#define _FILE_OFFSET_BITS 64 +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "xar.h" +#include "filetree.h" +#include "archive.h" +#include "io.h" +#include "arcmod.h" +#include "data.h" + +#ifndef O_EXLOCK +#define O_EXLOCK 0 +#endif + + + +int32_t xar_data_read(xar_t x, xar_file_t f, void *inbuf, size_t bsize, void *context) { + int32_t r; + + /* read from buffer, rather then fd,if available */ + if(DATA_CONTEXT(context)->length){ + char *readbuf = (char *)DATA_CONTEXT(context)->buffer; + size_t sizetoread = DATA_CONTEXT(context)->length - DATA_CONTEXT(context)->offset; + + if( !sizetoread){ + return 0; + } + + if( sizetoread > bsize ){ + sizetoread = bsize; + } + + /* dont read passed the end of the buffer */ + if((DATA_CONTEXT(context)->offset + sizetoread) > DATA_CONTEXT(context)->length){ + return -1; + //sizetoread = (DATA_CONTEXT(context)->offset + sizetoread) - DATA_CONTEXT(context)->length; + } + + readbuf += DATA_CONTEXT(context)->offset; + memcpy(inbuf,readbuf,sizetoread); + + DATA_CONTEXT(context)->total += sizetoread; + DATA_CONTEXT(context)->offset += sizetoread; + + return sizetoread; + } + + while(1) { + r = read(DATA_CONTEXT(context)->fd, inbuf, bsize); + if( (r < 0) && (errno == EINTR) ) + continue; + DATA_CONTEXT(context)->total += r; + return r; + } + +} + +int32_t xar_data_write(xar_t x, xar_file_t f, void *buf, size_t len, void *context) { + int32_t r; + size_t off = 0; + + /* read from buffer, rather then fd,if available */ + if(DATA_CONTEXT(context)->length){ + char *writebuf = (char *)DATA_CONTEXT(context)->buffer; + + /* dont write passed the end of the buffer */ + if((DATA_CONTEXT(context)->offset + len) > DATA_CONTEXT(context)->length){ + return -1; + } + + writebuf += DATA_CONTEXT(context)->offset; + memcpy(writebuf,buf,len); + + DATA_CONTEXT(context)->offset += len; + + return len; + } + + do { + r = write(DATA_CONTEXT(context)->fd, ((char *)buf)+off, len-off); + if( (r < 0) && (errno != EINTR) ) + return r; + off += r; + } while( off < len ); + return off; +} + +/* xar_data_archive + * This is the arcmod archival entry point for archiving the file's + * data into the heap file. + */ +int32_t xar_data_archive(xar_t x, xar_file_t f, const char *file, const char *buffer, size_t len) { + const char *opt; + int32_t retval = 0; + struct _data_context context; + xar_prop_t tmpp; + + memset(&context,0,sizeof(struct _data_context)); + + if( !xar_check_prop(x, "data") ) + return 0; + + xar_prop_get(f, "type", &opt); + if(!opt) return 0; + if( strcmp(opt, "file") != 0 ) { + if( strcmp(opt, "hardlink") == 0 ) { + opt = xar_attr_get(f, "type", "link"); + if( !opt ) + return 0; + if( strcmp(opt, "original") != 0 ) + return 0; + /* else, we're an original hardlink, so keep going */ + } else + return 0; + } + + if( 0 == len ){ + context.fd = open(file, O_RDONLY); + if( context.fd < 0 ) { + xar_err_new(x); + xar_err_set_file(x, f); + xar_err_set_string(x, "io: Could not open file"); + xar_err_callback(x, XAR_SEVERITY_NONFATAL, XAR_ERR_ARCHIVE_CREATION); + return -1; + } + }else{ + context.buffer = (void *)buffer; + context.length = len; + context.offset = 0; + } + +#ifdef F_NOCACHE + fcntl(context.fd, F_NOCACHE, 1); +#endif + + tmpp = xar_prop_pset(f, NULL, "data", NULL); + retval = XAR(x)->attrcopy_to_heap(x, f, tmpp, xar_data_read,(void *)(&context)); + if( context.total == 0 ) + xar_prop_unset(f, "data"); + + if(context.fd > 0){ + close(context.fd); + context.fd = -1; + } + + return retval; +} + +int32_t xar_data_extract(xar_t x, xar_file_t f, const char *file, char *buffer, size_t len) { + const char *opt; + int32_t retval = 0; + struct _data_context context; + xar_prop_t tmpp; + + memset(&context,0,sizeof(struct _data_context)); + + /* Only regular files are copied in and out of the heap here */ + xar_prop_get(f, "type", &opt); + if( !opt ) return 0; + if( strcmp(opt, "file") != 0 ) { + if( strcmp(opt, "hardlink") == 0 ) { + opt = xar_attr_get(f, "type", "link"); + if( !opt ) + return 0; + if( strcmp(opt, "original") != 0 ) + return 0; + /* else, we're an original hardlink, so keep going */ + } else + return 0; + } + + if ( len ){ + context.length = len; + context.buffer = buffer; + context.offset = 0; + }else{ + /* mode 600 since other modules may need to operate on the file + * prior to the real permissions being set. + */ + context.fd = open(file, O_RDWR|O_TRUNC|O_EXLOCK, 0600); + if( context.fd < 0 ) { + xar_err_new(x); + xar_err_set_file(x, f); + xar_err_set_string(x, "io: Could not create file"); + xar_err_callback(x, XAR_SEVERITY_NONFATAL, XAR_ERR_ARCHIVE_EXTRACTION); + return -1; + } + + } + + tmpp = xar_prop_pfirst(f); + if( tmpp ) + tmpp = xar_prop_find(tmpp, "data"); + if( !tmpp ) { + close(context.fd); + return 0; + } + retval = XAR(x)->attrcopy_from_heap(x, f, tmpp, xar_data_write, (void *)(&context)); + + if( context.fd > 0 ){ + close(context.fd); + context.fd = -1; + } + + return retval; +} + +int32_t xar_data_verify(xar_t x, xar_file_t f, xar_progress_callback p) +{ + const char *opt; + struct _data_context context; + xar_prop_t tmpp; + + memset(&context,0,sizeof(struct _data_context)); + + context.progress = p; + + /* Only regular files are copied in and out of the heap here */ + xar_prop_get(f, "type", &opt); + if( !opt ) return 0; + if( strcmp(opt, "directory") == 0 ) { + return 0; + } + + tmpp = xar_prop_pfirst(f); + if( tmpp ) + tmpp = xar_prop_find(tmpp, "data"); + + if (!tmpp) // It appears that xar can have truely empty files, aka, no data. We should just fail to verify these files. + return 0; // After all, the checksum of blank is meaningless. So, failing to do so will cause a crash. + + return XAR(x)->attrcopy_from_heap(x, f, tmpp, NULL , (void *)(&context)); +} diff --git a/xar/lib/data.h b/xar/lib/data.h new file mode 100644 index 0000000..df2301f --- /dev/null +++ b/xar/lib/data.h @@ -0,0 +1,57 @@ +/* + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Apple nor the names of any contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. +*/ +/* + * Rob Braun + * 21-Apr-2004 + * Copyright (c) 2004 Rob Braun. All rights reserved. + */ +/* + * Portions Copyright 2006, Apple Computer, Inc. + * Christopher Ryan +*/ + +#ifndef _XAR_DATA_H_ +#define _XAR_DATA_H_ + +struct _data_context{ + xar_progress_callback progress; + int fd; + void *buffer; + size_t length; + off_t offset; + off_t total; +}; + +#define DATA_CONTEXT(x) ((struct _data_context*)(x)) + + +int32_t xar_data_archive(xar_t x, xar_file_t f, const char* file, const char *buffer, size_t len); +int32_t xar_data_extract(xar_t x, xar_file_t f, const char* file, char *buffer, size_t len); + +int32_t xar_data_verify(xar_t x, xar_file_t f, xar_progress_callback p); +#endif /* _XAR_DATA_H_ */ diff --git a/xar/lib/ea.c b/xar/lib/ea.c new file mode 100644 index 0000000..1bb8e27 --- /dev/null +++ b/xar/lib/ea.c @@ -0,0 +1,127 @@ +/* + * Copyright (c) 2008 Rob Braun + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Rob Braun nor the names of his contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +#include "config.h" +#include +#include +#include +#include +#include + +#ifndef HAVE_ASPRINTF +#include "asprintf.h" +#endif +#include "xar.h" +#include "filetree.h" +#include "archive.h" +#include "b64.h" +#include "ea.h" + +struct __xar_ea_t { + const struct __xar_prop_t *prop; + const struct __xar_ea_t *next; +}; + +#define XAR_EA(x) ((struct __xar_ea_t *)(x)) + +xar_ea_t xar_ea_new(xar_file_t f, const char *name) +{ + xar_ea_t ret; + + ret = calloc(sizeof(struct __xar_ea_t), 1); + if( !ret ) + return NULL; + + XAR_EA(ret)->prop = xar_prop_new(f, NULL); + if( !XAR_EA(ret)->prop ) { + free(ret); + return NULL; + } + + xar_prop_setkey(XAR_EA(ret)->prop, "ea"); + xar_prop_setvalue(XAR_EA(ret)->prop, NULL); + XAR_PROP(XAR_EA(ret)->prop)->attrs = xar_attr_new(); + XAR_ATTR(XAR_PROP(XAR_EA(ret)->prop)->attrs)->key = strdup("id"); + asprintf((char **)&XAR_ATTR(XAR_PROP(XAR_EA(ret)->prop)->attrs)->value, "%lld", XAR_FILE(f)->nexteaid++); + + xar_prop_pset(f, XAR_EA(ret)->prop, "name", name); + + return ret; +} + +int32_t xar_ea_pset(xar_file_t f, xar_ea_t e, const char *key, const char *value){ + if( xar_prop_pset(f, XAR_EA(e)->prop, key, value) ) + return 0; + return -1; +} + +int32_t xar_ea_pget(xar_ea_t e, const char *key, const char **value) { + xar_prop_t r = xar_prop_find(XAR_EA(e)->prop, key); + if( !r ) { + if( value ) + *value = NULL; + return -1; + } + + if(value) + *value = XAR_PROP(r)->value; + + return 0; +} + +xar_prop_t xar_ea_root(xar_ea_t e) { + return XAR_EA(e)->prop; +} + +xar_prop_t xar_ea_find(xar_file_t f, const char *name) +{ + xar_prop_t p; + + for(p = xar_prop_pfirst(f); p; p = xar_prop_pnext(p)) { + const char *tmp; + xar_prop_t tmpp; + + tmp = xar_prop_getkey(p); + if( strncmp(tmp, XAR_EA_FORK, strlen(XAR_EA_FORK)) != 0 ) + continue; + if( strlen(tmp) != strlen(XAR_EA_FORK) ) + continue; + + tmpp = xar_prop_pget(p, "name"); + if( !tmpp ) + continue; + tmp = xar_prop_getvalue(tmpp); + if( !tmp ) + continue; + + if( strcmp(tmp, name) == 0 ) + return p; + } + + return NULL; +} diff --git a/xar/lib/ea.h b/xar/lib/ea.h new file mode 100644 index 0000000..0c43ee6 --- /dev/null +++ b/xar/lib/ea.h @@ -0,0 +1,15 @@ +#ifndef _XAR_EA_H_ +#define _XAR_EA_H_ + +#include "xar.h" +#include "filetree.h" + +typedef struct __xar_ea_t *xar_ea_t; + +xar_ea_t xar_ea_new(xar_file_t f, const char *name); +int32_t xar_ea_pset(xar_file_t f, xar_ea_t e, const char *key, const char *value); +int32_t xar_ea_pget(xar_ea_t e, const char *key, const char **value); +xar_prop_t xar_ea_root(xar_ea_t e); +xar_prop_t xar_ea_find(xar_file_t f, const char *name); + +#endif /* _XAR_EA_H_ */ diff --git a/xar/lib/err.c b/xar/lib/err.c new file mode 100644 index 0000000..e9b0679 --- /dev/null +++ b/xar/lib/err.c @@ -0,0 +1,101 @@ +/* + * Copyright (c) 2005-2007 Rob Braun + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Rob Braun nor the names of his contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +/* + * 03-Apr-2005 + * DRI: Rob Braun + */ + +#include +#include +#include +#include "xar.h" +#include "archive.h" + +#define ECTX(x) ((struct errctx *)(x)) + +void xar_register_errhandler(xar_t x, err_handler callback, void *usrctx) { + ECTX(&XAR(x)->errctx)->x = x; + ECTX(&XAR(x)->errctx)->usrctx = usrctx; + XAR(x)->ercallback = callback; + return; +} + +xar_t xar_err_get_archive(xar_errctx_t ctx) { + return ECTX(ctx)->x; +} + +xar_file_t xar_err_get_file(xar_errctx_t ctx) { + return ECTX(ctx)->file; +} + +void xar_err_set_file(xar_t x, xar_file_t f) { + XAR(x)->errctx.file = f; + return; +} + +const char *xar_err_get_string(xar_errctx_t ctx) { + return ECTX(ctx)->str; +} + +void xar_err_set_string(xar_t x, const char *str) { + XAR(x)->errctx.str = strdup(str); // this leaks right now, but it's safer than the alternative + return; +} + +void xar_err_set_formatted_string(xar_t x, const char *format, ...) { + va_list arg; + char *msg; + va_start(arg, format); + vasprintf(&msg, format, arg); + va_end(arg); + xar_err_set_string(x, msg); + free(msg); +} + + +int xar_err_get_errno(xar_errctx_t ctx) { + return ECTX(ctx)->saved_errno; +} + +void xar_err_set_errno(xar_t x, int e) { + XAR(x)->errctx.saved_errno = e; + return; +} + +void xar_err_new(xar_t x) { + memset(&XAR(x)->errctx, 0, sizeof(struct errctx)); + XAR(x)->errctx.saved_errno = errno; + return; +} + +int32_t xar_err_callback(xar_t x, int32_t sev, int32_t err) { + if( XAR(x)->ercallback ) + return XAR(x)->ercallback(sev, err, &XAR(x)->errctx, ECTX(&XAR(x)->errctx)->usrctx); + return 0; +} diff --git a/xar/lib/ext2.c b/xar/lib/ext2.c new file mode 100644 index 0000000..767891a --- /dev/null +++ b/xar/lib/ext2.c @@ -0,0 +1,257 @@ +/* + * Copyright (c) 2004 Rob Braun + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Rob Braun nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +/* + * 26-Oct-2004 + * DRI: Rob Braun + * Ported from xar-unsaxy 16-Apr-2005 + */ +/* + * Portions Copyright 2006, Apple Computer, Inc. + * Christopher Ryan +*/ + +#include "config.h" +#ifndef HAVE_ASPRINTF +#include "asprintf.h" +#endif +#include +#include +#include "xar.h" +#include "arcmod.h" +#include +#include +#include +#include +#include +#include "ext2.h" + +#ifdef HAVE_EXT2FS_EXT2_FS_H +#include +#else +#if defined(HAVE_LINUX_EXT2_FS_H) +typedef uint32_t u32; +typedef uint8_t u8; +#include +#endif +#endif + +#define XAR_EXT2_FORK "ext2" + +#if defined(HAVE_EXT2FS_EXT2_FS_H) || defined(HAVE_LINUX_EXT2_FS_H) +static void x_addprop(xar_file_t f, const char *name) { + char opt[1024]; + memset(opt, 0, sizeof(opt)); + snprintf(opt, sizeof(opt)-1, "%s/%s", XAR_ATTR_FORK, name); + xar_prop_set(f, opt, NULL); + xar_attr_set(f, opt, "fstype", "ext2"); + return; +} +#endif + +int xar_ext2attr_archive(xar_t x, xar_file_t f, const char* file, const char *buffer, size_t len) +{ + int ret = 0; + + /* if archiving from a buffer, then there is no place to get extattr */ + if ( len ) + return 0; + +#if defined(HAVE_EXT2FS_EXT2_FS_H) || defined(HAVE_LINUX_EXT2_FS_H) + int fd, flags=0, version; + char *vstr; + const char *opt; + + xar_prop_get(f, "type", &opt); + if(!opt) return 0; + if( strcmp(opt, "file") != 0 ) { + if( strcmp(opt, "hardlink") != 0 ) + if( strcmp(opt, "directory") != 0 ) + return 0; + } + + fd = open(file, O_RDONLY); + if( fd < 0 ) { + return 0; + } + if( ioctl(fd, EXT2_IOC_GETVERSION, &version) < 0 ) { + ret = 0; + goto BAIL; + } + if( ioctl(fd, EXT2_IOC_GETFLAGS, &flags) < 0 ) { + ret = 0; + goto BAIL; + } + + if( flags == 0 ) goto BAIL; + + xar_prop_set(f, XAR_EXT2_FORK, NULL); + asprintf(&vstr, "%d", version); + xar_attr_set(f, XAR_EXT2_FORK, "version", vstr); + free(vstr); + + if(! (flags & ~EXT2_SECRM_FL) ) + x_addprop(f, "SecureDeletion"); + if(! (flags & ~EXT2_UNRM_FL) ) + x_addprop(f, "Undelete"); + if(! (flags & ~EXT2_COMPR_FL) ) + x_addprop(f, "Compress"); + if(! (flags & ~EXT2_SYNC_FL) ) + x_addprop(f, "Synchronous"); + if(! (flags & ~EXT2_IMMUTABLE_FL) ) + x_addprop(f, "Immutable"); + if(! (flags & ~EXT2_APPEND_FL) ) + x_addprop(f, "AppendOnly"); + if(! (flags & ~EXT2_NODUMP_FL) ) + x_addprop(f, "NoDump"); + if(! (flags & ~EXT2_NOATIME_FL) ) + x_addprop(f, "NoAtime"); + if(! (flags & ~EXT2_DIRTY_FL) ) + x_addprop(f, "CompDirty"); + if(! (flags & ~EXT2_COMPRBLK_FL) ) + x_addprop(f, "CompBlock"); +#ifdef EXT2_NOCOMPR_FL + if(! (flags & ~EXT2_NOCOMPR_FL) ) + x_addprop(f, "NoCompBlock"); +#endif + if(! (flags & ~EXT2_ECOMPR_FL) ) + x_addprop(f, "CompError"); + if(! (flags & ~EXT2_BTREE_FL) ) + x_addprop(f, "BTree"); + if(! (flags & ~EXT2_INDEX_FL) ) + x_addprop(f, "HashIndexed"); + if(! (flags & ~EXT2_IMAGIC_FL) ) + x_addprop(f, "iMagic"); +#ifdef EXT3_JOURNAL_DATA_FL + if(! (flags & ~EXT3_JOURNAL_DATA_FL) ) + x_addprop(f, "Journaled"); +#endif + if(! (flags & ~EXT2_NOTAIL_FL) ) + x_addprop(f, "NoTail"); + if(! (flags & ~EXT2_DIRSYNC_FL) ) + x_addprop(f, "DirSync"); + if(! (flags & ~EXT2_TOPDIR_FL) ) + x_addprop(f, "TopDir"); + if(! (flags & ~EXT2_RESERVED_FL) ) + x_addprop(f, "Reserved"); + +BAIL: + close(fd); +#endif + return ret; +} + +#if defined(HAVE_EXT2FS_EXT2_FS_H) || defined(HAVE_LINUX_EXT2_FS_H) +static int32_t e2prop_get(xar_file_t f, const char *name, char **value) { + char v[1024]; + + memset(v, 0, sizeof(v)); + snprintf(v, sizeof(v)-1, "%s/%s", XAR_ATTR_FORK, name); + return xar_prop_get(f, v, (const char**)value); +} +#endif + +int xar_ext2attr_extract(xar_t x, xar_file_t f, const char* file, char *buffer, size_t len) +{ + /* if extracting to a buffer, then there is no place to write extattr */ + if ( len ) + return 0; + +#if defined(HAVE_EXT2FS_EXT2_FS_H) || defined(HAVE_LINUX_EXT2_FS_H) + int fd = -1, version, flags = 0; + char *tmp; + + if( xar_prop_get(f, XAR_EXT2_FORK, NULL) == 0 ) { + const char *temp; + temp = xar_attr_get(f, XAR_EXT2_FORK, "version"); + version = strtol(temp, NULL, 10); + fd = open(file, O_RDONLY); + if( fd < 0 ) + return 0; + ioctl(fd, EXT2_IOC_SETVERSION, &version); + } + + if( xar_prop_get(f, XAR_ATTR_FORK, NULL) ) { + if( fd >= 0 ) close(fd); + return 0; + } + + if( e2prop_get(f, "SecureDeletion", (char **)&tmp) == 0 ) + flags |= EXT2_SECRM_FL; + if( e2prop_get(f, "Undelete", (char **)&tmp) == 0 ) + flags |= EXT2_UNRM_FL ; + if( e2prop_get(f, "Compress", (char **)&tmp) == 0 ) + flags |= EXT2_COMPR_FL ; + if( e2prop_get(f, "Synchronous", (char **)&tmp) == 0 ) + flags |= EXT2_SYNC_FL ; + if( e2prop_get(f, "SystemImmutable", (char **)&tmp) == 0 ) + flags |= EXT2_IMMUTABLE_FL ; + if( e2prop_get(f, "AppendOnly", (char **)&tmp) == 0 ) + flags |= EXT2_APPEND_FL ; + if( e2prop_get(f, "NoDump", (char **)&tmp) == 0 ) + flags |= EXT2_NODUMP_FL ; + if( e2prop_get(f, "NoAtime", (char **)&tmp) == 0 ) + flags |= EXT2_NOATIME_FL ; + if( e2prop_get(f, "CompDirty", (char **)&tmp) == 0 ) + flags |= EXT2_DIRTY_FL ; + if( e2prop_get(f, "CompBlock", (char **)&tmp) == 0 ) + flags |= EXT2_COMPRBLK_FL ; +#ifdef EXT2_NOCOMPR_FL + if( e2prop_get(f, "NoCompBlock", (char **)&tmp) == 0 ) + flags |= EXT2_NOCOMPR_FL ; +#endif + if( e2prop_get(f, "CompError", (char **)&tmp) == 0 ) + flags |= EXT2_ECOMPR_FL ; + if( e2prop_get(f, "BTree", (char **)&tmp) == 0 ) + flags |= EXT2_BTREE_FL ; + if( e2prop_get(f, "HashIndexed", (char **)&tmp) == 0 ) + flags |= EXT2_INDEX_FL ; + if( e2prop_get(f, "iMagic", (char **)&tmp) == 0 ) + flags |= EXT2_IMAGIC_FL ; +#ifdef EXT3_JOURNAL_DATA_FL + if( e2prop_get(f, "Journaled", (char **)&tmp) == 0 ) + flags |= EXT3_JOURNAL_DATA_FL ; +#endif + if( e2prop_get(f, "NoTail", (char **)&tmp) == 0 ) + flags |= EXT2_NOTAIL_FL ; + if( e2prop_get(f, "DirSync", (char **)&tmp) == 0 ) + flags |= EXT2_DIRSYNC_FL ; + if( e2prop_get(f, "TopDir", (char **)&tmp) == 0 ) + flags |= EXT2_TOPDIR_FL ; + + if( fd < 0 ) { + fd = open(file, O_RDONLY); + if( fd < 0 ) + return 0; + } + + ioctl(fd, EXT2_IOC_SETFLAGS, &flags); + close(fd); +#endif + return 0; +} diff --git a/xar/lib/ext2.h b/xar/lib/ext2.h new file mode 100644 index 0000000..9c3a37b --- /dev/null +++ b/xar/lib/ext2.h @@ -0,0 +1,42 @@ +/* All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Apple nor the names of any contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. +*/ +/* + * Rob Braun + * 26-Oct-2004 + * Copyright (c) 2004 Rob Braun. All rights reserved. + */ +/* + * Portions Copyright 2006, Apple Computer, Inc. + * Christopher Ryan +*/ + +#ifndef _XAR_EXT2_H_ +#define _XAR_EXT2_H_ +#define XAR_ATTR_FORK "attribute" +int xar_ext2attr_archive(xar_t x, xar_file_t f, const char* file, const char *buffer, size_t len); +int xar_ext2attr_extract(xar_t x, xar_file_t f, const char* file, char *buffer, size_t len); +#endif /* _XAR_EXT2_H_ */ diff --git a/xar/lib/fbsdattr.c b/xar/lib/fbsdattr.c new file mode 100644 index 0000000..8d9a7ef --- /dev/null +++ b/xar/lib/fbsdattr.c @@ -0,0 +1,344 @@ +/* + * Copyright (c) 2007 Rob Braun + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Rob Braun nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +/* + * 28-Oct-2004 + * DRI: Rob Braun + */ +/* + * Portions Copyright 2006, Apple Computer, Inc. + * Christopher Ryan +*/ + +#include "config.h" +#include +#include "xar.h" +#include "arcmod.h" +#include "b64.h" +#include "io.h" +#include "archive.h" +#include +#include +#include + +/* FreeBSD Extended Attribute Headers */ +#ifdef HAVE_SYS_EXTATTR_H +#include +#endif +#ifdef HAVE_LIBUTIL_H +#include +#endif + +#ifdef HAVE_SYS_EXTATTR_H +#include +#include +#include +#endif + +#ifdef HAVE_SYS_EXTATTR_H +struct _fbsdattr_context{ + const char *file; + const char *attrname; + void *buf; + int off; + int bufsz; + int ns; +}; + +#define FBSDATTR_CONTEXT(x) ((struct _fbsdattr_context *)(x)) + +int32_t xar_fbsdattr_read(xar_t x, xar_file_t f, void *buf, size_t len, void *context) { + if( !FBSDATTR_CONTEXT(context)->buf ) { + FBSDATTR_CONTEXT(context)->bufsz = extattr_get_link(FBSDATTR_CONTEXT(context)->file, FBSDATTR_CONTEXT(context)->ns, FBSDATTR_CONTEXT(context)->attrname, NULL, 0); + if( FBSDATTR_CONTEXT(context)->bufsz < 0 ) + return -1; + FBSDATTR_CONTEXT(context)->buf = malloc(FBSDATTR_CONTEXT(context)->bufsz); + if( !FBSDATTR_CONTEXT(context)->buf ) + return -1; + + FBSDATTR_CONTEXT(context)->bufsz = extattr_get_link(FBSDATTR_CONTEXT(context)->file, FBSDATTR_CONTEXT(context)->ns, FBSDATTR_CONTEXT(context)->attrname, FBSDATTR_CONTEXT(context)->buf, FBSDATTR_CONTEXT(context)->bufsz); + } + + if( (FBSDATTR_CONTEXT(context)->bufsz - FBSDATTR_CONTEXT(context)->off) <= len ) { + int32_t ret; + + ret = FBSDATTR_CONTEXT(context)->bufsz - FBSDATTR_CONTEXT(context)->off; + memcpy(buf, FBSDATTR_CONTEXT(context)->buf+FBSDATTR_CONTEXT(context)->off, ret); + FBSDATTR_CONTEXT(context)->off += ret; + return(ret); + } else { + memcpy(buf, FBSDATTR_CONTEXT(context)->buf+FBSDATTR_CONTEXT(context)->off, len); + FBSDATTR_CONTEXT(context)->buf += len; + return(len); + } + +} +int32_t xar_fbsdattr_write(xar_t x, xar_file_t f, void *buf, size_t len, void *context) { + return extattr_set_link(FBSDATTR_CONTEXT(context)->file, FBSDATTR_CONTEXT(context)->ns, FBSDATTR_CONTEXT(context)->attrname, buf, len); +} +#endif + +int32_t xar_fbsdattr_archive(xar_t x, xar_file_t f, const char* file, const char *buffer, size_t len) +{ +#ifdef HAVE_SYS_EXTATTR_H + char *buf = NULL; + int ret, retval=0, bufsz, i; +#if defined(HAVE_STATVFS) && defined(HAVE_STRUCT_STATVFS_F_FSTYPENAME) + struct statvfs sfs; +#else + struct statfs sfs; +#endif + char *fsname = NULL; + int namespace = EXTATTR_NAMESPACE_USER; + struct _fbsdattr_context context; + + memset(&context,0,sizeof(struct _fbsdattr_context)); + + /* no fbsdattr attributes for data to a buffer */ + if(len) + return 0; + if(file == NULL) + return 0; + + if( !xar_check_prop(x, "ea") ) + return 0; + +TRYAGAIN: + /* extattr_list_link()'s man page does not define the return + * value. The kernel source comments say 0 for success, -1 for + * failure. However, the observed behavior is # of bytes + * used, 0 if none, -1 on error. + * Also, errno is not documented to be set to anything useful + * if buf is too small. We are using an undocumented "feature" + * that if the data argument is NULL, it will return the number + * of bytes that would have been written (beware, return value + * does not indicate success or failure on it's own. Need to + * check the return value *and* the parameters. + */ + ret = extattr_list_link(file, namespace, NULL, 0); + if( ret < 0 ) { + if( namespace == EXTATTR_NAMESPACE_USER ) { + namespace = EXTATTR_NAMESPACE_SYSTEM; + goto TRYAGAIN; + } else { + /* If we get eperm on system namespace, don't + * return error. This is expected for normal + * users trying to archive the system namespace + * on freebsd 6.2. On netbsd 3.1, they've decided + * to return EOPNOTSUPP instead. + */ + if( errno == EPERM ) + ret = 0; + else if( errno == EOPNOTSUPP ) + ret = 0; + else { + xar_err_new(x); + xar_err_set_file(x, f); + xar_err_set_string(x, "Error archiving EA"); + xar_err_callback(x, XAR_SEVERITY_NONFATAL, XAR_ERR_ARCHIVE_CREATION); + ret = 0; + } + goto BAIL; + } + } + bufsz = ret; + buf = malloc(bufsz); + if( !buf ) { + retval = -1; + goto BAIL; + } + memset(buf, 0, bufsz); + ret = extattr_list_link(file, namespace, buf, bufsz); + if( ret < 0 ) { + switch(errno) { + case ENOTSUP: retval=0; goto BAIL; + default: retval=-1; goto BAIL; + }; + } + /* Even though 0 is a documented success, observed behavior + * indicates 0 means all perms were satisfied, etc, but + * no extattrs were found to list. + */ + if( ret == 0 ) { + if( namespace == EXTATTR_NAMESPACE_USER ) { + namespace = EXTATTR_NAMESPACE_SYSTEM; + goto TRYAGAIN; + } else { + /* If we get eperm on system namespace, don't + * return error. This is expected for normal + * users trying to archive the system namespace + * on freebsd 6.2. On netbsd 3.1, they've decided + * to return EOPNOTSUPP instead. + */ + if( errno == EPERM ) + ret = 0; + else if( errno == EOPNOTSUPP ) + ret = 0; + else { + xar_err_new(x); + xar_err_set_file(x, f); + xar_err_set_string(x, "Error archiving EA"); + xar_err_callback(x, XAR_SEVERITY_NONFATAL, XAR_ERR_ARCHIVE_CREATION); + ret = 0; + } + goto BAIL; + } + } + + +#if defined(HAVE_STATVFS) && defined(HAVE_STRUCT_STATVFS_F_FSTYPENAME) + statvfs(file, &sfs); +#else + statfs(file, &sfs); +#endif + + fsname = sfs.f_fstypename; + + /* extattr_list_link() does not return the series of keys NUL + * separated, as documented in the man page. Instead, it + * returns things DNS style, with a 1 byte length followed by + * the key, repeated for as many keys as there are. + */ + for( i=0; i < ret; i++ ) { + char key[256]; + char *ns; + char tempnam[1024]; + xar_ea_t e; + + memset(key, 0, sizeof(key)); + memcpy(key, buf+i+1, buf[i]); + i += buf[i] ; + + extattr_namespace_to_string(namespace, &ns); + memset(tempnam, 0, sizeof(tempnam)); + snprintf(tempnam, sizeof(tempnam)-1, "%s.%s", ns, key); + FBSDATTR_CONTEXT(&context)->ns = namespace; + FBSDATTR_CONTEXT(&context)->file = file; + FBSDATTR_CONTEXT(&context)->attrname = key; + + e = xar_ea_new(f, tempnam); + xar_ea_pset(f, e, "fstype", fsname); + if (XAR(x)->attrcopy_to_heap(x, f, xar_ea_root(e), xar_fbsdattr_read, &context) < 0) { + ret = -1; + goto BAIL; + } + + free(FBSDATTR_CONTEXT(&context)->buf); + FBSDATTR_CONTEXT(&context)->buf = NULL; + FBSDATTR_CONTEXT(&context)->off = 0; + } + + if( namespace == EXTATTR_NAMESPACE_USER ) { + namespace = EXTATTR_NAMESPACE_SYSTEM; + free(buf); + buf = NULL; + goto TRYAGAIN; + } + +BAIL: + free(buf); + return ret; +#else + return 0; +#endif +} + +int32_t xar_fbsdattr_extract(xar_t x, xar_file_t f, const char* file, char *buffer, size_t len) +{ +#ifdef HAVE_SYS_EXTATTR_H + char *fsname = "bogus"; + xar_prop_t p; +#if defined(HAVE_STATVFS) && defined(HAVE_STRUCT_STATVFS_F_FSTYPENAME) + struct statvfs sfs; +#else + struct statfs sfs; +#endif + int eaopt = 0; + struct _fbsdattr_context context; + + memset(&context,0,sizeof(struct _fbsdattr_context)); + + /* no fbsdattr attributes for data to a buffer */ + if(len){ + return 0; + } + +#if defined(HAVE_STATVFS) && defined(HAVE_STRUCT_STATVFS_F_FSTYPENAME) + statvfs(file, &sfs); +#else + statfs(file, &sfs); +#endif + fsname = sfs.f_fstypename; + + for(p = xar_prop_pfirst(f); p; p = xar_prop_pnext(p)) { + const char *fs = NULL; + const char *prop; + const char *eaname = NULL; + xar_prop_t tmpp; + + prop = xar_prop_getkey(p); + + if( strncmp(prop, XAR_EA_FORK, strlen(XAR_EA_FORK) != 0 ) ) + continue; + if( strlen(prop) != strlen(XAR_EA_FORK) ) + continue; + + tmpp = xar_prop_pget(p, "fstype"); + if( tmpp ) + fs = xar_prop_getvalue(tmpp); + + if( !eaopt && fs && strcmp(fs, fsname) != 0 ) { + continue; + } + + tmpp = xar_prop_pget(p, "name"); + if( tmpp ) + eaname = xar_prop_getvalue(tmpp); + + if( !eaname ) + continue; + + if( strncmp(eaname, "user.", 5) == 0 ) { + FBSDATTR_CONTEXT(&context)->ns = EXTATTR_NAMESPACE_USER; + FBSDATTR_CONTEXT(&context)->attrname = eaname + 5; + } else if( strncmp(eaname, "system.", 7) == 0 ) { + FBSDATTR_CONTEXT(&context)->ns = EXTATTR_NAMESPACE_SYSTEM; + FBSDATTR_CONTEXT(&context)->attrname = eaname + 7; + } else { + continue; + } + + FBSDATTR_CONTEXT(&context)->file = file; + if (XAR(x)->attrcopy_from_heap(x, f, p, xar_fbsdattr_write, &context) < 0) + return -1; + } + + +#endif + return 0; +} diff --git a/xar/lib/fbsdattr.h b/xar/lib/fbsdattr.h new file mode 100644 index 0000000..71d3209 --- /dev/null +++ b/xar/lib/fbsdattr.h @@ -0,0 +1,41 @@ +/* All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Apple nor the names of any contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. +*/ +/* + * Rob Braun + * 26-Oct-2004 + * Copyright (c) 2004 Rob Braun. All rights reserved. + */ +/* + * Portions Copyright 2006, Apple Computer, Inc. + * Christopher Ryan +*/ + +#ifndef _XAR_FBSDATTR_H_ +#define _XAR_FBSDATTR_H_ +int32_t xar_fbsdattr_archive(xar_t x, xar_file_t f, const char* file, const char *buffer, size_t len); +int32_t xar_fbsdattr_extract(xar_t x, xar_file_t f, const char* file, char *buffer, size_t len); +#endif /* _XAR_FBSDATTR_H_ */ diff --git a/xar/lib/filetree.c b/xar/lib/filetree.c new file mode 100644 index 0000000..f96760d --- /dev/null +++ b/xar/lib/filetree.c @@ -0,0 +1,1103 @@ +/* + * Copyright (c) 2005-2008 Rob Braun + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Rob Braun nor the names of his contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +/* + * 03-Apr-2005 + * DRI: Rob Braun + */ +/* + * Portions Copyright 2006, Apple Computer, Inc. + * Christopher Ryan +*/ + +#define _FILE_OFFSET_BITS 64 + +#include "config.h" +#include +#include +#include +#include +#include +#include +#include +#include + +#ifndef HAVE_ASPRINTF +#include "asprintf.h" +#endif +#include "xar.h" +#include "filetree.h" +#include "archive.h" +#include "util.h" +#include "b64.h" +#include "ea.h" + + +/* xar_attr_prop + * Returns: a newly allocated and initialized property attribute. + * It is the caller's responsibility to associate the attribute + * with either a file or a property. + */ +xar_attr_t xar_attr_new(void) { + xar_attr_t ret; + + ret = malloc(sizeof(struct __xar_attr_t)); + if(!ret) return NULL; + + XAR_ATTR(ret)->key = NULL; + XAR_ATTR(ret)->value = NULL; + XAR_ATTR(ret)->next = NULL; + XAR_ATTR(ret)->ns = NULL; + return ret; +} + +int32_t xar_attr_pset(xar_file_t f, xar_prop_t p, const char *key, const char *value) { + xar_attr_t a, i; + if( !p ) { + a = XAR_FILE(f)->attrs; + } else { + a = XAR_PROP(p)->attrs; + } + + if( !a ) { + a = xar_attr_new(); + if(!p) + XAR_FILE(f)->attrs = a; + else + XAR_PROP(p)->attrs = a; + XAR_ATTR(a)->key = strdup(key); + XAR_ATTR(a)->value = strdup(value); + return 0; + } + + for(i = a; i && XAR_ATTR(i)->next; i = XAR_ATTR(i)->next) { + if(strcmp(XAR_ATTR(i)->key, key)==0) { + free((char*)XAR_ATTR(i)->value); + XAR_ATTR(i)->value = strdup(value); + return 0; + } + } + a = xar_attr_new(); + if(!p) { + XAR_ATTR(a)->next = XAR_ATTR(XAR_FILE(f)->attrs); + XAR_FILE(f)->attrs = a; + } else { + XAR_ATTR(a)->next = XAR_ATTR(XAR_PROP(p)->attrs); + XAR_PROP(p)->attrs = a; + } + XAR_ATTR(a)->key = strdup(key); + XAR_ATTR(a)->value = strdup(value); + return 0; +} + +/* xar_attr_set + * f: the file the attribute is associated with + * prop: The property key the attribute is associated with. This can + * be NULL to signify the attribute should be set for the file, + * rather than the property. + * key: The name of the attribute to set. + * value: The value of the attribute. + * Returns: 0 on success, -1 on failure. + * Summary: Basically, sets an attribute. The only tricky part is + * it can set an attribute on a property or a file. + */ +int32_t xar_attr_set(xar_file_t f, const char *prop, const char *key, const char *value) { + if( !prop ) { + return xar_attr_pset(f, NULL, key, value); + } else { + xar_prop_t p = NULL; + p = xar_prop_find(XAR_FILE(f)->props, prop); + if( !p ) return -1; + return xar_attr_pset(f, p, key, value); + } +} + +const char *xar_attr_pget(xar_file_t f, xar_prop_t p, const char *key) { + xar_attr_t a, i; + + if( !p ) + a = XAR_FILE(f)->attrs; + else + a = XAR_PROP(p)->attrs; + + if( !a ) return NULL; + + for(i = a; i && XAR_ATTR(i)->next; i = XAR_ATTR(i)->next) { + if(strcmp(XAR_ATTR(i)->key, key)==0) { + return XAR_ATTR(i)->value; + } + } + if( i && (strcmp(XAR_ATTR(i)->key, key)==0)) + return XAR_ATTR(i)->value; + return NULL; +} + +/* xar_attr_get + * f: file to find the associated attribute in + * prop: name of the property the attribute is of. May be NULL to specify + * the file's attributes. + * key: name of the attribute to search for. + * Returns: a reference to the value of the attribute. + */ +const char *xar_attr_get(xar_file_t f, const char *prop, const char *key) { + if( !prop ) + return xar_attr_pget(f, NULL, key); + else { + xar_prop_t p = NULL; + p = xar_prop_find(XAR_FILE(f)->props, prop); + if( !p ) return NULL; + return xar_attr_pget(f, p, key); + } +} + +/* xar_attr_free + * a: attribute to free + * Summary: frees the attribute structure and everything inside it. + * It is the caller's responsibility to ensure the linked list gets + * updated. This will *not* do anything to ensure the consistency + * of the attribute linked list. + */ +void xar_attr_free(xar_attr_t a) { + if(!a) return; + free((char*)XAR_ATTR(a)->key); + free((char*)XAR_ATTR(a)->value); + free(XAR_ATTR(a)); + return; +} + +/* xar_attr_first + * f: file to associate the iterator with + * prop: the name of the property within the file to associate the iterator with + * i: an iterator as returned by xar_iter_new + * Returns: a pointer to the value of the first attribute associated with the + * property 'prop' associated with the file 'f' + * Summary: This MUST be called prior to calling xar_attr_next, + * to iterate over the attributes of property key 'prop'. + */ +const char *xar_attr_first(xar_file_t f, const char *prop, xar_iter_t i) { + xar_prop_t p = NULL; + xar_attr_t a; + + if( !prop ) + a = XAR_FILE(f)->attrs; + else { + p = xar_prop_find(XAR_FILE(f)->props, prop); + if( !p ) return NULL; + a = XAR_PROP(p)->attrs; + } + + if( !a ) return NULL; + + XAR_ITER(i)->iter = a; + free(XAR_ITER(i)->node); + XAR_ITER(i)->node = strdup(XAR_ATTR(a)->key); + return XAR_ITER(i)->node; +} + +/* xar_attr_next + * i: iterator allocated by xar_iter_new, and initialized with xar_attr_first + * Returns: a pointer to the key of the next attribute associated with + * the iterator. NULL will be returned when there are no more attributes + * to find. + */ +const char *xar_attr_next(xar_iter_t i) { + xar_attr_t a = XAR_ITER(i)->iter; + + if( XAR_ATTR(a)->next == NULL ) + return NULL; + + XAR_ITER(i)->iter = XAR_ATTR(a)->next; + free(XAR_ITER(i)->node); + XAR_ITER(i)->node = strdup(XAR_ATTR(XAR_ITER(i)->iter)->key); + return XAR_ITER(i)->node; +} + +/* xar_iter_new + * Returns a newly allocated iterator for use on files, properties, or + * attributes. + */ +xar_iter_t xar_iter_new(void) { + xar_iter_t ret = malloc(sizeof(struct __xar_iter_t)); + if(!ret) return NULL; + + XAR_ITER(ret)->iter = NULL; + XAR_ITER(ret)->path = NULL; + XAR_ITER(ret)->node = NULL; + XAR_ITER(ret)->nochild = 0; + return ret; +} + +/* xar_iter_free + * Frees memory associated with the specified iterator + */ +void xar_iter_free(xar_iter_t i) { + free(XAR_ITER(i)->node); + if( XAR_ITER(i)->path ) + free(XAR_ITER(i)->path); + free(XAR_ITER(i)); +} + +const char *xar_prop_getkey(xar_prop_t p) { + return XAR_PROP(p)->key; +} +const char *xar_prop_getvalue(xar_prop_t p) { + return XAR_PROP(p)->value; +} +int32_t xar_prop_setkey(xar_prop_t p, const char *key) { + free((char *)XAR_PROP(p)->key); + if(key) + XAR_PROP(p)->key = strdup(key); + return 0; +} +int32_t xar_prop_setvalue(xar_prop_t p, const char *value) { + free((char *)XAR_PROP(p)->value); + if(value) + XAR_PROP(p)->value = strdup(value); + return 0; +} + +/* xar_prop_pfirst + * f: file to retrieve the first property from + * Returns: a xar_prop_t corresponding to the first xar_prop_t associated with f + * NULL if there are no properties associated with the file. + */ +xar_prop_t xar_prop_pfirst(xar_file_t f) { + return XAR_FILE(f)->props; +} + +/* xar_prop_pnext + * p: previous property used to retrieve the next + * Returns: a xar_prop_t if there is a next, NULL otherwise + */ +xar_prop_t xar_prop_pnext(xar_prop_t p) { + return XAR_PROP(p)->next; +} + +/* xar_prop_first + * f: file to associate the iterator with + * i: an iterator as returned by xar_iter_new + * Returns: a pointer to the value of the first property associated with + * the file 'f'. + * Summary: This MUST be called first prior to calling xar_prop_next, + * to iterate over properties of file 'f'. This has the side effect of + * associating the iterator with the file's properties, which is needed + * before xar_prop_next. + */ +const char *xar_prop_first(xar_file_t f, xar_iter_t i) { + XAR_ITER(i)->iter = XAR_FILE(f)->props; + free(XAR_ITER(i)->node); + XAR_ITER(i)->node = strdup(XAR_PROP(XAR_ITER(i)->iter)->key); + return XAR_ITER(i)->node; +} + +/* xar_prop_next + * i: iterator allocated by xar_iter_new, and initialized with xar_prop_first + * Returns: a pointer to the value of the next property associated with + * the iterator. NULL will be returned when there are no more properties + * to find. If a property has a NULL value, the string "" will be returned. + * This will recurse down child properties, flattening the namespace and + * adding separators. For instance a1->b1->c1, a1 will first be returned, + * the subsequent call will return "a1/b1", and the next call will return + * "a1/b1/c1", etc. + */ +const char *xar_prop_next(xar_iter_t i) { + xar_prop_t p = XAR_ITER(i)->iter; + if( !(XAR_ITER(i)->nochild) && XAR_PROP(p)->children ) { + char *tmp = XAR_ITER(i)->path; + if( tmp ) { + asprintf(&XAR_ITER(i)->path, "%s/%s", tmp, XAR_PROP(p)->key); + free(tmp); + } else + XAR_ITER(i)->path = strdup(XAR_PROP(p)->key); + XAR_ITER(i)->iter = p = XAR_PROP(p)->children; + goto SUCCESS; + } + XAR_ITER(i)->nochild = 0; + + if( XAR_PROP(p)->next ) { + XAR_ITER(i)->iter = p = XAR_PROP(p)->next; + goto SUCCESS; + } + + if( XAR_PROP(p)->parent ) { + char *tmp1, *tmp2; + + if( strstr(XAR_ITER(i)->path, "/") ) { + tmp1 = tmp2 = XAR_ITER(i)->path; + XAR_ITER(i)->path = xar_safe_dirname(tmp2); + free(tmp1); + } else { + free(XAR_ITER(i)->path); + XAR_ITER(i)->path = NULL; + } + + XAR_ITER(i)->iter = p = XAR_PROP(p)->parent; + XAR_ITER(i)->nochild = 1; + return xar_prop_next(i); + } + + return NULL; +SUCCESS: + free(XAR_ITER(i)->node); + if( XAR_ITER(i)->path ) + asprintf((char **)&XAR_ITER(i)->node, "%s/%s", XAR_ITER(i)->path, XAR_PROP(p)->key); + else { + if(XAR_PROP(p)->key == NULL) + XAR_ITER(i)->node = strdup(""); + else + XAR_ITER(i)->node = strdup(XAR_PROP(p)->key); + } + return XAR_ITER(i)->node; +} + +/* xar_prop_new + * f: file to associate the new file with. May not be NULL + * parent: the parent property of the new property. May be NULL + * Returns: a newly allocated and initialized property. + * Summary: in addition to allocating the new property, it + * will be inserted into the parent node's list of children, + * and/or added to the file's list of properties, as appropriate. + */ +xar_prop_t xar_prop_new(xar_file_t f, xar_prop_t parent) { + xar_prop_t p; + + p = malloc(sizeof(struct __xar_prop_t)); + if( !p ) return NULL; + + XAR_PROP(p)->key = NULL; + XAR_PROP(p)->value = NULL; + XAR_PROP(p)->children = NULL; + XAR_PROP(p)->next = NULL; + XAR_PROP(p)->attrs = NULL; + XAR_PROP(p)->parent = parent; + XAR_PROP(p)->file = f; + XAR_PROP(p)->prefix = XAR_FILE(f)->prefix; + XAR_PROP(p)->ns = NULL; + if(parent) { + if( !XAR_PROP(parent)->children ) { + XAR_PROP(parent)->children = p; + } else { + XAR_PROP(p)->next = XAR_PROP(parent)->children; + XAR_PROP(parent)->children = p; + } + } else { + if( XAR_FILE(f)->props == NULL ) { + XAR_FILE(f)->props = p; + } else { + XAR_PROP(p)->next = XAR_FILE(f)->props; + XAR_FILE(f)->props = p; + } + } + + return p; +} + +/* xar_prop_find + * p: property to check + * key: name of property to find. + * Returns: reference to the property with the specified key + * Summary: A node's name may be specified by a path, such as + * "a1/b1/c1", and child nodes will be searched for each + * "/" separator. + */ +xar_prop_t xar_prop_find(xar_prop_t p, const char *key) { + xar_prop_t i, ret; + char *tmp1, *tmp2, *tmp3; + + if( !p ) return NULL; + tmp2 = tmp1 = strdup(key); + tmp3 = strsep(&tmp2, "/"); + i = p; + do { + if( strcmp(tmp3, XAR_PROP(i)->key) == 0 ) { + if( tmp2 == NULL ) { + free(tmp1); + return i; + } + ret = xar_prop_find(XAR_PROP(i)->children, tmp2); + free(tmp1); + return ret; + } + i = XAR_PROP(i)->next; + } while(i); + free(tmp1); + return NULL; +} + +/* xar_prop_set_r + * p: property to recurse down and set the property of + * key: key of the property to set + * value: desired value of the property + * Returns: 0 on sucess, -1 on failure. + * Summary: This is an internal helper function for xar_prop_set() which + * does the recursion down the property tree. + */ +static xar_prop_t xar_prop_set_r(xar_file_t f, xar_prop_t p, const char *key, const char *value, int overwrite) { + xar_prop_t i, ret, ret2, start; + char *tmp1, *tmp2, *tmp3; + + tmp2 = tmp1 = strdup(key); + tmp3 = strsep(&tmp2, "/"); + + if( !p ) { + start = XAR_FILE(f)->props; + } else { + start = XAR_PROP(p)->children; + } + + for( i = start; i; i = XAR_PROP(i)->next ) { + if( strcmp(tmp3, XAR_PROP(i)->key) == 0 ) { + if( !tmp2 ) { + if( overwrite ) { + xar_prop_setvalue(i, value); + free(tmp1); + return i; + } else { + ret = xar_prop_new(f, p); + if( !ret ) { + free(tmp1); + return ret; + } + xar_prop_setvalue(ret, value); + xar_prop_setkey(ret, tmp3); + free(tmp1); + return ret; + } + } + + ret2 = xar_prop_set_r(f, i, tmp2, value, overwrite); + free(tmp1); + return ret2; + } + } + + ret = xar_prop_new(f, p); + if( !ret ) { + free(tmp1); + return ret; + } + + if( !tmp2 ) { + xar_prop_setvalue(ret, value); + xar_prop_setkey(ret, tmp3); + free(tmp1); + return ret; + } + + xar_prop_setkey(ret, tmp3); + xar_prop_setvalue(ret, NULL); + + ret2 = xar_prop_set_r(f, ret, tmp2, value, overwrite); + free(tmp1); + return ret2; +} + +/* xar_prop_set + * f: file to set the property on + * key: key of the property to set + * value: desired value of the property + * Returns: 0 on success, -1 on failure + * Summary: If the property already exists, its value is overwritten + * by 'value'. If the property does not exist, it is created. + * Copies of key and value are kept in the tree. The caller may do + * what they wish with these values after the call returns. + * References to these copies will be returned by iterating over + * the properties, or by calling xar_prop_get(). + * These copies will be released when the property is released. + * + * Note that you *CANNOT* have a node with a value and children. + * This implementation will let you, but the serialization to xml + * will not be what you're hoping for. + */ +int32_t xar_prop_set(xar_file_t f, const char *key, const char *value) { + if( xar_prop_set_r(f, NULL, key, value, 1) ) + return 0; + return -1; +} + +/* xar_prop_pset + * Same as xar_prop_set, except it takes a xar_prop_t which will be + * treated as the root property. + * Returns a xar_prop_t that was created or set. Returns NULL if error. + */ +xar_prop_t xar_prop_pset(xar_file_t f, xar_prop_t p, const char *key, const char *value) { + return xar_prop_set_r(f, p, key, value, 1); +} + +/* xar_prop_create + * Identical to xar_prop_set, except it will not overwrite an existing + * property, it will create another one. + */ +int32_t xar_prop_create(xar_file_t f, const char *key, const char *value) { + if( xar_prop_set_r(f, NULL, key, value, 0) ) + return 0; + return -1; +} + +/* xar_prop_get + * f: file to look for the property in + * key: name of property to find. + * value: on return, *value will point to the value of the property + * value may be NULL, in which case, only the existence of the property + * is tested. + * Returns: 0 for success, -1 on failure + * Summary: A node's name may be specified by a path, such as + * "a1/b1/c1", and child nodes will be searched for each + * "/" separator. + */ +int32_t xar_prop_get(xar_file_t f, const char *key, const char **value) { + xar_prop_t r = xar_prop_find(XAR_FILE(f)->props, key); + if( !r ) { + if(value) + *value = NULL; + return -1; + } + if(value) + *value = XAR_PROP(r)->value; + return 0; +} + +xar_prop_t xar_prop_pget(xar_prop_t p, const char *key) { + char *tmp; + const char *k; + xar_prop_t ret; + k = XAR_PROP(p)->key; + asprintf(&tmp, "%s/%s", k, key); + ret = xar_prop_find(p, tmp); + free(tmp); + return ret; +} + +/* xar_prop_replicate_r +* f: file to attach property +* p: property (list) to iterate and add +* parent: parent property +* Summary: Recursivley adds property list (p) to file (f) and parent (parent). +*/ + +void xar_prop_replicate_r(xar_file_t f, xar_prop_t p, xar_prop_t parent ) +{ + xar_prop_t property = p; + + /* look through properties */ + for( property = p; property; property = property->next ){ + xar_prop_t newprop = xar_prop_new( f, parent ); + + /* copy the key value for the property */ + XAR_PROP(newprop)->key = strdup(property->key); + if(property->value) + XAR_PROP(newprop)->value = strdup(property->value); + + /* loop through the attributes and copy them */ + xar_attr_t a = NULL; + xar_attr_t last = NULL; + + /* copy attributes for file */ + for(a = property->attrs; a; a = a->next) { + if( NULL == newprop->attrs ){ + last = xar_attr_new(); + XAR_PROP(newprop)->attrs = last; + }else{ + XAR_ATTR(last)->next = xar_attr_new(); + last = XAR_ATTR(last)->next; + } + + XAR_ATTR(last)->key = strdup(a->key); + if(a->value) + XAR_ATTR(last)->value = strdup(a->value); + } + + /* loop through the children properties and recursively add them */ + xar_prop_replicate_r(f, property->children, newprop ); + } + +} + +/* xar_prop_free + * p: property to free + * Summary: frees the specified property and all its children. + * Stored copies of the key and value will be released, as will + * all attributes. + */ +void xar_prop_free(xar_prop_t p) { + xar_prop_t i; + xar_attr_t a; + while( XAR_PROP(p)->children ) { + i = XAR_PROP(p)->children; + XAR_PROP(p)->children = XAR_PROP(i)->next; + xar_prop_free(i); + } + while(XAR_PROP(p)->attrs) { + a = XAR_PROP(p)->attrs; + XAR_PROP(p)->attrs = XAR_ATTR(a)->next; + xar_attr_free(a); + } + free((char*)XAR_PROP(p)->key); + free((char*)XAR_PROP(p)->value); + free(XAR_PROP(p)); +} + +void xar_prop_punset(xar_file_t f, xar_prop_t p) { + xar_prop_t i; + if( !p ) { + return; + } + if( XAR_PROP(p)->parent ) { + i = XAR_PROP(p)->parent->children; + if( i == p ) { + XAR_PROP(XAR_PROP(p)->parent)->children = XAR_PROP(p)->next; + xar_prop_free(p); + return; + } + } else { + i = XAR_FILE(f)->props; + if( i == p ) { + XAR_FILE(f)->props = XAR_PROP(p)->next; + xar_prop_free(p); + return; + } + } + + while( i && (XAR_PROP(i)->next != XAR_PROP(p)) ) { + i = XAR_PROP(i)->next; + } + if( i && (XAR_PROP(i)->next == XAR_PROP(p)) ) { + XAR_PROP(i)->next = XAR_PROP(p)->next; + xar_prop_free(p); + } + return; +} + +void xar_prop_unset(xar_file_t f, const char *key) { + xar_prop_t r = xar_prop_find(XAR_FILE(f)->props, key); + + xar_prop_punset(f, r); + return; +} + +/* xar_file_new + * f: parent file of the file to be created. May be NULL + * Returns: a newly allocated file structure. + */ +xar_file_t xar_file_new(xar_file_t f) { + xar_file_t ret, i; + + ret = calloc(1, sizeof(struct __xar_file_t)); + if(!ret) return NULL; + + XAR_FILE(ret)->parent = f; + XAR_FILE(ret)->next = NULL; + XAR_FILE(ret)->children = NULL; + XAR_FILE(ret)->props = NULL; + XAR_FILE(ret)->attrs = NULL; + XAR_FILE(ret)->prefix = NULL; + XAR_FILE(ret)->ns = NULL; + XAR_FILE(ret)->fspath = NULL; + XAR_FILE(ret)->eas = NULL; + XAR_FILE(ret)->nexteaid = 0; + if( f ) { + if( !XAR_FILE(f)->children ) { + XAR_FILE(f)->children = ret; + } else { + for(i = XAR_FILE(f)->children; XAR_FILE(i)->next; i = XAR_FILE(i)->next); + XAR_FILE(i)->next = ret; + } + } + + return ret; +} + +xar_file_t xar_file_replicate(xar_file_t original, xar_file_t newparent) +{ + xar_file_t ret = xar_file_new(newparent); + xar_attr_t a; + + /* copy attributes for file */ + for(a = XAR_FILE(original)->attrs; a; a = XAR_ATTR(a)->next) { + /* skip the id attribute */ + if( 0 == strcmp(a->key, "id" ) ) + continue; + + xar_attr_set(ret, NULL , a->key, a->value ); + } + + /* recursively copy properties */ + xar_prop_replicate_r(ret, XAR_FILE(original)->props, NULL); + + return ret; +} + +/* xar_file_free + * f: file to free + * Summary: frees the specified file and all children, + * properties, and attributes associated with the file. + */ +void xar_file_free(xar_file_t f) { + xar_file_t i; + xar_prop_t n; + xar_attr_t a; + while(XAR_FILE(f)->children) { + i = XAR_FILE(f)->children; + XAR_FILE(f)->children = XAR_FILE(i)->next; + xar_file_free(i); + } + while(XAR_FILE(f)->props) { + n = XAR_FILE(f)->props; + XAR_FILE(f)->props = XAR_PROP(n)->next; + xar_prop_free(n); + } + while(XAR_FILE(f)->attrs) { + a = XAR_FILE(f)->attrs; + XAR_FILE(f)->attrs = XAR_ATTR(a)->next; + xar_attr_free(a); + } + free((char *)XAR_FILE(f)->fspath); + free(XAR_FILE(f)); +} + +/* xar_file_first + * x: archive to associate the iterator with + * i: an iterator as returned by xar_iter_new + * Returns: a pointer to the name of the first file associated with + * the archive 'x'. + * Summary: This MUST be called first prior to calling xar_file_next, + * to iterate over files of archive 'x'. This has the side effect of + * associating the iterator with the archive's files, which is needed + * before xar_file_next. + */ +xar_file_t xar_file_first(xar_t x, xar_iter_t i) { + XAR_ITER(i)->iter = XAR(x)->files; + free(XAR_ITER(i)->node); + return XAR_ITER(i)->iter; +} + +/* xar_file_next + * i: iterator allocated by xar_iter_new, and initialized with xar_file_first + * Returns: a pointer to the name of the next file associated with + * the iterator. NULL will be returned when there are no more files + * to find. + * This will recurse down child files (directories), flattening the + * namespace and adding separators. For instance a1->b1->c1, a1 will + * first be returned, the subsequent call will return "a1/b1", and the + * next call will return "a1/b1/c1", etc. + */ +xar_file_t xar_file_next(xar_iter_t i) { + xar_file_t f = XAR_ITER(i)->iter; + const char *name; + if( !(XAR_ITER(i)->nochild) && XAR_FILE(f)->children ) { + char *tmp = XAR_ITER(i)->path; + xar_prop_get(f, "name", &name); + if( tmp ) { + asprintf(&XAR_ITER(i)->path, "%s/%s", tmp, name); + free(tmp); + } else + XAR_ITER(i)->path = strdup(name); + XAR_ITER(i)->iter = f = XAR_FILE(f)->children; + goto FSUCCESS; + } + XAR_ITER(i)->nochild = 0; + + if( XAR_FILE(f)->next ) { + XAR_ITER(i)->iter = f = XAR_FILE(f)->next; + goto FSUCCESS; + } + + if( XAR_FILE(f)->parent ) { + char *tmp1, *tmp2; + + if( strstr(XAR_ITER(i)->path, "/") ) { + tmp1 = tmp2 = XAR_ITER(i)->path; + XAR_ITER(i)->path = xar_safe_dirname(tmp2); + free(tmp1); + } else { + free(XAR_ITER(i)->path); + XAR_ITER(i)->path = NULL; + } + + XAR_ITER(i)->iter = f = XAR_FILE(f)->parent; + XAR_ITER(i)->nochild = 1; + return xar_file_next(i); + } + + return NULL; +FSUCCESS: + xar_prop_get(f, "name", &name); + XAR_ITER(i)->iter = (void *)f; + + return XAR_ITER(i)->iter; +} + +/* xar_file_find + * f: file subtree to look under + * path: path to file to find + * Returns the file_t describing the file, or NULL if not found. + */ +xar_file_t xar_file_find(xar_file_t f, const char *path) { + xar_file_t i, ret; + char *tmp1, *tmp2, *tmp3; + + if( !f ) return NULL; + tmp2 = tmp1 = strdup(path); + tmp3 = strsep(&tmp2, "/"); + i = f; + do { + const char *name; + xar_prop_get(i, "name", &name); + if( name == NULL ) continue; + if( strcmp(tmp3, name) == 0 ) { + if( tmp2 == NULL ) { + free(tmp1); + return i; + } + ret = xar_file_find(XAR_FILE(i)->children, tmp2); + free(tmp1); + return ret; + } + i = XAR_FILE(i)->next; + } while(i); + free(tmp1); + return NULL; +} + + +/* xar_prop_serialize + * p: property to serialize + * writer: the xmlTextWriterPtr allocated by xmlNewTextWriter*() + * Summary: recursively serializes the property passed to it, including + * children, siblings, attributes, etc. + */ +void xar_prop_serialize(xar_prop_t p, xmlTextWriterPtr writer) { + xar_prop_t i; + xar_attr_t a; + + if( !p ) + return; + i = p; + do { + if( XAR_PROP(i)->prefix || XAR_PROP(i)->ns ) + xmlTextWriterStartElementNS(writer, BAD_CAST(XAR_PROP(i)->prefix), BAD_CAST(XAR_PROP(i)->key), NULL); + else + xmlTextWriterStartElement(writer, BAD_CAST(XAR_PROP(i)->key)); + for(a = XAR_PROP(i)->attrs; a; a = XAR_ATTR(a)->next) { + xmlTextWriterWriteAttributeNS(writer, BAD_CAST(XAR_ATTR(a)->ns), BAD_CAST(XAR_ATTR(a)->key), NULL, BAD_CAST(XAR_ATTR(a)->value)); + } + if( XAR_PROP(i)->value ) { + if( strcmp(XAR_PROP(i)->key, "name") == 0 ) { + unsigned char *tmp; + int outlen = strlen(XAR_PROP(i)->value); + int inlen, len; + + inlen = len = outlen; + + tmp = malloc(len); + assert(tmp); + if( UTF8Toisolat1(tmp, &len, BAD_CAST(XAR_PROP(i)->value), &inlen) < 0 ) { + xmlTextWriterWriteAttribute(writer, BAD_CAST("enctype"), BAD_CAST("base64")); + xmlTextWriterWriteBase64(writer, XAR_PROP(i)->value, 0, strlen(XAR_PROP(i)->value)); + } else + xmlTextWriterWriteString(writer, BAD_CAST(XAR_PROP(i)->value)); + free(tmp); + } else + xmlTextWriterWriteString(writer, BAD_CAST(XAR_PROP(i)->value)); + } + + if( XAR_PROP(i)->children ) { + xar_prop_serialize(XAR_PROP(i)->children, writer); + } + xmlTextWriterEndElement(writer); + + i = XAR_PROP(i)->next; + } while(i); +} + +/* xar_file_serialize + * f: file to serialize + * writer: the xmlTextWriterPtr allocated by xmlNewTextWriter*() + * Summary: recursively serializes the file passed to it, including + * children, siblings, properties, attributes, etc. + */ +void xar_file_serialize(xar_file_t f, xmlTextWriterPtr writer) { + xar_file_t i; + xar_attr_t a; + + i = f; + do { + xmlTextWriterStartElement(writer, BAD_CAST("file")); + for(a = XAR_FILE(i)->attrs; a; a = XAR_ATTR(a)->next) { + xmlTextWriterWriteAttribute(writer, BAD_CAST(XAR_ATTR(a)->key), BAD_CAST(XAR_ATTR(a)->value)); + } + xar_prop_serialize(XAR_FILE(i)->props, writer); + if( XAR_FILE(i)->children ) + xar_file_serialize(XAR_FILE(i)->children, writer); + xmlTextWriterEndElement(writer); + i = XAR_FILE(i)->next; + } while(i); + return; +} + +/* xar_prop_unserialize + * f: file the property is to belong to + * p: parent property, may be NULL + * reader: xmlTextReaderPtr already allocated + */ +int32_t xar_prop_unserialize(xar_file_t f, xar_prop_t parent, xmlTextReaderPtr reader) { + const char *name, *value, *ns; + int type, i, isempty = 0; + int isname = 0, isencoded = 0; + xar_prop_t p; + + p = xar_prop_new(f, parent); + if( xmlTextReaderIsEmptyElement(reader) ) + isempty = 1; + i = xmlTextReaderAttributeCount(reader); + name = (const char *)xmlTextReaderConstLocalName(reader); + XAR_PROP(p)->key = strdup(name); + ns = (const char *)xmlTextReaderConstPrefix(reader); + if( ns ) XAR_PROP(p)->prefix = strdup(ns); + if( strcmp(name, "name") == 0 ) + isname = 1; + if( i > 0 ) { + for(i = xmlTextReaderMoveToFirstAttribute(reader); i == 1; i = xmlTextReaderMoveToNextAttribute(reader)) { + xar_attr_t a; + const char *name = (const char *)xmlTextReaderConstLocalName(reader); + const char *value = (const char *)xmlTextReaderConstValue(reader); + const char *ns = (const char *)xmlTextReaderConstPrefix(reader); + if( isname && (strcmp(name, "enctype") == 0) && (strcmp(value, "base64") == 0) ) { + isencoded = 1; + } else { + a = xar_attr_new(); + XAR_ATTR(a)->key = strdup(name); + XAR_ATTR(a)->value = strdup(value); + if(ns) XAR_ATTR(a)->ns = strdup(ns); + XAR_ATTR(a)->next = XAR_PROP(p)->attrs; + XAR_PROP(p)->attrs = a; + } + } + } + if( isempty ) + return 0; + while( xmlTextReaderRead(reader) == 1) { + type = xmlTextReaderNodeType(reader); + switch(type) { + case XML_READER_TYPE_ELEMENT: + xar_prop_unserialize(f, p, reader); + break; + case XML_READER_TYPE_TEXT: + value = (const char *)xmlTextReaderConstValue(reader); + free((char*)XAR_PROP(p)->value); + if( isencoded ) + XAR_PROP(p)->value = (const char *)xar_from_base64(BAD_CAST(value), strlen(value), NULL); + else + XAR_PROP(p)->value = strdup(value); + if( isname ) { + if( XAR_FILE(f)->parent ) { + + if (XAR_FILE(f)->fspath) { /* It's possible that a XAR header may contain multiple name entries. Make sure we don't smash the old one. */ + free((void*)XAR_FILE(f)->fspath); + XAR_FILE(f)->fspath = NULL; + } + + asprintf((char **)&XAR_FILE(f)->fspath, "%s/%s", XAR_FILE(XAR_FILE(f)->parent)->fspath, XAR_PROP(p)->value); + } else { + + if (XAR_FILE(f)->fspath) { /* It's possible that a XAR header may contain multiple name entries. Make sure we don't smash the old one. */ + free((void*)XAR_FILE(f)->fspath); + XAR_FILE(f)->fspath = NULL; + } + + XAR_FILE(f)->fspath = strdup(XAR_PROP(p)->value); + } + } + break; + case XML_READER_TYPE_END_ELEMENT: + return 0; + break; + } + } + + /* XXX: Should never be reached */ + return 0; +} + +/* xar_file_unserialize + * x: archive we're unserializing to + * parent: The parent file of the file to be unserialized. May be NULL + * reader: The xmlTextReaderPtr we are reading the xml from. + * Summary: Takes a node, and adds all attributes, child properties, + * and child files. + */ +xar_file_t xar_file_unserialize(xar_t x, xar_file_t parent, xmlTextReaderPtr reader) { + xar_file_t ret; + const char *name; + int type, i; + + ret = xar_file_new(parent); + + i = xmlTextReaderAttributeCount(reader); + if( i > 0 ) { + for(i = xmlTextReaderMoveToFirstAttribute(reader); i == 1; i = xmlTextReaderMoveToNextAttribute(reader)) { + xar_attr_t a; + const char *name = (const char *)xmlTextReaderConstLocalName(reader); + const char *value = (const char *)xmlTextReaderConstValue(reader); + a = xar_attr_new(); + XAR_ATTR(a)->key = strdup(name); + XAR_ATTR(a)->value = strdup(value); + XAR_ATTR(a)->next = XAR_FILE(ret)->attrs; + XAR_FILE(ret)->attrs = a; + } + } + + // recursively unserialize each element nested within this + while( xmlTextReaderRead(reader) == 1 ) { + type = xmlTextReaderNodeType(reader); + name = (const char *)xmlTextReaderConstLocalName(reader); + if( (type == XML_READER_TYPE_END_ELEMENT) && (strcmp(name, "file")==0) ) { + const char *opt; + xar_prop_get(ret, "type", &opt); + if( opt && (strcmp(opt, "hardlink") == 0) ) { + opt = xar_attr_get(ret, "type", "link"); + if( opt && (strcmp(opt, "original") == 0) ) { + opt = xar_attr_get(ret, NULL, "id"); + xmlHashAddEntry(XAR(x)->link_hash, BAD_CAST(opt), XAR_FILE(ret)); + } + } + return ret; + } + + if( type == XML_READER_TYPE_ELEMENT ) { + if( strcmp(name, "file")==0 ) { + xar_file_unserialize(x, ret, reader); + } else + xar_prop_unserialize(ret, NULL, reader); + } + } + + /* XXX Should never be reached */ + return ret; +} + diff --git a/xar/lib/filetree.h b/xar/lib/filetree.h new file mode 100644 index 0000000..0eb3897 --- /dev/null +++ b/xar/lib/filetree.h @@ -0,0 +1,144 @@ +/* + * Copyright (c) 2005-2007 Rob Braun + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Rob Braun nor the names of his contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +/* + * 03-Apr-2005 + * DRI: Rob Braun + */ +/* + * Portions Copyright 2006, Apple Computer, Inc. + * Christopher Ryan +*/ + +#ifndef _XAR_FILETREE_H_ +#define _XAR_FILETREE_H_ + +#ifndef _FILE_OFFSET_BITS +#define _FILE_OFFSET_BITS 64 +#endif + +#include +#include + +struct __xar_attr_t { + const char *key; + const char *value; + const char *ns; + const struct __xar_attr_t *next; +}; +typedef const struct __xar_attr_t *xar_attr_t; + +struct __xar_prop_t { + const char *key; + const char *value; + const struct __xar_prop_t *parent; + const struct __xar_prop_t *children; + const struct __xar_prop_t *next; + const struct __xar_attr_t *attrs; + const struct __xar_file_t *file; + const char *prefix; + const char *ns; +}; +typedef const struct __xar_prop_t *xar_prop_t; + +#include "ea.h" + +struct __xar_file_t { + const struct __xar_prop_t *props; + const struct __xar_attr_t *attrs; + const char *prefix; + const char *ns; + const char *fspath; + char parent_extracted; + const struct __xar_file_t *parent; + const struct __xar_file_t *children; + const struct __xar_file_t *next; + xar_ea_t eas; + uint64_t nexteaid; +}; + +/* Overview: + * xar_file_t's exist within a xar_archive_t. xar_prop_t's exist + * within xar_file_t's and xar_attr_t's exist within xar_prop_t's + * and xar_file_t's. + * Basically, a xar_file_t is a container for xar_prop_t's. + * xar_attr_t's are things like: blah + * In this example, foo is the key of a xar_prop_t, and blah is + * the value. bar is the key of a xar_attr_t which is part of + * foo's xar_prop_t, and 5 is bar's value. + * xar_file_t's have xar_attr_t's for the case of: + * + * The file has an attribute of "id" with a value of "42". + */ + +struct __xar_iter_t { + const void *iter; + char *path; + void *node; + int nochild; +}; + + + +/* Convenience macros for dereferencing the structs */ +#define XAR_ATTR(x) ((struct __xar_attr_t *)(x)) +#define XAR_FILE(x) ((struct __xar_file_t *)(x)) +#define XAR_PROP(x) ((struct __xar_prop_t *)(x)) +#define XAR_ITER(x) ((struct __xar_iter_t *)(x)) + + +void xar_file_free(xar_file_t f); +xar_attr_t xar_attr_new(void); +int32_t xar_attr_set(xar_file_t f, const char *prop, const char *key, const char *value); +int32_t xar_attr_pset(xar_file_t f, xar_prop_t p, const char *key, const char *value); +const char *xar_attr_get(xar_file_t f, const char *prop, const char *key); +const char *xar_attr_pget(xar_file_t f, xar_prop_t p, const char *key); +void xar_attr_free(xar_attr_t a); +void xar_file_serialize(xar_file_t f, xmlTextWriterPtr writer); +xar_file_t xar_file_unserialize(xar_t x, xar_file_t parent, xmlTextReaderPtr reader); +xar_file_t xar_file_find(xar_file_t f, const char *path); +xar_file_t xar_file_new(xar_file_t f); +xar_file_t xar_file_replicate(xar_file_t original, xar_file_t newparent); +void xar_file_free(xar_file_t f); + +void xar_prop_serialize(xar_prop_t p, xmlTextWriterPtr writer); +int32_t xar_prop_unserialize(xar_file_t f, xar_prop_t parent, xmlTextReaderPtr reader); +void xar_prop_free(xar_prop_t p); +xar_prop_t xar_prop_new(xar_file_t f, xar_prop_t parent); +xar_prop_t xar_prop_pset(xar_file_t f, xar_prop_t p, const char *key, const char *value); +xar_prop_t xar_prop_find(xar_prop_t p, const char *key); +xar_prop_t xar_prop_pget(xar_prop_t p, const char *key); +const char *xar_prop_getkey(xar_prop_t p); +const char *xar_prop_getvalue(xar_prop_t p); +int32_t xar_prop_setkey(xar_prop_t p, const char *key); +int32_t xar_prop_setvalue(xar_prop_t p, const char *value); +xar_prop_t xar_prop_pfirst(xar_file_t f); +xar_prop_t xar_prop_pnext(xar_prop_t p); +void xar_prop_punset(xar_file_t f, xar_prop_t p); + +#endif /* _XAR_FILETREE_H_ */ diff --git a/xar/lib/hash.c b/xar/lib/hash.c new file mode 100644 index 0000000..f3c9ca6 --- /dev/null +++ b/xar/lib/hash.c @@ -0,0 +1,407 @@ +/* + * Copyright (c) 2005-2007 Rob Braun + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Rob Braun nor the names of his contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +/* + * 03-Apr-2005 + * DRI: Rob Braun + */ +/* + * Portions Copyright 2006, Apple Computer, Inc. + * Christopher Ryan +*/ + + +#include +#include +#include +#include +#include +#ifdef __APPLE__ +#include +#include +#else +#include +#endif + +#include "xar.h" +#include "hash.h" +#include "config.h" +#ifndef HAVE_ASPRINTF +#include "asprintf.h" +#endif + + +#pragma mark Hash Wrapper Object + +#ifdef __APPLE__ + +CCDigestRef digestRef_from_name(const char* name, unsigned int *outHashSize) { + CCDigestRef result = NULL; + + if (NULL != outHashSize) + *outHashSize = 0; + + if (0 == strcasecmp(name, "sha512")) { + result = CCDigestCreate(kCCDigestSHA512); + if (NULL != outHashSize) + *outHashSize = CC_SHA512_DIGEST_LENGTH; + } else if (0 == strcasecmp(name, "sha256")) { + result = CCDigestCreate(kCCDigestSHA256); + if (NULL != outHashSize) + *outHashSize = CC_SHA256_DIGEST_LENGTH; + } else if (0 == strcasecmp(name, "sha") || !strcasecmp(name, "sha1")) { + result = CCDigestCreate(kCCDigestSHA1); + if (NULL != outHashSize) + *outHashSize = CC_SHA1_DIGEST_LENGTH; +#ifdef XAR_SUPPORT_MD5 + } else if (0 == strcasecmp(name, "md5")) { + result = CCDigestCreate(kCCDigestMD5); + if (NULL != outHashSize) + *outHashSize = CC_MD5_DIGEST_LENGTH; +#endif // XAR_SUPPORT_MD5 + } + + return result; +} +#endif // __APPLE__ + + +struct __xar_hash_t { + const char *digest_name; + void *context; +#ifdef __APPLE__ + CCDigestRef digest; +#else + EVP_MD_CTX digest; + const EVP_MD *type; +#endif + unsigned int length; +}; + +#define HASH_CTX(x) ((struct __xar_hash_t *)(x)) + +xar_hash_t xar_hash_new(const char *digest_name, void *context) { + struct __xar_hash_t *hash = calloc(1, sizeof(struct __xar_hash_t)); + if( ! hash ) + return NULL; // errno will already be set + + if( context ) + HASH_CTX(hash)->context = context; + +#ifdef __APPLE__ + HASH_CTX(hash)->digest = digestRef_from_name(digest_name, &HASH_CTX(hash)->length); +#else + OpenSSL_add_all_digests(); + HASH_CTX(hash)->type = EVP_get_digestbyname(digest_name); + EVP_DigestInit(&HASH_CTX(hash)->digest, HASH_CTX(hash)->type); +#endif + + HASH_CTX(hash)->digest_name = strdup(digest_name); + + return hash; +} + +void *xar_hash_get_context(xar_hash_t hash) { + return HASH_CTX(hash)->context; +} + +const char *xar_hash_get_digest_name(xar_hash_t hash) { + return HASH_CTX(hash)->digest_name; +} + +void xar_hash_update(xar_hash_t hash, void *buffer, size_t nbyte) { +#ifdef __APPLE__ + CCDigestUpdate(HASH_CTX(hash)->digest, buffer, nbyte); +#else + EVP_DigestUpdate(&HASH_CTX(hash)->digest, buffer, nbyte); +#endif +} + +void *xar_hash_finish(xar_hash_t hash, size_t *nbyte) { +#ifdef __APPLE__ + void *buffer = calloc(1, CC_SHA512_DIGEST_LENGTH); // current biggest digest size This is what OpenSSL uses +#else + void *buffer = calloc(1, EVP_MAX_MD_SIZE); +#endif + if( ! buffer ) + return NULL; + +#ifdef __APPLE__ + CCDigestFinal(HASH_CTX(hash)->digest, buffer); + CCDigestDestroy(HASH_CTX(hash)->digest); +#else + EVP_DigestFinal(&HASH_CTX(hash)->digest, buffer, &HASH_CTX(hash)->length); +#endif + + *nbyte = HASH_CTX(hash)->length; + free((void *)HASH_CTX(hash)->digest_name); + free((void *)hash); + return buffer; +} + +#undef HASH_CTX + + +#pragma mark datamod + +struct _hash_context { + xar_hash_t archived; + xar_hash_t unarchived; + uint64_t count; +}; + +#define CONTEXT(x) ((struct _hash_context *)(*x)) + +static char *_xar_format_hash(const unsigned char* m,unsigned int len) { + char *result = malloc((2*len)+1); + char hexValue[3]; + unsigned int itr = 0; + + result[0] = '\0'; + + for(itr = 0;itr < len;itr++) { + sprintf(hexValue,"%02x",m[itr]); + strncat(result,hexValue,2); + } + + return result; +} + +int32_t xar_hash_toheap_in(xar_t x, xar_file_t f, xar_prop_t p, void **in, size_t *inlen, void **context) { + return xar_hash_fromheap_out(x,f,p,*in,*inlen,context); +} + +int32_t xar_hash_fromheap_out(xar_t x, xar_file_t f, xar_prop_t p, void *in, size_t inlen, void **context) { + + if (!context) + return 0; + + if(!CONTEXT(context) || (! CONTEXT(context)->unarchived) ) { + const char *opt; + xar_prop_t tmpp; + + opt = NULL; + tmpp = xar_prop_pget(p, "extracted-checksum"); + if( tmpp ) { + opt = xar_attr_pget(f, tmpp, "style"); + } else { + // The xar-1.7 release in OS X Yosemite accidentally wrote + // instead of . Since archives like this are now in the wild, + // we check for both. + tmpp = xar_prop_pget(p, "unarchived-checksum"); + if( tmpp ) { + opt = xar_attr_pget(f, tmpp, "style"); + } + } + + // If there's an and no (or + // ), the archive is malformed. + if ( !opt && xar_prop_pget(p, "archived-checksum") ) { + xar_err_new(x); + xar_err_set_string(x, "No extracted-checksum"); + xar_err_callback(x, XAR_SEVERITY_FATAL, XAR_ERR_ARCHIVE_EXTRACTION); + return -1; + } + + if( !opt ) + opt = xar_opt_get(x, XAR_OPT_FILECKSUM); + + if( !opt || (0 == strcmp(opt, XAR_OPT_VAL_NONE) ) ) + return 0; + + + if (!CONTEXT(context)) { + *context = calloc(1, sizeof(struct _hash_context)); + if( ! *context ) + return -1; + } + + if( ! CONTEXT(context)->unarchived ) { + CONTEXT(context)->unarchived = xar_hash_new(opt, NULL); + if( ! CONTEXT(context)->unarchived ) { + free(*context); + *context = NULL; + return -1; + + } + } + } + + if( inlen == 0 ) + return 0; + + CONTEXT(context)->count += inlen; + xar_hash_update(CONTEXT(context)->unarchived, in, inlen); + + return 0; +} + +int32_t xar_hash_fromheap_in(xar_t x, xar_file_t f, xar_prop_t p, void **in, size_t *inlen, void **context) { + return xar_hash_toheap_out(x,f,p,*in,*inlen,context); +} + +int32_t xar_hash_toheap_out(xar_t x, xar_file_t f, xar_prop_t p, void *in, size_t inlen, void **context) { + const char *opt; + xar_prop_t tmpp; + + opt = NULL; + tmpp = xar_prop_pget(p, "archived-checksum"); + if( tmpp ) + opt = xar_attr_pget(f, tmpp, "style"); + + if( !opt ) + opt = xar_opt_get(x, XAR_OPT_FILECKSUM); + + if( !opt || (0 == strcmp(opt, XAR_OPT_VAL_NONE) ) ) + return 0; + + if( ! CONTEXT(context) ) { + *context = calloc(1, sizeof(struct _hash_context)); + if( ! *context ) + return -1; + } + + if( ! CONTEXT(context)->archived ) { + CONTEXT(context)->archived = xar_hash_new(opt, NULL); + if( ! CONTEXT(context)->archived ) { + free(*context); + *context = NULL; + return -1; + } + } + + if( inlen == 0 ) + return 0; + + CONTEXT(context)->count += inlen; + xar_hash_update(CONTEXT(context)->archived, in, inlen); + return 0; +} + +int32_t xar_hash_toheap_done(xar_t x, xar_file_t f, xar_prop_t p, void **context) { + const char *archived_style = NULL, *unarchived_style = NULL; + size_t archived_length = -1, unarchived_length = -1; + void *archived_hash = NULL, *unarchived_hash = NULL; + + if( ! CONTEXT(context) ) + return 0; + else if( CONTEXT(context)->count == 0 ) + goto DONE; + + archived_style = strdup(xar_hash_get_digest_name(CONTEXT(context)->archived)); + unarchived_style = strdup(xar_hash_get_digest_name(CONTEXT(context)->unarchived)); + + archived_hash = xar_hash_finish(CONTEXT(context)->archived, &archived_length); + unarchived_hash = xar_hash_finish(CONTEXT(context)->unarchived, &unarchived_length); + + char *str; + xar_prop_t tmpp; + + str = _xar_format_hash(archived_hash, archived_length); + if( f ) { + tmpp = xar_prop_pset(f, p, "archived-checksum", str); + if( tmpp ) + xar_attr_pset(f, tmpp, "style", archived_style); + } + free(str); + + str = _xar_format_hash(unarchived_hash, unarchived_length); + if( f ) { + tmpp = xar_prop_pset(f, p, "extracted-checksum", str); + if( tmpp ) + xar_attr_pset(f, tmpp, "style", unarchived_style); + } + free(str); + +DONE: + free((void *)archived_style); + free((void *)unarchived_style); + + free(archived_hash); + free(unarchived_hash); + + free(*context); + *context = NULL; + + return 0; +} + +int32_t xar_hash_fromheap_done(xar_t x, xar_file_t f, xar_prop_t p, void **context) { + if(!CONTEXT(context)) + return 0; + + int32_t result = 0; + const char *archived_hash = NULL, *archived_style = NULL; + + // Fetch the existing hash from the archive + if( CONTEXT(context)->archived ) { + xar_prop_t tmpp = xar_prop_pget(p, "archived-checksum"); + if( tmpp ) { + archived_style = xar_attr_pget(f, tmpp, "style"); + archived_hash = xar_prop_getvalue(tmpp); + } + + // We have the fetched hash; now get the calculated hash + if( archived_hash && archived_style ) { + size_t calculated_length = -1; + const char *calculated_style = strdup(xar_hash_get_digest_name(CONTEXT(context)->archived)); + void *calculated_buffer = xar_hash_finish(CONTEXT(context)->archived, &calculated_length); + char *calculated_hash = _xar_format_hash(calculated_buffer, calculated_length); + free(calculated_buffer); + + // Compare + int hash_match = ( strcmp(archived_hash, calculated_hash) == 0 ); + int style_match = (strcmp(archived_style, calculated_style) == 0 ); + + if( ! hash_match || ! style_match ) { + xar_err_new(x); + xar_err_set_file(x, f); + xar_err_set_formatted_string(x, "archived-checksum %s's do not match", archived_style); + xar_err_callback(x, XAR_SEVERITY_FATAL, XAR_ERR_ARCHIVE_EXTRACTION); + result = -1; + } + + free((void *)calculated_style); + free(calculated_hash); + } + } + + // Clean up the unarchived hash as well, if we have one + if( CONTEXT(context)->unarchived ) { + size_t length = -1; + void *hash = xar_hash_finish(CONTEXT(context)->unarchived, &length); + free(hash); + } + + if(*context) { + free(*context); + *context = NULL; + } + + return result; +} diff --git a/xar/lib/hash.h b/xar/lib/hash.h new file mode 100644 index 0000000..dd44709 --- /dev/null +++ b/xar/lib/hash.h @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2005-2007 Rob Braun + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Rob Braun nor the names of his contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +/* + * 03-Apr-2005 + * DRI: Rob Braun + */ +/* + * Portions Copyright 2006, Apple Computer, Inc. + * Christopher Ryan +*/ + +#ifndef _XAR_HASH_H_ +#define _XAR_HASH_H_ + +#include "filetree.h" + +#pragma mark Hash Wrapper Object + +typedef struct __xar_hash_t *xar_hash_t; + +xar_hash_t xar_hash_new(const char *digest_name, void *context); +void *xar_hash_get_context(xar_hash_t hash); +const char *xar_hash_get_digest_name(xar_hash_t hash); // returns inner pointer +void xar_hash_update(xar_hash_t hash, void *buffer, size_t nbyte); +void *xar_hash_finish(xar_hash_t hash, size_t *nbyte); + +#pragma mark datamod + +int32_t xar_hash_fromheap_in(xar_t x, xar_file_t f, xar_prop_t p, void **in, size_t *inlen, void **context); +int32_t xar_hash_fromheap_out(xar_t x, xar_file_t f, xar_prop_t p, void *in, size_t inlen, void **context); +int32_t xar_hash_fromheap_done(xar_t x, xar_file_t f, xar_prop_t p, void **context); + +int32_t xar_hash_toheap_in(xar_t x, xar_file_t f, xar_prop_t p, void **in, size_t *inlen, void **context); +int32_t xar_hash_toheap_out(xar_t x, xar_file_t f, xar_prop_t p, void *in, size_t inlen, void **context); +int32_t xar_hash_toheap_done(xar_t x, xar_file_t f, xar_prop_t p, void **context); + +#endif /* _XAR_HASH_H_ */ diff --git a/xar/lib/io.c b/xar/lib/io.c new file mode 100644 index 0000000..fcee90c --- /dev/null +++ b/xar/lib/io.c @@ -0,0 +1,871 @@ +/* + * Copyright (c) 2005-2008 Rob Braun + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Rob Braun nor the names of his contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +/* + * 03-Apr-2005 + * DRI: Rob Braun + */ +/* + * Portions Copyright 2006, Apple Computer, Inc. + * Christopher Ryan +*/ + +#define _FILE_OFFSET_BITS 64 + +#include "config.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifndef HAVE_ASPRINTF +#include "asprintf.h" +#endif +#include "xar.h" +#include "filetree.h" +#include "archive.h" +#include "io.h" +#include "zxar.h" +#include "bzxar.h" +#include "lzmaxar.h" +#include "hash.h" +#include "script.h" +#include "macho.h" +#include "util.h" +#include "data.h" + +#if !defined(LLONG_MAX) && defined(LONG_LONG_MAX) +#define LLONG_MAX LONG_LONG_MAX +#endif + +#if !defined(LLONG_MIN) && defined(LONG_LONG_MIN) +#define LLONG_MIN LONG_LONG_MIN +#endif + +// IMPORTANT: Keep datamod count up to date in io.h! +struct datamod xar_datamods[] = { + { xar_hash_fromheap_in, + xar_hash_fromheap_out, + xar_hash_fromheap_done, + xar_hash_toheap_in, + xar_hash_toheap_out, + xar_hash_toheap_done + }, + { (fromheap_in)NULL, + (fromheap_out)NULL, + (fromheap_done)NULL, + xar_script_in, + (toheap_out)NULL, + xar_script_done + }, + { (fromheap_in)NULL, + (fromheap_out)NULL, + (fromheap_done)NULL, + NULL, + (toheap_out)NULL, + NULL + }, + { xar_gzip_fromheap_in, + (fromheap_out)NULL, + xar_gzip_fromheap_done, + xar_gzip_toheap_in, + (toheap_out)NULL, + xar_gzip_toheap_done + }, + { xar_bzip_fromheap_in, + (fromheap_out)NULL, + xar_bzip_fromheap_done, + xar_bzip_toheap_in, + (toheap_out)NULL, + xar_bzip_toheap_done + }, + { xar_lzma_fromheap_in, + (fromheap_out)NULL, + xar_lzma_fromheap_done, + xar_lzma_toheap_in, + (toheap_out)NULL, + xar_lzma_toheap_done + } +}; + +size_t xar_io_get_rsize(xar_t x) { + size_t bsize; + const char *opt = NULL; + + opt = xar_opt_get(x, "rsize"); + if( !opt ) { + bsize = 4096; + } else { + bsize = strtol(opt, NULL, 0); + if( ((bsize == LONG_MAX) || (bsize == LONG_MIN)) && (errno == ERANGE) ) { + bsize = 4096; + } + } + + return bsize; +} + +off_t xar_io_get_heap_base_offset(xar_t x) { + return XAR(x)->toc_count + sizeof(xar_header_t); +} + +size_t xar_io_get_toc_checksum_length_for_type(const char *type) { + if( !type ) { + return 0; + } else if( strcmp(type, XAR_OPT_VAL_NONE) == 0 ) { + return 0; + } else if( strcmp(type, XAR_OPT_VAL_SHA1) == 0 ) { + return 20; + } else if( strcmp(type, XAR_OPT_VAL_SHA256) == 0 ) { + return 32; + } else if( strcmp(type, XAR_OPT_VAL_SHA512) == 0 ) { + return 64; + } else if( strcmp(type, XAR_OPT_VAL_MD5) == 0 ) { + // Left in place regardless of XAR_SUPPORT_MD5 for proper archive parsing + return 16; + } else { + return 0; + } +} + +size_t xar_io_get_toc_checksum_length(xar_t x) { + switch(XAR(x)->header.cksum_alg) { + case XAR_CKSUM_NONE: + // Left in place even though it is no longer supported for archive parsing + return 0; + case XAR_CKSUM_SHA1: + return 20; + case XAR_CKSUM_SHA256: + return 32; + case XAR_CKSUM_SHA512: + return 64; + case XAR_CKSUM_MD5: + // Left in place regardless of XAR_SUPPORT_MD5 for proper archive parsing + return 16; + default: + fprintf(stderr, "Unknown hashing algorithm, skipping\n"); + return 0; + }; +} + +off_t xar_io_get_file_offset(xar_t x, xar_file_t f, xar_prop_t p) { + xar_prop_t tmpp; + const char *opt = NULL; + tmpp = xar_prop_pget(p, "offset"); + if( tmpp ) { + opt = xar_prop_getvalue(tmpp); + if (opt == NULL){ + return -1; + } + return strtoll(opt, NULL, 0); + } else { + return -1; + } +} + +int64_t xar_io_get_length(xar_prop_t p) { + const char *opt = NULL; + int64_t fsize = 0; + xar_prop_t tmpp; + + tmpp = xar_prop_pget(p, "length"); + if( tmpp ) + opt = xar_prop_getvalue(tmpp); + if( !opt ) { + return 0; + } else { + fsize = strtoll(opt, NULL, 10); + if( ((fsize == LLONG_MAX) || (fsize == LLONG_MIN)) && (errno == ERANGE) ) { + return -1; + } + } + + return fsize; +} + +static void xar_io_seek(xar_t x, xar_file_t f, off_t seekoff) { + int r; + + if( XAR(x)->fd >= 0 ) { + r = lseek(XAR(x)->fd, seekoff, SEEK_SET); + if( r == -1 ) { + if( errno == ESPIPE ) { + ssize_t rr; + char *buf; + unsigned int len; + + len = seekoff - XAR(x)->toc_count; + len -= sizeof(xar_header_t); + if( XAR(x)->heap_offset > len ) { + xar_err_new(x); + xar_err_set_file(x, f); + xar_err_set_string(x, "Unable to seek"); + xar_err_callback(x, XAR_SEVERITY_NONFATAL, XAR_ERR_ARCHIVE_EXTRACTION); + } else { + len -= XAR(x)->heap_offset; + buf = malloc(len); + assert(buf); + rr = xar_read_fd(XAR(x)->fd, buf, len); + if( rr < len ) { + xar_err_new(x); + xar_err_set_file(x, f); + xar_err_set_string(x, "Unable to seek"); + xar_err_callback(x, XAR_SEVERITY_NONFATAL, XAR_ERR_ARCHIVE_EXTRACTION); + } + XAR(x)->heap_offset += rr; + free(buf); + } + } else { + xar_err_new(x); + xar_err_set_file(x, f); + xar_err_set_string(x, "Unable to seek"); + xar_err_callback(x, XAR_SEVERITY_NONFATAL, XAR_ERR_ARCHIVE_EXTRACTION); + } + } + } +} + +int32_t xar_attrcopy_to_heap(xar_t x, xar_file_t f, xar_prop_t p, read_callback rcb, void *context) { + int modulecount = (sizeof(xar_datamods)/sizeof(struct datamod)); + void *modulecontext[modulecount]; + int r, i; + size_t bsize, rsize; + int64_t readsize=0, writesize=0, inc = 0, this_write=0; + void *inbuf; + char *tmpstr = NULL; + const char *opt = NULL, *csum = NULL; + off_t orig_heap_offset = XAR(x)->heap_offset; + xar_file_t tmpf = NULL; + xar_prop_t tmpp = NULL; + + memset(modulecontext, 0, sizeof(void*)*modulecount); + + bsize = xar_io_get_rsize(x); + + r = 1; + + // (Apple) allocate once + inbuf = malloc(bsize); + if( !inbuf ) + return -1; + + while(r != 0) { + + r = rcb(x, f, inbuf, bsize, context); + if( r < 0 ) { + free(inbuf); + return -1; + } + + readsize+=r; + inc += r; + rsize = r; + + /* filter the data through the in modules */ + for( i = 0; i < modulecount; i++) { + if( xar_datamods[i].th_in ) { + xar_datamods[i].th_in(x, f, p, &inbuf, &rsize, &(modulecontext[i])); + } + } + + /* filter the data through the out modules */ + for( i = 0; i < modulecount; i++) { + if( xar_datamods[i].th_out ) + xar_datamods[i].th_out(x, f, p, inbuf, rsize, &(modulecontext[i])); + } + + size_t written = 0; + if( rsize != 0 ) { + while(written < rsize) { + this_write = xar_write_fd(XAR(x)->heap_fd, inbuf, rsize); + if( this_write < 0 ) { + xar_err_new(x); + xar_err_set_string(x, "write(2) error when writing to heap"); + xar_err_set_errno(x, errno); + xar_err_callback(x, XAR_SEVERITY_FATAL, XAR_ERR_ARCHIVE_CREATION); + free(inbuf); + return -1; + } + written += this_write; + } + } + XAR(x)->heap_offset += written; + writesize += written; + } + + free(inbuf); + + + /* If size is 0, don't bother having anything in the heap */ + if( readsize == 0 ) { + XAR(x)->heap_offset = orig_heap_offset; + lseek(XAR(x)->heap_fd, -writesize, SEEK_CUR); + for( i = 0; i < modulecount; i++) { + if( xar_datamods[i].th_done ) + xar_datamods[i].th_done(x, f, p, &(modulecontext[i])); + } + return 0; + } + /* finish up anything that still needs doing */ + for( i = 0; i < modulecount; i++) { + if( xar_datamods[i].th_done ) + xar_datamods[i].th_done(x, f, p, &(modulecontext[i])); + } + + XAR(x)->heap_len += writesize; + tmpp = xar_prop_pget(p, "archived-checksum"); + if( tmpp ) + csum = xar_prop_getvalue(tmpp); + if( csum ) + tmpf = xmlHashLookup(XAR(x)->csum_hash, BAD_CAST(csum)); + if( tmpf ) { + const char *attr = xar_prop_getkey(p); + opt = xar_opt_get(x, XAR_OPT_LINKSAME); + if( opt && (strcmp(attr, "data") == 0) ) { + const char *id = xar_attr_pget(tmpf, NULL, "id"); + xar_prop_pset(f, NULL, "type", "hardlink"); + tmpp = xar_prop_pfirst(f); + if( tmpp ) + tmpp = xar_prop_find(tmpp, "type"); + if( tmpp ) + xar_attr_pset(f, tmpp, "link", id); + + xar_prop_pset(tmpf, NULL, "type", "hardlink"); + tmpp = xar_prop_pfirst(tmpf); + if( tmpp ) + tmpp = xar_prop_find(tmpp, "type"); + if( tmpp ) + xar_attr_pset(tmpf, tmpp, "link", "original"); + + tmpp = xar_prop_pfirst(f); + if( tmpp ) + tmpp = xar_prop_find(tmpp, "data"); + xar_prop_punset(f, tmpp); + + XAR(x)->heap_offset = orig_heap_offset; + lseek(XAR(x)->heap_fd, -writesize, SEEK_CUR); + XAR(x)->heap_len -= writesize; + return 0; + } + opt = xar_opt_get(x, XAR_OPT_COALESCE); + if( opt ) { + long long tmpoff; + const char *offstr = NULL; + tmpp = xar_prop_pfirst(tmpf); + if( tmpp ) { + const char *key; + key = xar_prop_getkey(p); + tmpp = xar_prop_find(tmpp, key); + } + if( tmpp ) + tmpp = xar_prop_pget(tmpp, "offset"); + if( tmpp ) + offstr = xar_prop_getvalue(tmpp); + if( offstr ) { + tmpoff = strtoll(offstr, NULL, 10); + XAR(x)->heap_offset = orig_heap_offset; + lseek(XAR(x)->heap_fd, -writesize, SEEK_CUR); + orig_heap_offset = tmpoff; + XAR(x)->heap_len -= writesize; + } + + } + } else if( csum ) { + xmlHashAddEntry(XAR(x)->csum_hash, BAD_CAST(csum), XAR_FILE(f)); + } else { + xar_err_new(x); + xar_err_set_file(x, f); + xar_err_set_string(x, "No archived-checksum"); + xar_err_callback(x, XAR_SEVERITY_WARNING, XAR_ERR_ARCHIVE_CREATION); + } + + asprintf(&tmpstr, "%"PRIu64, readsize); + xar_prop_pset(f, p, "size", tmpstr); + free(tmpstr); + + asprintf(&tmpstr, "%"PRIu64, (uint64_t)orig_heap_offset); + xar_prop_pset(f, p, "offset", tmpstr); + free(tmpstr); + + tmpstr = (char *)xar_opt_get(x, XAR_OPT_COMPRESSION); + if( tmpstr && (strcmp(tmpstr, XAR_OPT_VAL_NONE) == 0) ) { + xar_prop_pset(f, p, "encoding", NULL); + tmpp = xar_prop_pget(p, "encoding"); + if( tmpp ) + xar_attr_pset(f, tmpp, "style", "application/octet-stream"); + } + + asprintf(&tmpstr, "%"PRIu64, writesize); + xar_prop_pset(f, p, "length", tmpstr); + free(tmpstr); + + return 0; +} + +/* xar_copy_from_heap + * This is the arcmod extraction entry point for extracting the file's + * data from the heap file. + * It is assumed the heap_fd is already positioned appropriately. + */ +int32_t xar_attrcopy_from_heap(xar_t x, xar_file_t f, xar_prop_t p, write_callback wcb, void *context) { + int modulecount = (sizeof(xar_datamods)/sizeof(struct datamod)); + void *modulecontext[modulecount]; + int r, i; + size_t bsize, def_bsize; + int64_t fsize, inc = 0, seekoff, readsofar = 0; + void *inbuf; + const char *opt; + xar_prop_t tmpp; + + memset(modulecontext, 0, sizeof(void*)*modulecount); + + def_bsize = xar_io_get_rsize(x); + + seekoff = xar_io_get_file_offset(x, f, p); + if( seekoff == -1 ) { + wcb(x, f, NULL, 0, context); + return 0; + } else if( ((seekoff == LLONG_MAX) || (seekoff == LLONG_MIN)) && (errno == ERANGE) ) { + return -1; + } + seekoff += xar_io_get_heap_base_offset(x); + xar_io_seek(x, f, seekoff); + + fsize = xar_io_get_length(p); + if( fsize == 0 ) + return 0; + if( fsize < 0 ) + return -1; + + bsize = def_bsize; + inbuf = malloc(bsize); + if( !inbuf ) { + return -1; + } + + while(1) { + /* Size has been reached */ + if( fsize == inc ) + break; + if( (fsize - inc) < bsize ) + bsize = fsize - inc; + r = read(XAR(x)->fd, inbuf, bsize); + if( r == 0 ) + break; + if( (r < 0) && (errno == EINTR) ) + continue; + if( r < 0 ) { + free(inbuf); + return -1; + } + + XAR(x)->heap_offset += r; + inc += r; + bsize = r; + + /* filter the data through the in modules */ + for( i = 0; i < modulecount; i++) { + if( xar_datamods[i].fh_in ) { + int32_t ret; + ret = xar_datamods[i].fh_in(x, f, p, &inbuf, &bsize, &(modulecontext[i])); + if( ret < 0 ) { + free(inbuf); // (Apple) don't leak inbuf + return -1; + } + } + } + + /* Only due the write phase, if there is a write function to call */ + if(wcb){ + + /* filter the data through the out modules */ + for( i = 0; i < modulecount; i++) { + if( xar_datamods[i].fh_out ) { + int32_t ret; + ret = xar_datamods[i].fh_out(x, f, p, inbuf, bsize, &(modulecontext[i])); + if( ret < 0 ) { + free(inbuf); // (Apple) don't leak inbuf + return -1; + } + } + } + + wcb(x, f, inbuf, bsize, context); + } + + readsofar += bsize; + + if (DATA_CONTEXT(context)->progress) + DATA_CONTEXT(context)->progress(x, f, readsofar); + + bsize = def_bsize; + } + + free(inbuf); + /* finish up anything that still needs doing */ + for( i = 0; i < modulecount; i++) { + if( xar_datamods[i].fh_done ) { + int32_t ret; + ret = xar_datamods[i].fh_done(x, f, p, &(modulecontext[i])); + if( ret < 0 ) + return ret; + } + } + return 0; +} + +/* xar_attrcopy_from_heap_to_heap +* This does a simple copy of the heap data from one head (read-only) to another heap (write only). +* This does not set any properties or attributes of the file, so this should not be used alone. +*/ +int32_t xar_attrcopy_from_heap_to_heap(xar_t xsource, xar_file_t fsource, xar_prop_t p, xar_t xdest, xar_file_t fdest){ + int r, off; + size_t bsize; + int64_t fsize, inc = 0, seekoff, writesize=0; + off_t orig_heap_offset = XAR(xdest)->heap_offset; + void *inbuf; + const char *opt; + char *tmpstr = NULL; + xar_prop_t tmpp; + + bsize = xar_io_get_rsize(xsource); + + seekoff = xar_io_get_file_offset(xsource, fsource, p); + if( seekoff < 0 ) + return -1; + + seekoff += XAR(xsource)->toc_count + sizeof(xar_header_t); + xar_io_seek(xsource, fsource, seekoff); + + fsize = xar_io_get_length(p); + if( fsize == 0 ) + return 0; + if( fsize < 0 ) + return -1; + + inbuf = malloc(bsize); + if( !inbuf ) { + return -1; + } + + + while(1) { + /* Size has been reached */ + if( fsize == inc ) + break; + if( (fsize - inc) < bsize ) + bsize = fsize - inc; + r = read(XAR(xsource)->fd, inbuf, bsize); + if( r == 0 ) + break; + if( (r < 0) && (errno == EINTR) ) + continue; + if( r < 0 ) { + free(inbuf); + return -1; + } + + XAR(xsource)->heap_offset += r; + inc += r; + bsize = r; + + off = 0; + + do { + r = write(XAR(xdest)->heap_fd, ((char *)inbuf)+off, r-off ); + off += r; + writesize += r; + } while( off < r ); + XAR(xdest)->heap_offset += off; + XAR(xdest)->heap_len += off; + } + + asprintf(&tmpstr, "%"PRIu64, (uint64_t)orig_heap_offset); + opt = xar_prop_getkey(p); + tmpp = xar_prop_pfirst(fdest); + if( tmpp ) + tmpp = xar_prop_find(tmpp, opt); + if( tmpp ) + xar_prop_pset(fdest, tmpp, "offset", tmpstr); + free(tmpstr); + + + free(inbuf); + + /* It is the caller's responsibility to copy the attributes of the file, etc, this only copies the data in the heap */ + + return 0; +} + +static int32_t flush_stream(xar_stream *stream) { + xar_stream_state_t *state = (xar_stream_state_t *)(stream->state); + + if( state->pending_buf && stream->avail_out ) { + size_t len = state->pending_buf_size; + + if( stream->avail_out < len ) { + len = stream->avail_out; + } + + memcpy(stream->next_out, state->pending_buf, len); + stream->next_out += len; + stream->avail_out -= len; + stream->total_out += len; + + if( state->pending_buf_size == len ) { + state->pending_buf_size = 0; + + free(state->pending_buf); + state->pending_buf = NULL; + } else if( state->pending_buf_size > len ) { + state->pending_buf_size -= len; + memcpy(state->pending_buf, state->pending_buf + len, state->pending_buf_size); + } + } + + return XAR_STREAM_OK; +} + +static int32_t write_to_stream(void *inbuf, size_t inlen, xar_stream *stream) { + xar_stream_state_t *state = (xar_stream_state_t *)stream->state; + size_t len = inlen; + + if( stream->avail_out < len ) { + len = stream->avail_out; + } + + memcpy(stream->next_out, inbuf, len); + stream->next_out += len; + stream->avail_out -= len; + stream->total_out += len; + + if( inlen > len ) { + state->pending_buf_size = inlen - len; + state->pending_buf = malloc(state->pending_buf_size); + + memcpy(state->pending_buf, ((char *)inbuf) + len, state->pending_buf_size); + } + + return XAR_STREAM_OK; +} + +int32_t xar_attrcopy_from_heap_to_stream_init(xar_t x, xar_file_t f, xar_prop_t p, xar_stream *stream) { + xar_stream_state_t *state; + off_t seekoff; + + seekoff = xar_io_get_file_offset(x, f, p); + if( seekoff < 0 ) + return XAR_STREAM_ERR; + + state = calloc(1, sizeof(xar_stream_state_t)); + if( !state ) { + return XAR_STREAM_ERR; + } + stream->state = (void*)state; + state->bsize = xar_io_get_rsize(x); + + state->modulecount = (sizeof(xar_datamods)/sizeof(struct datamod)); + state->modulecontext = calloc(1, sizeof(void*)*state->modulecount); + if( !state->modulecontext ) { + free(state); + return XAR_STREAM_ERR; + } + + seekoff += XAR(x)->toc_count + sizeof(xar_header_t); + xar_io_seek(x, f, seekoff); + + stream->total_in = 0; + stream->total_out = 0; + + state->fsize = xar_io_get_length(p); + + if(state->fsize == 0) { + return XAR_STREAM_OK; + } else if(state->fsize == -1) { + free(state->modulecontext); + free(state); + return XAR_STREAM_ERR; + } + + state->pending_buf = NULL; + state->pending_buf_size = 0; + state->x = x; + state->f = f; + state->p = p; + + return XAR_STREAM_OK; +} + +int32_t xar_attrcopy_from_heap_to_stream(xar_stream *stream) { + xar_stream_state_t *state = stream->state; + + int r, i; + size_t bsize; + void *inbuf; + + if( state->pending_buf_size ) { + return flush_stream(stream); + } + + bsize = state->bsize; + inbuf = malloc(bsize); + if( !inbuf ) { + return XAR_STREAM_ERR; + } + + /* Size has been reached */ + if( state->fsize == stream->total_in ) { + free(inbuf); + return XAR_STREAM_END; + } + if( (state->fsize - stream->total_in) < bsize ) + bsize = state->fsize - stream->total_in; + r = read(XAR(state->x)->fd, inbuf, bsize); + if( r == 0 ) { + free(inbuf); + return XAR_STREAM_END; + } + if( (r < 0) && (errno == EINTR) ) { + free(inbuf); + return XAR_STREAM_OK; + } + if( r < 0 ) { + free(inbuf); + return XAR_STREAM_ERR; + } + + XAR(state->x)->heap_offset += r; + stream->total_in += r; + bsize = r; + + /* filter the data through the in modules */ + for( i = 0; i < state->modulecount; i++) { + if( xar_datamods[i].fh_in ) { + int32_t ret; + ret = xar_datamods[i].fh_in(state->x, state->f, state->p, &inbuf, &bsize, &(state->modulecontext[i])); + if( ret < 0 ) + return XAR_STREAM_ERR; + } + } + + /* filter the data through the out modules */ + for( i = 0; i < state->modulecount; i++) { + if( xar_datamods[i].fh_out ) { + int32_t ret; + ret = xar_datamods[i].fh_out(state->x, state->f, state->p, inbuf, bsize, &(state->modulecontext[i])); + if( ret < 0 ) + return XAR_STREAM_ERR; + } + } + + write_to_stream(inbuf, bsize, stream); + + free(inbuf); + + return XAR_STREAM_OK; +} + +int32_t xar_attrcopy_from_heap_to_stream_end(xar_stream *stream) { + xar_stream_state_t *state = (xar_stream_state_t *)stream->state; + int i; + + /* finish up anything that still needs doing */ + for( i = 0; i < state->modulecount; i++) { + if( xar_datamods[i].fh_done ) { + int32_t ret; + ret = xar_datamods[i].fh_done(state->x, state->f, state->p, &(state->modulecontext[i])); + if( ret < 0 ) + return ret; + } + } + + if( state->pending_buf ) { + free(state->pending_buf); + } + + free(state->modulecontext); + free(state); + + return XAR_STREAM_OK; +} + +/* xar_heap_to_archive + * x: archive to operate on + * Returns 0 on success, -1 on error + * Summary: copies the heap into the archive. + */ +int32_t xar_heap_to_archive(xar_t x) { + long bsize; + ssize_t r; + int off; + const char *opt; + char *b; + + opt = xar_opt_get(x, "rsize"); + if( !opt ) { + bsize = 4096; + } else { + bsize = strtol(opt, NULL, 0); + if( ((bsize == LONG_MAX) || (bsize == LONG_MIN)) && (errno == ERANGE) ) { + bsize = 4096; + } + } + + b = calloc(1, bsize); + if( !b ) return -1; + + lseek(XAR(x)->heap_fd, 0, SEEK_SET); + while(1) { + r = read(XAR(x)->heap_fd, b, bsize); + if( r == 0 ) break; + if( (r < 0) && (errno == EINTR) ) continue; + if( r < 0 ) { + free(b); + return -1; + } + + size_t writesize = r; + off = 0; + do { + r = write(XAR(x)->fd, b+off, writesize-off); + if( (r < 0) && (errno != EINTR) ) { + free(b); + return -1; + } + off += r; + } while( off < bsize && off < writesize ); // writesize should always be less than bsize. + } + free(b); + return 0; +} diff --git a/xar/lib/io.h b/xar/lib/io.h new file mode 100644 index 0000000..206dbf1 --- /dev/null +++ b/xar/lib/io.h @@ -0,0 +1,96 @@ +/* + * Copyright (c) 2005-2007 Rob Braun + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Rob Braun nor the names of his contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +/* + * 03-Apr-2005 + * DRI: Rob Braun + */ +/* + * Portions Copyright 2006, Apple Computer, Inc. + * Christopher Ryan +*/ + +#ifndef _XAR_IO_H_ +#define _XAR_IO_H_ + +#include "archive.h" +//typedef int (*read_callback)(xar_t, xar_file_t, void *, size_t, void *context); +//typedef int (*write_callback)(xar_t, xar_file_t, void *, size_t, void *context); + +typedef int (*fromheap_in)(xar_t x, xar_file_t f, xar_prop_t p, void **in, size_t *inlen, void **context); +typedef int (*fromheap_out)(xar_t x, xar_file_t f, xar_prop_t p, void *in, size_t inlen, void **context); +typedef int (*fromheap_done)(xar_t x, xar_file_t f, xar_prop_t p, void **context); + +typedef int (*toheap_in)(xar_t x, xar_file_t f, xar_prop_t p, void **in, size_t *inlen, void **context); +typedef int (*toheap_out)(xar_t x, xar_file_t f, xar_prop_t p, void *in, size_t inlen, void **context); +typedef int (*toheap_done)(xar_t x, xar_file_t f, xar_prop_t p, void **context); + +struct datamod { + fromheap_in fh_in; + fromheap_out fh_out; + fromheap_done fh_done; + toheap_in th_in; + toheap_out th_out; + toheap_done th_done; +}; + +typedef struct xar_stream_state { + char *pending_buf; + size_t pending_buf_size; + + void **modulecontext; + int modulecount; + size_t bsize; + int64_t fsize; + xar_t x; + xar_file_t f; + xar_prop_t p; +} xar_stream_state_t; + +size_t xar_io_get_rsize(xar_t x); +off_t xar_io_get_heap_base_offset(xar_t x); +size_t xar_io_get_toc_checksum_length_for_type(const char *type); +size_t xar_io_get_toc_checksum_length(xar_t x); +off_t xar_io_get_file_offset(xar_t x, xar_file_t f, xar_prop_t p); +int64_t xar_io_get_length(xar_prop_t p); + +int32_t xar_attrcopy_to_heap(xar_t x, xar_file_t f, xar_prop_t p, read_callback rcb, void *context); +int32_t xar_attrcopy_from_heap(xar_t x, xar_file_t f, xar_prop_t p, write_callback wcb, void *context); +int32_t xar_attrcopy_from_heap_to_heap(xar_t xsource, xar_file_t fsource, xar_prop_t p, xar_t xdest, xar_file_t fdest); +int32_t xar_attrcopy_from_heap_to_stream_init(xar_t x, xar_file_t f, xar_prop_t p, xar_stream *stream); +int32_t xar_attrcopy_from_heap_to_stream(xar_stream *stream); +int32_t xar_attrcopy_from_heap_to_stream_end(xar_stream *stream); + +int32_t xar_heap_to_archive(xar_t x); + +#pragma mark internal + +// IMPORTANT: Keep count synchronized with declaration in io.c! +extern struct datamod xar_datamods[6]; + +#endif /* _XAR_IO_H_ */ diff --git a/xar/lib/libxar.la.in b/xar/lib/libxar.la.in new file mode 100644 index 0000000..928022b --- /dev/null +++ b/xar/lib/libxar.la.in @@ -0,0 +1,35 @@ +# libxar.la - a libtool library file +# Generated by Xar 1.8dev for libtool +# +# Please DO NOT delete this file! +# It is necessary for linking the library. + +# The name that we can dlopen(3). +dlname='@LIBXAR_SNAME@' + +# Names of this library. +library_names='@LIBXAR_SNAME@ @LIBXAR_LNAME@' + +# The name of the static archive. +old_library='@LIBXAR_ANAME@' + +# Libraries that this one depends upon. +dependency_libs='-lpthread -lbz2 -lz -lxml2 -lz -lpthread -licucore -lm' + +# Version information for libxar. +current=0 +age=0 +revision=1 + +# Is this an already installed library? +installed=no + +# Should we warn about portability when linking against -modules? +shouldnotlink=no + +# Files to dlopen/dlpreopen +dlopen='' +dlpreopen='' + +# Directory that this library needs to be installed in: +libdir='/usr/local/lib' diff --git a/xar/lib/libxar.la.in.in b/xar/lib/libxar.la.in.in new file mode 100644 index 0000000..62980e4 --- /dev/null +++ b/xar/lib/libxar.la.in.in @@ -0,0 +1,35 @@ +# libxar.la - a libtool library file +# Generated by @PACKAGE_STRING@ for libtool +# +# Please DO NOT delete this file! +# It is necessary for linking the library. + +# The name that we can dlopen(3). +dlname='@LIBXAR_SNAME@' + +# Names of this library. +library_names='@LIBXAR_SNAME@ @LIBXAR_LNAME@' + +# The name of the static archive. +old_library='@LIBXAR_ANAME@' + +# Libraries that this one depends upon. +dependency_libs='@LIBS@' + +# Version information for libxar. +current=0 +age=0 +revision=@LIB_REV@ + +# Is this an already installed library? +installed=no + +# Should we warn about portability when linking against -modules? +shouldnotlink=no + +# Files to dlopen/dlpreopen +dlopen='' +dlpreopen='' + +# Directory that this library needs to be installed in: +libdir='@LIBDIR@' diff --git a/xar/lib/linuxattr.c b/xar/lib/linuxattr.c new file mode 100644 index 0000000..0fec2bb --- /dev/null +++ b/xar/lib/linuxattr.c @@ -0,0 +1,275 @@ +/* + * Copyright (c) 2004 Rob Braun + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Rob Braun nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +/* + * 26-Oct-2004 + * DRI: Rob Braun + */ +/* + * Portions Copyright 2006, Apple Computer, Inc. + * Christopher Ryan +*/ + +#include "config.h" +#include +#include +#include +#include "xar.h" +#include "arcmod.h" +#include "b64.h" +#include +#include +#include "util.h" +#include "linuxattr.h" +#include "io.h" + +#ifdef HAVE_SYS_PARAM_H +#include +#endif + +#ifdef HAVE_SYS_STATFS_H /* Nonexistant future OS needs this */ +#include +#endif + +#ifdef HAVE_SYS_MOUNT_H +#include +#endif + +#ifdef HAVE_SYS_XATTR_H +#include +#endif + +#ifndef EXT3_SUPER_MAGIC +#define EXT3_SUPER_MAGIC 0xEF53 +#endif + +#ifndef JFS_SUPER_MAGIC +#define JFS_SUPER_MAGIC 0x3153464a +#endif + +#ifndef REISERFS_SUPER_MAGIC +#define REISERFS_SUPER_MAGIC 0x52654973 +#endif + +#ifndef XFS_SUPER_MAGIC +#define XFS_SUPER_MAGIC 0x58465342 +#endif + +#if defined(HAVE_SYS_XATTR_H) && defined(HAVE_LGETXATTR) && !defined(__APPLE__) + +struct _linuxattr_context{ + const char *file; + const char *attrname; + xar_ea_t ea; + void *buf; + int off; + int bufsz; +}; + +#define LINUXATTR_CONTEXT(x) ((struct _linuxattr_context *)(x)) + +int32_t xar_linuxattr_read(xar_t x, xar_file_t f, void * buf, size_t len, void *context) { + + if( !LINUXATTR_CONTEXT(context)->buf ) { + int r; + LINUXATTR_CONTEXT(context)->bufsz = 1024; +AGAIN2: + LINUXATTR_CONTEXT(context)->buf = malloc(LINUXATTR_CONTEXT(context)->bufsz); + if(!LINUXATTR_CONTEXT(context)->buf) + goto AGAIN2; + memset(LINUXATTR_CONTEXT(context)->buf, 0, LINUXATTR_CONTEXT(context)->bufsz); + r = lgetxattr(LINUXATTR_CONTEXT(context)->file, LINUXATTR_CONTEXT(context)->attrname, LINUXATTR_CONTEXT(context)->buf, LINUXATTR_CONTEXT(context)->bufsz); + if( r < 0 ) { + switch(errno) { + case ERANGE: LINUXATTR_CONTEXT(context)->bufsz *= 2; free(LINUXATTR_CONTEXT(context)->buf); goto AGAIN2; + case ENOTSUP: free(LINUXATTR_CONTEXT(context)->buf); return 0; + default: break; + }; + return -1; + } + LINUXATTR_CONTEXT(context)->bufsz = r; + } + + if( (LINUXATTR_CONTEXT(context)->bufsz-LINUXATTR_CONTEXT(context)->off) <= len ) { + int32_t ret; + ret = LINUXATTR_CONTEXT(context)->bufsz - LINUXATTR_CONTEXT(context)->off; + memcpy(buf, ((char *)LINUXATTR_CONTEXT(context)->buf)+LINUXATTR_CONTEXT(context)->off, ret); + LINUXATTR_CONTEXT(context)->off += ret; + return(ret); + } else { + memcpy(buf, ((char *)LINUXATTR_CONTEXT(context)->buf)+LINUXATTR_CONTEXT(context)->off, len); + LINUXATTR_CONTEXT(context)->buf = ((char *)LINUXATTR_CONTEXT(context)->buf) + len; + return len; + } +} + +int32_t xar_linuxattr_write(xar_t x, xar_file_t f, void *buf, size_t len, void *context) { + return lsetxattr(LINUXATTR_CONTEXT(context)->file, LINUXATTR_CONTEXT(context)->attrname, buf, len, 0); +} +#endif + +int32_t xar_linuxattr_archive(xar_t x, xar_file_t f, const char* file, const char *buffer, size_t len) +{ +#if defined(HAVE_SYS_XATTR_H) && defined(HAVE_LGETXATTR) && !defined(__APPLE__) + char *i, *buf = NULL; + int ret, retval=0, bufsz = 1024; + struct statfs sfs; + char *fsname = NULL; + struct _linuxattr_context context; + + memset(&context,0,sizeof(struct _linuxattr_context)); + + /* data from buffers don't have linuxattr */ + if(len) + return 0; + if( file == NULL ) + return 0; + + if( !xar_check_prop(x, "ea") ) + return 0; + +TRYAGAIN: + buf = malloc(bufsz); + if(!buf) + goto TRYAGAIN; + ret = llistxattr(file, buf, bufsz); + if( ret < 0 ) { + switch(errno) { + case ERANGE: bufsz = bufsz*2; free(buf); goto TRYAGAIN; + case ENOTSUP: retval = 0; goto BAIL; + default: retval = -1; goto BAIL; + }; + } + if( ret == 0 ) goto BAIL; + + memset(&sfs, 0, sizeof(sfs)); + statfs(file, &sfs); + + switch(sfs.f_type) { + case EXT3_SUPER_MAGIC: fsname = "ext3"; break; /* assume ext3 */ + case JFS_SUPER_MAGIC: fsname = "jfs" ; break; + case REISERFS_SUPER_MAGIC:fsname = "reiser" ; break; + case XFS_SUPER_MAGIC: fsname = "xfs" ; break; + default: retval=0; goto BAIL; + }; + + for( i=buf; (i-buf) < ret; i += strlen(i)+1 ) { + xar_ea_t e; + + context.bufsz = 0; + context.off = 0; + context.buf = NULL; + context.file = file; + e = xar_ea_new(f, i); + xar_ea_pset(f, e, "fstype", fsname); + context.attrname = i; + context.ea = e; + if (XAR(x)->attrcopy_to_heap(x, f, xar_ea_root(e), xar_linuxattr_read,&context) < 0) { + retval = -1; + goto BAIL; + } + free(context.buf); + context.attrname = NULL; + } + +BAIL: + free(buf); + return retval; +#endif + return 0; +} + +int32_t xar_linuxattr_extract(xar_t x, xar_file_t f, const char* file, char *buffer, size_t len) +{ +#if defined HAVE_SYS_XATTR_H && defined(HAVE_LSETXATTR) && !defined(__APPLE__) + const char *fsname = "bogus"; + struct statfs sfs; + int eaopt = 0; + struct _linuxattr_context context; + xar_prop_t p; + + memset(&context,0,sizeof(struct _linuxattr_context)); + + /* data buffers, can't store linux attrs */ + if(len){ + return 0; + } + + /* Check for EA extraction behavior */ + + memset(&sfs, 0, sizeof(sfs)); + if( statfs(file, &sfs) != 0 ) { + char *tmp, *bname; + tmp = strdup(file); + bname = safe_dirname(tmp); + statfs(bname, &sfs); + free(tmp); + free(bname); + } + switch(sfs.f_type) { + case EXT3_SUPER_MAGIC: fsname = "ext3"; break; /* assume ext3 */ + case JFS_SUPER_MAGIC: fsname = "jfs" ; break; + case REISERFS_SUPER_MAGIC:fsname = "reiser" ; break; + case XFS_SUPER_MAGIC: fsname = "xfs" ; break; + }; + + for(p = xar_prop_pfirst(f); p; p = xar_prop_pnext(p)) { + const char *fs = NULL; + const char *prop; + const char *eaname = NULL; + xar_prop_t tmpp; + prop = xar_prop_getkey(p); + + if( strncmp(prop, XAR_EA_FORK, strlen(XAR_EA_FORK)) != 0 ) + continue; + if( strlen(prop) != strlen(XAR_EA_FORK) ) + continue; + + tmpp = xar_prop_pget(p, "fstype"); + if( tmpp ) + fs = xar_prop_getvalue(tmpp); + if( !eaopt && fs && strcmp(fs, fsname) != 0 ) { + continue; + } + if( !fs ) + continue; + + tmpp = xar_prop_pget(p, "name"); + if( tmpp ) + eaname = xar_prop_getvalue(tmpp); + + context.file = file; + context.attrname = eaname; + if (XAR(x)->attrcopy_from_heap(x, f, p, xar_linuxattr_write, &context) < 0) + return -1; + + } + +#endif + return 0; +} diff --git a/xar/lib/linuxattr.h b/xar/lib/linuxattr.h new file mode 100644 index 0000000..d340b97 --- /dev/null +++ b/xar/lib/linuxattr.h @@ -0,0 +1,41 @@ +/* All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Apple nor the names of any contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +/* + * Rob Braun + * 26-Oct-2004 + * Copyright (c) 2004 Rob Braun. All rights reserved. + */ +/* + * Portions Copyright 2006, Apple Computer, Inc. + * Christopher Ryan +*/ + +#ifndef _XAR_LINUXATTR_H_ +#define _XAR_LINUXATTR_H_ +int32_t xar_linuxattr_archive(xar_t x, xar_file_t f, const char* file, const char *buffer, size_t len); +int32_t xar_linuxattr_extract(xar_t x, xar_file_t f, const char* file, char *buffer, size_t len); +#endif /* _XAR_LINUXATTR_H_ */ diff --git a/xar/lib/lzmaxar.c b/xar/lib/lzmaxar.c new file mode 100644 index 0000000..ba9c868 --- /dev/null +++ b/xar/lib/lzmaxar.c @@ -0,0 +1,357 @@ +/* + * Copyright (c) 2005 Rob Braun + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Rob Braun nor the names of his contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +/* + * 19-Sep-2007 + * DRI: Anders F Bjorklund + */ +/* + * Portions Copyright 2006, Apple Computer, Inc. + * Christopher Ryan +*/ + + +#include "config.h" +#ifndef HAVE_ASPRINTF +#include "asprintf.h" +#endif +#include +#include +#include +#include +#include +#ifdef HAVE_LIBLZMA +#include +#endif +#include "xar.h" +#include "filetree.h" +#include "io.h" + +#ifdef HAVE_LIBLZMA + +#ifndef UINT32_C +#define UINT32_C(v) (v ## U) /* from normally */ +#endif +#ifndef LZMA_VERSION +#define LZMA_VERSION UINT32_C(40420000) /* = 4.42.0alpha6 */ +#endif + +struct _lzma_context{ + uint8_t lzmacompressed; + lzma_stream lzma; + lzma_options_stream options; + lzma_allocator allocator; +#if LZMA_VERSION < 40420010U + lzma_memory_limitter *limit; +#else + lzma_memlimit *limit; +#endif +}; + +#define preset_level 7 +#define memory_limit 93*1024*1024 /* 1=1M, 5=24M, 6=39M, 7=93M, 8=185M, 9=369M */ + +#define LZMA_CONTEXT(x) ((struct _lzma_context *)(*x)) +#endif + +int xar_lzma_fromheap_done(xar_t x, xar_file_t f, xar_prop_t p, void **context) { +#ifdef HAVE_LIBLZMA + + if( !context || !LZMA_CONTEXT(context) ) + return 0; + + if( LZMA_CONTEXT(context)->lzmacompressed){ + lzma_end(&LZMA_CONTEXT(context)->lzma); + } + + /* free the context */ + free(LZMA_CONTEXT(context)); + *context = NULL; + +#endif + return 0; +} + +int xar_lzma_fromheap_in(xar_t x, xar_file_t f, xar_prop_t p, void **in, size_t *inlen, void **context) { + const char *opt; + xar_prop_t tmpp; +#ifdef HAVE_LIBLZMA + void *out = NULL; + size_t outlen, offset = 0; + lzma_ret r; + + /* on first run, we init the context and check the compression type */ + if( !LZMA_CONTEXT(context) ) { + *context = calloc(1,sizeof(struct _lzma_context)); + + opt = NULL; + tmpp = xar_prop_pget(p, "encoding"); + if( tmpp ) + opt = xar_attr_pget(f, tmpp, "style"); + if( !opt ) return 0; + if( strcmp(opt, "application/x-lzma") != 0 ) return 0; + + lzma_init_decoder(); + LZMA_CONTEXT(context)->lzma = LZMA_STREAM_INIT_VAR; + r = lzma_stream_decoder(&LZMA_CONTEXT(context)->lzma, NULL, NULL); + if( (r != LZMA_OK) ) { + xar_err_new(x); + xar_err_set_file(x, f); + xar_err_set_string(x, "Error decompressing file"); + xar_err_callback(x, XAR_SEVERITY_FATAL, XAR_ERR_ARCHIVE_EXTRACTION); + return -1; + } + LZMA_CONTEXT(context)->lzmacompressed = 1; + }else if( !LZMA_CONTEXT(context)->lzmacompressed ){ + /* once the context has been initialized, then we have already + checked the compression type, so we need only check if we + actually are compressed */ + return 0; + } + + outlen = *inlen; + + LZMA_CONTEXT(context)->lzma.next_in = *in; + LZMA_CONTEXT(context)->lzma.avail_in = *inlen; + LZMA_CONTEXT(context)->lzma.next_out = out; + LZMA_CONTEXT(context)->lzma.avail_out = 0; + + while( LZMA_CONTEXT(context)->lzma.avail_in != 0 ) { + size_t newlen = outlen * 2; + if (newlen > outlen) + outlen = newlen; + else + abort(); /* Someone has somehow malloced over 2^64 bits of ram. */ + + out = realloc(out, outlen); + if( out == NULL ) abort(); + + LZMA_CONTEXT(context)->lzma.next_out = ((unsigned char *)out) + offset; + LZMA_CONTEXT(context)->lzma.avail_out = outlen - offset; + + r = lzma_code(&(LZMA_CONTEXT(context)->lzma), LZMA_RUN); + if( (r != LZMA_OK) && (r != LZMA_STREAM_END) ) { + xar_err_new(x); + xar_err_set_file(x, f); + xar_err_set_errno(x, r); + xar_err_set_string(x, "Error decompressing file"); + xar_err_callback(x, XAR_SEVERITY_FATAL, XAR_ERR_ARCHIVE_EXTRACTION); + return -1; + } + offset += outlen - offset - LZMA_CONTEXT(context)->lzma.avail_out; + if( (r == LZMA_STREAM_END) && (offset == 0) ) + break; + } + + free(*in); + *in = out; + *inlen = offset; +#else + opt = NULL; + tmpp = xar_prop_pget(p, "encoding"); + if( tmpp ) + opt = xar_attr_pget(f, tmpp, "style"); + if( !opt ) return 0; + if( strcmp(opt, "application/x-lzma") != 0 ) return 0; + xar_err_new(x); + xar_err_set_file(x, f); + xar_err_set_errno(x, 0); + xar_err_set_string(x, "lzma support not compiled in."); + xar_err_callback(x, XAR_SEVERITY_FATAL, XAR_ERR_ARCHIVE_EXTRACTION); + +#endif /* HAVE_LIBLZMA */ + return 0; +} + +int xar_lzma_toheap_done(xar_t x, xar_file_t f, xar_prop_t p, void **context) { +#ifdef HAVE_LIBLZMA + xar_prop_t tmpp; + + if( LZMA_CONTEXT(context)->lzmacompressed){ + lzma_end(&LZMA_CONTEXT(context)->lzma); +#if LZMA_VERSION < 40420010U + lzma_memory_limitter_end(LZMA_CONTEXT(context)->limit, 1); +#else + lzma_memlimit_end(LZMA_CONTEXT(context)->limit, 1); +#endif + + tmpp = xar_prop_pset(f, p, "encoding", NULL); + if( tmpp ) + xar_attr_pset(f, tmpp, "style", "application/x-lzma"); + } + + /* free the context */ + free(LZMA_CONTEXT(context)); + *context = NULL; + +#endif /* HAVE_LIBLZMA */ + return 0; +} + +int32_t xar_lzma_toheap_in(xar_t x, xar_file_t f, xar_prop_t p, void **in, size_t *inlen, void **context) { + const char *opt; +#ifdef HAVE_LIBLZMA + void *out = NULL; + size_t outlen, offset = 0; + lzma_ret r; + + /* on first run, we init the context and check the compression type */ + if( !LZMA_CONTEXT(context) ) { + int level = preset_level; + *context = calloc(1,sizeof(struct _lzma_context)); + + opt = xar_opt_get(x, XAR_OPT_COMPRESSION); + if( !opt ) + return 0; + + if( strcmp(opt, XAR_OPT_VAL_LZMA) != 0 ) + return 0; + + opt = xar_opt_get(x, XAR_OPT_COMPRESSIONARG); + if( opt ) { + int tmp; + errno = 0; + tmp = strtol(opt, NULL, 10); + if( errno == 0 ) { + if( (level >= 0) && (level <= 9) ) + level = tmp; + } + } + + lzma_init_encoder(); + LZMA_CONTEXT(context)->options.check = LZMA_CHECK_CRC64; + LZMA_CONTEXT(context)->options.has_crc32 = 1; /* true */ + LZMA_CONTEXT(context)->options.alignment = 0; +#if defined (__ppc__) || defined (powerpc) || defined (__ppc64__) + LZMA_CONTEXT(context)->options.filters[0].id = LZMA_FILTER_POWERPC; +#elif defined (__i386__) || defined (__amd64__) || defined(__x86_64__) + LZMA_CONTEXT(context)->options.filters[0].id = LZMA_FILTER_X86; +#else + LZMA_CONTEXT(context)->options.filters[0].id = LZMA_FILTER_COPY; +#endif + LZMA_CONTEXT(context)->options.filters[0].options = NULL; + LZMA_CONTEXT(context)->options.filters[1].id = LZMA_FILTER_LZMA; + LZMA_CONTEXT(context)->options.filters[1].options = (lzma_options_lzma *)(lzma_preset_lzma + level - 1); + /* Terminate the filter options array. */ + LZMA_CONTEXT(context)->options.filters[2].id = UINT64_MAX; + LZMA_CONTEXT(context)->lzma = LZMA_STREAM_INIT_VAR; +#if LZMA_VERSION < 40420010U + LZMA_CONTEXT(context)->limit = lzma_memory_limitter_create(memory_limit); + LZMA_CONTEXT(context)->allocator.alloc = (void*) lzma_memory_alloc; + LZMA_CONTEXT(context)->allocator.free = (void*) lzma_memory_free; +#else + LZMA_CONTEXT(context)->limit = lzma_memlimit_create(memory_limit); + LZMA_CONTEXT(context)->allocator.alloc = (void*) lzma_memlimit_alloc; + LZMA_CONTEXT(context)->allocator.free = (void*) lzma_memlimit_free; +#endif + LZMA_CONTEXT(context)->allocator.opaque = LZMA_CONTEXT(context)->limit; + LZMA_CONTEXT(context)->lzma.allocator = &LZMA_CONTEXT(context)->allocator; + r = lzma_stream_encoder_single(&LZMA_CONTEXT(context)->lzma, &(LZMA_CONTEXT(context)->options)); + if( (r != LZMA_OK) ) { + xar_err_new(x); + xar_err_set_file(x, f); + xar_err_set_string(x, "Error compressing file"); + xar_err_callback(x, XAR_SEVERITY_FATAL, XAR_ERR_ARCHIVE_CREATION); + return -1; + } + LZMA_CONTEXT(context)->lzmacompressed = 1; + if( *inlen == 0 ) + return 0; + }else if( !LZMA_CONTEXT(context)->lzmacompressed ){ + /* once the context has been initialized, then we have already + checked the compression type, so we need only check if we + actually are compressed */ + return 0; + } + + outlen = *inlen/2; + if(outlen == 0) outlen = 1024; + LZMA_CONTEXT(context)->lzma.next_in = *in; + LZMA_CONTEXT(context)->lzma.avail_in = *inlen; + LZMA_CONTEXT(context)->lzma.next_out = out; + LZMA_CONTEXT(context)->lzma.avail_out = 0; + + if( *inlen != 0 ) { + do { + size_t newlen = outlen * 2; + if (newlen > outlen) + outlen = newlen; + else + abort(); /* Someone has somehow malloced over 2^64 bits of ram. */ + + if( out == NULL ) abort(); + + LZMA_CONTEXT(context)->lzma.next_out = ((unsigned char *)out) + offset; + LZMA_CONTEXT(context)->lzma.avail_out = outlen - offset; + + r = lzma_code(&LZMA_CONTEXT(context)->lzma, LZMA_RUN); + offset = outlen - LZMA_CONTEXT(context)->lzma.avail_out; + } while( r == LZMA_OK && LZMA_CONTEXT(context)->lzma.avail_in != 0); + } else { + do { + size_t newlen = outlen * 2; + if (newlen > outlen) + outlen = newlen; + else + abort(); /* Someone has somehow malloced over 2^64 bits of ram. */ if( out == NULL ) abort(); + + LZMA_CONTEXT(context)->lzma.next_out = ((unsigned char *)out) + offset; + LZMA_CONTEXT(context)->lzma.avail_out = outlen - offset; + + r = lzma_code(&LZMA_CONTEXT(context)->lzma, LZMA_FINISH); + offset = outlen - LZMA_CONTEXT(context)->lzma.avail_out; + } while( r == LZMA_OK && r != LZMA_STREAM_END); + } + + if( (r != LZMA_OK && r != LZMA_STREAM_END) ) { + xar_err_new(x); + xar_err_set_file(x, f); + xar_err_set_string(x, "Error compressing file"); + xar_err_set_errno(x, r); + xar_err_callback(x, XAR_SEVERITY_FATAL, XAR_ERR_ARCHIVE_CREATION); + return -1; + } + + free(*in); + *in = out; + *inlen = offset; +#else + opt = xar_opt_get(x, XAR_OPT_COMPRESSION); + if( !opt ) + return 0; + if( strcmp(opt, XAR_OPT_VAL_LZMA) != 0 ) + return 0; + xar_err_new(x); + xar_err_set_file(x, f); + xar_err_set_errno(x, 0); + xar_err_set_string(x, "lzma support not compiled in."); + xar_err_callback(x, XAR_SEVERITY_FATAL, XAR_ERR_ARCHIVE_CREATION); + +#endif /* HAVE_LIBLZMA */ + return 0; +} diff --git a/xar/lib/lzmaxar.h b/xar/lib/lzmaxar.h new file mode 100644 index 0000000..1699a38 --- /dev/null +++ b/xar/lib/lzmaxar.h @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2005 Rob Braun + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Rob Braun nor the names of his contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +/* + * + * DRI: + */ +/* + * Portions Copyright 2006, Apple Computer, Inc. + * Christopher Ryan +*/ + +#ifndef _XAR_LZMA_H_ +#define _XAR_LZMA_H_ + +int xar_lzma_fromheap_in(xar_t x, xar_file_t f, xar_prop_t p, void **in, size_t *inlen, void **context); +int xar_lzma_fromheap_done(xar_t x, xar_file_t f, xar_prop_t p, void **context); + +int32_t xar_lzma_toheap_in(xar_t x, xar_file_t f, xar_prop_t p, void **in, size_t *inlen, void **context); +int xar_lzma_toheap_done(xar_t x, xar_file_t f, xar_prop_t p, void **context); + +#endif /* _XAR_LZMA_H_ */ diff --git a/xar/lib/macho.c b/xar/lib/macho.c new file mode 100644 index 0000000..bfa1157 --- /dev/null +++ b/xar/lib/macho.c @@ -0,0 +1,407 @@ +/* All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Apple nor the names of any contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. +*/ +/* + * Portions Copyright 2006, Apple Computer, Inc. + * Christopher Ryan +*/ + +#define _FILE_OFFSET_BITS 64 + +#include +#include +#include +#include +#include +#include + +#include "config.h" +#ifndef HAVE_ASPRINTF +#include "asprintf.h" +#endif +#include "macho.h" +#include "util.h" +#include "data.h" +#include "arcmod.h" +#include "xar.h" + +#define BIT64 0x01000000 +#define PPC 0x00000012 +#define I386 0x00000007 + +struct machexecutables { + struct mach_header mh; + struct lc *lc; + uint32_t curlc; + uint64_t nextlc; + char **strings; + uint32_t stringsz; + uint8_t byteswapped; + uint8_t bits; +}; + +struct _macho_context{ + struct fat_header fath; /* Need to read and buffer the fat header */ + struct fat_arch *arches; /* Read and buffer array of arches */ + uint32_t curarch; /* Current arch being parsed */ + struct machexecutables *me; + uint64_t nextme; /* Offset of the next mach header */ + uint32_t curme; /* Current me being parsed */ + unsigned char buffer[512]; /* Place to store incomplete struct info */ + uint16_t buffersz; /* Keep track of how much of buffer is used*/ + uint16_t state; /* Keep track of what we're looking for */ + uint64_t curroffset; /* Current offset in file */ + uint8_t byteswapped; /* Keep track of whether we're byteswapping*/ +}; + +/* Looking for... */ +enum { + lf_fatheader = 0, + lf_inc_fatheader, + lf_archheader, + lf_inc_archheader, + lf_machheader, + lf_inc_machheader, + lf_loadcommand, + lf_inc_loadcommand, + lf_lcstr, + lf_inc_lcstr, + lf_none +}; + +#define MACHO_CONTEXT(x) ((struct _macho_context *)(*x)) + +static const char *macho_cpustr(uint32_t cputype) +{ + const char *cpustr; + switch(cputype) { + case PPC: cpustr = "ppc"; break; + case I386: cpustr = "i386"; break; + case PPC|BIT64: cpustr = "ppc64"; break; + default: cpustr = "unknown"; break; + }; + return cpustr; +} + +/* Returns number of bytes consumed during the parsing process */ +static int32_t macho_parse(xar_file_t f, void *in, size_t inlen, struct _macho_context *context) +{ + int32_t consumed = 0; + + switch( context->state ) { + case(lf_fatheader): + if( inlen >= sizeof(struct fat_header) ) { + struct fat_header *fh = (struct fat_header *)in; + if( fh->magic == 0xcafebabe ) { + context->fath.magic = fh->magic; + context->fath.nfat_arch = fh->nfat_arch; + context->arches = calloc(1,sizeof(struct fat_arch) * fh->nfat_arch); + context->me = calloc(1,sizeof(struct machexecutables) * fh->nfat_arch); + context->state = lf_archheader; + context->byteswapped = 0; + context->curarch = 0; + consumed = 8; + xar_prop_set(f, "contents/type", "Mach-O Fat File"); + } else if( fh->magic == 0xbebafeca ) { + context->fath.magic = xar_swap32(fh->magic); + context->fath.nfat_arch = xar_swap32(fh->nfat_arch); + context->arches = calloc(1,sizeof(struct fat_arch) * context->fath.nfat_arch); + context->me = calloc(1,sizeof(struct machexecutables) * context->fath.nfat_arch); + context->state = lf_archheader; + context->byteswapped = 1; + context->curarch = 0; + consumed = 8; + xar_prop_set(f, "contents/type", "Mach-O Fat File"); + } else { + context->me = calloc(1,sizeof(struct machexecutables)); + context->curme = 0; + context->state = lf_machheader; + } + } else { + uint32_t *tmp = in; + if( (*tmp == 0xcafebabe) || (*tmp == 0xbebafeca) ) { + memcpy(context->buffer, in, inlen); + context->buffersz = inlen; + consumed = (int32_t)inlen; + context->state = lf_inc_fatheader; + } else { + context->me = calloc(1,sizeof(struct machexecutables)); + context->curme = 0; + context->state = lf_machheader; + } + } + break; + case lf_archheader: + if( inlen >= sizeof(struct fat_arch) ) { + struct fat_arch *fa = in; + if( context->byteswapped ) { + context->arches[context->curarch].cputype = xar_swap32(fa->cputype); + context->arches[context->curarch].cpusubtype = xar_swap32(fa->cpusubtype); + context->arches[context->curarch].offset = xar_swap32(fa->offset); + context->arches[context->curarch].size = xar_swap32(fa->size); + context->arches[context->curarch].alighn = xar_swap32(fa->alighn); + } else { + memcpy(&context->arches[context->curarch], in, sizeof(struct fat_arch)); + } + context->curarch++; + if( context->curarch >=context->fath.nfat_arch ) { + context->nextme = context->arches[0].offset; + context->state = lf_machheader; + } + consumed = sizeof(struct fat_arch); + } else { + memcpy(context->buffer, in, inlen); + context->buffersz = inlen; + consumed = (int32_t)inlen; + context->state = lf_inc_archheader; + } + break; + case lf_machheader: + if( (context->curroffset+inlen) <= context->nextme ) + consumed = inlen; + else { + uint64_t off; + unsigned char *tmpin = in; + off = context->nextme - context->curroffset; + tmpin += off; + if( (inlen-off) >= sizeof(struct mach_header) ) { + const char *cpustr; + char *typestr, *typestr2; + struct mach_header *mh = (struct mach_header *)tmpin; + switch(mh->magic) { + case 0xcffaedfe: + context->me[context->curme].bits = 64; + context->me[context->curme].byteswapped = 1; + break; + case 0xcefaedfe: + context->me[context->curme].bits = 32; + context->me[context->curme].byteswapped = 1; + break; + case 0xfeedface: + context->me[context->curme].bits = 32; + break; + case 0xfeedfacf: + context->me[context->curme].bits = 64; + break; + default: + context->state = lf_none; + return inlen; + }; + + if( context->me[context->curme].byteswapped ) { + context->me[context->curme].mh.magic = xar_swap32(mh->magic); + context->me[context->curme].mh.cputype = xar_swap32(mh->cputype); + context->me[context->curme].mh.cpusubtype = xar_swap32(mh->cpusubtype); + context->me[context->curme].mh.filetype = xar_swap32(mh->filetype); + context->me[context->curme].mh.ncmds = xar_swap32(mh->ncmds); + context->me[context->curme].mh.sizeofcmds = xar_swap32(mh->sizeofcmds); + context->me[context->curme].mh.flags = xar_swap32(mh->flags); + } else { + memcpy(&context->me[context->curme].mh, tmpin, sizeof(struct mach_header)); + } + + cpustr = macho_cpustr(context->me[context->curme].mh.cputype); + + switch(context->me[context->curme].mh.filetype) { + case 0x01: typestr = "Mach-O Object"; break; + case 0x02: typestr = "Mach-O Executable"; break; + case 0x03: typestr = "Mach-O Fixed VM Library"; break; + case 0x04: typestr = "Mach-O core"; break; + case 0x05: typestr = "Mach-O Preloaded Executable"; break; + case 0x06: typestr = "Mach-O Dylib"; break; + case 0x07: typestr = "Mach-O Dylinker"; break; + case 0x08: typestr = "Mach-O Bundle"; break; + case 0x09: typestr = "Mach-O Stub"; break; + default: typestr = "Unknown"; break; + }; + + if( xar_prop_get(f, "contents/type", (const char **)&typestr2) ) { + xar_prop_set(f, "contents/type", typestr); + } + asprintf(&typestr2, "contents/%s/type", cpustr); + xar_prop_set(f, typestr2, typestr); + free(typestr2); + + context->me[context->curme].lc = malloc(sizeof(struct lc) * context->me[context->curme].mh.ncmds); + context->me[context->curme].strings = malloc(sizeof(char *) * context->me[context->curme].mh.ncmds); + context->me[context->curme].curlc = 0; + consumed = off + sizeof(struct mach_header); + if( context->me[context->curme].bits == 64 ) + consumed += 4; + context->me[context->curme].nextlc = context->curroffset + consumed; + context->state = lf_loadcommand; + } else { + memcpy(context->buffer, tmpin, inlen-off); + context->buffersz = inlen-off; + consumed = (int32_t)inlen; + context->state = lf_inc_machheader; + } + } + break; + case lf_loadcommand: + if( (context->curroffset+inlen) <= context->me[context->curme].nextlc ) + consumed = inlen; + else { + uint64_t off; + unsigned char *tmpin = in; + off = context->me[context->curme].nextlc - context->curroffset; + tmpin += off; + if( (inlen-off) >= sizeof(struct lc) ) { + if( context->me[context->curme].byteswapped ) { + struct lc *lc = (struct lc *)tmpin; + context->me[context->curme].lc[context->me[context->curme].curlc].cmd = xar_swap32(lc->cmd); + context->me[context->curme].lc[context->me[context->curme].curlc].cmdsize = xar_swap32(lc->cmdsize); + } else { + memcpy(&context->me[context->curme].lc[context->me[context->curme].curlc], tmpin, sizeof(struct lc)); + } + consumed = off + sizeof(struct lc); + context->me[context->curme].nextlc += context->me[context->curme].lc[context->me[context->curme].curlc].cmdsize; + if( (context->me[context->curme].lc[context->me[context->curme].curlc].cmd == 0xc) || (context->me[context->curme].lc[context->me[context->curme].curlc].cmd == 0xd) ) { + context->state = lf_lcstr; + } else { + context->me[context->curme].curlc++; + if( context->me[context->curme].curlc >= context->me[context->curme].mh.ncmds ) { + context->curme++; + if( context->fath.nfat_arch ) { + if( context->curme >= context->fath.nfat_arch ) { + context->state = lf_none; + } else { + context->nextme = context->arches[context->curme].offset; + context->state = lf_machheader; + } + } else { + context->state = lf_none; + } + } + } + } else { + memcpy(context->buffer, ((char *)in)+off, inlen-off); + context->buffersz = inlen-off; + consumed = inlen; + context->state = lf_inc_loadcommand; + } + } + break; + case lf_lcstr: + if( inlen >= (context->me[context->curme].lc[context->me[context->curme].curlc].cmdsize-8) ) { + const char *tmpstr; + uint32_t cmdsize = context->me[context->curme].lc[context->me[context->curme].curlc].cmdsize; + uint32_t *offsetp, offset; + char *lib, *propstr; + offsetp = in; + if( context->me[context->curme].byteswapped ) + offset = xar_swap32(*offsetp); + else + offset = *offsetp; + lib = calloc(1,(cmdsize - offset)+1); + memcpy(lib, ((char *)in)+(offset - 8), cmdsize - offset); + tmpstr = macho_cpustr(context->me[context->curme].mh.cputype); + asprintf(&propstr, "contents/%s/library", tmpstr); + xar_prop_create(f, propstr, lib); + free(lib); + free(propstr); + + consumed = cmdsize-8; + context->state = lf_loadcommand; + context->me[context->curme].curlc++; + if( context->me[context->curme].curlc >= context->me[context->curme].mh.ncmds ) { + context->curme++; + if( context->fath.nfat_arch ) { + if( context->curme >= context->fath.nfat_arch ) { + context->state = lf_none; + } else { + context->nextme = context->arches[context->curme].offset; + context->state = lf_machheader; + } + } else { + context->state = lf_none; + } + } + } else { + memcpy(context->buffer, in, inlen); + context->buffersz = inlen; + consumed = inlen; + context->state = lf_inc_lcstr; + } + break; + case lf_none: + default: + consumed = inlen; + break; + }; + return consumed; +} + +int32_t xar_macho_in(xar_t x, xar_file_t f, xar_prop_t p, void **in, size_t *inlen, void **context) { + int32_t consumed = 0, total = 0; + + if( strcmp(xar_prop_getkey(p), "data") != 0 ) + return 0; + + if( !xar_check_prop(x, "contents") ) + return 0; + + if( !*context ) { + *context = calloc(1,sizeof(struct _macho_context)); + } + + while( total < *inlen ) { + consumed = macho_parse(f, ((char *)*in)+total, *inlen-total, MACHO_CONTEXT(context)); + total += consumed; + MACHO_CONTEXT(context)->curroffset += consumed; + } + + return 0; +} + +int32_t xar_macho_done(xar_t x, xar_file_t f, xar_prop_t p, void **context) { + + if( MACHO_CONTEXT(context) ){ + int i; + if( MACHO_CONTEXT(context)->fath.nfat_arch ) { + for(i = 0; i < MACHO_CONTEXT(context)->fath.nfat_arch; i++) { + if( MACHO_CONTEXT(context)->me[i].lc ) + free(MACHO_CONTEXT(context)->me[i].lc); + if( MACHO_CONTEXT(context)->me[i].strings ) + free(MACHO_CONTEXT(context)->me[i].strings); + } + } else { + if( MACHO_CONTEXT(context)->me ) { + if( MACHO_CONTEXT(context)->me[0].lc ) + free(MACHO_CONTEXT(context)->me[0].lc); + if( MACHO_CONTEXT(context)->me[0].strings ) + free(MACHO_CONTEXT(context)->me[0].strings); + } + } + if( MACHO_CONTEXT(context)->me ) + free(MACHO_CONTEXT(context)->me); + if( MACHO_CONTEXT(context)->arches ) + free(MACHO_CONTEXT(context)->arches); + free(*context); + } + + return 0; +} diff --git a/xar/lib/macho.h b/xar/lib/macho.h new file mode 100644 index 0000000..705984a --- /dev/null +++ b/xar/lib/macho.h @@ -0,0 +1,69 @@ +/* All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Apple nor the names of any contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. +*/ +/* + * Portions Copyright 2006, Apple Computer, Inc. + * Christopher Ryan +*/ + +#ifndef _MACHO_H_ +#define _MACHO_H_ + +#include "xar.h" +#include "filetree.h" + +struct mach_header { + uint32_t magic; + uint32_t cputype; + uint32_t cpusubtype; + uint32_t filetype; + uint32_t ncmds; + uint32_t sizeofcmds; + uint32_t flags; +}; + +struct lc { + uint32_t cmd; + uint32_t cmdsize; +}; + +struct fat_header { + uint32_t magic; + uint32_t nfat_arch; +}; + +struct fat_arch { + uint32_t cputype; + uint32_t cpusubtype; + uint32_t offset; + uint32_t size; + uint32_t alighn; +}; + +int32_t xar_macho_in(xar_t x, xar_file_t f, xar_prop_t p, void **in, size_t *inlen, void **context); +int32_t xar_macho_done(xar_t x, xar_file_t f, xar_prop_t p, void **context); + +#endif /* _MACHO_H_ */ diff --git a/xar/lib/script.c b/xar/lib/script.c new file mode 100644 index 0000000..d0b01a2 --- /dev/null +++ b/xar/lib/script.c @@ -0,0 +1,111 @@ +/* + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Apple nor the names of any contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. +*/ +/* + * Portions Copyright 2006, Apple Computer, Inc. + * Christopher Ryan +*/ + +#include +#include +#include +#include +#include + +#include "config.h" +#ifndef HAVE_ASPRINTF +#include "asprintf.h" +#endif +#include "xar.h" +#include "filetree.h" +#include "arcmod.h" + +struct _script_context{ + int initted; +}; + +#define SCRIPT_CONTEXT(x) ((struct _script_context*)(*x)) + +int32_t xar_script_in(xar_t x, xar_file_t f, xar_prop_t p, void **in, size_t *inlen, void **context) { + char *buf = *in; + xar_prop_t tmpp; + + if(!SCRIPT_CONTEXT(context)){ + *context = calloc(1,sizeof(struct _script_context)); + } + + if( SCRIPT_CONTEXT(context)->initted ) + return 0; + + if( !xar_check_prop(x, "contents") ) + return 0; + + /* Sanity check *inlen, which really shouldn't be more than a + * few kbytes... + */ + if( *inlen > INT_MAX ) + return 0; + + /*We only run on the begining of the file, so once we init, we don't run again*/ + SCRIPT_CONTEXT(context)->initted = 1; + + if( (*inlen > 2) && (buf[0] == '#') && (buf[1] == '!') ) { + char *exe; + int i; + + exe = malloc(*inlen); + if( !exe ) + return -1; + memset(exe, 0, *inlen); + + for(i = 2; (i < *inlen) && (buf[i] != '\0') && (buf[i] != '\n') && (buf[i] != ' '); ++i) { + exe[i-2] = buf[i]; + } + + tmpp = xar_prop_pset(f, p, "contents", NULL); + if( tmpp ) { + xar_prop_pset(f, tmpp, "type", "script"); + xar_prop_pset(f, tmpp, "interpreter", exe); + } + free(exe); + } + return 0; +} + +int32_t xar_script_done(xar_t x, xar_file_t f, xar_prop_t p, void **context) { + + if(!SCRIPT_CONTEXT(context)){ + return 0; + } + + if( *context ){ + free(*context); + *context = NULL; + } + + return 0; +} diff --git a/xar/lib/script.h b/xar/lib/script.h new file mode 100644 index 0000000..8262996 --- /dev/null +++ b/xar/lib/script.h @@ -0,0 +1,39 @@ +/* + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Apple nor the names of any contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. +*/ +/* + * Portions Copyright 2006, Apple Computer, Inc. + * Christopher Ryan +*/ + +#ifndef _SCRIPT_H_ +#define _SCRIPT_H_ + +int32_t xar_script_in(xar_t x, xar_file_t f, xar_prop_t p, void **in, size_t *inlen, void **context); +int32_t xar_script_done(xar_t x, xar_file_t f, xar_prop_t p, void **context); + +#endif /* _SCRIPT_H_ */ diff --git a/xar/lib/signature.c b/xar/lib/signature.c new file mode 100644 index 0000000..b6e3d9a --- /dev/null +++ b/xar/lib/signature.c @@ -0,0 +1,558 @@ +/* + * Copyright (c) 2006 Apple Computer, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Apple nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +/* + * 6-July-2006 + * DRI: Christopher Ryan +*/ + +#include +#include +#include +#include +#include +#include /* for PRIu64 */ +#include + +#include "xar.h" +#include "archive.h" +#include "b64.h" +#include "signature.h" + +struct _signature_copy_context{ + void *buffer; + size_t length; + off_t offset; +}; + +#ifdef __APPLE__ +xar_signature_t xar_signature_new_internal(xar_t x, int is_extended, const char *type, int32_t length, xar_signer_callback callback, void *callback_context) +#else +xar_signature_t xar_signature_new(xar_t x,const char *type, int32_t length, xar_signer_callback callback, void *callback_context) +#endif +{ + xar_signature_t ret; + + if( XAR(x)->files ){ + xar_err_new(x); + xar_err_set_string(x, "Signatures must be added before files are added"); + xar_err_callback(x, XAR_SEVERITY_WARNING, XAR_ERR_ARCHIVE_CREATION); + return NULL; + } + + ret = malloc(sizeof(struct __xar_signature_t)); + if( ! ret ) + return NULL; + + memset(XAR_SIGNATURE(ret), 0, sizeof(struct __xar_signature_t)); + XAR_SIGNATURE(ret)->type = strdup(type); + XAR_SIGNATURE(ret)->len = length; + XAR_SIGNATURE(ret)->offset = XAR(x)->heap_offset; + XAR_SIGNATURE(ret)->signer_callback = callback; + XAR_SIGNATURE(ret)->callback_context = callback_context; +#ifdef __APPLE__ + XAR_SIGNATURE(ret)->is_extended = is_extended; +#endif + + /* Pre allocate space in the heap */ + XAR(x)->heap_offset += length; + XAR(x)->heap_len += length; + + // Put the new on at the end of the list + if( XAR_SIGNATURE(XAR(x)->signatures) ) { + struct __xar_signature_t *sig; + + // (Apple) Find the end of the signatures list + // The open source code seems to smash list items 1 through n when the head of this list is already defined + // despite the fact that the xar signatures are implemented as a list. This is an Apple xar 1.4 edit + // to allow that list to grow beyond 2 + for( sig = XAR_SIGNATURE(XAR(x)->signatures); sig->next; sig = sig->next); + + sig->next = XAR_SIGNATURE(ret); + } else + XAR(x)->signatures = ret; + + XAR_SIGNATURE(ret)->x = x; + + return ret; + +} + +#ifdef __APPLE__ +xar_signature_t xar_signature_new(xar_t x,const char *type, int32_t length, xar_signer_callback callback, void *callback_context) +{ + return xar_signature_new_internal(x, 0, type, length, callback, callback_context); +} +#endif + +xar_signature_t xar_signature_new_extended(xar_t x,const char *type, int32_t length, xar_signer_callback callback, void *callback_context) +{ +#ifdef __APPLE__ + return xar_signature_new_internal(x, 1, type, length, callback, callback_context); +#else + return xar_signature_new(x, type, length, callback, callback_context); +#endif +} + +const char *xar_signature_type(xar_signature_t s) +{ + if( !s ) + return NULL; + + return XAR_SIGNATURE(s)->type; +} + +/* Add x509 cert data to this signature */ +int32_t xar_signature_add_x509certificate(xar_signature_t sig, const uint8_t *cert_data, uint32_t cert_len ) +{ + struct __xar_x509cert_t *newcert; + + if( !sig ) + return -1; + + newcert = malloc(sizeof(struct __xar_x509cert_t)); + memset(newcert, 0, sizeof(struct __xar_x509cert_t)); + newcert->content = malloc(sizeof(const char)*cert_len); + memcpy(newcert->content,cert_data,cert_len); + newcert->len = cert_len; + + if( XAR_SIGNATURE(sig)->x509certs ){ + struct __xar_x509cert_t *cert; + + // Find the end of the linked list + for( cert = XAR_SIGNATURE(sig)->x509certs; cert->next; cert = cert->next ); + + cert->next = newcert; + }else{ + XAR_SIGNATURE(sig)->x509certs = newcert; + } + + XAR_SIGNATURE(sig)->x509cert_count++; + + return 0; +} + +int32_t xar_signature_get_x509certificate_count(xar_signature_t sig) +{ + if( !sig ){ + return 0; + } + + return XAR_SIGNATURE(sig)->x509cert_count; +} + +int32_t xar_signature_get_x509certificate_data(xar_signature_t sig, int32_t index, const uint8_t **cert_data, uint32_t *cert_len) +{ + struct __xar_x509cert_t *cert; + int i = 0; + + /* If there are no certs to return, return immediatly */ + if( !XAR_SIGNATURE(sig)->x509cert_count ){ + if( cert_data ) + *cert_data = 0; + + return -1; + } + + + /* Loop through the certs, copying each one's string ptr to the array */ + for( cert = XAR_SIGNATURE(sig)->x509certs; cert; cert = cert->next ){ + if( i == index ){ + if( cert_data ) + *cert_data = cert->content; + + if( cert_len ) + *cert_len = cert->len; + break; + } + i++; + } + + /* If the cert iterator is still valid, we did not find the proper index */ + if( !cert ){ + return -1; + } + + return 0; +} + +xar_signature_t xar_signature_first(xar_t x) +{ + return XAR(x)->signatures; +} + +xar_signature_t xar_signature_next(xar_signature_t s) +{ + return XAR_SIGNATURE(s)->next; +} + +int32_t _xar_signature_read_from_heap(xar_t x ,off_t offset,size_t length,uint8_t *data) +{ + off_t seek_off = XAR(x)->toc_count + sizeof(xar_header_t) + offset; + int r = 0; + + r = lseek(XAR(x)->fd, seek_off, SEEK_SET); + + /* can't seek to the proper location */ + if( -1 == r ){ + xar_err_new(x); + xar_err_set_string(x, "Unable to seek"); + xar_err_callback(x, XAR_SEVERITY_NONFATAL, XAR_ERR_ARCHIVE_EXTRACTION); + return -1; + } + + r = read(XAR(x)->fd,data,length); + + if( r != length ){ + xar_err_new(x); + xar_err_set_string(x, "Unable to read"); + xar_err_callback(x, XAR_SEVERITY_NONFATAL, XAR_ERR_ARCHIVE_EXTRACTION); + return -1; + } + + return 0; +} + +/* This method retrieves the signed data for this segment as well as the data the signed data is signing */ +uint8_t xar_signature_copy_signed_data(xar_signature_t sig, uint8_t **data, uint32_t *length, uint8_t **signed_data, uint32_t *signed_length, off_t *signed_offset) +{ + uint32_t offset = 0; + xar_t x = NULL; + const char *value; + + // xar 1.6 fails this method if any of data, length, signed_data, signed_length are NULL + // within OS X we use this method to get combinations of signature, signed data, or signed_offset, + // so this method checks and sets these out values independently + + if( !sig ) + return -1; + + x = XAR_SIGNATURE(sig)->x; + + + /* Get the checksum, to be used for signing. If we support multiple checksums + in the future, all checksums should be retrieved */ + if(length) { + if(0 == xar_prop_get( XAR_FILE(x) , "checksum/size", &value)){ + *length = strtoull( value, (char **)NULL, 10); + } + + if(0 == xar_prop_get( XAR_FILE(x) , "checksum/offset", &value)){ + offset = strtoull( value, (char **)NULL, 10); + } + + if(data) { + *data = malloc(sizeof(char)*(*length)); + + // This function will either read all of length or return -1. Check and bubble up. + if (_xar_signature_read_from_heap(x, offset, *length, *data) != 0) + return -1; + } + } + + /* read signature data */ + offset = XAR_SIGNATURE(sig)->offset; + + // This parameter is an Apple edit + // This out value is ignored OS X in SL, but this method prototype is included in the 10.5 SDK + if( signed_offset ) + *signed_offset = offset; + + if(signed_length) { + + *signed_length = XAR_SIGNATURE(sig)->len; + + if(signed_data) { + *signed_data = malloc(sizeof(char)*(*signed_length)); + + // This function will either read all of length or return -1. Check and bubble up. + if (_xar_signature_read_from_heap(x, offset, *signed_length, *signed_data) != 0) + return -1; + } + } + + return 0; +} + +xar_signature_t xar_signature_unserialize(xar_t x, xmlTextReaderPtr reader) +{ + struct __xar_signature_t *ret = NULL; +#ifdef __APPLE__ + const xmlChar *sig_type = NULL; +#endif + const xmlChar *value = NULL; + const xmlChar *name = NULL; + int type; + size_t outputLength = 0; + + ret = malloc(sizeof(struct __xar_signature_t)); + + if( ! ret ) + return NULL; + + memset(ret, 0, sizeof(struct __xar_signature_t)); + + ret->x = x; + + /* Read One Signature Element */ +#ifdef __APPLE__ + sig_type = xmlTextReaderConstLocalName(reader); + if(strcmp((const char*)sig_type, "x-signature") == 0) { + ret->is_extended = 1; + } +#endif + + /* Retrieve the type attr */ + value = xmlTextReaderGetAttribute(reader, (const xmlChar*)"style"); + + if( value ){ + ret->type = strdup((const char *)value); + } + + /* Look for the rest of the child elements */ + while( xmlTextReaderRead(reader) == 1 ) { + type = xmlTextReaderNodeType(reader); + name = xmlTextReaderConstLocalName(reader); + + if (value) { + xmlFree((void*)value); + value = NULL; + } + + if (!name) { /* archive corruption */ + return NULL; + } + + if( type == XML_READER_TYPE_ELEMENT ) { + if(strcmp((const char*)name, "size") == 0) { + while( xmlTextReaderRead(reader) == 1 ) { + type = xmlTextReaderNodeType(reader); + if( type == XML_READER_TYPE_TEXT ) { + + value = xmlTextReaderConstValue(reader); + ret->len = strtoull( (const char *)value, (char **)NULL, 10); + value = NULL; /* We don't want to accidentally release this const. */ + }else if( type == XML_READER_TYPE_END_ELEMENT ) { + break; + } + } + } else if( strcmp((const char*)name, "offset") == 0 ){ + while( xmlTextReaderRead(reader) == 1 ) { + type = xmlTextReaderNodeType(reader); + if( type == XML_READER_TYPE_TEXT ) { + + value = xmlTextReaderConstValue(reader); + ret->offset = strtoull( (const char *)value, (char **)NULL, 10); + value = NULL; /* We don't want to accidentally release this const. */ + }else if( type == XML_READER_TYPE_END_ELEMENT ) { + break; + } + } + } else if( strcmp((const char*)name, "KeyInfo") == 0 ){ + while( xmlTextReaderRead(reader) == 1 ) { + type = xmlTextReaderNodeType(reader); + name = xmlTextReaderConstLocalName(reader); + + if( type == XML_READER_TYPE_ELEMENT ) { + if(strcmp((const char*)name, "X509Data") == 0) { + while( xmlTextReaderRead(reader) == 1 ) { + type = xmlTextReaderNodeType(reader); + name = xmlTextReaderConstLocalName(reader); + + if( type == XML_READER_TYPE_ELEMENT ) { + if(strcmp((const char*)name, "X509Certificate") == 0) { + while( xmlTextReaderRead(reader) == 1 ) { + type = xmlTextReaderNodeType(reader); + if( type == XML_READER_TYPE_TEXT ) { + unsigned char *sig_data = NULL; + + value = xmlTextReaderConstValue(reader); + + /* this method allocates the resulting data */ + sig_data = xar_from_base64(value, strlen((const char *)value), &outputLength); + + if(sig_data){ + /* for convience we just use the same method, which means multiple allocations */ + xar_signature_add_x509certificate(ret, sig_data, outputLength); + free(sig_data); + }else{ + ret = NULL; + } + + value = NULL; /* We don't want to accidentally release this const. */ + //break; + }else if( type == XML_READER_TYPE_END_ELEMENT ) { + break; + } + } + } + }else if( type == XML_READER_TYPE_END_ELEMENT ) { + break; + } + } + } + }else if( type == XML_READER_TYPE_END_ELEMENT ) { + break; + } + + } + } + }else if( type == XML_READER_TYPE_TEXT ) { + + value = xmlTextReaderConstValue(reader); + value = NULL; /* We don't want to accidentally release this const. */ + + break; + }else if( type == XML_READER_TYPE_END_ELEMENT ) { + break; + } + } + + if (value) { + xmlFree((void*)value); + value = NULL; + } + + return ret; +} + +/* + + 20 + 256 + + + MIICXTCCA...base64... + + + + */ +/* This function will serialize an entire list of signatures */ +int32_t xar_signature_serialize(xar_signature_t sig, xmlTextWriterPtr writer) +{ + if( !sig ) return 0; + + /* */ +#ifdef __APPLE__ + const char* element_name = XAR_SIGNATURE(sig)->is_extended ? "x-signature" : "signature"; + xmlTextWriterStartElementNS( writer, NULL, BAD_CAST(element_name), NULL); +#else + xmlTextWriterStartElementNS( writer, NULL, BAD_CAST("signature"), NULL); +#endif + + /* write out the style */ + xmlTextWriterWriteAttribute(writer, BAD_CAST("style"), BAD_CAST(XAR_SIGNATURE(sig)->type)); + + /* */ + xmlTextWriterStartElementNS( writer, NULL, BAD_CAST("offset"), NULL); + xmlTextWriterWriteFormatString(writer, "%"PRIu64, (uint64_t)(XAR_SIGNATURE(sig)->offset)); + xmlTextWriterEndElement(writer); + + /* */ + xmlTextWriterStartElementNS( writer, NULL, BAD_CAST("size"), NULL); + xmlTextWriterWriteFormatString(writer, "%d", (XAR_SIGNATURE(sig)->len)); + xmlTextWriterEndElement(writer); + + /* */ + xmlTextWriterStartElementNS( writer, NULL, BAD_CAST("KeyInfo"), NULL); + xmlTextWriterWriteAttribute(writer, BAD_CAST("xmlns"), BAD_CAST("http://www.w3.org/2000/09/xmldsig#")); + + /* If we have x509 certs, write them out */ + if( XAR_SIGNATURE(sig)->x509certs ){ + struct __xar_x509cert_t *cert; + + /* */ + xmlTextWriterStartElementNS( writer, NULL, BAD_CAST("X509Data"), NULL); + + /* Loop through the certs, copying each one's string ptr to the array */ + for( cert = XAR_SIGNATURE(sig)->x509certs; cert; cert = cert->next ){ + xmlTextWriterStartElementNS( writer, NULL, BAD_CAST("X509Certificate"), NULL); + xmlTextWriterWriteBase64( writer, (const char *)cert->content, 0, cert->len); + xmlTextWriterEndElement(writer); + } + + /* */ + xmlTextWriterEndElement(writer); + } + + /* */ + xmlTextWriterEndElement(writer); + + + /* */ + xmlTextWriterEndElement(writer); + + /* serialize the next signature */ + if( XAR_SIGNATURE(sig)->next ) + xar_signature_serialize(XAR_SIGNATURE(sig)->next,writer); + + return 0; +} + +void _xar_signature_remove_cert(struct __xar_x509cert_t *cert) +{ + struct __xar_x509cert_t *next; + + if( !cert ) + return; + + next = cert->next; + + if( cert->content ) + free(cert->content); + + free(cert); + + _xar_signature_remove_cert(next); + + return; +} + +void xar_signature_remove(xar_signature_t sig) +{ + xar_signature_t next; + + if( !sig ) + return; + + next = XAR_SIGNATURE(sig)->next; + + if( XAR_SIGNATURE(sig)->type ) + free(XAR_SIGNATURE(sig)->type); + + if( XAR_SIGNATURE(sig)->x509cert_count ){ + _xar_signature_remove_cert(XAR_SIGNATURE(sig)->x509certs); + } + + free(XAR_SIGNATURE(sig)); + + /* remove the next one in the list */ + xar_signature_remove(next); + + return; +} diff --git a/xar/lib/signature.h b/xar/lib/signature.h new file mode 100644 index 0000000..766e43a --- /dev/null +++ b/xar/lib/signature.h @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2006 Apple Computer, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Apple nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +/* + * 6-July-2006 + * DRI: Christopher Ryan +*/ + +#ifndef _XAR_SIGNATURE_H_ +#define _XAR_SIGNATURE_H_ + +#include "xar.h" + +struct __xar_x509cert_t{ + uint8_t *content; + int32_t len; + struct __xar_x509cert_t *next; +}; + +struct __xar_signature_t { + char *type; + int32_t len; + off_t offset; + int32_t x509cert_count; + struct __xar_x509cert_t *x509certs; + struct __xar_signature_t *next; + xar_signer_callback signer_callback; /* callback for signing */ + void *callback_context; /* context for callback */ + xar_t x; +#ifdef __APPLE__ + int is_extended; +#endif +}; + +#define XAR_SIGNATURE(x) ((struct __xar_signature_t *)(x)) + +#ifdef __APPLE__ +xar_signature_t xar_signature_new_internal(xar_t x, int is_extended, const char *type, int32_t length, xar_signer_callback callback, void *callback_context); +#endif + +int32_t xar_signature_serialize(xar_signature_t sig, xmlTextWriterPtr writer); +xar_signature_t xar_signature_unserialize(xar_t x, xmlTextReaderPtr reader); + + +/* deallocates the link list of xar signatures */ +void xar_signature_remove(xar_signature_t sig); + +#endif /* _XAR_SIGNATURE_H_ */ diff --git a/xar/lib/stat.c b/xar/lib/stat.c new file mode 100644 index 0000000..b0cce7c --- /dev/null +++ b/xar/lib/stat.c @@ -0,0 +1,825 @@ +/* + * Copyright (c) 2007 Rob Braun + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Rob Braun nor the names of his contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +/* + * 03-Apr-2005 + * DRI: Rob Braun + */ +/* + * Portions Copyright 2003, Apple Computer, Inc. + * filetype_name() and associated structure. + * DRI: Kevin Van Vechten + */ +/* + * Portions Copyright 2006, Apple Computer, Inc. + * Christopher Ryan +*/ + +#define _FILE_OFFSET_BITS 64 + +#include "config.h" +#ifndef HAVE_ASPRINTF +#include "asprintf.h" +#endif +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef HAVE_SYS_ACL_H +#include +#endif +#include "xar.h" +#include "arcmod.h" +#include "archive.h" +#include "util.h" + +#ifndef LLONG_MIN +#define LLONG_MIN LONG_LONG_MIN +#endif + +#ifndef LLONG_MAX +#define LLONG_MAX LONG_LONG_MAX +#endif + +static struct { + const char *name; + mode_t type; +} filetypes [] = { + { "file", S_IFREG }, + { "directory", S_IFDIR }, + { "symlink", S_IFLNK }, + { "fifo", S_IFIFO }, + { "character special", S_IFCHR }, + { "block special", S_IFBLK }, + { "socket", S_IFSOCK }, +#ifdef S_IFWHT + { "whiteout", S_IFWHT }, +#endif + { NULL, 0 } +}; + +static const char * filetype_name (mode_t mode) { + unsigned int i; + for (i = 0; filetypes[i].name; i++) + if (mode == filetypes[i].type) + return (filetypes[i].name); + return ("unknown"); +} + +static xar_file_t xar_link_lookup(xar_t x, dev_t dev, ino_t ino, xar_file_t f) { + char key[32]; + xar_file_t ret; + + memset(key, 0, sizeof(key)); + snprintf(key, sizeof(key)-1, "%08" DEV_HEXSTRING "%08" INO_HEXSTRING, DEV_CAST dev, INO_CAST ino); + ret = xmlHashLookup(XAR(x)->ino_hash, BAD_CAST(key)); + if( ret == NULL ) { + xmlHashAddEntry(XAR(x)->ino_hash, BAD_CAST(key), XAR_FILE(f)); + return NULL; + } + return ret; +} + +static int32_t aacls(xar_t x, xar_file_t f, const char *file) { +#ifdef HAVE_SYS_ACL_H +#if !defined(__APPLE__) + acl_t a; + const char *type; + + xar_prop_get(f, "type", &type); + if( !type || (strcmp(type, "symlink") == 0) ) + return 0; + + if( !xar_check_prop(x, "acl") ) + return 0; + + a = acl_get_file(file, ACL_TYPE_DEFAULT); + if( a ) { + char *t; + acl_entry_t e; + + /* If the acl is empty, or not valid, skip it */ + if( acl_get_entry(a, ACL_FIRST_ENTRY, &e) != 1 ) + goto NEXT; + + t = acl_to_text(a, NULL); + if( t ) { + xar_prop_set(f, "acl/default", t); + acl_free(t); + } + acl_free(a); + } +NEXT: + + a = acl_get_file(file, ACL_TYPE_ACCESS); + if( a ) { + char *t; + acl_entry_t e; + + /* If the acl is empty, or not valid, skip it */ + if( acl_get_entry(a, ACL_FIRST_ENTRY, &e) != 1 ) + goto DONE; + + t = acl_to_text(a, NULL); + if( t ) { + xar_prop_set(f, "acl/access", t); + acl_free(t); + } + acl_free(a); + } +DONE: +#else /* !__APPLE__ */ + acl_entry_t e = NULL; + acl_t a; + int i; + + if( !xar_check_prop(x, "acl") ) + return 0; + + a = acl_get_file(file, ACL_TYPE_EXTENDED); + if( !a ) + return 0; + + for( i = 0; acl_get_entry(a, e == NULL ? ACL_FIRST_ENTRY : ACL_NEXT_ENTRY, &e) == 0; i++ ) { + char *t; + t = acl_to_text(a, NULL); + if( t ) { + xar_prop_set(f, "acl/appleextended", t); + acl_free(t); + } + + } + acl_free(a); +#endif /* !__APPLE__ */ +#endif + return 0; +} + +static int32_t eacls(xar_t x, xar_file_t f, const char *file) { +#ifdef HAVE_SYS_ACL_H +#if !defined(__APPLE__) + const char *t; + acl_t a; + const char *type; + + xar_prop_get(f, "type", &type); + if( !type || (strcmp(type, "symlink") == 0) ) + return 0; + + + xar_prop_get(f, "acl/default", &t); + if( t ) { + a = acl_from_text(t); + if( !a ) { + xar_err_new(x); + xar_err_set_errno(x, errno); + xar_err_set_string(x, "Error extracting default acl from toc"); + xar_err_set_file(x, f); + xar_err_callback(x, XAR_SEVERITY_NONFATAL, XAR_ERR_ARCHIVE_EXTRACTION); + } else { + if( acl_set_file(file, ACL_TYPE_DEFAULT, a) != 0 ) { + xar_err_new(x); + xar_err_set_errno(x, errno); + xar_err_set_string(x, "Error setting default acl"); + xar_err_set_file(x, f); + xar_err_callback(x, XAR_SEVERITY_NONFATAL, XAR_ERR_ARCHIVE_EXTRACTION); + } + } + } + + xar_prop_get(f, "acl/access", &t); + if( t ) { + a = acl_from_text(t); + if( !a ) { + xar_err_new(x); + xar_err_set_errno(x, errno); + xar_err_set_string(x, "Error extracting access acl from toc"); + xar_err_set_file(x, f); + xar_err_callback(x, XAR_SEVERITY_NONFATAL, XAR_ERR_ARCHIVE_EXTRACTION); + } else { + if( acl_set_file(file, ACL_TYPE_ACCESS, a) != 0 ) { + xar_err_new(x); + xar_err_set_errno(x, errno); + xar_err_set_string(x, "Error setting access acl"); + xar_err_set_file(x, f); + xar_err_callback(x, XAR_SEVERITY_NONFATAL, XAR_ERR_ARCHIVE_EXTRACTION); + } + acl_free(a); + } + } +#else /* !__APPLE__ */ + const char *t; + acl_t a; + + xar_prop_get(f, "acl/appleextended", &t); + if( t ) { + a = acl_from_text(t); + if( !a ) { + xar_err_new(x); + xar_err_set_errno(x, errno); + xar_err_set_string(x, "Error extracting access acl from toc"); + xar_err_set_file(x, f); + xar_err_callback(x, XAR_SEVERITY_NONFATAL, XAR_ERR_ARCHIVE_EXTRACTION); + } else { + if( acl_set_file(file, ACL_TYPE_ACCESS, a) != 0 ) { + xar_err_new(x); + xar_err_set_errno(x, errno); + xar_err_set_string(x, "Error setting access acl"); + xar_err_set_file(x, f); + xar_err_callback(x, XAR_SEVERITY_NONFATAL, XAR_ERR_ARCHIVE_EXTRACTION); + } + acl_free(a); + } + } +#endif /* !__APPLE__ */ +#endif + return 0; +} + +#ifdef HAVE_STRUCT_STAT_ST_FLAGS +#define XAR_FLAG_FORK "flags" +static void x_addflag(xar_file_t f, const char *name) { + char opt[1024]; + memset(opt, 0, sizeof(opt)); + snprintf(opt, sizeof(opt)-1, "%s/%s", XAR_FLAG_FORK, name); + xar_prop_set(f, opt, NULL); + return; +} +#endif + +static int32_t flags_archive(xar_t x, xar_file_t f, const struct stat *sb) { +#ifdef HAVE_STRUCT_STAT_ST_FLAGS + if( !sb->st_flags ) + return 0; + + if( !xar_check_prop(x, XAR_FLAG_FORK) ) + return 0; +#ifdef UF_NODUMP + if( sb->st_flags & UF_NODUMP ) + x_addflag(f, "UserNoDump"); +#endif +#ifdef UF_IMMUTABLE + if( sb->st_flags & UF_IMMUTABLE ) + x_addflag(f, "UserImmutable"); +#endif +#ifdef UF_APPEND + if( sb->st_flags & UF_APPEND ) + x_addflag(f, "UserAppend"); +#endif +#ifdef UF_OPAQUE + if( sb->st_flags & UF_OPAQUE ) + x_addflag(f, "UserOpaque"); +#endif +#ifdef SF_ARCHIVED + if( sb->st_flags & SF_ARCHIVED ) + x_addflag(f, "SystemArchived"); +#endif +#ifdef SF_IMMUTABLE + if( sb->st_flags & SF_IMMUTABLE ) + x_addflag(f, "SystemImmutable"); +#endif +#ifdef SF_APPEND + if( sb->st_flags & SF_APPEND ) + x_addflag(f, "SystemAppend"); +#endif + +#endif /* HAVE_STRUCT_STAT_ST_FLAGS */ + return 0; +} + +#ifdef HAVE_CHFLAGS +static int32_t x_getprop(xar_file_t f, const char *name, char **value) { + char v[1024]; + memset(v, 0, sizeof(v)); + snprintf(v, sizeof(v)-1, "%s/%s", XAR_FLAG_FORK, name); + return xar_prop_get(f, v, (const char **)value); +} +#endif + +int32_t xar_flags_extract(xar_t x, xar_file_t f, const char *file, char *buffer, size_t len) { +#ifdef HAVE_CHFLAGS + char *tmp; + u_int flags = 0; + + if( xar_prop_get(f, XAR_FLAG_FORK, NULL) ) + return 0; + +#ifdef UF_NODUMP + if( x_getprop(f, "UserNoDump", (char **)&tmp) == 0 ) + flags |= UF_NODUMP; +#endif +#ifdef UF_IMMUTABLE + if( x_getprop(f, "UserImmutable", (char **)&tmp) == 0 ) + flags |= UF_IMMUTABLE; +#endif +#ifdef UF_APPEND + if( x_getprop(f, "UserAppend", (char **)&tmp) == 0 ) + flags |= UF_APPEND; +#endif +#ifdef UF_OPAQUE + if( x_getprop(f, "UserOpaque", (char **)&tmp) == 0 ) + flags |= UF_OPAQUE; +#endif +#ifdef SF_ARCHIVED + if( x_getprop(f, "SystemArchived", (char **)&tmp) == 0 ) + flags |= SF_ARCHIVED; +#endif +#ifdef SF_IMMUTABLE + if( x_getprop(f, "SystemImmutable", (char **)&tmp) == 0 ) + flags |= SF_IMMUTABLE; +#endif +#ifdef SF_APPEND + if( x_getprop(f, "SystemAppend", (char **)&tmp) == 0 ) + flags |= SF_APPEND; +#endif + + if( !flags ) + return 0; + + if( chflags(file, flags) != 0 ) { + char e[1024]; + memset(e, 0, sizeof(e)); + snprintf(e, sizeof(e)-1, "chflags: %s", strerror(errno)); + xar_err_new(x); + xar_err_set_file(x, f); + xar_err_set_string(x, e); + xar_err_callback(x, XAR_SEVERITY_NONFATAL, XAR_ERR_ARCHIVE_EXTRACTION); + return -1; + } +#endif + + return 0; +} + +int32_t xar_stat_archive(xar_t x, xar_file_t f, const char *file, const char *buffer, size_t len) { + char *tmpstr; + struct passwd *pw; + struct group *gr; + char time[128]; + struct tm t; + const char *type; + + /* no stat attributes for data from a buffer, it is just a file */ + if(len){ + if( xar_check_prop(x, "type") ) + xar_prop_set(f, "type", "file"); + return 0; + } + + if( S_ISREG(XAR(x)->sbcache.st_mode) && (XAR(x)->sbcache.st_nlink > 1) ) { + xar_file_t tmpf; + const char *id = xar_attr_get(f, NULL, "id"); + if( !id ) { + xar_err_new(x); + xar_err_set_file(x, f); + xar_err_set_string(x, "stat: No file id for file"); + xar_err_callback(x, XAR_SEVERITY_NONFATAL, XAR_ERR_ARCHIVE_CREATION); + return -1; + } + tmpf = xar_link_lookup(x, XAR(x)->sbcache.st_dev, XAR(x)->sbcache.st_ino, f); + if( xar_check_prop(x, "type") ) { + xar_prop_set(f, "type", "hardlink"); + if( tmpf ) { + const char *id; + id = xar_attr_get(tmpf, NULL, "id"); + xar_attr_set(f, "type", "link", id); + } else { + xar_attr_set(f, "type", "link", "original"); + } + } + } else { + type = filetype_name(XAR(x)->sbcache.st_mode & S_IFMT); + if( xar_check_prop(x, "type") ) + xar_prop_set(f, "type", type); + } + + /* Record major/minor device node numbers */ + if( xar_check_prop(x, "device") && (S_ISBLK(XAR(x)->sbcache.st_mode) || S_ISCHR(XAR(x)->sbcache.st_mode))) { + uint32_t major, minor; + char tmpstr[12]; + xar_devmake(XAR(x)->sbcache.st_rdev, &major, &minor); + memset(tmpstr, 0, sizeof(tmpstr)); + snprintf(tmpstr, sizeof(tmpstr)-1, "%u", major); + xar_prop_set(f, "device/major", tmpstr); + memset(tmpstr, 0, sizeof(tmpstr)); + snprintf(tmpstr, sizeof(tmpstr)-1, "%u", minor); + xar_prop_set(f, "device/minor", tmpstr); + } + + if( S_ISLNK(XAR(x)->sbcache.st_mode) ) { + char link[4096]; + struct stat lsb; + + memset(link, 0, sizeof(link)); + readlink(file, link, sizeof(link)-1); + xar_prop_set(f, "link", link); + if( stat(file, &lsb) != 0 ) { + xar_attr_set(f, "link", "type", "broken"); + } else { + type = filetype_name(lsb.st_mode & S_IFMT); + xar_attr_set(f, "link", "type", type); + } + } + + if( xar_check_prop(x, "inode") ) { + asprintf(&tmpstr, "%"INO_STRING, XAR(x)->sbcache.st_ino); + xar_prop_set(f, "inode", tmpstr); + free(tmpstr); + } + + if( xar_check_prop(x, "deviceno") ) { + asprintf(&tmpstr, "%"DEV_STRING, XAR(x)->sbcache.st_dev); + xar_prop_set(f, "deviceno", tmpstr); + free(tmpstr); + } + + if( xar_check_prop(x, "mode") ) { + asprintf(&tmpstr, "%04o", XAR(x)->sbcache.st_mode & (~S_IFMT)); + xar_prop_set(f, "mode", tmpstr); + free(tmpstr); + } + + if( xar_check_prop(x, "uid") ) { + asprintf(&tmpstr, "%"PRIu64, (uint64_t)XAR(x)->sbcache.st_uid); + xar_prop_set(f, "uid", tmpstr); + free(tmpstr); + } + + if( xar_check_prop(x, "user") ) { + pw = getpwuid(XAR(x)->sbcache.st_uid); + if( pw ) + xar_prop_set(f, "user", pw->pw_name); + } + + if( xar_check_prop(x, "gid") ) { + asprintf(&tmpstr, "%"PRIu64, (uint64_t)XAR(x)->sbcache.st_gid); + xar_prop_set(f, "gid", tmpstr); + free(tmpstr); + } + + if( xar_check_prop(x, "group") ) { + gr = getgrgid(XAR(x)->sbcache.st_gid); + if( gr ) + xar_prop_set(f, "group", gr->gr_name); + } + + if( xar_check_prop(x, "atime") ) { + gmtime_r(&XAR(x)->sbcache.st_atime, &t); + memset(time, 0, sizeof(time)); + strftime(time, sizeof(time), "%FT%T", &t); + strcat(time, "Z"); + xar_prop_set(f, "atime", time); + } + + if( xar_check_prop(x, "mtime") ) { + gmtime_r(&XAR(x)->sbcache.st_mtime, &t); + memset(time, 0, sizeof(time)); + strftime(time, sizeof(time), "%FT%T", &t); + strcat(time, "Z"); + xar_prop_set(f, "mtime", time); + } + + if( xar_check_prop(x, "ctime") ) { + gmtime_r(&XAR(x)->sbcache.st_ctime, &t); + memset(time, 0, sizeof(time)); + strftime(time, sizeof(time), "%FT%T", &t); + strcat(time, "Z"); + xar_prop_set(f, "ctime", time); + } + + flags_archive(x, f, &(XAR(x)->sbcache)); + + aacls(x, f, file); + + return 0; +} + +int32_t xar_set_perm(xar_t x, xar_file_t f, const char *file, char *buffer, size_t len) { + const char *opt; + int32_t m=0, mset=0; + uid_t u; + gid_t g; + const char *timestr; + struct tm t; + enum {ATIME=0, MTIME}; + struct timeval tv[2]; + char savesuid = 0; + + /* when writing to a buffer, there are no permissions to set */ + if ( len ) + return 0; + + /* in case we don't find anything useful in the archive */ + u = geteuid(); + g = getegid(); + + opt = xar_opt_get(x, XAR_OPT_OWNERSHIP); + if( opt && (strcmp(opt, XAR_OPT_VAL_SYMBOLIC) == 0) ) { + struct passwd *pw; + struct group *gr; + + xar_prop_get(f, "user", &opt); + if( opt ) { + pw = getpwnam(opt); + if( pw ) { + u = pw->pw_uid; + } + } + xar_prop_get(f, "group", &opt); + if( opt ) { + gr = getgrnam(opt); + if( gr ) { + g = gr->gr_gid; + } + } + savesuid = 1; + } + if( opt && (strcmp(opt, XAR_OPT_VAL_NUMERIC) == 0) ) { + xar_prop_get(f, "uid", &opt); + if( opt ) { + long long tmp; + tmp = strtol(opt, NULL, 10); + if( ( (tmp == LLONG_MIN) || (tmp == LLONG_MAX) ) && (errno == ERANGE) ) { + return -1; + } + u = (uid_t)tmp; + } + + xar_prop_get(f, "gid", &opt); + if( opt ) { + long long tmp; + tmp = strtol(opt, NULL, 10); + if( ( (tmp == LLONG_MIN) || (tmp == LLONG_MAX) ) && (errno == ERANGE) ) { + return -1; + } + g = (gid_t)tmp; + } + savesuid = 1; + } + + opt = xar_opt_get(x, XAR_OPT_SAVESUID); + if( opt && (strcmp(opt, XAR_OPT_VAL_TRUE) == 0) ) { + savesuid = 1; + } + + xar_prop_get(f, "mode", &opt); + if( opt ) { + long long tmp; + tmp = strtoll(opt, NULL, 8); + if( ( (tmp == LLONG_MIN) || (tmp == LLONG_MAX) ) && (errno == ERANGE) ) { + return -1; + } + m = (mode_t)tmp; + if( !savesuid ) { + m &= ~S_ISUID; + m &= ~S_ISGID; + } + mset = 1; + } + + xar_prop_get(f, "type", &opt); + if( opt && !mset ) { + mode_t u = umask(0); + umask(u); + if( strcmp(opt, "directory") == 0 ) { + m = (mode_t)(0777 & ~u); + } else { + m = (mode_t)(0666 & ~u); + } + mset = 1; + } + if( opt && (strcmp(opt, "symlink") == 0) ) { +#ifdef HAVE_LCHOWN + if( lchown(file, u, g) ) { + xar_err_new(x); + xar_err_set_file(x, f); + xar_err_set_string(x, "perm: could not lchown symlink"); + xar_err_callback(x, XAR_SEVERITY_NONFATAL, XAR_ERR_ARCHIVE_EXTRACTION); + m &= ~S_ISUID; + m &= ~S_ISGID; + } +#ifdef HAVE_LCHMOD + if( mset ) + if( lchmod(file, m) ) { + xar_err_new(x); + xar_err_set_file(x, f); + xar_err_set_string(x, "perm: could not lchmod symlink"); + xar_err_callback(x, XAR_SEVERITY_NONFATAL, XAR_ERR_ARCHIVE_EXTRACTION); + } +#endif +#endif + } else { + if( chown(file, u, g) ) { + xar_err_new(x); + xar_err_set_file(x, f); + xar_err_set_string(x, "perm: could not chown file"); + xar_err_set_errno(x, errno); + xar_err_callback(x, XAR_SEVERITY_NONFATAL, XAR_ERR_ARCHIVE_EXTRACTION); + m &= ~S_ISUID; + m &= ~S_ISGID; + } + if( mset ) + if( chmod(file, m) ) { + xar_err_new(x); + xar_err_set_file(x, f); + xar_err_set_string(x, "perm: could not chmod file"); + xar_err_callback(x, XAR_SEVERITY_NONFATAL, XAR_ERR_ARCHIVE_EXTRACTION); + } + } + + eacls(x, f, file); + + memset(tv, 0, sizeof(struct timeval) * 2); + xar_prop_get(f, "atime", ×tr); + if( timestr ) { + memset(&t, 0, sizeof(t)); + strptime(timestr, "%FT%T", &t); + tv[ATIME].tv_sec = timegm(&t); + } else { + tv[ATIME].tv_sec = time(NULL); + } + + xar_prop_get(f, "mtime", ×tr); + if( timestr ) { + memset(&t, 0, sizeof(t)); + strptime(timestr, "%FT%T", &t); + tv[MTIME].tv_sec = timegm(&t); + } else { + tv[MTIME].tv_sec = time(NULL); + } + utimes(file, tv); + + return 0; +} + +int32_t xar_stat_extract(xar_t x, xar_file_t f, const char *file, char *buffer, size_t len) { + const char *opt; + int ret, fd; + mode_t modet = 0; + + xar_prop_get(f, "type", &opt); + + if(opt && ( (strcmp(opt, "character special") == 0) || (strcmp(opt, "block special") == 0)) ) { + // We do not extract device nodes anymore + return -1; + } + + if(opt && (strcmp(opt, "directory") == 0)) { + ret = mkdir(file, 0700); + + if( (ret != 0) && (errno != EEXIST)) { + xar_err_new(x); + xar_err_set_file(x, f); + xar_err_set_string(x, "stat: Could not create directory"); + xar_err_callback(x, XAR_SEVERITY_NONFATAL, XAR_ERR_ARCHIVE_EXTRACTION); + return ret; + } + + if (errno == EEXIST) { + struct stat statdata; + if (lstat(file, &statdata) != 0 || (statdata.st_mode & S_IFDIR) == 0) + { + xar_err_new(x); + xar_err_set_file(x, f); + xar_err_set_string(x, "stat: Could not create directory because overwriting file is not a directory"); + xar_err_callback(x, XAR_SEVERITY_NONFATAL, XAR_ERR_ARCHIVE_EXTRACTION); + return EINVAL; + } + } + + return 0; + } + if(opt && (strcmp(opt, "symlink") == 0)) { + xar_prop_get(f, "link", &opt); + if( opt ) { + unlink(file); + ret = symlink(opt, file); + if( ret != 0 ) { + xar_err_new(x); + xar_err_set_file(x, f); + xar_err_set_string(x, "stat: Could not create symlink"); + xar_err_callback(x, XAR_SEVERITY_NONFATAL, XAR_ERR_ARCHIVE_EXTRACTION); + } + return ret; + } + } + if(opt && (strcmp(opt, "hardlink") == 0)) { + xar_file_t tmpf; + opt = xar_attr_get(f, "type", "link"); + if( !opt ) + return 0; + if( strcmp(opt, "original") == 0 ) + goto CREATEFILE; + + tmpf = xmlHashLookup(XAR(x)->link_hash, BAD_CAST(opt)); + if( !tmpf ) { + xar_err_new(x); + xar_err_set_file(x, f); + xar_err_set_string(x, "stat: Encountered hardlink with no original"); + xar_err_callback(x, XAR_SEVERITY_NONFATAL, XAR_ERR_ARCHIVE_EXTRACTION); + return -1; + } + + unlink(file); + if( link(XAR_FILE(tmpf)->fspath, file) != 0 ) { + if( errno == ENOENT ) { + xar_iter_t i; + const char *ptr; + i = xar_iter_new(); + for(ptr = xar_prop_first(tmpf, i); ptr; ptr = xar_prop_next(i)) { + xar_iter_t a; + const char *val = NULL; + const char *akey, *aval; + if( strncmp("data", ptr, 4) != 0 ) + continue; + + if( xar_prop_get(tmpf, ptr, &val) ) + continue; + + xar_prop_set(f, ptr, val); + a = xar_iter_new(); + for(akey = xar_attr_first(tmpf, ptr, a); akey; akey = xar_attr_next(a)) { + aval = xar_attr_get(tmpf, ptr, akey); + xar_attr_set(f, ptr, akey, aval); + } + xar_iter_free(a); + } + xar_iter_free(i); + xar_attr_set(f, "type", "link", "original"); + return 0; + } else { + xar_err_new(x); + xar_err_set_file(x, f); + xar_err_set_string(x, "stat: Could not link hardlink to original"); + xar_err_callback(x, XAR_SEVERITY_NONFATAL, XAR_ERR_ARCHIVE_EXTRACTION); + return -1; + } + } + return 0; + } + + if(opt && (strcmp(opt, "fifo") == 0)) { + unlink(file); + if( mkfifo(file, 0) ) { + xar_err_new(x); + xar_err_set_file(x, f); + xar_err_set_string(x, "mkfifo: Could not create fifo"); + xar_err_callback(x, XAR_SEVERITY_NONFATAL, XAR_ERR_ARCHIVE_EXTRACTION); + return -1; + } + return 0; + } + + /* skip sockets */ + if(opt && (strcmp(opt, "socket") == 0)) { + return 0; + } + +CREATEFILE: + if (!file) + return 0; + + unlink(file); + fd = open(file, O_RDWR|O_CREAT|O_TRUNC, 0600); + if( fd > 0 ) + close(fd); + return 0; +} diff --git a/xar/lib/stat.h b/xar/lib/stat.h new file mode 100644 index 0000000..43540a6 --- /dev/null +++ b/xar/lib/stat.h @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2005-2007 Rob Braun + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Rob Braun nor the names of his contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +/* + * 03-Apr-2005 + * DRI: Rob Braun + */ +/* + * Portions Copyright 2006, Apple Computer, Inc. + * Christopher Ryan +*/ + +#ifndef _XAR_STAT_H_ +#define _XAR_STAT_H_ + +#include "xar.h" + +int32_t xar_stat_archive(xar_t x, xar_file_t f, const char *file, const char *buffer, size_t len); +int32_t xar_stat_extract(xar_t x, xar_file_t f, const char *file, char *buffer, size_t len); +int32_t xar_set_perm(xar_t x, xar_file_t f, const char *file, char *buffer, size_t len); +int32_t xar_flags_extract(xar_t x, xar_file_t f, const char *file, char *buffer, size_t len); + +#endif /* _XAR_STAT_H_ */ diff --git a/xar/lib/strmode.h b/xar/lib/strmode.h new file mode 100644 index 0000000..9d94933 --- /dev/null +++ b/xar/lib/strmode.h @@ -0,0 +1,149 @@ +/*- + * Copyright (c) 1990, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ +#ifndef HAVE_STRMODE +#if defined(LIBC_SCCS) && !defined(lint) +static char sccsid[] = "@(#)strmode.c 8.3 (Berkeley) 8/15/94"; +#endif /* LIBC_SCCS and not lint */ + +#include +#include +#include + +void +strmode(mode, p) + mode_t mode; + char *p; +{ + /* print type */ + switch (mode & S_IFMT) { + case S_IFDIR: /* directory */ + *p++ = 'd'; + break; + case S_IFCHR: /* character special */ + *p++ = 'c'; + break; + case S_IFBLK: /* block special */ + *p++ = 'b'; + break; + case S_IFREG: /* regular */ + *p++ = '-'; + break; + case S_IFLNK: /* symbolic link */ + *p++ = 'l'; + break; + case S_IFSOCK: /* socket */ + *p++ = 's'; + break; +#ifdef S_IFIFO + case S_IFIFO: /* fifo */ + *p++ = 'p'; + break; +#endif +#ifdef S_IFWHT + case S_IFWHT: /* whiteout */ + *p++ = 'w'; + break; +#endif + default: /* unknown */ + *p++ = '?'; + break; + } + /* usr */ + if (mode & S_IRUSR) + *p++ = 'r'; + else + *p++ = '-'; + if (mode & S_IWUSR) + *p++ = 'w'; + else + *p++ = '-'; + switch (mode & (S_IXUSR | S_ISUID)) { + case 0: + *p++ = '-'; + break; + case S_IXUSR: + *p++ = 'x'; + break; + case S_ISUID: + *p++ = 'S'; + break; + case S_IXUSR | S_ISUID: + *p++ = 's'; + break; + } + /* group */ + if (mode & S_IRGRP) + *p++ = 'r'; + else + *p++ = '-'; + if (mode & S_IWGRP) + *p++ = 'w'; + else + *p++ = '-'; + switch (mode & (S_IXGRP | S_ISGID)) { + case 0: + *p++ = '-'; + break; + case S_IXGRP: + *p++ = 'x'; + break; + case S_ISGID: + *p++ = 'S'; + break; + case S_IXGRP | S_ISGID: + *p++ = 's'; + break; + } + /* other */ + if (mode & S_IROTH) + *p++ = 'r'; + else + *p++ = '-'; + if (mode & S_IWOTH) + *p++ = 'w'; + else + *p++ = '-'; + switch (mode & (S_IXOTH | S_ISVTX)) { + case 0: + *p++ = '-'; + break; + case S_IXOTH: + *p++ = 'x'; + break; + case S_ISVTX: + *p++ = 'T'; + break; + case S_IXOTH | S_ISVTX: + *p++ = 't'; + break; + } + *p++ = ' '; /* will be a '+' if ACL's implemented */ + *p = '\0'; +} +#endif /* HAVE_STRMODE */ diff --git a/xar/lib/subdoc.c b/xar/lib/subdoc.c new file mode 100644 index 0000000..0e661b4 --- /dev/null +++ b/xar/lib/subdoc.c @@ -0,0 +1,218 @@ +/* + * Copyright (c) 2005-2007 Rob Braun + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Rob Braun nor the names of his contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +/* + * 04-Apr-2005 + * DRI: Rob Braun + */ + +#define _FILE_OFFSET_BITS 64 + +#include +#include +#include +#include +#include +#include "xar.h" +#include "subdoc.h" +#include "archive.h" +#include "filetree.h" + +xar_subdoc_t xar_subdoc_new(xar_t x, const char *name) { + xar_subdoc_t ret; + + if( xar_subdoc_find(x, name) ) + return NULL; + + ret = malloc(sizeof(struct __xar_subdoc_t)); + if( ! ret ) + return NULL; + + memset(XAR_SUBDOC(ret), 0, sizeof(struct __xar_subdoc_t)); + XAR_SUBDOC(ret)->name = strdup(name); + XAR_SUBDOC(ret)->next = XAR_SUBDOC(XAR(x)->subdocs); + XAR(x)->subdocs = ret; + XAR_SUBDOC(ret)->x = x; + + return ret; +} + +int32_t xar_subdoc_prop_set(xar_subdoc_t s, const char *key, const char *value){ + return xar_prop_set((xar_file_t)s, key, value); +} + +int32_t xar_subdoc_prop_get(xar_subdoc_t s, const char *key, const char **value) { + return xar_prop_get((xar_file_t)s, key, value); +} + +int32_t xar_subdoc_attr_set(xar_subdoc_t s, const char *prop, const char *key, const char *value){ + return xar_attr_set((xar_file_t)s, prop, key, value); +} + +const char *xar_subdoc_attr_get(xar_subdoc_t s, const char *prop, const char *key) { + return xar_attr_get((xar_file_t)s, prop, key); +} + +xar_subdoc_t xar_subdoc_first(xar_t x) { + return XAR(x)->subdocs; +} + +xar_subdoc_t xar_subdoc_next(xar_subdoc_t s) { + return XAR_SUBDOC(s)->next; +} + +const char *xar_subdoc_name(xar_subdoc_t s) { + return XAR_SUBDOC(s)->name; +} + +xar_subdoc_t xar_subdoc_find(xar_t x, const char *name) +{ + xar_subdoc_t i; + + for(i = XAR(x)->subdocs; i; i = XAR_SUBDOC(i)->next) { + if( strcmp(name, XAR_SUBDOC(i)->name) == 0 ) + return i; + } + + return NULL; +} + +int32_t xar_subdoc_copyout(xar_subdoc_t s, unsigned char **ret, unsigned int *size) { + xmlBufferPtr buf; + xmlTextWriterPtr writer; + + buf = xmlBufferCreate(); + if( !buf ) + return -1; + + writer = xmlNewTextWriterMemory(buf, 0); + if( !writer ) { + xmlBufferFree(buf); + return -1; + } + + xmlTextWriterSetIndent(writer, 4); + xar_subdoc_serialize(s, writer, 0); + + xmlTextWriterEndDocument(writer); + xmlFreeTextWriter(writer); + + if( size != NULL ) + *size = buf->use; + *ret = malloc(buf->size); + if( *ret == NULL ) { + xmlBufferFree(buf); + return -1; + } + + assert(size != NULL); + memcpy(*ret, buf->content, *size); + xmlBufferFree(buf); + return 0; +} + +int32_t xar_subdoc_copyin(xar_subdoc_t s, const unsigned char *buf, unsigned int len) { + xmlTextReaderPtr reader; + + reader = xmlReaderForMemory((const char *)buf, len, NULL, NULL, 0); + if( !reader ) + return -1; + + xar_subdoc_unserialize(s, reader); + xmlFreeTextReader(reader); + return 0; +} + +/* xar_subdoc_serialize + * s: a subdoc structure allocated and initialized by xar_subdoc_new() + * writer: and xmlTextWriterPtr that has already been opend and initialized + * and is pointing to the place where the subdocument will be serialized. + * wrap: an integer describing whether the subdocument is to be wrapped + * for placement in the xml header of an archive, or if we are trying to + * reconstruct the original document. 1 for wrapping, 0 for original. + */ +void xar_subdoc_serialize(xar_subdoc_t s, xmlTextWriterPtr writer, int wrap) { + if( !s ) return; + if( wrap ) { + xmlTextWriterStartElementNS(writer, BAD_CAST(XAR_SUBDOC(s)->prefix), BAD_CAST("subdoc"), BAD_CAST(XAR_SUBDOC(s)->ns)); + xmlTextWriterWriteAttribute(writer, BAD_CAST("subdoc_name"), BAD_CAST(XAR_SUBDOC(s)->name)); + if( XAR_SUBDOC(s)->value ) + xmlTextWriterWriteString(writer, BAD_CAST(XAR_SUBDOC(s)->value)); + } + xar_prop_serialize(XAR_SUBDOC(s)->props, writer); + xmlTextWriterEndElement(writer); +} + +void xar_subdoc_remove(xar_subdoc_t s) { + xar_prop_t p; + xar_subdoc_t tmp = xar_subdoc_first(XAR_SUBDOC(s)->x); + + if( tmp == s ) { + XAR(XAR_SUBDOC(s)->x)->subdocs = XAR_SUBDOC(s)->next; + } else { + while(XAR_SUBDOC(tmp)->next) { + if( XAR_SUBDOC(tmp)->next == s ) { + XAR_SUBDOC(tmp)->next = XAR_SUBDOC(s)->next; + break; + } + tmp = xar_subdoc_next(tmp); + } + } + + while(XAR_SUBDOC(s)->props) { + p = XAR_SUBDOC(s)->props; + XAR_SUBDOC(s)->props = XAR_PROP(XAR_PROP(p)->next); + xar_prop_free(p); + } + free((char *)XAR_SUBDOC(s)->blank1); + free((char *)XAR_SUBDOC(s)->name); + free((void *)s); + return; +} + +void xar_subdoc_unserialize(xar_subdoc_t s, xmlTextReaderPtr reader) { + int type; + + while( xmlTextReaderRead(reader) == 1 ) { + type = xmlTextReaderNodeType(reader); + if( type == XML_READER_TYPE_ELEMENT ) { + xar_prop_unserialize((xar_file_t)s, NULL, reader); + } + if( type == XML_READER_TYPE_TEXT ) { + const char *value; + value = (const char *)xmlTextReaderConstValue(reader); + free((char*)XAR_SUBDOC(s)->value); + XAR_SUBDOC(s)->value = strdup(value); + } + if( type == XML_READER_TYPE_END_ELEMENT ) { + break; + } + } + + return; +} diff --git a/xar/lib/subdoc.h b/xar/lib/subdoc.h new file mode 100644 index 0000000..2b733ff --- /dev/null +++ b/xar/lib/subdoc.h @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2005-2007 Rob Braun + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Rob Braun nor the names of his contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +/* + * 03-Apr-2005 + * DRI: Rob Braun + */ + +#ifndef _XAR_SUBDOC_H_ +#define _XAR_SUBDOC_H_ + +#include "xar.h" +#include "filetree.h" + +struct __xar_subdoc_t { + struct __xar_prop_t *props; + struct __xar_attr_t *attrs; + const char *prefix; + const char *ns; + const char *blank1; /* filler for xar_file_t compatibility */ + const char *blank2; /* filler for xar_file_t compatibility */ + const char blank3; /* filler for xar_file_t compatibility */ + const char *name; + struct __xar_subdoc_t *next; + const char *value; /* a subdoc should very rarely have a value */ + xar_t x; +}; + +#define XAR_SUBDOC(x) ((struct __xar_subdoc_t *)(x)) + +void xar_subdoc_unserialize(xar_subdoc_t s, xmlTextReaderPtr reader); +void xar_subdoc_serialize(xar_subdoc_t s, xmlTextWriterPtr writer, int wrap); +void xar_subdoc_free(xar_subdoc_t s); +xar_subdoc_t xar_subdoc_find(xar_t x, const char *name); + +#endif /* _XAR_SUBDOC_H_ */ diff --git a/xar/lib/util.c b/xar/lib/util.c new file mode 100644 index 0000000..b9b001d --- /dev/null +++ b/xar/lib/util.c @@ -0,0 +1,466 @@ +/* + * Copyright (c) 2005-2007 Rob Braun + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Rob Braun nor the names of his contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +/* + * 03-Apr-2005 + * DRI: Rob Braun + */ +/* + * Portions Copyright 2006, Apple Computer, Inc. + * Christopher Ryan +*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "config.h" +#ifndef HAVE_ASPRINTF +#include "asprintf.h" +#endif +#include "xar.h" +#include "archive.h" +#include "filetree.h" + + +// SC: This is function is a exact copy of dirname BUT instead of +// just using the same buffer over and over again, we allocate one. +// This means the result needs to be freed, but it also means the +// result will be correct. +char *xar_safe_dirname(const char *path) +{ + char *dname = malloc(MAXPATHLEN); + size_t len; + const char *endp; + + /* Empty or NULL string gets treated as "." */ + if (path == NULL || *path == '\0') { + dname[0] = '.'; + dname[1] = '\0'; + return (dname); + } + /* Strip any trailing slashes */ + endp = path + strlen(path) - 1; + while (endp > path && *endp == '/') + endp--; + /* Find the start of the dir */ + while (endp > path && *endp != '/') + endp--; + /* Either the dir is "/" or there are no slashes */ + if (endp == path) { + dname[0] = *endp == '/' ? '/' : '.'; + dname[1] = '\0'; + return (dname); + } else { + /* Move forward past the separating slashes */ + do { + endp--; + } while (endp > path && *endp == '/'); + } + len = endp - path + 1; + if (len >= MAXPATHLEN) { + errno = ENAMETOOLONG; + free(dname); + return (NULL); + } + memcpy(dname, path, len); + dname[len] = '\0'; + return (dname); +} + + +uint64_t xar_ntoh64(uint64_t num) { + int t = 1234; + union conv { + uint64_t i64; + uint32_t i32[2]; + } *in, out; + + if( ntohl(t) == t ) { + out.i64 = num; + return out.i64; + } + in = (union conv *)# + out.i32[1] = ntohl(in->i32[0]); + out.i32[0] = ntohl(in->i32[1]); + return(out.i64); +} + +uint32_t xar_swap32(uint32_t num) { + uint8_t *one, *two; + uint32_t ret; + + two = (uint8_t *)&ret; + one = (uint8_t *)# + two[3] = one[0]; + two[2] = one[1]; + two[1] = one[2]; + two[0] = one[3]; + + return ret; +} + +/* xar_get_path + * Summary: returns the archive path of the file f. + * Caller needs to free the return value. + */ +char *xar_get_path(xar_file_t f) { + char *ret, *tmp; + const char *name; + xar_file_t i; + + xar_prop_get(f, "name", &name); + if( name == NULL ) { + return NULL; + } + + ret = strdup(name); + for(i = XAR_FILE(f)->parent; i; i = XAR_FILE(i)->parent) { + const char *name; + xar_prop_get(i, "name", &name); + tmp = ret; + asprintf(&ret, "%s/%s", name, tmp); + free(tmp); + } + + return ret; +} + +off_t xar_get_heap_offset(xar_t x) { + return XAR(x)->toc_count + sizeof(xar_header_t); +} + +/* xar_read_fd + * Summary: Reads from a file descriptor a certain number of bytes to a specific + * buffer. This simple wrapper just handles certain retryable error situations. + * Returns -1 when it fails fatally; the number of bytes read otherwise. + */ +ssize_t xar_read_fd( int fd, void * buffer, size_t nbyte ) { + ssize_t rb; + ssize_t total = 0; + + while ( total < nbyte ) { + rb = read(fd, ((char *)buffer)+total, nbyte-total); + if( rb == 0 ) { + return total; + } else if( rb < 0 ) { + if( (errno == EINTR) || (errno == EAGAIN) ) + continue; + return rb; + } + total += rb; + } + + return total; +} + +/* xar_pread_fd + * Summary: Does the same as xar_read_fd, but uses pread(2) instead of read(2). + */ +ssize_t xar_pread_fd(int fd, void * buffer, size_t nbyte, off_t offset) { + ssize_t rb; + ssize_t total = 0; + + while ( total < nbyte ) { + rb = pread(fd, ((char *)buffer)+total, nbyte-total, offset+total); + if( rb == 0 ) { + return total; + } else if( rb < 0 ) { + if( (errno == EINTR) || (errno == EAGAIN) ) + continue; + return rb; + } + total += rb; + } + + return total; +} + +/* xar_write_fd + * Summary: Writes from a buffer to a file descriptor. Like xar_read_fd it + * also just handles certain retryable error situations. + * Returns -1 when it fails fatally; the number of bytes written otherwise. + */ +ssize_t xar_write_fd( int fd, void * buffer, size_t nbyte ) { + ssize_t rb; + ssize_t total = 0; + + while ( total < nbyte ) { + rb = write(fd, ((char *)buffer)+total, nbyte-total); + if( rb == 0 ) { + return total; + } else if( rb < 0 ) { + if( (errno == EINTR) || (errno == EAGAIN) ) + continue; + return rb; + } + total += rb; + } + + return total; +} + +/* xar_pwrite_fd + * Summary: Does the same as xar_write_fd, but uses pwrite(2) instead of write(2). + */ +ssize_t xar_pwrite_fd( int fd, void * buffer, size_t nbyte, off_t offset ) { + ssize_t rb; + size_t total = 0; + + while( total < nbyte ) { + rb = pwrite(fd, ((char *)buffer)+total, nbyte-total, offset+total); + if( rb == 0 ) { + return total; + } else if( rb < 0 ) { + if( (errno == EINTR) || (errno == EAGAIN) ) + continue; + return rb; + } + total += rb; + } + + return total; +} + +dev_t xar_makedev(uint32_t major, uint32_t minor) +{ +#ifdef makedev + return makedev(major, minor); +#else + return (major << 8) | minor; +#endif +} + +void xar_devmake(dev_t dev, uint32_t *out_major, uint32_t *out_minor) +{ +#ifdef major + *out_major = major(dev); +#else + *out_major = (dev >> 8) & 0xFF; +#endif +#ifdef minor + *out_minor = minor(dev); +#else + *out_minor = dev & 0xFF; +#endif + return; +} + +char* xar_path_nextcomponent(char** path_to_advance) { + char* component_start = *path_to_advance; + unsigned int component_length = 1; + char* out_component = NULL; + + if (**path_to_advance == '\0') // If we're trying to look at the end of the path, punt + return NULL; + + for (; **path_to_advance && (**path_to_advance != '/'); ++(*path_to_advance), ++component_length) { + if (**path_to_advance == '\\') { // Escape ignores next char + ++(*path_to_advance); + ++component_length; + continue; + } + } + + if (**path_to_advance == '/') { + ++(*path_to_advance); + } + + out_component = (char*)malloc(component_length); + strncpy(out_component, component_start, component_length); + + out_component[component_length-1] = 0; + + return out_component; +} + + +int xar_path_issane(char* path) { + char* path_walker = path; + char* component = NULL; + int path_depth = 0; + + if (path == NULL) { + return 0; + } + + // Ban 0 length / absolute paths. + if (strlen(path) == 0 || path[0] == '/') + return 0; + + while ((component = xar_path_nextcomponent(&path_walker))) { + + if (strlen(component) == 0 || strcmp(component, ".") == 0) { // Since // is legal, and '.' is legal it's possible to have empty path elements. Ignore them + free(component); + continue; + } + + if (strcmp(component, "..")) + ++path_depth; + else + --path_depth; + + free(component); + + if (path_depth < 0) // We've escaped our root, this path is not sane. + return 0; + } + + return 1; +} + + +#ifndef HAVE_STRMODE +#include "strmode.h" +#endif + +char *xar_get_type(xar_t x, xar_file_t f) { + const char *type = NULL; + xar_prop_get(f, "type", &type); + if( type == NULL ) + type = "unknown"; + return strdup(type); +} + +char *xar_get_size(xar_t x, xar_file_t f) { + const char *size = NULL; + const char *type = NULL; + + xar_prop_get(f, "type", &type); + if( type != NULL ) { + if( strcmp(type, "hardlink") == 0 ) { + const char *link = NULL; + link = xar_attr_get(f, "type", "link"); + if( link ) { + if( strcmp(link, "original") != 0 ) { + xar_iter_t i; + i = xar_iter_new(); + if( i ) { + xar_file_t tmpf; + for(tmpf = xar_file_first(x, i); tmpf; tmpf = xar_file_next(i)) { + const char *id; + id = xar_attr_get(tmpf, NULL, "id"); + if( !id ) continue; + if( strcmp(id, link) == 0 ) { + f = tmpf; + break; + } + } + } + xar_iter_free(i); + } + } + } + } + xar_prop_get(f, "data/size", &size); + if( size == NULL ) + size = "0"; + return strdup(size); +} + +char *xar_get_mode(xar_t x, xar_file_t f) { + const char *mode = NULL; + const char *type = NULL; + char *ret; + mode_t m; + xar_prop_get(f, "mode", &mode); + if( mode == NULL ) + return strdup("??????????"); + errno = 0; + m = strtoll(mode, 0, 8); + if( errno ) + return strdup("??????????"); + + xar_prop_get(f, "type", &type); + if( type == NULL ) + return strdup("??????????"); + + if( strcmp(type, "file") == 0 ) + m |= S_IFREG; + else if( strcmp(type, "hardlink") == 0 ) + m |= S_IFREG; + else if( strcmp(type, "directory") == 0 ) + m |= S_IFDIR; + else if( strcmp(type, "symlink") == 0 ) + m |= S_IFLNK; + else if( strcmp(type, "fifo") == 0 ) + m |= S_IFIFO; + else if( strcmp(type, "character special") == 0 ) + m |= S_IFCHR; + else if( strcmp(type, "block special") == 0 ) + m |= S_IFBLK; + else if( strcmp(type, "socket") == 0 ) + m |= S_IFSOCK; +#ifdef S_IFWHT + else if( strcmp(type, "whiteout") == 0 ) + m |= S_IFWHT; +#endif + + ret = calloc(12,1); + strmode(m, ret); + + return ret; +} + +char *xar_get_owner(xar_t x, xar_file_t f) { + const char *user = NULL; + + xar_prop_get(f, "user", &user); + if( !user ) + return strdup("unknown"); + return strdup(user); +} + +char *xar_get_group(xar_t x, xar_file_t f) { + const char *group = NULL; + + xar_prop_get(f, "group", &group); + if( !group ) + return strdup("unknown"); + return strdup(group); +} + +char *xar_get_mtime(xar_t x, xar_file_t f) { + const char *mtime = NULL; + char *tmp; + struct tm tm; + + xar_prop_get(f, "mtime", &mtime); + if( !mtime ) + mtime = "1970-01-01T00:00:00Z"; + + strptime(mtime, "%FT%T", &tm); + tmp = calloc(128,1); + strftime(tmp, 127, "%F %T", &tm); + return tmp; +} diff --git a/xar/lib/util.h b/xar/lib/util.h new file mode 100644 index 0000000..f434fa3 --- /dev/null +++ b/xar/lib/util.h @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2005-2007 Rob Braun + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Rob Braun nor the names of his contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +/* + * 03-Apr-2005 + * DRI: Rob Braun + */ +/* + * Portions Copyright 2006, Apple Computer, Inc. + * Christopher Ryan + * Steven Cento +*/ + +#ifndef _XAR_UTIL_H_ +#define _XAR_UTIL_H_ + +#include +#include "xar.h" + + +uint64_t xar_ntoh64(uint64_t num); +uint32_t xar_swap32(uint32_t num); +char *xar_get_path(xar_file_t f); +off_t xar_get_heap_offset(xar_t x); +ssize_t xar_read_fd(int fd, void * buffer, size_t nbyte); +ssize_t xar_pread_fd(int fd, void * buffer, size_t nbyte, off_t offset); +ssize_t xar_write_fd(int fd, void * buffer, size_t nbyte); +ssize_t xar_pwrite_fd( int fd, void * buffer, size_t nbyte, off_t offset ); +dev_t xar_makedev(uint32_t major, uint32_t minor); +void xar_devmake(dev_t dev, uint32_t *major, uint32_t *minor); +char* xar_safe_dirname(const char* path); + +// This is used to check to see if a given path escapes from +// the extraction root. +int xar_path_issane(char* path); + +// Returns a string containing the name of the next path component in path_to_advance. +// Path to advance also gets moved forward to the start of the next component in the path. +// The returned string must be released by the caller. +char* xar_path_nextcomponent(char** path_to_advance); + + +#endif /* _XAR_UTIL_H_ */ diff --git a/xar/lib/zxar.c b/xar/lib/zxar.c new file mode 100644 index 0000000..a6b49dc --- /dev/null +++ b/xar/lib/zxar.c @@ -0,0 +1,263 @@ +/* + * Copyright (c) 2005-2007 Rob Braun + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Rob Braun nor the names of his contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +/* + * 03-Apr-2005 + * DRI: Rob Braun + */ +/* + * Portions Copyright 2006, Apple Computer, Inc. + * Christopher Ryan +*/ + + +#include "config.h" +#ifndef HAVE_ASPRINTF +#include "asprintf.h" +#endif +#include +#include +#include +#include +#include +#include +#include "xar.h" +#include "filetree.h" +#include "io.h" + +struct _gzip_context{ + uint8_t gzipcompressed; + uint64_t count; + z_stream z; +}; + +#define GZIP_CONTEXT(x) ((struct _gzip_context *)(*x)) + +int xar_gzip_fromheap_done(xar_t x, xar_file_t f, xar_prop_t p, void **context) { + + if( !context || !GZIP_CONTEXT(context) ) + return 0; + + if( GZIP_CONTEXT(context)->gzipcompressed){ + inflateEnd(&GZIP_CONTEXT(context)->z); + } + + /* free the context */ + free(GZIP_CONTEXT(context)); + *context = NULL; + + return 0; +} + +int xar_gzip_fromheap_in(xar_t x, xar_file_t f, xar_prop_t p, void **in, size_t *inlen, void **context) { + const char *opt; + void *out = NULL; + size_t outlen, offset = 0; + int r; + xar_prop_t tmpp; + + /* on first run, we init the context and check the compression type */ + if( !GZIP_CONTEXT(context) ) { + *context = calloc(1,sizeof(struct _gzip_context)); + + opt = NULL; + tmpp = xar_prop_pget(p, "encoding"); + if( tmpp ) + opt = xar_attr_pget(f, tmpp, "style"); + if( !opt ) return 0; + if( strcmp(opt, "application/x-gzip") != 0 ) return 0; + + inflateInit(&GZIP_CONTEXT(context)->z); + GZIP_CONTEXT(context)->gzipcompressed = 1; + }else if( !GZIP_CONTEXT(context)->gzipcompressed ){ + /* once the context has been initialized, then we have already + checked the compression type, so we need only check if we + actually are compressed */ + return 0; + } + + outlen = *inlen; + + GZIP_CONTEXT(context)->z.next_in = *in; + GZIP_CONTEXT(context)->z.avail_in = *inlen; + GZIP_CONTEXT(context)->z.next_out = out; + GZIP_CONTEXT(context)->z.avail_out = 0; + + while( GZIP_CONTEXT(context)->z.avail_in != 0 ) { + size_t newlen = outlen * 2; + if (newlen > outlen) + outlen = newlen; + else + abort(); /* Someone has somehow malloced over 2^64 bits of ram. */ + + out = realloc(out, outlen); + if( out == NULL ) abort(); + + GZIP_CONTEXT(context)->z.next_out = ((unsigned char *)out) + offset; + GZIP_CONTEXT(context)->z.avail_out = outlen - offset; + + size_t start_avail_in = GZIP_CONTEXT(context)->z.avail_in; + size_t start_avail_out = GZIP_CONTEXT(context)->z.avail_out; + + r = inflate(&(GZIP_CONTEXT(context)->z), Z_NO_FLUSH); + if( (r != Z_OK) && (r != Z_STREAM_END) ) { + xar_err_new(x); + xar_err_set_file(x, f); + xar_err_set_string(x, "Error decompressing file"); + xar_err_callback(x, XAR_SEVERITY_FATAL, XAR_ERR_ARCHIVE_EXTRACTION); + return -1; + } + + offset += outlen - offset - GZIP_CONTEXT(context)->z.avail_out; + + } + + free(*in); + *in = out; + *inlen = offset; + return 0; +} + +int xar_gzip_toheap_done(xar_t x, xar_file_t f, xar_prop_t p, void **context) { + xar_prop_t tmpp; + + if( GZIP_CONTEXT(context)->gzipcompressed){ + deflateEnd(&GZIP_CONTEXT(context)->z); + + if( GZIP_CONTEXT(context)->count ) { + tmpp = xar_prop_pset(f, p, "encoding", NULL); + if( tmpp ) + xar_attr_pset(f, tmpp, "style", "application/x-gzip"); + } + } + + /* free the context */ + free(GZIP_CONTEXT(context)); + *context = NULL; + + return 0; +} + +int32_t xar_gzip_toheap_in(xar_t x, xar_file_t f, xar_prop_t p, void **in, size_t *inlen, void **context) { + void *out = NULL; + size_t outlen, offset = 0; + int r; + const char *opt; + + /* on first run, we init the context and check the compression type */ + if( !GZIP_CONTEXT(context) ) { + int level = Z_BEST_COMPRESSION; + *context = calloc(1,sizeof(struct _gzip_context)); + + opt = xar_opt_get(x, XAR_OPT_COMPRESSION); + if( !opt ) + return 0; + + if( strcmp(opt, XAR_OPT_VAL_GZIP) != 0 ) + return 0; + + opt = xar_opt_get(x, XAR_OPT_COMPRESSIONARG); + if( opt ) { + int tmp; + errno = 0; + tmp = strtol(opt, NULL, 10); + if( errno == 0 ) { + if( (level >= 0) && (level <= 9) ) + level = tmp; + } + } + + deflateInit(&GZIP_CONTEXT(context)->z, level); + GZIP_CONTEXT(context)->gzipcompressed = 1; + if( *inlen == 0 ) + return 0; + }else if( !GZIP_CONTEXT(context)->gzipcompressed ){ + /* once the context has been initialized, then we have already + checked the compression type, so we need only check if we + actually are compressed */ + return 0; + } + + outlen = *inlen/2; + if(outlen == 0) outlen = 1024; + GZIP_CONTEXT(context)->z.next_in = *in; + GZIP_CONTEXT(context)->z.avail_in = *inlen; + GZIP_CONTEXT(context)->z.next_out = out; + GZIP_CONTEXT(context)->z.avail_out = 0; + + if( *inlen != 0 ) { + do { + size_t newlen = outlen * 2; + if (newlen > outlen) + outlen = newlen; + else + abort(); /* Someone has somehow malloced over 2^64 bits of ram. */ + + out = realloc(out, outlen); + if( out == NULL ) abort(); + + GZIP_CONTEXT(context)->z.next_out = ((unsigned char *)out) + offset; + GZIP_CONTEXT(context)->z.avail_out = outlen - offset; + + r = deflate(&GZIP_CONTEXT(context)->z, Z_NO_FLUSH); + offset = outlen - GZIP_CONTEXT(context)->z.avail_out; + } while( r == Z_OK && GZIP_CONTEXT(context)->z.avail_in != 0 ); + } else { + do { + size_t newlen = outlen * 2; + if (newlen > outlen) + outlen = newlen; + else + abort(); /* Someone has somehow malloced over 2^64 bits of ram. */ + + out = realloc(out, outlen); + if( out == NULL ) abort(); + + GZIP_CONTEXT(context)->z.next_out = ((unsigned char *)out) + offset; + GZIP_CONTEXT(context)->z.avail_out = outlen - offset; + + r = deflate(&GZIP_CONTEXT(context)->z, Z_FINISH); + offset = outlen - GZIP_CONTEXT(context)->z.avail_out; + } while( r == Z_OK && r != Z_STREAM_END /* no-op */); + } + + if( (r != Z_OK && r != Z_STREAM_END) ) { + xar_err_new(x); + xar_err_set_file(x, f); + xar_err_set_string(x, "Error compressing file"); + xar_err_set_errno(x, r); + xar_err_callback(x, XAR_SEVERITY_FATAL, XAR_ERR_ARCHIVE_CREATION); + return -1; + } + + free(*in); + *in = out; + GZIP_CONTEXT(context)->count += *inlen; + *inlen = offset; + return 0; +} diff --git a/xar/lib/zxar.h b/xar/lib/zxar.h new file mode 100644 index 0000000..9e68fb0 --- /dev/null +++ b/xar/lib/zxar.h @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2005-2007 Rob Braun + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Rob Braun nor the names of his contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +/* + * 03-Apr-2005 + * DRI: Rob Braun + */ +/* + * Portions Copyright 2006, Apple Computer, Inc. + * Christopher Ryan +*/ + +#ifndef _XAR_ZLIB_H_ +#define _XAR_ZLIB_H_ + +int xar_gzip_fromheap_in(xar_t x, xar_file_t f, xar_prop_t p, void **in, size_t *inlen, void **context); +int xar_gzip_fromheap_done(xar_t x, xar_file_t f, xar_prop_t p, void **context); + +int32_t xar_gzip_toheap_in(xar_t x, xar_file_t f, xar_prop_t p, void **in, size_t *inlen, void **context); +int xar_gzip_toheap_done(xar_t x, xar_file_t f, xar_prop_t p, void **context); +#endif /* _XAR_ZLIB_H_ */ diff --git a/xar/src/.cvsignore b/xar/src/.cvsignore new file mode 100644 index 0000000..4f731ab --- /dev/null +++ b/xar/src/.cvsignore @@ -0,0 +1,4 @@ +Makefile.inc +ixar +xar +*.d diff --git a/xar/src/Makefile.inc b/xar/src/Makefile.inc new file mode 100644 index 0000000..f97f635 --- /dev/null +++ b/xar/src/Makefile.inc @@ -0,0 +1,65 @@ +# +# Include generated dependency files. +# +XAR_SRCS := xar.c +XAR_SRCS := $(patsubst %, src/%, $(XAR_SRCS)) +-include $(XAR_SRCS:%.c=%.d) + +src_all : src/xar src/ixar + +src_install : src/ixar + .././install-sh -c -d $(DESTDIR)$(BINDIR) + .././install-sh -c -m 0755 $< $(DESTDIR)$(BINDIR)/xar + .././install-sh -c -d $(DESTDIR)$(MANDIR)/man1 + .././install-sh -c -m 0644 src/xar.1 $(DESTDIR)$(MANDIR)/man1 + +src_uninstall : + rm -f $(DESTDIR)/$(BINDIR)/xar + rm -f $(DESTDIR)/$(MANDIR)/man1/xar.1 + +src_clean : + rm -f src/xar + rm -f src/ixar + rm -f $(XAR_SRCS:%.c=%.o) + rm -f $(XAR_SRCS:%.c=%.d) + +src_distclean : + + +ifeq (yes, yes) +LIBRXAR := $(LIBRXAR_S) +endif +ifeq (yes, yes) +LIBRXAR := $(LIBXAR_A) +endif + +# xar links against librxar, so that it can be run without first installing +# libxar. +src/% : src/%.o $(LIBRXAR) + @mkdir -p $(@D) +ifneq ($(words "" ), 1) + $(CC) $(CFLAGS) -o $@ $< /Users/ariel/LinuxHome/code/darling/src/xar/xar/lib $(LDFLAGS) $(LIBRXAR) -lpthread -lbz2 -lz -lxml2 -lz -lpthread -licucore -lm +else + $(CC) $(CFLAGS) -o $@ $< $(LDFLAGS) $(LIBRXAR) -lpthread -lbz2 -lz -lxml2 -lz -lpthread -licucore -lm +endif + +ifeq (yes, yes) +LIBXAR := $(LIBXAR_A) +endif +ifeq (yes, yes) +LIBXAR := $(LIBXAR_S) +endif + +# ixar is the version of the xar binary that gets installed. +src/i% : src/%.o $(LIBXAR) + @mkdir -p $(@D) +ifneq ($(words "" ), 1) + $(CC) $(CFLAGS) -o $@ $< $(LIBDIR) $(LDFLAGS) $(LIBXAR) -lpthread -lbz2 -lz -lxml2 -lz -lpthread -licucore -lm +else + $(CC) $(CFLAGS) -o $@ $< $(LDFLAGS) $(LIBXAR) -lpthread -lbz2 -lz -lxml2 -lz -lpthread -licucore -lm +endif + +src/%.o : src/%.c + @mkdir -p $(@D) + $(CC) $(CFLAGS) $(CPPFLAGS) -c $< -o $@ + @$(SHELL) -ec "$(CC) -MM $(CPPFLAGS) $< | sed \"s/\($(subst /,\/,$(notdir $(basename $@)))\)\.o\([ :]*\)/$(subst /,\/,$(strip $(dir $@)))\1.o \2/g\" > $(@:%.o=%.d)" diff --git a/xar/src/Makefile.inc.in b/xar/src/Makefile.inc.in new file mode 100644 index 0000000..a7467df --- /dev/null +++ b/xar/src/Makefile.inc.in @@ -0,0 +1,65 @@ +# +# Include generated dependency files. +# +XAR_SRCS := xar.c +XAR_SRCS := $(patsubst %, @srcroot@src/%, $(XAR_SRCS)) +-include $(XAR_SRCS:@srcroot@%.c=@objroot@%.d) + +src_all : @objroot@src/xar @objroot@src/ixar + +src_install : @objroot@src/ixar + @INSTALL@ -d $(DESTDIR)$(BINDIR) + @INSTALL@ -m 0755 $< $(DESTDIR)$(BINDIR)/xar + @INSTALL@ -d $(DESTDIR)$(MANDIR)/man1 + @INSTALL@ -m 0644 @srcroot@src/xar.1 $(DESTDIR)$(MANDIR)/man1 + +src_uninstall : + rm -f $(DESTDIR)/$(BINDIR)/xar + rm -f $(DESTDIR)/$(MANDIR)/man1/xar.1 + +src_clean : + rm -f @objroot@src/xar + rm -f @objroot@src/ixar + rm -f $(XAR_SRCS:@srcroot@%.c=@objroot@%.o) + rm -f $(XAR_SRCS:@srcroot@%.c=@objroot@%.d) + +src_distclean : + + +ifeq (yes, @shared@) +LIBRXAR := $(LIBRXAR_S) +endif +ifeq (yes, @static@) +LIBRXAR := $(LIBXAR_A) +endif + +# xar links against librxar, so that it can be run without first installing +# libxar. +@objroot@src/% : @objroot@src/%.o $(LIBRXAR) + @mkdir -p $(@D) +ifneq ($(words "" @RPATH@), 1) + $(CC) $(CFLAGS) -o $@ $< @RPATH@@abs_objroot@lib $(LDFLAGS) $(LIBRXAR) @LIBS@ +else + $(CC) $(CFLAGS) -o $@ $< $(LDFLAGS) $(LIBRXAR) @LIBS@ +endif + +ifeq (yes, @static@) +LIBXAR := $(LIBXAR_A) +endif +ifeq (yes, @shared@) +LIBXAR := $(LIBXAR_S) +endif + +# ixar is the version of the xar binary that gets installed. +@objroot@src/i% : @objroot@src/%.o $(LIBXAR) + @mkdir -p $(@D) +ifneq ($(words "" @RPATH@), 1) + $(CC) $(CFLAGS) -o $@ $< @RPATH@$(LIBDIR) $(LDFLAGS) $(LIBXAR) @LIBS@ +else + $(CC) $(CFLAGS) -o $@ $< $(LDFLAGS) $(LIBXAR) @LIBS@ +endif + +@objroot@src/%.o : @srcroot@src/%.c + @mkdir -p $(@D) + $(CC) $(CFLAGS) $(CPPFLAGS) -c $< -o $@ + @$(SHELL) -ec "$(CC) -MM $(CPPFLAGS) $< | sed \"s/\($(subst /,\/,$(notdir $(basename $@)))\)\.o\([ :]*\)/$(subst /,\/,$(strip $(dir $@)))\1.o \2/g\" > $(@:%.o=%.d)" diff --git a/xar/src/xar.1 b/xar/src/xar.1 new file mode 100644 index 0000000..799ebc8 --- /dev/null +++ b/xar/src/xar.1 @@ -0,0 +1,158 @@ +.TH XAR "1" "June 4, 2015" "version 1.8" "User Commands" +.SH NAME +xar \- eXtensible ARchiver +.SH SYNOPSIS +.B xar +\-[\fIctx\fR][\fIv\fR] ... +.SH DESCRIPTION +The XAR project aims to provide an easily extensible archive format. Important +design decisions include an easily extensible XML table of contents (TOC) for +random access to archived files, storing the TOC at the beginning of the +archive to allow for efficient handling of streamed archives, the ability to +handle files of arbitrarily large sizes, the ability to choose independent +encodings for individual files in the archive, the ability to store checksums +for individual files in both compressed and uncompressed form, and the ability +to query the table of content's rich meta-data. +.SH FUNCTIONS +.TP +.B One of the following options must be used: +.TP +\-c +Creates an archive +.TP +\-t +Lists the contents of an archive +.TP +\-x +Extracts an archive +.TP +.B NOTE: all of the above require the use of the -f option (filename) as this release of xar doesn't correctly handle pipes or sockets. +.TP +\-f +The filename to use for creation, listing or extraction. With extraction, this can be a POSIX regular expression. +.SH OPTIONS +.TP +\-\-compression +Specifies the compression type to use. +Valid values: none, gzip, bzip2, lzma (on some systems). Default value: gzip +.TP +\-C +On extract, xar will chdir to the specified path before extracting the archive. +.TP +\-a +Synonym for \-\-compression=lzma +.TP +\-j +Synonym for \-\-compression=bzip2 +.TP +\-z +Synonym for \-\-compression=gzip +.TP +\-\-compression-args= +Specifies arguments to the compression engine selected. +gzip, bzip2, and lzma all take a single integer argument between 0 and 9 specifying the compression level to use. +.TP +\-\-dump\-toc= +Has xar dump the xml header into the specified file. "-" can be specified to mean stdout. +.TP +\-\-dump\-toc\-cksum +Dumps the ToC checksum to stdout along with the algorithm of the ToC. +.TP +\-\-dump\-header +Has xar print out the xar binary header information to stdout. +.TP +\-\-extract\-subdoc= +Extracts the specified subdocument to a document in cwd named .xml +.TP +\-\-list\-subdocs +List the subdocuments in the xml header +.TP +\-\-toc\-cksum +Specifies the hashing algorithm to use for xml header verification. +Valid values: md5 (on some systems), sha1, sha256, and sha512. Default value: sha1 +.TP +\-\-file\-cksum +Specifies the hashing algorithm to use for file content verification. +Valid values: md5 (on some systems), sha1, sha256, and sha512. Default value: sha1 +.TP +\-l +On archival, stay on the local device. +.TP +\-P +On extract, set ownership based on uid/gid. If the uid/gid can be set +on the extracted file, setuid/setgid bits will also be preserved. +.TP +\-p +On extract, set ownership based on symbolic names, if possible. +If the uid/gid can be set on the extracted file, setuid/setgid bits +will also be preserved. +.TP +\-s +On extract, specifies the file to extract subdocuments to. +On archival, specifies an xml file to add as a subdocument. +.TP +\-v +Verbose output +.TP +\-\-exclude +Specifies a POSIX regular expression of files to exclude from adding to +the archive during creation or from being extracted during extraction. +This option can be specified multiple times. +.TP +\-\-rsize +Specifies a size (in bytes) for the internal libxar read buffer while performing I/O. +.TP +\-\-coalesce-heap +When multiple files in the archive are identical, only store one copy of the data in the heap. This creates smaller archives, but the archives created are not streamable. +.TP +\-\-link-same +When the data section of multiple files are identical, hardlink them within the archive. +.TP +\-\-no-compress +Specifies a POSIX regular expression of files to archive, but not compress. The archived files will be copied raw into the archive. This can be used to exclude already gzipped files from being gzipped during the archival process. +.TP +\-\-prop-include +Specifies a file property to be included in the archive. When this option is specified, only the specified options will be included. Anything not specifically included with this option will be omitted. This option can be used multiple times. +.TP +\-\-prop-exclude +Specifies a file property to be excluded from the archive. When this option is specified, all file properties will be included except the specified properties. This option can be used multiple times. +.TP +\-\-distribution +Creates an archive to only contain file properties safe for file distribution. Currently, only name, type, mode, and data are preserved with this option. +.TP +\-\-keep-existing +Does not overwrite existing files during extraction. Keeps any previously existing files while extracting. +.TP +\-k +Synonym for \-\-keep-existing. +.TP +\-\-keep-setuid +When extracting without -p or -P options, xar will extract files as the +uid/gid of the extracting process. In this situation, xar will strip +setuid/setgid bits from the extracted files for security reasons. +\-\-keep-setuid will preserve the setuid/setgid bits even though the +uid/gid of the extracted file is not the same as the archived file. +.SH EXAMPLES +.TP +xar -cf sample.xar /home/uid +Create a xar archive of all files in /home/uid +.TP +xar -tf sample.xar +List the contents of the xar archive sample.xar +.TP +xar -xf sample.xar +Extract the contents of sample.xar to the current working directory +.SH BUGS +.TP +Doesn't currently work with pipes or streams. Might be fixed in a future release. +.TP +Probably one or two more somewhere in there. If you find one please report it to http://code.google.com/p/xar/ +.SH AUTHORS +Rob Braun +.br +Landon Fuller +.br +David Leimbach +.br +Kevin Van Vechten + diff --git a/xar/src/xar.c b/xar/src/xar.c new file mode 100644 index 0000000..c32757e --- /dev/null +++ b/xar/src/xar.c @@ -0,0 +1,1240 @@ +/* + * Copyright (c) 2005 Rob Braun + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Rob Braun nor the names of his contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +/* + * 03-Apr-2005 + * DRI: Rob Braun + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "xar.h" +#include "config.h" +#include "filetree.h" +#include "util.h" +#define SYMBOLIC 1 +#define NUMERIC 2 +static int Perms = 0; +static int Local = 0; +static char *Subdoc = NULL; +static char *SubdocName = NULL; +static char *Toccksum = NULL; +static char *Filecksum = NULL; +static char *Compression = NULL; +static char *Rsize = NULL; +static char *CompressionArg = NULL; +static char *Chdir = NULL; + +static int Err = 0; +static int List = 0; +static int Verbose = 0; +static int Coalesce = 0; +static int LinkSame = 0; +static int NoOverwrite = 0; +static int SaveSuid = 0; + +struct lnode { + char *str; + regex_t reg; + struct lnode *next; +}; + +struct lnode *Exclude = NULL; +struct lnode *Exclude_Tail = NULL; +struct lnode *NoCompress = NULL; +struct lnode *NoCompress_Tail = NULL; +struct lnode *PropInclude = NULL; +struct lnode *PropInclude_Tail = NULL; +struct lnode *PropExclude = NULL; +struct lnode *PropExclude_Tail = NULL; + +static int32_t err_callback(int32_t sev, int32_t err, xar_errctx_t ctx, void *usrctx); + +static void print_file(xar_t x, xar_file_t f) { + if( List && Verbose ) { + char *size = xar_get_size(x, f); + char *path = xar_get_path(f); + char *type = xar_get_type(x, f); + char *mode = xar_get_mode(x, f); + char *user = xar_get_owner(x, f); + char *group = xar_get_group(x, f); + char *mtime = xar_get_mtime(x, f); + printf("%s %8s/%-8s %10s %s %s\n", mode, user, group, size, mtime, path); + free(size); + free(type); + free(path); + free(mode); + free(user); + free(group); + free(mtime); + } else if( List || Verbose ) { + char *path = xar_get_path(f); + + if (xar_path_issane(path) == 0) + printf("Warning, archive contains invalid path: %s\n", path); + else + printf("%s\n", path); + + free(path); + } +} + +static void add_subdoc(xar_t x) { + xar_subdoc_t s; + int fd; + unsigned char *buf; + unsigned int len; + struct stat sb; + + if( SubdocName == NULL ) SubdocName = "subdoc"; + + fd = open(Subdoc, O_RDONLY); + if( fd < 0 ) { + fprintf(stderr, "ERROR: subdoc file %s doesn't exist. Ignoring.\n", Subdoc); + return; + } + s = xar_subdoc_new(x, (const char *)SubdocName); + fstat(fd, &sb); + len = sb.st_size; + buf = malloc(len+1); + if( buf == NULL ) { + close(fd); + return; + } + memset(buf, 0, len+1); + read(fd, buf, len); + close(fd); + + xar_subdoc_copyin(s, buf, len); + + + return; +} + +static void extract_subdoc(xar_t x, const char *name) { + xar_subdoc_t i; + + for( i = xar_subdoc_first(x); i; i = xar_subdoc_next(i) ) { + const char *sname = xar_subdoc_name(i); + unsigned char *sdoc; + int fd, size; + if( name && strcmp(name, sname) != 0 ) + continue; + xar_subdoc_copyout(i, &sdoc, (unsigned int *)&size); + fd = open(Subdoc, O_WRONLY|O_CREAT|O_TRUNC, 0644); + if( fd < 0 ) return; + write(fd, sdoc, size); + close(fd); + free(sdoc); + } + + return; +} + +static int archive(const char *filename, int arglen, char *args[]) { + xar_t x; + FTS *fts; + FTSENT *ent; + int flags; + struct lnode *i; + const char *default_compression; + + x = xar_open(filename, WRITE); + if( !x ) { + fprintf(stderr, "Error creating archive %s\n", filename); + exit(1); + } + + if( Toccksum ) + xar_opt_set(x, XAR_OPT_TOCCKSUM, Toccksum); + + if( Filecksum ) + xar_opt_set(x, XAR_OPT_FILECKSUM, Filecksum); + + if( CompressionArg ) + xar_opt_set(x, XAR_OPT_COMPRESSIONARG, CompressionArg); + + if( Compression ) + xar_opt_set(x, XAR_OPT_COMPRESSION, Compression); + + if( Coalesce ) + xar_opt_set(x, XAR_OPT_COALESCE, "true"); + + if( LinkSame ) + xar_opt_set(x, XAR_OPT_LINKSAME, "true"); + + if ( Rsize != NULL ) + xar_opt_set(x, XAR_OPT_RSIZE, Rsize); + + xar_register_errhandler(x, err_callback, NULL); + + for( i = PropInclude; i; i=i->next ) { + xar_opt_set(x, XAR_OPT_PROPINCLUDE, i->str); + } + for( i = PropExclude; i; i=i->next ) { + xar_opt_set(x, XAR_OPT_PROPEXCLUDE, i->str); + } + + if( Subdoc ) + add_subdoc(x); + + if( Perms == SYMBOLIC ) { + xar_opt_set(x, XAR_OPT_OWNERSHIP, XAR_OPT_VAL_SYMBOLIC); + } + if( Perms == NUMERIC ) { + xar_opt_set(x, XAR_OPT_OWNERSHIP, XAR_OPT_VAL_NUMERIC); + } + + default_compression = strdup(xar_opt_get(x, XAR_OPT_COMPRESSION)); + if( !default_compression ) + default_compression = strdup(XAR_OPT_VAL_GZIP); + + flags = FTS_PHYSICAL|FTS_NOSTAT|FTS_NOCHDIR; + if( Local ) + flags |= FTS_XDEV; + fts = fts_open(args, flags, NULL); + if( !fts ) { + fprintf(stderr, "Error traversing file tree\n"); + exit(1); + } + + while( (ent = fts_read(fts)) ) { + xar_file_t f; + int exclude_match = 1; + int nocompress_match = 1; + if( ent->fts_info == FTS_DP ) + continue; + + if( strcmp(ent->fts_path, "/") == 0 ) + continue; + if( strcmp(ent->fts_path, ".") == 0 ) + continue; + + for( i = Exclude; i; i=i->next ) { + exclude_match = regexec(&i->reg, ent->fts_path, 0, NULL, 0); + if( !exclude_match ) + break; + } + if( !exclude_match ) { + if( Verbose ) + printf("Excluding %s\n", ent->fts_path); + continue; + } + + for( i = NoCompress; i; i=i->next ) { + nocompress_match = regexec(&i->reg, ent->fts_path, 0, NULL, 0); + if( !nocompress_match ) { + xar_opt_set(x, XAR_OPT_COMPRESSION, XAR_OPT_VAL_NONE); + break; + } + } + f = xar_add(x, ent->fts_path); + if( !f ) { + fprintf(stderr, "Error adding file %s\n", ent->fts_path); + } else { + print_file(x, f); + } + if( !nocompress_match ) + xar_opt_set(x, XAR_OPT_COMPRESSION, default_compression); + } + fts_close(fts); + if( xar_close(x) != 0 ) { + fprintf(stderr, "Error creating the archive\n"); + if( !Err ) + Err = 42; + } + + free((char *)default_compression); + for( i = Exclude; i; ) { + struct lnode *tmp; + regfree(&i->reg); + tmp = i; + i = i->next; + free(tmp); + } + for( i = NoCompress; i; ) { + struct lnode *tmp; + regfree(&i->reg); + tmp = i; + i = i->next; + free(tmp); + } + + return Err; +} + +static int extract(const char *filename, int arglen, char *args[]) { + xar_t x; + xar_iter_t iter; + xar_file_t f; + int files_extracted = 0; + int argi; + struct lnode *extract_files = NULL; + struct lnode *extract_tail = NULL; + struct lnode *lnodei = NULL; + struct lnode *dirs = NULL; + + for(argi = 0; args[argi]; argi++) { + struct lnode *tmp; + int err; + tmp = malloc(sizeof(struct lnode)); + tmp->str = strdup(args[argi]); + tmp->next = NULL; + err = regcomp(&tmp->reg, tmp->str, REG_NOSUB); + if( err ) { + char errstr[1024]; + regerror(err, &tmp->reg, errstr, sizeof(errstr)); + printf("Error with regular expression %s: %s\n", tmp->str, errstr); + exit(1); + } + if( extract_files == NULL ) { + extract_files = tmp; + extract_tail = tmp; + } else { + extract_tail->next = tmp; + extract_tail = tmp; + } + + /* Add a clause for recursive extraction */ + tmp = malloc(sizeof(struct lnode)); + asprintf(&tmp->str, "%s/.*", args[argi]); + tmp->next = NULL; + err = regcomp(&tmp->reg, tmp->str, REG_NOSUB); + if( err ) { + char errstr[1024]; + regerror(err, &tmp->reg, errstr, sizeof(errstr)); + printf("Error with regular expression %s: %s\n", tmp->str, errstr); + exit(1); + } + if( extract_files == NULL ) { + extract_files = tmp; + extract_tail = tmp; + } else { + extract_tail->next = tmp; + extract_tail = tmp; + } + } + + x = xar_open(filename, READ); + if( !x ) { + fprintf(stderr, "Error opening xar archive: %s\n", filename); + exit(1); + } + + if(Chdir) { + if( chdir(Chdir) != 0 ) { + fprintf(stderr, "Unable to chdir to %s\n", Chdir); + exit(1); + } + } + + xar_register_errhandler(x, err_callback, NULL); + + if( Perms == SYMBOLIC ) { + xar_opt_set(x, XAR_OPT_OWNERSHIP, XAR_OPT_VAL_SYMBOLIC); + } + if( Perms == NUMERIC ) { + xar_opt_set(x, XAR_OPT_OWNERSHIP, XAR_OPT_VAL_NUMERIC); + } + if ( Rsize != NULL ) { + xar_opt_set(x, XAR_OPT_RSIZE, Rsize); + } + if( SaveSuid ) { + xar_opt_set(x, XAR_OPT_SAVESUID, XAR_OPT_VAL_TRUE); + } + + iter = xar_iter_new(); + if( !iter ) { + fprintf(stderr, "Error creating xar iterator\n"); + exit(1); + } + + for(f = xar_file_first(x, iter); f; f = xar_file_next(iter)) { + int matched = 0; + int exclude_match = 1; + struct lnode *i; + + char *path = xar_get_path(f); + + // Check to see if this file is a symlink + const char* type = NULL; + xar_prop_get(f, "type", &type); + if( type == NULL ) + { + if (Verbose) + printf("Warning, not extracting file \"%s\" because we can't get it's type.\n", path); + free(path); + continue; + } + + // Sanity check if we have a symlink, that it's a valid path. + const char* kSymlinkName = "symlink"; // Why there is no const for this I have no idea. + if (strncmp(kSymlinkName, type, strlen(kSymlinkName)) == 0) + { + if (XAR_FILE(f)->children != NULL) + { + if (Verbose) + printf("Warning, children of \"%s\" will not extract because it's a symlink.\n", path); + + XAR_ITER(iter)->nochild = 1; // Do no extract children of a symlink + } + } + + // This includes a null check + if (!xar_path_issane(path)) { + if (Verbose) + printf("Warning, not extracting file \"%s\" because it's path is invalid.\n", path); + free(path); + continue; + } + + if( args[0] ) { + for(i = extract_files; i != NULL; i = i->next) { + int extract_match = 1; + + extract_match = regexec(&i->reg, path, 0, NULL, 0); + if( !extract_match ) { + matched = 1; + break; + } + } + } else { + matched = 1; + } + + for( i = Exclude; i; i=i->next ) { + exclude_match = regexec(&i->reg, path, 0, NULL, 0); + if( !exclude_match ) + break; + } + if( !exclude_match ) { + if( Verbose ) + printf("Excluding %s\n", path); + free(path); + continue; + } + + if( matched ) { + struct stat sb; + if( NoOverwrite && (lstat(path, &sb) == 0) ) { + printf("%s already exists, not overwriting\n", path); + } else { + const char *prop = NULL; + int deferred = 0; + if( xar_prop_get(f, "type", &prop) == 0 && prop != NULL ) { + if( strcmp(prop, "directory") == 0 ) { + struct lnode *tmpl = calloc(sizeof(struct lnode),1); + tmpl->str = (char *)f; + tmpl->next = dirs; + dirs = tmpl; + deferred = 1; + } + } + if( ! deferred ) { + files_extracted++; + print_file(x, f); + xar_extract(x, f); + } + } + } + free(path); + } + for(lnodei = dirs; lnodei; lnodei = lnodei->next) { + files_extracted++; + print_file(x,(xar_file_t)lnodei->str); + xar_extract(x, (xar_file_t)lnodei->str); + } + if( args[0] && (files_extracted == 0) ) { + fprintf(stderr, "No files matched extraction criteria.\n"); + Err = 3; + } + + if( Subdoc ) + extract_subdoc(x, NULL); + + xar_iter_free(iter); + if( xar_close(x) != 0 ) { + fprintf(stderr, "Error extracting the archive\n"); + if( !Err ) + Err = 42; + } + + for(lnodei = extract_files; lnodei != NULL; ) { + struct lnode *tmp; + free(lnodei->str); + regfree(&lnodei->reg); + tmp = lnodei; + lnodei = lnodei->next; + free(tmp); + } + return Err; +} + +static int list_subdocs(const char *filename) { + xar_t x; + xar_subdoc_t s; + + x = xar_open(filename, READ); + if( !x ) { + fprintf(stderr, "Error opening xar archive: %s\n", filename); + exit(1); + } + + for(s = xar_subdoc_first(x); s; s = xar_subdoc_next(s)) { + printf("%s\n", xar_subdoc_name(s)); + } + xar_close(x); + + return Err; +} + +static int list(const char *filename, int arglen, char *args[]) { + xar_t x; + xar_iter_t i; + xar_file_t f; + int argi = 0; + struct lnode *list_files = NULL; + struct lnode *list_tail = NULL; + struct lnode *lnodei = NULL; + + for(argi = 0; args[argi]; argi++) { + struct lnode *tmp; + int err; + tmp = malloc(sizeof(struct lnode)); + tmp->str = strdup(args[argi]); + tmp->next = NULL; + err = regcomp(&tmp->reg, tmp->str, REG_NOSUB); + if( err ) { + char errstr[1024]; + regerror(err, &tmp->reg, errstr, sizeof(errstr)); + printf("Error with regular expression %s: %s\n", tmp->str, errstr); + exit(1); + } + if( list_files == NULL ) { + list_files = tmp; + list_tail = tmp; + } else { + list_tail->next = tmp; + list_tail = tmp; + } + } + + x = xar_open(filename, READ); + if( !x ) { + fprintf(stderr, "Error opening xar archive: %s\n", filename); + exit(1); + } + + i = xar_iter_new(); + if( !i ) { + fprintf(stderr, "Error creating xar iterator\n"); + exit(1); + } + + for(f = xar_file_first(x, i); f; f = xar_file_next(i)) { + int matched = 0; + + if( args[0] ) { + char *path = xar_get_path(f); + + if (xar_path_issane(path) == 0) { + fprintf(stderr, "Warning, archive contains invalid path: %s\n", path); + free(path); + continue; + } + + for(lnodei = list_files; lnodei != NULL; lnodei = lnodei->next) { + int list_match = 1; + + list_match = regexec(&lnodei->reg, path, 0, NULL, 0); + if( !list_match ) { + matched = 1; + break; + } + } + free(path); + } else { + matched = 1; + } + + if( matched ) + print_file(x, f); + } + + xar_iter_free(i); + xar_close(x); + + for(lnodei = list_files; lnodei != NULL; ) { + struct lnode *tmp; + free(lnodei->str); + regfree(&lnodei->reg); + tmp = lnodei; + lnodei = lnodei->next; + free(tmp); + } + + return Err; +} + +static int dumptoc(const char *filename, const char* tocfile) { + xar_t x; + x = xar_open(filename, READ); + if( !x ) { + fprintf(stderr, "Error opening xar archive: %s\n", filename); + exit(1); + } + + xar_serialize(x, tocfile); + xar_close(x); + return Err; +} + +static int dump_toc_chksum(const char *filename) +{ + xar_t x; + x = xar_open(filename, READ); + if( !x ) { + fprintf(stderr, "Error opening xar archive: %s\n", filename); + exit(1); + } + + // locate data to sign + const char *value; + if( 0 != xar_prop_get((xar_file_t)x, "checksum/offset" ,&value) ) { + fprintf(stderr, "Could not locate checksum/offset in archive.\n"); + exit(1); + } + + uint32_t dataToSignOffset = xar_get_heap_offset(x); + dataToSignOffset += strtoull(value, (char **)NULL, 10); + if( 0 != xar_prop_get((xar_file_t)x, "checksum/size" ,&value) ) { + fprintf(stderr, "Could not locate checksum/size in archive.\n"); + exit(1); + } + + uint32_t dataToSignSize = strtoull(value, (char **)NULL, 10); + xar_close(x); + + // now get data to be signed, using offset and size + FILE *file = fopen(filename, "r"); + if (!file) { + fprintf(stderr, "Could not open %s for reading data to sign!\n", filename); + exit(1); + } + fseek(file, dataToSignOffset, SEEK_SET); + unsigned char *buffer = malloc(dataToSignSize); + int i = fread(buffer, dataToSignSize, 1, file); + if (i != 1) { + fprintf(stderr, "Failed to read data to sign from %s!\n", filename); + exit(1); + } + printf("Checksum: "); + for (int i = 0; i < dataToSignSize; i++) + printf("%02x", buffer[i]); + printf("\n"); + free(buffer); + + xar_header_t xh; + fseek(file, 0, SEEK_SET); + i = fread(&xh, sizeof(xh), 1, file); + + printf("Algorithm: "); + switch( ntohl(xh.cksum_alg) ) { + case XAR_CKSUM_NONE: printf("NONE\n"); + break; + case XAR_CKSUM_SHA1: printf("SHA1\n"); + break; + case XAR_CKSUM_SHA256: printf("SHA256\n"); + break; + case XAR_CKSUM_SHA512: printf("SHA512\n"); + break; + case XAR_CKSUM_MD5: printf("MD5\n"); + break; + default: printf("UNKNOWN\n"); + break; + } + + fflush(stdout); + fclose(file); + + return 0; +} + +static int dump_header(const char *filename) { + int fd; + xar_header_t xh; + + if(filename == NULL) + fd = 0; + else { + fd = open(filename, O_RDONLY); + if( fd < 0 ) { + perror("open"); + exit(1); + } + } + + if( read(fd, &xh, sizeof(xh)) < sizeof(xh) ) { + fprintf(stderr, "error reading header\n"); + exit(1); + } + + printf("magic: 0x%x ", ntohl(xh.magic)); + if( ntohl(xh.magic) != XAR_HEADER_MAGIC ) + printf("(BAD)\n"); + else + printf("(OK)\n"); + printf("size: %d\n", ntohs(xh.size)); + printf("version: %d\n", ntohs(xh.version)); + printf("Compressed TOC length: %" PRId64 "\n", xar_ntoh64(xh.toc_length_compressed)); + printf("Uncompressed TOC length: %" PRId64 "\n", xar_ntoh64(xh.toc_length_uncompressed)); + printf("Checksum algorithm: %d ", ntohl(xh.cksum_alg)); + switch( ntohl(xh.cksum_alg) ) { + case XAR_CKSUM_NONE: printf("(unsupported (none))\n"); + break; + case XAR_CKSUM_SHA1: printf("(SHA1)\n"); + break; + case XAR_CKSUM_SHA256: printf("(SHA256)\n"); + break; + case XAR_CKSUM_SHA512: printf("(SHA512)\n"); + break; +#ifdef XAR_SUPPORT_MD5 + case XAR_CKSUM_MD5: printf("(MD5)\n"); + break; +#else + case XAR_CKSUM_MD5: printf("(unsupported (MD5))\n"); + break; +#endif // XAR_SUPPORT_MD5 + default: printf("(unknown)\n"); + break; + }; + + return 0; +} + +static int32_t err_callback(int32_t sev, int32_t err, xar_errctx_t ctx, void *usrctx) { + xar_file_t f; + xar_t x; + const char *str; + int e; + + x = xar_err_get_archive(ctx); + f = xar_err_get_file(ctx); + str = xar_err_get_string(ctx); + e = xar_err_get_errno(ctx); + + switch(sev) { + case XAR_SEVERITY_DEBUG: + case XAR_SEVERITY_INFO: + break; + case XAR_SEVERITY_WARNING: + printf("%s\n", str); + break; + case XAR_SEVERITY_NORMAL: + if( (err = XAR_ERR_ARCHIVE_CREATION) && f ) + print_file(x, f); + break; + case XAR_SEVERITY_NONFATAL: + case XAR_SEVERITY_FATAL: + Err = 2; + printf("Error while "); + if( err == XAR_ERR_ARCHIVE_CREATION ) printf("creating"); + if( err == XAR_ERR_ARCHIVE_EXTRACTION ) printf("extracting"); + printf(" archive"); + if( f ) { + const char *file = xar_get_path(f); + if( file ) printf(":(%s)", file); + free((char *)file); + } + if( str ) printf(": %s", str); + if( err && e ) printf(" (%s)", strerror(e)); + if( sev == XAR_SEVERITY_NONFATAL ) { + printf(" - ignored"); + printf("\n"); + } else { + printf("\n"); + exit(1); + } + break; + } + return 0; +} + +static void usage(const char *prog) { + fprintf(stderr, "Usage: %s -[ctx][v] -f ...\n", prog); + fprintf(stderr, "\t-c Creates an archive\n"); + fprintf(stderr, "\t-x Extracts an archive\n"); + fprintf(stderr, "\t-t Lists an archive\n"); + fprintf(stderr, "\t-f Specifies an archive to operate on [REQUIRED!]\n"); + fprintf(stderr, "\t-v Print filenames as they are archived\n"); + fprintf(stderr, "\t-C On extract, chdir to this location\n"); + fprintf(stderr, "\t-n name Provides a name for a subdocument\n"); + fprintf(stderr, "\t-s On extract, specifies the file to extract\n"); + fprintf(stderr, "\t subdocuments to.\n"); + fprintf(stderr, "\t On archival, specifies an xml file to add\n"); + fprintf(stderr, "\t as a subdocument.\n"); + fprintf(stderr, "\t-l On archival, stay on the local device.\n"); + fprintf(stderr, "\t-p On extract, set ownership based on symbolic\n"); + fprintf(stderr, "\t names, if possible.\n"); + fprintf(stderr, "\t-P On extract, set ownership based on uid/gid.\n"); + fprintf(stderr, "\t--toc-cksum Specifies the hashing algorithm to use for\n"); + fprintf(stderr, "\t xml header verification.\n"); +#ifdef XAR_SUPPORT_MD5 + fprintf(stderr, "\t Valid values: md5, sha1, sha256, and sha512\n"); +#else + fprintf(stderr, "\t Valid values: sha1, sha256, and sha512\n"); +#endif // XAR_SUPPORT_MD5 + fprintf(stderr, "\t Default: sha1\n"); + fprintf(stderr, "\t--file-cksum Specifies the hashing algorithm to use for\n"); + fprintf(stderr, "\t file content verification.\n"); +#ifdef XAR_SUPPORT_MD5 + fprintf(stderr, "\t Valid values: md5, sha1, sha256, and sha512\n"); +#else + fprintf(stderr, "\t Valid values: sha1, sha256, and sha512\n"); +#endif + fprintf(stderr, "\t Default: sha1\n"); + fprintf(stderr, "\t--dump-toc-cksum Prints out the ToC chksum in hex.\n"); + fprintf(stderr, "\t The output is a hash of the ToC generated.\n"); + fprintf(stderr, "\t Also prints out the algorithm used.\n"); + fprintf(stderr, "\t by the checksum algorithm used during xar creation.\n"); + fprintf(stderr, "\t--dump-toc= Has xar dump the xml header into the\n"); + fprintf(stderr, "\t specified file.\n"); + fprintf(stderr, "\t--dump-header Prints out the xar binary header information\n"); + fprintf(stderr, "\t--compression Specifies the compression type to use.\n"); + fprintf(stderr, "\t Valid values: none, gzip, bzip2, lzma\n"); + fprintf(stderr, "\t Default: gzip\n"); + fprintf(stderr, "\t-a Synonym for \"--compression=lzma\"\n"); + fprintf(stderr, "\t-j Synonym for \"--compression=bzip2\"\n"); + fprintf(stderr, "\t-z Synonym for \"--compression=gzip\"\n"); + fprintf(stderr, "\t--compression-args=arg Specifies arguments to be passed\n"); + fprintf(stderr, "\t to the compression engine.\n"); + fprintf(stderr, "\t--compress-heap Compress entire heap instead of individual files.\n"); + fprintf(stderr, "\t Currently limited to gzip compression.\n"); + fprintf(stderr, "\t--list-subdocs List the subdocuments in the xml header\n"); + fprintf(stderr, "\t--extract-subdoc=name Extracts the specified subdocument\n"); + fprintf(stderr, "\t to a document in cwd named .xml\n"); + fprintf(stderr, "\t--exclude POSIX regular expression of files to \n"); + fprintf(stderr, "\t ignore while archiving.\n"); + fprintf(stderr, "\t--rsize Specifies the size of the buffer used\n"); + fprintf(stderr, "\t for read IO operations in bytes.\n"); + fprintf(stderr, "\t--coalesce-heap When archived files are identical, only store one copy\n"); + fprintf(stderr, "\t This option creates an archive which\n"); + fprintf(stderr, "\t is not streamable\n"); + fprintf(stderr, "\t--link-same Hardlink identical files\n"); + fprintf(stderr, "\t--no-compress POSIX regular expression of files\n"); + fprintf(stderr, "\t to archive, but not compress.\n"); + fprintf(stderr, "\t--prop-include File properties to include in archive\n"); + fprintf(stderr, "\t--prop-exclude File properties to exclude in archive\n"); + fprintf(stderr, "\t--distribution Only includes a subset of file properties\n"); + fprintf(stderr, "\t appropriate for archive distribution\n"); + fprintf(stderr, "\t--keep-existing Do not overwrite existing files while extracting\n"); + fprintf(stderr, "\t-k Synonym for --keep-existing\n"); + fprintf(stderr, "\t--keep-setuid Preserve the suid/sgid bits when extracting\n"); + fprintf(stderr, "\t--version Print xar's version number\n"); + + return; +} + +static void print_version() { + printf("xar %s\n", XAR_VERSION); +} + +int main(int argc, char *argv[]) { + int ret; + char *filename = NULL; + char command = 0, c; + char **args; + const char *tocfile = NULL; + int arglen, i, err; + xar_t x; + int loptind = 0; + int required_dash_f = 0; /* This release requires us to use -f */ + struct lnode *tmp; + long int longtmp; + struct option o[] = { + {"toc-cksum", required_argument, 0, 1}, + {"file-cksum", required_argument, 0, 19}, // out of order to avoid regressions + {"dump-toc", required_argument, 0, 'd'}, + {"dump-toc-cksum", no_argument, 0, 20}, + {"compression", required_argument, 0, 2}, + {"list-subdocs", no_argument, 0, 3}, + {"help", no_argument, 0, 'h'}, + {"version", no_argument, 0, 4}, + {"dump-header", no_argument, 0, 5}, + {"extract-subdoc", required_argument, 0, 6}, + {"exclude", required_argument, 0, 7}, + {"rsize", required_argument, 0, 8}, + {"coalesce-heap", no_argument, 0, 9}, + {"link-same", no_argument, 0, 10}, + {"no-compress", required_argument, 0, 11}, + {"prop-include", required_argument, 0, 12}, + {"prop-exclude", required_argument, 0, 13}, + {"distribution", no_argument, 0, 14}, + {"keep-existing", no_argument, 0, 15}, + {"keep-setuid", no_argument, 0, 16}, + {"compression-args", required_argument, 0, 17}, + { 0, 0, 0, 0} + }; + + if( argc < 2 ) { + usage(argv[0]); + exit(1); + } + + while( (c = getopt_long(argc, argv, "axcC:vtjzf:hpPln:s:d:vk", o, &loptind)) != -1 ) { + switch(c) { + case 1 : // toc-cksum + if( !optarg ) { + usage(argv[0]); + exit(1); + } + if( (strcmp(optarg, XAR_OPT_VAL_NONE) != 0) && +#ifdef XAR_SUPPORT_MD5 + (strcmp(optarg, XAR_OPT_VAL_MD5) != 0) && +#endif // XAR_SUPPORT_MD5 + (strcmp(optarg, XAR_OPT_VAL_SHA1) != 0) && + (strcmp(optarg, XAR_OPT_VAL_SHA256) != 0) && + (strcmp(optarg, XAR_OPT_VAL_SHA512) != 0) ) { + usage(argv[0]); + exit(1); + } + Toccksum = optarg; + break; + case 20: + command = 20; + break; + case 19 : // file-cksum + if( !optarg ) { + usage(argv[0]); + exit(1); + } + if( (strcmp(optarg, XAR_OPT_VAL_NONE) != 0) && +#ifdef XAR_SUPPORT_MD5 + (strcmp(optarg, XAR_OPT_VAL_MD5) != 0) && +#endif // XAR_SUPPORT_MD5 + (strcmp(optarg, XAR_OPT_VAL_SHA1) != 0) && + (strcmp(optarg, XAR_OPT_VAL_SHA256) != 0) && + (strcmp(optarg, XAR_OPT_VAL_SHA512) != 0) ) { + usage(argv[0]); + exit(1); + } + Filecksum = optarg; + break; + case 2 : // compression + if( !optarg ) { + usage(argv[0]); + exit(1); + } + if( (strcmp(optarg, XAR_OPT_VAL_NONE) != 0) && + (strcmp(optarg, XAR_OPT_VAL_GZIP) != 0) && + (strcmp(optarg, XAR_OPT_VAL_BZIP) != 0) && + (strcmp(optarg, XAR_OPT_VAL_LZMA) != 0) ) { + usage(argv[0]); + exit(1); + } + Compression = optarg; + break; + case 3 : // list-subdocs + if( command && (command != 3) ) { + fprintf(stderr, "Conflicting commands specified\n"); + exit(1); + } + command = 3; + break; + case 4 : // version + print_version(); + exit(0); + case 'd': // dump-toc + if( !optarg ) { + usage(argv[0]); + exit(1); + } + tocfile = optarg; + command = 'd'; + break; + case 5 : // dump-header + command = 5; + break; + case 6 : // extract-subdoc + SubdocName = optarg; + asprintf(&Subdoc, "%s.xml", SubdocName); + if( !command ) + command = 6; + break; + case 7 : // exclude + tmp = malloc(sizeof(struct lnode)); + tmp->str = optarg; + tmp->next = NULL; + err = regcomp(&tmp->reg, tmp->str, REG_NOSUB); + if( err ) { + char errstr[1024]; + regerror(err, &tmp->reg, errstr, sizeof(errstr)); + printf("Error with regular expression %s: %s\n", tmp->str, errstr); + exit(1); + } + if( Exclude == NULL ) { + Exclude = tmp; + Exclude_Tail = tmp; + } else { + Exclude_Tail->next = tmp; + Exclude_Tail = tmp; + } + break; + case 8 : // rsize + if ( !optarg ) { + usage(argv[0]); + exit(1); + } + longtmp = strtol(optarg, NULL, 10); + if( (((longtmp == LONG_MIN) || (longtmp == LONG_MAX)) && (errno == ERANGE)) || (longtmp < 1) ) { + fprintf(stderr, "Invalid rsize value: %s\n", optarg); + exit(5); + } + Rsize = optarg; + break; + case 9 : Coalesce = 1; break; // coalesce-heap + case 10 : LinkSame = 1; break; // link-same + case 11 : // no-compress + tmp = malloc(sizeof(struct lnode)); + tmp->str = optarg; + tmp->next = NULL; + err = regcomp(&tmp->reg, tmp->str, REG_NOSUB); + if( err ) { + char errstr[1024]; + regerror(err, &tmp->reg, errstr, sizeof(errstr)); + printf("Error with regular expression %s: %s\n", tmp->str, errstr); + exit(1); + } + if( NoCompress == NULL ) { + NoCompress = tmp; + NoCompress_Tail = tmp; + } else { + NoCompress_Tail->next = tmp; + NoCompress_Tail = tmp; + } + break; + case 12 : // prop-include + tmp = malloc(sizeof(struct lnode)); + tmp->str = optarg; + tmp->next = NULL; + if( PropInclude == NULL ) { + PropInclude = tmp; + PropInclude_Tail = tmp; + } else { + PropInclude_Tail->next = tmp; + PropInclude_Tail = tmp; + } + break; + case 13 : // prop-exclude + tmp = malloc(sizeof(struct lnode)); + tmp->str = optarg; + tmp->next = NULL; + if( PropExclude == NULL ) { + PropExclude = tmp; + PropExclude_Tail = tmp; + } else { + PropExclude_Tail->next = tmp; + PropExclude_Tail = tmp; + } + break; + case 14 : // distribution + { + char *props[] = { "type", "data", "mode", "name" }; + int i; + for( i = 0; i < 4; i++ ) { + tmp = malloc(sizeof(struct lnode)); + tmp->str = strdup(props[i]); + tmp->next = NULL; + if( PropInclude == NULL ) { + PropInclude = tmp; + PropInclude_Tail = tmp; + } else { + PropInclude_Tail->next = tmp; + PropInclude_Tail = tmp; + } + } + } + break; + case 'k': // keep-existing + case 15 : + NoOverwrite++; + break; + case 16 : // keep-setuid + SaveSuid++; + break; + case 17 : // compression-args + CompressionArg = optarg; + break; + case 'C': // chdir to + if( !optarg ) { + usage(argv[0]); + exit(1); + } + Chdir = optarg; + break; + case 'c': // create + case 'x': // extract + case 't': // list + if( command && (command != 's') ) { + usage(argv[0]); + fprintf(stderr, "Conflicting command flags: %c and %c specified\n", c, command); + exit(1); + } + if( c == 't' ) + List = 1; + command = c; + break; + case 'a': + Compression = "lzma"; + break; + case 'j': + Compression = "bzip2"; + break; + case 'z': + Compression = "gzip"; + break; + case 'f': // filename + required_dash_f = 1; + filename = optarg; + break; + case 'p': // set ownership based on symbolic names (if possible) + Perms = SYMBOLIC; + break; + case 'P': // set ownership based on uid/gid + Perms = NUMERIC; + break; + case 'l': // stay on local device + Local = 1; + break; + case 'n': // provide subdocument name + SubdocName = optarg; + break; + case 's': // extract subdocuments to/add subdocuments from + Subdoc = optarg; + if( !command ) + command = 's'; + break; + case 'v': // print filenames + Verbose++; + break; + case 'h': // help + default: + usage(argv[0]); + exit(1); + } + } + + if (! required_dash_f) { + usage(argv[0]); + fprintf(stderr, "\n -f option is REQUIRED\n"); + exit(1); + } + + switch(command) { + case 5 : + return dump_header(filename); + case 3 : + return list_subdocs(filename); + case 'c': + if( optind == argc ) { + usage(argv[0]); + fprintf(stderr, "No files to operate on.\n"); + exit(1); + } + arglen = argc - optind; + args = malloc(sizeof(char*) * (arglen+1)); + memset(args, 0, sizeof(char*) * (arglen+1)); + for( i = 0; i < arglen; i++ ) + args[i] = strdup(argv[optind + i]); + + return archive(filename, arglen, args); + case 'd': + if( !tocfile ) { + usage(argv[0]); + exit(1); + } + return dumptoc(filename, tocfile); + case 20: + if( !required_dash_f ) { + usage(argv[0]); + exit(1); + } + return dump_toc_chksum(filename); + break; + case 'x': + arglen = argc - optind; + args = malloc(sizeof(char*) * (arglen+1)); + for( i = 0; i < arglen; i++ ) + args[i] = strdup(argv[optind + i]); + args[i] = NULL; + return extract(filename, arglen, args); + case 't': + arglen = argc - optind; + args = calloc(sizeof(char*) * (arglen+1),1); + for( i = 0; i < arglen; i++ ) + args[i] = strdup(argv[optind + i]); + ret = list(filename, arglen, args); + for( i = 0; i < arglen; i++ ) + free(args[i]); + case 6 : + case 's': + x = xar_open(filename, READ); + if( !x ) { + fprintf(stderr, "Error opening xar archive: %s\n", filename); + exit(1); + } + xar_register_errhandler(x, err_callback, NULL); + extract_subdoc(x, SubdocName); + xar_close(x); + exit(Err); + break; + default: + usage(argv[0]); + fprintf(stderr, "Unrecognized command.\n"); + exit(1); + } + + /* unreached */ + exit(0); +} diff --git a/xar/test/attr.py b/xar/test/attr.py new file mode 100644 index 0000000..adc2c56 --- /dev/null +++ b/xar/test/attr.py @@ -0,0 +1,139 @@ +#!/usr/bin/env python + +from __future__ import print_function + +import os +import os.path +import shutil +import subprocess +import xattr + +import util + +# Notes: +# * Due to internal buffer sizing, "large" should be at least 4096 bytes for +# uncompressed archives and archives with individual file compression, and +# and at least 32768 bytes for archives with compressed heaps. +# * For large files, we intentionally use a non-base-2 file size to ensure we +# catch file extraction bugs for files with a size not equal to the internal +# read buffer size (which is base-2). +# * For large extended attributes, we do the same thing. + +# +# Utility Functions +# + +class MissingExtendedAttributeError(AssertionError): + pass + +def _random_big_data(bytes=65536, path="/dev/random"): + """ + Returns a random string with the number of bytes requested. Due to xar + implementation details, this should be greater than 4096 (32768 for + compressed heap testing). + + """ + with open(path, "r") as f: + return f.read(bytes) + +def _test_xattr_on_file_with_contents(filename, file_contents, xattrs=[], xar_create_flags=[], xar_extract_flags=[]): + try: + # Write file out + with open(filename, "w") as f: + f.write(file_contents) + for (key, value) in xattrs: + xattr.setxattr(f, key, value) + + # Store it into a xarchive + archive_name = "{f}.xar".format(f=filename) + with util.archive_created(archive_name, filename, *xar_create_flags) as path: + # Extract xarchive + with util.directory_created("extracted") as directory: + # Validate resulting xattrs + subprocess.check_call(["xar", "-x", "-C", directory, "-f", path] + xar_extract_flags) + for (key, value) in xattrs: + try: + assert xattr.getxattr(os.path.join(directory, filename), key) == value, "extended attribute \"{n}\" has incorrect contents after extraction".format(n=key) + except KeyError: + raise MissingExtendedAttributeError("extended attribute \"{n}\" missing after extraction".format(n=key)) + + # Validate file contents + with open(os.path.join(directory, filename), "r") as f: + if f.read() != file_contents: + raise MissingExtendedAttributeError("archived file \"{f}\" has has incorrect contents after extraction".format(f=filename)) + finally: + os.unlink(filename) + + +# +# Test Cases +# + +# Note: xar currently drops empty extended attributes (and any xar_prop_t with empty contents, actually). The empty +# tests are commented out awaiting a day when this might be different. + +# def empty_xattr_empty_file(filename): +# _test_xattr_on_file_with_contents(filename, "", xattrs=[("foo", "")]) + +def small_xattr_empty_file(filename): + _test_xattr_on_file_with_contents(filename, "", xattrs=[("foo", "1234")]) + +def large_xattr_empty_file(filename): + _test_xattr_on_file_with_contents(filename, "", xattrs=[("foo", _random_big_data(5000))]) + +# def empty_xattr_small_file(filename): +# _test_xattr_on_file_with_contents(filename, "small.file.contents", xattrs=[("foo", "")]) + +def small_xattr_small_file(filename): + _test_xattr_on_file_with_contents(filename, "small.file.contents", xattrs=[("foo", "1234")]) + +def large_xattr_small_file(filename): + _test_xattr_on_file_with_contents(filename, "small.file.contents", xattrs=[("foo", _random_big_data(4567))]) + +# def empty_xattr_large_file(filename): +# _test_xattr_on_file_with_contents(filename, _random_big_data(10000000), xattrs=[("foo", "")]) + +def small_xattr_large_file(filename): + _test_xattr_on_file_with_contents(filename, _random_big_data(5000000), xattrs=[("foo", "1234")]) + +def large_xattr_large_file(filename): + _test_xattr_on_file_with_contents(filename, _random_big_data(9876543), xattrs=[("foo", _random_big_data(6543))]) + +def multiple_xattrs(filename): + _test_xattr_on_file_with_contents(filename, "", xattrs=[("foo", "bar"), ("baz", "1234"), ("quux", "more")]) # ("empty", "") + +def distribution_create(filename): + try: + _test_xattr_on_file_with_contents(filename, "dummy", xattrs=[("foo", "bar")], xar_create_flags=["--distribution"]) + except MissingExtendedAttributeError: + pass + else: + raise AssertionError("no error encountered") + +# Note: xar currently has no way to exclude a property on extraction. This test is commented out awaiting the day +# when it can. + +# def distribution_extract(filename): +# try: +# _test_xattr_on_file_with_contents(filename, "dummy", xattrs=[("foo", "bar")], xar_extract_flags=["--distribution"]) +# except MissingExtendedAttributeError: +# pass +# else: +# raise AssertionError("no error encountered") + + +TEST_CASES = (small_xattr_empty_file, large_xattr_empty_file, + small_xattr_small_file, large_xattr_small_file, + small_xattr_large_file, large_xattr_large_file, + multiple_xattrs, distribution_create) + +if __name__ == "__main__": + for case in TEST_CASES: + try: + case(case.func_name) + print("PASSED: {f}".format(f=case.func_name)) + except (AssertionError, IOError, subprocess.CalledProcessError): + import sys, os + print("FAILED: {f}".format(f=case.func_name)) + sys.excepthook(*sys.exc_info()) + print("") diff --git a/xar/test/buffer.c b/xar/test/buffer.c new file mode 100644 index 0000000..a353cef --- /dev/null +++ b/xar/test/buffer.c @@ -0,0 +1,79 @@ +#include +#include +#include +#include +#include +#include + +int32_t err_callback(int32_t sev, int32_t err, xar_errctx_t ctx, void *usrctx) +{ + printf("error callback invoked\n"); + return 0; +} + +int main(int argc, char *argv[]) +{ + int fd; + unsigned char *buffer; + struct stat sb; + ssize_t red; + xar_t x; + xar_file_t f, f2; + + if( argc < 2 ) { + fprintf(stderr, "usage: %s \n", argv[0]); + exit(1); + } + + fd = open(argv[1], O_RDONLY); + if( fd < 0 ) { + fprintf(stderr, "Unable to open file %s\n", argv[1]); + exit(2); + } + + if( fstat(fd, &sb) < 0 ) { + fprintf(stderr, "Unable to stat file %s\n", argv[1]); + exit(3); + } + + buffer = malloc(sb.st_size); + if( buffer == NULL ) { + fprintf(stderr, "Unable to allocate memory\n"); + exit(4); + } + + red = read(fd, buffer, sb.st_size); + if( red <= 0 ) { + fprintf(stderr, "Error reading from file\n"); + exit(5); + } + if( red < sb.st_size ) + fprintf(stderr, "Incomplete read\n"); + + x = xar_open("/tmp/test.xar", WRITE); + if( x == NULL ) { + fprintf(stderr, "Error creating xarchive\n"); + exit(6); + } + + xar_register_errhandler(x, err_callback, NULL); + + memset(&sb, 0, sizeof(sb)); + + sb.st_mode = S_IFDIR | S_IRWXU; + f = xar_add_folder(x, NULL, "mydir", &sb); + if( !f ) { + fprintf(stderr, "Error adding parent to archive\n"); + exit(7); + } + + f2 = xar_add_frombuffer(x, f, "secondfile", buffer, red); + if( !f ) { + fprintf(stderr, "Error adding child to archive\n"); + exit(8); + } + + xar_close(x); + close(fd); + exit(0); +} diff --git a/xar/test/checksums.py b/xar/test/checksums.py new file mode 100644 index 0000000..7080d7c --- /dev/null +++ b/xar/test/checksums.py @@ -0,0 +1,225 @@ +#!/usr/bin/env python + +from __future__ import print_function + +import hashlib +import os +import os.path +import re +import shutil +import struct +import subprocess + +import util + + +# +# Utility Functions +# + +def _get_numeric_value_from_header(archive_name, key): + """ + Dumps the header of the specified xar archive and extracts the header + size from the output, in bytes. + + """ + header = subprocess.check_output(["xar", "--dump-header", "-f", archive_name]) + for line in header.splitlines(): + matchdata = re.match("^(.+):\s+(.+)$", line) # magic: 0x78617221 (OK) + assert matchdata, "unexpected output from `xar --dump-header`:\n{h}".format(h=header) + if matchdata.groups()[0] == key: + return int(matchdata.groups()[1]) + raise AssertionError("no \"{k}\" found for archive \"{n}\":\n{h}".format(k=key, n=archive_name, h=header)) + +def _get_header_size(archive_name): + return _get_numeric_value_from_header(archive_name, "size") + +def _get_toc_size(archive_name): + return _get_numeric_value_from_header(archive_name, "Compressed TOC length") + +def _clobber_bytes_at(clobber_range, path): + with open(path, "r+") as f: + f.seek(clobber_range[0]) + with open("/dev/random", "r") as r: + random_bytes = r.read(len(clobber_range)) + f.write(random_bytes) + +def _verify_extraction_failed(filename): + with util.directory_created("extracted") as directory: + try: + with open("/dev/null", "w") as n: + returncode = subprocess.call(["xar", "-x", "-C", directory, "-f", filename], stdout=n, stderr=n) + assert returncode != 0, "xar reported success extracting an archive with a broken TOC" + finally: + if os.path.exists(directory): + shutil.rmtree(directory) + +def _hex_digest_string(raw_digest): + unpack_string = "B" * len(raw_digest) + format_string = "%02x" * len(raw_digest) + return format_string % struct.unpack(unpack_string, raw_digest) + +def _verify_header_checksum(filename, algorithm): + header_size = _get_header_size(filename) + toc_length = _get_toc_size(filename) + + with open(filename, "r") as f: + f.seek(header_size) + h = hashlib.new(algorithm, f.read(toc_length)) + computed_digest = h.digest() + # We intentionally ignore the TOC-specified offset. We should build a variant of this that uses the TOC + # offset so we check both. + stored_digest = f.read(len(computed_digest)) + assert computed_digest == stored_digest, "Digests don't match: expected value {d1} != stored value {d2}".format(d1=_hex_digest_string(computed_digest), d2=_hex_digest_string(stored_digest)) +# +# Test Cases +# + +def default_toc_checksum_validity(filename): + with util.archive_created(filename, "/bin") as path: + _verify_header_checksum(path, "sha1") + +def sha1_toc_checksum_validity(filename): + with util.archive_created(filename, "/bin", "--toc-cksum", "sha1") as path: + _verify_header_checksum(path, "sha1") + +def sha256_toc_checksum_validity(filename): + with util.archive_created(filename, "/bin", "--toc-cksum", "sha256") as path: + _verify_header_checksum(path, "sha256") + +def sha512_toc_checksum_validity(filename): + with util.archive_created(filename, "/bin", "--toc-cksum", "sha512") as path: + _verify_header_checksum(path, "sha512") + +def broken_toc_default_checksum(filename): + with util.archive_created(filename, "/bin") as path: + # Mess up the archive + toc_start = _get_header_size(path) + _clobber_bytes_at(range(toc_start + 4, toc_start + 4 + 100), path) # Why did the original test specify 4? No idea. + + # Try to extract it + _verify_extraction_failed(filename) + +def broken_toc_sha1_checksum(filename): + with util.archive_created(filename, "/bin", "--toc-cksum", "sha1") as path: + # Mess up the archive + toc_start = _get_header_size(path) + _clobber_bytes_at(range(toc_start + 4, toc_start + 4 + 100), path) # Why did the original test specify 4? No idea. + + # Try to extract it + _verify_extraction_failed(filename) + +def broken_toc_sha256_checksum(filename): + with util.archive_created(filename, "/bin", "--toc-cksum", "sha256") as path: + # Mess up the archive + toc_start = _get_header_size(path) + _clobber_bytes_at(range(toc_start + 4, toc_start + 4 + 100), path) # Why did the original test specify 4? No idea. + + # Try to extract it + _verify_extraction_failed(filename) + +def broken_toc_sha512_checksum(filename): + with util.archive_created(filename, "/bin", "--toc-cksum", "sha512") as path: + # Mess up the archive + toc_start = _get_header_size(path) + _clobber_bytes_at(range(toc_start + 4, toc_start + 4 + 100), path) # Why did the original test specify 4? No idea. + + # Try to extract it + _verify_extraction_failed(filename) + +def broken_heap_default_checksum(filename): + with util.archive_created(filename, "/bin") as path: + # Mess up the archive + toc_start = _get_header_size(path) + toc_size = _get_toc_size(path) + # Why 32? That's the size of the default sha256 checksum, which is stored before the heap. + _clobber_bytes_at(range(toc_start + toc_size + 32, toc_start + toc_size + 32 + 100), path) + + # Try to extract it + _verify_extraction_failed(filename) + +def default_checksum_algorithm(filename): + with util.archive_created(filename, "/bin") as path: + header = subprocess.check_output(["xar", "--dump-header", "-f", path]) + found = False + for line in header.splitlines(): + matchdata = re.match("^Checksum algorithm:\s+(\d+)\s+\\((\w+)\\)$", line) + if not matchdata: + continue + found = True + algorithm = matchdata.groups()[1] + assert algorithm == "SHA1", "unexpected checksum algorithm default: received {a}, expected SHA1".format(a=algorithm) + assert found, "unexpected output from `xar --dump-header`:\n{h}".format(h=header) + + +# Apparently, xar doesn't currently fail when given an invalid checksum algorithm. Something to fix later. +# +# def invalid_checksum_algorithm(filename): +# try: +# with util.archive_created(filename, "/bin", "--toc-cksum", "invalid-algorithm") as path: +# raise AssertionError("xar succeeded when it should have failed") +# except subprocess.CalledProcessError: +# pass + +# It does fail for md5 explicitly, however +def md5_toc_checksum_failure(filename): + try: + with open("/dev/null", "a") as devnull: + with util.archive_created(filename, "/bin", "--toc-cksum", "md5", stderr=devnull) as path: + raise AssertionError("xar succeeded when it should have failed") + except subprocess.CalledProcessError: + pass + +def md5_file_checksum_failure(filename): + try: + with open("/dev/null", "a") as devnull: + with util.archive_created(filename, "/bin", "--file-cksum", "md5", stderr=devnull) as path: + raise AssertionError("xar succeeded when it should have failed") + except subprocess.CalledProcessError: + pass + +def _verify_checksum_algorithm(filename, algorithm): + additional_args = [] + if algorithm: + additional_args = ["--file-cksum", algorithm] + else: + algorithm = "sha1" + + with util.archive_created(filename, "/bin", *additional_args) as path: + toc = subprocess.check_output(["xar", "--dump-toc=-", "-f", path]) + found = False + for line in toc.splitlines(): + if ''.format(a=algorithm) in line or ''.format(a=algorithm) in line: + break + else: + raise AssertionError("unexpected output from `xar --dump-toc=-`:\n{t}".format(t=toc)) + +def default_file_checksum_algorithm(filename): + _verify_checksum_algorithm(filename, None) + +def sha1_file_checksum_algorithm(filename): + _verify_checksum_algorithm(filename, "sha1") + +def sha256_file_checksum_algorithm(filename): + _verify_checksum_algorithm(filename, "sha256") + +def sha512_file_checksum_algorithm(filename): + _verify_checksum_algorithm(filename, "sha512") + + +TEST_CASES = (default_toc_checksum_validity, sha1_toc_checksum_validity, sha256_toc_checksum_validity, sha512_toc_checksum_validity, + broken_toc_default_checksum, broken_toc_sha1_checksum, broken_toc_sha256_checksum, broken_toc_sha512_checksum, + broken_heap_default_checksum, default_checksum_algorithm, + default_file_checksum_algorithm, sha1_file_checksum_algorithm, sha256_file_checksum_algorithm, sha512_file_checksum_algorithm, + md5_toc_checksum_failure, md5_file_checksum_failure,) + +if __name__ == "__main__": + for case in TEST_CASES: + try: + case("{f}.xar".format(f=case.func_name)) + print("PASSED: {f}".format(f=case.func_name)) + except (AssertionError, IOError, subprocess.CalledProcessError): + import sys, os + print("FAILED: {f}".format(f=case.func_name)) + sys.excepthook(*sys.exc_info()) + print("") diff --git a/xar/test/compression.py b/xar/test/compression.py new file mode 100644 index 0000000..2b3b2ec --- /dev/null +++ b/xar/test/compression.py @@ -0,0 +1,74 @@ +#!/usr/bin/env python + +from __future__ import print_function + +import cStringIO +import os +import os.path +import subprocess +import tempfile + +import util + + +# +# Utility Functions +# + +def _check_compression(filename, *args, **kwargs): + with util.archive_created(filename, "/bin", *args, **kwargs) as path: + with util.directory_created("extracted") as directory: + subprocess.check_call(["xar", "-x", "-f", path, "-C", directory]) + util.assert_identical_directories("/bin", os.path.join(directory, "bin")) + + +# +# Test Cases +# + +def no_compression(filename): + _check_compression(filename, "--compression=none") + +def default_compression(filename): + _check_compression(filename) + +def gzip_compression_long(filename): + util.skip_if_no_compression_support("gzip") + _check_compression(filename, "--compression=gzip") + +def gzip_compression_short(filename): + util.skip_if_no_compression_support("gzip") + _check_compression(filename, "-z") + +def bzip2_compression_long(filename): + util.skip_if_no_compression_support("bzip2") + _check_compression(filename, "--compression=bzip2") + +def bzip2_compression_short(filename): + util.skip_if_no_compression_support("bzip2") + _check_compression(filename, "-j") + +def lzma_compression_long(filename): + util.skip_if_no_compression_support("lzma") + _check_compression(filename, "--compression=lzma") + +def lzma_compression_short(filename): + util.skip_if_no_compression_support("lzma") + _check_compression(filename, "-a") + +TEST_CASES = (no_compression, default_compression, + gzip_compression_long, bzip2_compression_long, lzma_compression_long, + gzip_compression_short, bzip2_compression_short, lzma_compression_short) + +if __name__ == "__main__": + for case in TEST_CASES: + try: + case("{f}.xar".format(f=case.func_name)) + print("PASSED: {f}".format(f=case.func_name)) + except (AssertionError, IOError, subprocess.CalledProcessError): + import sys, os + print("FAILED: {f}".format(f=case.func_name)) + sys.excepthook(*sys.exc_info()) + print("") + except util.TestCaseSkipError, e: + print("SKIPPED: {f}: {m}".format(f=case.func_name, m=e.message)) diff --git a/xar/test/data.py b/xar/test/data.py new file mode 100644 index 0000000..a9793f0 --- /dev/null +++ b/xar/test/data.py @@ -0,0 +1,103 @@ +#!/usr/bin/env python + +from __future__ import print_function + +import contextlib +import os +import os.path +import subprocess +import util + + +# +# Utility Functions +# + +@contextlib.contextmanager +def _data_test(filename, *args, **kwargs): + with util.directory_created("data_scratch") as directory: + yield directory + # Files are now created + with util.archive_created("data.xar", "./data_scratch", *args, **kwargs) as path: + _process_toc(path) + with util.directory_created("data_extracted") as extracted: + subprocess.check_call(["xar", "-x", "-f", path, "-C", extracted]) + util.assert_identical_directories(directory, os.path.join(extracted, "data_scratch")) + +def _process_toc(archive_path): + subprocess.check_call(["xar", "-f", archive_path, "--dump-toc=data_toc.xml"]) + try: + result = subprocess.check_output(["xsltproc", "-o", "-", os.path.realpath(os.path.join(__file__, "..", "data.xsl")), "data_toc.xml"]) + assert result == "", "expected no data offset, but instead found:{o}".format(o=result) + finally: + os.unlink("data_toc.xml") + +def _zero_length(filename, *args, **kwargs): + with _data_test(filename, *args, **kwargs) as directory: + util.touch(os.path.join(directory, "empty")) + + +# +# Test Cases +# + +def zero_length_default_compression(filename): + _zero_length(filename) + +def zero_length_no_compression(filename): + _zero_length(filename, "--compression=none") + +def zero_length_gzip_compression(filename): + util.skip_if_no_compression_support("gzip") + _zero_length(filename, "--compression=gzip") + +def zero_length_bzip2_compression(filename): + util.skip_if_no_compression_support("bzip2") + _zero_length(filename, "--compression=bzip2") + +def zero_length_lzma_compression(filename): + util.skip_if_no_compression_support("lzma") + _zero_length(filename, "--compression=lzma") + +def _mixed_length(filename, *args, **kwargs): + with _data_test(filename, *args, **kwargs) as directory: + util.touch(os.path.join(directory, "mixed_empty")) + with open(os.path.join(directory, "mixed_small"), "w") as f: + f.write("1234") + +def mixed_length_no_compression(filename): + _mixed_length(filename, "--compression=none") + +def mixed_length_default_compression(filename): + _mixed_length(filename) + +def mixed_length_gzip_compression(filename): + util.skip_if_no_compression_support("gzip") + _mixed_length(filename, "--compression=gzip") + +def mixed_length_bzip2_compression(filename): + util.skip_if_no_compression_support("bzip2") + _mixed_length(filename, "--compression=bzip2") + +def mixed_length_lzma_compression(filename): + util.skip_if_no_compression_support("lzma") + _mixed_length(filename, "--compression=lzma") + + +TEST_CASES = (zero_length_default_compression, zero_length_no_compression, + zero_length_gzip_compression, zero_length_bzip2_compression, zero_length_lzma_compression, + mixed_length_no_compression, mixed_length_default_compression, + mixed_length_gzip_compression, mixed_length_bzip2_compression, mixed_length_lzma_compression) + +if __name__ == "__main__": + for case in TEST_CASES: + try: + case("{f}.xar".format(f=case.func_name)) + print("PASSED: {f}".format(f=case.func_name)) + except (AssertionError, IOError, subprocess.CalledProcessError): + import sys, os + print("FAILED: {f}".format(f=case.func_name)) + sys.excepthook(*sys.exc_info()) + print("") + except util.TestCaseSkipError, e: + print("SKIPPED: {f}: {m}".format(f=case.func_name, m=e.message)) diff --git a/xar/test/data.xsl b/xar/test/data.xsl new file mode 100644 index 0000000..4236b7f --- /dev/null +++ b/xar/test/data.xsl @@ -0,0 +1,8 @@ + + + + + + + diff --git a/xar/test/hardlink.py b/xar/test/hardlink.py new file mode 100644 index 0000000..5145216 --- /dev/null +++ b/xar/test/hardlink.py @@ -0,0 +1,69 @@ +#!/usr/bin/env python + +from __future__ import print_function + +import os +import os.path +import subprocess + +import util + +# +# Utility Functions +# + +def _assert_same_inodes(path1, path2): + assert os.path.exists(path1), "missing hard-linked-file {p}".format(p=path1) + assert os.path.exists(path1), "missing hard-linked-file {p}".format(p=path2) + stat1 = os.lstat(path1) + stat2 = os.lstat(path2) + assert stat1.st_ino == stat2.st_ino, "inodes do not match for hard-linked files \"{p1}\" and \"{p2}\"".format(p1=path1, p2=path2) + + +# +# Test Cases +# + +def hard_link_in_directory(filename): + with util.directory_created("hardlink_scratch") as directory: + util.touch(os.path.join(directory, "a")) + os.link(os.path.join(directory, "a"), os.path.join(directory, "b")) + + with util.archive_created("hardlink_archive.xar", "hardlink_scratch") as path: + with util.directory_created("hardlink_extracted") as extracted: + subprocess.check_call(["xar", "-x", "-C", extracted, "-f", path]) + _assert_same_inodes(os.path.join(extracted, "hardlink_scratch", "a"), os.path.join(extracted, "hardlink_scratch", "b")) + +def hard_link_in_cwd(filename): + with util.directory_created("hardlink_scratch") as directory: + with util.chdir(directory): + util.touch("a") + os.link("a", "b") + with util.archive_created(os.path.join("..", "hardlink_archive.xar"), ".") as path: + with util.directory_created(os.path.join("..", "hardlink_extracted")) as extracted: + subprocess.check_call(["xar", "-x", "-C", extracted, "-f", path]) + _assert_same_inodes(os.path.join(extracted, "a"), os.path.join(extracted, "b")) + +def hard_link_identical_files(filename): + with util.directory_created("hardlink_scratch") as directory: + with open(os.path.join(directory, "a"), "w") as f: + f.write("1234samecontent") + with open(os.path.join(directory, "b"), "w") as f: + f.write("1234samecontent") + with util.archive_created("hardlink_archive.xar", "hardlink_scratch", "--link-same") as path: + with util.directory_created("hardlink_extracted") as extracted: + subprocess.check_call(["xar", "-x", "-C", extracted, "-f", path]) + _assert_same_inodes(os.path.join(extracted, "hardlink_scratch", "a"), os.path.join(extracted, "hardlink_scratch", "b")) + +TEST_CASES = (hard_link_in_directory, hard_link_in_cwd, hard_link_identical_files) + +if __name__ == "__main__": + for case in TEST_CASES: + try: + case("{f}.xar".format(f=case.func_name)) + print("PASSED: {f}".format(f=case.func_name)) + except (AssertionError, IOError, subprocess.CalledProcessError): + import sys, os + print("FAILED: {f}".format(f=case.func_name)) + sys.excepthook(*sys.exc_info()) + print("") diff --git a/xar/test/heap.py b/xar/test/heap.py new file mode 100644 index 0000000..f431c77 --- /dev/null +++ b/xar/test/heap.py @@ -0,0 +1,78 @@ +#!/usr/bin/env python + +from __future__ import print_function + +import glob +import os +import os.path +import re +import shutil +import subprocess + +import util + + +# +# Utility Functions +# + +def _file_offsets_for_archive(path, xsl_path): + subprocess.check_call(["xar", "--dump-toc=heap_toc.xml", "-f", path]) + try: + offsets = subprocess.check_output(["xsltproc", xsl_path, "heap_toc.xml"]) + matches = [re.match("^(.+)\s([^\s]+)$", offset) for offset in offsets.splitlines()] + offsets = [(match.groups()[0], int(match.groups()[1])) for match in matches] + return offsets + finally: + os.unlink("heap_toc.xml") + +# +# Test Cases +# + +XSL_PATH = os.path.join(os.path.dirname(os.path.realpath(__file__)), "heap1.xsl") + +def normal_heap(filename): + with util.directory_created("scratch") as directory: + shutil.copy("/bin/ls", os.path.join(directory, "ls")) + shutil.copy(os.path.join(directory, "ls"), os.path.join(directory, "foo")) + with util.chdir(directory): + with util.archive_created(os.path.join("..", "heap.xar"), ".") as path: + # Verify file offsets are as we expect + offsets = _file_offsets_for_archive(path, XSL_PATH) + (f1, o1) = offsets[0] + (f2, o2) = offsets[1] + + assert o1 < o2, "offset for first file \"{f1}\" ({o1}) greater than or equal to offset for last file \"{f2}\" ({o2})".format(f1=f1, o1=o1, f2=f2, o2=o2) + + # Make sure extraction goes all right + with util.directory_created("extracted") as extracted: + subprocess.check_call(["xar", "-x", "-f", path, "-C", extracted]) + +def coalesce_heap(filename): + with util.directory_created("scratch") as directory: + shutil.copy("/bin/ls", os.path.join(directory, "ls")) + shutil.copy(os.path.join(directory, "ls"), os.path.join(directory, "foo")) + with util.chdir(directory): + with util.archive_created(os.path.join("..", "heap.xar"), ".", "--coalesce-heap") as path: + # Verify file offsets are as we expect + offsets = _file_offsets_for_archive(path, XSL_PATH) + (f1, o1) = offsets[0] + (f2, o2) = offsets[1] + + # Make sure extraction goes all right + with util.directory_created("extracted") as extracted: + subprocess.check_call(["xar", "-x", "-f", path, "-C", extracted]) + +TEST_CASES = (normal_heap, coalesce_heap) + +if __name__ == "__main__": + for case in TEST_CASES: + try: + case("{f}.xar".format(f=case.func_name)) + print("PASSED: {f}".format(f=case.func_name)) + except (AssertionError, IOError, subprocess.CalledProcessError): + import sys, os + print("FAILED: {f}".format(f=case.func_name)) + sys.excepthook(*sys.exc_info()) + print("") diff --git a/xar/test/heap1.xsl b/xar/test/heap1.xsl new file mode 100644 index 0000000..9c47305 --- /dev/null +++ b/xar/test/heap1.xsl @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + diff --git a/xar/test/integrity.py b/xar/test/integrity.py new file mode 100644 index 0000000..c47ac6a --- /dev/null +++ b/xar/test/integrity.py @@ -0,0 +1,88 @@ +#!/usr/bin/env python + +from __future__ import print_function + +import os +import os.path +import subprocess + +import util + +# +# Utility Functions +# + +def _test_truncation(filename, path_to_be_archived, bytes_to_chop, *args): + with util.archive_created(filename, path_to_be_archived) as path: + with open("/dev/null", "w") as bitbucket: + size = os.stat(path).st_size + while size > 0: + last_size = size + size = max(0, size - bytes_to_chop) + with open(path, "w+") as f: + f.truncate(size) + + with util.directory_created("scratch") as directory: + returncode = subprocess.call(["xar", "-x", "-f", path, "-C", directory], stderr=bitbucket) + assert returncode != 0, "xar claimed to succeed when extracting a truncated archive" + +# +# Test Cases +# + +def large_uncompressed(filename): + _test_truncation(filename, "/usr/share/man/man1", 1024 * 1024, "--compression=none") + +def large_default_compression(filename): + _test_truncation(filename, "/usr/share/man/man1", 1024 * 1024) + +def large_gzip_compressed(filename): + util.skip_if_no_compression_support("gzip") + _test_truncation(filename, "/usr/share/man/man1", 1024 * 1024, "--compression=gzip") + +def large_bzip2_compressed(filename): + util.skip_if_no_compression_support("bzip2") + _test_truncation(filename, "/usr/share/man/man1", 1024 * 1024, "--compression=bzip2") + +def large_lzma_compressed(filename): + util.skip_if_no_compression_support("lzma") + _test_truncation(filename, "/usr/share/man/man1", 1024 * 1024, "--compression=lzma") + +# "small" variants use a non-base-2 size to try to catch issues that occur on uneven boundaries + +def small_uncompressed(filename): + _test_truncation(filename, "/bin", 43651, "--compression=none") + +def small_default_compression(filename): + _test_truncation(filename, "/bin", 43651) + +def small_gzip_compressed(filename): + util.skip_if_no_compression_support("gzip") + _test_truncation(filename, "/bin", 43651, "--compression=gzip") + +def small_bzip2_compressed(filename): + util.skip_if_no_compression_support("bzip2") + _test_truncation(filename, "/bin", 43651, "--compression=bzip2") + +def small_lzma_compressed(filename): + util.skip_if_no_compression_support("lzma") + _test_truncation(filename, "/bin", 43651, "--compression=lzma") + + +TEST_CASES = (large_uncompressed, large_default_compression, + large_gzip_compressed, large_bzip2_compressed, large_lzma_compressed, + small_uncompressed, small_default_compression, + small_gzip_compressed, small_bzip2_compressed, small_lzma_compressed) + +if __name__ == "__main__": + for case in TEST_CASES: + try: + case("{f}.xar".format(f=case.func_name)) + print("PASSED: {f}".format(f=case.func_name)) + except (AssertionError, IOError, subprocess.CalledProcessError): + import sys, os + print("FAILED: {f}".format(f=case.func_name)) + sys.excepthook(*sys.exc_info()) + print("") + except util.TestCaseSkipError, e: + print("SKIPPED: {f}: {m}".format(f=case.func_name, m=e.message)) diff --git a/xar/test/util.py b/xar/test/util.py new file mode 100644 index 0000000..da79925 --- /dev/null +++ b/xar/test/util.py @@ -0,0 +1,145 @@ +#!/usr/bin/env python + +import contextlib +import hashlib +import os +import os.path +import shutil +import stat +import subprocess +import sys +import xattr + +class TestCaseSkipError(Exception): + pass + +def skip_if_no_compression_support(type): + """ + Raises TestCaseSkipError if the type is "lzma" and the test is running on + darwin (OS X). In the future, we should add a hidden debugging flag to xar + to determine valid compression types. This will skip incorrectly if a + custom xar is used on OS X, or if a custom xar on another platform is + built without bzip2 or lzma. + + """ + if sys.platform == "darwin" and type == "lzma": + raise TestCaseSkipError("{t} support not compiled in".format(t=type)) + +@contextlib.contextmanager +def directory_created(directory_path): + """ + Creates the named directory and provides the path to the directory to the + calling code. Automatically removes the directory when finished. + + Usage: + with directory_created("foobar") as path: + do_stuff_with_path + + """ + os.mkdir(directory_path) + try: + yield os.path.realpath(directory_path) + finally: + if os.path.exists(directory_path): + shutil.rmtree(directory_path) + +@contextlib.contextmanager +def archive_created(archive_path, content_path, *extra_args, **extra_kwargs): + """ + Creates a named xar archive of the specified content path, returning the + path to the archive. Automatically removes the archive when finished. + + Usage: + with archive_created("/bin", "bin.xar") as path: + do_stuff_with(path) + + """ + cmd = ["xar", "-c", "-f", archive_path, content_path] + if extra_args: + cmd += list(extra_args) + try: + subprocess.check_call(cmd, **extra_kwargs) + assert os.path.exists(archive_path), "failed to create archive \"{p}\" but xar did not report an error".format(p=archive_path) + yield os.path.realpath(archive_path) + finally: + if os.path.exists(archive_path): + os.unlink(archive_path) + +HASH_CHUNK_SIZE = 32768 + +def _md5_path(path): + with open(path, "r") as f: + h = hashlib.md5() + while True: + last = f.read(HASH_CHUNK_SIZE) + if not last: + break + h.update(last) + return h.digest() + +def assert_identical_directories(path1, path2): + """ + Verifies two directories have identical contents. Checks file type (via + the high byte of the mode), size, atime, and mtime, but does not check + other attributes like uid and gid, since they can be expected to change. + + """ + seen = set([]) + for file1 in os.listdir(path1): + seen.add(file1) + entry1 = os.path.join(path1, file1) + entry2 = os.path.join(path2, file1) + assert os.path.exists(entry2), "\"{f1}\" exists in \"{p1}\" but not \"{p2}\"".format(f1=file1, p1=path1, p2=path2) + + # Extended attributes + xattr1 = xattr.xattr(entry1) + xattr2 = xattr.xattr(entry2) + assert set(xattr1.list()) == set(xattr2.list()), "list of extended attributes on \"{f1}\" ({l1}) differs from \"{f2}\" ({l2})".format(f1=entry1, l1=xattr1.list(), f2=entry2, l2=xattr2.list()) + for attribute in xattr1.list(): + assert xattr1.get(attribute) == xattr2.get(attribute), "extended attribute \"{a1}\" on \"{f1}\" doesn't match value from \"{f2}\"".format(a1=attribute, f1=entry1, f2=entry2) + + # Why do it this way? We want to lstat() instead of stat(), so we can't use os.path.isdir() and friends + stat1 = os.lstat(entry1) + stat2 = os.lstat(entry2) + + # Modes + mode1 = stat1.st_mode + mode2 = stat2.st_mode + if stat.S_ISREG(mode1): + assert stat.S_ISREG(mode2) + if stat.S_ISDIR(mode1): + assert stat.S_ISDIR(mode2) + if stat.S_ISLNK(mode1): + assert stat.S_ISLNK(mode2) + if stat.S_ISCHR(mode1): + assert stat.S_ISCHR(mode2) + if stat.S_ISBLK(mode1): + assert stat.S_ISBLK(mode2) + if stat.S_ISFIFO(mode1): + assert stat.S_ISFIFO(mode2) + if stat.S_ISSOCK(mode1): + assert stat.S_ISSOCK(mode2) + + # Sizes and the like + assert stat1.st_size == stat2.st_size, "size mismatch for \"{e1}\" ({s1}) and \"{e2}\" ({s2})".format(e1=entry1, s1=stat1.st_size, e2=entry2, s2=stat2.st_size) + assert stat1.st_mtime == stat2.st_mtime, "mtime mismatch for \"{e1}\" and \"{e2}\"".format(e1=entry1, e2=entry2) + assert _md5_path(entry1) == _md5_path(entry2), "md5 hash mismatch for \"{e1}\" and \"{e2}\"".format(e1=entry1, e2=entry2) + if os.path.isdir(entry1): + assert_identical_directories(entry1, entry2) + for file2 in os.listdir(path2): + assert file2 in seen, "\"{f2}\" exists in \"{p2}\" but not \"{p1}\"".format(f2=file2, p1=path1, p2=path2) + +def touch(path): + if not os.path.exists(path): + with open(path, "w"): + pass + os.utime(path, None) + +@contextlib.contextmanager +def chdir(*args, **kwargs): + cwd = os.getcwd() + os.chdir(*args, **kwargs) + try: + yield os.getcwd() + finally: + os.chdir(cwd) diff --git a/xar/test/validate.c b/xar/test/validate.c new file mode 100644 index 0000000..dfe69eb --- /dev/null +++ b/xar/test/validate.c @@ -0,0 +1,159 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +off_t HeapOff = 0; + +static char* xar_format_md5(const unsigned char* m) { + char* result = NULL; + asprintf(&result, + "%02x%02x%02x%02x" + "%02x%02x%02x%02x" + "%02x%02x%02x%02x" + "%02x%02x%02x%02x", + m[0], m[1], m[2], m[3], + m[4], m[5], m[6], m[7], + m[8], m[9], m[10], m[11], + m[12], m[13], m[14], m[15]); + return result; +} + +void heap_check(int fd, const char *name, const char *prop, off_t offset, off_t length, const char *csum) { + char *buf; + EVP_MD_CTX ctx; + const EVP_MD *md; + unsigned char md5str[EVP_MAX_MD_SIZE]; + unsigned int len; + ssize_t r; + char *formattedmd5; + + fprintf(stderr, "Heap checking %s %s at offset: %" PRIu64 "\n", name, prop, HeapOff+offset); + OpenSSL_add_all_digests(); + md = EVP_get_digestbyname("md5"); + if( md == NULL ) { + fprintf(stderr, "No md5 digest in openssl\n"); + exit(1); + } + EVP_DigestInit(&ctx, md); + + buf = malloc(length); + if( !buf ) { + fprintf(stderr, "Error allocating buffer\n"); + exit(1); + } + + if( lseek(fd, HeapOff+offset, SEEK_SET) < 0 ) { + perror("lseek"); + fprintf(stderr, "Error seeking in the heap to offet: %" PRIu64 "\n", HeapOff+offset); + exit(1); + } + + r = read(fd, buf, length); + if( r != length ) { + fprintf(stderr, "Error reading from the heap\n"); + exit(1); + } + EVP_DigestUpdate(&ctx, buf, length); + EVP_DigestFinal(&ctx, md5str, &len); + + formattedmd5 = xar_format_md5(md5str); + if( strcmp(formattedmd5, csum) != 0 ) { + fprintf(stderr, "%s %s checksum does not match\n", name, prop); + } + free(formattedmd5); + free(buf); +} + +void prop_check(int fd, xar_t x, xar_file_t f) { + xar_iter_t i; + const char *key, *value; + const char *name = NULL; + char *tmp; + off_t offset = 0, length = 0; + const char *origcsum = NULL; + + i = xar_iter_new(); + if( !i ) { + fprintf(stderr, "Error creating new prop iter\n"); + exit(1); + } + + xar_prop_get(f, "name", &name); + + for( key = xar_prop_first(f, i); key; key = xar_prop_next(i) ) { + asprintf(&tmp, "%s/offset", key); + if( xar_prop_get(f, tmp, &value) == 0 ) { + offset = strtoll(value, NULL, 10); + } + free(tmp); + asprintf(&tmp, "%s/length", key); + if( xar_prop_get(f, tmp, &value) == 0 ) { + length = strtoll(value, NULL, 10); + } + free(tmp); + asprintf(&tmp, "%s/archived-checksum", key); + if( xar_prop_get(f, tmp, &value) == 0 ) { + origcsum = value; + } + free(tmp); + + if( offset && length && origcsum ) { + heap_check(fd, name, key, offset, length, origcsum); + offset = 0; + length = 0; + origcsum = NULL; + } + } + +} + +int main(int argc, char *argv[]) { + char *file = argv[1]; + xar_t x; + xar_iter_t ifile, iprop, iattr; + xar_file_t f; + const char *key; + int fd; + off_t off; + xar_header_t hdr; + + x = xar_open(file, READ); + if( !x ) { + fprintf(stderr, "Error opening archive\n"); + exit(1); + } + + fd = open(file, O_RDONLY); + if( fd < 0 ) { + fprintf(stderr, "Error opening archive\n"); + exit(1); + } + + read(fd, &hdr, sizeof(hdr)); + hdr.size = htons(hdr.size); + hdr.toc_length_compressed = xar_ntoh64(hdr.toc_length_compressed); + HeapOff = hdr.size + hdr.toc_length_compressed; + + ifile = xar_iter_new(); + if( !ifile ) { + fprintf(stderr, "Error creating file iterator"); + exit(1); + } + + for(f = xar_file_first(x, ifile); f; f = xar_file_next(ifile)) { + prop_check(fd, x, f); + } + +} diff --git a/xar/xar.spec b/xar/xar.spec new file mode 100644 index 0000000..c0d13e6 --- /dev/null +++ b/xar/xar.spec @@ -0,0 +1,98 @@ +Summary: The XAR project aims to provide an easily extensible archive format. +Name: xar +Version: 1.8dev +Release: 0 +License: BSD +Group: Applications/Archiving +URL: http://code.google.com/p/%{name}/ +Source: http://%{name}.googlecode.com/files/%{name}-%{version}.tar.gz +BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root +%ifos linux +BuildRequires: libxml2-devel >= 2.6.11 +BuildRequires: openssl-devel +BuildRequires: bzip2-devel +BuildRequires: zlib-devel +BuildRequires: /usr/bin/awk +%endif + +%description +The XAR project aims to provide an easily extensible archive format. Important +design decisions include an easily extensible XML table of contents for random +access to archived files, storing the toc at the beginning of the archive to +allow for efficient handling of streamed archives, the ability to handle files +of arbitrarily large sizes, the ability to choose independent encodings for +individual files in the archive, the ability to store checksums for individual +files in both compressed and uncompressed form, and the ability to query the +table of content's rich meta-data. + +%package devel +Summary: Libraries and header files required for xar. +Group: Development/Libraries +Requires: %{name} = %{version}-%{release} + +%description devel +Libraries and header files required for xar. + +%prep +%setup -q -n %{name}-%{version} + +%build +%configure --disable-static +%{__make} %{?_smp_mflags} + +%install +%{__rm} -rf $RPM_BUILD_ROOT +%{__make} install DESTDIR=%{buildroot} + +%clean +%{__rm} -rf $RPM_BUILD_ROOT + +%ifos linux +%post -p /sbin/ldconfig + +%postun -p /sbin/ldconfig +%endif + +%files +%defattr(-,root,root,-) +%doc LICENSE TODO +%{_bindir}/%{name} +%ifnos darwin +%{_libdir}/lib%{name}.so.* +%else +%{_libdir}/lib%{name}.*.dylib +%endif +%{_mandir}/man1/xar.1* + +%files devel +%defattr(-,root,root,-) +%{_includedir}/%{name}/%{name}.h +%ifnos darwin +%{_libdir}/lib%{name}.so +%else +%{_libdir}/lib%{name}.dylib +%endif +%exclude %{_libdir}/lib%{name}.la + +%changelog +* Wed Sep 12 2007 Anders F Bjorklund 1.5.1-0 +- fixed spec, made darwin compatible +- moved non-versioned lib from devel + +* Mon May 07 2007 Rob Braun 0:1.5-1 +- 1.5 +* Thu Feb 23 2006 Rob Braun - 0:1.2-1 +- 1.4 +* Mon Oct 24 2005 Rob Braun - 0:1.2-1 +- 1.3 +* Wed Sep 21 2005 Jason Corley - 0:1.1-1 +- 1.1 +- correct library version +- add specific version to libxml requirements + +* Fri Sep 09 2005 Jason Corley - 0:1.0-1 +- 1.0 + +* Sat Apr 23 2005 Jason Corley - 0:0.0.0-0.20050423.0 +- Initial RPM release. + diff --git a/xar/xar.spec.in b/xar/xar.spec.in new file mode 100644 index 0000000..2e5cb1d --- /dev/null +++ b/xar/xar.spec.in @@ -0,0 +1,98 @@ +Summary: The XAR project aims to provide an easily extensible archive format. +Name: xar +Version: @XAR_VERSION@ +Release: 0 +License: BSD +Group: Applications/Archiving +URL: http://code.google.com/p/%{name}/ +Source: http://%{name}.googlecode.com/files/%{name}-%{version}.tar.gz +BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root +%ifos linux +BuildRequires: libxml2-devel >= 2.6.11 +BuildRequires: openssl-devel +BuildRequires: bzip2-devel +BuildRequires: zlib-devel +BuildRequires: /usr/bin/awk +%endif + +%description +The XAR project aims to provide an easily extensible archive format. Important +design decisions include an easily extensible XML table of contents for random +access to archived files, storing the toc at the beginning of the archive to +allow for efficient handling of streamed archives, the ability to handle files +of arbitrarily large sizes, the ability to choose independent encodings for +individual files in the archive, the ability to store checksums for individual +files in both compressed and uncompressed form, and the ability to query the +table of content's rich meta-data. + +%package devel +Summary: Libraries and header files required for xar. +Group: Development/Libraries +Requires: %{name} = %{version}-%{release} + +%description devel +Libraries and header files required for xar. + +%prep +%setup -q -n %{name}-%{version} + +%build +%configure --disable-static +%{__make} %{?_smp_mflags} + +%install +%{__rm} -rf $RPM_BUILD_ROOT +%{__make} install DESTDIR=%{buildroot} + +%clean +%{__rm} -rf $RPM_BUILD_ROOT + +%ifos linux +%post -p /sbin/ldconfig + +%postun -p /sbin/ldconfig +%endif + +%files +%defattr(-,root,root,-) +%doc LICENSE TODO +%{_bindir}/%{name} +%ifnos darwin +%{_libdir}/lib%{name}.so.* +%else +%{_libdir}/lib%{name}.*.dylib +%endif +%{_mandir}/man1/xar.1* + +%files devel +%defattr(-,root,root,-) +%{_includedir}/%{name}/%{name}.h +%ifnos darwin +%{_libdir}/lib%{name}.so +%else +%{_libdir}/lib%{name}.dylib +%endif +%exclude %{_libdir}/lib%{name}.la + +%changelog +* Wed Sep 12 2007 Anders F Bjorklund 1.5.1-0 +- fixed spec, made darwin compatible +- moved non-versioned lib from devel + +* Mon May 07 2007 Rob Braun 0:1.5-1 +- 1.5 +* Thu Feb 23 2006 Rob Braun - 0:1.2-1 +- 1.4 +* Mon Oct 24 2005 Rob Braun - 0:1.2-1 +- 1.3 +* Wed Sep 21 2005 Jason Corley - 0:1.1-1 +- 1.1 +- correct library version +- add specific version to libxml requirements + +* Fri Sep 09 2005 Jason Corley - 0:1.0-1 +- 1.0 + +* Sat Apr 23 2005 Jason Corley - 0:0.0.0-0.20050423.0 +- Initial RPM release. + diff --git a/xarsig/xar-sig.c b/xarsig/xar-sig.c new file mode 100644 index 0000000..5feda74 --- /dev/null +++ b/xarsig/xar-sig.c @@ -0,0 +1,1552 @@ +/* + * Copyright (c) 2005 Rob Braun + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Rob Braun nor the names of his contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +/* + * 03-Apr-2005 + * DRI: Rob Braun + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef XARSIG_BUILDING_WITH_XAR +#include "xar.h" +#else +#include +#endif // XARSIG_BUILDING_WITH_XAR +#include "filetree.h" + +#define SYMBOLIC 1 +#define NUMERIC 2 + +// error codes for B&I +#define E_NOSIG 60 +#define E_SIGEXISTS 61 + +extern char **environ; + +static int Perms = 0; +static int Local = 0; +static char *Subdoc = NULL; +static char *SubdocName = NULL; +static char *Toccksum = NULL; +static char *Filecksum = NULL; +static char *Compression = NULL; +static char *Rsize = NULL; +static char *DataToSignDumpPath = NULL; +static char *SigOffsetDumpPath = NULL; +static char *LeafCertPath = NULL; +static char *IntermediateCertPath = NULL; +static char *RootCertPath = NULL; + +static int Err = 0; +static int Verbose = 0; +static int Coalesce = 0; +static int LinkSame = 0; +static int DoSign = 0; + +static long SigSize = 0; + +struct lnode { + char *str; + regex_t reg; + struct lnode *next; +}; +struct __stack_element { + struct __stack_element *prev; + struct __stack_element *next; + void *data; +}; +struct __stack { + struct __stack_element *bottom; + struct __stack_element *top; +}; + +typedef struct __stack_element *stack_element; +typedef struct __stack *stack; + +struct lnode *Exclude = NULL; +struct lnode *Exclude_Tail = NULL; +struct lnode *NoCompress = NULL; +struct lnode *NoCompress_Tail = NULL; + +static int32_t err_callback(int32_t sev, int32_t err, xar_errctx_t ctx, void *usrctx); +static int32_t signingCallback(xar_signature_t sig, void *context, uint8_t *data, uint32_t length, uint8_t **signed_data, uint32_t *signed_len); +static void insert_cert(xar_signature_t sig, const char *cert_path); +static void add_subdoc(xar_t x); + +static void _set_xarsig_opts_from_args(xar_t x) { + // Update checksum algorithms before we start messing with the heap length in xar_signature_new() + if( Toccksum ) + xar_opt_set(x, XAR_OPT_TOCCKSUM, Toccksum); + + if( Filecksum ) + xar_opt_set(x, XAR_OPT_FILECKSUM, Filecksum); + + if ( SigSize ) { + xar_signature_t sig = xar_signature_new(x, "RSA", SigSize, &signingCallback, NULL); + if ( LeafCertPath ) + insert_cert(sig, LeafCertPath); + if ( IntermediateCertPath ) + insert_cert(sig, IntermediateCertPath); + if ( RootCertPath ) + insert_cert(sig, RootCertPath); + } + + if( Compression ) + xar_opt_set(x, XAR_OPT_COMPRESSION, Compression); + + if( Coalesce ) + xar_opt_set(x, XAR_OPT_COALESCE, "true"); + + if( LinkSame ) + xar_opt_set(x, XAR_OPT_LINKSAME, "true"); + + if ( Rsize != NULL ) + xar_opt_set(x, XAR_OPT_RSIZE, Rsize); + + xar_register_errhandler(x, err_callback, NULL); + + if( Subdoc ) + add_subdoc(x); + + if( Perms == SYMBOLIC ) { + xar_opt_set(x, XAR_OPT_OWNERSHIP, XAR_OPT_VAL_SYMBOLIC); + } + if( Perms == NUMERIC ) { + xar_opt_set(x, XAR_OPT_OWNERSHIP, XAR_OPT_VAL_NUMERIC); + } +} + +static void print_file(xar_file_t f) { + if( Verbose ) { + char *path = xar_get_path(f); + printf("%s\n", path); + free(path); + } +} + +static void add_subdoc(xar_t x) { + xar_subdoc_t s; + int fd; + unsigned char *buf; + unsigned int len; + struct stat sb; + + if( SubdocName == NULL ) SubdocName = "subdoc"; + s = xar_subdoc_new(x, (const char *)SubdocName); + + fd = open(Subdoc, O_RDONLY); + if( fd < 0 ) + return; + fstat(fd, &sb); + len = sb.st_size; + buf = malloc(len+1); + if( buf == NULL ) { + close(fd); + return; + } + memset(buf, 0, len+1); + read(fd, buf, len); + close(fd); + + xar_subdoc_copyin(s, buf, len); + + + return; +} + +static void extract_subdoc(xar_t x, const char *name) { + xar_subdoc_t i; + + for( i = xar_subdoc_first(x); i; i = xar_subdoc_next(i) ) { + const char *sname = xar_subdoc_name(i); + unsigned char *sdoc; + int fd, size; + if( name && strcmp(name, sname) != 0 ) + continue; + xar_subdoc_copyout(i, &sdoc, (unsigned int *)&size); + fd = open(Subdoc, O_WRONLY|O_CREAT|O_TRUNC, 0644); + if( fd < 0 ) return; + write(fd, sdoc, size); + close(fd); + free(sdoc); + } + + return; +} + +static void extract_data_to_sign(const char *filename) { + xar_signature_t sig; + off_t signatureOffset; + FILE *file; + xar_t x; + int i; + uint32_t dataToSignOffset = 0; + uint32_t dataToSignSize = 0; + char *buffer = NULL; + const char *value; + + // find signature stub + x = xar_open(filename, READ); + if ( x == NULL ) { + fprintf(stderr, "Could not open %s to extract data to sign!\n", filename); + exit(1); + } + sig = xar_signature_first(x); + if ( !sig ) { + fprintf(stderr, "No signatures found to extract data from.\n"); + exit(E_NOSIG); + } + + // locate data to sign + if( 0 != xar_prop_get((xar_file_t)x, "checksum/offset" ,&value) ) { + fprintf(stderr, "Could not locate checksum/offset in archive.\n"); + exit(1); + } + dataToSignOffset = xar_get_heap_offset(x); + dataToSignOffset += strtoull(value, (char **)NULL, 10); + if( 0 != xar_prop_get((xar_file_t)x, "checksum/size" ,&value) ) { + fprintf(stderr, "Could not locate checksum/size in archive.\n"); + exit(1); + } + dataToSignSize = strtoull(value, (char **)NULL, 10); + + // get signature offset (inject signature here) + xar_signature_copy_signed_data(sig, NULL, NULL, NULL, NULL, &signatureOffset); + signatureOffset += xar_get_heap_offset(x); + xar_close(x); + + // now get data to be signed, using offset and size + file = fopen(filename, "r"); + if (!file) { + fprintf(stderr, "Could not open %s for reading data to sign!\n", filename); + exit(1); + } + fseek(file, dataToSignOffset, SEEK_SET); + buffer = malloc(dataToSignSize); + i = fread(buffer, dataToSignSize, 1, file); + if (i != 1) { + fprintf(stderr, "Failed to read data to sign from %s!\n", filename); + exit(1); + } + fclose(file); + + // save data to sign + file = fopen(DataToSignDumpPath, "w"); + if (!file) { + fprintf(stderr, "Could not open %s for saving data to sign!\n", DataToSignDumpPath); + exit(1); + } + i = fwrite(buffer, dataToSignSize, 1, file); + if (i != 1) { + fprintf(stderr, "Failed to write data to sign to %s (fwrite() returned %i)!\n", DataToSignDumpPath, i); + exit(1); + } + fclose(file); + + // save signature offset + file = fopen(SigOffsetDumpPath, "w"); + if (!file) { + fprintf(stderr, "Could not open %s for saving signature offset!\n", SigOffsetDumpPath); + exit(1); + } + i = fprintf(file, "%lli\n", signatureOffset); + if (i < 0) { + fprintf(stderr, "Failed to write signature offset to %s (fprintf() returned %i)!\n", SigOffsetDumpPath, i); + exit(1); + } + fclose(file); + + free(buffer); +} + +static void extract_certs(char *filename, char *cert_base_path) { + xar_signature_t sig; + xar_t x; + int32_t count; + int i; + const uint8_t *cert_data; + uint32_t cert_len; + FILE *file; + char *cert_path; + + // open xar, get signature + x = xar_open(filename, READ); + if ( x == NULL ) { + fprintf(stderr, "Could not open %s to extract certificates!\n", filename); + exit(1); + } + sig = xar_signature_first(x); + if ( !sig ) { + fprintf(stderr, "No signatures found to extract data from.\n"); + exit(E_NOSIG); + } + + // iterate through all certificates associated with that signature, write them to disk + count = xar_signature_get_x509certificate_count(sig); + if (!count) { + fprintf(stderr, "Signature bears no certificates. Odd.\n"); + exit(1); + } + for (i=0; ibottom = s->top = NULL; + return s; +} +void stack_free(stack s) { + free(s); +} +void stack_push(stack s, void *data) { + stack_element e = malloc(sizeof(struct __stack_element)); + e->data = data; + if (s->top) { + s->top->next = e; + e->prev = s->top; + } else { + s->top = s->bottom = e; + e->prev = NULL; + } + e->next = NULL; + s->top = e; +} +void *stack_pop(stack s) { + if (!s->top) + return NULL; + void *ret = s->top->data; + stack_element temp = s->top; + s->top = s->top->prev; + free(temp); + if (s->top) + s->top->next = NULL; + else + s->bottom = NULL; + return ret; +} + +/* replace_sign: rip out all current signatures and certs and insert a new pair + Since libxar is currently not capable of doing this directly, we have to create a new xar archive, + copy all the files and options from the current archive, and sign the new archive +*/ +static void replace_sign(const char *filename) { + + xar_t old_xar, new_xar; + xar_signature_t sig; + char *new_xar_path = (char *)malloc(15); + strncpy(new_xar_path, "/tmp/xar.XXXXX", 15); + new_xar_path = mktemp(new_xar_path); + int err; + pid_t pid; + char **argv; + int status; + + // open the first archive + old_xar = xar_open(filename, READ); + if ( old_xar == NULL ) { + fprintf(stderr, "Could not open archive %s!\n", filename); + exit(1); + } + + // use command-line arguments to set xar opts; the copy operation below won't work unless they're set in the first place! + _set_xarsig_opts_from_args(old_xar); + + // open the second archive + new_xar = xar_open(new_xar_path, WRITE); + if( !new_xar ) { + fprintf(stderr, "Error creating new archive %s\n", new_xar_path); + exit(1); + } + + // copy options + char *opts[7] = {XAR_OPT_TOCCKSUM, XAR_OPT_FILECKSUM, XAR_OPT_COMPRESSION, XAR_OPT_COALESCE, XAR_OPT_LINKSAME, XAR_OPT_RSIZE, XAR_OPT_OWNERSHIP}; + int i; + const char *opt; + for (i=0; i<7; i++) { + opt = xar_opt_get(old_xar, opts[i]); + if (opt) + xar_opt_set(new_xar, opts[i], opt); + } + + // install new signature and new certs in new_xar + sig = xar_signature_new(new_xar, "RSA", SigSize, &signingCallback, NULL); + if ( LeafCertPath ) + insert_cert(sig, LeafCertPath); + if ( IntermediateCertPath ) + insert_cert(sig, IntermediateCertPath); + if ( RootCertPath ) + insert_cert(sig, RootCertPath); + + // skip copy subdocs for now since we don't use them yet + + // copy files + xar_iter_t iter = xar_iter_new(); + xar_file_t f = xar_file_first(old_xar, iter); + // xar_file_next iterates the archive depth-first, i.e. all children are enumerated before the siblings. + const char *name; + stack s_new = stack_new(); + stack s_old = stack_new(); + xar_file_t last_copied = NULL, last_added; + + xar_iter_t loopIter = xar_iter_new(); + xar_file_t current_xar_file; + for (current_xar_file = xar_file_first(old_xar, loopIter); current_xar_file; current_xar_file = xar_file_next(loopIter)) + { + printf("old_xar -> %s (parent: %s)\n",xar_get_path(current_xar_file),XAR_FILE(current_xar_file)->parent?xar_get_path(XAR_FILE(current_xar_file)->parent):"(nil)"); + } + + do { + // parent is the parent in the new archive! + // 3 cases: + // 1. the file has no parent. Happens for every file at the top level of the archive. + // 2. the file's parent is the last file we added. Happens while descending down a path + // 3. the file's parent is one of the ancestors of the last file (and not NULL, that would be case 1) + // that means we either go back up the tree and add a sibling of one of the ancestors, or we add a + // sibling on the same level + xar_prop_get(f, "name", &name); // filename, without any path info + if (!XAR_FILE(f)->parent) { // case 1 + printf("root: %s\n",xar_get_path(f)); + last_added = xar_add_from_archive(new_xar, NULL, name, old_xar, f); + last_copied = f; + stack_push(s_new, (void *)last_added); + stack_push(s_old, (void *)last_copied); + } else if (f->parent == last_copied) { // case 2 + printf("child: %s -> %s\n",xar_get_path(f->parent),xar_get_path(f)); + last_added = xar_add_from_archive(new_xar, last_added, name, old_xar, f); + last_copied = f; + stack_push(s_new, (void *)last_added); + stack_push(s_old, (void *)last_copied); + } else { // case 3 + printf("searching for parent: %s ?\n",xar_get_path(f)); + while (XAR_FILE(f)->parent != XAR_FILE(s_old->top->data)->parent) { + printf("popping: %s\n",xar_get_path(XAR_FILE(s_old->top->data))); + stack_pop(s_new); + stack_pop(s_old); + } + printf("found: %s -> %s\n",xar_get_path(XAR_FILE(s_new->top->data)),xar_get_path(f)); + stack_pop(s_new); + stack_pop(s_old); + last_added = xar_add_from_archive(new_xar, (xar_file_t)(s_new->top->data), name, old_xar, f); + last_copied = f; + stack_push(s_new, (void *)last_added); + stack_push(s_old, (void *)last_copied); + } + } while ((f = xar_file_next(iter))); + + loopIter = xar_iter_new(); + for (current_xar_file = xar_file_first(new_xar, loopIter); current_xar_file; current_xar_file = xar_file_next(loopIter)) + { + char * current_path = xar_get_path(current_xar_file); + printf("new_xar -> %s\n",current_path); + } + + xar_iter_free(iter); + stack_free(s_new); + stack_free(s_old); + if( xar_close(new_xar) != 0 ) { + fprintf(stderr, "Error creating the archive\n"); + if( !Err ) + Err = 42; + } + xar_close(old_xar); + + // write signature offset to file (have to re-open so xar_close can figure out the correct offset) + new_xar = xar_open(new_xar_path, READ); + if( !new_xar ) { + fprintf(stderr, "Error re-opening new archive %s\n", new_xar_path); + unlink(new_xar_path); + exit(1); + } + + if (extract_sig_offset(new_xar, SigOffsetDumpPath)) { + xar_close(new_xar); + unlink(new_xar_path); + exit(1); + } + + xar_close(new_xar); + + // delete old archive, move new in its place + unlink(filename); + argv = calloc(sizeof(char *), 4); + argv[0] = "cp"; + argv[1] = new_xar_path; + argv[2] = (char *)filename; + err = posix_spawn(&pid, "/bin/cp", NULL, NULL, argv, environ); + free(argv); + + if (err) { + fprintf(stderr, "Could not copy new archive to final location (posix_spawn(3) failed with %d)\n", errno); + unlink(new_xar_path); + exit(1); + } + + do { + err = waitpid(pid, &status, 0); + if (err == pid) { + if (WIFEXITED(status)) { + if (WEXITSTATUS(status) != 0) { + fprintf(stderr, "Could not copy new archive to final location (cp(1) exited %d)\n", WEXITSTATUS(status)); + unlink(new_xar_path); + exit(1); + } + break; + } + } else { + fprintf(stderr, "Could not copy new archive to final location (waidpid(2) failed with %d)\n", errno); + unlink(new_xar_path); + exit(1); + } + } while (1); + + // Delete the tmp archive + unlink(new_xar_path); +} + +/* belated_sign + Prepare a previously unsigned archive for signing by creating a signature placeholder and inserting the certificates. + Since libxar is currently not capable of doing this directly, we have to create a new xar archive, + copy all the files and options from the current archive, and sign the new archive +*/ +static void belated_sign(const char *filename) { + xar_t x = xar_open(filename, READ); + if ( x == NULL ) { + fprintf(stderr, "Could not open archive %s!\n", filename); + exit(1); + } + xar_signature_t sig = xar_signature_first(x); + if ( sig ) { + fprintf(stderr, "Archive has already been signed. Use --replace-sign instead.\n"); + exit(E_SIGEXISTS); + } + xar_close(x); + replace_sign(filename); +} + +static int32_t signingCallback(xar_signature_t sig, void *context, uint8_t *data, uint32_t length, uint8_t **signed_data, uint32_t *signed_len) { + + // save data to file for later signature + if (DataToSignDumpPath) { + FILE *file = fopen(DataToSignDumpPath, "w"); + if (!file) { + fprintf(stderr, "Could not open %s for saving data to sign!\n", DataToSignDumpPath); + exit(1); + } + int i = fwrite(data, length, 1, file); + if (i != 1) { + fprintf(stderr, "Failed to write data to sign to %s (fwrite() returned %i)!\n", DataToSignDumpPath, i); + exit(1); + } + fclose(file); + } + + // now return blank placeholder data + *signed_data = (uint8_t *)malloc(SigSize); + memset(*signed_data, 0, SigSize); + strncpy((char *)*signed_data, "helloworld", 10); // debug + *signed_len = SigSize; + return 0; // no error +} + +static void insert_cert(xar_signature_t sig, const char *cert_path) { + struct stat *s = malloc(sizeof(struct stat)); + if (stat(cert_path, s) == -1) { + fprintf(stderr, "Could not stat() certificate file %s (errno == %i)\n", cert_path, errno); + exit(1); + } + void *cert = malloc(s->st_size); + FILE *file = fopen(cert_path, "r"); + if (!file) { + fprintf(stderr, "Could not open %s for reading certificate!\n", cert_path); + exit(1); + } + int i = fread(cert, s->st_size, 1, file); + if (i != 1) { + fprintf(stderr, "Failed to read certificate from %s!\n", cert_path); + exit(1); + } + fclose(file); + xar_signature_add_x509certificate(sig, cert, s->st_size); + free(s); + free(cert); +} + +static void inject_signature(const char *xar_path, const char *sig_path) { + // since there is no API to insert a signature other than during signingCallback time, we have to + // inject it by editing the raw file + int buffer_size = 1024; + void *buffer = malloc(buffer_size); + FILE *sig, *xar; + off_t signedDataOffset; + xar_t x; + int i; + + printf("inject_signature(%s, %s)",xar_path,sig_path); + + // open xar via the API first to determine the signature offset + x = xar_open(xar_path, READ); + if ( x == NULL ) { + fprintf(stderr, "Could not open xar archive %s to get signature offset!\n", xar_path); + exit(1); + } + signedDataOffset = get_sig_offset(x); + xar_close(x); + + // then re-open xar and signature files raw... + sig = fopen(sig_path, "r"); + if (!sig) { + fprintf(stderr, "Could not open %s for reading signature!\n", sig_path); + exit(1); + } + xar = fopen(xar_path, "r+"); + if (!xar) { + fprintf(stderr, "Could not open xar archive %s for injecting signature!\n", xar_path); + exit(1); + } + + // ...and inject the signature + fseek(xar, signedDataOffset, SEEK_SET); + do { + i = fread(buffer, 1, buffer_size, sig); + if (ferror(sig)) { + fprintf(stderr, "Failed to read signature from %s!\n", sig_path); + exit(1); + } + fwrite(buffer, 1, i, xar); + } while (!feof(sig)); + fclose(sig); + fclose(xar); + + free(buffer); +} + +static int archive(const char *filename, int arglen, char *args[]) { + xar_t x; + FTS *fts; + FTSENT *ent; + int flags; + struct lnode *i; + const char *default_compression; + + x = xar_open(filename, WRITE); + if( !x ) { + fprintf(stderr, "Error creating archive %s\n", filename); + exit(1); + } + + _set_xarsig_opts_from_args(x); + + default_compression = strdup(xar_opt_get(x, XAR_OPT_COMPRESSION)); + if( !default_compression ) + default_compression = strdup(XAR_OPT_VAL_GZIP); + + flags = FTS_PHYSICAL|FTS_NOSTAT|FTS_NOCHDIR; + if( Local ) + flags |= FTS_XDEV; + fts = fts_open(args, flags, NULL); + if( !fts ) { + fprintf(stderr, "Error traversing file tree\n"); + exit(1); + } + + while( (ent = fts_read(fts)) ) { + xar_file_t f; + int exclude_match = 1; + int nocompress_match = 1; + if( ent->fts_info == FTS_DP ) + continue; + + if( strcmp(ent->fts_path, "/") == 0 ) + continue; + if( strcmp(ent->fts_path, ".") == 0 ) + continue; + + for( i = Exclude; i; i=i->next ) { + exclude_match = regexec(&i->reg, ent->fts_path, 0, NULL, 0); + if( !exclude_match ) + break; + } + if( !exclude_match ) { + if( Verbose ) + printf("Excluding %s\n", ent->fts_path); + continue; + } + + for( i = NoCompress; i; i=i->next ) { + nocompress_match = regexec(&i->reg, ent->fts_path, 0, NULL, 0); + if( !nocompress_match ) { + xar_opt_set(x, XAR_OPT_COMPRESSION, XAR_OPT_VAL_NONE); + break; + } + } + f = xar_add(x, ent->fts_path); + if( !f ) { + fprintf(stderr, "Error adding file %s\n", ent->fts_path); + } else { + print_file(f); + } + if( !nocompress_match ) + xar_opt_set(x, XAR_OPT_COMPRESSION, default_compression); + } + fts_close(fts); + if( xar_close(x) != 0 ) { + fprintf(stderr, "Error creating the archive\n"); + if( !Err ) + Err = 42; + } + + free((char *)default_compression); + for( i = Exclude; i; ) { + struct lnode *tmp; + regfree(&i->reg); + tmp = i; + i = i->next; + free(tmp); + } + for( i = NoCompress; i; ) { + struct lnode *tmp; + regfree(&i->reg); + tmp = i; + i = i->next; + free(tmp); + } + + if ( SigOffsetDumpPath ) { + x = xar_open(filename, READ); + if( !x ) { + fprintf(stderr, "Error re-opening archive %s\n", filename); + exit(1); + } + if (extract_sig_offset(x, SigOffsetDumpPath)) + exit(1); + } + + return Err; +} + +static int extract(const char *filename, int arglen, char *args[]) { + xar_t x; + xar_iter_t i; + xar_file_t f; + int files_extracted = 0; + + x = xar_open(filename, READ); + if( !x ) { + fprintf(stderr, "Error opening xar archive: %s\n", filename); + exit(1); + } + + xar_register_errhandler(x, err_callback, NULL); + + if( Perms == SYMBOLIC ) { + xar_opt_set(x, XAR_OPT_OWNERSHIP, XAR_OPT_VAL_SYMBOLIC); + } + if( Perms == NUMERIC ) { + xar_opt_set(x, XAR_OPT_OWNERSHIP, XAR_OPT_VAL_NUMERIC); + } + if ( Rsize != NULL ) { + xar_opt_set(x, XAR_OPT_RSIZE, Rsize); + } + + i = xar_iter_new(); + if( !i ) { + fprintf(stderr, "Error creating xar iterator\n"); + exit(1); + } + + for(f = xar_file_first(x, i); f; f = xar_file_next(i)) { + int matched = 0; + int exclude_match = 1; + struct lnode *i; + + char *path = xar_get_path(f); + + if( args[0] ) { + int i; + for(i = 0; args[i]; i++) { + if( strcmp(path, args[i]) == 0 ) { + matched = 1; + break; + } + } + } else { + matched = 1; + } + + for( i = Exclude; i; i=i->next ) { + exclude_match = regexec(&i->reg, path, 0, NULL, 0); + if( !exclude_match ) + break; + } + if( !exclude_match ) { + if( Verbose ) + printf("Excluding %s\n", path); + free(path); + continue; + } + + if( matched ) { + files_extracted++; + print_file(f); + xar_extract(x, f); + } + free(path); + } + if( args[0] && (files_extracted == 0) ) { + fprintf(stderr, "No files matched extraction criteria.\n"); + Err = 3; + } + + if( Subdoc ) + extract_subdoc(x, NULL); + + xar_iter_free(i); + if( xar_close(x) != 0 ) { + fprintf(stderr, "Error extracting the archive\n"); + if( !Err ) + Err = 42; + } + return Err; +} + +static int list_subdocs(const char *filename) { + xar_t x; + xar_subdoc_t s; + + x = xar_open(filename, READ); + if( !x ) { + fprintf(stderr, "Error opening xar archive: %s\n", filename); + exit(1); + } + + for(s = xar_subdoc_first(x); s; s = xar_subdoc_next(s)) { + printf("%s\n", xar_subdoc_name(s)); + } + xar_close(x); + + return Err; +} + +static int list(const char *filename, int arglen, char *args[]) { + xar_t x; + xar_iter_t i; + xar_file_t f; + + x = xar_open(filename, READ); + if( !x ) { + fprintf(stderr, "Error opening xar archive: %s\n", filename); + exit(1); + } + + i = xar_iter_new(); + if( !i ) { + fprintf(stderr, "Error creating xar iterator\n"); + exit(1); + } + + for(f = xar_file_first(x, i); f; f = xar_file_next(i)) { + print_file(f); + } + + xar_iter_free(i); + xar_close(x); + + return Err; +} + +static int dumptoc(const char *filename, const char* tocfile) { + xar_t x; + x = xar_open(filename, READ); + if( !x ) { + fprintf(stderr, "Error opening xar archive: %s\n", filename); + exit(1); + } + + xar_serialize(x, tocfile); + xar_close(x); + return Err; +} + +static int dump_header(const char *filename) { + int fd; + xar_header_t xh; + + if(filename == NULL) + fd = 0; + else { + fd = open(filename, O_RDONLY); + if( fd < 0 ) { + perror("open"); + exit(1); + } + } + + if( read(fd, &xh, sizeof(xh)) < sizeof(xh) ) { + fprintf(stderr, "error reading header\n"); + exit(1); + } + + printf("magic: 0x%x ", ntohl(xh.magic)); + if( ntohl(xh.magic) != XAR_HEADER_MAGIC ) + printf("(BAD)\n"); + else + printf("(OK)\n"); + printf("size: %d\n", ntohs(xh.size)); + printf("version: %d\n", ntohs(xh.version)); + printf("Compressed TOC length: %" PRId64 "\n", xar_ntoh64(xh.toc_length_compressed)); + printf("Uncompressed TOC length: %" PRId64 "\n", xar_ntoh64(xh.toc_length_uncompressed)); + printf("Checksum algorithm: %d ", ntohl(xh.cksum_alg)); + switch( ntohl(xh.cksum_alg) ) { + case XAR_CKSUM_NONE: printf("(unsupported (none))\n"); + break; + case XAR_CKSUM_SHA1: printf("(SHA1)\n"); + break; + case XAR_CKSUM_SHA256: printf("(SHA256)\n"); + break; + case XAR_CKSUM_SHA512: printf("(SHA512)\n"); + break; +#ifdef XAR_SUPOPRT_MD5 + case XAR_CKSUM_MD5: printf("(MD5)\n"); + break; +#else + case XAR_CKSUM_MD5: printf("(unsupported (MD5))\n"); + break; +#endif // XAR_SUPPORT_MD5 + default: printf("(unknown)\n"); + break; + }; + + return 0; +} + +static int32_t err_callback(int32_t sev, int32_t err, xar_errctx_t ctx, void *usrctx) { + xar_file_t f; + const char *str; + int e; + + f = xar_err_get_file(ctx); + str = xar_err_get_string(ctx); + e = xar_err_get_errno(ctx); + + switch(sev) { + case XAR_SEVERITY_DEBUG: + case XAR_SEVERITY_INFO: + break; + case XAR_SEVERITY_WARNING: + printf("%s\n", str); + break; + case XAR_SEVERITY_NORMAL: + if( (err = XAR_ERR_ARCHIVE_CREATION) && f ) + print_file(f); + break; + case XAR_SEVERITY_NONFATAL: + case XAR_SEVERITY_FATAL: + Err = 2; + printf("Error while "); + if( err == XAR_ERR_ARCHIVE_CREATION ) printf("creating"); + if( err == XAR_ERR_ARCHIVE_EXTRACTION ) printf("extracting"); + printf(" archive"); + if( f ) { + const char *file = xar_get_path(f); + if( file ) printf(":(%s)", file); + free((char *)file); + } + if( str ) printf(": %s", str); + if( err ) printf(" (%s)", strerror(e)); + if( sev == XAR_SEVERITY_NONFATAL ) { + printf(" - ignored"); + printf("\n"); + } else { + printf("\n"); + exit(1); + } + break; + } + return 0; +} + +static void usage(const char *prog) { + fprintf(stderr, "Usage: %s -[ctx][v] -f ...\n", prog); + fprintf(stderr, "\t-c Creates an archive\n"); + fprintf(stderr, "\t-x Extracts an archive\n"); + fprintf(stderr, "\t-t Lists an archive\n"); + fprintf(stderr, "\t--sign Creates a placeholder signature and saves\n"); + fprintf(stderr, "\t the data to sign to disk. Works with -c or -f, requires\n"); + fprintf(stderr, "\t --sig-size, --leaf-cert-loc and \n"); + fprintf(stderr, "\t --intermediate-cert-loc to be set. Setting\n"); + fprintf(stderr, "\t --data-to-sign and --sig-offset is optional.\n"); + fprintf(stderr, "\t Fails with error code %i if the archive has already\n", E_SIGEXISTS); + fprintf(stderr, "\t been signed.\n"); + fprintf(stderr, "\t--replace-sign Rips out existing signature(s) and makes a new one.\n"); + fprintf(stderr, "\t Same required parameter set as --sign, \n"); + fprintf(stderr, "\t but -f instead of -c.\n"); + fprintf(stderr, "\t--extract-data-to-sign Extracts data to be signed from an\n"); + fprintf(stderr, "\t existing archive. Requires --data-to-sign\n"); + fprintf(stderr, "\t and --sig-offset (and -f) to be set.\n"); + fprintf(stderr, "\t--extract-certs Extracts all certificates into the\n"); + fprintf(stderr, "\t specified directory, naming them 'cert1', 'cert2' etc.\n"); + fprintf(stderr, "\t Requires -f.\n"); + fprintf(stderr, "\t--inject-sig After extracting the data to be signed and\n"); + fprintf(stderr, "\t doing the signing externally, injects.\n"); + fprintf(stderr, "\t the signature. Requires -f\n"); + fprintf(stderr, "\t-f Specifies an archive to operate on [REQUIRED!]\n"); + fprintf(stderr, "\t-v Print filenames as they are archived\n"); + fprintf(stderr, "\t-n name Provides a name for a subdocument\n"); + fprintf(stderr, "\t-s On extract, specifies the file to extract\n"); + fprintf(stderr, "\t subdocuments to.\n"); + fprintf(stderr, "\t On archival, specifies an xml file to add\n"); + fprintf(stderr, "\t as a subdocument.\n"); + fprintf(stderr, "\t-l On archival, stay on the local device.\n"); + fprintf(stderr, "\t-p On extract, set ownership based on symbolic\n"); + fprintf(stderr, "\t names, if possible.\n"); + fprintf(stderr, "\t-P On extract, set ownership based on uid/gid.\n"); + fprintf(stderr, "\t--toc-cksum Specifies the hashing algorithm to use for\n"); + fprintf(stderr, "\t xml header verification.\n"); +#ifdef XAR_SUPPORT_MD5 + fprintf(stderr, "\t Valid values: none, md5, sha1, sha256, and sha512\n"); +#else + fprintf(stderr, "\t Valid values: none, sha1, sha256, and sha512\n"); +#endif // XAR_SUPPORT_MD5 + fprintf(stderr, "\t Default: sha1\n"); + fprintf(stderr, "\t--file-cksum Specifies the hashing algorithm to use for\n"); + fprintf(stderr, "\t xml header verification.\n"); +#ifdef XAR_SUPPORT_MD5 + fprintf(stderr, "\t Valid values: none, md5, sha1, sha256, and sha512\n"); +#else + fprintf(stderr, "\t Valid values: none, sha1, sha256, and sha512\n"); +#endif // XAR_SUPPORT_MD5 + fprintf(stderr, "\t Default: sha1\n"); + fprintf(stderr, "\t--dump-toc= Has xar dump the xml header into the\n"); + fprintf(stderr, "\t specified file.\n"); + fprintf(stderr, "\t--dump-header Prints out the xar binary header information\n"); + fprintf(stderr, "\t--compression Specifies the compression type to use.\n"); + fprintf(stderr, "\t Valid values: none, gzip, bzip2\n"); + fprintf(stderr, "\t Default: gzip\n"); + fprintf(stderr, "\t--list-subdocs List the subdocuments in the xml header\n"); + fprintf(stderr, "\t--extract-subdoc=name Extracts the specified subdocument\n"); + fprintf(stderr, "\t to a document in cwd named .xml\n"); + fprintf(stderr, "\t--exclude POSIX regular expression of files to \n"); + fprintf(stderr, "\t ignore while archiving.\n"); + fprintf(stderr, "\t--rsize Specifies the size of the buffer used\n"); + fprintf(stderr, "\t for read IO operations in bytes.\n"); + fprintf(stderr, "\t--coalesce-heap When archived files are identical, only store one copy\n"); + fprintf(stderr, "\t This option creates an archive which\n"); + fprintf(stderr, "\t is not streamable\n"); + fprintf(stderr, "\t--link-same Hardlink identical files\n"); + fprintf(stderr, "\t--no-compress POSIX regular expression of files\n"); + fprintf(stderr, "\t not to archive, but not compress.\n"); + fprintf(stderr, "\t--sig-size n Size (in bytes) of the signature placeholder\n"); + fprintf(stderr, "\t to generate.\n"); + fprintf(stderr, "\t--data-to-sign=file Path where to dump the data to be signed.\n"); + fprintf(stderr, "\t--sig-offset=file Path where to dump the signature's offset\n"); + fprintf(stderr, "\t within the xar.\n"); + fprintf(stderr, "\t--leaf-cert-loc=file Location of the leaf certificate\n"); + fprintf(stderr, "\t--intermediate-cert-loc=file Location of the intermediate certificate\n"); + fprintf(stderr, "\t--root-cert-loc=file Location of the root certificate\n"); + fprintf(stderr, "\t--version Print xar's version number\n"); + + return; +} + +static void print_version() { + printf("xar %s\n", XAR_VERSION); +} + +int main(int argc, char *argv[]) { + char *filename = NULL; + char *sig_path = NULL; + char *cert_path = NULL; + char command = 0, c; + char **args; + const char *tocfile = NULL; + int arglen, i, err; + xar_t x; + int loptind = 0; + int required_dash_f = 0; /* This release requires us to use -f */ + struct lnode *tmp; + long int longtmp; + struct stat stat_struct; + struct option o[] = { + {"toc-cksum", 1, 0, 1}, + {"file-cksum", 1, 0, 22}, // note out-of-order argument number + {"dump-toc", 1, 0, 'd'}, + {"compression", 1, 0, 2}, + {"list-subdocs", 0, 0, 3}, + {"help", 0, 0, 'h'}, + {"version", 0, 0, 4}, + {"dump-header", 0, 0, 5}, + {"extract-subdoc", 1, 0, 6}, + {"exclude", 1, 0, 7}, + {"rsize", 1, 0, 8}, + {"coalesce-heap", 0, 0, 9}, + {"link-same", 0, 0, 10}, + {"no-compress", 1, 0, 11}, + {"sig-size", 1, 0, 12}, + {"data-to-sign", 1, 0, 13}, + {"sig-offset", 1, 0, 14}, + {"leaf-cert-loc", 1, 0, 15}, + {"intermediate-cert-loc", 1, 0, 16}, + {"extract-data-to-sign", 0, 0, 17}, + {"sign", 0, 0, 18}, + {"replace-sign", 0, 0, 19}, + {"inject-sig", 1, 0, 20}, + {"extract-certs", 1, 0, 21}, + {"root-cert-loc", 1, 0, 23}, + { 0, 0, 0, 0} + }; + + if( argc < 2 ) { + usage(argv[0]); + exit(1); + } + + while( (c = getopt_long(argc, argv, "xcvtf:hpPln:s:d:v", o, &loptind)) != -1 ) { + switch(c) { + case 1 : if( !optarg ) { + usage(argv[0]); + exit(1); + } + if( (strcmp(optarg, XAR_OPT_VAL_NONE) != 0) && + (strcmp(optarg, XAR_OPT_VAL_SHA1) != 0) && + (strcmp(optarg, XAR_OPT_VAL_SHA256) != 0) && + (strcmp(optarg, XAR_OPT_VAL_SHA512) != 0) && + (strcmp(optarg, XAR_OPT_VAL_MD5) != 0) ) { + usage(argv[0]); + exit(1); + } + Toccksum = optarg; + break; + case 22: if( !optarg ) { + usage(argv[0]); + exit(1); + } + if( (strcmp(optarg, XAR_OPT_VAL_NONE) != 0) && + (strcmp(optarg, XAR_OPT_VAL_SHA1) != 0) && + (strcmp(optarg, XAR_OPT_VAL_SHA256) != 0) && + (strcmp(optarg, XAR_OPT_VAL_SHA512) != 0) && + (strcmp(optarg, XAR_OPT_VAL_MD5) != 0) ) { + usage(argv[0]); + exit(1); + } + Filecksum = optarg; + break; + case 2 : if( !optarg ) { + usage(argv[0]); + exit(1); + } + if( (strcmp(optarg, XAR_OPT_VAL_NONE) != 0) && + (strcmp(optarg, XAR_OPT_VAL_GZIP) != 0) && + (strcmp(optarg, XAR_OPT_VAL_BZIP) != 0) ) { + usage(argv[0]); + exit(1); + } + Compression = optarg; + break; + case 3 : if( command && (command != 3) ) { + fprintf(stderr, "Conflicting commands specified\n"); + exit(1); + } + command = 3; + break; + case 4 : print_version(); + exit(0); + case 'd': + if( !optarg ) { + usage(argv[0]); + exit(1); + } + tocfile = optarg; + command = 'd'; + break; + case 5 : command = 5; + break; + case 6 : + SubdocName = optarg; + asprintf(&Subdoc, "%s.xml", SubdocName); + if( !command ) + command = 6; + break; + case 7 : + tmp = malloc(sizeof(struct lnode)); + tmp->str = optarg; + tmp->next = NULL; + err = regcomp(&tmp->reg, tmp->str, REG_NOSUB); + if( err ) { + char errstr[1024]; + regerror(err, &tmp->reg, errstr, sizeof(errstr)); + printf("Error with regular expression %s: %s\n", tmp->str, errstr); + exit(1); + } + if( Exclude == NULL ) { + Exclude = tmp; + Exclude_Tail = tmp; + } else { + Exclude_Tail->next = tmp; + Exclude_Tail = tmp; + } + break; + case 8 : + if ( !optarg ) { + usage(argv[0]); + exit(1); + } + longtmp = strtol(optarg, NULL, 10); + if( (((longtmp == LONG_MIN) || (longtmp == LONG_MAX)) && (errno == ERANGE)) || (longtmp < 1) ) { + fprintf(stderr, "Invalid rsize value: %s\n", optarg); + exit(5); + } + Rsize = optarg; + break; + case 9 : Coalesce = 1; break; + case 10 : LinkSame = 1; break; + case 11 : + tmp = malloc(sizeof(struct lnode)); + tmp->str = optarg; + tmp->next = NULL; + err = regcomp(&tmp->reg, tmp->str, REG_NOSUB); + if( err ) { + char errstr[1024]; + regerror(err, &tmp->reg, errstr, sizeof(errstr)); + printf("Error with regular expression %s: %s\n", tmp->str, errstr); + exit(1); + } + if( NoCompress == NULL ) { + NoCompress = tmp; + NoCompress_Tail = tmp; + } else { + NoCompress_Tail->next = tmp; + NoCompress_Tail = tmp; + } + break; + case 12 : + if( !optarg ) { + usage(argv[0]); + exit(1); + } + SigSize = strtol(optarg, (char **)NULL, 10); + break; + case 13 : + if( !optarg ) { + usage(argv[0]); + exit(1); + } + DataToSignDumpPath = optarg; + break; + case 14 : + if( !optarg ) { + usage(argv[0]); + exit(1); + } + SigOffsetDumpPath = optarg; + break; + case 15 : + if( !optarg ) { + usage(argv[0]); + exit(1); + } + LeafCertPath = optarg; + break; + case 16 : + if( !optarg ) { + usage(argv[0]); + exit(1); + } + IntermediateCertPath = optarg; + break; + case 17 : // extract-data-to-sign + command = 'e'; + break; + case 18 : // sign + DoSign = 1; + break; + case 19 : // replace-sign + command = 'r'; + break; + case 20 : // inject signature + if( !optarg ) { + usage(argv[0]); + exit(1); + } + sig_path = optarg; + command = 'i'; + break; + case 21 : // extract-certs + if( !optarg ) { + usage(argv[0]); + exit(1); + } + cert_path = optarg; + stat(cert_path, &stat_struct); + if (!(stat_struct.st_mode & S_IFDIR)) { + usage(argv[0]); + fprintf(stderr, "%s is not a directory.\n", cert_path); + exit(1); + } + command = 'j'; + break; + case 23 : + if( !optarg ) { + usage(argv[0]); + exit(1); + } + RootCertPath = optarg; + break; + case 'c': + case 'x': + case 't': + if( command && (command != 's') ) { + usage(argv[0]); + fprintf(stderr, "Conflicting command flags: %c and %c specified\n", c, command); + exit(1); + } + if( c == 't' ) + Verbose++; + command = c; + break; + case 'f': + required_dash_f = 1; + filename = optarg; + break; + case 'p': + Perms = SYMBOLIC; + break; + case 'P': + Perms = NUMERIC; + break; + case 'l': + Local = 1; + break; + case 'n': + SubdocName = optarg; + break; + case 's': + Subdoc = optarg; + if( !command ) + command = 's'; + break; + case 'v': + Verbose++; + break; + case 'h': + default: + usage(argv[0]); + exit(1); + } + } + + if (! required_dash_f) { + usage(argv[0]); + fprintf(stderr, "\n -f option is REQUIRED\n"); + exit(1); + } + + // extract-data-to-sign + if ( (command == 'e') && ((!filename) || (!DataToSignDumpPath) || (!SigOffsetDumpPath)) ) { + usage(argv[0]); + exit(1); + } + + if ( DoSign ) { // XXX: should we require RootCertPath as well? + if ( ( !SigSize || !LeafCertPath || !IntermediateCertPath ) + || ((command != 'c') && (!filename)) ) { + usage(argv[0]); + exit(1); + } + if (!command) + command = 'n'; + } + + if (command == 'r') { + /*if ( !SigSize || !LeafCertPath || !IntermediateCertPath || !filename) { + usage(argv[0]); + exit(1); + } + xar_t x = xar_open(filename, READ); + if ( x == NULL ) { + fprintf(stderr, "Could not open archive %s!\n", filename); + exit(1); + } + xar_signature_t sig = xar_signature_first(x); + if ( !sig ) { + fprintf(stderr, "No signature found to replace.\n"); + exit(E_NOSIG); + } + xar_close(x);*/ + } + + if ((command == 'i') && ((!filename) || (!sig_path))) { + usage(argv[0]); + exit(1); + } + + if ((command == 'j') && (!filename)) { + usage(argv[0]); + exit(1); + } + + switch(command) { + case 5 : + return dump_header(filename); + case 3 : + return list_subdocs(filename); + case 'c': + if( optind == argc ) { + usage(argv[0]); + fprintf(stderr, "No files to operate on.\n"); + exit(1); + } + arglen = argc - optind; + args = malloc(sizeof(char*) * (arglen+1)); + memset(args, 0, sizeof(char*) * (arglen+1)); + for( i = 0; i < arglen; i++ ) + args[i] = strdup(argv[optind + i]); + + return archive(filename, arglen, args); + case 'd': + if( !tocfile ) { + usage(argv[0]); + exit(1); + } + return dumptoc(filename, tocfile); + case 'x': + arglen = argc - optind; + args = malloc(sizeof(char*) * (arglen+1)); + for( i = 0; i < arglen; i++ ) + args[i] = strdup(argv[optind + i]); + args[i] = NULL; + return extract(filename, arglen, args); + case 't': + arglen = argc - optind; + args = malloc(sizeof(char*) * (arglen+1)); + for( i = 0; i < arglen; i++ ) + args[i] = strdup(argv[optind + i]); + return list(filename, arglen, args); + case 6 : + case 's': + x = xar_open(filename, READ); + if( !x ) { + fprintf(stderr, "Error opening xar archive: %s\n", filename); + exit(1); + } + xar_register_errhandler(x, err_callback, NULL); + extract_subdoc(x, SubdocName); + xar_close(x); + exit(Err); + break; + case 'e': + extract_data_to_sign(filename); + exit(Err); + case 'r': + replace_sign(filename); + exit(Err); + case 'i': + inject_signature(filename, sig_path); + exit(Err); + case 'n': + belated_sign(filename); + exit(Err); + case 'j': + extract_certs(filename, cert_path); + exit(Err); + default: + usage(argv[0]); + fprintf(stderr, "Unrecognized command.\n"); + exit(1); + } + + /* unreached */ + exit(0); +}