#incude "stp.h" #define BSIZE ((d->d_size0&0377)<<7) | (((d->d_size1)>>9)&0177) int linepos; /* global, cleared by gettape, looked at in taboc */ gettape(how) int (*how)(); { register char *ptr0, *ptr1; register struct dent *d; int count; linepos = 0; /* see taboc() for meaning */ do { d = &dir[0]; count = 0; do { if (d->d_namep == 0) continue; decode(name,d); if (rnarg > 2) { /* ##stt 7/15/77 allow wild card matches */ /* as well as match to '/' */ if (!tpmatch(&name, *parg)) continue; } (*how)(d); /* delete, extract, or taboc */ ++count; } while (++d <= lastd); if (count == 0 && rnarg > 2) printf("%s not found\n", *parg); else if (count > 1 && linepos&03) { /* group directories together */ putchar('\n'); linepos = 0; } ++parg; } while (--narg > 2); /* terminate taboc with */ if (linepos&03) putchar('\n'); } /* this is the new filename matcher */ /* the first string must be within the set */ /* of filenames specified by the second string (wild cards */ /* and directory name only allowed) */ /* sequence './' is ignored in first arg. */ tpmatch(str, pattern) char *str, *pattern; { if ((str[0] == '.' && str[1] == '/') && (pattern[0] != '.' || pattern[1] != '/')) str =+ 2; return(match(str, pattern)); } match(str, pattern) char *str, *pattern; { register char *sp, *pp; sp = str; pp = pattern; do { if (*sp == *pp++) continue; switch(pp[-1]) { case 0: if (*sp == '/') return(1); return(0); case '?': if (*sp) continue; return(0); case '[': while (*pp != *sp) { if (*pp == 0 || *pp++ == ']') return(0); if (*pp == '-') { /* range specified (e.g. [a-z]) */ pp++; if (*sp <= *pp++ && *sp >= pp[-3]) break; } } /* skip over ']' */ while (*pp && *pp++ != ']'); continue; case '*': do { if (match(sp, pp)) return(1); } while (*sp && *sp++ != '/'); return(0); default: return(0); } } while (*sp++); return(1); } delete(dd) { if (verify('d') >= 0) clrent(dd); } /**/ update() { register struct dent *d; register b, last; int first, size; bitmap(); d = &dir[0]; /* find a place on the tape for first file */ last = -1; for (b = 0; b < sizeof map; b++) if (map[b]) last = b; if (last < 0) first = 0; else { first = (last<<3) + 8; last = map[last]; b = 0200; while ((b & last) == 0) { --first; b =>> 1; } } do { if (d->d_namep == 0 || d->d_mode >= 0) continue; if (d->d_size1 == 0 && d->d_size0 == 0) continue; d->d_tapea = first; first =+ BSIZE; if (d->d_size1 & 511) ++first; setmap(d); } while (++d <= lastd); update1(); } /**/ update1() { register struct dent *d; register index, id; int errs; optap(0, 1); if (flags & flc) { /* put out mboot and the directory */ wseek(0); id = open("/usr/mdec/mboot",0); if (id >= 0) { read(id,tapeb,512); close(id); } tpentry[7].cksum = ndirent; /* ##stt do this in any case */ twrite(); wrdir(); } for (;;) { d = &dir[0]; index = 32767; errs = id = 0; do { /* find new dent with lowest tape address */ if (d->d_namep == 0 || d->d_mode >= 0) continue; if (d->d_tapea < index) { index = d->d_tapea; id = d; } } while (++d <= lastd); if ((d = id) == 0) break; d->d_mode =& ~0100000; /* change from new to old */ if (d->d_size1 == 0 && d->d_size0 == 0) continue; decode(name,d); wseek(index); if ((id = open(name,0)) < 0) { printf("Can't open %s\nFile not saved\n", name); errs++; } for (index = BSIZE; index != 0; --index) { if(!errs) if (read(id,tapeb,512) != 512) { phserr(); errs++; } twrite(); } if (index = d->d_size1 & 511) { if(!errs) if (read(id,tapeb,index) != index) { phserr(); errs++; } twrite(); } if (!errs) if (read(id,tapeb,1) != 0) { phserr(); errs++; } close(id); } close(fio); } phserr() { printf("%s -- Phase error\nFile not saved\n",name); } /**/ bitmap() /* place old files in the map */ { register *m, count; register struct dent *d; m = ↦ count = sizeof map/2; do *m++ = 0; /* clear the map */ while (--count); if (lastd==0) ndentd8 = 0; else ndentd8 = ((lastd - &dir[0])>>3 ) + 1; ndirent = ndentd8<<3; if (flags & flc) { /* mark end of normal directory in map */ count = ndentd8; map[count>>3] =| (1 << (count & 7)); return; } if ((count = ndirent) == 0) return; d = &dir[-1]; do { d++; if (d->d_namep == 0 || d->d_mode < 0) continue; if (d->d_size1 || d->d_size0) setmap(d); } while (--count); } setmap(dd) { register char *c, *block, *d; char bit; d = dd; /* used for dent pointer then as map index */ c = BSIZE; if (d->d_size1 & 511) c++; block = d->d_tapea; if ((c =+ block) >= tapsiz) maperr(); do { bit = 1 << (block & 7); d = (block>>3) & ~0160000; if (bit & map[d]) maperr(); map[d] =| bit; } while (++block < c); } maperr(nnnnn) { printf("Tape overflow\n"); done(0); } /**/ usage() { register reg,count,d; int nentr; static lused; bitmap(); d = &dir[0]; count = ndirent; reg = 0; if (count) do { if (d->d_namep !=0) reg++; d =+ sizeof dir[0]; } while (--count); nentr = reg; d = 0; /* used to count nused */ for (reg = 0; reg < tapsiz; reg++) { if (map[(reg>>3) & ~0160000] & (1 << (reg&7))) { d++; lused = reg; } else ++count; } printf("%5d entries\n%5d used\n", nentr, d); printf("%5d free\n", count); printf("%5d last\n", lused); } /**/ taboc(dd) { register mode; register *m; register char *s; int count; extern linepos; if (flags & flv) { mode = dd->d_mode; s = &catlb[9]; *s = 0; for (count = 3; count; --count) { if (mode&1) *--s = 'x'; else *--s = '-'; if (mode&2) *--s = 'w'; else *--s = '-'; if (mode&4) *--s = 'r'; else *--s = '-'; mode =>> 3; } if (mode&4) s[2] = 's'; if (mode&2) s[5] = 's'; m = locv(dd->d_size0 & 255, dd->d_size1); printf("%s%4d%4d%5d%9s ",s,dd->d_uid, dd->d_gid,dd->d_tapea,m); m = localtime(dd->d_time); printf("%2d/%2d/%2d %2d:%2d ",m[5],m[4]+1,m[3],m[2],m[1]); printf("%s\n", name); } else { printf(++linepos&03? "%-20s": "%s\n", name); } } /**/ extract(dd) { register *d, count, id; d = dd; if (d->d_size0==0 && d->d_size1==0) return; if (verify('x') < 0) return; rseek(d->d_tapea); unlink(name); if ((id = creat(name,d->d_mode)) < 0) { printf("%s -- create error\nFile not extracted\n", name); return; } count = BSIZE; while (count--) { tread(0); if (write(id,tapeb,512) != 512) goto ng; } if (count = d->d_size1 & 511) { tread(0); if (write(id,tapeb,count) != count) { smdate(name,"\0,\0"); ng: printf("%s -- write error\n", name); close(id); return; } } close(id); count = (d->d_gid<<8) | (d->d_uid & 511); chown(name,count); smdate(name,d->time); /* DOESN'T EXIST, use 'as' routine */ } smdate() {} /* don't bother, unix doesn't do it anyway */