/* SYSDEP.VMS - System Dependent Routines for VAX/VMS Copyright 1989-90 Lawrence J. Jones; All Rights Reserved */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "arc.h" static void setstamp PROTO((FILE *, unsigned, unsigned)); void clsfil(f, name, date, time) FILE *f; char *name; unsigned date, time; { if (name) setstamp(f, date, time); fclose(f); } void getstamp(f, date, time) FILE *f; unsigned short *date, *time; { struct stat stbuf; struct tm *tmptr; fstat(fileno(f), &stbuf); tmptr = localtime(&stbuf.st_ctime); *date = (tmptr->tm_year - 80) << 9 | (tmptr->tm_mon + 1) << 5 | tmptr->tm_mday; *time = tmptr->tm_hour << 11 | tmptr->tm_min << 5 | tmptr->tm_sec >> 1; } static void setstamp(f, dt, tm) FILE *f; unsigned dt, tm; { struct stat stbuf; unsigned short chan, iosb[4], yy, mm, dd; unsigned long status, h, m, s, *pr; static struct dsc$descriptor devdsc = { 0, DSC$K_DTYPE_T, DSC$K_CLASS_S, NULL }; static struct fibdef fib; static struct dsc$descriptor fibdsc = { sizeof fib, DSC$K_DTYPE_T, DSC$K_CLASS_S, (char *)&fib }; static unsigned long vmstime[2]; static struct atrdef atrlst[] = { { sizeof vmstime, ATR$C_CREDATE, (unsigned long)vmstime }, { 0, 0, 0 } }; static const long tps = 10000000; /* clock ticks per second */ static const long zero = 0; static const unsigned long basetime[2] = /* 1-JAN-1980 00:00:00 */ { 0x58824000, 0x0087cb28 }; static const unsigned short k[12] = /* cumulative days per month */ { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 }; /* convert date & time to number of seconds since 1-JAN-1980 */ 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; s += 60 * (m + 60 * (h + 24 * dd)); /* now for the hard part: we need to convert from seconds since * 1-JAN-1980 to a VMS quadword time. First we need to convert * seconds to clock ticks which requires multiplying two unsigned * longwords to produce an unsigned quadword -- unfortunately the * VAX doesn't have any instructions which do this. Fortunately, * neither quad should have the top bit set, so we just cheat and * do a signed multiply instead. Once we get the number of ticks, * we can just add it to the base time to get the VMS equivalent * of the original time. */ LIB$EMUL(&s, &tps, &zero, vmstime); /* convert to clock ticks */ LIB$ADDX(basetime, vmstime, vmstime); /* add base (ignore overflow) */ fstat(fileno(f), &stbuf); devdsc.dsc$w_length = strlen(stbuf.st_dev); devdsc.dsc$a_pointer = stbuf.st_dev; status = SYS$ASSIGN(&devdsc, &chan, 0, 0); if (!(status & STS$M_SUCCESS)) { LIB$SIGNAL(status); return; } fib.fib$r_fid_overlay.fib$w_fid[0] = stbuf.st_ino[0]; fib.fib$r_fid_overlay.fib$w_fid[1] = stbuf.st_ino[1]; fib.fib$r_fid_overlay.fib$w_fid[2] = stbuf.st_ino[2]; status = SYS$QIOW(0, chan, IO$_MODIFY, iosb, 0, 0, &fibdsc, 0, 0, 0, atrlst, 0); if (!(status & STS$M_SUCCESS)) LIB$SIGNAL(status); if (!(iosb[0] & STS$M_SUCCESS)) LIB$SIGNAL(iosb[0]); status = SYS$DASSGN(chan); if (!(status & STS$M_SUCCESS)) LIB$SIGNAL(status); } 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; { long stv, status; char *result; static struct dsc$descriptor inpdsc = { 0, DSC$K_DTYPE_T, DSC$K_CLASS_S, 0 }; static struct dsc$descriptor outdsc = { 0, DSC$K_DTYPE_T, DSC$K_CLASS_D, 0 }; static long ctx = 0; if (filename) { inpdsc.dsc$w_length = strlen(filename); inpdsc.dsc$a_pointer = filename; } status = LIB$FIND_FILE(&inpdsc, &outdsc, &ctx, 0, 0, &stv, &2); if (!(status & STS$M_SUCCESS)) { if (status != RMS$_NMF && status != RMS$_FNF) LIB$SIGNAL(status, stv); return NULL; } if (result = malloc(outdsc.dsc$w_length + 1)) { memcpy(result, outdsc.dsc$a_pointer, outdsc.dsc$w_length); result[outdsc.dsc$w_length] = '\0'; } return result; } void rempath(nargs,arg) int nargs; char *arg[]; { char *q, *basename(); int n; for (n = 0; n < nargs; n++) arg[n] = basename(arg[n]); } char *strupr(s) char *s; { struct dsc$descriptor strdes; static struct dsc$descriptor stopc = {1, DSC$K_DTYPE_T, DSC$K_CLASS_S, ""}; static struct dsc$descriptor trans = {256, DSC$K_DTYPE_T, DSC$K_CLASS_S, 0}; globalref char LIB$AB_UPCASE[256]; strdes.dsc$w_length = 65535; strdes.dsc$b_dtype = DSC$K_DTYPE_T; strdes.dsc$b_class = DSC$K_CLASS_S; strdes.dsc$a_pointer = s; trans.dsc$a_pointer = LIB$AB_UPCASE; for (;;) { if (LIB$MOVTUC(&strdes, &stopc, &trans, &strdes) != 0) break; strdes.dsc$a_pointer += strdes.dsc$w_length; } return s; } char *makefnam(f, d, r) char *f, *d, *r; { struct FAB fab; struct NAM nam; long status; fab = cc$rms_fab; nam = cc$rms_nam; fab.fab$l_nam = &nam; fab.fab$l_fna = f; fab.fab$l_dna = d; fab.fab$b_fns = strlen(f); fab.fab$b_dns = strlen(d); nam.nam$b_ess = STRLEN; nam.nam$l_esa = r; status = SYS$PARSE(&fab); if (!(status & STS$M_SUCCESS)) { LIB$SIGNAL(fab.fab$l_sts, fab.fab$l_stv); nam.nam$b_esl = 0; } r[nam.nam$b_esl] = '\0'; return r; } char *basename(p) char *p; { char *q; struct FAB fab; struct NAM nam; long status; char buf[NAM$C_MAXRSS]; fab = cc$rms_fab; nam = cc$rms_nam; fab.fab$l_nam = &nam; fab.fab$l_fna = p; fab.fab$b_fns = strlen(p); fab.fab$l_dna = "*.*"; fab.fab$b_dns = 3; nam.nam$b_ess = sizeof buf; nam.nam$l_esa = buf; status = SYS$PARSE(&fab); if (!(status & STS$M_SUCCESS)) LIB$SIGNAL(fab.fab$l_sts, fab.fab$l_stv); if (nam.nam$b_name > 8) nam.nam$b_name = 8; if (nam.nam$b_type > 4) nam.nam$b_type = 4; p = q = malloc(nam.nam$b_name + nam.nam$b_type + 1); memcpy(q, nam.nam$l_name, nam.nam$b_name); q += nam.nam$b_name; memcpy(q, nam.nam$l_type, nam.nam$b_type); q += nam.nam$b_type; *q = '\0'; return p; } 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; { 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 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); }