macintosh@felix.UUCP (03/12/87)
[DeskCheck Source] [Moderator's Note: See the mod.mac.binaries posting for a description of DeskCheck and the binary application. The source is presented here in ascii form so that people with or without Macs can take a look at it.] --- #!/bin/sh # shar: Shell Archiver # Run the following text with /bin/sh to create: # DeskCheck/DeskCheck.asm # DeskCheck/FCensus.asm sed 's/^X//' << 'SHAR_EOF' > DeskCheck/DeskCheck.asm X XDebug equ 0 ; make non-zero for debugging X X String_Format 0 ; no string padding X X X; DeskCheck.asm: Find out whether everyone's bundle is legit. X; Ephraim Vishniac / P.O. Box 1357 / East Arlington, MA 02174 X; This program is in the public domain. X X; X X Include Traps.D X Include SysEquX.D X Include FSEqu.D X Include ToolEqu.D X Include SysErr.D X Include PackMacs.Txt X X; Our Macros X XMACRO DoAlert AlertNumber = X IF Debug X _Debugger X ENDIF X ; Alert (AlertNumber:INT, NIL:ProcPtr) : INT; X clr.w -(sp) ; space for result X move.w #{AlertNumber},-(sp) ; alert number X clr.l -(sp) ; NIL filter X _Alert X move.w (sp)+,d0 ; d0 = button hit X cmp.w #OKitem,d0 ; standard test X | X XMACRO DebugPoint = X IF Debug X _Debugger X ENDIF X | X XMACRO UseUs = X move.w OurMap(a5),CurMap ; make ours the current map X | X XMACRO UseThem = X move.w TheirMap(a5),CurMap ; make theirs the current map X | X XMACRO SetParamText = X move.l ParamZero(a5),-(sp) ; push our paramtext pointers X move.l ParamOne(a5),-(sp) X move.l ParamTwo(a5),-(sp) X move.l ParamThree(a5),-(sp) X _ParamText X | X Xmacro DNAME Name = X dc.b '{Name|0:8}' X .align 2 X | X X X; Our alerts X XGreeting equ 128 ; say hello XFarewell equ 129 ; say goodbye XSetVolFailed equ 130 ; couldn't SetVol XOpenResFailed equ 131 ; couldn't OpenResFile XBundleBitClear equ 132 ; has bundles, but no bundle bit XNumberOfTypes equ 133 ; bundles has unusual number of types XNoSigResource equ 134 ; couldn't load signature resource XNovelType equ 135 ; neither ICN#, nor FREF XMissingBundle equ 136 ; bundle is too short XExcessBundle equ 137 ; bundle runs too long XFunnyIcon equ 138 ; ICN# isn't 256 bytes XSmallFREF equ 139 ; FREF is less than six bytes XBigFREF equ 140 ; FREF is more than 262 bytes XMissingResource equ 141 ; can't find some bundled resource XDoVolumeAlert equ 142 ; should we do this volume? XNoIcons equ 143 ; no ICN# list in bundle XNoFREFs equ 144 ; no FREF list in bundle XBadLocalID equ 145 ; local ID unresolved XOrphanType equ 146 ; no FREF with this file type XOrphanCreator equ 147 ; no BNDL with matching signature X X X; Our dialogs X XCurrentFile equ 150 X X; Other miscellaneous equates X XOKitem equ 1 ; Item number for OK button XQuitItem equ 2 ; Item number for Quit button X X; Our globals X XOurMap ds.w 1 ; a word from our sponsor XTheirMap ds.w 1 ; equal time for the other guy XDialogPtr ds.l 1 ; current dialog XOtherBNDLs ds.w 1 ; 'background count' of BNDL resources XParamZero ds.l 1 ; our param zero text pointer XParamOne ds.l 1 ; our param one text pointer XParamTwo ds.l 1 ; our param two text pointer XParamThree ds.l 1 ; our param three text pointer XFileType ds.l 1 ; File Type of current file XFileCreator ds.l 1 ; File Creator of current file XTypeMatch ds.b 1 ; flag for file type matched XCreatorMatch ds.b 1 ; flag for file creator matched X X XDef FCensus X XDeskCheck X;------------------------------- Init Managers ---------------------------- X X pea -4(A5) ; Quickdraw's global area X _InitGraf ; Init Quickdraw X _InitFonts ; Init Font Manager X move.l #$FFFF,D0 ; Flush all events X _FlushEvents X _InitWindows ; Init Window Manager X _InitMenus ; Init Menu Manager X _TEInit ; Init Text Edit X clr.l -(SP) ; No restart procedure X _InitDialogs ; Init Dialog Manager X _InitCursor ; Turn on arrow cursor X X;------------------------------- Init Globals ----------------------------- X move.w CurMap,OurMap(a5) ; record our resource refnum X X ; we need to discount bundles in our file and the system X clr.w -(sp) X move.l #'BNDL',-(sp) ; How many bundles? X _CountResources X move.w (sp)+,OtherBNDLs(a5) ; save for later X X clr.l ParamZero(a5) ; clear our param text pointers X clr.l ParamOne(a5) X clr.l ParamTwo(a5) X clr.l ParamThree(a5) X X;-------------------------------Desk Check--------------------------------- X; Just do a census of all files on all volumes, running them X; through our bundle checker. X X DoAlert Greeting ; say hello X bne SayByeBye ; if not OK, split X X DebugPoint X X jsr CheckAllVols ; else test all volumes X DoAlert FareWell ; say goodbye XSayByeBye X _ExitToShell X X X; CheckAllVols: Check each mounted volume X XCAVinfo equ -ioVQElSize ; a handy parm block XVolumeName equ CAVinfo-256 ; name of current volume XLastLocal set VolumeName X XCheckAllVols X link a6,#LastLocal X lea CAVinfo(a6),a0 ; a0 = parm block X clr.l ioCompletion(a0) ; no completion routine X lea VolumeName(a6),a1 ; storage for volume name X move.l a1,ioFileName(a0) ; set in parm block X clr.w ioVolIndex(a0) ; clear index X@0 lea CAVinfo(a6),a0 ; a0 = parm block X clr.l VolumeName(a6) ; no volname yet X add.w #1,ioVolIndex(a0) ; advance to next volume X _GetVolInfo X cmp.w #nsvErr,d0 ; out of volumes? X beq @1 ; exit if so X move.l ioFileName(a0),ParamZero(a5) ; set param text zero X SetParamText X DoAlert DoVolumeAlert ; should we do this one? X bne @0 X lea CAVinfo(a6),a0 ; a0 = parm block X jsr CheckOneVol ; else check this volume X bra @0 ; and loop back X@1 clr.l ParamZero(a5) X unlk a6 X rts X DName CHECKALLVOLS X X; CheckOneVol: Survey a single volume X; Entry: a0 = _GetVolInfo poop on the volume to check X XTheItemType set -2 ; Dialog item type XTheItem set TheItemType-4 ; Dialog item handle XTheBox set TheItem-8 ; Dialog item box XLastLocal set TheBox X XCheckOneVol X link a6,#LastLocal X move.w ioVRefNum(a0),-(sp) ; save volume reference number X move.l ioFileName(a0),-(sp) ; save volume name pointer X X clr.l -(sp) ; space for result X move.w #CurrentFile,-(sp) ; dialog number X clr.l -(sp) ; take what we get X move.l #-1,-(sp) ; put this window in front X _GetNewDialog ; Pop the question X move.l (sp),DialogPtr(a5) ; save the dialog pointer X _SetPort ; make ours the current port X move.l DialogPtr(a5),-(sp) X _DrawDialog ; force complete dialog drawing X X move.l DialogPtr(a5),-(sp) X move.w #4,-(sp) ; item number 4 X pea TheItemType(a6) ; storage for item type X pea TheItem(a6) ; storage for item handle X pea TheBox(a6) ; storage for item box X _GetDItem X move.l (sp)+,a1 ; file name pointer X move.l TheItem(a6),-(sp) ; item handle X move.l a1,-(sp) ; point to file name X _SetIText ; set file name in dialog X X move.l #2,-(sp) ; root directory X pea CheckOneFile ; our file inspector X jsr FCensus ; scan everything X X move.l DialogPtr(a5),-(sp) ; push the dialog pointer X _DisposDialog ; and kill the dialog X X unlk a6 X rts X DName CHECKONEVOL X X; CheckOneFile(ParamBlock:ParmBlkPtr; dirID:longint):boolean X; Do the actual tests on a given file. X; A6 offsets XOldA6 set 0 XReturnAddr set OldA6+4 XDirID set ReturnAddr+4 ; directory ID XFileInfo set DirID+4 ; param block from _GetFileInfo XReturnValue set FileInfo+4 ; return value (0 = continue) XArgsSz set ReturnValue-DirID X; XParmBlk set OldA6-ioHVQElSize ; local parm block XErrString set ParmBlk-32 ; Str31 for error codes XTheItemType set ErrString-2 ; Dialog item type XTheItem set TheItemType-4 ; Dialog item handle XTheBox set TheItem-8 ; Dialog item box XLastLocal set TheBox X XCheckOneFile X link a6,#LastLocal X clr.w ReturnValue(a6) ; always continue search X X move.l DialogPtr(a5),-(sp) X move.w #2,-(sp) ; item number 2 X pea TheItemType(a6) ; storage for item type X pea TheItem(a6) ; storage for item handle X pea TheBox(a6) ; storage for item box X _GetDItem X move.l TheItem(a6),-(sp) ; item handle X move.l FileInfo(a6),a1 ; point to GetFileInfo stuff X move.l ioFileName(a1),-(sp) ; point to file name X _SetIText ; set file name in dialog X X ; is there a resource fork? X move.l FileInfo(a6),a1 ; point to _GetFileInfo stuff X tst.l ioFlRLgLen(a1) ; is there a resource fork? X beq @9 ; skip if not X X lea ParmBlk(a6),a0 ; point to parm block X clr.l ioCompletion(a0) X clr.l ioFileName(a0) X move.w ioVRefNum(a1),ioVRefNum(a0) ; volume from file info X move.l DirID(a6),ioWDDirID(a0) ; directory ID from file info X tst FSFCBLen ; HFS running? X bmi @0 ; branch if not X _HSetVol ; HFS, set volume and directory X bra @1 X@0 _SetVol ; MFS, just set volume X@1 move.w ioResult(a0),d0 ; did it work? X beq @2 ; skip if vol ok X X ext.l d0 X lea ErrString(a6),a0 X move.l a0,ParamZero(a5) ; move to param text ptrs X _NumToString X SetParamText X DoAlert SetVolFailed X bra @9 X X@2 move.l FileInfo(a6),a1 ; point to _GetFileInfo stuff X clr.w -(sp) ; for _OpenResFile result X move.l ioFileName(a1),-(sp) ; push given file name X move.b #0,ResLoad ; don't load resources X _OpenResFile ; give it a shot X move.b #-1,ResLoad ; do load resources X move.w (sp)+,d0 ; pop reference number X bpl @3 ; skip if reasonable number X X move.w ResErr,d0 ; get the error code X ext.l d0 X lea ErrString(a6),a0 X move.l a0,ParamZero(a5) ; move to param text ptrs X _NumToString X SetParamText X UseUs ; do we need this? X DoAlert OpenResFailed X bra @9 X X ; While the other file is open, we have to bracket our X ; alerts and stuff with 'UseUs' - 'UseThem' X X@3 cmp.w SysMap,d0 ; did we just open the system? X beq @9 ; skip ahead if so X cmp.w OurMap(a5),d0 ; is it us? X beq @9 ; skip ahead if so X move.w d0,TheirMap(a5) ; refnum of file under test X X ; Here's where we actually examine the file contents... X X ; Does this bozo have a bundle? X clr.w -(sp) X move.l #'BNDL',-(sp) ; How many bundles? X _CountResources X move.w (sp)+,d3 ; well? X cmp.w OtherBNDLs(a5),d3 ; discount other bundles X beq @5 ; skip if no more, close it up X X move.l FileInfo(a6),a1 ; point to _GetFileInfo stuff X move.l ioFlUsrWds+fdType(a1),FileType(a5) ; save file type X move.l ioFlUsrWds+fdCreator(a1),FileCreator(a5) ; ditto creator X clr.b TypeMatch(a5) ; no matches yet X clr.b CreatorMatch(a5) X X move.w ioFlUsrWds+fdFlags(a1),d0 ; d0 = file flags X btst #fHasBundle,d0 ; test bundle bit X bne @4 ; skip if set, that makes sense X X move.w D3,D0 X sub.w OtherBNDLs(a5),D0 X ext.l d0 X lea ErrString(a6),a0 X move.l a0,ParamZero(a5) ; move to param text ptrs X _NumToString X SetParamText X UseUs X DoAlert BundleBitClear X UseThem X X@4 move.w D3,D0 ; retrieve number of bundles X jsr TestBundles ; else go test the bundles X tst.b TypeMatch(a5) ; found FREF with our Type? X bne @6 ; skip if so X X lea ErrString+1(a6),a0 ; fudge alignment of string X move.l a0,ParamZero(a5) ; it's param text zero X move.b #4,(a0)+ ; set string length X move.l FileType(a5),(a0) ; and string contents X SetParamText X UseUs X DoAlert OrphanType X UseThem X@6 tst.b CreatorMatch(a5) ; found BNDL with our Creator? X bne @5 ; skip if so X X lea ErrString+1(a6),a0 ; fudge alignment of string X move.l a0,ParamZero(a5) ; it's param text zero X move.b #4,(a0)+ ; set string length X move.l FileCreator(a5),(a0) ; and string contents X SetParamText X UseUs X DoAlert OrphanCreator X UseThem X X ; Here's where we close up the file X@5 move.w TheirMap(a5),-(sp) ; retrieve test file refnum X _CloseResFile ; and close it up X X move.w CurMap,d0 ; check the current map X cmp.w OurMap(a5),d0 ; is it us? X beq @9 ; skip if so, we're good X DebugPoint X X ; so much for this file. Restore default volume X@9 UseUs ; in case we opened the System... X clr.l ParamZero(a5) ; the string storage is gone X unlk a6 X move.l (sp)+,a0 ; a0 = return address X lea ArgsSz(sp),sp ; pop arguments X jmp (a0) ; return X DName CHECKONEFILE X X; TestBundles: Test all the bundles of the current resource file X; d0 = number of BNDL available X; We only need to check ones native to the top map [TheirMap(a5)] X XOldA6 set 0 XReturnAddr set OldA6+4 X XResIndex set OldA6-2 ; current resource index XBNDLHandle set ResIndex-4 ; handle to current bundle XLastLocal set BNDLHandle X X XTestBundles X link a6,#LastLocal X move.w d0,ResIndex(a6) ; resources to check X X@0 clr.l -(sp) X move.l #'BNDL',-(sp) ; resource type X move.w ResIndex(a6),-(sp) ; resource index X _GetIndResource ; get the bundle X move.l (sp)+,BNDLHandle(a6) ; save handle X X ; is it one that we want? X clr.w -(sp) X move.l BNDLHandle(a6),-(sp) ; current bundle X _HomeResFile X move.w (sp)+,d0 X cmp.w TheirMap(a5),d0 ; is it theirs? X bne @1 ; skip if not X X move.l BNDLHandle(a6),a0 ; get the bundle handle X _HNoPurge ; make it unpurgeable X move.l BNDLHandle(a6),a0 ; get the bundle handle X _HLock ; lock it down X X move.l BNDLHandle(a6),a0 ; get the bundle handle X jsr TestOneBundle ; and check it out X X@1 sub.w #1,ResIndex(a6) ; decrement resource index X bne @0 ; and try again X X unlk a6 X rts X DName TESTBUNDLES X X; TestOneBundle: Examine one BNDL for validity, sanity, etc. X; a0 = handle to the bundle X XOldA6 set 0 XReturnAddr set OldA6+4 X XBNDLHandle set OldA6-4 ; handle to current bundle XBundleIDStr set BNDLHandle-32 ; Str31 for resource ID XBundleSize set BundleIDStr-4 ; size of bundle XBundleID set BundleSize-2 ; bundle's resource ID XBundleType set BundleID-4 ; bundle's resource type XBundleName set BundleType-256 ; bundle's resource name XOtherString set BundleName-32 ; for other stuff XICNlist set OtherString-4 ; pointer to ICN# list XFREFlist set ICNlist-4 ; pointer to FREF list XLastLocal set FREFlist X XTestOneBundle X link a6,#LastLocal X movem.l d2-d5/a2-a4,-(sp) ; save some registers X clr.l ICNlist(a6) ; clear list pointers X clr.l FREFlist(a6) X X move.l a0,BNDLHandle(a6) ; store bundle handle for later X move.l (a0),a4 ; a4 = bundle pointer X X move.l a0,-(sp) ; push handle X pea BundleID(a6) ; pointer to resource ID var X pea BundleType(a6) ; pointer to resource type var X pea BundleName(a6) ; pointer to resource name var X _GetResInfo X X lea BundleIDStr(a6),a0 ; string for bundle's res ID X move.l a0,ParamZero(a5) ; save for use in ParamText X move.w BundleID(a6),d0 ; get the resource ID X ext.l d0 X _NumToString X SetParamText X X ; Examine the bundle for size-wise sanity X clr.l -(sp) X move.l BNDLHandle(a6),-(sp) X _SizeRsrc ; how big is it? X move.l (sp)+,D4 ; save for later X move.l D4,BundleSize(a6) ; might need original figure... X sub.w #8,D4 ; at least minimum length? X bmi @5 ; branch if not X move.l (a4),D0 ; D0 = signature type X move.w 4(a4),d1 ; D1 = signature ID X jsr TestSignature ; check it out! X X move.w 6(a4),d3 ; D3 = # types - 1 X cmp.w #1,D3 ; usual number? X beq @0 ; skip if so X move.w d3,d0 X add.w #1,d0 ; actual number of types X lea OtherString(a6),a0 ; other string X move.l a0,ParamOne(a5) X ext.l d0 X _NumToString X SetParamText X UseUs X DoAlert NumberOfTypes X UseThem X@0 lea 8(a4),a4 ; a4 = header of first resource list X X@1 sub.w #6,D4 ; length of list header X bmi @5 ; skip out if too short X cmpi.l #'ICN#',(a4) ; icons? X bne @6 ; skip if not, try something else X move.l a4,ICNlist(a6) ; save ICN# list pointer X bra @2 ; and go check the list X@6 cmpi.l #'FREF',(a4) ; file references? X bne @7 ; skip if not, it's something weird X move.l a4,FREFlist(a6) ; save FREF list pointer X bra @2 ; and go check the list X@7 lea OtherString(a6),a0 ; point to other string X move.w #4,(a0) X move.l (a4),2(a0) ; fill in resource type X lea 1(a0),a0 ; use odd-aligned string X move.l a0,ParamOne(a5) X SetParamText X UseUs X DoAlert NovelType X UseThem X@2 move.w 4(a4),d2 ; resources - 1 of this type X lea 6(a4),a3 ; a3 = start of resource list X@3 sub.w #4,d4 ; size of list item X bmi @5 ; skip out if too short X move.l (a4),D0 ; resource type X move.w 2(a3),D1 ; resource ID X jsr TestOneResource ; test it! X lea 4(a3),a3 ; next item in list X dbra d2,@3 ; collect them all X move.l a3,a4 ; next list X dbra d3,@1 ; collect all of those, too X tst.w d4 ; All used up? X beq @4 ; skip if so, that's just right X ; The bundle runs on longer than expected X UseUs X DoAlert ExcessBundle X UseThem X@4 move.l ICNlist(a6),a0 ; pick up ICN# and FREF pointers X move.l FREFlist(a6),a1 X jsr TestLocalIDs X X clr.l ParamZero(a5) X clr.l ParamOne(a5) X movem.l (sp)+,d2-d5/a2-a4 ; restore some registers X unlk a6 X rts X DName TESTONEBUNDLE X X@5 UseUs X DoAlert MissingBundle X UseThem X bra @4 X X X; TestSignature: Does the 'signature' resource exist? X; D0 = resource type X; D1.w = resource ID X XOldA6 set 0 XReturnAddr set OldA6+4 X XSigType set OldA6-4 ; type of signature resource XTypeStr set SigType-1 ; for type string XFillerOne set TypeStr-1 ; restore alignment XSigID set FillerOne-2 ; resource ID for signature XIDString set SigID-32 ; Str31 for resource ID X XLastLocal set IDString X XTestSignature X link a6,#LastLocal X move.l d0,SigType(a6) ; save signature's resource type X move.w d1,SigID(a6) ; save resource ID X cmp.l FileCreator(a5),d0 ; FREF matches creator? X seq d0 X or.b d0,CreatorMatch(a5) ; set match flag if so X X clr.l -(sp) X move.l SigType(a6),-(sp) ; resource type X move.w SigID(a6),-(sp) ; resource ID X _GetResource ; Fetch! X move.l (sp)+,d0 ; pop the handle X beq @2 ; problem if NIL X tst.w ResErr ; something wrong? X bne @2 ; skip if so X clr.w -(sp) ; check home file of resource X move.l d0,-(sp) X _HomeResFile X move.w (sp)+,d0 ; pop res file reference X cmp.w TheirMap(a5),d0 ; right file? X beq @0 ; branch if so, it's good X X@2 move.b #4,TypeStr(a6) ; set resource type string X lea TypeStr(a6),a0 X move.l a0,ParamOne(a5) X SetParamText X X move.w SigID(a6),d0 ; d0 = signature's res ID X ext.l d0 X lea IDString(a6),a0 X move.l a0,ParamTwo(a5) X _NumToString X SetParamText X X UseUs X DoAlert NoSigResource X UseThem X X@0 clr.l ParamOne(a5) X clr.l ParamTwo(a5) X unlk a6 X rts X DName TESTSIGNATURE X X; TestOneResource: Do a sanity check on one resource. X; For all kinds, be sure it exists. X; For ICN# and FREF, do some other stuff X; D0 = resource type X; D1.W = resource ID X XOldA6 set 0 XReturnAddr set OldA6+4 X XResHandle set OldA6-4 ; handle to current resource XResType set ResHandle-4 ; resource type XResTypeStr set ResType-1 ; for using above as string XFillerOne set ResTypeStr-1 ; restore alignment XResID set FillerOne-2 ; resource ID XResIDStr set ResID-32 ; Str31 for resource ID XResSize set ResIDStr-4 ; size of resource XSizeString set ResSize-32 ; Str31 for resource size XLastLocal set SizeString X XTestOneResource X link a6,#LastLocal X movem.l d2-d5/a2-a4,-(sp) ; save some registers X X move.l d0,ResType(a6) X move.w d1,ResID(a6) X X move.b #4,ResTypeStr(a6) ; build type string X lea ResTypeStr(a6),a0 X move.l a0,ParamOne(a5) ; set indirect pointer X X move.w ResID(a6),d0 ; resource ID X lea ResIDStr(a6),a0 ; ID string X move.l a0,ParamTwo(a5) X ext.l d0 X _NumToString X SetParamText X X clr.l -(sp) X move.l ResType(a6),-(sp) ; resource type X move.w ResID(a6),-(sp) ; resource ID X _GetResource ; Fetch! X move.l (sp)+,ResHandle(a6) ; save the handle X tst.l ResHandle(a6) ; NIL handle? X beq @4 ; error if so, resource is missing X tst.w ResErr ; something wrong? X bne @4 ; skip if so X clr.w -(sp) ; else check home resource file X move.l ResHandle(a6),-(sp) X _HomeResFile X move.w (sp)+,d0 ; pop res file ref X cmp.w TheirMap(a5),d0 ; right file? X beq @0 ; branch if so, we'll take it X X@4 UseUs X DoAlert MissingResource X UseThem X bra @9 X@0 clr.l -(sp) X move.l ResHandle(a6),-(sp) X _SizeRsrc ; How big is this sucker? X move.l (sp)+,ResSize(a6) ; save for later testing X X move.l ResSize(a6),d0 ; set up length string X lea SizeString(a6),a0 X move.l a0,ParamThree(a5) X _NumToString X SetParamText X X move.l ResType(a6),d0 ; d0 = resource type X cmpi.l #'ICN#',d0 ; Icon list? X bne @2 ; skip if not X X move.l ResSize(a6),d0 ; check resource size X cmp.l #256,d0 ; must be 256 bytes X beq @9 ; exit if so, it's good X UseUs X DoAlert FunnyIcon X UseThem X bra @9 X@2 cmpi.l #'FREF',d0 ; FREF? X bne @9 ; exit if not, we don't care X move.l ResSize(a6),d0 ; check resource size X cmpi.l #6,d0 ; reasonable size? X bcc @3 ; branch if minimum or more X UseUs X DoAlert SmallFREF ; the FREF is too small X UseThem X bra @9 X@3 cmpi.l #263,d0 ; not too big? X bcs @9 ; branch if in bounds X UseUs X DoAlert BigFREF X UseThem X X@9 clr.l ParamOne(a5) X clr.l ParamTwo(a5) X clr.l ParamThree(a5) X movem.l (sp)+,d2-d5/a2-a4 ; restore some registers X unlk a6 X rts X DName TESTONERESOURCE X X; TestLocalIDs: See if the local IDs referred to by the FREFs are X; resolved in the ICN# list. X; a0 = ptr to ICN# list from bundle X; a1 = ptr to FREF list from bundle X XFREFIDStr set -32 ; Str31 for FREF ID # XLocalIDStr set FREFIDStr-32 ; Str31 for local ID # XFREFHandle set LocalIDStr-4 ; handle of current FREF XLastLocal set FREFHandle X XTestLocalIDs X link a6,#LastLocal ; some local storage X movem.l a2-a4/d2-d4,-(sp) ; save some regs X X move.l a0,d0 ; is there an ICN# list? X bne @0 ; skip if so X UseUs X DoAlert NoIcons X UseThem X bra @9 X@0 move.l a1,d0 ; is there an FREF list? X bne @1 ; skip if so X UseUs X DoAlert NoFREFs X UseThem X bra @9 X@1 move.l a0,a4 ; a4 = ICN# list pointer X move.w 4(a1),d4 ; d4 = # FREFs - 1 X lea 6(a1),a3 ; a3 = first FREF item X@2 clr.l -(sp) X move.l #'FREF',-(sp) X move.w 2(a3),-(sp) X _GetResource ; get the FREF X move.l (sp)+,d0 ; pop the handle X beq @5 ; skip if NIL handle X tst.w ResErr X bne @5 ; skip if resource error X move.l d0,FREFHandle(a6) ; save FREF handle X clr.w -(sp) ; check home res file X move.l d0,-(sp) X _HomeResFile X move.w (sp)+,d0 ; pop home res file X cmp.w TheirMap(a5),d0 ; from a good home? X bne @5 ; exit if not X X move.l FREFHandle(a6),a0 ; a0 = FREF handle X move.l (a0),a0 ; a0 = FREF pointer X X move.l (a0),d0 ; d0 = file type from FREF X cmp.l FileType(a5),d0 ; match our file type? X seq d0 X or.b d0,TypeMatch(a5) ; set type match flag if so X X move.w 4(a0),d0 ; d0 = local ID from FREF X move.w 4(a4),d3 ; d3 = # ICN#s - 1 X lea 6(a4),a2 ; a2 = first ICN# item X@3 cmp.w (a2),d0 ; local IDs match? X beq @5 ; skip if so, test next FREF X lea 4(a2),a2 ; else move to next ICN# item X dbra d3,@3 ; search through ICN# list X X ; If we fall out, we have an unsatisfied local ID in d0 X X ext.l d0 X lea LocalIDStr(a6),a0 ; string for local resource ID X move.l a0,ParamTwo(a5) X _NumToString X move.w 2(a3),d0 ; FREF resource ID X ext.l d0 X lea FREFIDStr(a6),a0 ; string for FREF resource ID X move.l a0,ParamOne(a5) X _NumToString X SetParamText X UseUs X DoAlert BadLocalID X UseThem X clr.l ParamOne(a5) X clr.l ParamTwo(a5) X@5 lea 4(a3),a3 ; next FREF item in list X dbra d4,@2 ; test entire FREF list X@9 movem.l (sp)+,a2-a4/d2-d4 ; restore registers X unlk a6 X rts X DName TESTLOCALIDS X SHAR_EOF sed 's/^X//' << 'SHAR_EOF' > DeskCheck/FCensus.asm X X; FCensus: HFS/MSF file census routine from Feb '86 MacTutor X; Provides info on each file on a volume, whether MFS or HFS. X X; Proc FCensus(vRefNum:integer; DirID:longint; Inspector:ProcPtr); X X; vRefNum: volume reference number (or drive number) of volume X X; dirID: ID of directory to start. Root dir = 2. X X; Inspector: user-supplied function X; MyInspector(ParamBlock:ParmBlkPtr; dirID:longint):boolean X; ParamBlock is a GetFileInfo block X; dirID is the ID of the file's directory X; If returned value = True, search ends. X; If returned value = False, search continues. X X Include Traps.D X Include SysEquX.D X Include FSEqu.D X Include SysErr.D X X .MACRO _TFSCORE X IF '%1' <> '' X LEA %1,A0 X ENDIF X IF '%3' = '' X DC.W $A200+%2 X ENDIF X IF '%3' = 'REGS' X DC.W $A300+%2 X ENDIF X IF '%3' = 'ASYNC' X DC.W $A600+%2 X ENDIF X IF '%3' = 'SYS' X DC.W $A600+%2 X ENDIF X IF '%3' = 'IMMED' X DC.W $A200+%2 X ENDIF X .ENDM X X X .MACRO _GetCatInfo X MOVEQ #9,D0 X _TFSCore %1,96,%2 X .ENDM X X X; A6 offsets XOldA6 set 0 XReturnAddr set OldA6+4 XInspec set ReturnAddr+4 XDirID set Inspec+4 XvRefNum set DirID+4 XArgsSz set vRefNum+2-Inspec X; XParmBlk set OldA6-ioHVQElSize ; local parm block XNameStr set ParmBlk-256 ; Str255 buffer XIndex set NameStr-2 ; directory index X X XRef FCensus X XFCensus X Link a6,#Index X clr.l -(sp) ; sentinel for end of DirID list XNextDir X clr Index(a6) ; init index = 0 XNextFile X lea ParmBlk(a6),a0 ; a0 = parm block pointer X clr.l ioCompletion(a0) X clr.l ioFileName(a0) X move vRefNum(a6),ioVRefNum(a0) ; set volume X move.l dirID(a6),ioDirID(a0) ; set directory ID X lea NameStr(a6),a1 ; a1 = name string buffer pointer X move.l a1,ioFileName(a0) ; set file name pointer X addq #1,Index(a6) ; advance index X move Index(a6),ioFDirIndex(a0) ; set index X tst FSFCBLen ; HFS running? X bmi.s @0 ; branch if not X _GetCatInfo X bra.s @1 X@0 _GetFileInfo ; MFS, get partial story X@1 beq.s NodeKind ; no error, check things out X cmp #fnfErr,d0 ; end of directory? X bne.s FCExit ; no, unexpected problem X move.l (sp)+,dirID(a6) ; pop next directory off stack X bne.s NextDir ; branch if there is one X bra.s FCExit ; branch if there isn't one XNodeKind X btst #ioDirFlg,ioFlAttrib(a0) ; directory? X beq.s CallInspec ; a file, call Inspector X move.l ioDirID(a0),-(sp) ; directory, push on stack X bra.s NextFile ; look for next file XCallInspec X clr -(sp) ; for returned value X pea ParmBlk(a6) ; param block for inspector X move.l dirID(a6),-(sp) ; pass dirID X move.l Inspec(a6),a0 ; address of user function X jsr (a0) ; call inspector X tst.b (sp)+ ; time to quit? X beq.s NextFile ; no, keep going XFCExit X unlk a6 X move.l (sp)+,a0 ; a0 = return address X lea ArgsSz(sp),sp ; pop arguments X jmp (a0) ; return X dc.b 'FCensus' X .align 2 SHAR_EOF exit ---