Tar now works perfectly.  It behaves much better now then it
used to.  Only thing left to do is add in exclude (-X) option.
 -Erik
diff --git a/TODO b/TODO
index 87f48db..421c402 100644
--- a/TODO
+++ b/TODO
@@ -15,15 +15,12 @@
 
 -----------
 
-* Allow tar to create archives with sockets, devices, and other special files
 * Make insmod actually work
 * dnsdomainname
 * traceroute/netstat
 * rdate
 * hwclock
-* killall
 * stty
-* tr
 * cut
 * expr (maybe?)  (ash builtin?)
 
@@ -40,58 +37,17 @@
 
 busybox.defs.h is too big and hard to follow.
 
-I either need to add a better build system (like the Linux kernel?)
-or I need to split up busybox.defs.h into coherent chunks (i.e.
-busybox.defs.h just has a bunch of: 
-
-#include "fileutils.h"
-#include "shellutils.h"
-
-which would then have smaller sets of #defines...
-Hmm.  Needs to be carefully thought out.
+Perhaps I need to add a better build system (like the Linux kernel?)
 
 -----------------------
 
 
--rw-r--r-- 1000/1000      4398 2000-01-06 21:55 uniq.c
--rw-r--r-- 1000/1000      1568 1999-10-20 18:08 update.c
--rw-r----- 0/1000         1168 2000-01-29 21:03 update.o
--rw-r--r-- 1000/1000     22820 2000-01-05 11:36 utility.c
--rw-r----- 0/1000         7372 2000-01-29 21:03 utility.o
-tar: Skipping to next file header
-tar: Skipping to next file header
-tar: Archive - EOF not on block boundary
-tar: Error is not recoverable: exiting now
-
-
-#1 You are storing by id instead of name like normal tar. Did you realize this?
-(or am I missing some compile option? )ctar did not do this, and I don't think
-it's a good idea for LRP.
-
-#2
-ctar did not produce the EOF error like your tar does. I believe you need to
-pad the end of the archive with at least 2 tarsized (512byte) blocks. (I
-think???)
-
-#3
 There is no exclude file(s) option to tar. LRP's packaging system can not
 function without this. Will you have the time to add this soon?
 
 
 -----------------------
 
-cd /mnt
-mkdir BACKUP
-mv * BACKUP
-
-Today, "mv" behaved as a cp -a and my disk becomed full. It does not
-work properly either when renaming a directory into something else
-(it produces a lot of disk activity when doing this).
-
-
------------------------
-
-
 Feature request:
 
 /bin/busybox --install -s    which makes all links to commands that it
@@ -114,13 +70,6 @@
 -----------------------
 
 
- In utility.c:copyFile: It uses followLinks for both source and
- destination files... is that right for `mv'?  Will need to revisit
- the GNU, freeBSD, and MINIX versions for this... Should read the
- Unix98 and POSIX specs also.
-
------------------------
-
  I think that the add_inode &c in utility.c needs to also stow the
  st_dev field, and that du.c should NOT call `reset_inode_list'
  because there can be hard links from inside one argv/ to inside
diff --git a/applets/busybox.c b/applets/busybox.c
index c2477a5..9a48f49 100644
--- a/applets/busybox.c
+++ b/applets/busybox.c
@@ -382,8 +382,8 @@
 		fprintf(stderr, "Usage: busybox [function] [arguments]...\n");
 		fprintf(stderr, "   or: [function] [arguments]...\n\n");
 		fprintf(stderr,
-				"\tMost people will create a link to busybox for each\n"
-				"\tfunction name, and busybox will act like whatever you invoke it as.\n");
+				"\tMost people will create a link to busybox for each function\n"
+				"\tname, and busybox will act like whatever you invoke it as.\n");
 		fprintf(stderr, "\nCurrently defined functions:\n");
 
 		while (a->name != 0) {
diff --git a/archival/tar.c b/archival/tar.c
index f9b3e18..979821e 100644
--- a/archival/tar.c
+++ b/archival/tar.c
@@ -56,7 +56,8 @@
 
 static const char tar_usage[] =
 	"tar -[cxtvOf] [tarFileName] [FILE] ...\n\n"
-	"Create, extract, or list files from a tar file.\n\n"
+	"Create, extract, or list files from a tar file.  Note that\n"
+	"this version of tar packs hard links as separate files.\n\n"
 	"Options:\n"
 
 	"\tc=create, x=extract, t=list contents, v=verbose,\n"
@@ -110,10 +111,10 @@
 
 /* A few useful constants */
 #define TAR_MAGIC          "ustar"        /* ustar and a null */
-#define TAR_VERSION        "00"           /* 00 and no null */
+//#define TAR_VERSION      "00"           /* 00 and no null */
+#define TAR_VERSION        "  "           /* Be compatable with old GNU format */
 #define TAR_MAGIC_LEN       6
 #define TAR_VERSION_LEN     2
-#define TAR_NAME_LEN        100
 #define TAR_BLOCK_SIZE      512
 
 /* A nice enum with all the possible tar file content types */
@@ -366,7 +367,8 @@
 		return;
 
 	if (link(header->linkname, header->name) < 0) {
-		errorMsg("Error creating hard link '%s': %s\n", header->linkname, strerror(errno)); 
+		errorMsg("Error creating hard link '%s' to '%s': %s\n", 
+				header->name, header->linkname, strerror(errno)); 
 		return;
 	}
 
@@ -382,7 +384,8 @@
 
 #ifdef	S_ISLNK
 	if (symlink(header->linkname, header->name) < 0) {
-		errorMsg("Error creating symlink '%s': %s\n", header->linkname, strerror(errno)); 
+		errorMsg("Error creating symlink '%s' to '%s': %s\n", 
+				header->name, header->linkname, strerror(errno)); 
 		return;
 	}
 	/* Try to change ownership of the symlink.
@@ -644,18 +647,15 @@
 static int putOctal (char *cp, int len, long value)
 {
 	int tempLength;
-	char *tempString;
 	char tempBuffer[32];
+	char *tempString = tempBuffer;
 
 	/* Create a string of the specified length with an initial space,
 	 * leading zeroes and the octal number, and a trailing null.  */
-	tempString = tempBuffer;
-
-	sprintf (tempString, " %0*lo", len - 2, value);
-
-	tempLength = strlen (tempString) + 1;
+	sprintf (tempString, "%0*lo", len - 1, value);
 
 	/* If the string is too large, suppress the leading space.  */
+	tempLength = strlen (tempString) + 1;
 	if (tempLength > len) {
 		tempLength--;
 		tempString++;
@@ -677,10 +677,14 @@
 
 /* Write out a tar header for the specified file/directory/whatever */
 static int
-writeTarHeader(struct TarHeader *header, const char *fileName, struct stat *statbuf)
+writeTarHeader(struct TarBallInfo *tbInfo, const char *fileName, struct stat *statbuf)
 {
-	//int i;
-	//long chksum, sum;
+	long chksum=0;
+	struct TarHeader header;
+	const unsigned char *cp = (const unsigned char *) &header;
+	ssize_t size = sizeof(struct TarHeader);
+
+	memset( &header, 0, size);
 
 	if (*fileName=='/') {
 		static int alreadyWarned=FALSE;
@@ -688,66 +692,88 @@
 			errorMsg("tar: Removing leading '/' from member names\n");
 			alreadyWarned=TRUE;
 		}
-		strcpy(header->name, fileName+1); 
+		strcpy(header.name, fileName+1); 
 	}
 	else {
-		strcpy(header->name, fileName); 
+		strcpy(header.name, fileName); 
 	}
-	putOctal(header->mode, sizeof(header->mode), statbuf->st_mode & 0777);
-	putOctal(header->uid, sizeof(header->uid), statbuf->st_uid);
-	putOctal(header->gid, sizeof(header->gid), statbuf->st_gid);
-	putOctal(header->size, sizeof(header->size), statbuf->st_size);
-	putOctal(header->mtime, sizeof(header->mtime), statbuf->st_mtime);
+	putOctal(header.mode, sizeof(header.mode), statbuf->st_mode);
+	putOctal(header.uid, sizeof(header.uid), statbuf->st_uid);
+	putOctal(header.gid, sizeof(header.gid), statbuf->st_gid);
+	putOctal(header.size, sizeof(header.size), 0); /* Regular file size is handled later */
+	putOctal(header.mtime, sizeof(header.mtime), statbuf->st_mtime);
+	strncpy(header.magic, TAR_MAGIC TAR_VERSION, 
+			TAR_MAGIC_LEN + TAR_VERSION_LEN );
 
+	my_getpwuid(header.uname, statbuf->st_uid);
+	/* Put some sort of sane fallback in place... */
+	if (! *header.uname)
+		strncpy(header.uname, "root", 5);
+	my_getgrgid(header.gname, statbuf->st_gid);
+	if (! *header.uname)
+		strncpy(header.uname, "root", 5);
+
+	// FIXME: (or most likely not) I break Hard Links
 	if (S_ISLNK(statbuf->st_mode)) {
-		header->typeflag  = LNKTYPE;
-		// TODO -- Handle SYMTYPE
+		char buffer[BUFSIZ];
+		header.typeflag  = SYMTYPE;
+		if ( readlink(fileName, buffer, sizeof(buffer) - 1) < 0) {
+			errorMsg("Error reading symlink '%s': %s\n", header.name, strerror(errno));
+			return ( FALSE);
+		}
+		strncpy(header.linkname, buffer, sizeof(header.linkname)); 
 	} else if (S_ISDIR(statbuf->st_mode)) {
-		header->typeflag  = DIRTYPE;
-		strncat(header->name, "/", sizeof(header->name)); 
+		header.typeflag  = DIRTYPE;
+		strncat(header.name, "/", sizeof(header.name)); 
 	} else if (S_ISCHR(statbuf->st_mode)) {
-		header->typeflag  = CHRTYPE;
-		putOctal(header->devmajor, sizeof(header->devmajor), MAJOR(statbuf->st_rdev));
-		putOctal(header->devminor, sizeof(header->devminor), MINOR(statbuf->st_rdev));
+		header.typeflag  = CHRTYPE;
+		putOctal(header.devmajor, sizeof(header.devmajor), MAJOR(statbuf->st_rdev));
+		putOctal(header.devminor, sizeof(header.devminor), MINOR(statbuf->st_rdev));
 	} else if (S_ISBLK(statbuf->st_mode)) {
-		header->typeflag  = BLKTYPE;
-		putOctal(header->devmajor, sizeof(header->devmajor), MAJOR(statbuf->st_rdev));
-		putOctal(header->devminor, sizeof(header->devminor), MINOR(statbuf->st_rdev));
+		header.typeflag  = BLKTYPE;
+		putOctal(header.devmajor, sizeof(header.devmajor), MAJOR(statbuf->st_rdev));
+		putOctal(header.devminor, sizeof(header.devminor), MINOR(statbuf->st_rdev));
 	} else if (S_ISFIFO(statbuf->st_mode)) {
-		header->typeflag  = FIFOTYPE;
-	} else if (S_ISLNK(statbuf->st_mode)) {
-		header->typeflag  = LNKTYPE;
-	} else if (S_ISLNK(statbuf->st_mode)) {
-		header->typeflag  = REGTYPE;
+		header.typeflag  = FIFOTYPE;
+	} else if (S_ISREG(statbuf->st_mode)) {
+		header.typeflag  = REGTYPE;
+		putOctal(header.size, sizeof(header.size), statbuf->st_size);
 	} else {
+		errorMsg("tar: %s: Unknown file type\n", fileName);
 		return ( FALSE);
 	}
-	return ( TRUE);
 
-#if 0	
-	header->linkname  = rawHeader->linkname;
-	header->devmajor  = getOctal(rawHeader->devmajor, sizeof(rawHeader->devmajor));
-	header->devminor  = getOctal(rawHeader->devminor, sizeof(rawHeader->devminor));
-
-	/* Write out the checksum */
-	chksum = getOctal(rawHeader->chksum, sizeof(rawHeader->chksum));
+	/* Calculate and store the checksum (i.e. the sum of all of the bytes of
+	 * the header).  The checksum field must be filled with blanks for the
+	 * calculation.  The checksum field is formatted differently from the
+	 * other fields: it has [6] digits, a null, then a space -- rather than
+	 * digits, followed by a null like the other fields... */
+	memset(header.chksum, ' ', sizeof(header.chksum));
+	cp = (const unsigned char *) &header;
+	while (size-- > 0)
+		chksum += *cp++;
+	putOctal(header.chksum, 7, chksum);
+	
+	/* Now write the header out to disk */
+	if ((size=fullWrite(tbInfo->tarFd, (char*)&header, sizeof(struct TarHeader))) < 0) {
+		errorMsg(io_error, fileName, strerror(errno)); 
+		return ( FALSE);
+	}
+	/* Pad the header up to the tar block size */
+	for (; size<TAR_BLOCK_SIZE; size++) {
+		write(tbInfo->tarFd, "\0", 1);
+	}
+	/* Now do the verbose thing (or not) */
+	if (tbInfo->verboseFlag==TRUE)
+		fprintf(stdout, "%s\n", header.name);
 
 	return ( TRUE);
-#endif
 }
 
 
 static int writeFileToTarball(const char *fileName, struct stat *statbuf, void* userData)
 {
-	int inputFileFd;
 	struct TarBallInfo *tbInfo = (struct TarBallInfo *)userData;
-	char header[sizeof(struct TarHeader)];
-
-	/* First open the file we want to archive, and make sure all is well */
-	if ((inputFileFd = open(fileName, O_RDONLY)) < 0) {
-		errorMsg("tar: %s: Cannot open: %s\n", fileName, strerror(errno));
-		return( TRUE);
-	}
 
 	/* It is against the rules to archive a socket */
 	if (S_ISSOCK(statbuf->st_mode)) {
@@ -764,13 +790,41 @@
 		return( TRUE);
 	}
 
-	memset( header, 0, sizeof(struct TarHeader));
-	if (writeTarHeader((struct TarHeader *)header, fileName, statbuf)==FALSE) {
-		dprintf(tbInfo->tarFd, "%s", header);
+	if (writeTarHeader(tbInfo, fileName, statbuf)==FALSE) {
+		return( FALSE);
 	} 
-	/* Now do the verbose thing (or not) */
-	if (tbInfo->verboseFlag==TRUE)
-		fprintf(stdout, "%s\n", ((struct TarHeader *)header)->name);
+
+	/* Now, if the file is a regular file, copy it out to the tarball */
+	if (S_ISREG(statbuf->st_mode)) {
+		int  inputFileFd;
+		char buffer[BUFSIZ];
+		ssize_t size=0, readSize=0;
+
+		/* open the file we want to archive, and make sure all is well */
+		if ((inputFileFd = open(fileName, O_RDONLY)) < 0) {
+			errorMsg("tar: %s: Cannot open: %s\n", fileName, strerror(errno));
+			return( FALSE);
+		}
+		
+		/* write the file to the archive */
+		while ( (size = fullRead(inputFileFd, buffer, sizeof(buffer))) > 0 ) {
+			if (fullWrite(tbInfo->tarFd, buffer, size) != size ) {
+				/* Output file seems to have a problem */
+				errorMsg(io_error, fileName, strerror(errno)); 
+				return( FALSE);
+			}
+			readSize+=size;
+		}
+		if (size == -1) {
+			errorMsg(io_error, fileName, strerror(errno)); 
+			return( FALSE);
+		}
+		/* Pad the file up to the tar block size */
+		for (; (readSize%TAR_BLOCK_SIZE) != 0; readSize++) {
+			write(tbInfo->tarFd, "\0", 1);
+		}
+		close( inputFileFd);
+	}
 
 	return( TRUE);
 }
@@ -780,6 +834,7 @@
 {
 	int tarFd=-1;
 	int errorFlag=FALSE;
+	ssize_t size;
 	//int skipFileFlag=FALSE;
 	struct TarBallInfo tbInfo;
 	tbInfo.verboseFlag = verboseFlag;
@@ -814,6 +869,10 @@
 			errorFlag = TRUE;
 		}
 	}
+	/* Write two empty blocks to the end of the archive */
+	for (size=0; size<(2*TAR_BLOCK_SIZE); size++) {
+		write(tbInfo.tarFd, "\0", 1);
+	}
 	/* Hang up the tools, close up shop, head home */
 	close(tarFd);
 	if (errorFlag == TRUE) {
diff --git a/busybox.c b/busybox.c
index c2477a5..9a48f49 100644
--- a/busybox.c
+++ b/busybox.c
@@ -382,8 +382,8 @@
 		fprintf(stderr, "Usage: busybox [function] [arguments]...\n");
 		fprintf(stderr, "   or: [function] [arguments]...\n\n");
 		fprintf(stderr,
-				"\tMost people will create a link to busybox for each\n"
-				"\tfunction name, and busybox will act like whatever you invoke it as.\n");
+				"\tMost people will create a link to busybox for each function\n"
+				"\tname, and busybox will act like whatever you invoke it as.\n");
 		fprintf(stderr, "\nCurrently defined functions:\n");
 
 		while (a->name != 0) {
diff --git a/kill.c b/kill.c
index 10343a1..260f4a0 100644
--- a/kill.c
+++ b/kill.c
@@ -1,6 +1,6 @@
 /* vi: set sw=4 ts=4: */
 /*
- * Mini kill implementation for busybox
+ * Mini kill/killall implementation for busybox
  *
  * Copyright (C) 1995, 1996 by Bruce Perens <bruce@pixar.com>.
  *
diff --git a/procps/kill.c b/procps/kill.c
index 10343a1..260f4a0 100644
--- a/procps/kill.c
+++ b/procps/kill.c
@@ -1,6 +1,6 @@
 /* vi: set sw=4 ts=4: */
 /*
- * Mini kill implementation for busybox
+ * Mini kill/killall implementation for busybox
  *
  * Copyright (C) 1995, 1996 by Bruce Perens <bruce@pixar.com>.
  *
diff --git a/tar.c b/tar.c
index f9b3e18..979821e 100644
--- a/tar.c
+++ b/tar.c
@@ -56,7 +56,8 @@
 
 static const char tar_usage[] =
 	"tar -[cxtvOf] [tarFileName] [FILE] ...\n\n"
-	"Create, extract, or list files from a tar file.\n\n"
+	"Create, extract, or list files from a tar file.  Note that\n"
+	"this version of tar packs hard links as separate files.\n\n"
 	"Options:\n"
 
 	"\tc=create, x=extract, t=list contents, v=verbose,\n"
@@ -110,10 +111,10 @@
 
 /* A few useful constants */
 #define TAR_MAGIC          "ustar"        /* ustar and a null */
-#define TAR_VERSION        "00"           /* 00 and no null */
+//#define TAR_VERSION      "00"           /* 00 and no null */
+#define TAR_VERSION        "  "           /* Be compatable with old GNU format */
 #define TAR_MAGIC_LEN       6
 #define TAR_VERSION_LEN     2
-#define TAR_NAME_LEN        100
 #define TAR_BLOCK_SIZE      512
 
 /* A nice enum with all the possible tar file content types */
@@ -366,7 +367,8 @@
 		return;
 
 	if (link(header->linkname, header->name) < 0) {
-		errorMsg("Error creating hard link '%s': %s\n", header->linkname, strerror(errno)); 
+		errorMsg("Error creating hard link '%s' to '%s': %s\n", 
+				header->name, header->linkname, strerror(errno)); 
 		return;
 	}
 
@@ -382,7 +384,8 @@
 
 #ifdef	S_ISLNK
 	if (symlink(header->linkname, header->name) < 0) {
-		errorMsg("Error creating symlink '%s': %s\n", header->linkname, strerror(errno)); 
+		errorMsg("Error creating symlink '%s' to '%s': %s\n", 
+				header->name, header->linkname, strerror(errno)); 
 		return;
 	}
 	/* Try to change ownership of the symlink.
@@ -644,18 +647,15 @@
 static int putOctal (char *cp, int len, long value)
 {
 	int tempLength;
-	char *tempString;
 	char tempBuffer[32];
+	char *tempString = tempBuffer;
 
 	/* Create a string of the specified length with an initial space,
 	 * leading zeroes and the octal number, and a trailing null.  */
-	tempString = tempBuffer;
-
-	sprintf (tempString, " %0*lo", len - 2, value);
-
-	tempLength = strlen (tempString) + 1;
+	sprintf (tempString, "%0*lo", len - 1, value);
 
 	/* If the string is too large, suppress the leading space.  */
+	tempLength = strlen (tempString) + 1;
 	if (tempLength > len) {
 		tempLength--;
 		tempString++;
@@ -677,10 +677,14 @@
 
 /* Write out a tar header for the specified file/directory/whatever */
 static int
-writeTarHeader(struct TarHeader *header, const char *fileName, struct stat *statbuf)
+writeTarHeader(struct TarBallInfo *tbInfo, const char *fileName, struct stat *statbuf)
 {
-	//int i;
-	//long chksum, sum;
+	long chksum=0;
+	struct TarHeader header;
+	const unsigned char *cp = (const unsigned char *) &header;
+	ssize_t size = sizeof(struct TarHeader);
+
+	memset( &header, 0, size);
 
 	if (*fileName=='/') {
 		static int alreadyWarned=FALSE;
@@ -688,66 +692,88 @@
 			errorMsg("tar: Removing leading '/' from member names\n");
 			alreadyWarned=TRUE;
 		}
-		strcpy(header->name, fileName+1); 
+		strcpy(header.name, fileName+1); 
 	}
 	else {
-		strcpy(header->name, fileName); 
+		strcpy(header.name, fileName); 
 	}
-	putOctal(header->mode, sizeof(header->mode), statbuf->st_mode & 0777);
-	putOctal(header->uid, sizeof(header->uid), statbuf->st_uid);
-	putOctal(header->gid, sizeof(header->gid), statbuf->st_gid);
-	putOctal(header->size, sizeof(header->size), statbuf->st_size);
-	putOctal(header->mtime, sizeof(header->mtime), statbuf->st_mtime);
+	putOctal(header.mode, sizeof(header.mode), statbuf->st_mode);
+	putOctal(header.uid, sizeof(header.uid), statbuf->st_uid);
+	putOctal(header.gid, sizeof(header.gid), statbuf->st_gid);
+	putOctal(header.size, sizeof(header.size), 0); /* Regular file size is handled later */
+	putOctal(header.mtime, sizeof(header.mtime), statbuf->st_mtime);
+	strncpy(header.magic, TAR_MAGIC TAR_VERSION, 
+			TAR_MAGIC_LEN + TAR_VERSION_LEN );
 
+	my_getpwuid(header.uname, statbuf->st_uid);
+	/* Put some sort of sane fallback in place... */
+	if (! *header.uname)
+		strncpy(header.uname, "root", 5);
+	my_getgrgid(header.gname, statbuf->st_gid);
+	if (! *header.uname)
+		strncpy(header.uname, "root", 5);
+
+	// FIXME: (or most likely not) I break Hard Links
 	if (S_ISLNK(statbuf->st_mode)) {
-		header->typeflag  = LNKTYPE;
-		// TODO -- Handle SYMTYPE
+		char buffer[BUFSIZ];
+		header.typeflag  = SYMTYPE;
+		if ( readlink(fileName, buffer, sizeof(buffer) - 1) < 0) {
+			errorMsg("Error reading symlink '%s': %s\n", header.name, strerror(errno));
+			return ( FALSE);
+		}
+		strncpy(header.linkname, buffer, sizeof(header.linkname)); 
 	} else if (S_ISDIR(statbuf->st_mode)) {
-		header->typeflag  = DIRTYPE;
-		strncat(header->name, "/", sizeof(header->name)); 
+		header.typeflag  = DIRTYPE;
+		strncat(header.name, "/", sizeof(header.name)); 
 	} else if (S_ISCHR(statbuf->st_mode)) {
-		header->typeflag  = CHRTYPE;
-		putOctal(header->devmajor, sizeof(header->devmajor), MAJOR(statbuf->st_rdev));
-		putOctal(header->devminor, sizeof(header->devminor), MINOR(statbuf->st_rdev));
+		header.typeflag  = CHRTYPE;
+		putOctal(header.devmajor, sizeof(header.devmajor), MAJOR(statbuf->st_rdev));
+		putOctal(header.devminor, sizeof(header.devminor), MINOR(statbuf->st_rdev));
 	} else if (S_ISBLK(statbuf->st_mode)) {
-		header->typeflag  = BLKTYPE;
-		putOctal(header->devmajor, sizeof(header->devmajor), MAJOR(statbuf->st_rdev));
-		putOctal(header->devminor, sizeof(header->devminor), MINOR(statbuf->st_rdev));
+		header.typeflag  = BLKTYPE;
+		putOctal(header.devmajor, sizeof(header.devmajor), MAJOR(statbuf->st_rdev));
+		putOctal(header.devminor, sizeof(header.devminor), MINOR(statbuf->st_rdev));
 	} else if (S_ISFIFO(statbuf->st_mode)) {
-		header->typeflag  = FIFOTYPE;
-	} else if (S_ISLNK(statbuf->st_mode)) {
-		header->typeflag  = LNKTYPE;
-	} else if (S_ISLNK(statbuf->st_mode)) {
-		header->typeflag  = REGTYPE;
+		header.typeflag  = FIFOTYPE;
+	} else if (S_ISREG(statbuf->st_mode)) {
+		header.typeflag  = REGTYPE;
+		putOctal(header.size, sizeof(header.size), statbuf->st_size);
 	} else {
+		errorMsg("tar: %s: Unknown file type\n", fileName);
 		return ( FALSE);
 	}
-	return ( TRUE);
 
-#if 0	
-	header->linkname  = rawHeader->linkname;
-	header->devmajor  = getOctal(rawHeader->devmajor, sizeof(rawHeader->devmajor));
-	header->devminor  = getOctal(rawHeader->devminor, sizeof(rawHeader->devminor));
-
-	/* Write out the checksum */
-	chksum = getOctal(rawHeader->chksum, sizeof(rawHeader->chksum));
+	/* Calculate and store the checksum (i.e. the sum of all of the bytes of
+	 * the header).  The checksum field must be filled with blanks for the
+	 * calculation.  The checksum field is formatted differently from the
+	 * other fields: it has [6] digits, a null, then a space -- rather than
+	 * digits, followed by a null like the other fields... */
+	memset(header.chksum, ' ', sizeof(header.chksum));
+	cp = (const unsigned char *) &header;
+	while (size-- > 0)
+		chksum += *cp++;
+	putOctal(header.chksum, 7, chksum);
+	
+	/* Now write the header out to disk */
+	if ((size=fullWrite(tbInfo->tarFd, (char*)&header, sizeof(struct TarHeader))) < 0) {
+		errorMsg(io_error, fileName, strerror(errno)); 
+		return ( FALSE);
+	}
+	/* Pad the header up to the tar block size */
+	for (; size<TAR_BLOCK_SIZE; size++) {
+		write(tbInfo->tarFd, "\0", 1);
+	}
+	/* Now do the verbose thing (or not) */
+	if (tbInfo->verboseFlag==TRUE)
+		fprintf(stdout, "%s\n", header.name);
 
 	return ( TRUE);
-#endif
 }
 
 
 static int writeFileToTarball(const char *fileName, struct stat *statbuf, void* userData)
 {
-	int inputFileFd;
 	struct TarBallInfo *tbInfo = (struct TarBallInfo *)userData;
-	char header[sizeof(struct TarHeader)];
-
-	/* First open the file we want to archive, and make sure all is well */
-	if ((inputFileFd = open(fileName, O_RDONLY)) < 0) {
-		errorMsg("tar: %s: Cannot open: %s\n", fileName, strerror(errno));
-		return( TRUE);
-	}
 
 	/* It is against the rules to archive a socket */
 	if (S_ISSOCK(statbuf->st_mode)) {
@@ -764,13 +790,41 @@
 		return( TRUE);
 	}
 
-	memset( header, 0, sizeof(struct TarHeader));
-	if (writeTarHeader((struct TarHeader *)header, fileName, statbuf)==FALSE) {
-		dprintf(tbInfo->tarFd, "%s", header);
+	if (writeTarHeader(tbInfo, fileName, statbuf)==FALSE) {
+		return( FALSE);
 	} 
-	/* Now do the verbose thing (or not) */
-	if (tbInfo->verboseFlag==TRUE)
-		fprintf(stdout, "%s\n", ((struct TarHeader *)header)->name);
+
+	/* Now, if the file is a regular file, copy it out to the tarball */
+	if (S_ISREG(statbuf->st_mode)) {
+		int  inputFileFd;
+		char buffer[BUFSIZ];
+		ssize_t size=0, readSize=0;
+
+		/* open the file we want to archive, and make sure all is well */
+		if ((inputFileFd = open(fileName, O_RDONLY)) < 0) {
+			errorMsg("tar: %s: Cannot open: %s\n", fileName, strerror(errno));
+			return( FALSE);
+		}
+		
+		/* write the file to the archive */
+		while ( (size = fullRead(inputFileFd, buffer, sizeof(buffer))) > 0 ) {
+			if (fullWrite(tbInfo->tarFd, buffer, size) != size ) {
+				/* Output file seems to have a problem */
+				errorMsg(io_error, fileName, strerror(errno)); 
+				return( FALSE);
+			}
+			readSize+=size;
+		}
+		if (size == -1) {
+			errorMsg(io_error, fileName, strerror(errno)); 
+			return( FALSE);
+		}
+		/* Pad the file up to the tar block size */
+		for (; (readSize%TAR_BLOCK_SIZE) != 0; readSize++) {
+			write(tbInfo->tarFd, "\0", 1);
+		}
+		close( inputFileFd);
+	}
 
 	return( TRUE);
 }
@@ -780,6 +834,7 @@
 {
 	int tarFd=-1;
 	int errorFlag=FALSE;
+	ssize_t size;
 	//int skipFileFlag=FALSE;
 	struct TarBallInfo tbInfo;
 	tbInfo.verboseFlag = verboseFlag;
@@ -814,6 +869,10 @@
 			errorFlag = TRUE;
 		}
 	}
+	/* Write two empty blocks to the end of the archive */
+	for (size=0; size<(2*TAR_BLOCK_SIZE); size++) {
+		write(tbInfo.tarFd, "\0", 1);
+	}
 	/* Hang up the tools, close up shop, head home */
 	close(tarFd);
 	if (errorFlag == TRUE) {
diff --git a/utility.c b/utility.c
index 0d4799f..b91da4c 100644
--- a/utility.c
+++ b/utility.c
@@ -783,7 +783,7 @@
 
 
 
-#if defined (BB_CHMOD_CHOWN_CHGRP) || defined (BB_PS)
+#if defined BB_CHMOD_CHOWN_CHGRP || defined BB_PS || defined BB_LS || defined BB_TAR 
 
 /* Use this to avoid needing the glibc NSS stuff 
  * This uses storage buf to hold things.
@@ -858,7 +858,7 @@
 }
 
 
-#endif							/* BB_CHMOD_CHOWN_CHGRP || BB_PS */
+#endif							/* BB_CHMOD_CHOWN_CHGRP || BB_PS || BB_LS || BB_TAR */