/* undelete.c - undelete files-11 files - RSX, DECUS C, FILES-11 level 1.1 */ /* after find.c */ /* based on fid.c */ /* based on bum.c */ /* understands all flavours of wildcards */ /* breaks if not ODS-1 : it assumes lots of default offsets */ #include #include #include #include #include #include #include #include struct home homblk; /* home block */ struct header hedblk; /* file header */ struct bithead bhead; /* bitmap header */ char bitblk[512]; /* bitmap block */ char indxnm[100]; /* index file print name */ FILE * indexf; /* [0,0]indexf.sys;1 */ FILE * bitmapf; /* [0,0]bitmap.sys;1 */ unsigned filnum; /* file number */ unsigned filoff; /* (VBN of header (1,1) in indexf.sys)-1*/ unsigned maxfil; /* maximum file number (permitted by */ /* bitmap of index file) */ FDB * fdbp; /* point to fdb of indexf for fcs rape */ char nam[10]; /* file name from this header */ char ext[4]; /* file extension from this header */ int proj; /* project number from this header */ int prog; /* programmer number from this header */ int ver; /* version number from this header */ char wnam[10]; /* the name user is looking for */ char wext[4]; /* the extension user wants */ /* a % in above means match anything */ /* one day we will implement - */ int wproj; /* the group # user wants */ int wprog; /* the user # user wants */ int wver; /* the version user wants */ /* a -1 in above means wild */ /* one day we will mask bits, and range */ char wdev[10]; /* user nominated device */ main(argc,argv) int argc; char ** argv; BEGIN char * p; BOOL accept; IF (argc!=2) THEN printf("usage: %s [device_name:]filespec [-r]\n",argv[0]); printf("the filespec may be as wild as [*,*]mum%%%ble.*;*\n"); printf("each recoverable file, asks you which filename you want to give it\n"); printf("if you reply with an empty name, file is not recovered"); exit(); FI; $_$uc(argv[1]); /* uppercase everything */ IF (p=strchr(argv[1],':')) THEN p++; copy(wdev,argv[1],p-argv[1]); ELSE p = argv[1]; strcpy(wdev,""); FI /* p just after ':', wdev known */ IF (*p=='[') THEN p++; IF (*p=='*' || *p==',') THEN wproj = -1; IF (*p!=',') THEN p++; FI ELSE wproj=0; WHILE (isoctal(*p)) DO wproj = wproj*8 + (*p++)-'0'; OD FI /* p points to ',' and wproj is known */ IF (*p++!=',') THEN error("\7can't see ',' in []"); FI IF (*p=='*' || *p==']') THEN wprog = -1; IF (*p!=']') THEN p++; FI ELSE wprog=0; WHILE (isoctal(*p)) DO wprog = wprog*8 + (*p++)-'0'; OD FI /* *p -> '[' and wprog is known */ IF (*p++!=']') THEN error("\7can't see ']' in []"); FI ELSE wproj = wprog = -1; FI /* p points to filename. wproj,wprog known */ strcpy(wnam,"%%%%%%%%%"); strcpy(wext,"%%%"); constr(wnam,'.',&p); IF (*p=='.') THEN p++; constr(wext,';',&p); FI IF (*p==';') THEN p++; FOR (wver=0; isoctal(*p); p++) DO wver = wver*8 + *p-'0'; OD FI IF (*p) THEN fprintf(stderr,"%s: rest of ambiguous file spec ignored: \"%s\"\n\7" ,argv[0],p); FI strcpy(indxnm,wdev); strcat(indxnm,"[0,0]indexf.sys;1"); IF (! (indexf=fopenr(indxnm,512)) ) THEN error("\7$$ferr=%oo fopenr: %s",$$ferr,indxnm); FI /* now fake end-of-file to fcs: so we can read home block */ fdbp = indexf -> io_fdb; fdbp -> f_fatt . f_hibk = fdbp -> f_fatt . f_efbk = 42; IF (frget(&homblk,512,indexf,2L)) THEN error("\7$$ferr=%oo home",$$ferr); FI filoff = 2 + homblk . h_ibsz; maxfil = homblk . h_fmax; fdbp -> f_fatt . f_hibk = fdbp -> f_fatt . f_efbk = maxfil + 1; /* re-use of fdbp OK now */ strcpy(bitmnm,wdev); strcat(bitmnm,"[0,0]bitmap.sys;1"); IF (! (bitmapf=fopenr(bitmnm,512)) ) THEN error("$$ferr=%Oo fopenr: %s",$$ferr,bitmnm); FI /* fake eof to fcs: so we can read it */ fdbp = bitmapf -> io_fdb; fdbp -> f_fatt . f_hibk = fdbp -> f_fatt . f_efblk = 2; IF (frget(&bhead,512,bitmapf,1L)) THEN error("\7$$ferr=%oo bitmaphead",$$ferr); FI fdbp -> f_fatt . f_hibk = fdbp -> f_fatt . f_efbk = bhead.bh_nbb + 2; /* we can now read (&write?) whole bitmap file */ /* re-use of fdbp OK now */ FOR (filnum=1; filnum=0 && wproj!=proj) THEN accept = FALSE; FI IF (wprog>=0 && wprog!=prog) THEN accept = FALSE; FI IF (compare(ext,wext,3)) THEN accept = FALSE; FI IF (compare(nam,wnam,9)) THEN accept = FALSE; FI IF (accept) THEN printf("[%o,%o]%s.%s;%o\\%d. (%o:%o)\n" ,hedblk.h_proj&0xFF,hedblk.h_prog&0xFF,nam,ext ,hedblk.i_fver,hedblk.i_rvno,hedblk.h_fnum ,hedblk.h_fseq); recover(); FI FI OD END /* * recover() * * in: hedblk holds 0th file header for this file * do: display header details to user: * each inconsistent index file bitmap bit * each re-used disk bitmap bit * out: if user requests, then: * recover each header * mark each index bitmap bit as used * mark each disk bitmap as used */ recover() BEGIN long ivbn; /* vbn of this index block */ int esn; /* extension segment number of this index block */ esn = 0; ivbn = hedblk.m_efnu; ??? END xwfree(vbn) /* gripe if index file bitmap says vbn is used */ long vbn; BEGIN int bytndx; int msk; long blk; int bitnum; blk = vbn>>12; bitnum = vbn & 0xFFFF; bytndx = bitnum >> 3; msk = 1 << (bitnum & 0x7); xget(blk) IF ( xblk[bytndx] & msk ) THEN fprintf(stderr ,"\7indexfile bitmap says index vbn %ld. is used!\n" ,vbn); FI END xuse(vbn) /* set index file bitmap to say vbn is used */ long vbn; BEGIN int bytndx; int msk; long blk; int bitnum; blk = vbn>>12; bitnum = vbn & 0xFFFF; bytndx = bitnum >> 3; msk = 1 << (bitnum & 0x7); xget(blk) IF ( ! ( xblk[bytndx] & msk ) ) THEN xblk[bytndx] |= msk ; xput(blk); FI END xget(vbn) /* get vbn'th index bitmap block to xblk[] */ long vbn; BEGIN IF (frget(xblk,512,indexf,vbn+homblk.h_iblb)) THEN error("\7$$ferr=%oo index bitmap read %loo",$$ferr,vbn); FI END xput(vbn) /* put vbn'th index bitmap block from xblk[] */ long vbn; BEGIN return(0); IF (frput(xblk,512,indexf,vbn+homblk.h_iblb)) THEN error("\7$$ferr=%oo index bitmap read %loo",$$ferr,vbn); FI END int compare(a,b,len) /* return TRUE if no match */ char *a; char *b; int len; BEGIN FOR (; len--; a++,b++) DO IF (*a!=*b && *a!='%' && *b!='%') THEN return(TRUE); FI OD return(FALSE); END constr(dest,stop,pointer) char * dest; char stop; char ** pointer; BEGIN register char * q; register char * p; FOR (q=dest,p=*pointer; *p && *p!=stop && *q; p++) DO switch (*p) { case '*': WHILE (*q) DO *q++ = '%'; OD break; default: *q++ = *p; break; } ; OD /* p points to terminator (usually EOS or stop) */ *pointer = p; END BOOL isoctal(c) char c; BEGIN c &= 0x7F; return(c<'8' && c>='0'); END /* end: find.c */