ref: 0bea8c5077c0ed1f2c61ce65f0b8f14eed89eca3
parent: 95e151ee065ec25ae3bab2b8a74a8529e72f5ee8
author: Roberto E. Vargas Caballero <[email protected]>
date: Tue Feb 13 05:04:24 EST 2018
[ar] Add -d flag This flag removes files from the archive. This is not a tested version, but it is good base version.
--- a/ar/main.c
+++ b/ar/main.c
@@ -1,6 +1,7 @@
static char sccsid[] = "@(#) ./ar/main.c";
#include <errno.h>
+#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -15,17 +16,30 @@
char *argv0;
static int bflag, iflag, vflag, cflag, lflag, uflag, aflag;
-static int done;
-static char *afile, *posname;
+static char *afile, *posname, *tmpafile;
+struct arop {
+ FILE *src;
+ FILE *dst;
+ struct ar_hdr hdr;
+ char *fname;
+};
+
static void
cleanup(void)
{
- if (!done)
- remove(afile);
+ if (tmpafile)
+ remove(tmpafile);
}
static void
+sigfun(int signum)
+{
+ cleanup();
+ exit(1);
+}
+
+static void
usage(void)
{
fputs("ar [-drqtpmx][posname] [-vuaibcl] [posname] afile name ...\n", stderr);
@@ -42,7 +56,7 @@
if ((fp = fopen(afile,"rb")) == NULL) {
if (!cflag)
fprintf(stderr, "ar: creating %s\n", afile);
- if ((fopen(afile, "w+b")) == NULL)
+ if ((fp = fopen(afile, "w+b")) == NULL)
goto file_error;
fputs(ARMAG, fp);
fflush(fp);
@@ -49,7 +63,7 @@
} else {
if (fgets(magic, sizeof(magic), fp) == NULL)
goto file_error;
- if (!strcmp(magic, ARMAG)) {
+ if (strcmp(magic, ARMAG)) {
fprintf(stderr,
"ar:%s:invalid magic number '%s'\n",
afile,
@@ -75,6 +89,8 @@
char mtime[13];
struct stat st;
+ if (vflag)
+ printf("a - %s\n", fname);
if (strlen(fname) > 16)
fprintf(stderr, "ar:%s: too long name\n", fname);
if (stat(fname, &st) < 0) {
@@ -119,13 +135,146 @@
perror("ar:seeking archive");
exit(1);
}
- while ((fname = *list++) != NULL) {
- if (vflag)
- printf("a - %s\n", fname);
+ while ((fname = *list++) != NULL)
archieve(fname, fp);
+ if (fclose(fp) == EOF) {
+ perror("ar:error writing archive");
+ exit(1);
}
}
+static void
+copymember(char *fname, struct ar_hdr *hdr, FILE *dst, FILE *src)
+{
+ int c;
+ long siz, n;
+
+ if (vflag)
+ printf("a - %s\n", fname);
+ fwrite(&hdr, sizeof(hdr), 1, dst);
+ siz = atol(hdr->ar_size);
+ if (siz < 0) {
+ fprintf(stderr, "ar:corrupted member header '%s'\n", fname);
+ exit(1);
+ }
+ if ((siz & 1) == 1)
+ siz++;
+ while (siz--) {
+ if ((c = getc(src)) == EOF)
+ break;
+ fputc(c, dst);
+ }
+ if (ferror(src)) {
+ perror("ar:writing temporary");
+ exit(1);
+ }
+}
+
+static void
+delmembers(struct arop *op, char *files[])
+{
+ char **bp;
+
+ for (bp = files; *bp && strcmp(*bp, op->fname); ++bp)
+ ;
+ if (*bp)
+ return;
+ copymember(op->fname, &op->hdr, op->dst, op->src);
+}
+
+static char *
+getfname(struct ar_hdr *hdr)
+{
+ static char fname[FILENAME_MAX];
+ size_t i;
+ char *bp = fname;
+
+ for (i = 0; i < sizeof(hdr->ar_name); i++) {
+ if ((*bp = hdr->ar_name[i]) == ' ')
+ break;
+ ++bp;
+ }
+ *bp = '\0';
+ return fname;
+}
+
+static void
+run(FILE *fp, char *files[], void (*fun)(struct arop *, char *files[]))
+{
+ FILE *tmp;
+ struct arop op;
+
+ if (*files == NULL)
+ return;
+
+ if (lflag) {
+ tmpafile = "ar.tmp";
+ tmp = fopen(tmpafile, "wb");
+ } else {
+ tmp = tmpfile();
+ }
+ if (tmp == NULL) {
+ perror("ar:creating temporary");
+ exit(1);
+ }
+ fputs(ARMAG, tmp);
+
+ op.src = fp;
+ 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) {
+ fputs("ar:corrupted member\n", stderr);
+ exit(1);
+ }
+ op.fname = getfname(&op.hdr);
+ fgetpos(fp, &pos);
+ (*fun)(&op, files);
+ fsetpos(fp, &pos);
+ fseek(fp, len+1 & ~1, SEEK_CUR);
+ }
+ fflush(tmp);
+ if (ferror(fp)) {
+ perror("ar:reading members");
+ exit(1);
+ }
+ if (ferror(tmp)) {
+ perror("ar:writing members");
+ exit(1);
+ }
+
+ fclose(fp);
+ if (tmpafile) {
+ fclose(tmp);
+ if (rename(tmpafile, afile) < 0) {
+ perror("ar:renaming temporary");
+ exit(1);
+ }
+ tmpafile;
+ } else {
+ int c;
+
+ if ((fp = fopen(afile, "wb")) == NULL) {
+ perror("ar:reopening archive file");
+ exit(1);
+ }
+ rewind(tmp);
+ while ((c = getc(tmp)) != EOF)
+ fputc(c, tmp);
+ fflush(fp);
+ if (ferror(fp) || ferror(tmp)) {
+ perror("ar:copying from temporary");
+ exit(1);
+ }
+ fclose(fp);
+ fclose(tmp);
+ }
+}
+
int
main(int argc, char *argv[])
{
@@ -161,7 +310,6 @@
nkey++;
key = 'x';
break;
-
case 'a':
aflag = 1;
pos++;
@@ -195,6 +343,11 @@
if (nkey == 0 || nkey > 1 || pos > 1 || argc == 0)
usage();
+
+ signal(SIGINT, sigfun);
+ signal(SIGQUIT, sigfun);
+ signal(SIGTERM, sigfun);
+
afile = *argv++;
fp = openar(afile);
@@ -203,6 +356,8 @@
append(fp, argv);
break;
case 'd':
+ run(fp, argv, delmembers);
+ break;
case 'r':
case 't':
case 'p':
@@ -212,15 +367,5 @@
;
}
- if (ferror(fp)) {
- perror("ar:error reading archive");
- exit(1);
- }
-
-
- /* TODO: check status of stdout */
- done = 1;
-
return 0;
-
}