diff --git a/WEGA/src/cmd/dump.c b/WEGA/src/cmd/dump.c new file mode 100644 index 0000000..0364785 --- /dev/null +++ b/WEGA/src/cmd/dump.c @@ -0,0 +1,643 @@ +/* WEGA P8000 'dump' Version 25.11.87 */ +#define NI 16 +#define DIRPB (BSIZE/sizeof(struct direct)) +#define SEC 1 + +#include +#include +#include +#include +#include +#include +#include +#include +#include /* NTREC = 8 */ + +#define MWORD(m,i) (m[(unsigned)(i-1)/MLEN]) +#define MBIT(i) (1<<((unsigned)(i-1)%MLEN)) +#define BIS(i,w) (MWORD(w,i) |= MBIT(i)) +#define BIC(i,w) (MWORD(w,i) &= ~MBIT(i)) +#define BIT(i,w) (MWORD(w,i) & MBIT(i)) + +struct filsys sblock; +struct dinode itab[INOPB*NI]; +short clrmap[MSIZ], dirmap[MSIZ], nodmap[MSIZ]; + +char *hdisk, *archiv, *increm; +char incno; +int uflag, dflag, fi, to; +ino_t ino; +int nsubdir, narchiv, nadded, dadded; +int density = 160; +int timeout; + +char *ctime(), *prdate(); +long atol(); +int archivn, BLOCKS; +long tsize, esize, asize; +int mark(), add(), dump(), tapsrec(); +int dmpspc(), dsrch(), nullf(); + +#define HOUR (60L*60L) +#define DAY (24L*HOUR) +#define YEAR (365L*DAY) + +/* default: Disk.-Drive 1, cpi 96, double-sided, 9 sector */ +/* Typ 6 = rfd196ds9 (Blocklaenge : 512 Byte ) */ +/* (Blockanzahl : 1440 ) */ + +main(argc, argv) +char *argv[]; +{ + char *arg; + register i; + + time(&spcl.c_date); + + tsize = 2300L*12L*10L; + archiv = "/dev/dumpdev"; /* default: dump-Ziel dumpdev (rfd1) */ + hdisk = "/dev/rz"; /* default: dump-Quelle rz (rmd4) */ + increm = "/etc/ddate"; + incno = '9'; /* default: dump-level 0 */ + uflag = 0; + arg = "u"; /* default: Datum eintragen */ + if(argc > 1) { + argv++; + argc--; + arg = *argv; } + while(*arg) + switch (*arg++) { + + case 'f': + if(argc > 1) { + argv++; + argc--; + archiv = *argv; } + break; + + case 'd': + dflag++; + break; + + case 's': + if(argc > 1) { + argv++; + argc--; + tsize = atol(*argv); + tsize *= 12L*10L; } + break; + + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + incno = arg[-1]; + break; + + case 'u': + uflag++; + break; + + default: + printf("bad key '%c%'\n", arg[-1]); + usage(); + } + + if(argc > 1) { + argv++; + argc--; + hdisk = *argv; } + +if (dflag) printf("dump: Version 25.11.87\n"); + + getitime(); + printf(" date = %s\n", prdate(spcl.c_date)); + printf("dump date = %s\n", prdate(spcl.c_ddate)); + printf("dumping %s to %s\n", hdisk, archiv); + fi = open(hdisk, 0); + if(fi < 0) { + printf("dump: cannot open %s\n", hdisk); + exit(1); } + oarchiv(); + printf("I\n"); + esize = 0; + CLR(clrmap); + CLR(dirmap); + CLR(nodmap); + + pass(mark, (short *)NULL); + do { + printf("II\n"); + nadded = 0; + pass(add, dirmap); + } while(nadded); + + bmapest(clrmap); + bmapest(nodmap); + if (BLOCKS) printf("estimated %D disk blocks on %d disk", + esize, archivn = (int)(esize/BLOCKS)+1); + else printf("estimated %D archiv blocks on %d archiv", + esize, archivn = (int)(esize/tsize)+1); + if (archivn > 1) printf("s"); + printf("\n"); + + printf("III\n"); + bitmap(clrmap, TS_CLRI); + pass(dump, dirmap); + printf("IV\n"); + pass(dump, nodmap); + putitime(); + printf("DONE\n"); + spcl.c_type = TS_END; + for(i=0; i 1) printf("s"); + printf("\n"); +} + +printad() +{ + if (BLOCKS) printf("disk"); + else printf("archiv"); +} + +/* Hole BLOCKS ueber ioctl() */ +inBL() +{ +register i; + if (i=ioctl(to,SHOWFD,&BLOCKS)) BLOCKS = 0; +if (dflag && BLOCKS) fprintf(stderr, "tar: disk capacity %d blocks\n", BLOCKS); +} + +usage() +{ + printf("dump: usage dump [Lufs] [archivdev] [archivsize] [filesystem]\n"); + printf(" Level\(0,...,9\) _/ || \\_ set archiv size\n"); + printf(" update __/ \\__ give archiv device\n"); + exit(1); } + +pass(fn, map) +int (*fn)(); +short *map; +{ + register i, j; + int bits; + ino_t mino; + daddr_t d; + + sync(); + bread((daddr_t)1, (char *)&sblock, sizeof(sblock)); + mino = (sblock.s_isize-2) * INOPB; + ino = 0; + for(i=2;; i+=NI) { + if(ino >= mino) + break; + d = (unsigned)i; + for(j=0; j= mino) + break; + if((ino % MLEN) == 0) { + bits = ~0; + if(map != NULL) bits = *map++; } + ino++; + if(bits & 1) { + if(d != 0) { + bread(d, (char *)itab, sizeof(itab)); + d = 0; } + (*fn)(&itab[j]); } + bits >>= 1; + } + } +} + +icat(ip, fn1, fn2) +struct dinode *ip; +int (*fn1)(), (*fn2)(); +{ + register i; + daddr_t d[NADDR]; + + l3tol(&d[0], &ip->di_addr[0], NADDR); + (*fn2)(d, NADDR-3); + for(i=0; idi_mode & IFMT; + if(f == 0) + return; + BIS(ino, clrmap); + if(f == IFDIR) + BIS(ino, dirmap); + if(ip->di_mtime >= spcl.c_ddate || + ip->di_ctime >= spcl.c_ddate) { + BIS(ino, nodmap); + if (f != IFREG) + return; + est(ip); } +} + +add(ip) +struct dinode *ip; +{ + + if(BIT(ino, nodmap)) + return; + nsubdir = 0; + dadded = 0; + icat(ip, dsrch, nullf); + if(dadded) { + BIS(ino, nodmap); + est(ip); + nadded++; } + if(nsubdir == 0) + if(!BIT(ino, nodmap)) + BIC(ino, dirmap); +} + +dump(ip) +struct dinode *ip; +{ + register i; + + if(narchiv) { + narchiv = 0; + bitmap(nodmap, TS_BITS); } + BIC(ino, nodmap); + spcl.c_dinode = *ip; + spcl.c_type = TS_INODE; + spcl.c_count = 0; + i = ip->di_mode & IFMT; + if(i != IFDIR && i != IFREG) { + spclrec(); + return; } + icat(ip, tapsrec, dmpspc); +} + +dmpspc(dp, n) +daddr_t *dp; +{ + register i, t; + + spcl.c_count = n; + for(i=0; i "); + taprec(cp); + cp += BSIZE; } +} + +spclrec() +{ + register i, *ip, s; + + spcl.c_inumber = ino; + spcl.c_magic = MAGIC; + spcl.c_checksum = 0; + ip = (int *)&spcl; + s = 0; + for(i=0; i "); + taprec((char *)&spcl); +} + +dsrch(d) +daddr_t d; +{ + register char *cp; + register i; + register ino_t in; + struct direct dblk[DIRPB]; + + if(dadded) + return; + bread(d, (char *)dblk, sizeof(dblk)); + for(i=0; i= NTREC) flusht(); +} + +tapsrec(d) +daddr_t d; +{ + + if(d == 0) + return; + tdaddr[trecno] = d; + trecno++; + spcl.c_tapea++; +if (dflag == 2) printf("tapsrec"); +if (dflag == 2 && trecno >= NTREC) printf("\n"); +if (dflag == 2 && trecno < NTREC) printf("; "); + if(trecno >= NTREC) flusht(); +} + +flusht() +{ + int time_out(); + char place[100]; + register i, si; + daddr_t d; + + while(trecno < NTREC) + tdaddr[trecno++] = 1; + +loop: + d = 0; + for(i=0; i tsize) { + close(to); + signal(SIGALRM,time_out); + timeout=0; + alarm(SEC); + while (!timeout) getchar(); + alarm(0); + if (BLOCKS) printf("insert disk %d: ",spcl.c_volume+1); + else printf("change archiv : "); + read(0, place, sizeof(place)); + oarchiv(); } +} + +time_out() +{ + signal(SIGALRM,time_out); + timeout++; +} + +oarchiv() +{ + + nonex1: + if ((to = open(archiv, 1)) < 0) { + printf("dump: cannot open %s\n", archiv); + if (strcmp(archiv,"/dev/dumpdev") == 0) { + archiv = "/dev/rfd1"; + printf("dump: tries open %s\n", archiv); + goto nonex1; } + exit(1); } + inBL(); + if (BLOCKS) tsize = BLOCKS * 4; + asize = 0; + narchiv++; + spcl.c_volume++; + spcl.c_type = TS_TAPE; + spclrec(); +} + +char * +prdate(d) +time_t d; +{ + char *p; + + if(d == 0) + return("the epoch"); + p = ctime(&d); + p[24] = 0; + return(p); +} + +getitime() +{ + register i, df; + struct idates idbuf; + char *fname; + + fname = hdisk; +l1: + for(i=0; fname[i]; i++) + if(fname[i] == '/') { + fname += i+1; + goto l1; } + + spcl.c_ddate = 0; + + if ((df = open(increm, 2)) < 0) { + if ((df = creat(increm, 0600)) < 0) { + printf("dump: cannot open %s\n", increm); + printf(" You are superuser ???\n"); + exit(1); } } + +l2: + i = read(df, (char *)&idbuf, sizeof(idbuf)); + if(i != sizeof(idbuf)) { + close(df); + return; } + for(i=0;; i++) { + if(fname[i] != idbuf.id_name[i]) goto l2; + if(fname[i] == '\0') break; } + if(idbuf.id_incno >= incno) goto l2; + if(idbuf.id_ddate <= spcl.c_ddate) goto l2; + spcl.c_ddate = idbuf.id_ddate; + goto l2; +} + +putitime() +{ + register i, n, df; + struct idates idbuf; + char *fname; + + if(uflag == 0) + return; + fname = hdisk; +l1: + for(i=0; fname[i]; i++) + if(fname[i] == '/') { + fname += i+1; + goto l1; } + + spcl.c_ddate = 0; + df = open(increm, 2); + if(df < 0) { + printf("cannot open %s\n", increm); + exit(1); } + n = 0; +l2: + i = read(df, (char *)&idbuf, sizeof(idbuf)); + if(i != sizeof(idbuf)) goto l3; + n++; + for(i=0;; i++) { + if(fname[i] != idbuf.id_name[i]) goto l2; + if(fname[i] == '\0') break; } + if(idbuf.id_incno != incno) goto l2; +l3: + lseek(df, (long)n*sizeof(idbuf), 0); + for(i=0;; i++) { + idbuf.id_name[i] = fname[i]; + if(fname[i] == '\0') + break; } + idbuf.id_incno = incno; + idbuf.id_ddate = spcl.c_date; + write(df, (char *)&idbuf, sizeof(idbuf)); + close(df); + printf("level %c dump on %s\n", incno, prdate(spcl.c_date)); +} + +est(ip) +struct dinode *ip; +{ + long s; + + esize++; + s = (ip->di_size + BSIZE-1) / BSIZE; + esize += s; + if(s > NADDR-3) { + s -= NADDR-3; + s = (s + (BSIZE/sizeof(daddr_t))-1) / (BSIZE/sizeof(daddr_t)); + esize += s; } +} + +bmapest(map) +short *map; +{ + register i, n; + + n = -1; + for(i=0; i +#include +#include +#include +#include +#include +#include +#include +#include + +#define MWORD(m,i) (m[(unsigned)(i-1)/MLEN]) +#define MBIT(i) (1<<((unsigned)(i-1)%MLEN)) +#define BIS(i,w) (MWORD(w,i) |= MBIT(i)) +#define BIC(i,w) (MWORD(w,i) &= ~MBIT(i)) +#define BIT(i,w) (MWORD(w,i) & MBIT(i)) + +int fd; +char archiv[] = "/dev/dumpdev"; +char devrfd1[] = "/dev/rfd1"; +char *readfrom = archiv; + +daddr_t seekpt; +int ofile; +FILE *df; +char dirfile[] = "rstXXXXXX"; + +struct { + ino_t t_ino; + daddr_t t_seekpt; + } inotab[MAXINO]; +int ipos; + +#define ONTAPE 1 +#define XTRACTD 2 +#define XINUSE 4 + +short dumpmap[MSIZ]; /* MSIZ = 4096 */ +short clrimap[MSIZ]; + + +int bct = NTREC+1; +char tbf[NTREC*BSIZE]; + +char prebuf[512]; + +int dflag; +int BLOCKS, nblock; +int volno = 1; + +main(argc, argv) +char *argv[]; +{ + register char *cp; + extern char *ctime(); + + mktemp(dirfile); + argv++; + if (argc >= 2) { + argc -= 2; + for (cp = *argv++; *cp; cp++) { + switch (*cp) { + case 'd': + dflag++; + break; + case 'f': + readfrom = *argv++; + argc--; + break; + default: + printf("bad key '%c%'\n", *cp); + usage(); } } } + +if (dflag) printf("dumpdir: Version 6.11.87\n"); + + nonex: + if ((fd = open(readfrom, 0)) < 0) { + printf("dumpdir: cannot open %s\n", readfrom); + if (strcmp(readfrom,archiv) == 0) { + readfrom = devrfd1; + printf("dumpdir: tries open %s\n", readfrom); + goto nonex; } + exit(1); } + inBL(); + + if (readhdr(&spcl) == 0) { + printf("Not a dump-archiv\n"); + exit(1); } + + df = fopen(dirfile, "w"); + if (df == NULL) { + printf("dumpdir: %s - cannot create directory temporary\n", dirfile); + exit(1); } + + printf("Dump date: %s", ctime(&spcl.c_date)); + printf("Dumped from: %s", ctime(&spcl.c_ddate)); + if (checkvol(&spcl, 1) == 0) { + printf("Tape is not volume 1 of the dump\n"); + exit(1); } + pass1(); /* This sets the various maps on the way by */ + freopen(dirfile, "r", df); + strcpy(prebuf, "/"); + printem(prebuf, (ino_t) 2); + unlink(dirfile); + exit(0); +} + +usage() +{ + printf("dumpdir: usage dumpdir [f archivdev]\n"); + exit(1); +} + +/* Hole BLOCKS ueber ioctl() */ +inBL() +{ +register i; + if (i=ioctl(fd,SHOWFD,&BLOCKS)) BLOCKS = 0; +if (dflag && BLOCKS) fprintf(stderr, "tar: disk capacity %d blocks\n", BLOCKS); +} + +/* + * Read the archiv, bulding up a directory structure for extraction + * by name + */ +pass1() +{ + register i; + struct dinode *ip; + int putdir(), null(); + + while (gethead(&spcl) == 0) { + printf("Can't find directory header!\n"); } + for (;;) { + if (checktype(&spcl, TS_BITS) == 1) { + readbits(dumpmap); + continue; } + if (checktype(&spcl, TS_CLRI) == 1) { + readbits(clrimap); + continue; } + if (checktype(&spcl, TS_INODE) == 0) { + finish: + fflush(df); + close(fd); + return; } + ip = &spcl.c_dinode; + i = ip->di_mode & IFMT; + if (i != IFDIR) goto finish; + inotab[ipos].t_ino = spcl.c_inumber; + inotab[ipos++].t_seekpt = seekpt; + getfile(spcl.c_inumber, putdir, null, spcl.c_dinode.di_size); + putent("\000\000/"); + } +} + +printem(prefix, inum) +char *prefix; +ino_t inum; +{ + struct direct dir; + register int i; + + for (i = 0; i < MAXINO; i++) + if (inotab[i].t_ino == inum) goto found; + printf("PANIC - can't find directory %d\n", inum); + return; + found: + mseek(inotab[i].t_seekpt); + for (;;) { + getent((char *) &dir); + if (direq(dir.d_name, "/")) + return; + if (search(dir.d_ino) != 0 && + direq(dir.d_name, ".") == 0 && + direq(dir.d_name, "..") == 0) { + int len; + FILE *tdf; + + tdf = df; + df = fopen(dirfile, "r"); + len = strlen(prefix); + strncat(prefix, dir.d_name, sizeof(dir.d_name)); + strcat(prefix, "/"); + printem(prefix, dir.d_ino); + prefix[len] = '\0'; + fclose(df); + df = tdf; + } + else + if (BIT(dir.d_ino, dumpmap)) + printf("%5d %s%-.14s\n", dir.d_ino, prefix, dir.d_name); + } +} +/* + * Do the file extraction, calling the supplied functions + * with the blocks + */ +getfile(n, f1, f2, size) +ino_t n; +int (*f2)(), (*f1)(); +long size; +{ + register i; + struct spcl addrbl; + char buf[BSIZE]; + + addrbl = spcl; + goto start; + for (;;) { + if (gethead(&addrbl) == 0) { + printf("Missing address (header) block\n"); + goto eloop; } + if (checktype(&addrbl, TS_ADDR) == 0) { + spcl = addrbl; + return; } + start: + for (i = 0; i < addrbl.c_count; i++) { + if (addrbl.c_block.c_addr[i]) { + readarchiv(buf); + (*f1)(buf, size > BSIZE ? (long) BSIZE : size); } + else { + clearbuf(buf); + (*f2)(buf, size > BSIZE ? (long) BSIZE : size); } + if ((size -= BSIZE) <= 0) { + eloop: + while (gethead(&spcl) == 0) ; + if (checktype(&spcl, TS_ADDR) == 1) + goto eloop; + return; } + } + } +} + +/* + * Do the archiv i\/o, dealling with volume changes + * etc.. + */ +readarchiv(b) +char *b; +{ + register i; + struct spcl tmpbuf; + + if (bct >= NTREC) { + for (i = 0; i < NTREC; i++) + ((struct spcl *)&tbf[i*BSIZE])->c_magic = 0; + bct = 0; + if (BLOCKS && nblock < BLOCKS) + if ((i = read(fd, tbf, NTREC*BSIZE)) < 0) exit(1); +if (dflag > 1 && BLOCKS) printf("Ich las Block %d bis %d\n",nblock*NTREC,(nblock+1)*NTREC-1); + nblock++; + if (i == 0 || (BLOCKS && nblock > BLOCKS)) { + bct = NTREC+1; + volno++; + loop: + bct = NTREC+1; /* ehemals: flsht(); */ + close(fd); + nblock = 0; + if (BLOCKS) printf("insert disk %d : ",volno); + else printf("change archiv %d : ", volno); + while (getchar() != '\n') ; + if ((fd = open(readfrom, 0)) == -1) + printf("Cannot open archiv!\n"); + if (readhdr(&tmpbuf) == 0) { + printf("Not a dump-archiv. Try again\n"); + goto loop; } + if (checkvol(&tmpbuf, volno) == 0) { + printf("Wrong archiv. Try again\n"); + goto loop; } + readarchiv(b); + return; } + } + copy(&tbf[(bct++*BSIZE)], b, BSIZE); +} + +copy(f, t, s) +register char *f, *t; +{ + register i; + + i = s; + do *t++ = *f++; while (--i); +} + +clearbuf(cp) +register char *cp; +{ + register i; + + i = BSIZE; + do *cp++ = 0; while (--i); +} + +/* + * Put and get the directory entries from the compressed + * directory file + */ +putent(cp) +char *cp; +{ + register i; + + for (i = 0; i < sizeof(ino_t); i++) + writec(*cp++); + for (i = 0; i < DIRSIZ; i++) { + writec(*cp); + if (*cp++ == 0) return; } +} + +getent(bf) +register char *bf; +{ + register i; + + for (i = 0; i < sizeof(ino_t); i++) + *bf++ = readc(); + for (i = 0; i < DIRSIZ; i++) + if ((*bf++ = readc()) == 0) + return; +} + +/* + * read/write te directory file + */ +writec(c) +char c; +{ + seekpt++; + fwrite(&c, 1, 1, df); +} + +readc() +{ + char c; + + fread(&c, 1, 1, df); + return(c); +} + +mseek(pt) +daddr_t pt; +{ + fseek(df, pt, 0); +} + +/* + * search the directory inode ino + * looking for entry cp + */ +search(inum) +ino_t inum; +{ + register low, high, probe; + + low = 0; + high = ipos-1; + + while (low != high) { + probe = (high - low + 1)/2 + low; +/* +printf("low = %d, high = %d, probe = %d, ino = %d, inum = %d\n", low, high, probe, inum, inotab[probe].t_ino); +*/ + if (inum >= inotab[probe].t_ino) + low = probe; + else + high = probe - 1; } + return(inum == inotab[low].t_ino); +} + +direq(s1, s2) +register char *s1, *s2; +{ + register i; + + for (i = 0; i < DIRSIZ; i++) + if (*s1++ == *s2) { + if (*s2++ == 0) + return(1); } + else return(0); + return(1); +} + +/* + * read the archiv into buf, then return whether or + * or not it is a header block. + */ +gethead(buf) +struct spcl *buf; +{ + readarchiv((char *)buf); + if (buf->c_magic != MAGIC || checksum((int *) buf) == 0) + return(0); + return(1); +} + +/* + * return whether or not the buffer contains a header block + */ +checktype(b, t) +struct spcl *b; +int t; +{ + return(b->c_type == t); +} + + +checksum(b) +int *b; +{ + register i, j; + + j = BSIZE/sizeof(int); + i = 0; + do i += *b++; while (--j); + if (i != CHECKSUM) { + printf("Checksum error %o\n", i); + return(0); } + return(1); +} + +checkvol(b, t) +struct spcl *b; +int t; +{ + if (b->c_volume == t) return(1); + return(0); +} + +readhdr(b) +struct spcl *b; +{ + if (gethead(b) == 0) return(0); + if (checktype(b, TS_TAPE) == 0) return(0); + return(1); +} + +putdir(b) +char *b; +{ + register struct direct *dp; + register i; + + for (dp = (struct direct *)b, i = 0; i < BSIZE; dp++, i += sizeof(*dp)) { + if (dp->d_ino == 0) + continue; + putent((char *) dp); } +} + +/* + * read a bit mask from the archiv into m. + */ +readbits(m) +short *m; +{ + register i; + + i = spcl.c_count; + + while (i--) { + readarchiv((char *) m); + m += (BSIZE/(MLEN/BITS)); } + while (gethead(&spcl) == 0) ; +} + +null() { ; } diff --git a/WEGA/src/cmd/getud.c b/WEGA/src/cmd/getud.c new file mode 100644 index 0000000..f4325dc --- /dev/null +++ b/WEGA/src/cmd/getud.c @@ -0,0 +1,237 @@ +/* getud P8000 - Datei Laden von 8-Bit-Teil unter UDOS */ + +#define SOH 0x01 /* ascii start-of-header character */ +#define STX 0x02 /* ascii start-of-text character */ +#define ETX 0x03 /* ascii end-of-text character */ +#define EOT 0x04 /* ascii end-of-transmission character */ +#define ACK 0x06 /* ascii acknowledge character */ +#define NAK 0x15 /* ascii non-acknowledge character */ +#define CAN 0x18 /* ascii cancel character (ctrl-x) */ +#define ESC 0x1b /* ascii escape character */ +#define RETRIES 3 /* number of allowable transmission errors */ +#define XFER_SIZE 64 /* max number of characters sent as a block */ +#define CMODE 0644 /* creation mode for transmitted files */ + +#define BINARY 0x01 /* flag byte bit settings */ +#define FATAL 0x04 +#define ALLBIN 0x08 + +#include +#include + +char bufw[20], bufr[2]; +int dd, k; + +char c, acknak, checksum, buffer[XFER_SIZE]; +int high_count, low_count; +int i, j, n_to_read, n_written, fd, tflags, success, unsuccess; + +int verbose=0; +int del=0; +int del_pro(); + +char *fname; +char flags = 0; + +main (argc, argv) + +int argc; +char **argv; + +{ + + signal(SIGINT, del_pro); /* Interrupt-Signal (DEL-Taste) einfangen */ + signal(SIGHUP, SIG_IGN); /* weitere Signale ignorieren */ + signal(SIGQUIT,SIG_IGN); + signal(SIGILL, SIG_IGN); + signal(SIGTRAP,SIG_IGN); + signal(SIGIOT, SIG_IGN); + signal(SIGSEGV,SIG_IGN); + signal(SIGSYS, SIG_IGN); + signal(SIGPIPE,SIG_IGN); + signal(SIGALRM,SIG_IGN); + signal(SIGTERM,SIG_IGN); + + if((dd=open("/dev/ud",2))==-1) { + printf("\nunable to open /dev/ud\n"); goto ende; } + + while (--argc > 0) /* process all command line args */ + { + if ((*++argv)[0] == '-') /* test for command line option */ + switch ((*argv)[1]) + { + case 'b': + flags |= BINARY; /* set binary file type */ + break; + case 'f': + flags |= FATAL; /* udos-procedure file */ + break; + case 'B': + flags |= ALLBIN; /* all files are binary */ + break; + case 'v': + verbose = 1; + break; + } + else /* argument is a file name */ + { + bufw[0]='S'; write(dd,bufw,1); + read(dd,bufr,1); acknak=bufr[0]; + acknak &= 0177; + + if (flags & ALLBIN) /* set binary if all files binary */ + flags |= BINARY; + bufw[0]=flags; write(dd,bufw,1); + read(dd,bufr,1); acknak=bufr[0]; + acknak &= 0177; + + checksum = 0; /* compute checksum to send */ + fname = *argv; /* pointer to file name */ + for (; **argv; (*argv)++) /* loop until end of name string */ + if (**argv == '/') /* strip path name from string */ + { + fname = *argv; /* fname points to char after '/' */ + fname++; + checksum = 0; /* start checksum over */ + } + else + checksum ^= **argv; /* checksum is xor of filename chars */ + acknak = NAK; /* no acknowledge so far */ + + /* send the filename first and get an ACK. Try RETRIES times */ + + for (i=0; i +#include +#include + +struct stat stbuf; + +char bufw[20], bufr[2]; +int dd, k; + +char acknak, checksum, buffer[XFER_SIZE], high_count, low_count; +int i, n_read, fd, tflags, success, unsuccess; + +int verbose=0; +int del=0; +int del_pro(); + +char *fname; +char flags = 0; + +main (argc, argv) + +int argc; +char **argv; + +{ + + signal(SIGINT, del_pro); /* Interrupt-Signal (DEL-Taste) einfangen */ + signal(SIGHUP, SIG_IGN); /* weitere Signale ignorieren */ + signal(SIGQUIT,SIG_IGN); + signal(SIGILL, SIG_IGN); + signal(SIGTRAP,SIG_IGN); + signal(SIGIOT, SIG_IGN); + signal(SIGSEGV,SIG_IGN); + signal(SIGSYS, SIG_IGN); + signal(SIGPIPE,SIG_IGN); + signal(SIGALRM,SIG_IGN); + signal(SIGTERM,SIG_IGN); + + if((dd=open("/dev/ud",2))==-1) + {printf("\nunable to open /dev/ud\n");goto ende;} + + while (--argc > 0) /* process all command line args */ + { + if ((*++argv)[0] == '-') /* test for command line option */ + switch ((*argv)[1]) + { + case 'b': + flags |= BINARY; /* set binary file type */ + break; + case 'f': + flags |= FATAL; /* udos-procedure file */ + break; + case 'B': /* all files are binary */ + flags |= ALLBIN; + break; + case 'v': + verbose = 1; + break; + } + else /* argument is a file name */ + { + if ((fd = open(*argv, 0)) == -1) /* open file and test for error */ + printf ("\n%s unable to open file\n", *argv); + else /* file was opened with no error */ + { + fstat (fd, &stbuf); /* is the file executable? */ + if (stbuf.st_mode & S_IEXEC) + flags |= EXEC; /* if yes, set executable bit */ + + if(stbuf.st_size == 0L) + printf("\nfile %s has length of zero\n",*argv); + else + { + bufw[0]='L';write(dd,bufw,1); + read(dd,bufr,1); acknak=bufr[0]; + acknak &= 0177; + + if (flags & ALLBIN) /* set binary if all files binary */ + flags |= BINARY; + bufw[0]=flags; write(dd,bufw,1); + read(dd,bufr,1); acknak=bufr[0]; + acknak &= 0177; + + checksum = 0; /* compute checksum to send */ + fname = *argv; /* pointer to file name */ + for (; **argv; (*argv)++) /* loop until end of name string */ + if (**argv == '/') /* strip path name from string */ + { + fname = *argv; /* fname points to char after '/' */ + fname++; + checksum = 0; /* start checksum over */ + } + else + checksum ^= **argv; /* checksum is xor of filename chars */ + acknak = NAK; /* no acknowledge so far */ + + /* send the filename first and get an ACK. Try RETRIES times */ + + for (i=0; i 0) + { + high_count = n_read/256; /* compute the two bytes containing */ + low_count = n_read - (high_count*256); /* the data length */ + acknak = NAK; /* no acknowledge so far */ + checksum = 0; /* compute checksum to send */ + for (i=0; i +#include +#include +#endif +#include +#include +#include +#include +#include +#include +#include + +#define MWORD(m,i) (m[(unsigned)(i-1)/MLEN]) +#define MBIT(i) (1<<((unsigned)(i-1)%MLEN)) +#define BIS(i,w) (MWORD(w,i) |= MBIT(i)) +#define BIC(i,w) (MWORD(w,i) &= ~MBIT(i)) +#define BIT(i,w) (MWORD(w,i) & MBIT(i)) + +struct filsys sblock; + +int timeout; +int fi; +ino_t ino, maxi, curino; + +/* default: Disk.-Drive 1, cpi 96, double-sided, 9 sector */ +/* Typ 6 = rfd196ds9 (Blocklaenge : 512 Byte ) */ +/* (Blockanzahl : 1440 ) */ + +int fd; +char archiv[] = "/dev/dumpdev"; +char devrfd1[] = "/dev/rfd1"; +char *readfrom = archiv; +#ifdef STANDALONE +char mbuf[50]; +#endif + +#ifndef STANDALONE +daddr_t seekpt; +int df, ofile; +char dirfile[] = "rstXXXXXX"; + +struct { + ino_t t_ino; + daddr_t t_seekpt; +} inotab[MAXINO]; +int ipos; + +#define ONTAPE 1 +#define XTRACTD 2 +#define XINUSE 4 +struct xtrlist { + ino_t x_ino; + char x_flags; +} xtrlist[MAXXTR]; + +char name[12]; + +char drblock[BSIZE]; +int bpt; +#endif + +int eflag, dflag; +int BLOCKS, nblock; + +int volno = 1; + +struct dinode tino, dino; +daddr_t taddr[NADDR]; + +daddr_t curbno; + +short dumpmap[MSIZ]; /* MSIZ = 4096 */ +short clrimap[MSIZ]; + + +int bct = NTREC+1; +char tbf[NTREC*BSIZE]; + +struct cache { + daddr_t c_bno; + int c_time; + char c_block[BSIZE]; +} cache[NCACHE]; +int curcache; + +main(argc, argv) +char *argv[]; +{ + register char *cp; + char command; + int done(); + +#ifndef STANDALONE + mktemp(dirfile); + if (argc < 2) usage(); + argv++; + argc -= 2; + for (cp = *argv++; *cp; cp++) { + switch (*cp) { + case '-': + break; + case 'f': + readfrom = *argv++; + argc--; + break; + case 'd': + dflag++; + break; + case 'r': + case 'R': + case 't': + case 'x': + command = *cp; + break; + default: + printf("bad key '%c'%\n", *cp); + usage(); } } + +if (dflag) printf("restor: Version 25.11.87\n"); + + if (command == 'x') { + if (signal(SIGINT, done) == SIG_IGN) + signal(SIGINT, SIG_IGN); + if (signal(SIGTERM, done) == SIG_IGN) + signal(SIGTERM, SIG_IGN); + + df = creat(dirfile, 0666); + if (df < 0) { + printf("restor: %s - cannot create directory temporary\n", dirfile); + exit(1); } + close(df); + df = open(dirfile, 2); } + doit(command, argc, argv); + if (command == 'x') + unlink(dirfile); + exit(0); +#else + readfrom = "archiv"; + doit('r', 1, 0); +#endif +} + +/* Hole BLOCKS ueber ioctl() */ +inBL() +{ +register i; + if (i=ioctl(fd,SHOWFD,&BLOCKS)) BLOCKS = 0; +if (dflag && BLOCKS) fprintf(stderr, "tar: disk capacity %d blocks\n", BLOCKS); +} + +usage() +{ + printf("restor: usage restor [-][frRxt] [archivdev] [filesystem] [name]\n"); + printf(" give archiv device _/ ||| \\_ display date of archiv\n"); + printf(" give filesystem __/ | \\__ extract named files\n"); + printf(" 'r' with start from any archiv-volume\n"); + exit(1); } + +doit(command, argc, argv) +char command; +int argc; +char *argv[]; +{ + extern char *ctime(); + register i, k; + ino_t d; +#ifndef STANDALONE + int xtrfile(), skip(); +#endif + int rstrfile(), rstrskip(); + struct dinode *ip, *ip1; + +#ifndef STANDALONE + nonex1: + if ((fd = open(readfrom, 0)) < 0) { + printf("restor: cannot open %s\n", readfrom); + if (strcmp(readfrom,archiv) == 0) { + readfrom = devrfd1; + printf("restor: tries open %s\n", readfrom); + goto nonex1; } + exit(1); } + inBL(); + if (BLOCKS) BLOCKS = BLOCKS / NTREC; /* NTREC = 8 */ +#else + do { + printf("Archiv : "); + gets(mbuf); + fd = open(mbuf, 0); + } while (fd == -1); + readfrom = mbuf; +#endif + switch(command) { +#ifndef STANDALONE + case 't': + if (readhdr(&spcl) == 0) { + printf("Not a dump-archiv\n"); + exit(1); } + printf("Dump date: %s", ctime(&spcl.c_date)); + printf("Dumped from: %s", ctime(&spcl.c_ddate)); + return; + case 'x': + if (readhdr(&spcl) == 0) { + printf("Not a dump-archiv\n"); + exit(1); } + if (checkvol(&spcl, 1) == 0) { + printf("Not volume 1 of the dump\n"); + exit(1); } + pass1(); /* This sets the various maps on the way by */ + i = 0; + while (i < MAXXTR-1 && argc--) { + if ((d = psearch(*argv)) == 0 || BIT(d, dumpmap) == 0) { + printf("%s: not on the archiv\n", *argv++); + continue; } + xtrlist[i].x_ino = d; + xtrlist[i].x_flags |= XINUSE; + printf("%s: inode %u\n", *argv, d); + argv++; + i++; } +newvol: + bct = NTREC+1; + close(fd); +getvol: + printf("Mount desired archiv volume: Specify volume #: "); + if (gets(tbf) == NULL) + return; + volno = atoi(tbf); + if (volno <= 0) { + printf("Volume numbers are positive numerics\n"); + goto getvol; } + fd = open(readfrom, 0); + if (readhdr(&spcl) == 0) { + printf("Not a dump-archiv\n"); + goto newvol; } + if (checkvol(&spcl, volno) == 0) { + printf("Wrong volume (%d)\n", spcl.c_volume); + goto newvol; } +rbits: + while (gethead(&spcl) == 0) ; + if (checktype(&spcl, TS_INODE) == 1) { + printf("Can't find inode mask!\n"); + goto newvol; } + if (checktype(&spcl, TS_BITS) == 0) + goto rbits; + readbits(dumpmap); + i = 0; + for (k = 0; xtrlist[k].x_flags; k++) { + if (BIT(xtrlist[k].x_ino, dumpmap)) { + xtrlist[k].x_flags |= ONTAPE; + i++; } } + while (i > 0) { +again: + if (ishead(&spcl) == 0) + while(gethead(&spcl) == 0) + ; + if (checktype(&spcl, TS_END) == 1) { + printf("End of archiv\n"); +checkdone: + for (k = 0; xtrlist[k].x_flags; k++) + if ((xtrlist[k].x_flags&XTRACTD) == 0) + goto newvol; + return; } + if (checktype(&spcl, TS_INODE) == 0) { + gethead(&spcl); + goto again; } + d = spcl.c_inumber; + for (k = 0; xtrlist[k].x_flags; k++) { + if (d == xtrlist[k].x_ino) { + printf("extract file %u\n", xtrlist[k].x_ino); + sprintf(name, "%u", xtrlist[k].x_ino); + if ((ofile = creat(name, 0666)) < 0) { + printf("%s: cannot create file\n", name); + i--; + continue; } + chown(name, spcl.c_dinode.di_uid, spcl.c_dinode.di_gid); + getfile(ino, xtrfile, skip, spcl.c_dinode.di_size); + i--; + xtrlist[k].x_flags |= XTRACTD; + close(ofile); + goto done; } } + gethead(&spcl); +done: + ; + } + goto checkdone; +#endif + case 'r': + case 'R': +#ifndef STANDALONE + if ((fi = open(*argv, 2)) < 0) { + printf("%s: cannot open\n", *argv); + exit(1); } +#else + do { + char charbuf[50]; + + printf("Disk : "); + gets(charbuf); + fi = open(charbuf, 2); + } while (fi == -1); +#endif +#ifndef STANDALONE + if (command == 'R') { + printf("Enter starting volume number: "); + if (gets(tbf) == NULL) { + volno = 1; + printf("\n"); } + else + volno = atoi(tbf); } + else +#endif + volno = 1; + printf("Last chance before scribbling on %s : ", +#ifdef STANDALONE + "winchester"); +#else + *argv); +#endif + while (getchar() != '\n'); + dread((daddr_t)1, (char *)&sblock, sizeof(sblock)); + maxi = (sblock.s_isize-2)*INOPB; + if (readhdr(&spcl) == 0) { + printf("Missing volume record\n"); + exit(1); } + if (checkvol(&spcl, volno) == 0) { + printf("Archiv is not volume %d\n", volno); + exit(1); } + gethead(&spcl); + for (;;) { +ragain: + if (ishead(&spcl) == 0) { + printf("Missing header block\n"); + while (gethead(&spcl) == 0) + ; + eflag++; } + if (checktype(&spcl, TS_END) == 1) { + printf("End of archiv\n"); + close(fd); + dwrite( (daddr_t) 1, (char *) &sblock); + return; } + if (checktype(&spcl, TS_CLRI) == 1) { +if (dflag > 1) printf("\"doit\('r'\)\" TS_CLRI ruft \"readbits\"\n"); + readbits(clrimap); + printf("One moment please.\n"); + for (ino = 1; ino <= maxi; ino++) + if (BIT(ino, clrimap) == 0) { + getdino(ino, &tino); + if (tino.di_mode == 0) + continue; + itrunc(&tino); + clri(&tino); + putdino(ino, &tino); } + dwrite( (daddr_t) 1, (char *) &sblock); + goto ragain; + } + if (checktype(&spcl, TS_BITS) == 1) { +if (dflag > 1) printf("\"doit\('r'\)\" TS_BITS ruft \"readbits\"\n"); + readbits(dumpmap); + goto ragain; } + if (checktype(&spcl, TS_INODE) == 0) { + printf("Unknown header type\n"); + eflag++; + gethead(&spcl); + goto ragain; } + ino = spcl.c_inumber; + if (eflag) + printf("Resynced at inode %u\n", ino); + eflag = 0; + if (ino > maxi) { + printf("%u: ilist too small\n", ino); + gethead(&spcl); + goto ragain; } + dino = spcl.c_dinode; + getdino(ino, &tino); + curbno = 0; + itrunc(&tino); + clri(&tino); + for (i = 0; i < NADDR; i++) + taddr[i] = 0; + l3tol(taddr, dino.di_addr, 1); +if (dflag > 1) printf("Lese Disk-File mit Inode %u\n",ino); + getfile(ino, rstrfile, rstrskip, dino.di_size); + ip = &tino; + ltol3(ip->di_addr, taddr, NADDR); + ip1 = &dino; + ip->di_mode = ip1->di_mode; + ip->di_nlink = ip1->di_nlink; + ip->di_uid = ip1->di_uid; + ip->di_gid = ip1->di_gid; + ip->di_size = ip1->di_size; + ip->di_atime = ip1->di_atime; + ip->di_mtime = ip1->di_mtime; + ip->di_ctime = ip1->di_ctime; + putdino(ino, &tino); + } + } +} + +/* + * Read the archiv, bulding up a directory structure for extraction + * by name + */ +#ifndef STANDALONE +pass1() +{ + register i; + struct dinode *ip; + int putdir(), null(); + + while (gethead(&spcl) == 0) { + printf("Can't find directory header!\n"); } + for (;;) { + if (checktype(&spcl, TS_CLRI) == 1) { + readbits(clrimap); + continue; } + if (checktype(&spcl, TS_BITS) == 1) { + readbits(dumpmap); + continue; } + if (checktype(&spcl, TS_INODE) == 0) { +finish: + write(df, drblock, bpt+1); /* flsh() */ + close(fd); + return; } + ip = &spcl.c_dinode; + i = ip->di_mode & IFMT; + if (i != IFDIR) goto finish; + inotab[ipos].t_ino = spcl.c_inumber; + inotab[ipos++].t_seekpt = seekpt; + getfile(spcl.c_inumber, putdir, null, spcl.c_dinode.di_size); + putent("\000\000/"); + } +} +#endif + +/* + * Do the file extraction, calling the supplied functions + * with the blocks + */ +getfile(n, f1, f2, size) +ino_t n; +int (*f2)(), (*f1)(); +long size; +{ + register i; + struct spcl spclbl; + char buf[BSIZE]; + + spclbl = spcl; + curino = n; + goto start; + for (;;) { + if (gethead(&spclbl) == 0) { + printf("Missing address (header) block\n"); + goto eloop; } + if (checktype(&spclbl, TS_ADDR) == 0) { + spcl = spclbl; + curino = 0; + return; } + start: + for (i = 0; i < spclbl.c_count; i++) { + if (spclbl.c_block.c_addr[i]) { + readarchiv(buf); + (*f1)(buf, size > BSIZE ? (long) BSIZE : size); + } + else { + clearbuf(buf); + (*f2)(buf, size > BSIZE ? (long) BSIZE : size); + } + if ((size -= BSIZE) <= 0) { + eloop: + while (gethead(&spcl) == 0) ; + if (checktype(&spcl, TS_ADDR) == 1) + goto eloop; + curino = 0; + return; } } + } +} + +readarchiv(b) +char *b; +{ + int time_out(); + register i; + struct spcl tmpbuf; + + if (bct >= NTREC) { + for (i = 0; i < NTREC; i++) + ((struct spcl *)&tbf[i*BSIZE])->c_magic = 0; + bct = 0; + if (BLOCKS && nblock < BLOCKS) + if ((i = read(fd, tbf, NTREC*BSIZE)) < 0) { + printf("Archiv read error: inode %u\n", curino); + eflag++; + for (i = 0; i < NTREC; i++) + clearbuf(&tbf[i*BSIZE]); } +if ((dflag > 1) && (BLOCKS && nblock < BLOCKS)) printf("Lese Block %d bis %d\n",nblock*NTREC, (nblock+1)*NTREC-1); + nblock++; + if ((i == 0) || (BLOCKS && nblock > BLOCKS)) { +if (dflag > 1) printf("i = %d, BLOCKS(%d) < nblock(%d)\n",i,BLOCKS,nblock); + bct = NTREC + 1; + volno++; +loop: + bct = NTREC+1; + close(fd); + nblock = 0; + signal(SIGALRM,time_out); + alarm(SEC); + timeout=0; + while (!timeout) getchar(); + alarm(0); + if (BLOCKS) printf("insert disk %d : ",volno); + else printf("change archiv %d : ", volno); + while (getchar() != '\n') ; + if ((fd = open(readfrom, 0)) == -1) { + printf("Cannot open archiv!\n"); + goto loop; } + if (readhdr(&tmpbuf) == 0) { + printf("Not a dump-archiv. Try again\n"); + goto loop; } + if (checkvol(&tmpbuf, volno) == 0) { + printf("Wrong archiv. Try again\n"); + goto loop; } + readarchiv(b); + return; } + } + copy(&tbf[(bct++*BSIZE)], b, BSIZE); +} + +time_out() +{ + signal(SIGALRM,time_out); + timeout++; +} + +copy(f, t, s) +register char *f, *t; +{ + register i; + + i = s; + do + *t++ = *f++; + while (--i); +} + +clearbuf(cp) +register char *cp; +{ + register i; + + i = BSIZE; + do + *cp++ = 0; + while (--i); +} + +/* + * Put and get the directory entries from the compressed + * directory file + */ +#ifndef STANDALONE +putent(cp) +char *cp; +{ + register i; + + for (i = 0; i < sizeof(ino_t); i++) + writec(*cp++); + for (i = 0; i < DIRSIZ; i++) { + writec(*cp); + if (*cp++ == 0) return; } + return; +} + +/* Nur fuer search */ +getent(bf) +register char *bf; +{ + register i; + + for (i = 0; i < sizeof(ino_t); i++) + *bf++ = readc(); + for (i = 0; i < DIRSIZ; i++) + if ((*bf++ = readc()) == 0) return; + return; +} + +/* + * read/write te directory file + */ +/* Nur fuer putent */ +writec(c) +char c; +{ + drblock[bpt++] = c; + seekpt++; + if (bpt >= BSIZE) { + bpt = 0; + write(df, drblock, BSIZE); } +} + +/* Nur fuer getent */ +readc() +{ + if (bpt >= BSIZE) { + read(df, drblock, BSIZE); + bpt = 0; } + return(drblock[bpt++]); +} + +mseek(pt) +daddr_t pt; +{ + bpt = BSIZE; + lseek(df, pt, 0); +} + +/* + * search the directory inode ino + * looking for entry cp + */ +/* Nur fuer psearch */ +ino_t +search(inum, cp) +ino_t inum; +char *cp; +{ + register i; + struct direct dir; + + for (i = 0; i < MAXINO; i++) + if (inotab[i].t_ino == inum) goto found; + return(0); +found: + mseek(inotab[i].t_seekpt); + do { + getent((char *)&dir); + if (direq(dir.d_name, "/")) return(0); + } while (direq(dir.d_name, cp) == 0); + return(dir.d_ino); +} + +/* + * Search the directory tree rooted at inode 2 + * for the path pointed at by n + * Nur fuer doit('x') + */ +psearch(n) +char *n; +{ + register char *cp, *cp1; + char c; + + ino = 2; + if (*(cp = n) == '/') + cp++; +next: + cp1 = cp + 1; + while (*cp1 != '/' && *cp1) + cp1++; + c = *cp1; + *cp1 = 0; + ino = search(ino, cp); + if (ino == 0) { + *cp1 = c; + return(0); } + *cp1 = c; + if (c == '/') { + cp = cp1+1; + goto next; } + return(ino); +} + +direq(s1, s2) +register char *s1, *s2; +{ + register i; + + for (i = 0; i < DIRSIZ; i++) + if (*s1++ == *s2) + if (*s2++ == 0) return(1); + else return(0); + return(1); +} +#endif + +/* + * read/write a winchester block, be sure to update the buffer + * cache if needed. + */ +dwrite(bno, b) +daddr_t bno; +char *b; +{ + register i; + + for (i = 0; i < NCACHE; i++) { + if (cache[i].c_bno == bno) { + copy(b, cache[i].c_block, BSIZE); + cache[i].c_time = 0; + break; } + else + cache[i].c_time++; } + lseek(fi, bno*BSIZE, 0); + if(write(fi, b, BSIZE) != BSIZE) { +#ifdef STANDALONE + printf("winchester write error %D\n", bno); +#else + fprintf(stderr, "winchester write error %ld\n", bno); +#endif + exit(1); + } +} + +dread(bno, buf, cnt) +daddr_t bno; +char *buf; +{ + register i, j; + + j = 0; + for (i = 0; i < NCACHE; i++) { + if (++curcache >= NCACHE) + curcache = 0; + if (cache[curcache].c_bno == bno) { + copy(cache[curcache].c_block, buf, cnt); + cache[curcache].c_time = 0; + return; + } + else { + cache[curcache].c_time++; + if (cache[j].c_time < cache[curcache].c_time) + j = curcache; + } + } + + lseek(fi, bno*BSIZE, 0); + if (read(fi, cache[j].c_block, BSIZE) != BSIZE) { +#ifdef STANDALONE + printf("read error %D\n", bno); +#else + printf("read error %ld\n", bno); +#endif + exit(1); + } + copy(cache[j].c_block, buf, cnt); + cache[j].c_time = 0; + cache[j].c_bno = bno; +} + +/* + * the inode manpulation routines. Like the system. + * + * clri zeros the inode + */ +clri(ip) +struct dinode *ip; +{ + int i, *p; + i = sizeof(struct dinode)/sizeof(int); + p = (int *)ip; + do + *p++ = 0; + while(--i); +} + +/* + * itrunc/tloop/bfree free all of the blocks pointed at by the inode + */ +itrunc(ip) +register struct dinode *ip; +{ + register i; + daddr_t bn, iaddr[NADDR]; + + if (ip->di_mode == 0) + return; + i = ip->di_mode & IFMT; + if (i != IFDIR && i != IFREG) + return; + l3tol(iaddr, ip->di_addr, NADDR); + for(i=NADDR-1;i>=0;i--) { + bn = iaddr[i]; + if(bn == 0) continue; + switch(i) { + + default: + bfree(bn); + break; + + case NADDR-3: + tloop(bn, 0, 0); + break; + + case NADDR-2: + tloop(bn, 1, 0); + break; + + case NADDR-1: + tloop(bn, 1, 1); + } + } + ip->di_size = 0; +} + +tloop(bn, f1, f2) +daddr_t bn; +int f1, f2; +{ + register i; + daddr_t nb; + union { + char data[BSIZE]; + daddr_t indir[NINDIR]; + } ibuf; + + dread(bn, ibuf.data, BSIZE); + for(i=NINDIR-1;i>=0;i--) { + nb = ibuf.indir[i]; + if(nb) { + if(f1) + tloop(nb, f2, 0); + else + bfree(nb); + } + } + bfree(bn); +} + +bfree(bn) +daddr_t bn; +{ + register i; + union { + char data[BSIZE]; + struct fblk frees; + } fbuf; + + if(sblock.s_nfree >= NICFREE) { + fbuf.df_nfree = sblock.s_nfree; + for(i=0;i0; j--) { + sh += NSHIFT; + nb <<= NSHIFT; + if(bn < nb) + break; + bn -= nb; + } + if(j == 0) { + return((daddr_t)0); + } + + /* + * fetch the address from the inode + */ + if((nb = iaddr[NADDR-j]) == 0) { + iaddr[NADDR-j] = nb = balloc(); + } + + /* + * fetch through the indirect blocks + */ + for(; j<=3; j++) { + dread(nb, (char *)indir, BSIZE); + sh -= NSHIFT; + i = (bn>>sh) & NMASK; + nnb = indir[i]; + if(nnb == 0) { + nnb = balloc(); + indir[i] = nnb; + dwrite(nb, (char *)indir); + } + nb = nnb; + } + return(nb); +} + +/* + * read the archiv into buf, then return whether or + * or not it is a header block. + */ +gethead(buf) +struct spcl *buf; +{ + readarchiv((char *)buf); + if (buf->c_magic != MAGIC || checksum((int *) buf) == 0) + return(0); + return(1); +} + +/* + * return whether or not the buffer contains a header block + */ +ishead(buf) +struct spcl *buf; +{ + if (buf->c_magic != MAGIC || checksum((int *) buf) == 0) + return(0); + return(1); +} + +checktype(b, t) +struct spcl *b; +int t; +{ + return(b->c_type == t); +} + + +checksum(b) +int *b; +{ + register i, j; + + j = BSIZE/sizeof(int); + i = 0; + do + i += *b++; + while (--j); + if (i != CHECKSUM) { + printf("Checksum error %o\n", i); + return(0); + } + return(1); +} + +checkvol(b, t) +struct spcl *b; +int t; +{ + if (b->c_volume == t) + return(1); + return(0); +} + +readhdr(b) +struct spcl *b; +{ + if (gethead(b) == 0) + return(0); + if (checktype(b, TS_TAPE) == 0) + return(0); + return(1); +} + +/* + * The next routines are called during file extraction to + * put the data into the right form and place. + */ +#ifndef STANDALONE +xtrfile(b, size) +char *b; +long size; +{ + write(ofile, b, (int) size); +} + +null() {;} + +skip() +{ + lseek(ofile, (long) BSIZE, 1); +} +#endif + + +rstrfile(b, s) +char *b; +long s; +{ + daddr_t d; + + d = bmap(taddr, curbno); + dwrite(d, b); + curbno += 1; +} + +rstrskip(b, s) +char *b; +long s; +{ + curbno += 1; +} + +#ifndef STANDALONE +putdir(b) +char *b; +{ + register struct direct *dp; + register i; + + for (dp = (struct direct *) b, i = 0; i < BSIZE; dp++, i += sizeof(*dp)) { + if (dp->d_ino == 0) + continue; + putent((char *) dp); + } +} +#endif + +/* + * read/write an inode from the winchester + */ +getdino(inum, b) +ino_t inum; +struct dinode *b; +{ + daddr_t bno; + char buf[BSIZE]; + + bno = (ino - 1)/INOPB; + bno += 2; + dread(bno, buf, BSIZE); + copy(&buf[((inum-1)%INOPB)*sizeof(struct dinode)], (char *) b, sizeof(struct dinode)); +} + +putdino(inum, b) +ino_t inum; +struct dinode *b; +{ + daddr_t bno; + char buf[BSIZE]; + + bno = ((ino - 1)/INOPB) + 2; + dread(bno, buf, BSIZE); + copy((char *) b, &buf[((inum-1)%INOPB)*sizeof(struct dinode)], sizeof(struct dinode)); + dwrite(bno, buf); +} + +/* + * read a bit mask from the archiv into m. + */ +readbits(m) +short *m; +{ + register i; + + i = spcl.c_count; + + while (i--) { + readarchiv((char *) m); + m += (BSIZE/(MLEN/BITS)); + } + while (gethead(&spcl) == 0) + ; +} + +done() +{ +#ifndef STANDALONE + unlink(dirfile); +#endif + exit(0); +} diff --git a/WEGA/src/cmd/tar.c b/WEGA/src/cmd/tar.c new file mode 100644 index 0000000..2e40dc8 --- /dev/null +++ b/WEGA/src/cmd/tar.c @@ -0,0 +1,1079 @@ +/* WEGA P8000 'tar' Version: 12.1.88 */ + +#include +#include +#include +#include +#include +#include + +#define TBLOCK 512 /* Blocklaenge (512 Byte) */ +#define NBLOCK 20 /* max. Blockung (512 * 20 Byte) */ +#define NAMSIZ 100 + +union hblock { + char dummy[TBLOCK]; + struct header { + char name[NAMSIZ]; + char mode[8]; + char uid[8]; + char gid[8]; + char size[12]; + char mtime[12]; + char chksum[8]; + char linkflag; + char linkname[NAMSIZ]; + } dbuf; +} dblock, tbuf[NBLOCK]; + +struct linkbuf { + ino_t inum; + dev_t devnum; + int count; + char pathname[NAMSIZ]; + struct linkbuf *nextp; +} *ihead; + +struct stat stbuf; + +char *sprintf(); +char *strcat(); +char *malloc(); +daddr_t bsrch(); + +int rflag, xflag, vflag, tflag, dflag, cflag, mflag; +int fd, term, chksum, wflag, recno, first, linkerrok; +int archuid, rhead, timeout; +int freemem = 1; +int nblock = 1; /* default: nur bei tardev */ +int BLOCKS, Blocks; +int xbuf[TBLOCK]; + +daddr_t low; +daddr_t high; + +FILE *tfile; +char tname[] = "/tmp/tarXXXXXX"; + +/* default: Disk.-Drive 1, cpi 96, double-sided, 9 sector */ +/* Typ 6 = rfd196ds9 (Blocklaenge : 512 Byte ) */ +/* (Blockanzahl : 1440 ) */ + +char *usefile; +char tardev[] = "/dev/tardev"; +char devrfd1[] = "/dev/rfd1"; + +main(argc, argv) +int argc; +char *argv[]; +{ + char *cp; + int onintr(), onquit(), onhup(), onterm(); + + if (argc < 2) + usage(); + + tfile = NULL; + usefile = tardev; + argv[argc] = 0; + argv++; + for (cp = *argv++; *cp; cp++) + switch(*cp) { + case 'f': + usefile = *argv++; + if (nblock == 1) nblock = 0; + break; + case 'c': + cflag++; + rflag++; + break; + case 'u': + mktemp(tname); + if ((tfile = fopen(tname, "w")) == NULL) { + fprintf(stderr, "tar: cannot create temporary file (%s)\n", tname); + done(1); } + fprintf(tfile, "!!!!!/!/!/!/!/!/!/! 000\n"); + /* kein 'break' !!! */ + case 'r': + rflag++; + if (nblock != 1 && cflag == 0) { +noupdate: + fprintf(stderr, "tar: Blocked archiv cannot be updated (yet)\n"); + done(1); } + break; + case 'v': + vflag++; + break; + case 'd': /* TEST */ + dflag++; + break; + case 'w': + wflag++; + break; + case 'X': /* Lese mit eigenen uid/gid's */ + archuid++; + case 'x': + xflag++; + break; + case 't': + tflag++; + break; + case 'm': + mflag++; + break; + case '-': + break; + case '0': + case '1': + devrfd1[8] = *cp; /* d.h. /dev/rfd0 oder 1 */ + usefile = devrfd1; + break; + case 'b': + nblock = atoi(*argv++); + if (nblock > NBLOCK || nblock <= 0) { + fprintf(stderr, "Invalid blocksize (Max %d)\n", NBLOCK); + done(1); } + if (rflag && !cflag) + goto noupdate; + break; + case 'l': + linkerrok++; + break; + default: + fprintf(stderr, "tar: %c: unknown option\n", *cp); + usage(); + } + +if (dflag) fprintf(stderr, "tar: Version 12.1.88\n"); /* TEST */ + + if (rflag) { + if (cflag && tfile != NULL) { usage(); done(1); } + if (signal(SIGINT, SIG_IGN) != SIG_IGN) + signal(SIGINT, onintr); + if (signal(SIGHUP, SIG_IGN) != SIG_IGN) + signal(SIGHUP, onhup); + if (signal(SIGQUIT, SIG_IGN) != SIG_IGN) + signal(SIGQUIT, onquit); +/* WOFUER ??? + if (signal(SIGTERM, SIG_IGN) != SIG_IGN) + signal(SIGTERM, onterm); +*/ + if (strcmp(usefile, "-") == 0) { + if (cflag == 0) { + fprintf(stderr, "Can only create standard output archives\n"); + done(1); } + fd = dup(1); + nblock = 1; } + else + nonex1: + if ((fd = open(usefile, 2)) < 0) { + if (cflag == 0 || (fd = creat(usefile, 0666)) < 0) { + fprintf(stderr, "tar: cannot open %s\n", usefile); + if (strcmp(usefile,tardev) == 0) { + usefile = devrfd1; + fprintf(stderr, "tar: tries open %s\n", usefile); + goto nonex1; } + done(1); } } + inBL(); + if (cflag == 0 && nblock == 0) nblock = 1; + dorep(argv); + } + else if (xflag) { + if (dflag) + if (archuid) fprintf(stderr, "Take your own uid/gid\n"); + else fprintf(stderr, "Get uid/gid from Archiv\n"); + + if (strcmp(usefile, "-") == 0) { + fd = dup(0); nblock = 1; } + else + nonex2: + if ((fd = open(usefile, 0)) < 0) { + fprintf(stderr, "tar: cannot open %s\n", usefile); + if (strcmp(usefile,tardev) == 0) { + usefile = devrfd1; + fprintf(stderr, "tar: tries open %s\n", usefile); + goto nonex2; } + done(1); } + inBL(); + doxtract(argv); + } + else if (tflag) { + if (strcmp(usefile, "-") == 0) { + fd = dup(0); nblock = 1; } + else + nonex3: + if ((fd = open(usefile, 0)) < 0) { + fprintf(stderr, "tar: cannot open %s\n", usefile); + if (strcmp(usefile,tardev) == 0) { + usefile = devrfd1; + fprintf(stderr, "tar: tries open %s\n", usefile); + goto nonex3; } + done(1); } + inBL(); + dotable(); } + else usage(); + done(0); +} + +usage() +{ + fprintf(stderr, "tar: usage tar [-]{crutxX}[Nbflmvw] [blocksize] [archivdev] [name ... ]\n"); + fprintf(stderr, " c: create archiv\n"); + fprintf(stderr, " r: write after archivend\n"); + fprintf(stderr, " u: update archiv\n"); + fprintf(stderr, " t: display archiv\n"); + fprintf(stderr, " x: read archiv \(get UID GID from archiv\)\n"); + fprintf(stderr, " X: read archiv \(get your own UID GID\)\n"); + fprintf(stderr, " N=0,1: archiv device number \(drive\)\n"); + fprintf(stderr, " b blocksize: verify archivblocksize\n"); + fprintf(stderr, " f archivdev: verify archivdevice\n"); + fprintf(stderr, " l: diagnostic links\n"); + fprintf(stderr, " m: time of modification for files becomes actual systemetime\n"); + fprintf(stderr, " v: display in verbosemode\n"); + fprintf(stderr, " w: interactive archivwork \(x,X with rename\)\n"); + done(1); } + +/* Hole BLOCKS ueber ioctl() */ +inBL() +{ +register i; + + i = ioctl(fd,SHOWFD,&BLOCKS); +if (dflag >= 2) fprintf(stderr, "ioctl: i = %d BLOCKS = %d\n",i,BLOCKS); + if (i) BLOCKS = 0; + if (BLOCKS && !nblock) nblock = 1; +if (dflag && BLOCKS) fprintf(stderr, "tar: disk capacity %d blocks\n", BLOCKS); +} + +/* Lese von Platte, Schreibe auf Archiv */ +dorep(argv) +char *argv[]; +{ + register char *cp, *cp2; + char wdir[60]; + +if (dflag >= 2) fprintf(stderr, "dorep(argv)\n"); /* TEST */ + if (!cflag) { /* vorheriges Archivlesen (Opt.: u,r) */ + gethead(); + do { + passarchiv(); + if (term) + done(0); + gethead(); + } while (!endarchiv()); + if (tfile != NULL) { + char buf[200]; + + strcat(buf, "sort +0 -1 +1nr "); + strcat(buf, tname); + strcat(buf, " -o "); + strcat(buf, tname); + sprintf(buf, "sort +0 -1 +1nr %s -o %s; awk '$1 != prev {print; prev=$1}' %s >%sX;mv %sX %s", + tname, tname, tname, tname, tname, tname); + fflush(tfile); + system(buf); + freopen(tname, "r", tfile); + fstat(fileno(tfile), &stbuf); + high = stbuf.st_size; + } + } + + getwdir(wdir); + while (*argv && ! term) { + cp2 = *argv; + for (cp = *argv; *cp; cp++) + if (*cp == '/') + cp2 = cp; + if (cp2 != *argv) { + *cp2 = '\0'; + chdir(*argv); + *cp2 = '/'; + cp2++; } + putfile(*argv++, cp2); + chdir(wdir); } + putempty(); + putempty(); +if (dflag >= 2) fprintf(stderr, "getwd ruft diskend\n"); + diskend(); /* NEU */ + write(fd, tbuf, TBLOCK*nblock); /* ehemals flushtape(); */ + if (linkerrok == 1) + for (; ihead != NULL; ihead = ihead->nextp) + if (ihead->count != 0) + fprintf(stderr, "Missing links to %s\n", ihead->pathname); + if (BLOCKS) { + fprintf(stderr, "\ntar: allocated space on disk %4d blocks with 512 bytes\n", + Blocks); + fprintf(stderr, "tar: free space on disk %4d blocks from %4d blocks\n", + BLOCKS-Blocks, BLOCKS); } +} + +endarchiv() +{ +if (dflag >= 2) fprintf(stderr, "endarchiv\n"); /* TEST */ + if (dblock.dbuf.name[0] == '\0') { + backarchiv(); + return(1); + } + else + return(0); +} + +/* Lese Head-Block vom Archiv und Werte seine Informationen aus */ +gethead() +{ + register struct stat *sp; + int i, j; + + j = 0; +readhead: + rhead = 1; /* an readarchiv: "Erwarte headblock" */ + readarchiv( (char *) &dblock); + if (rhead > 1) goto readhead; /* readarchiv-Fehler */ + for (i=0;ist_mode); + if (archuid) { /* uid/gid vom tar-Benutzer nehmen */ + sp->st_uid = getuid(); + sp->st_gid = getgid(); } + else { /* uid/gid vom Archiv nehmen */ + sscanf(dblock.dbuf.uid, "%o", &sp->st_uid); + sscanf(dblock.dbuf.gid, "%o", &sp->st_gid); } + sscanf(dblock.dbuf.size, "%lo", &sp->st_size); + sscanf(dblock.dbuf.mtime, "%lo", &sp->st_mtime); + sscanf(dblock.dbuf.chksum, "%o", &chksum); + if (chksum != checksum()) { + fprintf(stderr, "headblock checksum error\n"); + if (j) goto readhead; + else { + fprintf(stderr, "test next blocks ? (y/n) : "); + if (response() == 'y') { j++; goto readhead; } } + done(2); } + if (tfile != NULL) + fprintf(tfile, "%s %s\n", dblock.dbuf.name, dblock.dbuf.mtime); + rhead = 0; +} + +/* Archiv-Durchlauf zum Lesen der Header-Informationen */ +passarchiv() +{ + long blocks; + char buf[TBLOCK]; + +if (dflag >= 2) fprintf(stderr, "passarchiv\n"); /* TEST */ + if (dblock.dbuf.linkflag == '1') + return; + blocks = (stbuf.st_size + (TBLOCK-1)) / TBLOCK; + if (BLOCKS) { + Blocks += blocks; + while (Blocks >= BLOCKS) { +if (dflag >= 2) fprintf(stderr, "passarchiv: Blocks = Blocks + blocks (%d = %D + %D)\n", + Blocks, Blocks-blocks, blocks); + blocks = Blocks; +if (dflag >= 2) fprintf(stderr, "passarchiv ruft diskend\n"); + diskend(); + blocks -= BLOCKS; + Blocks = blocks; } +if (dflag >= 2) fprintf(stderr, "passarchiv: Blocks = %d : ", Blocks); +if (dflag >= 2) fprintf(stderr, "lseek mit blocks = %D\n", blocks); + lseek(fd, (long)TBLOCK*blocks, 1); + blocks = 0; } + else while (blocks-- > 0) + readarchiv(buf); +} + +/* Schreibe Datei auf Archiv */ +putfile(longname, shortname) +char *longname; +char *shortname; +{ + int infile; + long blocks; + char buf[TBLOCK]; + register char *cp, *cp2; + struct direct dbuf; + int i, j; + + infile = open(shortname, 0); + if (infile < 0) { + fprintf(stderr, "tar: %s: cannot open file\n", longname); + return; } + + fstat(infile, &stbuf); + + if (tfile != NULL && checkupdate(longname) == 0) { + close(infile); + return; } + if (checkw('r', longname) == 0) { + close(infile); + return; } + + if ((stbuf.st_mode & S_IFMT) == S_IFDIR) { /* = Directory */ + for (i = 0, cp = buf; *cp++ = longname[i++];); + *--cp = '/'; + cp++; + i = 0; + chdir(shortname); + while (read(infile, (char *)&dbuf, sizeof(dbuf)) > 0 && !term) { + if (dbuf.d_ino == 0) { + i++; continue; } + if (strcmp(".", dbuf.d_name) == 0 || + strcmp("..", dbuf.d_name) == 0) { + i++; continue; } + cp2 = cp; + for (j=0; j < DIRSIZ; j++) + *cp2++ = dbuf.d_name[j]; + *cp2 = '\0'; + close(infile); + putfile(buf, cp); /* rekursiv */ + infile = open(".", 0); + i++; + lseek(infile, (long) (sizeof(dbuf) * i), 0); + } + close(infile); + chdir(".."); + return; + } + if ((stbuf.st_mode & S_IFMT) != S_IFREG) { + fprintf(stderr, "tar: %s is not a file. Not archived\n", longname); + return; + } + + tomodes(&stbuf); + + cp2 = longname; + for (cp = dblock.dbuf.name, i=0; (*cp++ = *cp2++) && i < NAMSIZ; i++); + if (i >= NAMSIZ) { + fprintf(stderr, "%s: file name too long\n", longname); + close(infile); + return; + } + + if (stbuf.st_nlink > 1) { + struct linkbuf *lp; + int found = 0; + + for (lp = ihead; lp != NULL; lp = lp->nextp) { + if (lp->inum == stbuf.st_ino && lp->devnum == stbuf.st_dev) { + found++; + break; + } + } + if (found) { + strcpy(dblock.dbuf.linkname, lp->pathname); + dblock.dbuf.linkflag = '1'; + sprintf(dblock.dbuf.chksum, "%6o", checksum()); + writearchiv( (char *) &dblock); + if (vflag) { + fprintf(stderr, "a %s ", longname); + fprintf(stderr, "link to %s\n", lp->pathname); + } + lp->count--; + close(infile); + return; + } + else { + lp = (struct linkbuf *) malloc(sizeof(*lp)); + if (lp == NULL) { + if (freemem) { + fprintf(stderr, "Out of memory. Link information lost\n"); + freemem = 0; + } + } + else { + lp->nextp = ihead; + ihead = lp; + lp->inum = stbuf.st_ino; + lp->devnum = stbuf.st_dev; + lp->count = stbuf.st_nlink - 1; + strcpy(lp->pathname, longname); + } + } + } + + blocks = (stbuf.st_size + (TBLOCK-1)) / TBLOCK; + if (vflag) { + fprintf(stderr, "a %s ", longname); + fprintf(stderr, "%ld blocks\n", blocks); + } + sprintf(dblock.dbuf.chksum, "%6o", checksum()); + writearchiv( (char *) &dblock); + + while ((i = read(infile, buf, TBLOCK)) > 0 && blocks > 0) { + writearchiv(buf); + blocks--; + } + close(infile); + if (blocks != 0 || i != 0) + fprintf(stderr, "%s: file changed size\n", longname); + while (blocks-- > 0) + putempty(); +} + +/* Lese von Archiv, Schreibe auf Platte */ +doxtract(argv) +char *argv[]; +{ + long blocks, bytes; + char buf[TBLOCK]; + char **cp; + int ofile, i; + + for (;;) { + gethead(); + if (endarchiv()) + break; + + if (*argv == 0) + goto gotit; + + for (cp = argv, i = 0; *cp; cp++, i++) + if (prefix(*cp, dblock.dbuf.name)) + goto vgotit; + passarchiv(); + continue; + +vgotit: + xbuf[i]++; +gotit: + if (checkw('x', dblock.dbuf.name) == 0) { + passarchiv(); + continue; + } + + checkdir(dblock.dbuf.name); + + if (dblock.dbuf.linkflag == '1') { + unlink(dblock.dbuf.name); + if (link(dblock.dbuf.linkname, dblock.dbuf.name) < 0) { + fprintf(stderr, "%s: cannot link\n", dblock.dbuf.name); + continue; + } + if (vflag) + fprintf(stderr, "%s linked to %s\n", dblock.dbuf.name, dblock.dbuf.linkname); + continue; + } + if ((ofile = creat(dblock.dbuf.name, stbuf.st_mode & 07777)) < 0) { + fprintf(stderr, "tar: %s - cannot create\n", dblock.dbuf.name); + passarchiv(); + continue; + } + + chown(dblock.dbuf.name, stbuf.st_uid, stbuf.st_gid); + + blocks = ((bytes = stbuf.st_size) + TBLOCK-1)/TBLOCK; + if (vflag) + fprintf(stderr, "x %s, %ld bytes, %ld archiv blocks\n", dblock.dbuf.name, bytes, blocks); + while (blocks-- > 0) { + readarchiv(buf); + if (bytes > TBLOCK) { + if (write(ofile, buf, TBLOCK) < 0) { +if (dflag >= 2) fprintf(stderr,"\n"); /* TEST */ + fprintf(stderr, "tar: %s: HELP1 - extract write error\n", dblock.dbuf.name); + done(2); + } + } else + if (write(ofile, buf, (int) bytes) < 0) { +if (dflag >= 2) fprintf(stderr,"\n"); /* TEST */ + fprintf(stderr, "tar: %s: HELP2 - extract write error\n", dblock.dbuf.name); + done(2); + } + bytes -= TBLOCK; + } + close(ofile); + if (mflag == 0) { + time_t timep[2]; + + timep[0] = time(NULL); + timep[1] = stbuf.st_mtime; + utime(dblock.dbuf.name, timep); } + } + if (*argv) { + for (cp = argv, i = 0; *cp; cp++, i++) + if (!xbuf[i]) + fprintf(stderr, "tar: %s not in archiv\n", *cp); } +} + +/* Lese von Archiv (Realisierung t-Option) */ +dotable() +{ + for (;;) { + gethead(); + if (endarchiv()) break; + if (vflag) longt(&stbuf); + printf("%s", dblock.dbuf.name); + if (dblock.dbuf.linkflag == '1') + printf(" linked to %s", dblock.dbuf.linkname); + printf("\n"); + passarchiv(); + } +} + +putempty() +{ + char buf[TBLOCK]; + char *cp; + +if (dflag >= 2) fprintf(stderr, "putempty\n"); /* TEST */ + for (cp = buf; cp < &buf[TBLOCK]; ) + *cp++ = '\0'; + writearchiv(buf); +} + +/* v-Option fuer Terminalanzeige von: mode, uid, gid, size, ctime */ +longt(st) +register struct stat *st; +{ + register char *cp; + char *ctime(); + + pmode(st); + printf("%3d/%1d", st->st_uid, st->st_gid); + printf("%7D", st->st_size); + cp = ctime(&st->st_mtime); + printf(" %-12.12s %-4.4s ", cp+4, cp+20); +} + +#define SUID 04000 +#define SGID 02000 +#define ROWN 0400 +#define WOWN 0200 +#define XOWN 0100 +#define RGRP 040 +#define WGRP 020 +#define XGRP 010 +#define ROTH 04 +#define WOTH 02 +#define XOTH 01 +#define STXT 01000 +int m1[] = { 1, ROWN, 'r', '-' }; +int m2[] = { 1, WOWN, 'w', '-' }; +int m3[] = { 2, SUID, 's', XOWN, 'x', '-' }; +int m4[] = { 1, RGRP, 'r', '-' }; +int m5[] = { 1, WGRP, 'w', '-' }; +int m6[] = { 2, SGID, 's', XGRP, 'x', '-' }; +int m7[] = { 1, ROTH, 'r', '-' }; +int m8[] = { 1, WOTH, 'w', '-' }; +int m9[] = { 2, STXT, 't', XOTH, 'x', '-' }; + +int *m[] = { m1, m2, m3, m4, m5, m6, m7, m8, m9}; + +pmode(st) +register struct stat *st; +{ + register int **mp; + + for (mp = &m[0]; mp < &m[9];) + select(*mp++, st); +} + +select(pairp, st) +int *pairp; +struct stat *st; +{ + register int n, *ap; + + ap = pairp; + n = *ap++; + while (--n>=0 && (st->st_mode&*ap++)==0) + ap++; + printf("%c", *ap); +} + +checkdir(name) +register char *name; +{ + register char *cp; + int i; + for (cp = name; *cp; cp++) { + if (*cp == '/') { + *cp = '\0'; + if (access(name, 01) < 0) { + if (fork() == 0) { + execl("/bin/mkdir", "mkdir", name, 0); + execl("/usr/bin/mkdir", "mkdir", name, 0); + fprintf(stderr, "tar: cannot find mkdir!\n"); + done(0); + } + while (wait(&i) >= 0); + chown(name, stbuf.st_uid, stbuf.st_gid); + } + *cp = '/'; + } + } +} + +onintr() +{ + signal(SIGINT, SIG_IGN); + term++; +} + +onquit() +{ + signal(SIGQUIT, SIG_IGN); + term++; +} + +onhup() +{ + signal(SIGHUP, SIG_IGN); + term++; +} + +onterm() +{ + signal(SIGTERM, SIG_IGN); + term++; +} + +tomodes(sp) +register struct stat *sp; +{ + register char *cp; + + for (cp = dblock.dummy; cp < &dblock.dummy[TBLOCK]; cp++) + *cp = '\0'; + sprintf(dblock.dbuf.mode, "%6o ", sp->st_mode & 07777); + sprintf(dblock.dbuf.uid, "%6o ", sp->st_uid); + sprintf(dblock.dbuf.gid, "%6o ", sp->st_gid); + sprintf(dblock.dbuf.size, "%11lo ", sp->st_size); + sprintf(dblock.dbuf.mtime, "%11lo ", sp->st_mtime); +} + +checksum() +{ + register i; + register char *cp; + + for (cp = dblock.dbuf.chksum; cp < &dblock.dbuf.chksum[sizeof(dblock.dbuf.chksum)]; cp++) + *cp = ' '; + i = 0; + for (cp = dblock.dummy; cp < &dblock.dummy[TBLOCK]; cp++) + i += *cp; +if (dflag >= 2) fprintf(stderr, "checksum = %o\n",i); /* TEST */ + return(i); +} + +checkw(c, name) +char *name; +{ +char estring[100]; +register i; + + if (wflag) { + printf("%c ", c); + if (vflag) longt(&stbuf); + printf("%s: ", name); + gets(estring); + if (estring[0] == 'y') { + if (c == 'x' && estring[1] == ' ' && strlen(estring) > 2) { + for (i=1; estring[i] == ' '; i++) ; + for ( ; estring[i] != '\0'; i++) *name++ = estring[i]; + *name = '\0'; } + return(1); } + else return(0); } + return(1); +} + +response() +{ + char c; + + c = getchar(); + if (c != '\n') + while (getchar() != '\n'); + else c = 'n'; + return(c); +} + +checkupdate(arg) +char *arg; +{ + char name[100]; + long mtime; + daddr_t seekp; + daddr_t lookup(); + + rewind(tfile); + for (;;) { + if ((seekp = lookup(arg)) < 0) + return(1); + fseek(tfile, seekp, 0); + fscanf(tfile, "%s %lo", name, &mtime); + if (stbuf.st_mtime > mtime) + return(1); + else + return(0); + } +} + +done(n) +{ + unlink(tname); + exit(n); +} + +prefix(s1, s2) +register char *s1, *s2; +{ + while (*s1) + if (*s1++ != *s2++) + return(0); + if (*s2) + return(*s2 == '/'); + return(1); +} + +getwdir(s) +char *s; +{ + int pipdes[2]; + + pipe(pipdes); + if (fork() == 0) { + close(1); + dup(pipdes[1]); + execl("/bin/pwd", "pwd", 0); + execl("/usr/bin/pwd", "pwd", 0); + fprintf(stderr, "pwd failed!\n"); + printf("/\n"); + exit(1); + } + while (wait((int *)NULL) != -1) + ; + read(pipdes[0], s, 50); + while(*s != '\n') + s++; + *s = '\0'; + close(pipdes[0]); + close(pipdes[1]); +} + +#define N 200 +int njab; +daddr_t +lookup(s) +char *s; +{ + register i; + daddr_t a; + + for(i=0; s[i]; i++) + if(s[i] == ' ') + break; + a = bsrch(s, i, low, high); + return(a); +} + +daddr_t +bsrch(s, n, l, h) +daddr_t l, h; +char *s; +{ + register i, j; + char b[N]; + daddr_t m, m1; + + njab = 0; + +loop: + if(l >= h) + return(-1L); + m = l + (h-l)/2 - N/2; + if(m < l) + m = l; + fseek(tfile, m, 0); + fread(b, 1, N, tfile); + njab++; + for(i=0; i= h) + return(-1L); + m1 = m; + j = i; + for(i++; i 0) { + l = m1; + goto loop; + } + return(m); +} + +cmp(b, s, n) +char *b, *s; +{ + register i; + + if(b[0] != '\n') + exit(2); + for(i=0; i s[i]) + return(-1); + if(b[i+1] < s[i]) + return(1); + } + return(b[i+1] == ' '? 0 : -1); +} + +readarchiv(buffer) +char *buffer; +{ + int i, j; + + if (recno >= nblock || first == 0) { + if (first == 0 && nblock == 0) j = NBLOCK; + else j = nblock; +if (dflag >= 2) fprintf(stderr, "readarchiv ruft diskend\n"); + diskend(); /* NEU */ + if ((i = read(fd, tbuf, TBLOCK*j)) < 0) { + fprintf(stderr, "tar: archiv read error\n"); + if (rhead) { rhead++; /* Fehlermeldung an 'gethead' */ + fprintf(stderr, " in head-block\n"); } + if (!tflag) + fprintf(stderr, "tar: file %s is not complete\n", dblock.dbuf.name); + fprintf(stderr, " continue (y/n) : "); + if (response() != 'y') done(3); + lseek(fd, (long)(TBLOCK*j), 1); } /*? *j ?*/ + if (first == 0) { + if (i % TBLOCK) { + fprintf(stderr, "tar: archiv blocksize error\n"); + done(3); + } + i /= TBLOCK; + if (rflag && i != 1) { + fprintf(stderr, "tar: Cannot update blocked archiv (yet)\n"); + done(4); + } + if (i != nblock && i != 1) { +if (dflag >= 2) fprintf(stderr, "i = %d, nblock = %d\n",i, nblock); + fprintf(stderr, "tar: blocksize = %d\n", i); + nblock = i; + } + } + recno = 0; + } + first = 1; + copy(buffer, &tbuf[recno++]); + return(TBLOCK); +} + +writearchiv(buffer) +char *buffer; +{ + first = 1; +if (dflag >= 2) fprintf(stderr, "writearchiv: recno=%d nblock=%d\n",recno, nblock); + if (nblock == 0) + nblock = 1; + if (recno >= nblock) { +if (dflag >= 2) fprintf(stderr, "writearchiv ruft diskend\n"); + diskend(); /* NEU */ +/* Hier muesste Test auf Diskettenformat rein, inkl. Format-Moeglichkeit */ + if (write(fd, tbuf, TBLOCK*nblock) < 0) { + fprintf(stderr, "tar: archiv write error\n"); + done(2); + } + recno = 0; + } + copy(&tbuf[recno++], buffer); + if (recno >= nblock) { +if (dflag >= 2) fprintf(stderr, "writearchiv ruft diskend\n"); + diskend(); /* NEU */ + if (write(fd, tbuf, TBLOCK*nblock) < 0) { + fprintf(stderr, "tar: archiv write error\n"); + done(2); + } + recno = 0; + } + return(TBLOCK); +} + +/* Wird nur beim Archiv-Lesen aufgerufen (Optionen: r,u,x,t) */ +backarchiv() +{ + Blocks--; +if (dflag >= 2) { /* TEST */ + fprintf(stderr, "backarchiv\n"); + fprintf(stderr, "lseek: Blocks := Blocks-1 = %d\n", Blocks); } + + lseek(fd, (long)(-TBLOCK*nblock), 1); + if (recno >= nblock) { + recno = nblock - 1; +if (dflag >= 2) fprintf(stderr, "backarchiv ruft diskend\n"); + diskend(); /* NEU */ + if (read(fd, tbuf, TBLOCK*nblock) < 0) { + fprintf(stderr, "tar: archiv read error after seek\n"); + done(4); + } + Blocks--; +if (dflag >= 2) /* TEST */ + fprintf(stderr, "lseek: Blocks := Blocks-1 = %d\n", Blocks); +if (BLOCKS && tflag) { + printf("\ntar: allocated space on disk %4d blocks with 512 bytes\n", + Blocks+3); + printf("tar: free space on disk %4d blocks from %4d blocks\n", + BLOCKS-Blocks-3, BLOCKS); } + lseek(fd, (long)(-TBLOCK*nblock), 1); + } +} + +copy(to, from) +register char *to, *from; +{ + register i; + + i = TBLOCK; + do { + *to++ = *from++; + } while (--i); +} + +diskend() +{ +#define SEC 2 +int time_out(); + + if (BLOCKS == 0) return; +if (dflag >= 2) fprintf(stderr, "diskend: Blocks = %d\n", Blocks+1); /* TEST */ + if (++Blocks == 0) { + close(fd); + fprintf(stderr, "\ninsert previous disk : "); + Blocks = 1; /* da 'diskend' mit ++Blocks beginnt */ + while (getchar() != '\n') ; + if ((fd = open(usefile, 2)) < 0) { + if (cflag == 0 || (fd = creat(usefile, 0666)) < 0) { + fprintf(stderr, "tar: cannot open %s\n", usefile); + done(1); } } } + if (Blocks > BLOCKS) { + close(fd); + timeout = 0; + signal(SIGALRM,time_out); + alarm(SEC); + while (!timeout) getchar(); + alarm(0); + fprintf(stderr, "\ninsert next disk : "); + Blocks = 1; + while (getchar() != '\n') ; + if ((fd = open(usefile, 2)) < 0) { + if (cflag == 0 || (fd = creat(usefile, 0666)) < 0) { + fprintf(stderr, "tar: cannot open %s\n", usefile); + done(1); } } } +} + +time_out() +{ + signal(SIGALRM,time_out); + timeout++; +}