#include #include #include #include #include #include #include #include #include #include #include "arc.h" static void setstamp PROTO((char *, unsigned, unsigned)); static char *strlwr PROTO((char *)); static void putlong PROTO((long, FILE *)); static void putint PROTO((int, FILE *)); extern int access PROTO((const char *, int)); extern int link PROTO((const char *, const char *)); extern long lseek PROTO((int, long, int)); extern int pclose PROTO((FILE *)); extern FILE *popen PROTO((const char *, const char *)); extern int read PROTO((int, char *, unsigned)); extern int write PROTO((int, const char *, unsigned)); void clsfil(f, name, date, time) FILE *f; char *name; unsigned date, time; { fclose(f); if (name) setstamp(name, date, time); } void getstamp(f, dt, tm) FILE *f; unsigned short *dt, *tm; { struct stat stbuf; struct tm *tmptr; if (fstat(fileno(f), &stbuf) != 0) { perror("Unable to getstamp"); stbuf.st_mtime = time(NULL); } tmptr = localtime(&stbuf.st_mtime); *dt = (tmptr->tm_year - 80) << 9 | (tmptr->tm_mon + 1) << 5 | tmptr->tm_mday; *tm = tmptr->tm_hour << 11 | tmptr->tm_min << 5 | tmptr->tm_sec >> 1; } static void setstamp(name, dt, tm) char *name; unsigned dt, tm; { struct utimbuf utb; unsigned yy, mm, dd; unsigned long h, m, s; static int k[12] = /* cumulative days per month */ { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 }; extern long timezone; tzset(); utb.actime = time(NULL); dd = (dt & 0x1f) - 1; mm = ((dt >>= 5) & 0x0f) - 1; yy = dt >> 4; dd += 365 * yy + (yy + 3) / 4 + (yy % 4 == 0 && mm > 2) + k[mm]; s = (tm & 0x1f) << 1; m = (tm >>= 5) & 0x3f; h = tm >> 6; utb.modtime = timezone + s + 60L * (m + 60L * (h + 24L * (dd + 3652))); if (utime(name, &utb) != 0) perror("Unable to setstamp"); } void fatal(a, b, c, d, e, f) const char *a; int b, c, d, e, f; { printf(a, b, c, d, e, f); exit(EXIT_FAILURE); } char *dir(filename) char *filename; { char *result; int len; char buf[256]; static char cmd[] = "for i in %s; do if [ -f $i ]; then echo $i; fi; done"; static FILE *ptr; if (filename) { if (ptr) pclose(ptr); sprintf(buf, cmd, filename); ptr = popen(buf, "r"); } if (!ptr) return NULL; if (fgets(buf, sizeof buf, ptr) == NULL) { pclose(ptr); ptr = NULL; return NULL; } len = strlen(buf); buf[len - 1] = '\0'; /* get rid of newline */ if (!(result = malloc(len))) fatal("Out of memory"); memcpy(result, buf, len); return result; } void rempath(nargs, arg) int nargs; char *arg[]; { int n; for (n = 0; n < nargs; n++) arg[n] = basename(arg[n]); } char *strupr(s) char *s; { register unsigned char *p; for (p = (unsigned char *)s; *p; p++) *p = toupper(*p); return s; } static char *strlwr(s) char *s; { register unsigned char *p; for (p = (unsigned char *)s; *p; p++) *p = tolower(*p); return s; } char *makefnam(f, d, res) char *f, *d, *res; { register char *p, *q, *r; register int len; r = res; len = 0; if ((q = strrchr(d, '/')) != NULL) /* if there's a path in d ... */ { p = d; /* remember it */ len = ++q - d; /* and its length */ d = q; /* and skip over it */ } if ((q = strrchr(f, '/')) != NULL) /* if there's a path in f ... */ { p = f; /* it supercedes any from d */ len = ++q - f; f = q; } if (len > 0) /* if there's a path anywere ... */ { memcpy(r, p, len); /* put it in the result */ r += len; len = 0; } if ((q = strrchr(d, '.')) != d) /* if there's a name in d ... */ { p = d; len = q ? q - d : strlen(d); d = q; } if ((q = strrchr(f, '.')) != f) /* if there's a name in f ... */ { p = f; len = q ? q - f : strlen(f); f = q; } q = r; /* remember where the name starts */ if (len > 0) /* if there's a name anywhere ... */ { memcpy(r, p, len); r += len; len = 0; } if (d) /* if there's an extension in d ... */ { p = d; len = strlen(d); } if (f) /* if there's an extension in f ... */ { p = f; len = strlen(f); } if (len > 0) /* if there's an extension anywhere ... */ { memcpy(r, p, len); r += len; len = 0; } *r = '\0'; strlwr(q); /* convert name to lower case per tradition */ return res; } char *basename(p) char *p; { char *q, *res; int len; if (!(res = malloc(FNLEN))) fatal("Out of memory"); if (q = strrchr(p, '/')) p = q + 1; len = (q = strrchr(p, '.')) != NULL ? q - p : strlen(p); if (len > 8) len = 8; memcpy(res, p, len); res[len] = '\0'; for (p = res; (p = strchr(p, '.')) != NULL; *p++ = '_') ; if (q) { strncpy(res + len, q, 4); res[len + 4] = '\0'; } for (p = res; *p; p++) if (iscntrl(*p)) *p = '_'; strupr(res); return res; } FILE *opnfilwr(p) char *p; { FILE *f; char buf[STRLEN]; if (f = fopen(p, image ? "rb" : "r")) { fclose(f); printf("WARNING: File %s already exists!", p); do { printf(" Overwrite it (y/n)? "); fgets(buf, STRLEN, stdin); *buf = toupper(*buf); if (*buf == 'N') { printf("%s not extracted.\n", p); return NULL; } } while (*buf != 'Y'); } if (!(f = fopen(p, image ? "wb" : "w")) && warn) { perror(p); nerrs++; } return f; } int getfilch(f) FILE *f; { int c; static int nl = 0; if (nl) { nl = 0; return '\n'; } if (nl = ((c = getc(f)) == '\n' && !image)) c = '\r'; return c; } int putfilch(c, f) int c; FILE *f; { static int nl = 0; if (nl && c != '\n') putc('\r', f); if (!image && (nl = (c == '\r'))) return c; return putc(c & 0xff, f); } int readhdr(hdr, f) struct heads *hdr; FILE *f; { unsigned char c1, c2, c3, c4; int try = 0; static int first = 1; if (!f || feof(f)) return 0; if (getc(f) != ARCMARK) { if (warn) { printf("An entry in %s has a bad header.",arcname); nerrs++; } while(!feof(f)) { try++; if (getc(f) == ARCMARK) { ungetc(hdrver = getc(f), f); if (hdrver >= 0 && hdrver <= ARCVER) break; } } if (feof(f) && first) fatal("%s is not an archive", arcname); if (warn) { if (changing) fatal("%s is corrupted -- changes disallowed", arcname); printf(" %d bytes skipped.\n", try); } if (feof(f)) return 0; } hdrver = getc(f); if (hdrver < 0) fatal("Invalid header in archive %s", arcname); if (hdrver == 0) return 0; if (hdrver > ARCVER) { fread(hdr->name, FNLEN, 1, f); printf("I don't know how to handle file %s in archive %s\n", hdr->name, arcname); printf("I think you need a newer version of ARC.\n"); exit(EXIT_FAILURE); } fread(hdr->name, FNLEN, 1, f); c1 = getc(f), c2 = getc(f), c3 = getc(f), c4 = getc(f); hdr->size = (((((c4 << 8) | c3) << 8) | c2) << 8) | c1; c1 = getc(f), c2 = getc(f); hdr->date = (c2 << 8) | c1; c1 = getc(f), c2 = getc(f); hdr->time = (c2 << 8) | c1; c1 = getc(f), c2 = getc(f); hdr->crc = (c2 << 8) | c1; if (hdrver == 1) { hdrver = 2; hdr->length = hdr->size; } else { c1 = getc(f), c2 = getc(f), c3 = getc(f), c4 = getc(f); hdr->length = (((((c4 << 8) | c3) << 8) | c2) << 8) | c1; } if (hdr->date > olddate || (hdr->date == olddate && hdr->time > oldtime)) { olddate = hdr->date; oldtime = hdr->time; } first = 0; return 1; } void writehdr(hdr, f) struct heads *hdr; FILE *f; { putc(ARCMARK, f); putc(hdrver, f); if (!hdrver) return; fwrite(hdr->name, FNLEN, 1, f); putlong(hdr->size, f); putint(hdr->date, f); putint(hdr->time, f); putint(hdr->crc, f); putlong(hdr->length, f); if (hdr->date > arcdate || (hdr->date == arcdate && hdr->time > arctime)) { arcdate = hdr->date; arctime = hdr->time; } } static void putlong(l, f) long l; FILE *f; { putc(l & 0xff, f); l >>= 8; putc(l & 0xff, f); l >>= 8; putc(l & 0xff, f); l >>= 8; putc(l & 0xff, f); } static void putint(l, f) int l; FILE *f; { putc(l & 0xff, f); l >>= 8; putc(l & 0xff, f); } void filecopy(f, t, size) FILE *f, *t; long size; { char *buf; unsigned int bufl; unsigned int cpy; bufl = size > 60000 ? size : 60000; while (!(buf = malloc(bufl))) if ((bufl >>= 1) == 0) fatal("Out of memory"); lseek(fileno(f), ftell(f), SEEK_SET); fflush(f); fflush(t); while (size > 0) { cpy = read(fileno(f), buf, size < bufl ? size : bufl); if (cpy <= 0) fatal("Read fail"); if (write(fileno(t), buf, cpy) != cpy) fatal("Write fail (disk full?)"); size -= (long)cpy; } free(buf); } int rename(old, new) const char *old, *new; { register int ret; if ((ret = link(old, new)) != 0) { if (errno != EEXIST || access(new, W_OK) != 0) return -1; unlink(new); if ((ret = link(old, new)) != 0) return ret; } if ((ret = unlink(old)) != 0) unlink(new); return ret; }