/* ARC - Archive utility - SYSDEP.C Copyright 1989 Lawrence J. Jones; All Rights Reserved Description: This file contains certain DOS level routines that assist in doing fancy things with an archive, primarily reading and setting the date and time last modified. These are, by nature, system dependant functions. But they are also, by nature, very expendable. Language: Microsoft C */ #include #include #include #include #include #include #include "arc.h" static void runfile PROTO((struct heads *, int, char **)); void fatal(fmt, ...) char *fmt; { va_list arg; va_start(arg, fmt); vprintf(fmt, arg); va_end(arg); exit(EXIT_FAILURE); } char *dir(filename) char *filename; { char *result, *p, *q; static int first = 1; static char *path; static int pathlen; static struct find_t ff_area; if (filename) { if (_dos_findfirst(filename, _A_NORMAL, &ff_area) != 0) return NULL; p = filename; if (q = strrchr(p, '/')) p = q + 1; if (q = strrchr(p, '\\')) p = q + 1; if (q = strrchr(p, ':')) p = q + 1; pathlen = p - filename; if (!(path = malloc(pathlen))) fatal("Out of memory"); memcpy(path, filename, pathlen); } else if (first) return NULL; else if (_dos_findnext(&ff_area) != 0) { free(path); return NULL; } first = 0; result = malloc(pathlen + strlen(ff_area.name) + 1); memcpy(result, path, pathlen); strcpy(result + pathlen, ff_area.name); return result; } void rempath(nargs, arg) int nargs; char *arg[]; { int n; for (n = 0; n < nargs; n++) arg[n] = basename(arg[n]); } char *makefnam(f, d, r) char *f, *d, *r; { char drive[2][_MAX_DRIVE]; char dir[2][_MAX_DIR]; char name[2][_MAX_FNAME]; char ext[2][_MAX_EXT]; _splitpath(f, drive[0], dir[0], name[0], ext[0]); _splitpath(d, drive[1], dir[1], name[1], ext[1]); if (drive[0][0] == '\0') strcpy(drive[0], drive[1]); if (dir[0][0] == '\0') strcpy(dir[0], dir[1]); if (name[0][0] == '\0') strcpy(name[0], name[1]); if (ext[0][0] == '\0') strcpy(ext[0], ext[1]); _makepath(r, drive[0], dir[0], name[0], ext[0]); return r; } char *basename(p) char *p; { char *q; if (q = strrchr(p, '/')) p = q + 1; if (q = strrchr(p, '\\')) p = q + 1; if (q = strrchr(p, ':')) p = q + 1; if (!(q = malloc(strlen(p) + 1))) fatal("Out of memory"); strcpy(q, p); return q; } FILE *opnfilwr(p) char *p; { FILE *f; char buf[STRLEN]; if (f = fopen(p, "rb")) { fclose(f); printf("WARNING: File %s already exists!", p); do { printf(" Overwrite it (y/n)? "); fgets(buf, STRLEN, stdin); *buf = (char)toupper(*buf); if (*buf == 'N') { printf("%s not extracted.\n", p); return NULL; } } while (*buf != 'Y'); } if (!(f = fopen(p, "wb")) && warn) { perror(p); nerrs++; } return f; } void runarc(num, arg) int num; char *arg[]; { struct heads hdr; char buf[STRLEN]; rempath(num,arg); openarc(0); if (num > 0) { while (readhdr(&hdr, arc)) { if (match(hdr.name, makefnam(arg[0], ".*", buf))) runfile(&hdr, num, &arg[1]); else fseek(arc, hdr.size, 1); } } else { while (readhdr(&hdr, arc)) runfile(&hdr, 0, NULL); } closearc(0); } static void runfile(hdr, num, arg) struct heads *hdr; int num; char *arg[]; { FILE *tmp; char buf[STRLEN], sys[STRLEN], *dir; int n; makefnam("$ARCTEMP", hdr->name, buf); if (strcmp(buf,"$ARCTEMP.BAS") == 0) strcpy(sys, "BASICA $ARCTEMP"); else if(strcmp(buf, "$ARCTEMP.BAT") == 0 || strcmp(buf, "$ARCTEMP.COM") == 0 || strcmp(buf, "$ARCTEMP.EXE") == 0) strcpy(sys, "$ARCTEMP"); else { if (warn) { printf("File %s is not a .BAS, .BAT, .COM, or .EXE\n", hdr->name); nerrs++; } fseek(arc, hdr->size, 1); return; } if (warn && (tmp = fopen(buf, "rb")) != NULL) fatal("Temporary file %s already exists", buf); if ((tmp=opnfilwr(buf)) == NULL) fatal("Unable to create temporary file %s", buf); if (note) printf("Invoking file: %s\n", hdr->name); for (n = 0; n < num; n++) { strcat(sys, " "); strcat(sys, arg[n]); } dir = getcwd(NULL, 0); unpack(arc, tmp, hdr); fclose(tmp); system(sys); chdir(dir); free(dir); if (remove(buf) && warn) { printf("Cannot remove temporary file %s\n", buf); nerrs++; } } int readhdr(hdr, f) struct heads *hdr; FILE *f; { char name[FNLEN]; 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 (changing && warn) fatal("%s is corrupted -- changes disallowed", arcname); if (warn) 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(name, 1, FNLEN, f); printf("I don't know how to handle file %s in archive %s\n", name, arcname); printf("I think you need a newer version of ARC.\n"); exit(EXIT_FAILURE); } if (hdrver == 1) { fread(hdr, sizeof (struct heads) - sizeof (long), 1, f); hdrver = 2; hdr->length = hdr->size; } else fread(hdr, sizeof (struct heads), 1, f); 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 == 0) return; fwrite(hdr, sizeof (struct heads), 1, f); if (hdr->date > arcdate || (hdr->date == arcdate && hdr->time > arctime)) { arcdate = hdr->date; arctime = hdr->time; } } void filecopy(f, t, size) FILE *f, *t; long size; { char *buf; unsigned int bufl; unsigned int bytr, bytw; lseek(fileno(f), ftell(f), SEEK_SET); fflush(f); fflush(t); bufl = coreleft(); if (bufl > size) bufl = size; if (bufl > 60000) bufl = 60000; while (!(buf = malloc(bufl))) if ((bufl >>= 1) == 0) fatal("Out of memory"); while (size > 0) { if (_dos_read(fileno(f), buf, size < bufl ? size : bufl, &bytr) != 0 || bytr == 0) fatal("Read fail"); if (_dos_write(fileno(t), buf, bytr, &bytw) != 0 || bytw != bytr) fatal("Write fail (disk full?)"); size -= bytr; } free(buf); }