Hey all,

I've written a quick patch for sltar which lets you create archives as
well as extract and list them. (It reads the files' paths in through
stdin.) I've not tested it extensively, but it seems to work well.
Maybe Enno could apply it to the sltar repo?

Thanks,
cls
diff -r 8e03adc56a1d config.mk
--- a/config.mk	Sun Feb 10 12:24:10 2008 +0100
+++ b/config.mk	Thu May 19 19:15:18 2011 +0100
@@ -12,8 +12,9 @@
 LIBS = -L/usr/lib -lc
 
 # flags
-CFLAGS = -static -Os -g -Wall -Werror ${INCS} -DVERSION=\"${VERSION}\"
-LDFLAGS = -g ${LIBS}
+CPPFLAGS = -D_BSD_SOURCE -DVERSION=\"${VERSION}\"
+CFLAGS   = -static -ansi -Os -g -Wall ${INCS} ${CPPFLAGS}
+LDFLAGS  = -g ${LIBS}
 
 # compiler and linker
 CC = cc
diff -r 8e03adc56a1d sltar.c
--- a/sltar.c	Sun Feb 10 12:24:10 2008 +0100
+++ b/sltar.c	Thu May 19 19:15:18 2011 +0100
@@ -10,14 +10,119 @@
 #include <sys/stat.h>
 
 enum Header {
-	MODE = 100, UID = 108, GID = 116, SIZE = 124, MTIME = 136,
-	TYPE = 156, LINK = 157, MAJ = 329, MIN = 337, END = 512
+	NAME = 0,   MODE = 100, UID  = 108, GID = 116, SIZE = 124, MTIME = 136,
+	SUM  = 148, TYPE = 156, LINK = 157, MAJ = 329, MIN  = 337, END   = 512
 };
-int c() {
-	fputs("Creating tars does not work yet\n", stderr);
+
+static int append(const char *file);
+static int cksum(unsigned char *b);
+static int create(void);
+static int xtract(char a);
+
+int
+main(int argc, char *argv[]) {
+	char a;
+
+	if(argc == 2 && strlen(argv[1]) == 1)
+		switch((a = argv[1][0])) {
+		case 'c':
+			return create();
+		case 'x':
+		case 't':
+			return xtract(a);
+		}
+
+	/* should not reach */
+	fputs("sltar-" VERSION " - suckless tar\n"
+	      "sltar [ctx]\n", stderr);
 	return EXIT_FAILURE;
 }
-int xt(char a) {
+
+int
+append(const char *file)
+{
+	char buf[END];
+	size_t n;
+	struct stat st;
+	FILE *fp;
+
+	if(stat(file, &st) == -1) {
+		fprintf(stderr, "%s: cannot stat\n", file);
+		return EXIT_FAILURE;
+	}
+	memset(buf, 0, sizeof buf);
+	snprintf(&buf[NAME], 100, "%s",     file);
+	snprintf(&buf[MODE],   8, "%07o",   st.st_mode);
+	snprintf(&buf[UID],    8, "%07o",   st.st_uid);
+	snprintf(&buf[GID],    8, "%07o",   st.st_gid);
+	snprintf(&buf[SIZE],  12, "%011lo", st.st_size);
+	snprintf(&buf[MTIME], 12, "%011lo", st.st_mtime);
+
+	if(S_ISREG(st.st_mode))
+		buf[TYPE] = '0';
+	/* no hard link check yet */
+	else if(S_ISLNK(st.st_mode)) {
+		buf[TYPE] = '2';
+		if(readlink(file, &buf[LINK], 100) == -1) {
+			fprintf(stderr, "%s: cannot readlink\n", file);
+			return EXIT_FAILURE;
+		}
+	}
+	else if(S_ISCHR(st.st_mode))
+		buf[TYPE] = '3';
+	else if(S_ISBLK(st.st_mode))
+		buf[TYPE] = '4';
+	else if(S_ISDIR(st.st_mode))
+		buf[TYPE] = '5';
+	else {
+		fprintf(stderr, "%s: unsupported file type\n", file);
+		return EXIT_FAILURE;
+	}
+	if(buf[TYPE] == '3' || buf[TYPE] == '4') {
+		snprintf(&buf[MAJ], 8, "%07o", major(st.st_rdev));
+		snprintf(&buf[MIN], 8, "%07o", minor(st.st_rdev));
+	}
+	snprintf(&buf[SUM], 8, "%06o", cksum((unsigned char *)buf));
+	buf[SUM+7] = ' ';
+
+	if(!(fp = fopen(file, "r"))) {
+		fprintf(stderr, "%s: cannot open\n", file);
+		return EXIT_FAILURE;
+	}
+	for(n = 1; n > 0; n = fread(buf, 1, sizeof buf, fp)) {
+		fwrite(buf, sizeof buf, 1, stdout);
+		memset(buf, 0, sizeof buf);
+	}
+	fclose(fp);
+	return EXIT_SUCCESS;
+}
+
+int
+cksum(unsigned char *b)
+{
+	int i, n = 0;
+
+	for(i = 0; i < END; i++)
+		n += (i >= SUM && i < SUM + 8) ? ' ' : b[i];
+	return n;
+}
+
+int
+create(void) {
+	char buf[BUFSIZ], *p;
+	int ret = EXIT_SUCCESS;
+
+	while(fgets(buf, sizeof buf, stdin)) {
+		if((p = strchr(buf, '\n')))
+			*p = '\0';
+		if(append(buf) == EXIT_FAILURE)
+			ret = EXIT_FAILURE;
+	}
+	return ret;
+}
+
+int
+xtract(char a) {
 	int l;
 	char b[END],fname[101],lname[101];
 	FILE *f = NULL;
@@ -80,20 +185,3 @@
 		fclose(f);
 	return EXIT_SUCCESS;
 }
-
-int main(int argc, char *argv[]) {
-	char a = 0;
-
-	if(argc == 2 && argv[1][0] != 0 && argv[1][1] == 0)
-		a = argv[1][0];
-	switch(a) {
-	case 'c':
-		return c();
-	case 'x':
-	case 't':
-		return xt(a);
-	default:
-		fputs("sltar-" VERSION " - suckless tar\nsltar [ctx]\n",stderr);
-		return EXIT_SUCCESS;
-	}
-}

Reply via email to