Beispiel #1
0
static xar_file_t xar_link_lookup(xar_t x, dev_t dev, ino_t ino, xar_file_t f) {
	char key[32];
	xar_file_t ret;

	memset(key, 0, sizeof(key));
	snprintf(key, sizeof(key)-1, "%08" DEV_HEXSTRING "%08" INO_HEXSTRING, DEV_CAST dev, INO_CAST ino);
	ret = xmlHashLookup(XAR(x)->ino_hash, BAD_CAST(key));
	if( ret == NULL ) {
		xmlHashAddEntry(XAR(x)->ino_hash, BAD_CAST(key), XAR_FILE(f));
		return NULL;
	}
	return ret;
}
Beispiel #2
0
xar_ea_t xar_ea_new(xar_file_t f, const char *name)
{
	xar_ea_t ret;

	ret = calloc(sizeof(struct __xar_ea_t), 1);
	 if( !ret )
		return NULL;

	XAR_EA(ret)->prop = xar_prop_new(f, NULL);
	if( !XAR_EA(ret)->prop ) {
		free(ret);
		return NULL;
	}

	xar_prop_setkey(XAR_EA(ret)->prop, "ea");
	xar_prop_setvalue(XAR_EA(ret)->prop, NULL);
	XAR_PROP(XAR_EA(ret)->prop)->attrs = xar_attr_new();
	XAR_ATTR(XAR_PROP(XAR_EA(ret)->prop)->attrs)->key = strdup("id");
	asprintf((char **)&XAR_ATTR(XAR_PROP(XAR_EA(ret)->prop)->attrs)->value, "%lld", XAR_FILE(f)->nexteaid++);

	xar_prop_pset(f, XAR_EA(ret)->prop, "name", name);
	
	return ret;
}
Beispiel #3
0
int32_t xar_attrcopy_to_heap(xar_t x, xar_file_t f, xar_prop_t p, read_callback rcb, void *context) {
	int modulecount = (sizeof(xar_datamods)/sizeof(struct datamod));
	void	*modulecontext[modulecount];
	int r, off, i;
	size_t bsize, rsize;
	int64_t readsize=0, writesize=0, inc = 0;
	void *inbuf;
	char *tmpstr = NULL;
	const char *opt, *csum;
	off_t orig_heap_offset = XAR(x)->heap_offset;
	xar_file_t tmpf = NULL;
	xar_prop_t tmpp = NULL;

	memset(modulecontext, 0, sizeof(void*)*modulecount);

	opt = xar_opt_get(x, XAR_OPT_RSIZE);
	if( !opt ) {
		bsize = 4096;
	} else {
		bsize = strtol(opt, NULL, 0);
		if( ((bsize == LONG_MAX) || (bsize == LONG_MIN)) && (errno == ERANGE) ) {
			bsize = 4096;
		}
	}

	r = 1;
	while(r != 0) {
		inbuf = malloc(bsize);
		if( !inbuf )
			return -1;

		r = rcb(x, f, inbuf, bsize, context);
		if( r < 0 ) {
			free(inbuf);
			return -1;
		}

		readsize+=r;
		inc += r;
		rsize = r;

		/* filter the data through the in modules */
		for( i = 0; i < modulecount; i++) {
			if( xar_datamods[i].th_in ) {
				xar_datamods[i].th_in(x, f, p, &inbuf, &rsize, &(modulecontext[i]));
			}
		}

		/* filter the data through the out modules */
		for( i = 0; i < modulecount; i++) {
			if( xar_datamods[i].th_out )
				xar_datamods[i].th_out(x, f, p, inbuf, rsize, &(modulecontext[i]));
		}

		off = 0;
		if( rsize != 0 ) {
			do {
				r = write(XAR(x)->heap_fd, inbuf+off, rsize-off);
				if( (r < 0) && (errno != EINTR) )
					return -1;
				off += r;
				writesize += r;
			} while( off < rsize );
		}
		XAR(x)->heap_offset += off;
		free(inbuf);
		
	}


	/* If size is 0, don't bother having anything in the heap */
	if( readsize == 0 ) {
		XAR(x)->heap_offset = orig_heap_offset;
		lseek(XAR(x)->heap_fd, -writesize, SEEK_CUR);
		for( i = 0; i < modulecount; i++) {
			if( xar_datamods[i].th_done )
				xar_datamods[i].th_done(x, f, p, &(modulecontext[i]));
		}
		return 0;
	}
	/* finish up anything that still needs doing */
	for( i = 0; i < modulecount; i++) {
		if( xar_datamods[i].th_done )
			xar_datamods[i].th_done(x, f, p, &(modulecontext[i]));
	}

	XAR(x)->heap_len += writesize;
	tmpp = xar_prop_pget(p, "archived-checksum");
	if( tmpp )
		csum = xar_prop_getvalue(tmpp);
	tmpf = xmlHashLookup(XAR(x)->csum_hash, BAD_CAST(csum));
	if( tmpf ) {
		const char *attr = xar_prop_getkey(p);
		opt = xar_opt_get(x, XAR_OPT_LINKSAME);
		if( opt && (strcmp(attr, "data") == 0) ) {
			const char *id = xar_attr_pget(tmpf, NULL, "id");
			xar_prop_pset(f, NULL, "type", "hardlink");
			tmpp = xar_prop_pfirst(f);
			if( tmpp )
				tmpp = xar_prop_find(tmpp, "type");
			if( tmpp )
				xar_attr_pset(f, tmpp, "link", id);

			xar_prop_pset(tmpf, NULL, "type", "hardlink");
			tmpp = xar_prop_pfirst(tmpf);
			if( tmpp )
				tmpp = xar_prop_find(tmpp, "type");
			if( tmpp )
				xar_attr_pset(tmpf, tmpp, "link", "original");
			
			tmpp = xar_prop_pfirst(f);
			if( tmpp )
				tmpp = xar_prop_find(tmpp, "data");
			xar_prop_punset(f, tmpp);

			XAR(x)->heap_offset = orig_heap_offset;
			lseek(XAR(x)->heap_fd, -writesize, SEEK_CUR);
			XAR(x)->heap_len -= writesize;
			return 0;
		} 
		opt = xar_opt_get(x, XAR_OPT_COALESCE);
		if( opt ) {
			long long tmpoff;
			const char *offstr = NULL;
			tmpp = xar_prop_pfirst(tmpf);
			if( tmpp ) {
				const char *key;
				key = xar_prop_getkey(p);
				tmpp = xar_prop_find(tmpp, key);
			}
			if( tmpp )
				tmpp = xar_prop_pget(tmpp, "offset");
			if( tmpp )
				offstr = xar_prop_getvalue(tmpp);
			if( offstr ) {
				tmpoff = strtoll(offstr, NULL, 10);
				XAR(x)->heap_offset = orig_heap_offset;
				lseek(XAR(x)->heap_fd, -writesize, SEEK_CUR);
				orig_heap_offset = tmpoff;
				XAR(x)->heap_len -= writesize;
			}
			
		}
	} else {
		xmlHashAddEntry(XAR(x)->csum_hash, BAD_CAST(csum), XAR_FILE(f));
	}

	asprintf(&tmpstr, "%"PRIu64, readsize);
	xar_prop_pset(f, p, "size", tmpstr);
	free(tmpstr);

	asprintf(&tmpstr, "%"PRIu64, (uint64_t)orig_heap_offset);
	xar_prop_pset(f, p, "offset", tmpstr);
	free(tmpstr);
	
	tmpstr = (char *)xar_opt_get(x, XAR_OPT_COMPRESSION);
	if( tmpstr && (strcmp(tmpstr, XAR_OPT_VAL_NONE) == 0) ) {
		xar_prop_pset(f, p, "encoding", NULL);
		tmpp = xar_prop_pget(p, "encoding");
		if( tmpp )
			xar_attr_pset(f, tmpp, "style", "application/octet-stream");
	}

	asprintf(&tmpstr, "%"PRIu64, writesize);
	xar_prop_pset(f, p, "length", tmpstr);
	free(tmpstr);

	return 0;
}
Beispiel #4
0
int32_t xar_attrcopy_to_heap(xar_t x, xar_file_t f, xar_prop_t p, read_callback rcb, void *context) {
	int modulecount = (sizeof(xar_datamods)/sizeof(struct datamod));
	void *modulecontext[modulecount];
	int r, i;
	size_t bsize, rsize;
	int64_t readsize=0, writesize=0, inc = 0, this_write=0;
	void *inbuf;
	char *tmpstr = NULL;
	const char *opt = NULL, *csum = NULL;
	off_t orig_heap_offset = XAR(x)->heap_offset;
	xar_file_t tmpf = NULL;
	xar_prop_t tmpp = NULL;

	memset(modulecontext, 0, sizeof(void*)*modulecount);

	bsize = xar_io_get_rsize(x);

	r = 1;
	
	// (Apple) allocate once
	inbuf = malloc(bsize);
	if( !inbuf )
		return -1;
	
	while(r != 0) {

		r = rcb(x, f, inbuf, bsize, context);
		if( r < 0 ) {
			free(inbuf);
			return -1;
		}

		readsize+=r;
		inc += r;
		rsize = r;

		/* filter the data through the in modules */
		for( i = 0; i < modulecount; i++) {
			if( xar_datamods[i].th_in ) {
				xar_datamods[i].th_in(x, f, p, &inbuf, &rsize, &(modulecontext[i]));
			}
		}

		/* filter the data through the out modules */
		for( i = 0; i < modulecount; i++) {
			if( xar_datamods[i].th_out )
				xar_datamods[i].th_out(x, f, p, inbuf, rsize, &(modulecontext[i]));
		}
		
		size_t written = 0;
		if( rsize != 0 ) {
			while(written < rsize) {
				this_write = xar_write_fd(XAR(x)->heap_fd, inbuf, rsize);
				if( this_write < 0 ) {
					xar_err_new(x);
					xar_err_set_string(x, "write(2) error when writing to heap");
					xar_err_set_errno(x, errno);
					xar_err_callback(x, XAR_SEVERITY_FATAL, XAR_ERR_ARCHIVE_CREATION);
					free(inbuf);
					return -1;
				}
				written += this_write;
			}
		}
		XAR(x)->heap_offset += written;
		writesize += written;
	}
	
	free(inbuf);


	/* If size is 0, don't bother having anything in the heap */
	if( readsize == 0 ) {
		XAR(x)->heap_offset = orig_heap_offset;
		lseek(XAR(x)->heap_fd, -writesize, SEEK_CUR);
		for( i = 0; i < modulecount; i++) {
			if( xar_datamods[i].th_done )
				xar_datamods[i].th_done(x, f, p, &(modulecontext[i]));
		}
		return 0;
	}
	/* finish up anything that still needs doing */
	for( i = 0; i < modulecount; i++) {
		if( xar_datamods[i].th_done )
			xar_datamods[i].th_done(x, f, p, &(modulecontext[i]));
	}

	XAR(x)->heap_len += writesize;
	tmpp = xar_prop_pget(p, "archived-checksum");
	if( tmpp )
		csum = xar_prop_getvalue(tmpp);
	if( csum )
		tmpf = xmlHashLookup(XAR(x)->csum_hash, BAD_CAST(csum));
	if( tmpf ) {
		const char *attr = xar_prop_getkey(p);
		opt = xar_opt_get(x, XAR_OPT_LINKSAME);
		if( opt && (strcmp(attr, "data") == 0) ) {
			const char *id = xar_attr_pget(tmpf, NULL, "id");
			xar_prop_pset(f, NULL, "type", "hardlink");
			tmpp = xar_prop_pfirst(f);
			if( tmpp )
				tmpp = xar_prop_find(tmpp, "type");
			if( tmpp )
				xar_attr_pset(f, tmpp, "link", id);

			xar_prop_pset(tmpf, NULL, "type", "hardlink");
			tmpp = xar_prop_pfirst(tmpf);
			if( tmpp )
				tmpp = xar_prop_find(tmpp, "type");
			if( tmpp )
				xar_attr_pset(tmpf, tmpp, "link", "original");
			
			tmpp = xar_prop_pfirst(f);
			if( tmpp )
				tmpp = xar_prop_find(tmpp, "data");
			xar_prop_punset(f, tmpp);

			XAR(x)->heap_offset = orig_heap_offset;
			lseek(XAR(x)->heap_fd, -writesize, SEEK_CUR);
			XAR(x)->heap_len -= writesize;
			return 0;
		} 
		opt = xar_opt_get(x, XAR_OPT_COALESCE);
		if( opt ) {
			long long tmpoff;
			const char *offstr = NULL;
			tmpp = xar_prop_pfirst(tmpf);
			if( tmpp ) {
				const char *key;
				key = xar_prop_getkey(p);
				tmpp = xar_prop_find(tmpp, key);
			}
			if( tmpp )
				tmpp = xar_prop_pget(tmpp, "offset");
			if( tmpp )
				offstr = xar_prop_getvalue(tmpp);
			if( offstr ) {
				tmpoff = strtoll(offstr, NULL, 10);
				XAR(x)->heap_offset = orig_heap_offset;
				lseek(XAR(x)->heap_fd, -writesize, SEEK_CUR);
				orig_heap_offset = tmpoff;
				XAR(x)->heap_len -= writesize;
			}
			
		}
	} else if( csum ) {
		xmlHashAddEntry(XAR(x)->csum_hash, BAD_CAST(csum), XAR_FILE(f));
	} else {
		xar_err_new(x);
		xar_err_set_file(x, f);
		xar_err_set_string(x, "No archived-checksum");
		xar_err_callback(x, XAR_SEVERITY_WARNING, XAR_ERR_ARCHIVE_CREATION);
	}

	asprintf(&tmpstr, "%"PRIu64, readsize);
	xar_prop_pset(f, p, "size", tmpstr);
	free(tmpstr);

	asprintf(&tmpstr, "%"PRIu64, (uint64_t)orig_heap_offset);
	xar_prop_pset(f, p, "offset", tmpstr);
	free(tmpstr);
	
	tmpstr = (char *)xar_opt_get(x, XAR_OPT_COMPRESSION);
	if( tmpstr && (strcmp(tmpstr, XAR_OPT_VAL_NONE) == 0) ) {
		xar_prop_pset(f, p, "encoding", NULL);
		tmpp = xar_prop_pget(p, "encoding");
		if( tmpp )
			xar_attr_pset(f, tmpp, "style", "application/octet-stream");
	}

	asprintf(&tmpstr, "%"PRIu64, writesize);
	xar_prop_pset(f, p, "length", tmpstr);
	free(tmpstr);

	return 0;
}
Beispiel #5
0
/* replace_sign: rip out all current signatures and certs and insert a new pair
		Since libxar is currently not capable of doing this directly, we have to create a new xar archive,
		copy all the files and options from the current archive, and sign the new archive
*/
static void replace_sign(const char *filename) {

	xar_t old_xar, new_xar;
	xar_signature_t sig;
	char *new_xar_path = (char *)malloc(15);
	strncpy(new_xar_path, "/tmp/xar.XXXXX", 15);
	new_xar_path = mktemp(new_xar_path);
	char *systemcall;
	int err;
	
	// open both archives
	old_xar = xar_open(filename, READ);
	if ( old_xar == NULL ) {
		fprintf(stderr, "Could not open archive %s!\n", filename);
		exit(1);
	}
	new_xar = xar_open(new_xar_path, WRITE);
	if( !new_xar ) {
		fprintf(stderr, "Error creating new archive %s\n", new_xar_path);
		exit(1);
	}
	
	// install new signature and new certs in new_xar
	sig = xar_signature_new(new_xar, "RSA", SigSize, &signingCallback, NULL);
	if ( LeafCertPath )
		insert_cert(sig, LeafCertPath);
	if ( IntermediateCertPath )
		insert_cert(sig, IntermediateCertPath);
	
	// copy options
	char *opts[6] = {XAR_OPT_TOCCKSUM, XAR_OPT_COMPRESSION, XAR_OPT_COALESCE, XAR_OPT_LINKSAME, XAR_OPT_RSIZE, XAR_OPT_OWNERSHIP};
	int i;
	const char *opt;
	for (i=0; i<6; i++) {
		opt = xar_opt_get(old_xar, opts[i]);
		if (opt)
			xar_opt_set(new_xar, opts[i], opt);
	}

	// skip copy subdocs for now since we don't use them yet
	
	// copy files
	xar_iter_t iter = xar_iter_new();
	xar_file_t f = xar_file_first(old_xar, iter);
		// xar_file_next iterates the archive depth-first, i.e. all children are enumerated before the siblings.
	const char *name;
	char *f_dirname, *stack_top_dirname;
	stack s_new = stack_new();
	stack s_old = stack_new();
	xar_file_t last_copied = NULL, last_added;
	
	xar_iter_t loopIter = xar_iter_new();
	xar_file_t current_xar_file;
	for (current_xar_file = xar_file_first(old_xar, loopIter); current_xar_file; current_xar_file = xar_file_next(loopIter))
	{
		printf("old_xar -> %s (parent: %s)\n",xar_get_path(current_xar_file),XAR_FILE(current_xar_file)->parent?xar_get_path(XAR_FILE(current_xar_file)->parent):"(nil)");
	}
	
	do {
		// parent is the parent in the new archive!
		// 3 cases:
		//  1. the file has no parent. Happens for every file at the top level of the archive.
		//  2. the file's parent is the last file we added. Happens while descending down a path
		//  3. the file's parent is one of the ancestors of the last file (and not NULL, that would be case 1)
		//		that means we either go back up the tree and add a sibling of one of the ancestors, or we add a
		//		sibling on the same level
		xar_prop_get(f, "name", &name);	// filename, without any path info
		if (!XAR_FILE(f)->parent) {	// case 1
			printf("root: %s\n",xar_get_path(f));
			last_added = xar_add_from_archive(new_xar, NULL, name, old_xar, f);
			last_copied = f;
			stack_push(s_new, (void *)last_added);
			stack_push(s_old, (void *)last_copied);
		} else if (f->parent == last_copied) {	// case 2			
			printf("child: %s -> %s\n",xar_get_path(f->parent),xar_get_path(f));
			last_added = xar_add_from_archive(new_xar, last_added, name, old_xar, f);
			last_copied = f;
			stack_push(s_new, (void *)last_added);
			stack_push(s_old, (void *)last_copied);
		} else {	// case 3
			printf("searching for parent: %s ?\n",xar_get_path(f));
			while (XAR_FILE(f)->parent != XAR_FILE(s_old->top->data)->parent) {
				printf("popping: %s\n",xar_get_path(XAR_FILE(s_old->top->data)));
				stack_pop(s_new);
				stack_pop(s_old);
			}
			printf("found: %s -> %s\n",xar_get_path(XAR_FILE(s_new->top->data)),xar_get_path(f));
			stack_pop(s_new);
			stack_pop(s_old);
			last_added = xar_add_from_archive(new_xar, (xar_file_t)(s_new->top->data), name, old_xar, f);
			last_copied = f;
			stack_push(s_new, (void *)last_added);
			stack_push(s_old, (void *)last_copied);
		}
	} while (f = xar_file_next(iter));
		
	loopIter = xar_iter_new();
	for (current_xar_file = xar_file_first(new_xar, loopIter); current_xar_file; current_xar_file = xar_file_next(loopIter))
	{
		char * current_path = xar_get_path(current_xar_file);
		printf("new_xar -> %s\n",current_path);
	}
	
	xar_iter_free(iter);
	stack_free(s_new);
	stack_free(s_old);
	if( xar_close(new_xar) != 0 ) {
		fprintf(stderr, "Error creating the archive\n");
		if( !Err )
			Err = 42;
	}
	xar_close(old_xar);
	
	// write signature offset to file (have to re-open so xar_close can figure out the correct offset)
	new_xar = xar_open(new_xar_path, READ);
	if( !new_xar ) {
		fprintf(stderr, "Error re-opening new archive %s\n", new_xar_path);
		unlink(new_xar_path);
		exit(1);
	}
	
	if (extract_sig_offset(new_xar, SigOffsetDumpPath)) {
		xar_close(new_xar);
		unlink(new_xar_path);
		exit(1);
	}
		
	xar_close(new_xar);
	
	// delete old archive, move new in its place
	unlink(filename);
	asprintf(&systemcall, "cp \"%s\" \"%s\"", new_xar_path, filename);
	err = system(systemcall);
	if (err) {
		fprintf(stderr, "Could not copy new archive to final location (system() returned %i)\n", err);
		unlink(new_xar_path);
		exit(1);
	}
	
	// Delete the tmp archive
	unlink(new_xar_path);
	
	free(systemcall);
}
Beispiel #6
0
int32_t xar_stat_extract(xar_t x, xar_file_t f, const char *file, char *buffer, size_t len) {
	const char *opt;
	int ret, fd;
	mode_t modet = 0;

	xar_prop_get(f, "type", &opt);
	if(opt && (strcmp(opt, "character special") == 0))
		modet = S_IFCHR;
	if(opt && (strcmp(opt, "block special") == 0))
		modet = S_IFBLK;

	if( modet ) {
		uint32_t major, minor;
		long long tmpll;
		dev_t devt;

		xar_prop_get(f, "device/major", &opt);
		tmpll = strtoll(opt, NULL, 10);
		if( ( (tmpll == LLONG_MIN) || (tmpll == LLONG_MAX) ) && (errno == ERANGE) )
			return -1;
		if( (tmpll < 0) || (tmpll > 255) )
			return -1;
		major = tmpll;

		xar_prop_get(f, "device/minor", &opt);
		tmpll = strtoll(opt, NULL, 10);
		if( ( (tmpll == LLONG_MIN) || (tmpll == LLONG_MAX) ) && (errno == ERANGE) )
			return -1;
		if( (tmpll < 0) || (tmpll > 255) )
			return -1;
		minor = tmpll;
		
		devt = xar_makedev(major, minor);
		unlink(file);
		if( mknod(file, modet, devt) ) {
			xar_err_new(x);
			xar_err_set_file(x, f);
			xar_err_set_string(x, "mknod: Could not create character device");
			xar_err_callback(x, XAR_SEVERITY_NONFATAL, XAR_ERR_ARCHIVE_EXTRACTION);
			return -1;
		}
		return 0;
	}
	if(opt && (strcmp(opt, "directory") == 0)) {
		ret = mkdir(file, 0700);
		if( (ret != 0) && (errno != EEXIST) ) {
			xar_err_new(x);
			xar_err_set_file(x, f);
			xar_err_set_string(x, "stat: Could not create directory");
			xar_err_callback(x, XAR_SEVERITY_NONFATAL, XAR_ERR_ARCHIVE_EXTRACTION);
			return ret;
		}
		return 0;
	}
	if(opt && (strcmp(opt, "symlink") == 0)) {
		xar_prop_get(f, "link", &opt);
		if( opt ) {
			unlink(file);
			ret = symlink(opt, file);
			if( ret != 0 ) {
				xar_err_new(x);
				xar_err_set_file(x, f);
				xar_err_set_string(x, "stat: Could not create symlink");
				xar_err_callback(x, XAR_SEVERITY_NONFATAL, XAR_ERR_ARCHIVE_EXTRACTION);
			}
			return ret;
		}
	}
	if(opt && (strcmp(opt, "hardlink") == 0)) {
		xar_file_t tmpf;
		opt = xar_attr_get(f, "type", "link");
		if( !opt )
			return 0;
		if( strcmp(opt, "original") == 0 )
			goto CREATEFILE;

		tmpf = xmlHashLookup(XAR(x)->link_hash, BAD_CAST(opt));
		if( !tmpf ) {
			xar_err_new(x);
			xar_err_set_file(x, f);
			xar_err_set_string(x, "stat: Encountered hardlink with no original");
			xar_err_callback(x, XAR_SEVERITY_NONFATAL, XAR_ERR_ARCHIVE_EXTRACTION);
			return -1;
		}

		unlink(file);
		if( link(XAR_FILE(tmpf)->fspath, file) != 0 ) {
			if( errno == ENOENT ) {
				xar_iter_t i;
				const char *ptr;
				i = xar_iter_new(x);
				for(ptr = xar_prop_first(tmpf, i); ptr; ptr = xar_prop_next(i)) {
					xar_iter_t a;
					const char *val = NULL;
					const char *akey, *aval;
					if( strncmp("data", ptr, 4) != 0 )
						continue;
	
					if( xar_prop_get(tmpf, ptr, &val) )
						continue;
	
					xar_prop_set(f, ptr, val);
					a = xar_iter_new(x);
					for(akey = xar_attr_first(tmpf, ptr, a); akey; akey = xar_attr_next(a)) {
						aval = xar_attr_get(tmpf, ptr, akey);
						xar_attr_set(f, ptr, akey, aval);
					}
					xar_iter_free(a);
				}
				xar_iter_free(i);
				xar_attr_set(f, "type", "link", "original");
				return 0;
			} else {
				xar_err_new(x);
				xar_err_set_file(x, f);
				xar_err_set_string(x, "stat: Could not link hardlink to original");
				xar_err_callback(x, XAR_SEVERITY_NONFATAL, XAR_ERR_ARCHIVE_EXTRACTION);
				return -1;
			}
		}
		return 0;
	}

	if(opt && (strcmp(opt, "fifo") == 0)) {
		unlink(file);
		if( mkfifo(file, 0) ) {
			xar_err_new(x);
			xar_err_set_file(x, f);
			xar_err_set_string(x, "mkfifo: Could not create fifo");
			xar_err_callback(x, XAR_SEVERITY_NONFATAL, XAR_ERR_ARCHIVE_EXTRACTION);
			return -1;
		}
		return 0;
	}

	/* skip sockets */
	if(opt && (strcmp(opt, "socket") == 0)) {
		return 0;
	}

CREATEFILE:
	unlink(file);
	fd = open(file, O_RDWR|O_CREAT|O_TRUNC, 0600);
	if( fd > 0 )
		close(fd);
	return 0;
}