diff -Nupr star-1.5.orig/include/schily/schily.h star-1.5/include/schily/schily.h
--- star-1.5.orig/include/schily/schily.h	2012-09-25 12:56:41.655757133 +0200
+++ star-1.5/include/schily/schily.h	2012-09-25 14:27:44.652760750 +0200
@@ -113,8 +113,6 @@ extern	int	fexecle __PR((const char *, F
 		/* 6th arg not const, fexecv forces av[ac] = NULL */
 extern	int	fexecv __PR((const char *, FILE *, FILE *, FILE *, int,
 							char **));
-extern	int	fexecve __PR((const char *, FILE *, FILE *, FILE *,
-					char * const *, char * const *));
 extern	int	fspawnv __PR((FILE *, FILE *, FILE *, int, char * const *));
 extern	int	fspawnl __PR((FILE *, FILE *, FILE *,
 					const char *, const char *, ...));
@@ -243,7 +241,6 @@ extern	char	*fillbytes __PR((void *, int
 extern	char	*findbytes __PR((const void *, int, char));
 extern	int	findline __PR((const char *, char, const char *,
 							int, char **, int));
-extern	int	getline __PR((char *, int));
 extern	int	getstr __PR((char *, int));
 extern	int	breakline __PR((char *, char, char **, int));
 extern	int	getallargs __PR((int *, char * const**, const char *, ...));
diff -Nupr star-1.5.orig/star/buffer.c star-1.5/star/buffer.c
--- star-1.5.orig/star/buffer.c	2008-03-16 16:40:41.000000000 +0100
+++ star-1.5/star/buffer.c	2012-09-25 12:57:13.018761999 +0200
@@ -798,7 +798,7 @@ initbuf(nblocks)
 
 		bigptr = bigbuf = __malloc((size_t) bufsize+10+pagesize,
 								"buffer");
-		bigptr = bigbuf = (char *)roundup((Intptr_t)bigptr, pagesize);
+		bigptr = bigbuf = (char *)roundup((UIntptr_t)bigptr, pagesize);
 		fillbytes(bigbuf, bufsize, '\0');
 		fillbytes(&bigbuf[bufsize], 10, 'U');
 
diff -Nupr star-1.5.orig/star/buffer.c.orig star-1.5/star/buffer.c.orig
--- star-1.5.orig/star/buffer.c.orig	1970-01-01 01:00:00.000000000 +0100
+++ star-1.5/star/buffer.c.orig	2008-03-16 16:40:41.000000000 +0100
@@ -0,0 +1,1977 @@
+/* @(#)buffer.c	1.146 08/03/16 Copyright 1985, 1995, 2001-2008 J. Schilling */
+#ifndef lint
+static	char sccsid[] =
+	"@(#)buffer.c	1.146 08/03/16 Copyright 1985, 1995, 2001-2008 J. Schilling";
+#endif
+/*
+ *	Buffer handling routines
+ *
+ *	Copyright (c) 1985, 1995, 2001-2008 J. Schilling
+ */
+/*
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License").  You may not use this file except in compliance
+ * with the License.
+ *
+ * See the file CDDL.Schily.txt in this distribution for details.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file CDDL.Schily.txt from this distribution.
+ */
+
+#include <schily/mconfig.h>
+
+/*
+ * XXX Until we find a better way, the next definitions must be in sync
+ * XXX with the definitions in librmt/remote.c
+ */
+#if !defined(HAVE_FORK) || !defined(HAVE_SOCKETPAIR) || !defined(HAVE_DUP2)
+#undef	USE_RCMD_RSH
+#endif
+#if !defined(HAVE_GETSERVBYNAME)
+#undef	USE_REMOTE				/* Cannot get rcmd() port # */
+#endif
+#if (!defined(HAVE_NETDB_H) || !defined(HAVE_RCMD)) && !defined(USE_RCMD_RSH)
+#undef	USE_REMOTE				/* There is no rcmd() */
+#endif
+
+#include <stdio.h>
+#include <schily/stdlib.h>
+#include <schily/unistd.h>
+#include <schily/libport.h>	/* getpagesize() */
+#include <schily/fcntl.h>
+#include <schily/ioctl.h>
+#include <schily/varargs.h>
+#include "star.h"
+#include "props.h"
+#include <schily/errno.h>
+#include <schily/standard.h>
+#include "fifo.h"
+#include <schily/string.h>
+#include <schily/wait.h>
+#include <schily/schily.h>
+#include <schily/mtio.h>
+#include <schily/librmt.h>
+#include "starsubs.h"
+
+#ifdef	NEED_O_BINARY
+#include <io.h>					/* for setmode() prototype */
+#endif
+
+long	bigcnt	= 0;
+int	bigsize	= 0;		/* Tape block size */
+int	bufsize	= 0;		/* Available buffer size */
+char	*bigbase = NULL;
+char	*bigbuf	= NULL;
+char	*bigptr	= NULL;
+char	*eofptr	= NULL;
+Llong	curblockno;
+
+m_stats	bstat;
+m_stats	*stats	= &bstat;
+int	pid;
+
+#ifdef	timerclear
+LOCAL	struct	timeval	starttime;
+LOCAL	struct	timeval	stoptime;
+#endif
+
+LOCAL	BOOL	isremote = FALSE;
+LOCAL	int	remfd	= -1;
+LOCAL	char	*remfn;
+
+#ifdef __DJGPP__
+LOCAL	FILE	*compress_tarf_save;	/* Old value of tarf	 */
+LOCAL	FILE	*compress_tmpf = NULL;	/* FILE * from tmpfile() */
+#endif
+
+extern	FILE	*tarf;
+extern	FILE	*tty;
+extern	FILE	*vpr;
+extern	char	*tarfiles[];
+extern	int	ntarfiles;
+extern	int	tarfindex;
+extern	BOOL	force_noremote;
+LOCAL	int	lastremote = -1;
+extern	BOOL	multivol;
+extern	char	*newvol_script;
+extern	BOOL	use_fifo;
+extern	int	swapflg;
+extern	int	cmptype;
+extern	BOOL	debug;
+extern	BOOL	print_artype;
+extern	BOOL	silent;
+extern	BOOL	showtime;
+extern	BOOL	no_stats;
+extern	BOOL	cpio_stats;
+extern	BOOL	do_fifostats;
+extern	BOOL	cflag;
+extern	BOOL	uflag;
+extern	BOOL	rflag;
+extern	BOOL	copyflag;
+extern	BOOL	Zflag;
+extern	BOOL	zflag;
+extern	BOOL	bzflag;
+extern	BOOL	lzoflag;
+extern	BOOL	p7zflag;
+extern	char	*compress_prg;
+extern	BOOL	multblk;
+extern	BOOL	partial;
+extern	BOOL	wready;
+extern	BOOL	nullout;
+extern	Ullong	tsize;
+extern	BOOL	nowarn;
+
+extern	int	intr;
+
+extern	GINFO	*gip;
+
+
+EXPORT	void	opt_remote	__PR((void));
+EXPORT	BOOL	openremote	__PR((void));
+EXPORT	void	opentape	__PR((void));
+EXPORT	void	closetape	__PR((void));
+EXPORT	void	changetape	__PR((BOOL donext));
+EXPORT	void	nextitape	__PR((void));
+EXPORT	void	nextotape	__PR((void));
+EXPORT	int	startvol	__PR((char *buf, int amount));
+EXPORT	void	newvolhdr	__PR((char *buf, int amount, BOOL do_fifo));
+#ifdef	FIFO
+LOCAL	void	fbit_ffss	__PR((bitstr_t *name, int startb, int stopb, int *value));
+LOCAL	BOOL	fifo_hpos	__PR((char *buf, off_t *posp));
+#endif
+EXPORT	void	initbuf		__PR((int nblocks));
+EXPORT	void	markeof		__PR((void));
+EXPORT	void	syncbuf		__PR((void));
+EXPORT	int	peekblock	__PR((char *buf, int amount));
+EXPORT	int	readblock	__PR((char *buf, int amount));
+LOCAL	int	readtblock	__PR((char *buf, int amount));
+LOCAL	void	readbuf		__PR((void));
+EXPORT	int	readtape	__PR((char *buf, int amount));
+EXPORT	void	filltcb		__PR((TCB *ptb));
+EXPORT	void	movetcb		__PR((TCB *from_ptb, TCB *to_ptb));
+EXPORT	void	*get_block	__PR((int amount));
+EXPORT	void	put_block	__PR((int amount));
+EXPORT	char	*writeblock	__PR((char *buf));
+EXPORT	int	writetape	__PR((char *buf, int amount));
+LOCAL	void	writebuf	__PR((int amount));
+LOCAL	void	flushbuf	__PR((void));
+EXPORT	void	writeempty	__PR((void));
+EXPORT	void	weof		__PR((void));
+EXPORT	void	buf_sync	__PR((int size));
+EXPORT	void	buf_drain	__PR((void));
+EXPORT	int	buf_wait	__PR((int amount));
+EXPORT	void	buf_wake	__PR((int amount));
+EXPORT	int	buf_rwait	__PR((int amount));
+EXPORT	void	buf_rwake	__PR((int amount));
+EXPORT	void	buf_resume	__PR((void));
+EXPORT	void	backtape	__PR((void));
+EXPORT	int	mtioctl		__PR((int cmd, int count));
+EXPORT	off_t	mtseek		__PR((off_t offset, int whence));
+EXPORT	void	marktcb		__PR((char *addr));
+EXPORT	Llong	tblocks		__PR((void));
+EXPORT	void	prstats		__PR((void));
+EXPORT	BOOL	checkerrs	__PR((void));
+EXPORT	void	exprstats	__PR((int ret));
+EXPORT	void	excomerrno	__PR((int err, char *fmt, ...)) __printflike__(2, 3);
+EXPORT	void	excomerr	__PR((char *fmt, ...)) __printflike__(1, 2);
+EXPORT	void	die		__PR((int err));
+LOCAL	void	compressopen	__PR((void));
+LOCAL	void	compressclose	__PR((void));
+
+EXPORT void
+opt_remote()
+{
+#ifdef	USE_REMOTE
+	printf(" remote");
+#endif
+}
+
+/*
+ * Check whether the current tarfiles[tarfindex] refers to a remote archive
+ * location and open a remote connection if needed.
+ * Called from star.c main() and from changetape().
+ */
+EXPORT BOOL
+openremote()
+{
+	char	host[128];
+	char	lasthost[128];
+
+	if ((!nullout || (uflag || rflag)) && !force_noremote &&
+			(remfn = rmtfilename(tarfiles[tarfindex])) != NULL) {
+
+#ifdef	USE_REMOTE
+		isremote = TRUE;
+		rmtdebug(debug);
+		rmthostname(host, sizeof (host), tarfiles[tarfindex]);
+		if (debug)
+			errmsgno(EX_BAD, "Remote: %s Host: %s file: %s\n",
+					tarfiles[tarfindex], host, remfn);
+
+		if (lastremote >= 0) {
+			rmthostname(lasthost, sizeof (lasthost),
+							tarfiles[lastremote]);
+			if (!streql(host, lasthost)) {
+				close(remfd);
+				remfd = -1;
+				lastremote = -1;
+			}
+		}
+		if (remfd < 0 && (remfd = rmtgetconn(host, bigsize, 0)) < 0)
+			comerrno(EX_BAD, "Cannot get connection to '%s'.\n",
+				/* errno not valid !! */		host);
+		lastremote = tarfindex;
+#else
+		comerrno(EX_BAD, "Remote tape support not present.\n");
+#endif
+	} else {
+		isremote = FALSE;
+	}
+	return (isremote);
+}
+
+/*
+ * Open the current tarfiles[tarfindex] (a remote connection must be open)
+ * Called from star.c main() and from changetape().
+ */
+EXPORT void
+opentape()
+{
+	int	n = 0;
+	extern	dev_t	tape_dev;
+	extern	ino_t	tape_ino;
+	extern	BOOL	tape_isreg;
+
+	if (copyflag || (nullout && !(uflag || rflag))) {
+		tarfiles[tarfindex] = "null";
+		tarf = (FILE *)NULL;
+	} else if (streql(tarfiles[tarfindex], "-")) {
+		if (cflag) {
+/*			tarfiles[tarfindex] = "stdout";*/
+			tarf = stdout;
+		} else {
+/*			tarfiles[tarfindex] = "stdin";*/
+			tarf = stdin;
+			multblk = TRUE;
+		}
+		setbuf(tarf, (char *)NULL);
+#ifdef	NEED_O_BINARY
+		setmode(fileno(tarf), O_BINARY);
+#endif
+	} else if (isremote) {
+#ifdef	USE_REMOTE
+		/*
+		 * isremote will always be FALSE if USE_REMOTE is not defined.
+		 * NOTE any open flag bejond O_RDWR is not portable across
+		 * different platforms. The remote tape library will check
+		 * whether the current /etc/rmt server supports symbolic
+		 * open flags. If there is no symbolic support in the
+		 * remote server, our rmt client code will mask off all
+		 * non portable bits. The remote rmt server defaults to
+		 * O_BINARY as the client (we) may not know about O_BINARY.
+		 * XXX Should we add an option that allows to specify O_TRUNC?
+		 */
+		while (rmtopen(remfd, remfn, (cflag ? O_RDWR|O_CREAT:O_RDONLY)|O_BINARY) < 0) {
+			if (!wready || n++ > 12 ||
+			    (geterrno() != EIO && geterrno() != EBUSY)) {
+				comerr("Cannot open remote '%s'.\n",
+						tarfiles[tarfindex]);
+			} else {
+				sleep(10);
+			}
+		}
+#endif
+	} else {
+		FINFO	finfo;
+	extern	BOOL	follow;
+	extern	BOOL	fcompat;
+	extern	int	ptype;
+
+		if (fcompat && (cflag && !(uflag || rflag))) {
+			/*
+			 * The old syntax has a high risk of corrupting
+			 * files if the user disorders the args.
+			 * For this reason, we do not allow to overwrite
+			 * a plain file in compat mode.
+			 * XXX What if we implement 'r' & 'u' ???
+			 */
+			follow++;
+			n = _getinfo(tarfiles[tarfindex], &finfo);
+			follow--;
+			if (n >= 0 && is_file(&finfo) && finfo.f_size > (off_t)0) {
+				if (ptype != P_SUNTAR) {
+					comerrno(EX_BAD,
+					"Will not overwrite non empty plain files in compat mode.\n");
+				} else {
+					errmsgno(EX_BAD,
+					"WARNING: Overwriting archive file '%s'.\n",
+					tarfiles[tarfindex]);
+				}
+			}
+		}
+
+		n = 0;
+		/*
+		 * XXX Should we add an option that allows to specify O_TRUNC?
+		 */
+		while ((tarf = fileopen(tarfiles[tarfindex],
+						cflag?"rwcub":"rub")) ==
+								(FILE *)NULL) {
+			if (!wready || n++ > 12 ||
+			    (geterrno() != EIO && geterrno() != EBUSY)) {
+				comerr("Cannot open '%s'.\n",
+						tarfiles[tarfindex]);
+			} else {
+				sleep(10);
+			}
+		}
+	}
+	if (!isremote && (!nullout || (uflag || rflag)) &&
+	    tarf != (FILE *)NULL) {
+		file_raise(tarf, FALSE);
+		checkarch(tarf);
+	}
+	vpr = tarf == stdout ? stderr : stdout;
+	if (samefile(tarf, vpr))		/* Catch -f /dev/stdout case */
+		vpr = stderr;
+
+	/*
+	 * If the archive is a plain file and thus seekable
+	 * do automatic compression detection.
+	 */
+	if (stats->volno == 1 &&
+	    tape_isreg && !cflag && (!Zflag && !zflag && !bzflag && !lzoflag && !p7zflag && !compress_prg)) {
+		long	htype;
+		TCB	*ptb;
+
+		readtblock(bigbuf, TBLOCK);
+		ptb = (TCB *)bigbuf;
+		htype = get_hdrtype(ptb, FALSE);
+
+		if (htype == H_UNDEF) {
+			switch (cmptype = get_compression(ptb)) {
+
+			case C_NONE:
+				break;
+			case C_PACK:
+			case C_GZIP:
+			case C_LZW:
+			case C_FREEZE:
+			case C_LZH:
+			case C_PKZIP:
+				if (!silent && !print_artype) errmsgno(EX_BAD,
+					"WARNING: Archive is '%s' compressed, trying to use the -z option.\n",
+						get_cmpname(cmptype));
+				zflag = TRUE;
+				break;
+			case C_BZIP2:
+				if (!silent && !print_artype) errmsgno(EX_BAD,
+					"WARNING: Archive is 'bzip2' compressed, trying to use the -bz option.\n");
+				bzflag = TRUE;
+				break;
+			case C_LZO:
+				if (!silent) errmsgno(EX_BAD,
+					"WARNING: Archive is 'lzop' compressed, trying to use the -lzo option.\n");
+				lzoflag = TRUE;
+				break;
+			case C_7Z:
+				if (!silent) errmsgno(EX_BAD,
+					"WARNING: Archive is '7z' compressed, trying to use the -7z option.\n");
+				p7zflag = TRUE;
+				break;
+			default:
+				if (!silent) errmsgno(EX_BAD,
+					"WARNING: Unknown compression type %d.\n", cmptype);
+				break;
+			}
+		}
+		mtseek((off_t)0, SEEK_SET);
+	}
+	if (Zflag || zflag || bzflag || lzoflag || p7zflag || compress_prg) {
+		if (isremote)
+			comerrno(EX_BAD, "Cannot compress remote archives (yet).\n");
+		/*
+		 * If both values are zero, this is a device and thus may be a tape.
+		 */
+		if (tape_dev || tape_ino)
+			compressopen();
+		else
+			comerrno(EX_BAD, "Can only compress files.\n");
+	}
+
+#ifdef	timerclear
+	if (showtime && starttime.tv_sec == 0 && starttime.tv_usec == 0 &&
+	    gettimeofday(&starttime, (struct timezone *)0) < 0)
+		comerr("Cannot get starttime\n");
+#endif
+}
+
+/*
+ * Close the current open tarf/remfd (a remote connection must be open)
+ * Called from star.c main() and from changetape().
+ */
+EXPORT void
+closetape()
+{
+	if (isremote) {
+#ifdef	USE_REMOTE
+		/*
+		 * isremote will always be FALSE if USE_REMOTE is not defined.
+		 */
+		if (rmtclose(remfd) < 0)
+			errmsg("Remote close failed.\n");
+#endif
+	} else {
+		compressclose();
+		if (tarf)
+			fclose(tarf);
+	}
+}
+
+/*
+ * Low level medium change routine.
+ * Called from nextitape()/nextotape() and fifo_owait().
+ */
+EXPORT void
+changetape(donext)
+	BOOL	donext;
+{
+	char	ans[2];
+	int	nextindex;
+
+	if (donext) {
+		pid_t	opid = pid;
+
+		if (pid == 0)
+			pid = 1; /* Make sure the statistics are printed */
+		prstats();
+		pid = opid;
+		if (!cflag &&
+		    (gip->tapesize > 0) &&
+		    (stats->blocks*stats->nblocks + stats->parts/TBLOCK) !=
+							    gip->tapesize) {
+			errmsgno(EX_BAD,
+			"WARNING: Archive size error.\n");
+			errmsgno(EX_BAD,
+			"Expected size %llu blocks, actual size %lld blocks.\n",
+			gip->tapesize,
+			stats->blocks*stats->nblocks + stats->parts/TBLOCK);
+		}
+		stats->Tblocks += stats->blocks;
+		stats->Tparts += stats->parts;
+	}
+	stats->blocks = 0L;
+	stats->parts = 0L;
+	closetape();
+	/*
+	 * XXX Was passiert, wenn wir das 2. Mal bei einem Band vorbeikommen?
+	 * XXX Zur Zeit wird gnadenlos ueberschrieben.
+	 */
+	if (donext) {
+		stats->volno++;
+		gip->volno = stats->volno;
+		nextindex = tarfindex + 1;
+		if (nextindex >= ntarfiles)
+			nextindex = 0;
+	} else {
+		nextindex = tarfindex;
+	}
+	/*
+	 * XXX We need to add something like the -l & -o option from
+	 * XXX ufsdump.
+	 */
+	if (newvol_script) {
+		char	scrbuf[PATH_MAX];
+
+		fflush(vpr);
+		if (!donext) {
+			errmsgno(EX_BAD,
+			"Mounted volume on '%s' did not match archive",
+				tarfiles[nextindex]);
+			comerrno(EX_BAD, "Aborting.\n");
+		}
+		/*
+		 * The script is called with the next volume # and volume name
+		 * as argument.
+		 */
+		js_snprintf(scrbuf, sizeof (scrbuf), "%s '%d' '%s'",
+				newvol_script,
+				stats->volno, tarfiles[nextindex]);
+		system(scrbuf);
+	} else {
+		errmsgno(EX_BAD, "Mount volume #%d on '%s' and hit <RETURN>",
+			stats->volno, tarfiles[nextindex]);
+		fgetline(tty, ans, sizeof (ans));
+		if (feof(tty))
+			exit(1);
+	}
+	tarfindex = nextindex;
+	openremote();
+	opentape();
+}
+
+/*
+ * High level input medium change routine.
+ * Currently called from buf_rwait().
+ * Volume verification in the fifo case is done in the fifo process.
+ * For this reason, we only verify the new volume in the non fifo case.
+ */
+EXPORT void
+nextitape()
+{
+#ifdef	FIFO
+	if (use_fifo) {
+		fifo_chitape();
+	} else
+#endif
+	{
+		int	skip;
+
+		changetape(TRUE);
+		readbuf();
+		while (bigcnt > 0 && !verifyvol(bigptr, bigcnt, stats->volno, &skip)) {
+			changetape(FALSE);
+			readbuf();
+		}
+		if (skip > 0)
+			buf_rwake(skip*TBLOCK);
+	}
+	if (intr)
+		exit(2);
+}
+
+/*
+ * High level output medium change routine.
+ * Currently called from write_tcb() and only used if
+ * -multivol has not been specified. So this is always called
+ * from the tar process and never from the fifo background process.
+ */
+EXPORT void
+nextotape()
+{
+	weof();
+#ifdef	FIFO
+	if (use_fifo) {
+		fifo_chotape();
+	} else
+#endif
+	changetape(TRUE);
+	if (intr)
+		exit(2);
+}
+
+/*
+ * Called from writetape()
+ */
+EXPORT int
+startvol(buf, amount)
+	char	*buf;		/* The original buffer address		*/
+	int	amount;		/* The related requested transfer count	*/
+{
+	char	*obuf = bigbuf;
+	char	*optr = bigptr;
+	long	ocnt = bigcnt;
+	long	xcnt = 0;
+	BOOL	ofifo = use_fifo;
+static	BOOL	active = FALSE;	/* If TRUE: We are already in a media change */
+
+	if (amount <= 0)
+		return (amount);
+	if (active)
+		comerrno(EX_BAD, "Panic: recursive media change requested!\n");
+	if (amount > bigsize) {
+		comerrno(EX_BAD,
+		"Panic: trying to write more than bs (%d > %d)!\n",
+		amount, bigsize);
+	}
+	active = TRUE;
+
+	/*
+	 * Save the current write data in "bigbase".
+	 */
+	movebytes(buf, bigbase, amount);
+
+	use_fifo = FALSE;
+	bigbuf = &bigbase[bigsize];
+	bigptr = bigbuf;
+	bigcnt = 0;
+
+	newvolhdr(buf, amount, ofifo);
+
+	if (bigcnt > 0) {	/* We did create a volhdr */
+		xcnt = bigsize - bigcnt;
+		if (amount < xcnt)
+			xcnt = amount;
+		if (xcnt > 0) {
+			/*
+			 * Move data from original buffer past the volhdr to
+			 * fill up a complete block size.
+			 */
+			movebytes(bigbase, bigptr, xcnt);
+			bigcnt += xcnt;
+		}
+		writetape(bigbuf, bigcnt);
+	}
+
+	movebytes(bigbase, buf, amount);
+	bigbuf = obuf;
+	bigptr = optr;
+	bigcnt = ocnt;
+	use_fifo = ofifo;
+	active = FALSE;
+	return (xcnt);		/* Return the amount taken from orig. buffer */
+}
+
+EXPORT void
+newvolhdr(buf, amount, do_fifo)
+	char	*buf;		/* The original buffer address		*/
+	int	amount;		/* The related requested transfer count	*/
+	BOOL	do_fifo;
+{
+extern	m_head	*mp;
+	off_t	scur_size;
+	off_t	scur_off;
+	off_t	sold_size;
+	off_t	sold_off;
+#ifdef	FIFO
+	off_t	new_size = 0;
+	BOOL	nsize_valid = FALSE;
+#endif
+
+	fifo_lock_critical();
+	scur_size = stats->cur_size;
+	scur_off  = stats->cur_off;
+	sold_size = stats->old_size;
+	sold_off  = stats->old_off;
+#ifdef	FIFO
+	/*
+	 * If needed, find next header position in FIFO bitmap.
+	 */
+	if (do_fifo && buf != NULL)	/* buf == NULL -> called from put_tcb */
+		nsize_valid = fifo_hpos(buf, &new_size);
+#endif
+	fifo_unlock_critical();
+
+	xbbackup();		/* Save current xheader data */
+
+	gip->blockoff = stats->Tblocks * stats->nblocks +
+			stats->Tparts / TBLOCK;
+
+	put_release();		/* Pax 'g' vendor unique */
+	put_archtype();		/* Pax 'g' vendor unique */
+
+#ifdef	FIFO
+	if (do_fifo && buf != NULL) {	/* buf == NULL -> called from put_tcb */
+		off_t	new_off = 0;
+
+		if (!nsize_valid) {
+			new_size = scur_size;
+			new_off  = scur_off - FIFO_AMOUNT(mp);
+		}
+		/*
+		 * Write a 'g'-header and either a 'V'-header
+		 * or a 'M'-header.
+		 */
+		put_volhdr(gip->label, new_size <= 0);
+		if (new_size > 0)
+			put_multhdr(new_size, new_off);
+	} else
+#endif
+	/*
+	 * Write a 'g'-header and either a 'V'-header
+	 * or a 'M'-header.
+	 */
+	if (!do_fifo && (sold_off < sold_size)) {
+		put_volhdr(gip->label, FALSE);
+		put_multhdr(sold_size, sold_off);
+	} else {
+		put_volhdr(gip->label, TRUE);
+	}
+
+	xbrestore();		/* Restore current xheader data */
+	stats->cur_size = scur_size;
+	stats->cur_off  = scur_off;
+	stats->old_size = sold_size;
+	stats->old_off  = sold_off;
+}
+
+#ifdef	FIFO
+/*
+ * Make the macro a function...
+ */
+LOCAL void
+fbit_ffss(name, startb, stopb, value)
+	register bitstr_t *name;
+	register int	startb;
+	register int	stopb;
+	register int	*value;
+{
+	bit_ffss(name, startb, stopb, value);
+}
+
+/*
+ * Find next header position in FIFO bitmap.
+ */
+LOCAL BOOL
+fifo_hpos(buf, posp)
+	char	*buf;
+	off_t	*posp;
+{
+		int	startb;
+		int	stopb;
+		int	endb;
+		int	bitpos = -1;
+	extern	m_head	*mp;
+
+	startb = (buf - mp->base) / TBLOCK;
+	stopb  = -1 + (mp->putptr - mp->base) / TBLOCK;
+	endb   = -1 + (mp->size) / TBLOCK;
+
+	if (buf < mp->base) {
+		stopb = mp->bmlast;
+		startb = stopb + 1 - (mp->base - buf) / TBLOCK;
+
+		fbit_ffss(mp->bmap, startb, stopb, &bitpos);
+		if (bitpos >= 0) {
+			*posp = (bitpos - startb) * TBLOCK;
+			return (TRUE);
+		}
+		startb = 0;
+		stopb = -1 + (mp->putptr - mp->base) / TBLOCK;
+	}
+	if (stopb < startb)
+		fbit_ffss(mp->bmap, startb, endb, &bitpos);
+	else
+		fbit_ffss(mp->bmap, startb, stopb, &bitpos);
+	if (bitpos >= 0) {
+		*posp = (bitpos - startb) * TBLOCK;
+		return (TRUE);
+	}
+	if (stopb < startb) {
+		fbit_ffss(mp->bmap, 0, stopb, &bitpos);
+		if (bitpos >= 0) {
+			/*
+			 * endb+1 - startb == # of bits in rear part
+			 */
+			*posp = (bitpos + endb+1 - startb) * TBLOCK;
+			return (TRUE);
+		}
+	}
+	return (FALSE);
+}
+#endif
+
+/*
+ * Init buffer or fifo.
+ * called from star.c main().
+ */
+EXPORT void
+initbuf(nblocks)
+	int	nblocks;
+{
+	BOOL	cvolhdr = cflag && (multivol || tsize > 0);
+
+	pid = getpid();
+	bufsize = bigsize = nblocks * TBLOCK;
+#ifdef	FIFO
+	if (use_fifo) {
+		initfifo();
+	}
+#endif
+	if (!use_fifo || cvolhdr) {
+		int	pagesize = getpagesize();
+
+		/*
+		 * llitos() overshoots by one space (' ') in cpio mode,
+		 * add 10 bytes.
+		 * If we create multi volume archives that need volume
+		 * headers, we need additional space to prepare the
+		 * first write to a new medium after a medium change.
+		 */
+		if (cvolhdr)
+			bufsize *= 2;
+
+#undef	roundup
+#define	roundup(x, y)	((((x)+((y)-1))/(y))*(y))
+
+		bigptr = bigbuf = __malloc((size_t) bufsize+10+pagesize,
+								"buffer");
+		bigptr = bigbuf = (char *)roundup((Intptr_t)bigptr, pagesize);
+		fillbytes(bigbuf, bufsize, '\0');
+		fillbytes(&bigbuf[bufsize], 10, 'U');
+
+		if (cvolhdr) {
+			bufsize /= 2;
+			bigbase = bigbuf;
+			bigbuf = bigptr = &bigbase[bufsize];
+		}
+	}
+	stats->nblocks = nblocks;
+	stats->blocksize = bigsize;
+	stats->volno = 1;
+	stats->swapflg = -1;
+}
+
+/*
+ * Mark the EOF position (the position of the first logical TAR EOF block)
+ * We need this position for later repositioning when appending to an archive.
+ */
+EXPORT void
+markeof()
+{
+#ifdef	FIFO
+	if (use_fifo) {
+		/*
+		 * Remember current FIFO status.
+		 */
+		/* EMPTY */
+	}
+#endif
+	eofptr = bigptr - TBLOCK;
+
+	if (debug) {
+		error("Blocks: %lld\n", tblocks());
+		error("bigptr - bigbuff: %lld %p %p %p lastsize: %ld\n",
+			(Llong)(bigptr - bigbuf),
+			(void *)bigbuf, (void *)bigptr, (void *)eofptr,
+			stats->lastsize);
+	}
+}
+
+EXPORT void
+marktcb(addr)
+	char	*addr;
+{
+#ifdef	FIFO
+	extern	m_head  *mp;
+	register int	bit;
+#endif
+	if (!multivol || !use_fifo)
+		return;
+	/*
+	 * As long as we don't start supporting -multivol with CPIO archives,
+	 * we will never come here when writing unblocked archives.
+	 */
+#ifdef	FIFO
+	bit = addr - mp->base;
+	if (bit % TBLOCK)		/* Remove this paranoia test in future. */
+		error("TCB offset not mudulo 512.\n");
+	bit /= TBLOCK;
+	if (bit_test(mp->bmap, bit))	/* Remove this paranoia test in future. */
+		error("Bit %d is already set.\n", bit);
+	bit_set(mp->bmap, bit);
+#endif
+}
+
+/*
+ * Prepare the buffer/fifo for reversing the direction from reading to writing.
+ * Called from star.c main() after skipall() is ready.
+ */
+EXPORT void
+syncbuf()
+{
+#ifdef	FIFO
+	if (use_fifo) {
+		/*
+		 * Switch FIFO direction.
+		 */
+		excomerr("Cannot update tape with FIFO.\n");
+	}
+#endif
+	if (eofptr) {
+		/*
+		 * Only back up to "eofptr" if markeof() has been called,
+		 * this is not the case when we did ancounter a hard EOF
+		 * at the beginning of the archive (empty file),
+		 */
+		bigptr = eofptr;
+		bigcnt = eofptr - bigbuf;
+	}
+}
+
+/*
+ * Peek into buffer for amount bytes.
+ * Return at most TBLOCK (512) bytes.
+ *
+ * Called from get_tcb() for checking the archive format of the first
+ * tape block.
+ */
+EXPORT int
+peekblock(buf, amount)
+	register char	*buf;
+	register int	amount;
+{
+	register int	n;
+
+	if ((n = buf_rwait(amount)) == 0)
+		return (EOF);
+	if (n > amount)
+		n = amount;
+	if (n >= TBLOCK) {
+		n = TBLOCK;
+		movetcb((TCB *)bigptr, (TCB *)buf);
+	} else {
+		movebytes(bigptr, buf, n);
+	}
+	return (n);
+}
+
+/*
+ * Read amount bytes.
+ * Return at most TBLOCK (512) bytes.
+ * Do CPIO buffer wrap handling here.
+ *
+ * Called from get_tcb() and from the sparse handling functions in hole.c
+ */
+EXPORT int
+readblock(buf, amount)
+	register char	*buf;
+	register int	amount;
+{
+	register int	n;
+
+	if ((n = peekblock(buf, amount)) != EOF) {
+		buf_rwake(n);
+		if (n < amount) {
+			if ((amount = readblock(&buf[n], amount-n)) == EOF)
+				return (n);
+			return (n + amount);
+		}
+	}
+	return (n);
+}
+
+/*
+ * Low level routine to read a TAPE Block (usually 10k)
+ * Called from opentape() to check the compression and from readtape().
+ */
+LOCAL int
+readtblock(buf, amount)
+	char	*buf;
+	int	amount;
+{
+	int	cnt;
+
+	stats->reading = TRUE;
+	if (isremote) {
+#ifdef	USE_REMOTE
+		/*
+		 * isremote will always be FALSE if USE_REMOTE is not defined.
+		 */
+		if ((cnt = rmtread(remfd, buf, amount)) < 0)
+			excomerr("Error reading '%s'.\n", tarfiles[tarfindex]);
+#endif
+	} else {
+		if ((cnt = _niread(fileno(tarf), buf, amount)) < 0)
+			excomerr("Error reading '%s'.\n", tarfiles[tarfindex]);
+	}
+	return (cnt);
+}
+
+/*
+ * Refill the buffer if no fifo.
+ * Called from buf_rwait()
+ */
+LOCAL void
+readbuf()
+{
+	bigcnt = readtape(bigbuf, bigsize);
+	bigptr = bigbuf;
+}
+
+/*
+ * Mid level function to read a tape block (usually 10k)
+ * Called from the fifo fill code and from readbuf().
+ */
+EXPORT int
+readtape(buf, amount)
+	char	*buf;
+	int	amount;
+{
+	int	amt;
+	int	cnt;
+	char	*bp;
+	int	size;
+static	BOOL	teof = FALSE;
+
+	if (teof)
+		return (0);
+
+	amt = 0;
+	bp = buf;
+	size = amount;
+
+	do {
+		cnt = readtblock(bp, size);
+
+		amt += cnt;
+		bp += cnt;
+		size -= cnt;
+	} while (amt < amount && cnt > 0 && multblk);
+
+	if (amt == 0)
+		return (amt);
+	if (amt < TBLOCK) {
+		errmsgno(EX_BAD, "Error reading '%s' size (%d) too small.\n",
+						tarfiles[tarfindex], amt);
+		/*
+		 * Do not continue after we did read less than 512 bytes.
+		 */
+		teof = TRUE;
+	}
+	/*
+	 * First block
+	 */
+	if (stats->swapflg < 0) {
+		if ((amt % TBLOCK) != 0)
+			comerrno(EX_BAD, "Invalid blocksize %d bytes.\n", amt);
+		if (amt < amount) {
+			stats->blocksize = bigsize = amt;
+			stats->nblocks = bigsize/TBLOCK;
+#ifdef	FIFO
+			if (use_fifo)
+				fifo_ibs_shrink(amt);
+#endif
+			errmsgno(EX_BAD, "Blocksize = %ld records.\n",
+						stats->blocksize/TBLOCK);
+		}
+	}
+	if (stats->swapflg > 0)
+		swabbytes(buf, amt);
+
+	if (amt == stats->blocksize)
+		stats->blocks++;
+	else
+		stats->parts += amt;
+	stats->lastsize = amt;
+#ifdef	DEBUG
+	error("readbuf: cnt: %d.\n", amt);
+#endif
+	return (amt);
+}
+
+#define	DO8(a)	a; a; a; a; a; a; a; a;
+
+/*#define	MY_SWABBYTES*/
+#ifdef	MY_SWABBYTES
+
+void
+swabbytes(bp, cnt)
+	register char	*bp;
+	register int	cnt;
+{
+	register char	c;
+
+	cnt /= 2;	/* even count only */
+	while ((cnt -= 8) >= 0) {
+		DO8(c = *bp++; bp[-1] = *bp; *bp++ = c);
+	}
+	cnt += 8;
+
+	while (--cnt >= 0) {
+		c = *bp++; bp[-1] = *bp; *bp++ = c;
+	}
+}
+#endif
+
+#define	DO16(a)		DO8(a) DO8(a)
+
+EXPORT void
+filltcb(ptb)
+	register TCB	*ptb;
+{
+	register int	i;
+	register long	*lp = ptb->ldummy;
+
+	for (i = 512/sizeof (long)/16; --i >= 0; ) {
+		DO16(*lp++ = 0L)
+	}
+}
+
+EXPORT void
+movetcb(from_ptb, to_ptb)
+	register TCB	*from_ptb;
+	register TCB	*to_ptb;
+{
+	register int	i;
+	register long	*from = from_ptb->ldummy;
+	register long	*to   = to_ptb->ldummy;
+
+	for (i = 512/sizeof (long)/16; --i >= 0; ) {
+		DO16(*to++ = *from++)
+	}
+}
+
+/*
+ * Try to allocate 'amount' bytes from the buffer or from the fifo.
+ * If it is not possible to get 'amount' bytes in a single chunk, return NULL.
+ */
+EXPORT void *
+get_block(amount)
+	int	amount;
+{
+	if (buf_wait(amount) < amount)
+		return ((void *)NULL);
+	return ((void *)bigptr);
+}
+
+/*
+ * Tell the buffer or the fifo that 'amount' bytes in the buffer/fifo space
+ * are ready to be written.
+ */
+EXPORT void
+put_block(amount)
+	int	amount;
+{
+	buf_wake(amount);
+}
+
+/*
+ * Write TBLOCK bytes into the buffer/fifo space and tell the buffer/fifo
+ * that TBLOCK bytes are ready to be written.
+ */
+EXPORT char *
+writeblock(buf)
+	char	*buf;
+{
+	char	*obp;
+
+	buf_wait(TBLOCK);
+	obp = bigptr;
+	movetcb((TCB *)buf, (TCB *)bigptr);
+	buf_wake(TBLOCK);
+
+	return (obp);
+}
+
+/*
+ * Mid level function to write a tape block (usually 10k)
+ * Called from the fifo fill output code and from writebuf().
+ */
+EXPORT int
+writetape(buf, amount)
+	char	*buf;
+	int	amount;
+{
+	int	cnt;
+	int	err = 0;
+					/* hartes oder weiches EOF ???  */
+					/* d.h. < 0 oder <= 0		*/
+	stats->reading = FALSE;
+	if (multivol && tsize) {
+		Ullong	cursize;
+
+		cursize = stats->blocks * stats->nblocks + stats->parts / TBLOCK;
+
+		if (cursize >= tsize) {	/* tsize= induced change */
+			changetape(TRUE);
+			cnt = startvol(buf, amount);
+			if (cnt > 0)
+				return (cnt);
+		}
+	}
+	seterrno(0);
+	if (nullout) {
+		cnt = amount;
+#ifdef	USE_REMOTE
+	} else if (isremote) {
+		cnt = rmtwrite(remfd, buf, amount);	   /* Handles EINTR */
+#endif
+	} else {
+		cnt = _niwrite(fileno(tarf), buf, amount); /* Handles EINTR */
+	}
+	if (cnt == 0) {
+		err = EFBIG;
+	} else if (cnt < 0) {
+		err = geterrno();
+	}
+
+	if (multivol && (err == EFBIG || err == ENOSPC)) {
+		/*
+		 * QIC tapes (unblocked) may do partial writes at EOT.
+		 * We do the tape change not at the point when we write less
+		 * than a tape block (this may happen on pipes too) but after
+		 * we got a true EOF condition.
+		 */
+		return (-2);
+	}
+
+	if (cnt == stats->blocksize)
+		stats->blocks++;
+	else if (cnt >= 0)
+		stats->parts += cnt;
+
+	if (cnt <= 0)
+		excomerrno(err, "Error writing '%s'.\n", tarfiles[tarfindex]);
+	return (cnt);
+}
+
+/*
+ * Write output the buffer if no fifo.
+ * Called from buf_wait()
+ */
+LOCAL void
+writebuf(amount)
+	int	amount;
+{
+	long	cnt;
+
+
+nextwrite:
+	cnt = writetape(bigbuf, amount);
+
+	if (cnt < amount) {
+		if (cnt == -2) {		/* EOT induced change */
+			changetape(TRUE);
+			if ((cnt = startvol(bigbuf, amount)) <= 0)
+				goto nextwrite;
+		}
+		/*
+		 * QIC tapes (unblocked) may do partial writes at EOT
+		 *
+		 * Even if we hit a "planned" tape change, the fact
+		 * that we need to write a vol header looks from higher
+		 * levels as if there was a partial write.
+		 */
+		bigptr  = &bigbuf[cnt];
+		bigcnt -= cnt;
+		movebytes(bigptr, bigbuf, bigcnt);
+		bigptr  = &bigbuf[bigcnt];
+	} else {
+		bigptr = bigbuf;
+		bigcnt = 0;
+	}
+	stats->old_size = stats->cur_size;
+	stats->old_off  = stats->cur_off;
+}
+
+/*
+ * Called only from weof()
+ */
+LOCAL void
+flushbuf()
+{
+#ifdef	FIFO
+	if (!use_fifo)
+#endif
+	{
+		/*
+		 * Loop because a tape change and writing a vol header
+		 * may look like an incomplete write and need a second
+		 * write to really flush the buffer.
+		 */
+		while (bigcnt > 0)
+			writebuf(bigcnt);
+	}
+}
+
+/*
+ * Write an empty TBLOCK
+ * Called from weof() and cr_file()
+ */
+EXPORT void
+writeempty()
+{
+	TCB	tb;
+
+	filltcb(&tb);
+	writeblock((char *)&tb);
+}
+
+/*
+ * Write a logical TAR EOF (2 empty TBLOCK sized blocks)
+ * or a CPIO EOF marker.
+ */
+EXPORT void
+weof()
+{
+	if ((props.pr_flags & PR_CPIO) != 0) {
+		cpio_weof();
+		buf_sync(TBLOCK);
+	} else {
+		writeempty();
+		writeempty();
+	}
+	if (!partial)
+		buf_sync(0);
+	flushbuf();
+}
+
+/*
+ * If size == 0, fill the buffer up to a TAPE record (usually 10k),
+ * if size != 0, fill the buffer up to size.
+ */
+EXPORT void
+buf_sync(size)
+	int	size;
+{
+#ifdef	FIFO
+	if (use_fifo) {
+		fifo_sync(size);
+	} else
+#endif
+	if (size) {
+		int	amt = 0;
+
+		if ((bigcnt % size) != 0)
+			amt = size - bigcnt%size;
+
+		fillbytes(bigptr, amt, '\0');
+		bigcnt += amt;
+		bigptr += amt;
+	} else {
+		fillbytes(bigptr, bigsize - bigcnt, '\0');
+		bigcnt = bigsize;
+	}
+}
+
+/*
+ * Drain the fifo if in fifo mode.
+ */
+EXPORT void
+buf_drain()
+{
+#ifdef	FIFO
+	if (use_fifo) {
+		fifo_oflush();
+		wait(0);
+	}
+#endif
+}
+
+/*
+ * Wait until we may put amount bytes into the buffer/fifo.
+ * The returned count may be lower. Callers need to be prepared about this.
+ */
+EXPORT int
+buf_wait(amount)
+	int	amount;
+{
+#ifdef	FIFO
+	if (use_fifo) {
+		return (fifo_iwait(amount));
+	} else
+#endif
+	{
+		if (bigcnt >= bigsize)
+			writebuf(bigsize);
+		return (bigsize - bigcnt);
+	}
+}
+
+/*
+ * Tell the buffer/fifo management that amount bytes are ready to be written.
+ * The space may now be written to the media and the space may be made
+ * avbailable for being filled up again.
+ */
+EXPORT void
+buf_wake(amount)
+	int	amount;
+{
+#ifdef	FIFO
+	if (use_fifo) {
+		fifo_owake(amount);
+	} else
+#endif
+	{
+		bigptr += amount;
+		bigcnt += amount;
+	}
+	if (copyflag) {
+		/*
+		 * In copy mode, there is no blocked read/write from the fifo
+		 * Tape process. For this reason, we increment the byte count
+		 * at this place.
+		 */
+		stats->parts += amount;
+	}
+}
+
+/*
+ * Wait until we may read amount bytes from the buffer/fifo.
+ * The returned count may be lower. Callers need to be prepared about this.
+ */
+EXPORT int
+buf_rwait(amount)
+	int	amount;
+{
+	int	cnt;
+
+again:
+#ifdef	FIFO
+	if (use_fifo) {
+		cnt = fifo_owait(amount);
+	} else
+#endif
+	{
+/*		if (bigcnt < amount)*/ /* neu ?? */
+		if (bigcnt <= 0)
+			readbuf();
+		cnt = bigcnt;
+	}
+	if (cnt == 0 && multivol) {
+		nextitape();
+		goto again;
+	}
+	return (cnt);
+}
+
+/*
+ * Tell the buffer/fifo management that amount bytes are no longer needed for
+ * read access. The space may now be filled up with new data from the medium.
+ */
+EXPORT void
+buf_rwake(amount)
+	int	amount;
+{
+#ifdef	FIFO
+	if (use_fifo) {
+		fifo_iwake(amount);
+	} else
+#endif
+	{
+		bigptr += amount;
+		bigcnt -= amount;
+	}
+}
+
+/*
+ * Resume the fifo if the fifo has been blocked after the first read
+ * TAPE block (usually 10 k).
+ * If the fifo is active, fifo_resume() triggers a shadow call to
+ * setprops() in the fifo background process.
+ */
+EXPORT void
+buf_resume()
+{
+extern	long	hdrtype;
+	stats->swapflg = swapflg;	/* copy over for fifo process */
+	stats->hdrtype = hdrtype;	/* copy over for fifo process */
+	bigsize = stats->blocksize;	/* copy over for tar process */
+#ifdef	FIFO
+	if (use_fifo)
+		fifo_resume();
+#endif
+}
+
+/*
+ * Backspace tape or medium to prepare it for appending to an archive.
+ * Note that this currently only handles TAR archives and that even then it
+ * will not work if the TAPE recordr size is < 2*TBLOCK (1024 bytes).
+ */
+EXPORT void
+backtape()
+{
+	Llong	ret;
+	BOOL	istape = FALSE;
+
+	if (debug) {
+		error("Blocks: %lld\n", tblocks());
+		error("filepos: %lld seeking to: %lld bigsize: %d\n",
+		(Llong)mtseek((off_t)0, SEEK_CUR),
+		(Llong)mtseek((off_t)0, SEEK_CUR) - (Llong)stats->lastsize, bigsize);
+	}
+
+	if (mtioctl(MTNOP, 0) >= 0) {
+		istape = TRUE;
+		if (debug)
+			error("Is a tape: BSR 1...\n");
+		ret = mtioctl(MTBSR, 1);
+	} else {
+		if (debug)
+			error("Is a file: lseek()\n");
+		ret = mtseek(-stats->lastsize, SEEK_CUR);
+	}
+	if (ret == (Llong)-1)
+		excomerr("Cannot backspace %s.\n", istape ? "tape":"medium");
+
+	if (stats->lastsize == stats->blocksize)
+		stats->blocks--;
+	else
+		stats->parts -= stats->lastsize;
+}
+
+/*
+ * Send an MTIOCTOP call to the file descriptor that is use for the medium.
+ */
+EXPORT int
+mtioctl(cmd, count)
+	int	cmd;
+	int	count;
+{
+	int	ret;
+
+	if (nullout && !(uflag || rflag)) {
+		return (0);
+#ifdef	USE_REMOTE
+	} else if (isremote) {
+		ret = rmtioctl(remfd, cmd, count);
+#endif
+	} else {
+#ifdef	MTIOCTOP
+		struct mtop mtop;
+
+		mtop.mt_op = cmd;
+		mtop.mt_count = count;
+
+		ret = ioctl(fdown(tarf), MTIOCTOP, &mtop);
+#else
+		return (-1);
+#endif
+	}
+	if (ret < 0 && debug) {
+		errmsg("Error sending mtioctl(%d, %d) to '%s'.\n",
+					cmd, count, tarfiles[tarfindex]);
+	}
+	return (ret);
+}
+
+/*
+ * Make an lseek() call to the file descriptor that is use for the medium.
+ */
+EXPORT off_t
+mtseek(offset, whence)
+	off_t	offset;
+	int	whence;
+{
+	if (nullout && !(uflag || rflag)) {
+		return (0L);
+#ifdef	USE_REMOTE
+	} else if (isremote) {
+		return (rmtseek(remfd, offset, whence));
+#endif
+	} else {
+		return (lseek(fileno(tarf), offset, whence));
+	}
+}
+
+/*
+ * Return the current archive block number based on 512 byte (TBLOCK) units.
+ */
+EXPORT Llong
+tblocks()
+{
+	long	fifo_cnt = 0;
+	Llong	ret;
+
+#ifdef	FIFO
+	if (use_fifo)
+		fifo_cnt = fifo_amount()/TBLOCK;
+#endif
+	if (stats->reading)
+		ret = (-fifo_cnt + stats->blocks * stats->nblocks +
+				(stats->parts - (bigcnt+TBLOCK))/TBLOCK);
+	else
+		ret = (fifo_cnt + stats->blocks * stats->nblocks +
+				(stats->parts + bigcnt)/TBLOCK);
+	if (debug) {
+		error("tblocks: %lld blocks: %lld blocksize: %ld parts: %lld bigcnt: %ld fifo_cnt: %ld\n",
+		ret, stats->blocks, stats->blocksize, stats->parts, bigcnt, fifo_cnt);
+	}
+	curblockno = ret;
+	return (ret);
+}
+
+EXPORT void
+prstats()
+{
+	Llong	bytes;
+	Llong	kbytes;
+	int	per;
+#ifdef	timerclear
+	int	sec;
+	int	usec;
+	int	tmsec;
+#endif
+	char	*p;
+
+#ifdef	FIFO
+	if (use_fifo) {
+		extern	m_head  *mp;
+		p = mp->end;
+	} else
+#endif
+		p = &bigbuf[bufsize];
+	if ((*p != 'U' && *p != ' ') || p[1] != 'U')
+		errmsgno(EX_BAD, "The buffer has been overwritten, please contact the author.\n");
+
+	if (no_stats)
+		return;
+	if (pid == 0)	/* child */
+		return;
+
+#ifdef	timerclear
+	if (showtime && gettimeofday(&stoptime, (struct timezone *)0) < 0)
+		comerr("Cannot get stoptime\n");
+#endif
+#ifdef	FIFO
+	if (use_fifo && do_fifostats)
+		fifo_stats();
+#endif
+
+	bytes = stats->blocks * (Llong)stats->blocksize + stats->parts;
+	kbytes = bytes >> 10;
+	per = ((bytes&1023)<<10)/10485;
+
+	if (cpio_stats) {
+		bytes = stats->Tblocks * (Llong)stats->blocksize + stats->Tparts;
+
+		error("%lld blocks\n", stats->eofblock + 1 + bytes/512);
+		return;
+	}
+
+	errmsgno(EX_BAD,
+		"%lld blocks + %lld bytes (total of %lld bytes = %lld.%02dk).\n",
+		stats->blocks, stats->parts, bytes, kbytes, per);
+
+	if (stats->Tblocks + stats->Tparts) {
+		bytes = (stats->blocks + stats->Tblocks) *
+						(Llong)stats->blocksize +
+						(stats->parts + stats->Tparts);
+		kbytes = bytes >> 10;
+		per = ((bytes&1023)<<10)/10485;
+
+		errmsgno(EX_BAD,
+		"Total %lld blocks + %lld bytes (total of %lld bytes = %lld.%02dk).\n",
+		stats->blocks + stats->Tblocks,
+		stats->parts + stats->Tparts,
+		bytes, kbytes, per);
+	}
+#ifdef	timerclear
+	if (showtime) {
+		Llong	kbs;
+
+		sec = stoptime.tv_sec - starttime.tv_sec;
+		usec = stoptime.tv_usec - starttime.tv_usec;
+		tmsec = sec*1000 + usec/1000;
+		if (usec < 0) {
+			sec--;
+			usec += 1000000;
+		}
+		if (tmsec == 0)
+			tmsec++;
+
+		kbs = kbytes*(Llong)1000/tmsec;
+
+		errmsgno(EX_BAD, "Total time %d.%03dsec (%lld kBytes/sec)\n",
+				sec, usec/1000, kbs);
+	}
+#endif
+}
+
+EXPORT BOOL
+checkerrs()
+{
+	if (xstats.s_staterrs	||
+#ifdef	USE_ACL
+	    xstats.s_getaclerrs	||
+#endif
+	    xstats.s_openerrs	||
+	    xstats.s_rwerrs	||
+	    xstats.s_misslinks	||
+	    xstats.s_toolong	||
+	    xstats.s_toobig	||
+	    xstats.s_isspecial	||
+	    xstats.s_sizeerrs	||
+
+	    xstats.s_settime	||
+	    xstats.s_security	||
+	    xstats.s_lsecurity	||
+	    xstats.s_samefile	||
+#ifdef	USE_ACL
+	    xstats.s_badacl	||
+	    xstats.s_setacl	||
+#endif
+#ifdef USE_XATTR
+	    xstats.s_getxattr	||
+	    xstats.s_setxattr	||
+#endif
+	    xstats.s_setmodes	||
+	    xstats.s_restore) {
+		if (nowarn || no_stats || (pid == 0) /* child */)
+			return (TRUE);
+
+		errmsgno(EX_BAD, "The following problems occurred during archive processing:\n");
+		errmsgno(EX_BAD, "Cannot: stat %d, open %d, read/write %d. Size changed %d.\n",
+				xstats.s_staterrs,
+				xstats.s_openerrs,
+				xstats.s_rwerrs,
+				xstats.s_sizeerrs);
+		errmsgno(EX_BAD, "Missing links %d, Name too long %d, File too big %d, Not dumped %d.\n",
+				xstats.s_misslinks,
+				xstats.s_toolong,
+				xstats.s_toobig,
+				xstats.s_isspecial);
+		if (xstats.s_settime || xstats.s_setmodes)
+			errmsgno(EX_BAD, "Cannot set: time %d, modes %d.\n",
+				xstats.s_settime,
+				xstats.s_setmodes);
+		if (xstats.s_security || xstats.s_lsecurity)
+			errmsgno(EX_BAD, "Skipped for security reason: path name %d, link name %d.\n",
+				xstats.s_security, xstats.s_lsecurity);
+		if (xstats.s_samefile)
+			errmsgno(EX_BAD, "Skipped same file %d.\n",
+				xstats.s_samefile);
+#ifdef	USE_ACL
+		if (xstats.s_getaclerrs || xstats.s_badacl || xstats.s_setacl)
+			errmsgno(EX_BAD, "Cannot get ACL: %d set ACL: %d. Bad ACL %d.\n",
+				xstats.s_getaclerrs,
+				xstats.s_setacl,
+				xstats.s_badacl);
+#endif
+#ifdef USE_XATTR
+		if (xstats.s_getxattr || xstats.s_setxattr)
+			errmsgno(EX_BAD, "Cannot get xattr: %d set xattr: %d.\n",
+				xstats.s_getxattr,
+				xstats.s_setxattr);
+#endif
+		if (xstats.s_restore)
+			errmsgno(EX_BAD, "Problems with restore database.\n");
+		return (TRUE);
+	}
+	return (FALSE);
+}
+
+EXPORT void
+exprstats(ret)
+	int	ret;
+{
+	prstats();
+	checkerrs();
+	exit(ret);
+}
+
+/* VARARGS2 */
+#ifdef	PROTOTYPES
+EXPORT void
+excomerrno(int err, char *fmt, ...)
+#else
+EXPORT void
+excomerrno(err, fmt, va_alist)
+	int	err;
+	char	*fmt;
+	va_dcl
+#endif
+{
+	va_list	args;
+
+#ifdef	PROTOTYPES
+	va_start(args, fmt);
+#else
+	va_start(args);
+#endif
+	errmsgno(err, "%r", fmt, args);
+	va_end(args);
+#ifdef	FIFO
+	fifo_exit(err);
+#endif
+	exprstats(err);
+	/* NOTREACHED */
+}
+
+/* VARARGS1 */
+#ifdef	PROTOTYPES
+EXPORT void
+excomerr(char *fmt, ...)
+#else
+EXPORT void
+excomerr(fmt, va_alist)
+	char	*fmt;
+	va_dcl
+#endif
+{
+	va_list	args;
+	int	err = geterrno();
+
+#ifdef	PROTOTYPES
+	va_start(args, fmt);
+#else
+	va_start(args);
+#endif
+	errmsgno(err, "%r", fmt, args);
+	va_end(args);
+#ifdef	FIFO
+	fifo_exit(err);
+#endif
+	exprstats(err);
+	/* NOTREACHED */
+}
+
+EXPORT void
+die(err)
+	int	err;
+{
+	excomerrno(err, "Cannot recover from error - exiting.\n");
+}
+
+/*
+ * Quick hack to implement a -z flag. May be changed soon.
+ */
+#include <signal.h>
+#if	defined(SIGDEFER) || defined(SVR4)
+#define	signal	sigset
+#endif
+LOCAL void
+compressopen()
+{
+#ifdef	HAVE_FORK
+	FILE	*pp[2];
+	int	mypid;
+	char	*zip_prog = "gzip";
+
+	if (compress_prg)
+		zip_prog = compress_prg;
+	else if (bzflag)
+		zip_prog = "bzip2";
+	else if (Zflag)
+		zip_prog = "compress";
+	else if (lzoflag)
+		zip_prog = "lzop";
+	else if (p7zflag)
+		zip_prog = "p7zip";
+
+	multblk = TRUE;
+
+	if (cflag && (uflag || rflag))
+		comerrno(EX_BAD, "Cannot update compressed archives.\n");
+
+#ifdef __DJGPP__
+	if (cflag) {
+		/*
+		 * We try to emulate a command line like:
+		 *
+		 *	"star -c dir | %s > dir.tar.%s\n",
+		 *	zip_prog,
+		 *	Zflag?"Z":bzflag?"bz2":compress_prg?compress_prg:"gz");
+		 *
+		 * If we would use popen() instead, DJGPP will run the program
+		 * from popen() first, so there would
+		 * be no data from the "tarf" File pointer.
+		 * We use the temporary file instead.
+		 */
+		if ((compress_tmpf = tmpfile()) == NULL)
+			comerr("Compress pipe failed\n");
+		compress_tarf_save = tarf;
+		tarf = compress_tmpf;
+
+	} else {
+		int	stdin_save;
+		char	zip_cmd[256];
+
+		/*
+		 * We try to emulate a command line like:
+		 *
+		 *	"%s -d < archive.tar.%s | star -x\n",
+		 *	zip_prog,
+		 *	Zflag?"Z":bzflag?"bz2":compress_prg?compress_prg:"gz");
+		 */
+		js_snprintf(zip_cmd, sizeof (zip_cmd), "%s.exe -d", zip_prog);
+
+		stdin_save = dup(STDIN_FILENO);
+		dup2(fileno(tarf), STDIN_FILENO);
+		compress_tarf_save = tarf;
+		if ((tarf = popen(zip_cmd, "rb")) == NULL)
+			comerr("Compress pipe failed\n");
+		dup2(stdin_save, STDIN_FILENO);
+		fclose(compress_tarf_save);
+	}
+#else
+	if (fpipe(pp) == 0)
+		comerr("Compress pipe failed\n");
+	mypid = fork();
+	if (mypid < 0)
+		comerr("Compress fork failed\n");
+	if (mypid == 0) {
+		FILE	*null;
+		char	*flg = getenv("STAR_COMPRESS_FLAG"); /* Temporary ? */
+
+		signal(SIGQUIT, SIG_IGN);
+		if (cflag)
+			fclose(pp[1]);
+		else
+			fclose(pp[0]);
+
+#ifdef	NEED_O_BINARY
+		if (cflag)
+			setmode(fileno(pp[0]), O_BINARY);
+		else
+			setmode(fileno(pp[1]), O_BINARY);
+#endif
+
+		/* We don't want to see errors */
+		null = fileopen("/dev/null", "rw");
+
+		if (cflag)
+			fexecl(zip_prog, pp[0], tarf, null, zip_prog, flg, (char *)NULL);
+		else
+			fexecl(zip_prog, tarf, pp[1], null, zip_prog, "-d", (char *)NULL);
+		errmsg("Compress: exec of '%s' failed\n", zip_prog);
+		_exit(-1);
+	}
+	fclose(tarf);
+	if (cflag) {
+		tarf = pp[1];
+		fclose(pp[0]);
+	} else {
+		tarf = pp[0];
+		fclose(pp[1]);
+	}
+#ifdef	NEED_O_BINARY
+	setmode(fileno(tarf), O_BINARY);
+#endif
+#endif /* !__DJGPP__ */
+#else  /* !HAVE_FORK */
+	comerrno(EX_BAD, "Inline compression not available.\n");
+#endif
+}
+
+LOCAL void
+compressclose()
+{
+#ifdef HAVE_FORK
+	char	*zip_prog = "gzip";
+
+	if (compress_prg)
+		zip_prog = compress_prg;
+	else if (bzflag)
+		zip_prog = "bzip2";
+	else if (Zflag)
+		zip_prog = "compress";
+	else if (lzoflag)
+		zip_prog = "lzop";
+	else if (p7zflag)
+		zip_prog = "p7zip";
+
+#ifdef __DJGPP__
+	if (cflag) {
+		if (compress_tmpf) {
+			char	zip_cmd[256];
+			FILE	*zipf;
+			int	cnt = -1;
+			char	buf[8192];
+
+			js_snprintf(zip_cmd, sizeof (zip_cmd), "%s.exe", zip_prog);
+
+			dup2(fileno(compress_tarf_save), STDOUT_FILENO);
+
+			if ((zipf = popen(zip_cmd, "wb")) == NULL)
+				comerr("Compress pipe failed\n");
+
+			fseek(compress_tmpf, 0l, SEEK_SET);
+
+			while ((cnt = ffileread(compress_tmpf, buf, sizeof (buf))) > 0)
+				ffilewrite(zipf, buf, cnt);
+
+			pclose(zipf);
+			fclose(compress_tmpf);
+			compress_tmpf = (FILE *)NULL;
+		}
+
+	} else {
+		pclose(tarf);
+	}
+#endif
+#endif
+}
diff -Nupr star-1.5.orig/star/longnames.c star-1.5/star/longnames.c
--- star-1.5.orig/star/longnames.c	2006-10-31 18:06:25.000000000 +0100
+++ star-1.5/star/longnames.c	2012-09-25 12:57:13.017762000 +0200
@@ -154,7 +154,7 @@ name_to_tcb(info, ptb)
 		if (add)
 			strcatl(ptb->dbuf.t_name, name, "/", (char *)NULL);
 		else
-			strcpy(ptb->dbuf.t_name, name);
+			strncpy(ptb->dbuf.t_name, name, props.pr_maxsname);
 		return (TRUE);
 	}
 
@@ -197,7 +197,7 @@ name_to_tcb(info, ptb)
 	if (add)
 		strcatl(ptb->dbuf.t_name, &np[1], "/", (char *)NULL);
 	else
-		strcpy(ptb->dbuf.t_name, &np[1]);
+		strncpy(ptb->dbuf.t_name, &np[1], props.pr_maxsname);
 	strncpy(ptb->dbuf.t_prefix, name, np - name);
 	info->f_flags |= F_SPLIT_NAME;
 	return (TRUE);
diff -Nupr star-1.5.orig/star/longnames.c.orig star-1.5/star/longnames.c.orig
--- star-1.5.orig/star/longnames.c.orig	1970-01-01 01:00:00.000000000 +0100
+++ star-1.5/star/longnames.c.orig	2006-10-31 18:06:25.000000000 +0100
@@ -0,0 +1,408 @@
+/* @(#)longnames.c	1.48 06/10/31 Copyright 1993, 1995, 2001-2006 J. Schilling */
+#ifndef lint
+static	char sccsid[] =
+	"@(#)longnames.c	1.48 06/10/31 Copyright 1993, 1995, 2001-2006 J. Schilling";
+#endif
+/*
+ *	Handle filenames that cannot fit into a single
+ *	string of 100 charecters
+ *
+ *	Copyright (c) 1993, 1995, 2001-2006 J. Schilling
+ */
+/*
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License").  You may not use this file except in compliance
+ * with the License.
+ *
+ * See the file CDDL.Schily.txt in this distribution for details.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file CDDL.Schily.txt from this distribution.
+ */
+
+#include <schily/mconfig.h>
+#include "star.h"
+#include "props.h"
+#include "table.h"
+#include <schily/standard.h>
+#include <schily/string.h>
+#include <schily/schily.h>
+#include "starsubs.h"
+#include "movearch.h"
+#include "checkerr.h"
+
+extern	BOOL	no_dirslash;
+
+LOCAL	void	enametoolong	__PR((char *name, int len, int maxlen));
+LOCAL	char	*split_posix_name __PR((char *name, int namlen, int add));
+EXPORT	BOOL	name_to_tcb	__PR((FINFO *info, TCB *ptb));
+EXPORT	void	tcb_to_name	__PR((TCB *ptb, FINFO *info));
+EXPORT	void	tcb_undo_split	__PR((TCB *ptb, FINFO *info));
+EXPORT	int	tcb_to_longname	__PR((TCB *ptb, FINFO *info));
+EXPORT	void	write_longnames	__PR((FINFO *info));
+LOCAL	void	put_longname	__PR((FINFO *info,
+					char *name, int namelen, char *tname,
+							Ulong  xftype));
+
+LOCAL void
+enametoolong(name, len, maxlen)
+	char	*name;
+	int	len;
+	int	maxlen;
+{
+	if (!errhidden(E_NAMETOOLONG, name)) {
+		if (!errwarnonly(E_NAMETOOLONG, name))
+			xstats.s_toolong++;
+		errmsgno(EX_BAD, "%s: Name too long (%d > %d chars)\n",
+							name, len, maxlen);
+		(void) errabort(E_NAMETOOLONG, name, TRUE);
+	}
+}
+
+
+LOCAL char *
+split_posix_name(name, namlen, add)
+	char	*name;
+	int	namlen;
+	int	add;
+{
+	register char	*low;	/* Lower margin to start searching for '/' */
+	register char	*high;	/* Upper margin to start searching for '/' */
+
+	if (namlen+add > props.pr_maxprefix+1+props.pr_maxsname) {
+		/*
+		 * Name too long to be split (does not fit in pfx + '/' + name)
+		 */
+		if ((props.pr_nflags & PR_LONG_NAMES) == 0) /* No longnames */
+			enametoolong(name, namlen+add,
+				props.pr_maxprefix+1+props.pr_maxsname);
+		return (NULL);
+	}
+	/*
+	 * 'low' is set to (namelen - 100) because we cannot split more than
+	 * 100 chars before the end of the name.
+	 * 'high' is set to 155 because we cannot put more than 155 chars into
+	 * the prefix.
+	 * Then start to look backwards from the rightmost position if there is
+	 * slash where we may split.
+	 */
+	low = &name[namlen+add - props.pr_maxsname];
+	if (--low < name)
+		low = name;
+	high = &name[props.pr_maxprefix > namlen ? namlen:props.pr_maxprefix];
+
+#ifdef	DEBUG
+error("low: %d:%s high: %d:'%c',%s\n",
+			strlen(low), low, strlen(high), *high, high);
+#endif
+	high++;
+	while (--high >= low)
+		if (*high == '/')
+			break;
+	if (high < low) {
+		if ((props.pr_nflags & PR_LONG_NAMES) == 0) {
+			if (!errhidden(E_NAMETOOLONG, name)) {
+				if (!errwarnonly(E_NAMETOOLONG, name))
+					xstats.s_toolong++;
+				errmsgno(EX_BAD,
+				"%s: Name too long (cannot split)\n",
+									name);
+				(void) errabort(E_NAMETOOLONG, name, TRUE);
+			}
+		}
+		return (NULL);
+	}
+#ifdef	DEBUG
+error("solved: add: %d prefix: %d suffix: %d\n",
+			add, high-name, strlen(high+1)+add);
+#endif
+	return (high);
+}
+
+/*
+ * Es ist sichergestelt, da� namelen >= 1 ist.
+ */
+EXPORT BOOL
+name_to_tcb(info, ptb)
+	FINFO	*info;
+	TCB	*ptb;
+{
+	char	*name = info->f_name;
+	int	namelen = info->f_namelen;
+	int	add = 0;
+	char	*np = NULL;
+
+	if (namelen == 0)
+		raisecond("name_to_tcb: namelen", 0L);
+
+	/*
+	 * We need a test without 'add' because we currently never add a slash
+	 * at the end of a directiry name when in CPIO mode.
+	 */
+	if (namelen > props.pr_maxnamelen) {
+		enametoolong(name, namelen, props.pr_maxnamelen);
+		return (FALSE);
+	}
+	if ((props.pr_flags & PR_CPIO) != 0)
+		return (TRUE);
+
+	if (is_dir(info) && !no_dirslash && name[namelen-1] != '/')
+		add++;
+
+	if ((namelen+add) <= props.pr_maxsname) {	/* Fits in shortname */
+		if (add)
+			strcatl(ptb->dbuf.t_name, name, "/", (char *)NULL);
+		else
+			strcpy(ptb->dbuf.t_name, name);
+		return (TRUE);
+	}
+
+	if (namelen+add > props.pr_maxnamelen) {	/* Now we know 'add' */
+		enametoolong(name, namelen+add, props.pr_maxnamelen);
+		return (FALSE);
+	}
+	if (props.pr_nflags & PR_POSIX_SPLIT)
+		np = split_posix_name(name, namelen, add);
+	if (np == NULL) {
+		/*
+		 * Cannot split
+		 * (namelen+add <= props.pr_maxnamelen) has been checked before
+		 */
+		if (props.pr_nflags & PR_LONG_NAMES) {
+			if (props.pr_flags & PR_XHDR)
+				info->f_xflags |= XF_PATH;
+			else
+				info->f_flags |= F_LONGNAME;
+			if (add)
+				info->f_flags |= F_ADDSLASH;
+			strncpy(ptb->dbuf.t_name, name, props.pr_maxsname);
+			return (TRUE);
+		} else {
+			/*
+			 * In case of PR_POSIX_SPLIT we did already print the
+			 * error message.
+			 */
+			if ((props.pr_nflags & PR_POSIX_SPLIT) == 0) {
+				enametoolong(name, namelen+add,
+							props.pr_maxnamelen);
+			}
+			return (FALSE);
+		}
+	}
+
+	/*
+	 * Do actual splitting based on split name pointer 'np'.
+	 */
+	if (add)
+		strcatl(ptb->dbuf.t_name, &np[1], "/", (char *)NULL);
+	else
+		strcpy(ptb->dbuf.t_name, &np[1]);
+	strncpy(ptb->dbuf.t_prefix, name, np - name);
+	info->f_flags |= F_SPLIT_NAME;
+	return (TRUE);
+}
+
+/*
+ * This function is only called by tcb_to_info().
+ * If we ever decide to call it from somewhere else check if the linkname
+ * kludge for 100 char linknames does not make problems.
+ */
+EXPORT void
+tcb_to_name(ptb, info)
+	TCB	*ptb;
+	FINFO	*info;
+{
+	/*
+	 * Name has already been set up from somwhere else.
+	 * We have nothing to do.
+	 */
+	if (info->f_flags & F_HAS_NAME)
+		return;
+
+	if ((info->f_flags & F_LONGLINK) == 0 &&	/* name from 'K' head*/
+	    (info->f_xflags & XF_LINKPATH) == 0) {	/* name from 'x' head*/
+
+		/*
+		 * Our caller has set ptb->dbuf.t_linkname[NAMSIZ] to '\0'
+		 * if the link name len is exactly 100 chars.
+		 */
+		strcpy(info->f_lname, ptb->dbuf.t_linkname);
+	}
+
+	/*
+	 * Name has already been set up because it is a very long name.
+	 */
+	if (info->f_flags & F_LONGNAME)
+		return;
+	/*
+	 * Name has already been set up from a POSIX.1-2001 extended header.
+	 */
+	if (info->f_xflags & XF_PATH)
+		return;
+
+	if (props.pr_nflags & PR_POSIX_SPLIT) {
+		strcatl(info->f_name, ptb->dbuf.t_prefix,
+					*ptb->dbuf.t_prefix?"/":"",
+					ptb->dbuf.t_name, (char *)NULL);
+	} else {
+		strcpy(info->f_name, ptb->dbuf.t_name);
+	}
+}
+
+EXPORT void
+tcb_undo_split(ptb, info)
+	TCB	*ptb;
+	FINFO	*info;
+{
+	fillbytes(ptb->dbuf.t_name, NAMSIZ, '\0');
+	fillbytes(ptb->dbuf.t_prefix, props.pr_maxprefix, '\0');
+
+	info->f_flags &= ~F_SPLIT_NAME;
+
+	if (props.pr_flags & PR_XHDR)
+		info->f_xflags |= XF_PATH;
+	else
+		info->f_flags |= F_LONGNAME;
+
+	strncpy(ptb->dbuf.t_name, info->f_name, props.pr_maxsname);
+}
+
+/*
+ * A bad idea to do this here!
+ * We have to set up a more generalized pool of namebuffers wich are allocated
+ * on an actual MAX_PATH base or even better allocated on demand.
+ *
+ * XXX If we change the code to allocate the data, we need to make sure that
+ * XXX the allocated data holds one byte more than needed as movearch.c
+ * XXX adds a second null byte to the buffer to enforce null-termination.
+ */
+#ifdef	__needed__
+char	longlinkname[PATH_MAX+1];
+#endif
+
+EXPORT int
+tcb_to_longname(ptb, info)
+	register TCB	*ptb;
+	register FINFO	*info;
+{
+	move_t	move;
+	Ullong	ull;
+
+	/*
+	 * File size is strlen of name + 1
+	 */
+	stolli(ptb->dbuf.t_size, &ull);
+	info->f_size = ull;
+	info->f_rsize = info->f_size;
+	if (info->f_size > PATH_MAX) {
+		/*
+		 * We do not know the name here,
+		 * we only have the short ptb->dbuf.t_name
+		 */
+/*		if (!errhidden(E_NAMETOOLONG, name)) {*/
+/*			if (!errwarnonly(E_NAMETOOLONG, name))*/
+				xstats.s_toolong++;
+			errmsgno(EX_BAD,
+			"Long name too long (%lld) ignored.\n",
+							(Llong)info->f_size);
+/*			(void) errabort(E_NAMETOOLONG, name, TRUE);*/
+/*		}*/
+		void_file(info);
+		return (get_tcb(ptb));
+	}
+	if (ptb->dbuf.t_linkflag == LF_LONGNAME) {
+		if ((info->f_xflags & XF_PATH) != 0) {
+			/*
+			 * Ignore old star/gnutar extended headers for very
+			 * long filenames if we already found a POSIX.1-2001
+			 * compliant long PATH name.
+			 */
+			void_file(info);
+			return (get_tcb(ptb));
+		}
+		info->f_namelen = info->f_size -1;
+		info->f_flags |= F_LONGNAME;
+		move.m_data = info->f_name;
+	} else {
+		if ((info->f_xflags & XF_LINKPATH) != 0) {
+			/*
+			 * Ignore old star/gnutar extended headers for very
+			 * long linknames if we already found a POSIX.1-2001
+			 * compliant long LINKPATH name.
+			 */
+			void_file(info);
+			return (get_tcb(ptb));
+		}
+		info->f_lnamelen = info->f_size -1;
+		info->f_flags |= F_LONGLINK;
+		move.m_data = info->f_lname;
+	}
+	move.m_flags = 0;
+	if (xt_file(info, vp_move_from_arch, &move, 0, "moving long name") < 0)
+		die(EX_BAD);
+
+	return (get_tcb(ptb));
+}
+
+EXPORT void
+write_longnames(info)
+	register FINFO	*info;
+{
+	/*
+	 * XXX Should test for F_LONGNAME & F_FLONGLINK
+	 */
+	if ((info->f_flags & F_LONGNAME) ||
+	    (info->f_namelen > props.pr_maxsname)) {
+		put_longname(info, info->f_name, info->f_namelen+1,
+						"././@LongName", XT_LONGNAME);
+	}
+	if ((info->f_flags & F_LONGLINK) ||
+	    (info->f_lnamelen > props.pr_maxslname)) {
+		put_longname(info, info->f_lname, info->f_lnamelen+1,
+						"././@LongLink", XT_LONGLINK);
+	}
+}
+
+LOCAL void
+put_longname(info, name, namelen, tname, xftype)
+	FINFO	*info;
+	char	*name;
+	int	namelen;
+	char	*tname;
+	Ulong	xftype;
+{
+	FINFO	finfo;
+	TCB	tb;
+	TCB	*ptb;
+	move_t	move;
+
+	fillbytes((char *)&finfo, sizeof (finfo), '\0');
+
+	if ((ptb = (TCB *)get_block(TBLOCK)) == NULL)
+		ptb = &tb;
+	else
+		finfo.f_flags |= F_TCB_BUF;
+	filltcb(ptb);
+
+	strcpy(ptb->dbuf.t_name, tname);
+
+	move.m_flags = 0;
+	if ((info->f_flags & F_ADDSLASH) != 0 && xftype == XT_LONGNAME) {
+		/*
+		 * A slash is only added to the filename and not to the
+		 * linkname.
+		 */
+		move.m_flags |= MF_ADDSLASH;
+		namelen++;
+	}
+	finfo.f_mode = TUREAD|TUWRITE;
+	finfo.f_rsize = finfo.f_size = namelen;
+	finfo.f_xftype = xftype;
+	info_to_tcb(&finfo, ptb);
+	write_tcb(ptb, &finfo);
+
+	move.m_data = name;
+	move.m_size = finfo.f_size;
+	cr_file(&finfo, vp_move_to_arch, &move, 0, "moving long name");
+}
diff -Nupr star-1.5.orig/star_sym/find.h star-1.5/star_sym/find.h
--- star-1.5.orig/star_sym/find.h	1970-01-01 01:00:00.000000000 +0100
+++ star-1.5/star_sym/find.h	2012-09-25 13:40:23.243184999 +0200
@@ -0,0 +1,109 @@
+/* @(#)find.h	1.19 08/04/06 Copyright 2005-2008 J. Schilling */
+/*
+ *	Definitions for libfind users.
+ *
+ *	Copyright (c) 2004-2008 J. Schilling
+ */
+/*
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License").  You may not use this file except in compliance
+ * with the License.
+ *
+ * See the file CDDL.Schily.txt in this distribution for details.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file CDDL.Schily.txt from this distribution.
+ */
+
+#ifndef	_SCHILY_FIND_H
+#define	_SCHILY_FIND_H
+
+#ifndef _SCHILY_MCONFIG_H
+#include <schily/mconfig.h>
+#endif
+
+#ifndef _INCL_STDIO_H
+#include <stdio.h>
+#define	_INCL_STDIO_H
+#endif
+
+#ifndef _SCHILY_STANDARD_H
+#include <schily/standard.h>
+#endif
+#ifndef _SCHILY_STAT_H
+#include <schily/stat.h>
+#endif
+
+#ifdef	__cplusplus
+extern "C" {
+#endif
+
+typedef struct find_args {
+	int	Argc;		/* A copy of argc		*/
+	char	**Argv;		/* A copy of argv		*/
+	FILE	*std[3];	/* To redirect stdin/stdout/err	*/
+	int	primtype;	/* The type of the last primary	*/
+	BOOL	found_action;	/* -print/-ls/-exec found	*/
+	int	patlen;		/* strlen() for longest pattern	*/
+	int	walkflags;	/* Walkflags modifed by parser	*/
+	int	maxdepth;	/* -mindepth arg		*/
+	int	mindepth;	/* -maxdepth arg		*/
+	struct plusargs *plusp;	/* List of -exec {} + commands	*/
+	void	*jmp;		/* Used internally by parser	*/
+	int	error;		/* Error code from find_parse()	*/
+} finda_t;
+
+/*
+ * finda_t->primtype is set to ENDARGS by find_parse() if a complete expression
+ * could be parsed.
+ */
+#define	FIND_ENDARGS	1000	/* Found End of Arg Vector		*/
+#define	FIND_ERRARG	1001	/* Parser abort by -help or error	*/
+
+/*
+ * Flags used for struct WALK->pflags:
+ */
+#define	PF_ACL		0x00001	/* Check ACL from struct WALK->pflags	*/
+#define	PF_HAS_ACL	0x10000	/* This file has ACL			*/
+#define	PF_XATTR	0x00002	/* Check XATTR from struct WALK->pflags	*/
+#define	PF_HAS_XATTR	0x20000	/* This file has XATTR			*/
+
+#ifndef	FIND_NODE
+#define	findn_t	void
+#endif
+
+#ifndef	__squit_t_defined
+
+typedef struct {
+	sqfun_t	quitfun;	/* Function to query for shell signal quit   */
+	void	*qfarg;		/* Generic arg for shell builtin quit fun    */
+} squit_t;
+
+#define	__squit_t_defined
+#endif
+
+
+extern	void	find_argsinit	__PR((finda_t *fap));
+extern	void	find_timeinit	__PR((time_t __now));
+extern	findn_t	*find_printnode	__PR((void));
+extern	findn_t	*find_addprint	__PR((findn_t *np, finda_t *fap));
+extern	void	find_free	__PR((findn_t *t, finda_t *fap));
+extern	int	find_token	__PR((char *word));
+extern	char	*find_tname	__PR((int op));
+extern	findn_t	*find_parse	__PR((finda_t *fap));
+extern	void	find_firstprim	__PR((int *pac, char *const **pav));
+
+extern	BOOL	find_primary	__PR((findn_t *t, int op));
+extern	BOOL	find_pname	__PR((findn_t *t, char *word));
+extern	BOOL	find_expr	__PR((char *f, char *ff, struct stat *fs, struct WALK *state, findn_t *t));
+
+extern	int	find_plusflush	__PR((void *p, struct WALK *state));
+extern	void	find_usage	__PR((FILE *f));
+extern	int	find_main	__PR((int ac, char **av, char **ev, FILE *std[3], squit_t *__quit));
+
+#ifdef	__cplusplus
+}
+#endif
+
+#endif	/* _SCHILY_FIND_H */
diff -Nupr star-1.5.orig/star_sym/walk.h star-1.5/star_sym/walk.h
--- star-1.5.orig/star_sym/walk.h	1970-01-01 01:00:00.000000000 +0100
+++ star-1.5/star_sym/walk.h	2012-09-25 13:40:39.763187831 +0200
@@ -0,0 +1,124 @@
+/* @(#)walk.h	1.24 08/04/06 Copyright 2004-2008 J. Schilling */
+/*
+ *	Definitions for directory tree walking
+ *
+ *	Copyright (c) 2004-2008 J. Schilling
+ */
+/*
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License").  You may not use this file except in compliance
+ * with the License.
+ *
+ * See the file CDDL.Schily.txt in this distribution for details.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file CDDL.Schily.txt from this distribution.
+ */
+
+#ifndef	_SCHILY_WALK_H
+#define	_SCHILY_WALK_H
+
+#ifndef _SCHILY_STAT_H
+#include <schily/stat.h>
+#endif
+
+#ifndef _INCL_STDIO_H
+#include <stdio.h>
+#define	_INCL_STDIO_H
+#endif
+
+#ifdef	__cplusplus
+extern "C" {
+#endif
+
+/*
+ * Flags to control treewalk() via 'walkflags'.
+ *
+ *	WALK_CHDIR	is not implemented, treewalk() always does chdir()
+ *
+ *	WALK_PHYS	Clearing WALK_PHYS has highest precedence and equals
+ *			'find -follow'. If WALK_PHYS is clear, always use stat.
+ *			By default, WALK_PHYS should be set.
+ *
+ *	WALK_ARGFOLLOW	If WALK_ARGFOLLOW is set, symlinks that are used as
+ *			the first argument for trewalk() are followed even
+ *			if WALK_PHYS is set. Setting WALK_ARGFOLLOW equals
+ *			'find -H'.
+ *
+ *	WALK_ALLFOLLOW	If WALK_ALLFOLLOW is set, all symlinks are followed
+ *			even if WALK_PHYS is set. Setting WALK_ALLFOLLOW
+ *			equals 'find -L'.
+ */
+#define	WALK_PHYS	1	/* Use lstat() instead of stat()	*/
+#define	WALK_MOUNT	2	/* Do not cross mount points		*/
+#define	WALK_DEPTH	4	/* Call content before calling the dir	*/
+#define	WALK_CHDIR	8	/* Use chdir() to each directory	*/
+#define	WALK_ARGFOLLOW	0x10	/* Use stat() for top level args only	*/
+#define	WALK_ALLFOLLOW	0x20	/* Use stat() for all files		*/
+#define	WALK_NOSTAT	0x40	/* Avoid to call stat() if st_nlink =>2 */
+#define	WALK_NOEXIT	0x100	/* Do not exit() in case of hard errors	*/
+#define	WALK_NOMSG	0x200	/* Do not write messages to stderr	*/
+#define	WALK_LS_ATIME	0x1000	/* -ls lists atime instead of mtime	*/
+#define	WALK_LS_CTIME	0x2000	/* -ls lists ctime instead of mtime	*/
+
+/*
+ * The 'type' argument to walkfun.
+ */
+#define	WALK_F		1	/* File	*/
+#define	WALK_SL		2	/* Symbolic Link */
+#define	WALK_D		3	/* Directory */
+#define	WALK_DP		4	/* Directory previously visited */
+#define	WALK_DNR	5	/* Directory with no read permission */
+#define	WALK_NS		6	/* Unknown file type stat failed */
+#define	WALK_SLN	7	/* Symbolic Link that points to nonexistent file */
+
+#ifndef	__sqfun_t_defined
+typedef	int	(*sqfun_t)	__PR((void *arg));
+#define	__sqfun_t_defined
+#endif
+
+struct WALK {
+	int	flags;		/* Flags for communication with (*walkfun)() */
+	int	base;		/* Filename offset in path for  (*walkfun)() */
+	int	level;		/* The nesting level set up for (*walkfun)() */
+	int	walkflags;	/* treewalk() control flags		    */
+	void	*twprivate;	/* treewalk() private do not touch	    */
+	FILE	*std[3];	/* To redirect stdin/stdout/err in treewalk  */
+	char	**env;		/* To allow different env in treewalk/exec   */
+	sqfun_t	quitfun;	/* Function to query for shell signal quit   */
+	void	*qfarg;		/* Generic arg for shell builtin quit fun    */
+	int	maxdepth;	/* (*walkfun)() private, unused by treewalk  */
+	int	mindepth;	/* (*walkfun)() private, unused by treewalk  */
+	char	*lname;		/* (*walkfun)() private, unused by treewalk  */
+	void	*tree;		/* (*walkfun)() private, unused by treewalk  */
+	void	*patstate;	/* (*walkfun)() private, unused by treewalk  */
+	int	err;		/* (*walkfun)() private, unused by treewalk  */
+	int	pflags;		/* (*walkfun)() private, unused by treewalk  */
+	int	auxi;		/* (*walkfun)() private, unused by treewalk  */
+	void	*auxp;		/* (*walkfun)() private, unused by treewalk  */
+};
+
+/*
+ * Flags in struct WALK used to communicate with (*walkfun)()
+ */
+#define	WALK_WF_PRUNE	1	/* (*walkfun)() -> walk(): abort waking tree	*/
+#define	WALK_WF_QUIT	2	/* (*walkfun)() -> walk(): quit completely	*/
+#define	WALK_WF_NOCHDIR	4	/* walk() -> (*walkfun)(): WALK_DNR is cannot chdir() */
+#define	WALK_WF_NOCWD	8	/* walk() -> caller: cannot get working dir	*/
+#define	WALK_WF_NOHOME	16	/* walk() -> caller: cannot chdir("..")		*/
+
+typedef	int	(*walkfun)	__PR((char *_nm, struct stat *_fs, int _type, struct WALK *_state));
+
+extern	int	treewalk	__PR((char *_nm, walkfun _fn, struct WALK *_state));
+extern	void	walkinitstate	__PR((struct WALK *_state));
+extern	void	*walkopen	__PR((struct WALK *_state));
+extern	int	walkgethome	__PR((struct WALK *_state));
+extern	int	walkhome	__PR((struct WALK *_state));
+extern	int	walkclose	__PR((struct WALK *_state));
+
+#ifdef	__cplusplus
+}
+#endif
+
+#endif	/* _SCHILY_WALK_H */

