diff --git a/LICENSE b/LICENSE
index 8f1caaf..ab13f3c 100644
--- a/LICENSE
+++ b/LICENSE
@@ -11,6 +11,7 @@ MIT/X Consortium License
 © 2012 Kurt H. Maier <khm@intma.in>
 © 2012 Christoph Lohmann <20h@r-36.net> 
 © 2012 David Galos <galosd83@students.rowan.edu> 
+© 2012 Enno Boland <g s01 de>
 © 2012 Robert Ransom <rransom.8774@gmail.com>
 © 2013 Jakob Kramer <jakob.kramer@gmx.de>
 
diff --git a/Makefile b/Makefile
index f825ec4..38f4efa 100644
--- a/Makefile
+++ b/Makefile
@@ -68,6 +68,7 @@ SRC = \
 	sponge.c   \
 	sync.c     \
 	tail.c     \
+	tar.c      \
 	tee.c      \
 	test.c     \
 	touch.c    \
diff --git a/tar.1 b/tar.1
new file mode 100644
index 0000000..414ca4b
--- /dev/null
+++ b/tar.1
@@ -0,0 +1,27 @@
+.TH TAR 1 sbase\-VERSION
+.SH NAME
+tar \- create, list or extract a tape archive
+.SH SYNOPSIS
+.B tar
+.BR c | t | x
+.RI [ path ]
+.SH DESCRIPTION
+.B tar 
+is the standard file archiver. Generally the archices
+created with it are further compressed.
+.SH OPTIONS
+.TP
+.B x
+extract tarball from stdin
+.TP
+.B t
+list all files in tarball from stdin
+.TP
+.BI c\  path 
+creates tarball from 
+.I path 
+and prints it to stdout
+.SH SEE ALSO
+.IR ar (1)
+.IR gzip (1)
+.IR bzip2 (1)
diff --git a/tar.c b/tar.c
new file mode 100644
index 0000000..ba4d41a
--- /dev/null
+++ b/tar.c
@@ -0,0 +1,204 @@
+/* See LICENSE file for copyright and license details */
+#include <stdlib.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <limits.h>
+#include <ftw.h>
+#include <grp.h>
+#include <pwd.h>
+#include "util.h"
+
+enum Header {
+	NAME=0, MODE = 100, UID = 108, GID = 116, SIZE = 124, MTIME = 136, CHKSUM=148,
+	TYPE = 156, LINK = 157, MAGIC=257, VERS=263, UNAME=265, GNAME=297, MAJ = 329, 
+	MIN = 337, END = 512
+};
+
+enum Type {
+	REG = '0', HARDLINK = '1', SYMLINK = '2', CHARDEV='3', BLOCKDEV='4',
+	DIRECTORY='5', FIFO='6' 
+};
+
+static int archive(const char *, const struct stat *, int);
+static int unarchive(char *, int, char[END]);
+static int print(char *, int, char[END]);
+static int c(char *);
+static int xt(int (*)(char*, int, char[END]));
+
+static void 
+usage(void)
+{
+	eprintf("usage: tar t|x|c [path]\n");
+}
+
+int
+main(int argc, char *argv[])
+{
+	if(argc < 2 || argc > 3 || strlen(argv[1]) != 1)
+		usage();
+	switch(argv[1][0]) {
+	case 'c':
+		if(argc<3)
+			usage();
+		return c(argv[2]);
+	case 'x':
+		return xt(unarchive);
+	case 't':
+		return xt(print);
+	default:
+		usage();
+	}
+	return EXIT_FAILURE;
+}
+
+int
+archive(const char* path, const struct stat* sta, int type)
+{
+	char b[END];
+	FILE *f = NULL;
+	struct stat st;
+	struct passwd *pw;
+	struct group *gr;
+	mode_t mode;
+	unsigned sum = 0;
+	int x;
+
+	lstat(path, &st);
+	memset(b, 0, END);
+	snprintf(b+NAME, 100, "%s", path);
+	snprintf(b+MODE, 8, "%.7o", (unsigned)st.st_mode&0777);
+	snprintf(b+UID,  8, "%.7o", (unsigned)st.st_uid);
+	snprintf(b+GID,  8, "%.7o", (unsigned)st.st_gid);
+	snprintf(b+SIZE, 12, "%.11o", 0);
+	snprintf(b+MTIME,12, "%.11o", (unsigned)st.st_mtime);
+	memcpy(b+MAGIC, "ustar", strlen("ustar")+1);
+	memcpy(b+VERS, "00", strlen("00"));
+	pw = getpwuid(st.st_uid);
+	snprintf(b+UNAME, 32, "%s", pw->pw_name);
+	gr = getgrgid(st.st_gid);
+	snprintf(b+GNAME, 32, "%s", gr->gr_name);	
+	mode = st.st_mode;
+
+	if(S_ISREG(mode)) {
+		b[TYPE] = REG;
+		snprintf(b+SIZE, 12, "%.11o", (unsigned)st.st_size);
+		f = fopen(path, "r");
+	} else if(S_ISDIR(mode)) {
+		b[TYPE] = DIRECTORY;
+	} else if(S_ISLNK(mode)) {
+		b[TYPE] = SYMLINK;
+		readlink(path, b+LINK, 99);
+	} else if(S_ISCHR(mode)) {
+		b[TYPE] = CHARDEV;
+		snprintf(b+MAJ,  8, "%.7o", (unsigned)major(st.st_dev));
+		snprintf(b+MIN,  8, "%.7o", (unsigned)minor(st.st_dev));
+	} else if(S_ISBLK(mode)) {
+		b[TYPE] = BLOCKDEV;
+		snprintf(b+MAJ,  8, "%.7o", (unsigned)major(st.st_dev));
+		snprintf(b+MIN,  8, "%.7o", (unsigned)minor(st.st_dev));
+	} else if(S_ISFIFO(mode)) {
+		b[TYPE] = FIFO;
+	}
+	memset(b+CHKSUM, ' ', 8);
+	for(x = 0; x < END; x++)
+		sum+=b[x];
+	snprintf(b+CHKSUM, 8, "%.7o", sum);
+	fwrite(b, END, 1, stdout);
+	if(!f)
+		return 0;
+	while((x = fread(b, 1, END, f)) > 0){
+		if(x < END)
+			memset(b+x, 0, END-x);
+		fwrite(b, END, 1, stdout);
+	}
+	fclose(f);
+	return 0;	
+}
+
+int
+unarchive(char *fname, int l, char b[END])
+{
+	static char lname[101] = {0};
+	FILE *f = NULL;
+	memcpy(lname, b+LINK, 100);
+
+	unlink(fname);
+	switch(b[TYPE]) {
+	case REG:
+		if(!(f = fopen(fname,"w")) || chmod(fname,strtoul(b + MODE,0,8)))
+			perror(fname);
+		break;
+	case HARDLINK:
+		if(!link(lname,fname))
+			perror(fname);
+		break;
+	case SYMLINK:
+		if(!symlink(lname,fname))
+			perror(fname);
+		break;
+	case DIRECTORY:
+		if(mkdir(fname,(mode_t) strtoull(b + MODE,0,8)))
+			perror(fname);
+		break;
+	case CHARDEV:
+	case BLOCKDEV:
+		if(mknod(fname, (b[TYPE] == '3' ? S_IFCHR : S_IFBLK) | strtoul(b + MODE,0,8),
+				makedev(strtoul(b + MAJ,0,8),
+					strtoul(b + MIN,0,8))))
+			perror(fname);
+		break;
+	case FIFO:
+		if(mknod(fname, S_IFIFO | strtoul(b + MODE,0,8), 0))
+			perror(fname);
+		break;
+	default:
+		fprintf(stderr,"tar: '%c': unsupported filetype\n",b[TYPE]);
+	}
+	if(getuid() == 0 && chown(fname, strtoul(b + UID,0,8),strtoul(b + GID,0,8)))
+		perror(fname);
+
+	for(; l > 0; l -= END){
+		fread(b, END, 1, stdin);
+		if(f)
+			fwrite(b, MIN(l, 512), 1, f);
+	}
+	if(f)
+		fclose(f);
+	return 0;
+}
+
+int
+print(char *fname, int l, char b[END])
+{
+	puts(fname);
+	for(; l > 0; l -= END)
+		fread(b, END, 1, stdin);
+	return 0;
+}
+
+int
+c(char *dir)
+{
+	ftw(dir, archive, 128); /* OPEN_MAX); */
+	return EXIT_SUCCESS;
+}
+
+int 
+xt(int (*fn)(char*, int, char[END]))
+{
+	int l;
+	char b[END],fname[101];
+	fname[100] = '\0';
+
+	while(fread(b, END, 1, stdin)){
+		if(*b == '\0')
+			break;
+		memcpy(fname, b, 100);
+		l = strtol(b+SIZE, 0, 8);
+		fn(fname, l, b);
+	}
+	return EXIT_SUCCESS;
+}
