shithub: scc

Download patch

ref: 73a6628e17cff58f721f995f3ce533432e6703fe
parent: f3d06fb5d6fc6d3540f693f883c90c50141fc6f1
author: Roberto E. Vargas Caballero <k0ga@shike2.com>
date: Thu Feb 15 17:31:40 EST 2018

[ar] Improve -m implementation

This implementation should worl, but it is not tested
and a lot of different things would happen.

--- a/ar/main.c
+++ b/ar/main.c
@@ -21,6 +21,7 @@
 struct arop {
 	FILE *src;
 	FILE *dst;
+	FILE *tmp;
 	struct ar_hdr hdr;
 	char *fname;
 	long size;
@@ -144,20 +145,33 @@
 }
 
 static void
-copy(struct arop *op)
+cat(FILE *src1, FILE *src2, FILE *dst)
 {
 	int c;
-	long siz, n;
-	struct ar_hdr *hdr = &op->hdr;
 
-	fwrite(hdr, sizeof(*hdr), 1, op->dst);
-	siz = op->size;
+	while ((c = getc(src1)) != EOF)
+		fputc(c, dst);
+	while ((c = getc(src2)) != EOF)
+		fputc(c, dst);
+	if (ferror(src1) || ferror(src2) || fclose(dst) == EOF) {
+		perror("ar:moving files in archive");
+		exit(1);
+	}
+}
+
+static void
+copy(struct ar_hdr *hdr, long siz, FILE *src, FILE *dst)
+{
+	int c;
+	long n;
+
+	fwrite(hdr, sizeof(*hdr), 1, dst);
 	if ((siz & 1) == 1)
 		siz++;
 	while (siz--) {
-		if ((c = getc(op->src)) == EOF)
+		if ((c = getc(src)) == EOF)
 			break;
-		fputc(c, op->dst);
+		fputc(c, dst);
 	}
 }
 
@@ -200,8 +214,18 @@
 }
 
 static void
-filter(struct arop *op, char *list[])
+split(struct arop *op, char *files[])
 {
+	char **l;
+
+	l = inlist(op->fname, files);
+	if (!l) {
+		copy(&op->hdr, op->size, op->src, op->dst);
+		return;
+	} else {
+		copy(&op->hdr, op->size, op->src, op->tmp);
+		rmlist(l);
+	}
 }
 
 static void
@@ -213,15 +237,15 @@
 insert(struct arop *op, char *list[])
 {
 	if (!posname || strcmp(op->fname, posname)) {
-		copy(op);
+		copy(&op->hdr, op->size, op->src, op->dst);
 		return;
 	}
 	if (bflag || iflag) {
 		for ( ; *list; ++list)
 			archive(*list, op->dst, 'a');
-		copy(op);
+		copy(&op->hdr, op->size, op->src, op->dst);
 	} else {
-		copy(op);
+		copy(&op->hdr, op->size, op->src, op->dst);
 		for ( ; *list; ++list)
 			archive(*list, op->dst, 'a');
 	}
@@ -234,7 +258,7 @@
 
 	l = inlist(op->fname, files);
 	if (!l) {
-		copy(op);
+		copy(&op->hdr, op->size, op->src, op->dst);
 		return;
 	}
 	archive(op->fname, op->dst, 'r');
@@ -321,7 +345,7 @@
 			printf("d - %s\n", op->fname);
 		return;
 	}
-	copy(op);
+	copy(&op->hdr, op->size, op->src, op->dst);
 }
 
 static char *
@@ -389,6 +413,7 @@
 
 	op.src = fp;
 	op.dst = tmp1;
+	op.dst = tmp2;
 	while (!ferror(fp) && fread(&op.hdr, sizeof(op.hdr), 1, fp) == 1) {
 		fpos_t pos;
 
@@ -456,7 +481,7 @@
 
 	if (lflag) {
 		*dst = fname;
-		tmp = fopen(fname, "wb");
+		tmp = fopen(fname, "w+b");
 	} else {
 		tmp = tmpfile();
 	}
@@ -481,7 +506,7 @@
 {
 	int key, nkey = 0, pos = 0;
 	char *afile;
-	FILE *fp, *tmp1, *tmp2;;
+	FILE *fp, *tmp1, *tmp2;
 
 	atexit(cleanup);
 	ARGBEGIN {
@@ -602,9 +627,22 @@
 	case 'm':
 		tmp1 = opentmp("ar.tmp1", &tmpafile1);
 		tmp2 = opentmp("ar.tmp2", &tmpafile2);
-		run(fp, tmp1, NULL, argv, filter);
+		run(fp, tmp1, tmp2, argv, split);
+
+		if (*argv) {
+			fprintf(stderr, "ar: entry '%s' not found\n", *argv);
+			exit(1);
+		}
+		fp = openar(afile);
 		fseek(tmp1, SARMAG, SEEK_SET);
-		run(tmp1, tmp2, NULL, NULL, merge);
+		fseek(tmp2, SARMAG, SEEK_SET);
+		if (!posname) {
+			cat(tmp1, tmp2, fp);
+			break;
+		}
+		run(tmp1, fp, tmp2, NULL, merge);
+		closetmp(tmp1, &tmpafile1, NULL);
+		closetmp(tmp2, &tmpafile2, NULL);
 		break;
 	}