From: SMTP%"DSJ@WKUVX1.WKU.EDU" 7-FEB-1995 12:48:10.76 To: EVERHART CC: Subj: DECEMBER94.RECOVR From: DSJ-Mgr@WKUVX1.WKU.EDU Message-Id: <199502071725.MAA23764@mx2.smtp.psi.net> X-FileServer: Digital Systems Journal File Server Date: Tue, 07 Feb 1995 11:25:12 CST Sender: DSJ-Mgr@WKUVX1.WKU.EDU Errors-To: DSJ-Mgr@WKUVX1.WKU.EDU Warnings-To: <> Reply-To: DSJ@WKUVX1.WKU.EDU Subject: DECEMBER94.RECOVR To: EVERHART@arisia.gce.com $! ------------------ CUT HERE ----------------------- $ v='f$verify(f$trnlnm("SHARE_UNPACK_VERIFY"))' $! $! This archive created: $! Name : RECOVR $! By : Hunter Goatley $! Date : 4-JAN-1995 09:16:11.87 $! Using: VMS_SHARE 8.5-1, (C) 1993 Andy Harper, Kings College London UK $! $! Credit is due to these people for their original ideas: $! James Gray, Michael Bednarek $! $! To unpack this archive: $! Minimum of VMS 4.4 (VAX) / OpenVMS 1.0 (Alpha) is required. $! Remove the headers of the first part, up to `cut here' line. $! Execute file as a command procedure. $! $! The following file(s) will be created after unpacking: $! 1. RECOVR.DSJ;1 $! $ set="set" $ set symbol/scope=(nolocal,noglobal) $ f="SYS$SCRATCH:."+f$getjpi("","PID")+";" $ if f$trnlnm("SHARE_UNPACK") .nes. "" then $ - f=f$parse("SHARE_UNPACK_TEMP",f) $ e="write sys$error ""%UNPACK"", " $ w="write sys$output ""%UNPACK"", " $ if .not. f$trnlnm("SHARE_UNPACK_LOG") then $ w = "!" $ if f$getsyi("CPU") .gt. 127 then $ goto start $ ve=f$getsyi("version") $ if ve-f$extract(0,1,ve) .ges. "4.4" then $ goto start $ e "-E-OLDVER, Must run at least VMS 4.4" $ v=f$verify(v) $ exit 44 $unpack:subroutine!P1=file,P2=chksum,P3=attrib,P4=size,P5=fileno,P6=filetotal $ if f$parse(P1) .nes. "" then $ goto dirok $ dn=f$parse(P1,,,"DIRECTORY") $ w "-I-CREDIR, Creating directory ''dn'" $ create/dir 'dn' $ if $status then $ goto dirok $ e "-E-CREDIRFAIL, Unable to create ''dn' File skipped" $ delete 'f'* $ exit $dirok: $ x=f$search(P1) $ if x .eqs. "" then $ goto file_absent $ e "-W-EXISTS, File ''P1' exists. Skipped" $ delete 'f'* $ exit $file_absent: $ w "-I-UNPACK, Unpacking ", P5, " of ", P6, " - ", P1, " - ", P4, " Blocks" $ n=P1 $ if P3 .nes. "" then $ n=f $ if .not. f$verify() then $ define/user sys$output nl: $ EDIT/TPU/NOSEC/NODIS/COM=SYS$INPUT/NOJOURNAL 'f'/OUT='n' PROCEDURE GetHex(s,p)LOCAL x1,x2;x1:=INDEX(t,SUBSTR(s,p,1))-1;x2:=INDEX(t, SUBSTR(s,p+1,1))-1;RETURN 16*x1+x2;ENDPROCEDURE;PROCEDURE SkipPartsep LOCAL m; LOOP m:=MARK(NONE);EXITIF m=END_OF(CURRENT_BUFFER);DELETE(m);EXITIF INDEX( ERASE_LINE,"-+-+-+-+-+-+-+-+")=1;ENDLOOP;ENDPROCEDURE; PROCEDURE ProcessLine LOCAL c,s,l,b,n,p;s := ERASE_LINE;c := SUBSTR(s,1,1);s := s-c;IF c = "X" THEN SPLIT_LINE; ENDIF;MOVE_HORIZONTAL(-1);l := LENGTH(s);p := 1;LOOP EXITIF p > l;c := SUBSTR(s,p,1);p := p+1;CASE c FROM ' ' TO '`' ['`'] : COPY_TEXT(ASCII(GetHex(s,p))); p:=p+2;[' ']: p:=p+1;[INRANGE,OUTRANGE] : COPY_TEXT(c);ENDCASE;ENDLOOP;ENDPROCEDURE;PROCEDURE Decode(b)LOCAL m; POSITION(BEGINNING_OF(b));LOOP m:=MARK(NONE);EXITIF m=END_OF(b);DELETE(m); IF INDEX(CURRENT_LINE,"+-+-+-+-+-+-+-+-")=1 THEN SkipPartSep;ELSE ProcessLine; MOVE_HORIZONTAL(1);ENDIF;ENDLOOP;ENDPROCEDURE;SET(FACILITY_NAME,"UNPACK");SET( SUCCESS,OFF);SET(INFORMATIONAL,OFF);t:="0123456789ABCDEF";f:=GET_INFO( COMMAND_LINE,"file_name");o:=CREATE_BUFFER(f,f);Decode(o);WRITE_FILE(o, GET_INFO(COMMAND_LINE,"output_file"));QUIT; $ if p3 .eqs. "" then $ goto dl $ open/write fdl &f $ write fdl "RECORD" $ write fdl P3 $ close fdl $ w "-I-CONVRFM, Converting record format to ", P3 $ convert/fdl='f' 'f'-1 'f' $ fa=f$getdvi(f$parse(f),"ALLDEVNAM") $ Pa=f$getdvi(f$parse(P1),"ALLDEVNAM") $ if fa .eqs. Pa then $ rename &f 'f$parse(P1)' $ if fa .nes. Pa then $ copy &f 'f$parse(P1)' $dl: delete 'f'* $ checksum 'P1' $ if checksum$checksum .nes. P2 then $ - e "-E-CHKSMFAIL, Checksum of ''P1' failed." $ exit $ endsubroutine $start: $! $ create 'f' XRecovery`20program`20-`20README X XOverview`20 X X`09This`20program`20illustrates`20how`20to`20read`20the`20cylinder`20group`20b Vits X`09maps`20and`20examine`20the`20free`20fragments`20for`20each`20group.`20`20Th Ve X`09examination`20function`20is`20a`20working`20example`20of`20how`20to`20recov Ver X`09text`20files`20in`20the`20desired`20cylinder`20group. X X`09To`20use`20the`20program`20to`20recover`20a`20file: X X`09`09#`20recover`20special`20hint X X`09The`20program`20will`20convert`20a`20file`20name`20to`20the`20raw`20device V`20for X`09the`20partition`20it`20is`20on.`20`20Since`20files`20are`20typically`20crea Vted X`09in`20the`20same`20cylinder`20group`20as`20the`20directory`20they`20are`20in V X`09the`20directory`20name`20makes`20a`20good`20hint,`20when`20the`20file`20sys Vtem X`09is`20mounted. X XExample: X X`09#`20recover`20`7Ealan`20`7Ealan/src/fs/dxfs`20>`20/var/tmp/saved X X`09I`20let`20the`20C-shell`20expand`20the`20location`20of`20my`20home`20direct Vory`20from X`09`7Ealan.`20`20A`20utility`20function`20in`20the`20program`20finds`20the`20r Vaw`20device X`09from`20the`20file`20name.`20`20It`20should`20do`20suitable`20error`20checki Vng X`09for`20NFS`20mounted`20file`20systems.`20`20Since`20a`20"hint"`20is`20provid Ved, X`09the`20cylinder`20group`20number`20is`20used`20to`20limit`20the`20search.`20 V`20Whatever X`09blocks`20look`20like`20ASCII`20text`20are`20written`20to`20stdout. X X`09Note:`20You`20don't`20want`20to`20write`20on`20the`20same`20file`20system V`20as`20is X`09being`20recovered;`20saving`20the`20file`20may`20overwrite`20the`20blocks X`09you`20want`20to`20save. X X`09Note:`20The`20file`20system`20must`20be`20mounted`20for`20the`20"hint"`20to V`20work. X XOptions: X X`09There`20are`20two`20command`20lines`20options: X X`09`09-v`20-`20Verbose`20output X`09`09-h`20-`20Simple`20help. X X`09If`20the`20-v`20options`20is`20used`20twice`20the`20output`20will`20be`20ev Ven`20more X`09verbose,`20with`20fragment`20and`20cylinder`20group`20information`20appeari Vng X`09in`20stdout`20along`20with`20the`20file`20data. X XArguments. X X`09The`20"special"`20argument`20can`20either`20be`20the`20path`20name`20of`20a V`20mounted X`09file`20system`20or`20the`20raw`20device`20the`20file`20system`20is`20on.`20 V`20If`20the X`09path`20is`20provided`20the`20program`20will`20figure`20out`20where`20the`20 Vfile X`09system`20is. X X`09The`20"hint"`20argument`20can`20one`20of: X X`09`20`20`20o`20`20A`20path`20name. X`09`20`20`20o`20`20A`20cylinder`20group`20number`20in`20the`20form`20@cgn. X`09`20`20`20o`20`20An`20inode`20number`20in`20the`20form`20#cgn. X XExamples: X X`20`20`20`20Hint`20by`20path. X X`09#`20recover`20/fs`20/fs/recover X X`20`20`20`20Hint`20by`20Inode. X X`09#`20recover`20/fs`20#1536 X X`20`20`20`20Hint`20by`20Cylinder`20group`20number. X X`09#`20recover`20/fs`20@1 X XProblems`20Fixed. X X`09The`20previous`20version`20of`20the`20program`20read`20fragments`20one`20at V X`09a`20time,`20considerably`20limiting`20the`20I/O`20speed.`20`20This`20versio Vn X`09counts`20the`20length`20of`20free`20"strings"`20of`20fragments`20and`20hand Vles X`09them`20in`20large`20groups.`20`20The`20data`20analysis`20work`20is`20still V`20done X`09by`20fragment,`20but`20at`20least`20the`20I/O`20is`20faster. X XRestrictions/Bugs. X X`09Read`20access`20is`20required`20on`20the`20raw`20device`20that`20has`20the V X`09file`20system`20on`20it.`20`20Blocks`20are`20not`20erased`20when`20a`20file V X`09is`20closed`20(obviously`20or`20the`20program`20wouldn't`20work).`20`20The V X`09security`20implications`20are`20left`20as`20an`20exercise`20to`20the`20 X`09reader. X`0C XRecovery`20program`20-`20examine.c X X/* X`20*`09Author:`20`20Alan`20Rollow,`20Subsystems`20Engineering,`20Digital`20Equ Vipment`20Corp. X`20*`09File:`09`20examine.c X`20*`09Date:`09`206/23/94 X`20*`09Version:`201.5 X`20* X`20*`09examine.c`20-`20Examine`20a`20data`20block. X`20*/ X#ifndef`09lint Xstatic`09char`09SccsId`5B`5D`20=`20"@(#)examine.c`091.5`20(recover)`206/23/94" V`20; X#endif X X#include`20 X#include`20 X X#include`20 X X#include`20 X#include`20 X#include`20 X#include`20 X Xvoid`09bread()`20; X Xextern`20int`20verbose`20; X Xstatic`20char`20*format`20=`20"Block`20%d`20(%d)`20looks`20interesting:`20%.2f V%%`20(%d).`5Cn"`20; X X/* X`20*`09Print`20some`20Cylinder`20group`20stuff. X`20* X`20*`09ARGSUSED X`20*/ Xexamine_cg(int`20fd,`20struct`20cg`20*cgp,`20int`20cgn) X`7B X`09if(`20verbose`20>`201`20) X`09`09printf("#`5Cn#`5CtCylinder`20Group`20%d.`5Cn#`5Cn",`20cgn)`20; X`7D X X/* X`20*`09The`20application`20writer`20can`20season`20to`20taste.`20`20The`20argu Vments`20are: X`20* X`20*`09fd`20`20`20`20-`20The`20file`20descriptor`20for`20the`20character`20dev Vice. X`20*`09block`20-`20The`20disk`20block`20number. X`20*`09size`20`20-`20The`20size`20of`20the`20data`20block. X`20*`09cgn`20`20`20-`20The`20cylinder`20group`20number`20(not`20used). X`20* X`20*`09This`20version`20examines`20the`20content`20of`20the`20block`20to`20det Vermine X`20*`09if`20the`20block`20is`20useful`20and`20interesting.`20`20Interesting`20 Vcharacters X`20*`09are`20those`20which`20are`20not`20NUL.`20`20Useful`20characters`20are V`20white`20space X`20*`09and`20printable`20characters.`20`20When`20the`20number`20of`20useful`20 Vcharacters X`20*`09is`20the`20same`20as`20the`20number`20of`20interesting`20characters`20a Vnd`20neither X`20*`09is`20zero,`20the`20block`20is`20printed`20to`20stdout,`20with`20a`20sho Vrt`20header. X`20* X`20*`09This`20is`20currently`20not`20used,`20but`20kept`20for`20example`20purp Voses. X`20*/ Xstatic`09char`09frag`5BMAXBSIZE`5D`20; X Xexamine(int`20fd,`20daddr_t`20block,`20int`20size,`20int`20cgn) X`7B X`09if(`20size`20>`20sizeof(frag))`20`7B X`09`09fprintf(stderr,`20"The`20static`20buffer`20is`20not`20large`20enough:`20 V%d.`5Cn", X`09`09`09size)`20; X X`09`09return`200`20; X`09`7D X X`09bread(fd,`20block,`20frag,`20size)`20; X X`09examine_data(frag,`20size,`20block)`20; X X`09return`201`20; X`7D X X/* X`20*`09This`20may`20also`20be`20seasoned`20to`20taste.`20`20This`20is`20the`20 Vfragment X`20*`09examination`20function`20called`20by`20the`20program.`20`20The`20argume Vnts X`20*`09are: X`20* X`20*`09fd`20`20`20`20`20`20`20`20`20-`20The`20file`20descriptor`20for`20the`20 Vcharacter`20device. X`20*`09start`20`20`20`20`20`20-`20The`20disk`20block`20number`20of`20the`20fir Vst`20block`20in`20the`20string. X`20*`09run_length`20-`20The`20length`20of`20the`20string`20(number`20of`20frag Vments). X`20*`09fsize`20`20`20`20`20`20-`20The`20size`20of`20a`20fragment. X`20*`09cgn`20`20`20`20`20`20`20`20-`20The`20cylinder`20group`20number`20(not V`20used). X`20* X`20*`09Using`20as`20many`20reads`20as`20necessary,`20read`20each`20string`20an Vd X`20*`09examine`20it`20one`20fragment`20at`20a`20time. X`20* X`20*`09An`20assumption`20that`20may`20not`20be`20safe: X`20* X`20*`091.`20`20The`20fragment`20size`20is`20a`20factor`20of`2065536. X`20*/ X#define`09SIZE`09(65536) X Xexamine_string(int`20fd,`20daddr_t`20start,`20int`20run_length,`20size_t`20fsi Vze,`20int`20cgn) X`7B X`09char`09`20block`5BSIZE`5D`20; X`09register`20i,`20bytes,`20rc`20; X`09off_t`09`20offset`20; X X`09/* X`09`20*`09Get`20the`20byte`20length`20of`20the`20string. X`09`20*/ X`09bytes`20=`20fsize`20*`20run_length`20; X X`09/* X`09`20*`09Seek`20to`20the`20starting`20block. X`09`20*/ X`09offset`20`20=`20(off_t)start`20; X`09offset`20*=`20DEV_BSIZE`20; X X`09if(`20lseek(fd,`20offset,`20SEEK_SET)`20==`20-1`20)`20`7B X`09`09fprintf(stderr,`20"Can't`20seek`20to`20LBN`20%d:`20%s.`5Cn",`20start, X`09`09`09strerror(errno))`20; X X`09`09return`20; X`09`7D X X`09/* X`09`20*`09Read`20at`20most`20SIZE`20until`20we`20reach`20the`20end. X`09`20*/ X`09while((rc`20=`20read(fd,`20block,`20bytes`20>`20SIZE`20?`20SIZE`20:`20bytes V))`20>`200`20)`20`7B X`09`09/* X`09`09`20*`09Reduce`20the`20byte`20count. X`09`09`20*/ X`09`09bytes`20-=`20rc`20; X X`09`09/* X`09`09`20*`09For`20each`20fragment,`20call`20examine_data. X`09`09`20*/ X`09`09run_length`20=`20rc`20/`20fsize`20; X X`09`09for(i`20=`200;`20i`20<`20run_length;`20i++) X`09`09`09examine_data(block`20+`20(i`20*`20fsize),`20fsize,`20start`20+`20i) V`20; X X`09`09/* X`09`09`20*`09If`20we've`20run`20out`20of`20length,`20stop. X`09`09`20*/ X`09`09if(`20bytes`20<=`200`20) X`09`09`09break`20; X`09`7D X X`09if(`20rc`20==`20-1`20) X`09`09fprintf(stderr,`20"Read`20error:`20%s.`5Cn",`20strerror(errno))`20; X`7D X X/* X`20*`09Given`20a`20pointer`20to`20a`20block`20of`20data`20and`20the`20length, V`20examine X`20*`09it`20to`20determine`20if`20it`20is`20interesting`20and`20useful.`20`20C Vharacters X`20*`09which`20are`20printable`20or`20whitespace`20count`20as`20"useful".`20 V`20The X`20*`09difference`20in`20the`20count`20of`20useful`20characters`20and`20NUL`20 Vchar- X`20*`09acters`20is`20"interesting". X`20* X`20*`09This`20implementation`20of`20examine_data`20requires`20that`20the`20num Vber X`20*`09of`20interesting`20characters`20be`20the`20same`20as`20the`20number`20o Vf`20useful X`20*`09characters,`20making`20the`20calculation`20of`20"interesting"`20unneces Vsary. X`20*`09Other`20implementations`20may`20want`20to`20use`20a`20high`20precentage V`20of X`20*`09useful`20to`20interesting`20or`20some`20other`20condition.`20`20For`20f Vile X`20*`09specific`20recovery`20this`20routine`20must`20be`20seasoned`20to`20tast Ve. X`20*/ Xexamine_data(char`20*frag,`20int`20size,`20daddr_t`20block) X`7B X`09register`20char`20*cp,`20*lastp,`20c`20; X`09register`20useful,`20nul,`20interesting`20; X X`09nul`20=`20useful`20=`20interesting`20=`200`20; X X`09for(cp`20=`20frag,`20lastp`20=`20frag`20+`20size;`20cp`20<`20lastp;`20cp++) V`20`7B X`09`09if(`20*cp`20==`20'`5C0'`20) X`09`09`09nul++`20; X X`09`09if(`20isspace(*cp)`20`7C`7C`20isprint(*cp)) X`09`09`09useful++`20; X`09`7D X X`09interesting`20=`20size`20-`20nul`20; X X`09/* X`09`20*`09This`20is`20a`20rather`20strict`20interpretation`20of`20what X`09`20*`09makes`20a`20block`20interesting.`20`20It`20means`20ALL`20the X`09`20*`09non`20NUL`20character`20are`20either`20white`20space`20or X`09`20*`09printable.`20`20This`20should`20correspond`20nicely`20to X`09`20*`09common`20C`20source`20code`20though.`20`20The`20extra`20check X`09`20*`09on`20"useful"`20ensures`20that`20neither`20is`20zero. X`09`20*/ X`09if((interesting`20==`20useful)`20`26`26`20useful`20)`20`7B X`09`09if(`20verbose`20>`201`20) X`09`09`09printf("#`5Cn#`5CtBlock`20%d`20(%d).`5Cn#`5Cn",`20block,`20size)`20; V X X`09`09if(`20verbose`20) X`09`09`09fprintf(stderr,`20format,`20block,`20size, X`09`09`09`09(100.0`20*`20useful)/interesting,`20useful)`20; X X`09`09/* X`09`09`20*`09For`20fragments`20with`20NULs`20at`20the`20end,`20fputs`20will X`09`09`20*`09do`20the`20reasonable`20and`20not`20print`20the`20NULs.`20`20If X`09`09`20*`09the`20block`20runs`20into`20the`20next`20one,`20then`20its X`09`09`20*`09length`20will`20appear`20to`20be`20longer`20than`20the`20size. X`09`09`20* X`09`09`20*`09When`20this`20is`20the`20case`20limit`20the`20write`20by`20using V X`09`09`20*`09fwrite. X`09`09`20*/ X`09`09if(`20strlen(frag)`20<=`20size`20) X`09`09`09fputs(frag,`20stdout)`20; X`09`09else X`09`09`09fwrite(frag,`20sizeof(char),`20size,`20stdout)`20; X`09`7D X`7D X`0C XRecovery`20program`20-`20Makefile.alpha X X# X#`09Author:`20`20Alan`20Rollow,`20Subsystems`20Engineering,`20Digital`20Equipm Vent`20Corp. X#`09File:`09`20%M% X#`09Date:`09`20%G% X#`09Version:`20%I% X# X#`09%M%`20-`20Makefile`20for`20prototype`20recovery. X# XSOURCES=recover.c`20utility.c`20examine.c XOBJECTS=recover.o`20utility.o`20examine.o X# XCFLAGS=-O X Xrecover`09:`20$(OBJECTS) X`09$(CC)`20-o`20recover`20$(CFLAGS)`20$(OBJECTS) X Xlint`09:`20$(SOURCES) X`09lint`20$(SOURCES) X X# X#`09SCCS`20rules. X# Xrecover.c`20: X`09sccs`20get`20$@ X Xutility.c`20: X`09sccs`20get`20$@ X Xexamine.c`20: X`09sccs`20get`20$@ X Xfill.c`20: X`09sccs`20get`20$@ X X# X#`09Dependencies.`20`20cc`20-E`20-M`20*.c`20`7C`20sort`20`7C`20uniq`20>>`20Mak Vefile.alpha X# Xexamine.o:`09/usr/include/NLchar.h Xexamine.o:`09/usr/include/NLctype.h Xexamine.o:`09/usr/include/ctype.h Xexamine.o:`09/usr/include/float.h Xexamine.o:`09/usr/include/fp_class.h Xexamine.o:`09/usr/include/mach/machine/vm_types.h Xexamine.o:`09/usr/include/machine/endian.h Xexamine.o:`09/usr/include/machine/machlimits.h Xexamine.o:`09/usr/include/machine/machparam.h Xexamine.o:`09/usr/include/machine/machtime.h Xexamine.o:`09/usr/include/standards.h Xexamine.o:`09/usr/include/stdio.h Xexamine.o:`09/usr/include/stdlib.h Xexamine.o:`09/usr/include/sys/limits.h Xexamine.o:`09/usr/include/sys/localedef.h Xexamine.o:`09/usr/include/sys/param.h Xexamine.o:`09/usr/include/sys/rt_limits.h Xexamine.o:`09/usr/include/sys/secdefines.h Xexamine.o:`09/usr/include/sys/signal.h Xexamine.o:`09/usr/include/sys/syslimits.h Xexamine.o:`09/usr/include/sys/types.h Xexamine.o:`09/usr/include/ufs/fs.h Xexamine.o:`09examine.c Xrecover.o:`09/usr/include/errno.h Xrecover.o:`09/usr/include/float.h Xrecover.o:`09/usr/include/fp_class.h Xrecover.o:`09/usr/include/mach/machine/vm_types.h Xrecover.o:`09/usr/include/machine/endian.h Xrecover.o:`09/usr/include/machine/machlimits.h Xrecover.o:`09/usr/include/machine/machparam.h Xrecover.o:`09/usr/include/machine/machtime.h Xrecover.o:`09/usr/include/standards.h Xrecover.o:`09/usr/include/stdio.h Xrecover.o:`09/usr/include/stdlib.h Xrecover.o:`09/usr/include/string.h Xrecover.o:`09/usr/include/sys/access.h Xrecover.o:`09/usr/include/sys/fcntl.h Xrecover.o:`09/usr/include/sys/file.h Xrecover.o:`09/usr/include/sys/limits.h Xrecover.o:`09/usr/include/sys/mode.h Xrecover.o:`09/usr/include/sys/mount.h Xrecover.o:`09/usr/include/sys/param.h Xrecover.o:`09/usr/include/sys/rt_limits.h Xrecover.o:`09/usr/include/sys/secdefines.h Xrecover.o:`09/usr/include/sys/signal.h Xrecover.o:`09/usr/include/sys/stat.h Xrecover.o:`09/usr/include/sys/syslimits.h Xrecover.o:`09/usr/include/sys/types.h Xrecover.o:`09/usr/include/ufs/fs.h Xrecover.o:`09recover.c Xutility.o:`09/usr/include/errno.h Xutility.o:`09/usr/include/float.h Xutility.o:`09/usr/include/fp_class.h Xutility.o:`09/usr/include/io/common/devio.h Xutility.o:`09/usr/include/mach/machine/vm_types.h Xutility.o:`09/usr/include/machine/endian.h Xutility.o:`09/usr/include/machine/machlimits.h Xutility.o:`09/usr/include/machine/machparam.h Xutility.o:`09/usr/include/machine/machtime.h Xutility.o:`09/usr/include/standards.h Xutility.o:`09/usr/include/stdio.h Xutility.o:`09/usr/include/stdlib.h Xutility.o:`09/usr/include/sys/access.h Xutility.o:`09/usr/include/sys/devio.h Xutility.o:`09/usr/include/sys/fcntl.h Xutility.o:`09/usr/include/sys/file.h Xutility.o:`09/usr/include/sys/fs_types.h Xutility.o:`09/usr/include/sys/ioctl.h Xutility.o:`09/usr/include/sys/ioctl_compat.h Xutility.o:`09/usr/include/sys/limits.h Xutility.o:`09/usr/include/sys/mode.h Xutility.o:`09/usr/include/sys/mount.h Xutility.o:`09/usr/include/sys/param.h Xutility.o:`09/usr/include/sys/rt_limits.h Xutility.o:`09/usr/include/sys/secdefines.h Xutility.o:`09/usr/include/sys/signal.h Xutility.o:`09/usr/include/sys/stat.h Xutility.o:`09/usr/include/sys/syslimits.h Xutility.o:`09/usr/include/sys/ttychars.h Xutility.o:`09/usr/include/sys/ttydefaults.h Xutility.o:`09/usr/include/sys/ttydev.h Xutility.o:`09/usr/include/sys/types.h Xutility.o:`09/usr/include/ufs/fs.h Xutility.o:`09utility.c X`0C XRecovery`20program`20-`20recover.c X X/* X`20*`09Author:`20`20Alan`20Rollow,`20Subsystems`20Engineering,`20Digital`20Equ Vipment`20Corp. X`20*`09File:`09`20recover.c X`20*`09Date:`09`207/16/94 X`20*`09Version:`201.8 X`20* X`20*`09recover.c`20-`20Given`20a`20file`20system`20name,`20examine`20all`20the V`20blocks X`20*`09that`20are`20free. X`20*/ X#ifndef`09lint Xstatic`09char`09SccsId`5B`5D`20=`20"@(#)recover.c`091.8`20(recover)`207/16/94" V`20; X#endif X X#include`20 X#include`20 X#include`20 X#include`20 X X#include`20 X#include`20 X#include`20 X#include`20 X X#include`20 X X/* X`20*`09I'm`20not`20sure`20why`20this`20trick`20is`20used,`20but`20it`20seems X`20*`09to`20work.`20`20When`20not`20doing`20this`20I`20have`20sometimes`20noti Vced X`20*`09"Bad`20argument"`20on`20reads.`20`20Probably`20has`20something`20to X`20*`09do`20with`20alignment. X`20*/ Xunion`20`7B X`09struct`20fs`20sb`20; X`09char`09pad`5BMAXBSIZE`5D`20; X`7D`20sblock`20; X Xunion`20`7B X`09struct`20cg`20cg`20; X`09char`09pad`5BMAXBSIZE`5D`20; X`7D`20cgroup`20; X X#define`09cylinder_group`20cgroup.cg X#define`09superblock`20`20`20`20`20sblock.sb X X/* X`20*`09Local`20data`20only`20needed`20here. X`20*/ Xstatic`09char`09*module`20=`20"main"`20; X X/* X`20*`09Needed`20by`20other`20modules. X`20*/ Xchar`09*program`20; Xint`09verbose`20=`200`20; X X/* X`20*`09Functions`20that`20don't`20return`20(int). X`20*/ Xvoid`09exit(),`20sync(),`20abort(); X X/* X`20*`09Prototypes. X`20*/ Xvoid`09bread(int,`20daddr_t,`20char`20*,`20int)`20; Xvoid`09examine(int,`20daddr_t,`20int,`20int)`20; Xvoid`09examine_string(int,`20daddr_t,`20int,`20int,`20int)`20; Xint`09file_to_special(char`20*,`20char`20*,`20int)`20; Xint`09file_to_cgn(char`20*,`20struct`20fs`20*)`20; Xvoid`09one_group(int,`20int,`20struct`20fs`20*)`20; Xvoid`09examine_cg(int,`20struct`20cg`20*,`20int)`20; Xint`09close(int)`20; X X/* X`20*`20 X`20*/ Xhelp(char`20*name) X`7B X`09fprintf(stderr,`20"usage:`20%s`20`5B`20options`20`5D`20special`20`5B`20hint V`20`5D`5Cn",`20name)`20; X`09fprintf(stderr,`20"`5Cn`20`20`20`20Options:`5Cn`5Cn")`20; X`09fprintf(stderr,`20"`5Ct-v`20`20-`20Verbose`20output.`5Cn")`20; X`09fprintf(stderr,`20"`5Ct-vv`20-`20Very`20Verbose`20output.`5Cn")`20; X`09fprintf(stderr,`20"`5Ct-h`20`20-`20This`20help`20message.`5Cn`5Cn")`20; X X`09exit(-1)`20; X`7D X/* X`20*`09Draw`20a`20picture`20of`20a`20file`20system. X`20*/ Xmain(int`20argc,`20char`20*argv`5B`5D) X`7B X`09register`20fd,`20cgn,`20c`20; X`09char`09special`5BMAXPATHLEN+1`5D,`20*file_hint`20=`20NULL`20; X`09extern`20optind`20; X X`09program`20=`20argv`5B0`5D`20; X X`09while((c`20=`20getopt(argc,`20argv,`20"vh"))`20!=`20EOF`20) X`09`09switch(`20c`20)`20`7B X`09`09case`20'v': X`09`09`09verbose++`20; X`09`09`09break`20; X`09`09default: X`09`09case`20'h': X`09`09`09help(argv`5B0`5D)`20; X`09`09`09break`20; X`09`09`7D X X`09if(`20optind`20==`20argc`20) X`09`09help(argv`5B0`5D)`20; X`09else`20`7B X`09`09file_to_special(argv`5Boptind`5D,`20special,`200)`20; X X`09`09optind++`20; X X`09`09if(`20optind`20!=`20argc`20) X`09`09`09file_hint`20=`20argv`5Boptind`5D`20; X`09`7D X X`09/* X`09`20*`09Open`20the`20file. X`09`20*/ X`09if((fd`20=`20open(special,`20O_RDONLY))`20==`20-1`20)`20`7B X`09`09fprintf(stderr,`20"%s:`20%s:`20Can't`20open`20%s:`20%s.`5Cn",`20program, V X`09`09`09module,`20special,`20strerror(errno))`20; X`09`09exit(errno)`20; X`09`7D X`09else`20if(`20verbose`20) X`09`09fprintf(stderr,`20"Using`20%s.`5Cn",`20special)`20; X X`09/* X`09`20*`09I`20follow`20the`20tradition`20of`20other`20programs`20that`20do X`09`20*`09this`20sort`20of`20thing...`20`20I`20plead`20guility`20to`20perpet- V X`09`20*`09trating`20folklore... X`09`20*/ X`09sync()`20; X X`09/* X`09`20*`09Read`20the`20super`20block. X`09`20*/ X`09bread(fd,`20SBLOCK,`20(char`20*)`26superblock,`20SBSIZE)`20; X`09 X`09/* X`09`20*`09Verify`20that`20there`20is`20a`20file`20system`20here. X`09`20*/ X`09if(`20superblock.fs_magic`20!=`20FS_MAGIC`20)`20`7B X`09`09fprintf(stderr,`20"%s:`20%s:`20%s`20doesn't`20have`20a`20file`20system. V`5Cn", X`09`09`09program,`20module,`20special)`20; X`09`09exit(-1)`20; X`09`7D X X`09/* X`09`20*`09TODO:`20There's`20really`20no`20reason`20why`20this`20couldn't X`09`20*`09also`20allow`20an`20explicit`20list`20of`20cylinder`20group X`09`20*`09numbers.`20`20Certainly`20a`20list`20of`20file`20names`20would X`09`20*`09be`20almost`20trivial. X`09`20*/ X`09if(`20file_hint`20)`20`7B X`09`09cgn`20=`20file_to_cgn(file_hint,`20`26superblock)`20; X X`09`09if(`20verbose`20) X`09`09`09fprintf(stderr,`20"Limit`20search`20to`20CGN`20#%d.`5Cn",`20cgn)`20; V X X`09`09one_group(fd,`20cgn,`20`26superblock)`20; X`09`7D X`09else X`09`09for(cgn`20=`200;`20cgn`20<`20superblock.fs_ncg;`20cgn++) X`09`09`09one_group(fd,`20cgn,`20`26superblock)`20; X X`09/* X`09`20*`09Close`20the`20file. X`09`20*/ X`09if(`20close(fd)`20==`20-1`20) X`09`09fprintf(stderr,`20"%s:`20%s:`20Can't`20close`20%s:`20%s.`5Cn", X`09`09`09program,`20module,`20special,`20strerror(errno))`20; X X`09return`200`20; X`7D X X/* X`20*`09See`20the`20body`20of`20the`20program`20for`20the`20comments.`20`20The V`20biggest X`20*`09problem`20with`20this`20function`20at`20the`20moment`20is`20that`20it V`20reads X`20*`09the`20file`20system`20data`20one`20fragment`20at`20a`20time.`20`20It`20 Vshould X`20*`09examine`20the`20space/time`20tradeoff`20bit`20of`20the`20superblock`20a Vnd X`20*`09try`20to`20read`20multiple`20appropriate`20fragments`20at`20once. X`20* X`20*`09But`20that`20is`20also`20something`20for`20the`20old`20TODO`20list. X`20*/ Xvoid Xone_group(int`20fd,`20int`20cgn,`20struct`20fs`20*sp) X`7B X`09register`20bit,`20length`20; X`09register`20u_char`20*cp`20; X`09register`20struct`20cg`20*cgp`20; X X`09/* X`09`20*`09Read`20the`20cylinder`20group`20data.`20`20You`20needn't`20really X`09`20*`09understand`20all`20this,`20but`20the`20arguments`20to`20bread X`09`20*`09are: X`09`20* X`09`20*`09bread(fd,`20offset,`20address,`20size)`20; X`09`20* X`09`20*`09fd`20-`20The`20file`20descriptor`20from`20which`20to`20read. X`09`20* X`09`20*`09The`20offset`20is`20the`20disk`20LBN`20where`20the`20cylinder X`09`20*`09group`20starts.`20`20This`20can`20be`20found`20using`20the`20two X`09`20*`09macros`20fsbtodb()`20and`20cgtod().`20`20The`20first`20converts X`09`20*`09file`20system`20block`20numbers`20to`20disk`20block`20numbers. X`09`20*`09The`20second`20is`20the`20start`20of`20the`20cylinder`20group`20data V X`09`20*`09for`20the`20particular`20cylinder`20group. X`09`20* X`09`20*`09The`20address`20is`20simply`20the`20address`20of`20some`20space X`09`20*`09large`20enough`20to`20hold`20a`20cylinder`20group. X`09`20* X`09`20*`09The`20size`20is`20found`20taking`20the`20difference`20of`20the X`09`20*`09file`20system`20block`20where`20the`20inodes`20start`20and X`09`20*`09where`20the`20cylinder`20group`20data`20starts`20and`20then X`09`20*`09multiplied`20by`20the`20fragment`20size. X`09`20*/ X`09cgp`20=`20`26cylinder_group`20; X X`09bread(fd,`20fsbtodb(sp,`20cgtod(sp,`20cgn)),`20(char`20*)cgp,`20 X`09`09(int)((cgimin(sp,`20cgn)`20-`20cgtod(sp,`20cgn))`20*`20sp->fs_fsize))`20 V; X X`09/* X`09`20*`09Verify`20this`20really`20is`20a`20cylinder`20group. X`09`20*/ X`09if(`20cgp->cg_magic`20!=`20CG_MAGIC`20)`20`7B X`09`09fprintf(stderr,`20"%s:`20#%d:`20Not`20a`20cylinder`20group.`5Cn", X`09`09`09program,`20cgn)`20; X X`09`09return`20; X`09`7D X X`09/* X`09`20*`09A`20user`20function`20provided`20to`20do`20something`20based`20on`20 V X`09`20*`09the`20cylinder`20group`20number.`20`20The`20example`20prints`20a X`09`20*`09simple`20header. X`09`20*/ X`09examine_cg(fd,`20cgp,`20cgn)`20; X X`09/* X`09`20*`09On`20OSF`20there`20are`20two`20choices`20for`20where`20the`20bit`20m Vap X`09`20*`09is`20and`20it`20depends`20on`20the`20value`20on`20the`20magic`20numb Ver. X`09`20*`09The`20macro`20"cg_blksfree"`20takes`20care`20of`20it... X`09`20* X`09`20*`09For`20ULTRIX`20it`20is`20simply`20where`20it`20is`20supposed`20to`20 Vbe... X`09`20*/ X#ifdef`09__osf__ X`09cp`20=`20(u_char`20*)cg_blksfree(cgp)`20; X#else X`09cp`20=`20(u_char`20*)`26cgp->cg_free`5B0`5D`20; X#endif X X`09/* X`09`20*`09Check`20each`20bit`20of`20the`20free`20list`20and`20call`20examine X`09`20*`09for`20each`20that`20is`20set.`20`20Two`20version`20of`20the`20fragme Vnt X`09`20*`09examination`20code`20are`20illustrated.`20`20When`20SLOW_VERSION X`09`20*`09is`20defined,`20a`20function`20to`20read`20and`20examine`20one`20(si Vngle) X`09`20*`09fragment`20is`20used.`20`20This`20tends`20to`20be`20slow. X`09`20* X`09`20*`09The`20other`20version`20uses`20run`20length`20counting`20to`20count V X`09`20*`09the`20length`20of`20a`20string`20of`20free`20fragments`20and`20uses V X`09`20*`09a`20function`20that`20examines`20them`20in`20blocks.`20`20In`20the X`09`20*`09end,`20the`20work`20is`20still`20done`20a`20fragment`20at`20a`20time V, X`09`20*`09but`20this`20help`20the`20I/O`20rate. X`09`20*/ X`09for(bit`20=`200,`20length`20=`200;`20bit`20<`20cgp->cg_ndblk;`20bit++) X`09`09if(`20cp`5Bbit`20/`20NBBY`5D`20`26`20(1`20<<`20(bit`20`26`20(NBBY-1)))) V X#ifdef`09SLOW_VERSION X`09`09`09examine(fd,`20fsbtodb(sp,`20bit`20+`20(sp->fs_fpg`20*`20cgn)), X`09`09`09`09(int)sp->fs_fsize,`20cgn)`20; X#else X`09`09`09length++`20; X`09`09else`20`7B X`09`09`09if(`20length`20)`20`7B X`09`09`09`09register`20b`20; X X`09`09`09`09b`20=`20(sp->fs_fpg`20*`20cgn)`20+`20(bit`20-`20length)`20; X X`09`09`09`09examine_string(fd,`20fsbtodb(sp,`20b),`20length, X`09`09`09`09`09sp->fs_fsize,`20cgn)`20; X X`09`09`09`09length`20=`200`20; X`09`09`09`7D X`09`09`7D X#endif X X#ifndef`09SLOW_VERSION X`09if(`20length`20)`20`7B X`09`09register`20b`20=`20sp->fs_fpg`20*`20cgn`20+`20(bit`20-`20length)`20; X X`09`09examine_string(fd,`20fsbtodb(sp,`20b),`20length,`20sp->fs_fsize,`20cgn) V`20; X`09`7D X#endif X`7D X X`0C XRecovery`20program`20-`20utility.c X X/* X`20*`09Author:`20`20Alan`20Rollow,`20DBS/SRM,`20Digital`20Equipment`20Corp. X`20*`09File:`09`20utility.c X`20*`09Date:`09`206/17/94 X`20*`09Version:`201.3 X`20* X`20*`09utility.c`20-`20Utility`20functions`20for`20mucking`20around`20the X`20*`09file`20system. X`20*/ X#ifndef`09lint Xstatic`09char`09SccsId`5B`5D`20=`20"@(#)utility.c`091.3`20(inode)`206/17/94" V`20; X#endif X X#include`20 X#include`20 X#include`20 X#include`20 X#include`20 X#include`20 X#include`20 X#include`20 X X#include`20 X X#include`20 X#include`20 X#include`20 X X/*`20 X`20*`09Things`20needed`20by`20the`20error`20functions. X`20*/ Xstatic`09char`09*module`20=`20"utility"`20; X X/* X`20*`09Things`20that`20are`20elsewhere. X`20*/ Xextern`09char`09*program`20; X X/* X`20*`09Things`20that`20don't`20return`20(int). X`20*/ Xoff_t`09lseek()`20; Xchar`09*strncpy(),`20*strerror()`20; X X/* X`20*`09Prototypes. X`20*/ Xvoid`09convert_buffered_path(char`20*result,`20char`20*source,`20size_t`20leng Vth)`20; X X#ifdef`09__osf__ Xint`09statfs(char`20*,`20struct`20statfs`20*,`20int)`20; Xssize_t`09read(int,`20char`20*,`20size_t)`20; X#else Xint`09statfs(char`20*,`20struct`20fs_data`20*)`20; Xint`09read(int,`20char`20*,`20int)`20; X#endif X X/* X`20*`09A`20table`20of`20the`20file`20types. X`20*/ Xstatic`20struct`20`7B X`09mode_t`09mode`20; X`09char`09*type`20; X`7D`20table`5B`5D`20=`20`7B X`09S_IFDIR,`20`20"directory", X`09S_IFCHR,`20`20"character", X`09S_IFBLK,`20`20"buffered", X`09S_IFREG,`20`20"regular", X`09S_IFLNK,`20`20"symbolic`20link", X`09S_IFSOCK,`20"socket", X`09S_IFIFO,`20`20"named`20pipe", X`7D; X X/* X`20*`09Return`20the`20file`20type`20string`20given`20the`20file`20mode. X`20*/ Xchar`20* Xf_types(mode_t`20mode) X`7B X`09int`09i`20; X X`09mode`20`26=`20S_IFMT`20; X X`09for(i`20=`200;`20i`20<`20sizeof(table)/sizeof(table`5B0`5D);`20i++) X`09`09if(`20mode`20==`20table`5Bi`5D.mode`20) X`09`09`09return`20table`5Bi`5D.type`20; X X`09return`20"unknown"`20; X`7D X X/* X`20*`09Take`20a`20file`20name`20and`20return`20the`20name`20of`20the`20device V`20that X`20*`09it`20is`20on`20and`20the`20inode`20number. X`20*/ Xfile_to_special(char`20*path,`20char`20*special,`20int`20device) X`7B X#ifdef`09__osf__ X`09struct`20statfs`20fs_data`20; X#else X`09struct`20fs_data`20fs_data`20; X#endif X`09struct`20stat`20`20`20`20file_data`20; X X`09/* X`09`20*`09Determine`20if`20this`20a`20regular`20file`20or`20a`20special X`09`20*`09device.`20`20If`20it's`20a`20device`20look`20at`20the`20device X`09`20*`09flag`20to`20see`20if`20we`20treat`20it`20as`20a`20device`20that X`09`20*`09might`20have`20a`20file`20system`20on`20it`20or`20if`20the`20user X`09`20*`09really`20wants`20the`20inode`20information`20about`20the X`09`20*`09special`20device`20file. X`09`20*/ X`09if(`20stat(path,`20`26file_data)`20==`20-1`20)`20`7B X`09`09fprintf(stderr,`20"%s:`20%s:`20stat(2)`20on`20%s`20failed:`20%s.`5Cn", X`09`09`09program,`20module,`20path,`20strerror(errno))`20; X`09`09exit(errno)`20; X`09`7D X X`09/* X`09`20*`09It's`20a`20special`20device`20file.`20`20We`20look`20at`20the`20devi Vce X`09`20*`09to`20see`20if`20the`20user`20is`20interested`20in`20the`20special`20 Vdevice X`09`20*`09file`20or`20the`20file`20system`20on`20that`20device.`20`20The`20dev Vice X`09`20*`09flags`20gets`20set`20to`201`20if`20the`20-device`20flag`20is`20speci Vfied X`09`20*`09on`20the`20command`20line.`20`20The`20default`20case`20is`20to`20tre Vat X`09`20*`09special`20device`20files`20as`20file`20systems. X`09`20*/ X`09if(`20S_ISBLK(file_data.st_mode)`20`7C`7C`20S_ISCHR(file_data.st_mode))`20 V`7B X`09`09if(`20device`20==`200`20)`20`7B X`09`09`09(void)strncpy(special,`20path,`20MAXPATHLEN)`20; X`09`09`09return`200`20; X`09`09`7D X`09`7D X X`09/* X`09`20*`09Get`20the`20file`20system`20information`20first. X`09`20*/ X#ifdef`09__osf__ X`09if(`20statfs(path,`20`26fs_data,`20sizeof(fs_data))`20==`20-1`20)`20`7B X#else X`09if(`20statfs(path,`20`26fs_data)`20==`20-1`20)`20`7B X#endif X`09`09fprintf(stderr,`20"%s:`20%s:`20statfs(3)`20on`20%s`20failed:`20%s.`5Cn", V X`09`09`09program,`20module,`20path,`20strerror(errno))`20; X`09`09exit(errno)`20; X`09`7D X X`09/* X`09`20*`09Verify`20that`20this`20is`20local`20UFS`20file`20system. X`09`20*/ X#ifdef`09__osf__ X`09if(`20fs_data.f_type`20!=`20MOUNT_UFS`20)`20`7B X#else X`09if(`20fs_data.fd_fstype`20!=`20GT_ULTRIX`20)`20`7B X#endif X`09`09fprintf(stderr,`20"%s:`20%s:`20Unsupported`20file`20system`20type:`20%s. V`5Cn", X`09`09`09program,`20module,`20 X#ifdef`09__osf__ X`09`09`09mnt_names`5Bfs_data.f_type`5D)`20; X#else X`09`09`09gt_names`5Bfs_data.fd_fstype`5D)`20; X#endif X`09`09exit(-1)`20; X`09`7D X X`09/* X`09`20*`09Copy`20the`20device`20name`20and`20translate`20it`20into`20a X`09`20*`09raw`20device`20instead`20of`20buffered. X`09`20*/ X#ifdef`09__osf__ X`09convert_buffered_path(special,`20fs_data.f_mntfromname,`20MAXPATHLEN)`20; X#else X`09convert_buffered_path(special,`20fs_data.fd_devname,`20MAXPATHLEN)`20; X#endif X X`09/* X`09`20*`09File`20maps`20can`20only`20be`20made`20for`20regular`20files,`20dire Vctories X`09`20*`09and`20links. X`09`20*/ X`09if((file_data.st_mode`20`26`20(S_IFREG`7CS_IFDIR`7CS_IFLNK))`20==`200`20) V`20`7B X`09`09fprintf(stderr,`20"%s:`20%s:`20Unsupported`20file`20type:`20%s.`5Cn", X`09`09`09program,`20module,`20f_types(file_data.st_mode))`20; X`09`09exit(-1)`20; X`09`7D X X`09/* X`09`20*`09If`20this`20is`20the`20mount`20point`20treat`20it`20same`20way`20we V`20do X`09`20*`09special`20device`20files.`20`20If`20"device"`20is`20set`20to`200`20t Vhen X`09`20*`09we're`20interested`20in`20the`20whole`20file`20system.`20`20Otherwis Ve X`09`20*`09we're`20only`20interested`20in`20that`20inode. X`09`20*/ X`09if(`20file_data.st_ino`20==`202`20`26`26`20device`20==`200`20) X`09`09return`200`20; X`09else X`09`09return`20file_data.st_ino`20; X`7D X X/* X`20*`09Seek`20to`20and`20read`20a`20device`20block`20number. X`20*/ Xvoid Xbread(int`20fd,`20daddr_t`20bno,`20char`20*buf,`20int`20size) X`7B X`09off_t`20offset`20; X X`09offset`20=`20(off_t)bno`20; X`09offset`20*=`20DEV_BSIZE`20; X X`09if(`20lseek(fd,`20offset,`20SEEK_SET)`20==`20-1`20)`20`7B X`09`09fprintf(stderr,`20"%s:`20%s:`20Can't`20seek`20to`20block`20%u:`20%s.`5Cn V", X`09`09`09program,`20module,`20(char`20*)bno,`20strerror(errno))`20; X`09`09exit(errno)`20; X`09`7D X X`09if(`20read(fd,`20buf,`20size)`20==`20-1`20)`20`7B X`09`09fprintf(stderr,`20"%s:`20%s:`20Can't`20read`20block`20%u:`20%s.`5Cn", X`09`09`09program,`20module,`20(char`20*)bno,`20strerror(errno))`20; X`09`09exit(errno)`20; X`09`7D X`7D X X/* X`20*`09Copy`20the`20device`20name`20and`20translate`20it`20into`20a X`20*`09raw`20device`20instead`20of`20buffered.`20`20To`20do`20this X`20*`09we'll`20make`20some`20assumptions. X`20* X`20*`091.`20`20That`20the`20part`20after`20the`20last`20'/'`20is`20interesting V X`20*`09`20`20`20`20and`20the`20rest`20looks`20like:`20/dev/. X`20* X`20*`092.`20`20That`20we're`20always`20handed`20the`20name`20of`20a`20buffered V X`20*`09`20`20`20`20device. X`20* X`20*`09Based`20on`20these`20two`20assumptions`20we`20can`20split`20the`20strin Vg`20at X`20*`09the`20last`20'/',`20copy`20the`20first`20part`20into`20the`20result`20s Vtring X`20*`09append`20an`20'r'`20and`20then`20append`20the`202nd`20part. X`20*/ Xvoid Xconvert_buffered_path(char`20*result,`20char`20*source,`20size_t`20length) X`7B X`09char`09*strrchr(),`20*slash`20; X X`09/* X`09`20*`09Find`20the`20last`20slash.`20`20If`20there`20isn't`20one,`20just X`09`20*`09copy`20the`20string`20and`20return. X`09`20*/ X`09if((slash`20=`20strrchr(source,`20'/'))`20==`20NULL`20)`20`7B X`09`09(void)strncpy(result,`20source,`20length)`20; X`09`09return`20; X`09`7D X X`09/* X`09`20*`09Null`20terminate`20the`20first`20part`20and`20advance`20the`20pointe Vr. X`09`20*/ X`09*slash++`20=`20'`5C0'`20; X X`09/* X`09`20*`09Make`20sure`20the`20'/'`20wasn't`20the`20last`20character`20in`20the V X`09`20*`09string.`20`20If`20it`20we`20can`20just`20copy`20the`20first`20part V`20into X`09`20*`09to`20the`20result`20and`20return. X`09`20*/ X`09if(`20*slash`20==`20'`5C0'`20)`20`7B X`09`09(void)strncpy(result,`20source,`20length)`20; X`09`09return`20; X`09`7D X X`09/* X`09`20*`09Now`20we`20can`20combine`20the`20two`20parts`20back`20together`20int Vo X`09`20*`09a`20new`20string. X`09`20*/ X`09(void)sprintf(result,`20"%s/r%s",`20source,`20slash)`20; X X`09return`20; X`7D X X/*`0C*/ X/* X`20*`09Given`20a`20file`20name`20and`20address`20of`20a`20superblock,`20conver Vt X`20*`09it`20into`20a`20cylinder`20group`20number`20where`20the`20file`20probab Vly X`20*`09resides. X`20*/ Xfile_to_cgn(char`20*file,`20struct`20fs`20*sp) X`7B X`09struct`20stat`20data`20; X X`09/* X`09`20*`09Treat`20two`20special`20cases. X`09`20* X`09`20*`09#`20=`20Inode`20number. X`09`20*`09@`20=`20Cylinder`20group`20number. X`09`20*/ X`09if(`20*file`20==`20'#'`20) X`09`09return`20itog(sp,`20atoi(file`20+`201))`20; X`09else`20if(`20*file`20==`20'@'`20) X`09`09return`20atoi(file`20+`201)`20; X X`09/* X`09`20*`09If`20this`20doesn't`20work,`20assume`20the`20first`20cylinder`20grou Vp. X`09`20*/ X`09if(`20stat(file,`20`26data)`20==`20-1`20)`20`7B X`09`09fprintf(stderr,`20"%s:`20%s:`20Can't`20stat(2)`20%s:`20%s.`5Cn",`20progr Vam, X`09`09`09module,`20file,`20strerror(errno))`20; X`09`09return`200`20; X`09`7D X X`09return`20itog(sp,`20data.st_ino)`20; X`7D $ call unpack RECOVR.DSJ;1 1367050761 "" 53 1 1 $ v=f$verify(v) $ exit