1 #include <clib/macros.h>
2 #include <devices/scsidisk.h>
3 #include <devices/trackdisk.h>
5 #include <dos/dosextens.h>
6 #include <dos/filehandler.h>
7 #include <exec/errors.h>
9 #include <exec/memory.h>
10 #include <proto/dos.h>
11 #include <proto/exec.h>
12 #include <proto/intuition.h>
16 #include "../FS/globals.h"
17 #include "../FS/deviceio.h"
18 #include "../FS/deviceio_protos.h"
19 #include "../FS/cachedio_protos.h"
20 #include "../FS/asmsupport.h"
21 #include "../FS/adminspaces.h"
22 #include "../FS/bitmap.h"
23 #include "../FS/objects.h"
24 #include "../FS/transactions.h"
26 #include "../FS/btreenodes.h"
29 #define BLCKFACCURACY (5) /* 2^5 = 32 */
32 const char version
[]={"\0$VER: SFSCheck 1.3 (" ADATE
")r\n"};
35 LONG
read2(ULONG block
);
36 void dumpblock(ULONG block
, void *data
, ULONG bytes
);
38 BOOL
iszero(void *a
,LONG size
);
39 BOOL
isblockvalid(void *b
, ULONG block
, ULONG id
);
40 LONG
findbnode(BLCK rootblock
,ULONG key
,struct BNode
**returned_bnode
);
41 UBYTE
*mark(LONG offset
, LONG blocks
);
42 BOOL
error(UBYTE
*fmt
, ... );
43 void freestring(UBYTE
*str
);
44 UBYTE
*tostring(UBYTE
*fmt
, ... );
48 UBYTE emptystring
[]="";
52 struct DosEnvec
*dosenvec
;
54 /* blocks_ = the number of blocks of something (blocks can contain 1 or more sectors)
55 block_ = a block number of something (relative to start of partition)
56 sectors_ = the number of sectors of something (1 or more sectors form a logical block)
57 sector_ = a sector number (relative to the start of the disk)
58 bytes_ = the number of bytes of something
59 byte_ = a byte number of something
60 shifts_ = the number of bytes written as 2^x of something
61 mask_ = a mask for something */
63 ULONG blocks_reserved_start
; /* number of blocks reserved at start (=reserved) */
64 ULONG blocks_reserved_end
; /* number of blocks reserved at end (=prealloc) */
65 ULONG blocks_bitmap
; /* number of BTMP blocks for this partition */
66 ULONG blocks_inbitmap
; /* number of blocks a single bitmap block can contain info on */
67 ULONG blocks_admin
; /* the size of all AdminSpaces */
69 ULONG block_root
; /* the block offset of the root block */
70 ULONG block_bitmapbase
; /* the block offset of the first bitmap block */
71 ULONG block_extentbnoderoot
; /* the block offset of the root of the extent bnode tree */
72 ULONG block_adminspace
; /* the block offset of the first adminspacecontainer block */
73 ULONG block_rovingblockptr
; /* the roving block pointer! */
74 ULONG block_objectnodesbase
;
76 ULONG node_containers
; /* number of containers per ExtentIndexContainer */
78 ULONG mask_block32
; /* masks the least significant bits of a BLCKf pointer */
80 UWORD shifts_block32
; /* shift count needed to convert a blockoffset<->32byteoffset (only used by nodes.c!) */
90 struct RDArgs
*readarg
;
91 UBYTE
template[]="DEVICE=DRIVE/A,LOCK/S,LINES/N,READAHEADSIZE/N\n";
96 ULONG
*readaheadsize
;} arglist
={NULL
};
98 globals
= AllocMem(sizeof(struct SFSBase
), MEMF_PUBLIC
| MEMF_CLEAR
);
103 if((DOSBase
=(struct DosLibrary
*)OpenLibrary("dos.library",39))!=0) {
104 if((IntuitionBase
=(APTR
)OpenLibrary("intuition.library",39))!=0) {
105 if((pool
=CreatePool(0,16384,8192))!=0) {
106 if((readarg
=ReadArgs(template,(IPTR
*)&arglist
,0))!=0) {
108 UBYTE
*devname
=arglist
.device
;
118 dl
=LockDosList(LDF_DEVICES
|LDF_READ
);
119 if((dl
=FindDosEntry(dl
,arglist
.device
,LDF_DEVICES
))!=0) {
120 struct FileSysStartupMsg
*fssm
;
123 fssm
=(struct FileSysStartupMsg
*)BADDR(dl
->dol_misc
.dol_handler
.dol_Startup
);
124 dosenvec
=(struct DosEnvec
*)BADDR(fssm
->fssm_Environ
);
126 UnLockDosList(LDF_DEVICES
|LDF_READ
);
128 if(arglist
.lock
==0 || Inhibit(arglist
.device
, DOSTRUE
)!=DOSFALSE
) {
130 if((initcachedio(AROS_BSTR_ADDR(fssm
->fssm_Device
), fssm
->fssm_Unit
, fssm
->fssm_Flags
, dosenvec
))==0) {
132 setiocache(arglist
.lines
!=0 ? *arglist
.lines
: 128, arglist
.readaheadsize
!=0 ? *arglist
.readaheadsize
: 8192, FALSE
); /* 1 MB for read-ahead cache, no copyback mode. */
134 shifts_block32
=globals
->shifts_block
-BLCKFACCURACY
;
136 mask_block32
=(1<<shifts_block32
)-1;
138 blocks_reserved_start
=MAX(dosenvec
->de_Reserved
,1);
139 blocks_reserved_end
=MAX(dosenvec
->de_PreAlloc
,1);
141 blocks_inbitmap
=(globals
->bytes_block
-sizeof(struct fsBitmap
))<<3; /* must be a multiple of 32 !! */
142 blocks_bitmap
=(globals
->blocks_total
+blocks_inbitmap
-1)/blocks_inbitmap
;
145 printf("Partition start offset : 0x%llx End offset : 0x%llx\n", (unsigned long long)globals
->byte_low
, (unsigned long long)globals
->byte_high
);
146 printf("Surfaces : %-5ld Blocks/Track : %ld\n", dosenvec
->de_Surfaces
, dosenvec
->de_BlocksPerTrack
);
147 printf("Bytes/Block : %-5ld Sectors/Block : %ld\n", (long)globals
->bytes_block
, dosenvec
->de_SectorPerBlock
);
148 printf("Total blocks : %ld\n", (long)globals
->blocks_total
);
149 printf("Device interface : ");
151 switch(deviceapiused()) {
153 printf("NSD (64-bit)\n");
159 printf("SCSI direct\n");
162 printf("(standard)\n");
166 if((buffer
=AllocVec(globals
->bytes_block
, globals
->bufmemtype
))!=0) {
167 if((bitmap
=AllocVec(((globals
->blocks_total
+31)>>5)<<3,MEMF_CLEAR
))!=0) {
170 bitmap
[globals
->blocks_total
>>5]=L2BE(0xFFFFFFFF>>(globals
->blocks_total
& 0x0000001F));
171 if((str
=mark(0,blocks_reserved_start
))!=0) {
172 printf("Error while marking reserved blocks at start:\n%s",str
);
175 if((str
=mark(globals
->blocks_total
-blocks_reserved_end
,blocks_reserved_end
))!=0) {
176 printf("Error while marking reserved blocks at end:\n%s",str
);
185 printf("Not enough memory\n");
190 printf("Not enough memory\n");
196 if(arglist
.lock
!=0) {
197 Inhibit(arglist
.device
, DOSFALSE
);
202 PrintFault(errorcode
, "error while locking the drive");
206 Printf("Unknown device %s\n", arglist
.device
);
207 UnLockDosList(LDF_DEVICES
|LDF_READ
);
214 CloseLibrary((struct Library
*)IntuitionBase
);
216 CloseLibrary((struct Library
*)DOSBase
);
224 else if(SetSignal(0L,SIGBREAKF_CTRL_C) & SIGBREAKF_CTRL_C) {
225 PutStr("\n***Break\n");
231 BOOL
validblock(ULONG block
) {
232 if(block
<globals
->blocks_total
) {
240 LONG
read2(ULONG block
) {
241 // return(transfer(DIO_READ, buffer, block, 1));
242 return(read(block
, buffer
, 1));
247 BOOL
checkchecksum(void *d
) {
248 ULONG
*data
=(ULONG
*)d
;
250 if(CALCCHECKSUM(globals
->bytes_block
,data
)==0) {
258 BOOL
checkobjectcontainerblock(struct fsObjectContainer
*b
, ULONG block
) {
259 if(isblockvalid(b
,block
,OBJECTCONTAINER_ID
)!=FALSE
) {
268 BOOL
checkbitmapblock(struct fsBitmap
*b
, ULONG block
, ULONG sequencenumber
) {
269 if(isblockvalid(b
,block
,BITMAP_ID
)!=FALSE
) {
270 ULONG l
=(sequencenumber
-1)*(blocks_inbitmap
>>5);
271 WORD n
=blocks_inbitmap
>>5;
274 if(sequencenumber
==blocks_bitmap
) {
275 n
=((globals
->blocks_total
- ((blocks_bitmap
-1) * blocks_inbitmap
))+31)>>5;
278 while(--n
>=0 && ~bitmap
[l
++]==*bm
++) {
283 if(sequencenumber
==blocks_bitmap
) {
284 if((bmffo(b
->bitmap
, blocks_inbitmap
>>5, globals
->blocks_total
- ((blocks_bitmap
-1) * blocks_inbitmap
) ))==blocks_inbitmap
) {
288 printf("Last bitmap block wasn't correctly filled out with 0's\n");
296 printf("%ld %08lx == %08lx\n",(long)n
,(unsigned long)~bitmap
[--l
],(unsigned long)*--bm
);
297 printf("Bitmap block %ld contents is incorrect!\n",(long)block
);
307 BOOL
checkbitmap(ULONG block
) {
310 for(n
=1; n
<=blocks_bitmap
; n
++) {
312 if(checkbitmapblock((struct fsBitmap
*)buffer
, block
, n
)==FALSE
) {
313 printf("...error in bitmap block at block %ld\n",(long)block
);
324 BOOL
checkrootblock(struct fsRootBlock
*b
, ULONG block
) {
325 if(isblockvalid(b
,block
,L2BE(DOSTYPE_ID
))!=FALSE
) {
326 if(b
->be_version
==W2BE(STRUCTURE_VERSION
)) {
327 if(b
->pad1
==0 && b
->be_pad2
==0 && iszero(b
->be_reserved1
,8) && iszero(b
->be_reserved2
,8) && iszero(b
->be_reserved3
,32) && iszero(b
->be_reserved4
,16) && iszero((UBYTE
*)b
+sizeof(struct fsRootBlock
),globals
->bytes_block
-sizeof(struct fsRootBlock
))) {
328 if(BE2L(b
->be_totalblocks
)==globals
->blocks_total
) {
329 if(BE2L(b
->be_blocksize
)==globals
->bytes_block
) {
333 printf("RootBlock's blocksize field is %ld, while it should be %ld.\n",(long)BE2L(b
->be_blocksize
),(long)globals
->bytes_block
);
337 printf("RootBlock's total number of blocks is %ld, while it should be %ld.\n",(long)BE2L(b
->be_totalblocks
),(long)globals
->blocks_total
);
341 printf("Reserved areas in RootBlock weren't all set to zero.\n");
345 printf("RootBlock's version is unsupported by this version of SFScheck\n");
354 BOOL
isblockvalid(void *bh
, ULONG block
, ULONG id
) {
355 struct fsBlockHeader
*b
=(struct fsBlockHeader
*)bh
;
357 if(checkchecksum((UBYTE
*)b
)!=FALSE
) {
359 if(BE2L(b
->be_ownblock
)==block
) {
363 printf("Location of block is invalid.\n");
367 printf("Incorrect block type at block %ld. Expected was 0x%08lx but it was 0x%08lx.\n",(long)block
,(unsigned long)BE2L(id
),(unsigned long)BE2L(b
->id
));
371 printf("Checksum failure.\n");
379 BOOL
iszero(void *a
,LONG size
) {
380 UBYTE
*adr
=(UBYTE
*)a
;
382 while(--size
>=0 && *adr
++==0) {
393 struct fsObject
*nextobject(struct fsObject
*o
) {
396 /* skips the passed in fsObject and gives a pointer back to the place where
397 a next fsObject structure could be located */
399 p
=(UBYTE
*)&o
->name
[0];
401 /* skip the filename */
405 /* skip the comment */
409 /* ensure WORD boundary */
410 if((((IPTR
)p
) & 0x01)!=0) {
414 return((struct fsObject
*)p
);
419 WORD
isobject(struct fsObject
*o
, struct fsObjectContainer
*oc
) {
422 endadr
=(UBYTE
*)oc
+globals
->bytes_block
-sizeof(struct fsObject
)-2;
424 if((UBYTE
*)o
<endadr
&& o
->name
[0]!=0) {
432 BOOL
checkobjectcontainerfornode(ULONG block
, ULONG node
) {
433 struct fsObjectContainer
*oc
=(struct fsObjectContainer
*)buffer
;
437 if(isblockvalid(oc
,block
,OBJECTCONTAINER_ID
)!=FALSE
) {
438 struct fsObject
*o
=oc
->object
;
440 while(isobject(o
,oc
)!=FALSE
) {
441 if(BE2L(o
->be_objectnode
)==node
) {
448 printf("ObjectContainer at block %ld doesn't contain node %ld\n",(long)block
,(long)node
);
452 printf("ObjectContainer at block %ld is invalid and doesn't contain node %ld\n",(long)block
,(long)node
);
458 BOOL
checknodecontainers2(ULONG block
, ULONG parent
, ULONG nodenumber
, ULONG nodes
) {
459 struct fsNodeContainer
*b
;
461 // printf("Checking NodeContainer at block %ld, with parent %ld, nodenumber %ld and nodes %ld\n",block,parent,nodenumber,nodes);
463 if((b
=AllocVec(globals
->bytes_block
, globals
->bufmemtype
))!=0) {
465 CopyMemQuick(buffer
,b
,globals
->bytes_block
);
467 if(isblockvalid(b
,block
,NODECONTAINER_ID
)!=FALSE
) {
468 if(BE2L(b
->be_nodenumber
)==nodenumber
) {
470 nodes
=BE2L(b
->be_nodes
);
473 if(BE2L(b
->be_nodes
)==nodes
) {
475 WORD maxnodes
=(globals
->bytes_block
-sizeof(struct fsNodeContainer
))/4;
476 LONG nodes2
=nodes
/maxnodes
;
483 for(n
=0; n
<maxnodes
; n
++) {
484 if(BE2L(b
->be_node
[n
])!=0) {
485 if(checknodecontainers2(BE2L(b
->be_node
[n
])>>shifts_block32
, block
, nodenumber
, nodes2
)==FALSE
) {
497 WORD maxnodes
=(globals
->bytes_block
-sizeof(struct fsNodeContainer
))/sizeof(struct fsObjectNode
);
499 struct fsObjectNode
*on
=(struct fsObjectNode
*)b
->be_node
;
501 for(n
=0; n
<maxnodes
; n
++) {
502 if(BE2L(on
->node
.be_data
)!=0 && BE2L(on
->node
.be_data
)!=-1) {
503 if(checkobjectcontainerfornode(BE2L(on
->node
.be_data
),nodenumber
+n
)==FALSE
) {
510 else if(BE2L(on->node.be_data)==0 && (on->next!=0 || on->hash16!=0)) {
511 printf("NodeContainer at block %ld has a not fully cleared node.\n",block);
525 printf("NodeContainer at block %ld has nodes %ld while it should be %ld.\n",(long)block
,(long)BE2L(b
->be_nodes
),(long)nodes
);
529 printf("NodeContainer at block %ld has nodenumber %ld while it should be %ld.\n",(long)block
,(long)BE2L(b
->be_nodenumber
),(long)nodenumber
);
536 printf("ERROR: Out of memory!\n");
543 BOOL
checknodecontainers(ULONG block
) {
544 return(checknodecontainers2(block
,0,1,0));
549 UBYTE
*mark(LONG offset
, LONG blocks
) {
552 result
=bmffo(bitmap
, (globals
->blocks_total
+31)>>5, offset
);
554 if(result
!=((globals
->blocks_total
+31)&(~0x1f)) && result
< offset
+blocks
) {
555 return(tostring("Block at offset %ld is already in use while marking %ld blocks from %ld.\n",result
,blocks
,offset
));
558 if((result
=bmset(bitmap
, (globals
->blocks_total
+31)>>5, offset
, blocks
))!=blocks
) {
559 return(tostring("Error while marking %ld blocks from %ld. Could only mark %ld blocks.\n",blocks
,offset
,result
));
567 LONG
findnode(BLCK nodeindex
,UWORD nodesize
,NODE nodeno
,struct fsNode
**returned_node
) {
570 /* Finds a specific node by number. It returns the cachebuffer which contains the fsNode
571 structure and a pointer to the fsNode structure directly. */
573 while((errorcode
=read2(nodeindex
))==0) {
574 struct fsNodeContainer
*nc
=(struct fsNodeContainer
*)buffer
;
576 if(BE2L(nc
->be_nodes
)==1) {
577 /* We've descended the tree to a leaf NodeContainer */
579 *returned_node
=(struct fsNode
*)((UBYTE
*)nc
->be_node
+nodesize
*(nodeno
-BE2L(nc
->be_nodenumber
)));
584 UWORD containerentry
=(nodeno
-BE2L(nc
->be_nodenumber
))/BE2L(nc
->be_nodes
);
586 nodeindex
=BE2L(nc
->be_node
[containerentry
])>>shifts_block32
;
595 BOOL
checkobjectcontainers2(ULONG block
, ULONG previous
, ULONG parent
) {
596 struct fsObjectContainer
*oc
;
599 if((oc
=AllocVec(globals
->bytes_block
, globals
->bufmemtype
))!=0) {
602 CopyMemQuick(buffer
,oc
,globals
->bytes_block
);
604 if(isblockvalid(oc
,block
,OBJECTCONTAINER_ID
)!=FALSE
) {
605 if(BE2L(oc
->be_previous
)==previous
) {
606 if(BE2L(oc
->be_parent
)==parent
) {
607 struct fsObject
*o
=oc
->object
;
608 struct fsObjectNode
*node
;
611 while(isobject(o
,oc
)!=FALSE
) {
613 if((errorcode
=findnode(block_objectnodesbase
, sizeof(struct fsObjectNode
), BE2L(o
->be_objectnode
), (struct fsNode
**)&node
))==0) {
614 if(BE2L(node
->node
.be_data
)==block
) {
615 if((o
->bits
& OTYPE_LINK
)==0) {
616 if((o
->bits
& OTYPE_DIR
)!=0 && BE2L(o
->object
.dir
.be_firstdirblock
)!=0) {
617 if(checkobjectcontainers2(BE2L(o
->object
.dir
.be_firstdirblock
), 0, BE2L(o
->be_objectnode
))==FALSE
) {
621 else if((o
->bits
& OTYPE_DIR
)==0) {
622 struct fsExtentBNode
*ebn
= NULL
;
623 ULONG next
=BE2L(o
->object
.file
.be_data
);
628 if((errorcode
=findbnode(block_extentbnoderoot
, next
, (struct BNode
**)&ebn
))!=0) {
629 if(error("Errorcode %ld while locating BNode %ld of Object '%s' in ObjectContainer at block %ld.\n",errorcode
,BE2L(o
->object
.file
.be_data
),o
->name
,block
)) {
634 if(BE2L(ebn
->be_key
)!=next
) {
635 if(error("Error in Object '%s' in ObjectContainer at block %ld:\nBNode %ld has incorrect key. It is %ld while it should be %ld.\n",o
->name
,block
,next
,BE2L(ebn
->be_key
),next
)) {
640 if((prev
!=0 && BE2L(ebn
->be_prev
)!=prev
) || (prev
==0 && BE2L(ebn
->be_prev
)!=(BE2L(o
->be_objectnode
) | 0x80000000))) {
641 if(error("Error in Object '%s' in ObjectContainer at block %ld:\nBNode %ld has incorrect previous. It is 0x%08lx.\n",o
->name
,block
,next
,BE2L(ebn
->be_prev
))) {
646 if(BE2W(ebn
->be_blocks
)==0) {
647 if(error("Error in Object '%s' in ObjectContainer at block %ld:\nBNode %ld has a zero block count!\n",o
->name
,block
,next
)) {
652 if((str
=mark(BE2L(ebn
->be_key
), BE2W(ebn
->be_blocks
)))!=0) {
653 if(error("Error in Object '%s' in ObjectContainer at block %ld:\nBNode %ld points to space already in use:\n %s",o
->name
,block
,next
,str
)) {
661 next
=BE2L(ebn
->be_next
);
671 printf("Node %ld of Object in ObjectContainer at block %ld points to wrong block (%ld)\n",(long)BE2L(o
->be_objectnode
),(long)block
,(long)BE2L(node
->node
.be_data
));
676 printf("Error %ld occured while locating Node %ld of Object in ObjectContainer at block %ld.\n",(long)errorcode
,(long)BE2L(o
->be_objectnode
),(long)block
);
683 if(isobject(o
,oc
)!=FALSE
) {
688 printf("ObjectContainer at block %ld has parent %ld while it should be %ld.\n",(long)block
,(long)BE2L(oc
->be_parent
),(long)parent
);
693 printf("ObjectContainer at block %ld has previous %ld while it should be %ld.\n",(long)block
,(long)BE2L(oc
->be_previous
),(long)previous
);
702 block
=BE2L(oc
->be_next
);
712 printf("ERROR: Out of memory!\n");
720 BOOL
checkobjectcontainers(ULONG block
) {
721 return(checkobjectcontainers2(block
,0,0));
726 void dumpblock(ULONG block
, void *data
, ULONG bytes
) {
727 ULONG
*d
=(ULONG
*)data
;
728 UBYTE
*d2
=(UBYTE
*)data
;
732 if(bytes
<globals
->bytes_block
) {
733 printf("Dump of first %ld bytes of block %ld.\n",(long)bytes
,(long)block
);
736 printf("Dump of block %ld.\n",(long)block
);
753 if(c
>=127 && c
<=160) {
761 printf("0x%04lx: %08lx %08lx %08lx %08lx %s\n",(unsigned long)off
,(unsigned long)BE2L(d
[0]),(unsigned long)BE2L(d
[1]),(unsigned long)BE2L(d
[2]),(unsigned long)BE2L(d
[3]),s
);
771 BOOL
checkadminspacecontainers(ULONG block
) {
772 struct fsAdminSpaceContainer
*asc
;
774 if((asc
=AllocVec(globals
->bytes_block
, globals
->bufmemtype
))!=0) {
779 CopyMemQuick(buffer
,asc
,globals
->bytes_block
);
781 if(isblockvalid(asc
,block
,ADMINSPACECONTAINER_ID
)!=FALSE
) {
782 if(BE2L(asc
->be_previous
)==previous
) {
783 // if(asc->bits==32) {
784 struct fsAdminSpace
*as
=asc
->adminspace
;
786 while((UBYTE
*)as
<((UBYTE
*)asc
+globals
->bytes_block
) && BE2L(as
->be_space
)!=0) {
787 ULONG adminblock
=BE2L(as
->be_space
);
788 LONG bits
=BE2L(as
->be_bits
);
793 if((str
=mark(adminblock
,32))!=0) {
794 if(error("AdminSpaceContainer at %ld occupies already used space:\n %s",block
,str
)) {
803 struct fsBlockHeader
*bh
=(struct fsBlockHeader
*)buffer
;
808 if(checkchecksum((UBYTE
*)bh
)!=FALSE
) {
809 if(bh
->id
==ADMINSPACECONTAINER_ID
|| bh
->id
==OBJECTCONTAINER_ID
|| bh
->id
==HASHTABLE_ID
|| bh
->id
==NODECONTAINER_ID
|| bh
->id
==BNODECONTAINER_ID
|| bh
->id
==TRANSACTIONOK_ID
|| bh
->id
==SOFTLINK_ID
) {
810 if(BE2L(bh
->be_ownblock
)==adminblock
) {
817 printf("Block %ld is not a valid admin block but it is marked in use in AdminSpaceContainer at %ld\n",(long)adminblock
,(long)block
);
818 dumpblock(adminblock
,buffer
,64);
833 if((UBYTE
*)as
<((UBYTE
*)asc
+globals
->bytes_block
) && BE2L(as
->be_space
)!=0) {
839 // printf("AdminSpaceContainer at block %ld hasn't got 32 blocks/entry (%ld)!\n",block,asc->bits);
844 printf("AdminSpaceContainer at block %ld has previous %ld while it should be %ld.\n",(long)block
,(long)BE2L(asc
->be_previous
),(long)previous
);
853 block
=BE2L(asc
->be_next
);
863 printf("ERROR: Out of memory!\n");
871 void sfscheck(void) {
872 ULONG block_bitmapbase
;
873 ULONG block_adminspacecontainer
;
876 printf("Checking RootBlocks\n");
878 read2(globals
->blocks_total
-1);
880 if((checkrootblock((struct fsRootBlock
*)buffer
,globals
->blocks_total
-1))!=FALSE
) {
884 if((checkrootblock((struct fsRootBlock
*)buffer
,0))!=FALSE
) {
885 struct fsRootBlock
*b
=(struct fsRootBlock
*)buffer
;
890 block_bitmapbase
=BE2L(b
->be_bitmapbase
);
891 block_root
=BE2L(b
->be_rootobjectcontainer
);
892 block_extentbnoderoot
=BE2L(b
->be_extentbnoderoot
);
893 block_adminspacecontainer
=BE2L(b
->be_adminspacecontainer
);
894 block_objectnodesbase
=BE2L(b
->be_objectnoderoot
);
896 if((str
=mark(block_bitmapbase
,blocks_bitmap
))!=0) {
897 Printf("Error while marking bitmap space:\n %s",str
);
901 printf("Checking AdminSpaceContainers at block %ld\n",(long)block_adminspacecontainer
);
902 if((checkadminspacecontainers(block_adminspacecontainer
))!=FALSE
) {
905 printf("Checking NodeContainers at block %ld\n",(long)block_objectnodesbase
);
906 if((checknodecontainers(block_objectnodesbase
))!=FALSE
) {
909 printf("Checking ObjectContainers at block %ld\n",(long)block_root
);
910 if((checkobjectcontainers(block_root
))!=FALSE
) {
913 printf("Checking Bitmap at block %ld (%ld blocks, %ld bits/bitmap)\n",(long)block_bitmapbase
,(long)blocks_bitmap
,(long)blocks_inbitmap
);
914 if((checkbitmap(block_bitmapbase
))!=FALSE
) {
920 printf("...damaged\n");
925 printf("...damaged\n");
930 printf("...damaged\n");
935 printf("...damaged\n");
940 printf("...damaged\n");
945 printf("...damaged\n");
956 struct BNode
*searchforbnode(ULONG key
,struct BTreeContainer
*tc
) {
958 WORD n
=BE2W(tc
->be_nodecount
)-1;
960 tn
=(struct BNode
*)((UBYTE
*)tc
->bnode
+n
*tc
->nodesize
);
963 if(n
<=0 || key
>= BE2L(tn
->be_key
)) {
966 tn
=(struct BNode
*)((UBYTE
*)tn
-tc
->nodesize
);
973 LONG
findbnode(BLCK rootblock
,ULONG key
,struct BNode
**returned_bnode
) {
976 while((errorcode
=read2(rootblock
))==0) {
977 struct fsBNodeContainer
*bnc
=(struct fsBNodeContainer
*)buffer
;
978 struct BTreeContainer
*btc
=&bnc
->btc
;
980 *returned_bnode
=searchforbnode(key
,btc
);
981 if(btc
->isleaf
==TRUE
) {
984 rootblock
=BE2L((*returned_bnode
)->be_data
);
992 void freestring(UBYTE
*str
) {
993 if(str
!=emptystring
) {
1000 UBYTE
*tostring(UBYTE
*fmt
, ... ) {
1003 if((buf
=AllocVec(200,MEMF_CLEAR
))!=0) {
1004 AROS_SLOWSTACKFORMAT_PRE(fmt
);
1006 RawDoFmt(fmt
,AROS_SLOWSTACKFORMAT_ARG(fmt
),RAWFMTFUNC_STRING
,buf
);
1008 AROS_SLOWSTACKFORMAT_POST(fmt
);
1012 return(emptystring
);
1018 BOOL
error(UBYTE
*fmt
, ... ) {
1020 AROS_SLOWSTACKFORMAT_PRE(fmt
);
1021 VPrintf(fmt
,AROS_SLOWSTACKFORMAT_ARG(fmt
));
1022 AROS_SLOWSTACKFORMAT_POST(fmt
);
1026 if(errors
>maxerrors
) {
1035 /* cachedio.o already implements this function, so the
1036 dummy function below is not needed. */
1038 LONG
getbuffer(UBYTE
**tempbuffer
, ULONG
*maxblocks
) {
1040 /* Used by deviceio.o to get a piece of memory which it can
1041 use for buffering transfers when the Mask prevents a
1044 You must return 0, a pointer to the buffer and the number
1045 of blocks (each /bytes_block/ bytes in size) you allocated.
1046 For the purpose of SFScheck this function is probably never
1047 called since all our buffers are atleast LONG aligned and
1048 allocated with the correct bufmemtype. */
1050 return(ERROR_NO_FREE_STORE
);
1056 void starttimeout(void) {
1057 /* Called by deviceio.o each time there is a physical
1058 disk access. You can use this to start a timer and
1059 call motoroff() when the disk hasn't been accessed
1060 for a specific amount of time (SFS uses 1 second).
1062 SFScheck doesn't use this function. */