1diff -urN xar.hash/include/xar.h.in xar.final/include/xar.h.in 2--- xar.hash/include/xar.h.in 2006-03-17 13:36:32.000000000 -0800 3+++ xar.final/include/xar.h.in 2006-03-17 10:35:14.000000000 -0800 4@@ -101,8 +101,20 @@ 5 xar_t xar_open(const char *file, int32_t flags); 6 int xar_close(xar_t x); 7 xar_file_t xar_add(xar_t x, const char *path); 8+ 9+xar_file_t xar_add_frombuffer(xar_t x, xar_file_t parent, const char *name, char *buffer, size_t length); 10+xar_file_t xar_add_folder(xar_t x, xar_file_t f, const char *name, struct stat *info); 11+xar_file_t xar_add_frompath(xar_t x, xar_file_t parent, const char *name, const char *realpath); 12+ 13+xar_file_t xar_add_from_archive(xar_t x, xar_file_t parent, const char *name, xar_t sourcearchive, xar_file_t sourcefile); 14+ 15 int32_t xar_extract(xar_t x, xar_file_t f); 16 int32_t xar_extract_tofile(xar_t x, xar_file_t f, const char *path); 17+int32_t xar_extract_tobuffer(xar_t x, xar_file_t f, char **buffer); 18+ 19+int32_t xar_verify(xar_t x, xar_file_t f); 20+ 21+ 22 const char *xar_opt_get(xar_t x, const char *option); 23 int32_t xar_opt_set(xar_t x, const char *option, const char *value); 24 25@@ -148,6 +160,7 @@ 26 int32_t xar_err_callback(xar_t x, int32_t sev, int32_t err); 27 28 char *xar_get_path(xar_file_t f); 29+off_t xar_get_heap_offset(xar_t x); 30 uint64_t xar_ntoh64(uint64_t num); 31 32 #endif /* _XAR_H_ */ 33diff -urN xar.hash/lib/archive.c xar.final/lib/archive.c 34--- xar.hash/lib/archive.c 2006-03-17 11:25:05.000000000 -0800 35+++ xar.final/lib/archive.c 2006-03-17 10:35:14.000000000 -0800 36@@ -217,6 +217,7 @@ 37 XAR(ret)->heap_len += 20; 38 39 xar_opt_set(ret, XAR_OPT_COMPRESSION, XAR_OPT_VAL_GZIP); 40+ xar_opt_set(ret, XAR_OPT_FILECKSUM, XAR_OPT_VAL_SHA1); 41 } else { 42 unsigned char toccksum[EVP_MAX_MD_SIZE]; 43 unsigned char cval[EVP_MAX_MD_SIZE]; 44@@ -455,6 +456,7 @@ 45 46 if( XAR(x)->docksum ) { 47 unsigned int l = r; 48+ 49 memset(chkstr, 0, sizeof(chkstr)); 50 EVP_DigestFinal(&XAR(x)->toc_ctx, chkstr, &l); 51 r = l; 52@@ -588,19 +590,25 @@ 53 * x: archive the file should belong to 54 * f: parent node, possibly NULL 55 * name: name of the node to add 56+ * realpath: real path to item, this is used if the item being archived is to be located at a different location in the tree 57+ * then it is on the real filesystem. 58 * Returns: newly allocated and populated node 59 * Summary: helper function which adds a child of f and populates 60 * its properties. If f is NULL, the node will be added as a top 61 * level node of the archive, x. 62 */ 63-static xar_file_t xar_add_node(xar_t x, xar_file_t f, const char *name, const char *prefix, int srcpath) { 64+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) { 65 xar_file_t ret; 66 const char *path; 67 char *tmp; 68 char idstr[32]; 69 70 if( !f ) { 71- asprintf(&tmp, "%s%s%s", XAR(x)->path_prefix, prefix, name); 72+ if( realpath ) 73+ asprintf(&tmp, "%s", realpath); 74+ else 75+ asprintf(&tmp, "%s%s%s", XAR(x)->path_prefix, prefix, name); 76+ 77 if( lstat(tmp, &XAR(x)->sbcache) != 0 ) { 78 free(tmp); 79 return NULL; 80@@ -631,7 +639,12 @@ 81 } 82 83 } 84- asprintf(&tmp, "%s/%s%s", path, prefix, name); 85+ 86+ if( realpath ){ 87+ asprintf(&tmp, "%s", realpath); 88+ }else 89+ asprintf(&tmp, "%s/%s%s", path, prefix, name); 90+ 91 if( lstat(tmp, &XAR(x)->sbcache) != 0 ) { 92 free(tmp); 93 return NULL; 94@@ -648,7 +661,7 @@ 95 96 xar_prop_set(ret, "name", name); 97 98- if( xar_arcmod_archive(x, ret, XAR_FILE(ret)->fspath) < 0 ) { 99+ if( xar_arcmod_archive(x, ret, XAR_FILE(ret)->fspath, NULL, 0) < 0 ) { 100 xar_file_t i; 101 if( f ) { 102 for( i = XAR_FILE(f)->children; i && (XAR_FILE(i)->next != ret); i = XAR_FILE(i)->next ); 103@@ -736,9 +749,9 @@ 104 105 /* tmp3 was not found in children of start, so we add it */ 106 if( tmp2 ) { 107- ret = xar_add_node(x, f, tmp3, prefix, 1); 108+ ret = xar_add_node(x, f, tmp3, prefix, NULL, 1); 109 } else { 110- ret = xar_add_node(x, f, tmp3, prefix, 0); 111+ ret = xar_add_node(x, f, tmp3, prefix, NULL, 0); 112 } 113 114 if( !ret ) { 115@@ -783,18 +796,209 @@ 116 return xar_add_r(x, NULL, path, ""); 117 } 118 119+/* xar_add_frombuffer 120+* x: archive to add the file to 121+* parent: parent node, possibly NULL 122+* name: name of file 123+* buffer: buffer for file contents 124+* length: length of buffer 125+* Returns: allocated an populated xar_file_t representing the 126+* specified file. 127+* Summary: Use this to add chunks of named data to a xar without 128+* using the filesystem. 129+*/ 130+ 131+xar_file_t xar_add_frombuffer(xar_t x, xar_file_t parent, const char *name, char *buffer, size_t length) { 132+ xar_file_t ret; 133+ char *tmp; 134+ char idstr[32]; 135+ 136+ if( !parent ) { 137+ ret = xar_file_new(NULL); 138+ if( !ret ) 139+ return NULL; 140+ memset(idstr, 0, sizeof(idstr)); 141+ snprintf(idstr, sizeof(idstr)-1, "%"PRIu64, ++XAR(x)->last_fileid); 142+ xar_attr_set(ret, NULL, "id", idstr); 143+ XAR_FILE(ret)->parent = NULL; 144+ if( XAR(x)->files == NULL ) 145+ XAR(x)->files = ret; 146+ else { 147+ XAR_FILE(ret)->next = XAR(x)->files; 148+ XAR(x)->files = ret; 149+ } 150+ } else { 151+ ret = xar_file_new(parent); 152+ if( !ret ) 153+ return NULL; 154+ memset(idstr, 0, sizeof(idstr)); 155+ snprintf(idstr, sizeof(idstr)-1, "%"PRIu64, ++XAR(x)->last_fileid); 156+ xar_attr_set(ret, NULL, "id", idstr); 157+ XAR_FILE(ret)->fspath = tmp; 158+ } 159+ 160+ xar_prop_set(ret, "name", name); 161+ 162+ //int32_t xar_arcmod_archive(xar_t x, xar_file_t f, const char *file, const char *buffer, size_t len) 163+ if( xar_arcmod_archive(x, ret, NULL , buffer , length) < 0 ) { 164+ xar_file_t i; 165+ if( parent ) { 166+ for( i = XAR_FILE(parent)->children; i && (XAR_FILE(i)->next != ret); i = XAR_FILE(i)->next ); 167+ } else { 168+ for( i = XAR(x)->files; i && (XAR_FILE(i)->next != ret); i = XAR_FILE(i)->next ); 169+ } 170+ if( i ) 171+ XAR_FILE(i)->next = XAR_FILE(ret)->next; 172+ xar_file_free(ret); 173+ return NULL; 174+ } 175+ 176+ return ret; 177+} 178+ 179+xar_file_t xar_add_folder(xar_t x, xar_file_t f, const char *name, struct stat *info) 180+{ 181+ xar_file_t ret; 182+ char idstr[32]; 183+ 184+ if( info ) 185+ memcpy(&XAR(x)->sbcache,info,sizeof(struct stat)); 186+ 187+ ret = xar_file_new(f); 188+ if( !ret ) 189+ return NULL; 190+ 191+ memset(idstr, 0, sizeof(idstr)); 192+ snprintf(idstr, sizeof(idstr)-1, "%"PRIu64, ++XAR(x)->last_fileid); 193+ xar_attr_set(ret, NULL, "id", idstr); 194+ XAR_FILE(ret)->fspath = NULL; 195+ 196+ if( !f ) { 197+ XAR_FILE(ret)->parent = NULL; 198+ 199+ if( XAR(x)->files == NULL ) 200+ XAR(x)->files = ret; 201+ else { 202+ XAR_FILE(ret)->next = XAR(x)->files; 203+ XAR(x)->files = ret; 204+ } 205+ } 206+ 207+ xar_prop_set(ret, "name", name); 208+ 209+ if( xar_arcmod_archive(x, ret, XAR_FILE(ret)->fspath, NULL, 0) < 0 ) { 210+ xar_file_t i; 211+ if( f ) { 212+ for( i = XAR_FILE(f)->children; i && (XAR_FILE(i)->next != ret); i = XAR_FILE(i)->next ); 213+ } else { 214+ for( i = XAR(x)->files; i && (XAR_FILE(i)->next != ret); i = XAR_FILE(i)->next ); 215+ } 216+ if( i ) 217+ XAR_FILE(i)->next = XAR_FILE(ret)->next; 218+ xar_file_free(ret); 219+ return NULL; 220+ } 221+ 222+ return ret; 223+} 224+ 225+xar_file_t xar_add_frompath(xar_t x, xar_file_t parent, const char *name, const char *realpath) 226+{ 227+ return xar_add_node(x, parent, name , "" , realpath, 1); 228+} 229+ 230+xar_file_t xar_add_from_archive(xar_t x, xar_file_t parent, const char *name, xar_t sourcearchive, xar_file_t sourcefile) 231+{ 232+ xar_file_t ret; 233+ char idstr[32]; 234+ 235+ ret = xar_file_replicate(sourcefile, parent); 236+ 237+ if( !ret ) 238+ return NULL; 239+ 240+ memset(idstr, 0, sizeof(idstr)); 241+ snprintf(idstr, sizeof(idstr)-1, "%"PRIu64, ++XAR(x)->last_fileid); 242+ xar_attr_set(ret, NULL, "id", idstr); 243+ XAR_FILE(ret)->fspath = NULL; 244+ 245+ if( !parent ) { 246+ XAR_FILE(ret)->parent = NULL; 247+ 248+ if( XAR(x)->files == NULL ) 249+ XAR(x)->files = ret; 250+ else { 251+ XAR_FILE(ret)->next = XAR(x)->files; 252+ XAR(x)->files = ret; 253+ } 254+ } 255+ 256+ xar_prop_set(ret, "name", name); 257+ 258+ /* iterate through all the properties, see if any of them have an offset */ 259+ xar_iter_t iter = xar_iter_new(); 260+ const char *attr = xar_prop_first(ret , iter); 261+ char *tmpstr = NULL; 262+ 263+ do{ 264+ asprintf(&tmpstr, "%s/offset", attr); 265+ if(0 == xar_prop_get(ret, tmpstr, NULL) ){ 266+ if( 0 != xar_attrcopy_from_heap_to_heap(sourcearchive, sourcefile, attr, x, ret)){ 267+ xar_file_free(ret); 268+ ret = NULL; 269+ break; 270+ } 271+ } 272+ free(tmpstr); 273+ 274+ }while( (attr = xar_prop_next(iter)) ); 275+ 276+ xar_iter_free(iter); 277+ 278+ return ret; 279+} 280+ 281 /* xar_extract_tofile 282- * x: archive to extract from 283- * f: file associated with x 284- * Returns 0 on success, -1 on failure 285- * Summary: This actually does the file extraction. 286- * No traversal is performed, it is assumed all directory paths 287- * leading up to f already exist. 288- */ 289+* x: archive to extract from 290+* f: file associated with x 291+* Returns 0 on success, -1 on failure 292+* Summary: This actually does the file extraction. 293+* No traversal is performed, it is assumed all directory paths 294+* leading up to f already exist. 295+*/ 296 int32_t xar_extract_tofile(xar_t x, xar_file_t f, const char *path) { 297- return xar_arcmod_extract(x, f, path); 298+ return xar_arcmod_extract(x, f, path,NULL, 0); 299 } 300 301+ 302+/* xar_extract_tobuffer 303+* x: archive to extract from 304+* buffer: buffer to extract to 305+* Returns 0 on success, -1 on failure. 306+* Summary: This is the entry point for extraction to a buffer. 307+* On success, a buffer is allocated with the contents of the file 308+* specified. The caller is responsible for freeing the returend buffer. 309+* Example: xar_extract_tobuffer(x, "foo/bar/blah",&buffer) 310+*/ 311+int32_t xar_extract_tobuffer(xar_t x, xar_file_t f, char **buffer) { 312+ size_t size; 313+ const char *sizestring = NULL; 314+ 315+ if(0 != xar_prop_get(f,"data/size",&sizestring)){ 316+ return -1; 317+ } 318+ 319+ size = strtoull(sizestring, (char **)NULL, 10); 320+ *buffer = malloc(size); 321+ 322+ if(!(*buffer)){ 323+ return -1; 324+ } 325+ 326+ return xar_arcmod_extract(x,f,NULL,*buffer,size); 327+} 328+ 329+ 330 /* xar_extract 331 * x: archive to extract from 332 * path: path to file to extract 333@@ -828,6 +1032,18 @@ 334 return xar_extract_tofile(x, f, XAR_FILE(f)->fspath); 335 } 336 337+/* xar_extract 338+* x: archive to extract from 339+* f: file to verify 340+* Returns 0 on success, -1 on failure. 341+* Summary: This function allows for verification of 342+* an entry without extraction. If there is no checksum 343+* the verification will pass. 344+*/ 345+int32_t xar_verify(xar_t x, xar_file_t f) { 346+ return xar_arcmod_verify(x,f); 347+} 348+ 349 /* read_callback 350 * context: context passed through from the reader 351 * buffer: buffer to read into 352diff -urN xar.hash/lib/archive.h xar.final/lib/archive.h 353--- xar.hash/lib/archive.h 2006-03-17 11:19:16.000000000 -0800 354+++ xar.final/lib/archive.h 2006-03-17 10:35:14.000000000 -0800 355@@ -55,28 +55,28 @@ 356 const char *ns; 357 const char *filler1; 358 const char *filler2; 359- xar_file_t files; /* file forest */ 360- const char *filename; /* name of the archive we are operating on */ 361- char *dirname; /* directory of the archive, used in creation */ 362- int fd; /* open file descriptor for the archive */ 363- int heap_fd; /* fd for tmp heap archive, used in creation */ 364- off_t heap_offset; /* current offset within the heap */ 365- off_t heap_len; /* current length of the heap */ 366- xar_header_t header; /* header of the xar archive */ 367- void *readbuf; /* buffer for reading/writing compressed toc */ 368- size_t readbuf_len; /* length of readbuf */ 369- size_t offset; /* offset into readbuf for keeping track 370- * between callbacks. */ 371- size_t toc_count; /* current bytes read of the toc */ 372- z_stream zs; /* gz state for compressing/decompressing toc */ 373- char *path_prefix; /* used for distinguishing absolute paths */ 374- err_handler ercallback; /* callback for errors/warnings */ 375- struct errctx errctx; /* error callback context */ 376- xar_subdoc_t subdocs; /* linked list of subdocs */ 377- uint64_t last_fileid; /* unique fileid's in the archive */ 378- xmlHashTablePtr ino_hash;/* Hash for looking up hardlinked files (add)*/ 379- xmlHashTablePtr link_hash;/* Hash for looking up hardlinked files (extract)*/ 380- xmlHashTablePtr csum_hash;/* Hash for looking up checksums of files */ 381+ xar_file_t files; /* file forest */ 382+ const char *filename; /* name of the archive we are operating on */ 383+ char *dirname; /* directory of the archive, used in creation */ 384+ int fd; /* open file descriptor for the archive */ 385+ int heap_fd; /* fd for tmp heap archive, used in creation */ 386+ off_t heap_offset; /* current offset within the heap */ 387+ off_t heap_len; /* current length of the heap */ 388+ xar_header_t header; /* header of the xar archive */ 389+ void *readbuf; /* buffer for reading/writing compressed toc */ 390+ size_t readbuf_len; /* length of readbuf */ 391+ size_t offset; /* offset into readbuf for keeping track 392+ * between callbacks. */ 393+ size_t toc_count; /* current bytes read of the toc */ 394+ z_stream zs; /* gz state for compressing/decompressing toc */ 395+ char *path_prefix; /* used for distinguishing absolute paths */ 396+ err_handler ercallback; /* callback for errors/warnings */ 397+ struct errctx errctx; /* error callback context */ 398+ xar_subdoc_t subdocs; /* linked list of subdocs */ 399+ uint64_t last_fileid; /* unique fileid's in the archive */ 400+ xmlHashTablePtr ino_hash; /* Hash for looking up hardlinked files (add)*/ 401+ xmlHashTablePtr link_hash; /* Hash for looking up hardlinked files (extract)*/ 402+ xmlHashTablePtr csum_hash; /* Hash for looking up checksums of files */ 403 EVP_MD_CTX toc_ctx; 404 int docksum; 405 int skipwarn; 406diff -urN xar.hash/lib/arcmod.c xar.final/lib/arcmod.c 407--- xar.hash/lib/arcmod.c 2006-03-17 11:19:16.000000000 -0800 408+++ xar.final/lib/arcmod.c 2006-03-17 10:35:14.000000000 -0800 409@@ -57,12 +57,12 @@ 410 * Returns: 0 on success 411 * Summary: This is the entry point to actual file archival. 412 */ 413-int32_t xar_arcmod_archive(xar_t x, xar_file_t f, const char *file) { 414+int32_t xar_arcmod_archive(xar_t x, xar_file_t f, const char *file, const char *buffer, size_t len) { 415 int i; 416 int32_t ret; 417 for(i = 0; i < (sizeof(xar_arcmods)/sizeof(struct arcmod)); i++) { 418 if( xar_arcmods[i].archive ) { 419- ret = xar_arcmods[i].archive(x, f, file); 420+ ret = xar_arcmods[i].archive(x, f, file, buffer, len); 421 if( ret < 0 ) { 422 return ret; 423 } 424@@ -81,12 +81,12 @@ 425 * Returns: 0 on success 426 * Summary: This is the entry point to actual file archival. 427 */ 428-int32_t xar_arcmod_extract(xar_t x, xar_file_t f, const char *file) { 429+int32_t xar_arcmod_extract(xar_t x, xar_file_t f, const char *file, char *buffer, size_t len) { 430 int i; 431 int32_t ret; 432 for(i = 0; i < (sizeof(xar_arcmods)/sizeof(struct arcmod)); i++) { 433 if( xar_arcmods[i].extract ) { 434- ret = xar_arcmods[i].extract(x, f, file); 435+ ret = xar_arcmods[i].extract(x, f, file, buffer, len); 436 if( ret < 0 ) { 437 return ret; 438 } 439@@ -97,3 +97,8 @@ 440 } 441 return 0; 442 } 443+ 444+ 445+int32_t xar_arcmod_verify(xar_t x, xar_file_t f){ 446+ return xar_data_verify(x,f); 447+} 448diff -urN xar.hash/lib/arcmod.h xar.final/lib/arcmod.h 449--- xar.hash/lib/arcmod.h 2006-03-17 11:19:16.000000000 -0800 450+++ xar.final/lib/arcmod.h 2006-03-17 10:35:14.000000000 -0800 451@@ -37,15 +37,17 @@ 452 #include "filetree.h" 453 454 455-typedef int32_t (*arcmod_archive)(xar_t x, xar_file_t f, const char* file); 456-typedef int32_t (*arcmod_extract)(xar_t x, xar_file_t f, const char* file); 457+typedef int32_t (*arcmod_archive)(xar_t x, xar_file_t f, const char* file, const char *buffer, size_t len); 458+typedef int32_t (*arcmod_extract)(xar_t x, xar_file_t f, const char* file, char *buffer, size_t len); 459 460 struct arcmod { 461 arcmod_archive archive; 462 arcmod_extract extract; 463 }; 464 465-int32_t xar_arcmod_archive(xar_t x, xar_file_t f, const char *file); 466-int32_t xar_arcmod_extract(xar_t x, xar_file_t f, const char *file); 467+int32_t xar_arcmod_archive(xar_t x, xar_file_t f, const char *file, const char *buffer, size_t len); 468+int32_t xar_arcmod_extract(xar_t x, xar_file_t f, const char *file, char *buffer, size_t len); 469+ 470+int32_t xar_arcmod_verify(xar_t x, xar_file_t f); 471 472 #endif /* _XAR_ARCMOD_H_ */ 473diff -urN xar.hash/lib/darwinattr.c xar.final/lib/darwinattr.c 474--- xar.hash/lib/darwinattr.c 2006-03-17 11:26:55.000000000 -0800 475+++ xar.final/lib/darwinattr.c 2006-03-17 10:35:14.000000000 -0800 476@@ -554,19 +554,21 @@ 477 478 DARWINATTR_CONTEXT(context)->fd = 0; 479 480- xar_set_perm(x, f, underbarname ); 481+ xar_set_perm(x, f, underbarname, NULL, 0 ); 482 483 return 0; 484 } 485 486 487-int32_t xar_darwinattr_archive(xar_t x, xar_file_t f, const char* file) 488+int32_t xar_darwinattr_archive(xar_t x, xar_file_t f, const char* file, const char *buffer, size_t len) 489 { 490 struct _darwinattr_context context; 491 492 memset(&context,0,sizeof(struct _darwinattr_context)); 493 494 #if defined(__APPLE__) 495+ if( len ) 496+ return 0; 497 #if defined(HAVE_GETXATTR) 498 if( ea_archive(x, f, file, (void *)&context) == 0 ) 499 return 0; 500@@ -578,13 +580,15 @@ 501 return 0; 502 } 503 504-int32_t xar_darwinattr_extract(xar_t x, xar_file_t f, const char* file) 505+int32_t xar_darwinattr_extract(xar_t x, xar_file_t f, const char* file, char *buffer, size_t len) 506 { 507 struct _darwinattr_context context; 508 509 memset(&context,0,sizeof(struct _darwinattr_context)); 510 511 #if defined(__APPLE__) 512+ if( len ) 513+ return 0; 514 #if defined(HAVE_GETXATTR) 515 if( ea_extract(x, f, file, (void *)&context) == 0 ) 516 return 0; 517diff -urN xar.hash/lib/darwinattr.h xar.final/lib/darwinattr.h 518--- xar.hash/lib/darwinattr.h 2006-03-17 11:19:16.000000000 -0800 519+++ xar.final/lib/darwinattr.h 2006-03-17 10:35:14.000000000 -0800 520@@ -6,6 +6,6 @@ 521 #ifndef _XAR_DARWINATTR_H_ 522 #define _XAR_DARWINATTR_H_ 523 int32_t xar_underbar_check(xar_t x, xar_file_t f, const char* file); 524-int32_t xar_darwinattr_archive(xar_t x, xar_file_t f, const char* file); 525-int32_t xar_darwinattr_extract(xar_t x, xar_file_t f, const char* file); 526+int32_t xar_darwinattr_archive(xar_t x, xar_file_t f, const char* file, const char *buffer, size_t len); 527+int32_t xar_darwinattr_extract(xar_t x, xar_file_t f, const char* file, char *buffer, size_t len); 528 #endif /* _XAR_DARWINATTR_H_ */ 529diff -urN xar.hash/lib/data.c xar.final/lib/data.c 530--- xar.hash/lib/data.c 2006-03-17 11:19:16.000000000 -0800 531+++ xar.final/lib/data.c 2006-03-17 10:35:14.000000000 -0800 532@@ -99,7 +99,7 @@ 533 * This is the arcmod archival entry point for archiving the file's 534 * data into the heap file. 535 */ 536-int32_t xar_data_archive(xar_t x, xar_file_t f, const char *file) { 537+int32_t xar_data_archive(xar_t x, xar_file_t f, const char *file, const char *buffer, size_t len) { 538 const char *opt; 539 int32_t retval = 0; 540 struct _data_context context; 541@@ -120,14 +120,20 @@ 542 return 0; 543 } 544 545- context.fd = open(file, O_RDONLY); 546- if( context.fd < 0 ) { 547- xar_err_new(x); 548- xar_err_set_file(x, f); 549- xar_err_set_string(x, "io: Could not open file"); 550- xar_err_callback(x, XAR_SEVERITY_NONFATAL, XAR_ERR_ARCHIVE_CREATION); 551- return -1; 552- } 553+ if( 0 == len ){ 554+ context.fd = open(file, O_RDONLY); 555+ if( context.fd < 0 ) { 556+ xar_err_new(x); 557+ xar_err_set_file(x, f); 558+ xar_err_set_string(x, "io: Could not open file"); 559+ xar_err_callback(x, XAR_SEVERITY_NONFATAL, XAR_ERR_ARCHIVE_CREATION); 560+ return -1; 561+ } 562+ }else{ 563+ context.buffer = (void *)buffer; 564+ context.length = len; 565+ context.offset = 0; 566+ } 567 568 retval = xar_attrcopy_to_heap(x, f, "data", xar_data_read,(void *)(&context)); 569 570@@ -137,7 +143,7 @@ 571 return retval; 572 } 573 574-int32_t xar_data_extract(xar_t x, xar_file_t f, const char *file) { 575+int32_t xar_data_extract(xar_t x, xar_file_t f, const char *file, char *buffer, size_t len) { 576 const char *opt; 577 struct _data_context context; 578 579@@ -158,25 +164,32 @@ 580 return 0; 581 } 582 583- /* mode 600 since other modules may need to operate on the file 584- * prior to the real permissions being set. 585- */ 586+ if ( len ){ 587+ context.length = len; 588+ context.buffer = buffer; 589+ context.offset = 0; 590+ }else{ 591+ /* mode 600 since other modules may need to operate on the file 592+ * prior to the real permissions being set. 593+ */ 594 TRYAGAIN: 595- context.fd = open(file, O_RDWR|O_TRUNC|O_EXLOCK, 0600); 596- if( context.fd < 0 ) { 597- if( errno == ENOENT ) { 598- xar_file_t parent = XAR_FILE(f)->parent; 599- if( parent && (xar_extract(x, parent) == 0) ) 600- goto TRYAGAIN; 601+ context.fd = open(file, O_RDWR|O_TRUNC|O_EXLOCK, 0600); 602+ if( context.fd < 0 ) { 603+ if( errno == ENOENT ) { 604+ xar_file_t parent = XAR_FILE(f)->parent; 605+ if( parent && (xar_extract(x, parent) == 0) ) 606+ goto TRYAGAIN; 607+ } 608+ 609+ xar_err_new(x); 610+ xar_err_set_file(x, f); 611+ xar_err_set_string(x, "io: Could not create file"); 612+ xar_err_callback(x, XAR_SEVERITY_NONFATAL, XAR_ERR_ARCHIVE_EXTRACTION); 613+ return -1; 614 } 615 616- xar_err_new(x); 617- xar_err_set_file(x, f); 618- xar_err_set_string(x, "io: Could not create file"); 619- xar_err_callback(x, XAR_SEVERITY_NONFATAL, XAR_ERR_ARCHIVE_EXTRACTION); 620- return -1; 621 } 622- 623+ 624 xar_attrcopy_from_heap(x, f, "data", xar_data_write, (void *)(&context)); 625 626 if( context.fd > 0 ) 627@@ -185,3 +198,19 @@ 628 return 0; 629 } 630 631+int32_t xar_data_verify(xar_t x, xar_file_t f) 632+{ 633+ const char *opt; 634+ struct _data_context context; 635+ 636+ memset(&context,0,sizeof(struct _data_context)); 637+ 638+ /* Only regular files are copied in and out of the heap here */ 639+ xar_prop_get(f, "type", &opt); 640+ if( !opt ) return 0; 641+ if( strcmp(opt, "directory") == 0 ) { 642+ return 0; 643+ } 644+ 645+ return xar_attrcopy_from_heap(x, f, "data", NULL , (void *)(&context)); 646+} 647diff -urN xar.hash/lib/data.h xar.final/lib/data.h 648--- xar.hash/lib/data.h 2006-03-17 11:19:16.000000000 -0800 649+++ xar.final/lib/data.h 2006-03-17 10:35:14.000000000 -0800 650@@ -5,6 +5,8 @@ 651 */ 652 #ifndef _XAR_DATA_H_ 653 #define _XAR_DATA_H_ 654-int32_t xar_data_archive(xar_t x, xar_file_t f, const char* file); 655-int32_t xar_data_extract(xar_t x, xar_file_t f, const char* file); 656+int32_t xar_data_archive(xar_t x, xar_file_t f, const char* file, const char *buffer, size_t len); 657+int32_t xar_data_extract(xar_t x, xar_file_t f, const char* file, char *buffer, size_t len); 658+ 659+int32_t xar_data_verify(xar_t x, xar_file_t f); 660 #endif /* _XAR_DATA_H_ */ 661diff -urN xar.hash/lib/ext2.c xar.final/lib/ext2.c 662--- xar.hash/lib/ext2.c 2006-03-17 11:19:16.000000000 -0800 663+++ xar.final/lib/ext2.c 2006-03-17 10:35:14.000000000 -0800 664@@ -70,9 +70,14 @@ 665 } 666 #endif 667 668-int xar_ext2attr_archive(xar_t x, xar_file_t f, const char* file) 669+int xar_ext2attr_archive(xar_t x, xar_file_t f, const char* file, const char *buffer, size_t len) 670 { 671 int ret = 0; 672+ 673+ /* if archiving from a buffer, then there is no place to get extattr */ 674+ if ( len ) 675+ return 0; 676+ 677 #if defined(HAVE_EXT2FS_EXT2_FS_H) || defined(HAVE_LINUX_EXT2_FS_H) 678 int fd, flags=0, version; 679 char *vstr; 680@@ -158,8 +163,12 @@ 681 } 682 #endif 683 684-int xar_ext2attr_extract(xar_t x, xar_file_t f, const char* file) 685+int xar_ext2attr_extract(xar_t x, xar_file_t f, const char* file, char *buffer, size_t len) 686 { 687+ /* if extracting to a buffer, then there is no place to write extattr */ 688+ if ( len ) 689+ return 0; 690+ 691 #if defined(HAVE_EXT2FS_EXT2_FS_H) || defined(HAVE_LINUX_EXT2_FS_H) 692 int fd = -1, version, flags = 0; 693 char *tmp; 694diff -urN xar.hash/lib/ext2.h xar.final/lib/ext2.h 695--- xar.hash/lib/ext2.h 2006-03-17 11:19:16.000000000 -0800 696+++ xar.final/lib/ext2.h 2006-03-17 10:35:14.000000000 -0800 697@@ -6,6 +6,6 @@ 698 #ifndef _XAR_EXT2_H_ 699 #define _XAR_EXT2_H_ 700 #define XAR_ATTR_FORK "attribute" 701-int xar_ext2attr_archive(xar_t x, xar_file_t f, const char* file); 702-int xar_ext2attr_extract(xar_t x, xar_file_t f, const char* file); 703+int xar_ext2attr_archive(xar_t x, xar_file_t f, const char* file, const char *buffer, size_t len); 704+int xar_ext2attr_extract(xar_t x, xar_file_t f, const char* file, char *buffer, size_t len); 705 #endif /* _XAR_EXT2_H_ */ 706diff -urN xar.hash/lib/fbsdattr.c xar.final/lib/fbsdattr.c 707--- xar.hash/lib/fbsdattr.c 2006-03-17 11:19:16.000000000 -0800 708+++ xar.final/lib/fbsdattr.c 2006-03-17 10:54:53.000000000 -0800 709@@ -99,7 +99,7 @@ 710 } 711 #endif 712 713-int32_t xar_fbsdattr_archive(xar_t x, xar_file_t f, const char* file) 714+int32_t xar_fbsdattr_archive(xar_t x, xar_file_t f, const char* file, const char *buffer, size_t len) 715 { 716 #ifdef HAVE_SYS_EXTATTR_H 717 char *buf = NULL; 718@@ -110,6 +110,11 @@ 719 struct _fbsdattr_context context; 720 721 memset(&context,0,sizeof(struct _fbsdattr_context)); 722+ 723+ /* no fbsdattr attributes for data to a buffer */ 724+ if(len){ 725+ return 0; 726+ } 727 728 TRYAGAIN: 729 /* extattr_list_link()'s man page does not define the return 730@@ -218,7 +223,12 @@ 731 struct _fbsdattr_context context; 732 733 memset(&context,0,sizeof(struct _fbsdattr_context)); 734- 735+ 736+ /* no fbsdattr attributes for data to a buffer */ 737+ if(len){ 738+ return 0; 739+ } 740+ 741 statfs(file, &sfs); 742 fsname = sfs.f_fstypename; 743 744diff -urN xar.hash/lib/fbsdattr.h xar.final/lib/fbsdattr.h 745--- xar.hash/lib/fbsdattr.h 2006-03-17 11:19:16.000000000 -0800 746+++ xar.final/lib/fbsdattr.h 2006-03-17 10:35:14.000000000 -0800 747@@ -5,6 +5,6 @@ 748 */ 749 #ifndef _XAR_FBSDATTR_H_ 750 #define _XAR_FBSDATTR_H_ 751-int32_t xar_fbsdattr_archive(xar_t x, xar_file_t f, const char* file); 752-int32_t xar_fbsdattr_extract(xar_t x, xar_file_t f, const char* file); 753+int32_t xar_fbsdattr_archive(xar_t x, xar_file_t f, const char* file, const char *buffer, size_t len); 754+int32_t xar_fbsdattr_extract(xar_t x, xar_file_t f, const char* file, char *buffer, size_t len); 755 #endif /* _XAR_FBSDATTR_H_ */ 756diff -urN xar.hash/lib/filetree.c xar.final/lib/filetree.c 757--- xar.hash/lib/filetree.c 2006-03-17 11:19:16.000000000 -0800 758+++ xar.final/lib/filetree.c 2006-03-17 10:35:14.000000000 -0800 759@@ -545,6 +545,51 @@ 760 return 0; 761 } 762 763+/* xar_prop_replicate_r 764+* f: file to attach property 765+* p: property (list) to iterate and add 766+* parent: parent property 767+* Summary: Recursivley adds property list (p) to file (f) and parent (parent). 768+*/ 769+ 770+void xar_prop_replicate_r(xar_file_t f, xar_prop_t p, xar_prop_t parent ) 771+{ 772+ xar_prop_t property = p; 773+ 774+ /* look through properties */ 775+ for( property = p; property; property = property->next ){ 776+ xar_prop_t newprop = xar_prop_new( f, parent ); 777+ 778+ /* copy the key value for the property */ 779+ XAR_PROP(newprop)->key = strdup(property->key); 780+ if(property->value) 781+ XAR_PROP(newprop)->value = strdup(property->value); 782+ 783+ /* loop through the attributes and copy them */ 784+ xar_attr_t a = NULL; 785+ xar_attr_t last = NULL; 786+ 787+ /* copy attributes for file */ 788+ for(a = property->attrs; a; a = a->next) { 789+ if( NULL == newprop->attrs ){ 790+ last = xar_attr_new(); 791+ XAR_PROP(newprop)->attrs = last; 792+ }else{ 793+ XAR_ATTR(last)->next = xar_attr_new(); 794+ last = XAR_ATTR(last)->next; 795+ } 796+ 797+ XAR_ATTR(last)->key = strdup(a->key); 798+ if(a->value) 799+ XAR_ATTR(last)->value = strdup(a->value); 800+ } 801+ 802+ /* loop through the children properties and recursively add them */ 803+ xar_prop_replicate_r(f, property->children, newprop ); 804+ } 805+ 806+} 807+ 808 /* xar_prop_free 809 * p: property to free 810 * Summary: frees the specified property and all its children. 811@@ -621,6 +666,26 @@ 812 return ret; 813 } 814 815+xar_file_t xar_file_replicate(xar_file_t original, xar_file_t newparent) 816+{ 817+ xar_file_t ret = xar_file_new(newparent); 818+ xar_attr_t a; 819+ 820+ /* copy attributes for file */ 821+ for(a = XAR_FILE(original)->attrs; a; a = XAR_ATTR(a)->next) { 822+ /* skip the id attribute */ 823+ if( 0 == strcmp(a->key, "id" ) ) 824+ continue; 825+ 826+ xar_attr_set(ret, NULL , a->key, a->value ); 827+ } 828+ 829+ /* recursively copy properties */ 830+ xar_prop_replicate_r(ret, XAR_FILE(original)->props, NULL); 831+ 832+ return ret; 833+} 834+ 835 /* xar_file_free 836 * f: file to free 837 * Summary: frees the specified file and all children, 838diff -urN xar.hash/lib/filetree.h xar.final/lib/filetree.h 839--- xar.hash/lib/filetree.h 2006-03-17 11:19:16.000000000 -0800 840+++ xar.final/lib/filetree.h 2006-03-17 10:35:14.000000000 -0800 841@@ -82,6 +82,7 @@ 842 xar_file_t xar_file_unserialize(xar_t x, xar_file_t parent, xmlTextReaderPtr reader); 843 xar_file_t xar_file_find(xar_file_t f, const char *path); 844 xar_file_t xar_file_new(xar_file_t f); 845+xar_file_t xar_file_replicate(xar_file_t original, xar_file_t newparent); 846 void xar_file_free(xar_file_t f); 847 848 void xar_prop_serialize(xar_prop_t p, xmlTextWriterPtr writer); 849diff -urN xar.hash/lib/io.c xar.final/lib/io.c 850--- xar.hash/lib/io.c 2006-03-17 11:20:06.000000000 -0800 851+++ xar.final/lib/io.c 2006-03-17 10:35:14.000000000 -0800 852@@ -415,6 +415,140 @@ 853 return 0; 854 } 855 856+/* xar_attrcopy_from_heap_to_heap 857+* This does a simple copy of the heap data from one head (read-only) to another heap (write only). 858+* This does not set any properties or attributes of the file, so this should not be used alone. 859+*/ 860+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){ 861+ int r, off; 862+ size_t bsize; 863+ int64_t fsize, inc = 0, seekoff, writesize=0; 864+ off_t orig_heap_offset = XAR(xdest)->heap_offset; 865+ void *inbuf; 866+ const char *opt; 867+ char *tmpstr = NULL, *tmpstr2 = NULL; 868+ 869+ opt = xar_opt_get(xsource, "rsize"); 870+ if( !opt ) { 871+ bsize = 4096; 872+ } else { 873+ bsize = strtol(opt, NULL, 0); 874+ if( ((bsize == LONG_MAX) || (bsize == LONG_MIN)) && (errno == ERANGE) ) { 875+ bsize = 4096; 876+ } 877+ } 878+ 879+ asprintf(&tmpstr, "%s/offset", attr); 880+ xar_prop_get(fsource, tmpstr, &opt); 881+ free(tmpstr); 882+ 883+ seekoff = strtoll(opt, NULL, 0); 884+ 885+ if( ((seekoff == LLONG_MAX) || (seekoff == LLONG_MIN)) && (errno == ERANGE) ) { 886+ return -1; 887+ } 888+ 889+ seekoff += XAR(xsource)->toc_count + sizeof(xar_header_t); 890+ 891+ if( XAR(xsource)->fd > 1 ) { 892+ r = lseek(XAR(xsource)->fd, seekoff, SEEK_SET); 893+ if( r == -1 ) { 894+ if( errno == ESPIPE ) { 895+ ssize_t rr; 896+ char *buf; 897+ unsigned int len; 898+ 899+ len = seekoff - XAR(xsource)->toc_count; 900+ len -= sizeof(xar_header_t); 901+ if( XAR(xsource)->heap_offset > len ) { 902+ xar_err_new(xsource); 903+ xar_err_set_file(xsource, fsource); 904+ xar_err_set_string(xsource, "Unable to seek"); 905+ xar_err_callback(xsource, XAR_SEVERITY_NONFATAL, XAR_ERR_ARCHIVE_EXTRACTION); 906+ } else { 907+ len -= XAR(xsource)->heap_offset; 908+ buf = malloc(len); 909+ assert(buf); 910+ rr = read(XAR(xsource)->fd, buf, len); 911+ if( rr < len ) { 912+ xar_err_new(xsource); 913+ xar_err_set_file(xsource, fsource); 914+ xar_err_set_string(xsource, "Unable to seek"); 915+ xar_err_callback(xsource, XAR_SEVERITY_NONFATAL, XAR_ERR_ARCHIVE_EXTRACTION); 916+ } 917+ free(buf); 918+ } 919+ } else { 920+ xar_err_new(xsource); 921+ xar_err_set_file(xsource, fsource); 922+ xar_err_set_string(xsource, "Unable to seek"); 923+ xar_err_callback(xsource, XAR_SEVERITY_NONFATAL, XAR_ERR_ARCHIVE_EXTRACTION); 924+ } 925+ } 926+ } 927+ 928+ asprintf(&tmpstr, "%s/length", attr); 929+ xar_prop_get(fsource, tmpstr, &opt); 930+ free(tmpstr); 931+ if( !opt ) { 932+ return 0; 933+ } else { 934+ fsize = strtoll(opt, NULL, 10); 935+ if( ((fsize == LLONG_MAX) || (fsize == LLONG_MIN)) && (errno == ERANGE) ) { 936+ return -1; 937+ } 938+ } 939+ 940+ inbuf = malloc(bsize); 941+ if( !inbuf ) { 942+ return -1; 943+ } 944+ 945+ 946+ while(1) { 947+ /* Size has been reached */ 948+ if( fsize == inc ) 949+ break; 950+ if( (fsize - inc) < bsize ) 951+ bsize = fsize - inc; 952+ r = read(XAR(xsource)->fd, inbuf, bsize); 953+ if( r == 0 ) 954+ break; 955+ if( (r < 0) && (errno == EINTR) ) 956+ continue; 957+ if( r < 0 ) { 958+ free(inbuf); 959+ return -1; 960+ } 961+ 962+ XAR(xsource)->heap_offset += r; 963+ inc += r; 964+ bsize = r; 965+ 966+ off = 0; 967+ 968+ do { 969+ r = write(XAR(xdest)->heap_fd, inbuf+off, r-off ); 970+ off += r; 971+ writesize += r; 972+ } while( off < r ); 973+ XAR(xdest)->heap_offset += off; 974+ XAR(xdest)->heap_len += off; 975+ } 976+ 977+ asprintf(&tmpstr, "%"PRIu64, (uint64_t)orig_heap_offset); 978+ asprintf(&tmpstr2, "%s/offset", attr); 979+ xar_prop_set(fdest, tmpstr2, tmpstr); 980+ free(tmpstr); 981+ free(tmpstr2); 982+ 983+ 984+ free(inbuf); 985+ 986+ /* It is the caller's responsibility to copy the attributes of the file, etc, this only copies the data in the heap */ 987+ 988+ return 0; 989+} 990 /* xar_heap_to_archive 991 * x: archive to operate on 992 * Returns 0 on success, -1 on error 993diff -urN xar.hash/lib/io.h xar.final/lib/io.h 994--- xar.hash/lib/io.h 2006-03-17 11:19:16.000000000 -0800 995+++ xar.final/lib/io.h 2006-03-17 10:35:14.000000000 -0800 996@@ -56,6 +56,7 @@ 997 998 int32_t xar_attrcopy_to_heap(xar_t x, xar_file_t f, const char *attr, read_callback rcb, void *context); 999 int32_t xar_attrcopy_from_heap(xar_t x, xar_file_t f, const char *attr, write_callback wcb, void *context); 1000+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); 1001 int32_t xar_heap_to_archive(xar_t x); 1002 1003 #endif /* _XAR_IO_H_ */ 1004diff -urN xar.hash/lib/linuxattr.c xar.final/lib/linuxattr.c 1005--- xar.hash/lib/linuxattr.c 2006-03-17 11:19:16.000000000 -0800 1006+++ xar.final/lib/linuxattr.c 2006-03-17 13:38:53.000000000 -0800 1007@@ -128,7 +128,7 @@ 1008 } 1009 #endif 1010 1011-int32_t xar_linuxattr_archive(xar_t x, xar_file_t f, const char* file) 1012+int32_t xar_linuxattr_archive(xar_t x, xar_file_t f, const char* file, const char *buffer, size_t len) 1013 { 1014 #if defined(HAVE_SYS_XATTR_H) && defined(HAVE_LGETXATTR) && !defined(__APPLE__) 1015 char *i, *buf = NULL; 1016@@ -139,6 +139,11 @@ 1017 1018 memset(&context,0,sizeof(struct _linuxattr_context)); 1019 1020+ /* data from buffers don't have linuxattr */ 1021+ if(len){ 1022+ return 0; 1023+ } 1024+ 1025 TRYAGAIN: 1026 buf = malloc(bufsz); 1027 if(!buf) 1028@@ -188,7 +193,7 @@ 1029 return 0; 1030 } 1031 1032-int32_t xar_linuxattr_extract(xar_t x, xar_file_t f, const char* file) 1033+int32_t xar_linuxattr_extract(xar_t x, xar_file_t f, const char* file, char *buffer, size_t len) 1034 { 1035 #if defined HAVE_SYS_XATTR_H && defined(HAVE_LSETXATTR) && !defined(__APPLE__) 1036 const char *fsname = "bogus"; 1037@@ -200,6 +205,11 @@ 1038 1039 memset(&context,0,sizeof(struct _linuxattr_context)); 1040 1041+ /* data buffers, can't store linux attrs */ 1042+ if(len){ 1043+ return 0; 1044+ } 1045+ 1046 /* Check for EA extraction behavior */ 1047 1048 memset(&sfs, 0, sizeof(sfs)); 1049diff -urN xar.hash/lib/linuxattr.h xar.final/lib/linuxattr.h 1050--- xar.hash/lib/linuxattr.h 2006-03-17 11:19:16.000000000 -0800 1051+++ xar.final/lib/linuxattr.h 2006-03-17 13:38:55.000000000 -0800 1052@@ -5,6 +5,6 @@ 1053 */ 1054 #ifndef _XAR_LINUXATTR_H_ 1055 #define _XAR_LINUXATTR_H_ 1056-int32_t xar_linuxattr_archive(xar_t x, xar_file_t f, const char* file); 1057-int32_t xar_linuxattr_extract(xar_t x, xar_file_t f, const char* file); 1058+int32_t xar_linuxattr_archive(xar_t x, xar_file_t f, const char* file, const char *buffer, size_t len); 1059+int32_t xar_linuxattr_extract(xar_t x, xar_file_t f, const char* file, char *buffer, size_t len); 1060 #endif /* _XAR_LINUXATTR_H_ */ 1061diff -urN xar.hash/lib/stat.c xar.final/lib/stat.c 1062--- xar.hash/lib/stat.c 2006-03-17 11:19:16.000000000 -0800 1063+++ xar.final/lib/stat.c 2006-03-17 10:35:14.000000000 -0800 1064@@ -214,7 +214,7 @@ 1065 return 0; 1066 } 1067 1068-int32_t xar_stat_archive(xar_t x, xar_file_t f, const char *file) { 1069+int32_t xar_stat_archive(xar_t x, xar_file_t f, const char *file, const char *buffer, size_t len) { 1070 char *tmpstr; 1071 struct passwd *pw; 1072 struct group *gr; 1073@@ -222,6 +222,12 @@ 1074 struct tm t; 1075 const char *type; 1076 1077+ /* no stat attributes for data from a buffer, it is just a file */ 1078+ if(len){ 1079+ xar_prop_set(f, "type", "file"); 1080+ return 0; 1081+ } 1082+ 1083 if( S_ISREG(XAR(x)->sbcache.st_mode) && (XAR(x)->sbcache.st_nlink > 1) ) { 1084 xar_file_t tmpf; 1085 const char *id = xar_attr_get(f, NULL, "id"); 1086@@ -304,7 +310,7 @@ 1087 return 0; 1088 } 1089 1090-int32_t xar_set_perm(xar_t x, xar_file_t f, const char *file) { 1091+int32_t xar_set_perm(xar_t x, xar_file_t f, const char *file, char *buffer, size_t len) { 1092 const char *opt; 1093 int32_t m=0, mset=0; 1094 uid_t u; 1095@@ -314,6 +320,10 @@ 1096 enum {ATIME=0, MTIME}; 1097 struct timeval tv[2]; 1098 1099+ /* when writing to a buffer, there are no permissions to set */ 1100+ if ( len ) 1101+ return 0; 1102+ 1103 /* in case we don't find anything useful in the archive */ 1104 u = geteuid(); 1105 g = getegid(); 1106@@ -433,7 +443,7 @@ 1107 return 0; 1108 } 1109 1110-int32_t xar_stat_extract(xar_t x, xar_file_t f, const char *file) { 1111+int32_t xar_stat_extract(xar_t x, xar_file_t f, const char *file, char *buffer, size_t len) { 1112 const char *opt; 1113 int ret, fd; 1114 1115diff -urN xar.hash/lib/stat.h xar.final/lib/stat.h 1116--- xar.hash/lib/stat.h 2006-03-17 11:19:16.000000000 -0800 1117+++ xar.final/lib/stat.h 2006-03-17 10:35:14.000000000 -0800 1118@@ -36,8 +36,8 @@ 1119 1120 #include "xar.h" 1121 1122-int32_t xar_stat_archive(xar_t x, xar_file_t f, const char *file); 1123-int32_t xar_stat_extract(xar_t x, xar_file_t f, const char *file); 1124-int32_t xar_set_perm(xar_t x, xar_file_t f, const char *file); 1125+int32_t xar_stat_archive(xar_t x, xar_file_t f, const char *file, const char *buffer, size_t len); 1126+int32_t xar_stat_extract(xar_t x, xar_file_t f, const char *file, char *buffer, size_t len); 1127+int32_t xar_set_perm(xar_t x, xar_file_t f, const char *file, char *buffer, size_t len); 1128 1129 #endif /* _XAR_STAT_H_ */ 1130diff -urN xar.hash/lib/util.c xar.final/lib/util.c 1131--- xar.hash/lib/util.c 2006-03-17 11:19:16.000000000 -0800 1132+++ xar.final/lib/util.c 2006-03-17 10:35:14.000000000 -0800 1133@@ -30,6 +30,7 @@ 1134 * 03-Apr-2005 1135 * DRI: Rob Braun <bbraun@opendarwin.org> 1136 */ 1137+ 1138 #include <stdio.h> 1139 #include <stdint.h> 1140 #include <sys/types.h> 1141@@ -42,6 +43,7 @@ 1142 #include "asprintf.h" 1143 #endif 1144 #include "xar.h" 1145+#include "archive.h" 1146 #include "filetree.h" 1147 1148 uint64_t xar_ntoh64(uint64_t num) { 1149@@ -97,6 +99,10 @@ 1150 return ret; 1151 } 1152 1153+off_t xar_get_heap_offset(xar_t x) { 1154+ return XAR(x)->toc_count + sizeof(xar_header_t); 1155+} 1156+ 1157 /* xar_read_fd 1158 * Summary: Reads from a file descriptor a certain number of bytes to a specific 1159 * buffer. This simple wrapper just handles certain retryable error situations. 1160diff -urN xar.hash/lib/util.h xar.final/lib/util.h 1161--- xar.hash/lib/util.h 2006-03-17 11:19:16.000000000 -0800 1162+++ xar.final/lib/util.h 2006-03-17 10:35:14.000000000 -0800 1163@@ -41,6 +41,7 @@ 1164 uint64_t xar_ntoh64(uint64_t num); 1165 uint32_t xar_swap32(uint32_t num); 1166 char *xar_get_path(xar_file_t f); 1167+off_t xar_get_heap_offset(xar_t x); 1168 ssize_t xar_read_fd(int fd, void * buffer, size_t nbytes); 1169 ssize_t xar_write_fd(int fd, void * buffer, size_t nbytes); 1170 1171