diff -urN xar.hash/include/xar.h.in xar.final/include/xar.h.in --- xar.hash/include/xar.h.in 2006-03-17 13:36:32.000000000 -0800 +++ xar.final/include/xar.h.in 2006-03-17 10:35:14.000000000 -0800 @@ -101,8 +101,20 @@ xar_t xar_open(const char *file, int32_t flags); int xar_close(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_verify(xar_t x, xar_file_t f); + + 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); @@ -148,6 +160,7 @@ int32_t xar_err_callback(xar_t x, int32_t sev, int32_t err); char *xar_get_path(xar_file_t f); +off_t xar_get_heap_offset(xar_t x); uint64_t xar_ntoh64(uint64_t num); #endif /* _XAR_H_ */ diff -urN xar.hash/lib/archive.c xar.final/lib/archive.c --- xar.hash/lib/archive.c 2006-03-17 11:25:05.000000000 -0800 +++ xar.final/lib/archive.c 2006-03-17 10:35:14.000000000 -0800 @@ -217,6 +217,7 @@ 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); } 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);