#define NI 16 #define DIRPB (BSIZE/sizeof(struct direct)) #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)) struct filsys sblock; struct dinode itab[INOPB*NI]; short clrmap[MSIZ]; short dirmap[MSIZ]; short nodmap[MSIZ]; char *disk; char *tape; char *increm; char incno; int uflag; int fi; int to; ino_t ino; int nsubdir; int ntape; int nadded; int dadded; int density = 160; char *ctime(); char *prdate(); long atol(); int fi; long tsize; long esize; long asize; int mark(); int add(); int dump(); int tapsrec(); int dmpspc(); int dsrch(); int nullf(); #define HOUR (60L*60L) #define DAY (24L*HOUR) #define YEAR (365L*DAY) main(argc, argv) char *argv[]; { char *arg; register i; time(&spcl.c_date); tsize = 2300L*12L*10L; tape = "/dev/rmt1"; disk = "/dev/rrp3"; increm = "/etc/ddate"; incno = '9'; uflag = 0; arg = "u"; if(argc > 1) { argv++; argc--; arg = *argv; } while(*arg) switch (*arg++) { case 'f': if(argc > 1) { argv++; argc--; tape = *argv; } break; case 'd': if (argc > 1) { argv++; argc--; density = atoi(*argv)/10; } 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]); exit(1); } if(argc > 1) { argv++; argc--; disk = *argv; } getitime(); printf(" date = %s\n", prdate(spcl.c_date)); printf("dump date = %s\n", prdate(spcl.c_ddate)); printf("dumping %s to %s\n", disk, tape); fi = open(disk, 0); if(fi < 0) { printf("dump: cannot open %s\n", disk); exit(1); } otape(); 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); printf("estimated %ld tape blocks on %d tape(s)\n", esize, 0); 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= 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(ntape) { ntape = 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= NTREC) flusht(); } tapsrec(d) daddr_t d; { if(d == 0) return; tdaddr[trecno] = d; trecno++; spcl.c_tapea++; if(trecno >= NTREC) flusht(); } flusht() { 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); printf("change tapes\n"); read(0, place, sizeof(place)); otape(); } } otape() { to = creat(tape, 0666); if(to < 0) { printf("dump: cannot create %s\n", tape); exit(1); } asize = 0; ntape++; 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 = disk; l1: for(i=0; fname[i]; i++) if(fname[i] == '/') { fname += i+1; goto l1; } spcl.c_ddate = 0; df = open(increm, 0); if(df < 0) { printf("cannot open %s\n", increm); 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 = disk; 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