shithub: scc

Download patch

ref: 458a063eb092b36470332d6418a3dde377e8e2be
parent: fe9bac1eb738478ab7335626802ae4b954454dc1
author: Roberto E. Vargas Caballero <k0ga@shike2.com>
date: Tue Feb 13 09:42:29 EST 2018

[ar] Add extract key

--- a/ar/main.c
+++ b/ar/main.c
@@ -23,6 +23,7 @@
 	FILE *dst;
 	struct ar_hdr hdr;
 	char *fname;
+	long size;
 };
 
 static void
@@ -138,7 +139,7 @@
 }
 
 static void
-copymember(char *fname, struct ar_hdr *hdr, FILE *dst, FILE *src)
+copy(char *fname, struct ar_hdr *hdr, FILE *dst, FILE *src)
 {
 	int c;
 	long siz, n;
@@ -210,6 +211,37 @@
 }
 
 static void
+extract(struct arop *op, char *files[])
+{
+	int c;
+	long siz;
+	FILE *fp;
+
+	if (*files && !inlist(op->fname, files))
+		return;
+	if (vflag)
+		printf("x - %s\n", op->fname);
+	siz = op->size;
+
+	if ((fp = fopen(op->fname, "wb")) == NULL)
+		goto error_file;
+	while (siz-- > 0 && (c = getc(op->src)) != EOF)
+		putc(c, fp);
+	fflush(fp);
+	if (ferror(op->src) || ferror(fp))
+		goto error_file;
+	fclose(fp);
+
+	/* TODO: set attributes */
+	return;
+
+
+error_file:
+	perror("ar:error extracting file");
+	exit(1);
+}
+
+static void
 print(struct arop *op, char *files[])
 {
 	long siz;
@@ -219,11 +251,7 @@
 		return;
 	if (vflag)
 		printf("\n<%s>\n\n", op->fname);
-	siz = atol(op->hdr.ar_size);
-	if (siz < 0) {
-		fputs("ar:corrupted member\n", stderr);
-		exit(1);
-	}
+	siz = op->size;
 	while (siz-- > 0 && (c = getc(op->src)) != EOF)
 		putchar(c);
 }
@@ -264,7 +292,7 @@
 {
 	if (inlist(op->fname, files))
 		return;
-	copymember(op->fname, &op->hdr, op->dst, op->src);
+	copy(op->fname, &op->hdr, op->dst, op->src);
 }
 
 static char *
@@ -292,11 +320,9 @@
 	op.dst = tmp;
 	while (!ferror(fp) && fread(&op.hdr, sizeof(op.hdr), 1, fp) == 1) {
 		fpos_t pos;
-		long len;
-		char *fname;
 
 		if (strncmp(op.hdr.ar_fmag, ARFMAG, sizeof(op.hdr.ar_fmag)) ||
-		    (len = atol(op.hdr.ar_size)) < 0) {
+		    (op.size = atol(op.hdr.ar_size)) < 0) {
 			fputs("ar:corrupted member\n", stderr);
 			exit(1);
 		}
@@ -304,7 +330,7 @@
 		fgetpos(fp, &pos);
 		(*fun)(&op, files);
 		fsetpos(fp, &pos);
-		fseek(fp, len+1 & ~1, SEEK_CUR);
+		fseek(fp, op.size+1 & ~1, SEEK_CUR);
 	}
 	if (ferror(fp)) {
 		perror("ar:reading members");
@@ -472,9 +498,13 @@
 	case 'p':
 		tmp = NULL;
 		fun = print;
+		break;
+	case 'x':
+		tmp = NULL;
+		fun = extract;
+		break;
 	case 'r':
 	case 'm':
-	case 'x':
 		/* TODO */
 		;
 	}