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