- Handle multiple nodes having output volume control.
[AROS.git] / rom / filesys / SFS / SFSdisplay / SFSdisplay.c
blobb34f71280df01453cef4d38de1bc699f6a6ccd8b
1 #include <devices/scsidisk.h>
2 #include <devices/trackdisk.h>
3 #include <dos/dos.h>
4 #include <dos/dosextens.h>
5 #include <dos/filehandler.h>
6 #include <exec/errors.h>
7 #include <exec/io.h>
8 #include <exec/memory.h>
9 #include <proto/dos.h>
10 #include <clib-org/exec_protos.h>
11 #include "stdio.h"
14 /* Almost ALL functions in this source are support functions
15 which were quickly copied from the main SFS source. The
16 most interesting function is saveextents(), which performs
17 the actual function of this program. */
20 #include "/fs/bitmap.h"
21 #include "/fs/objects.h"
22 #include "/fs/deviceio.h"
23 #include "/fs/fs.h"
24 #include "/fs/btreenodes.h"
26 #include <devices/newstyle.h> /* Doesn't include exec/types.h which is why it is placed here */
28 #include "/bitfuncs.c"
30 #define BLCKFACCURACY (5) /* 2^5 = 32 */
34 /* ASM prototypes */
36 extern ULONG __asm RANDOM(register __d0 ULONG);
37 extern LONG __asm STACKSWAP(void);
38 extern ULONG __asm CALCCHECKSUM(register __d0 ULONG,register __a0 ULONG *);
39 extern ULONG __asm MULU64(register __d0 ULONG,register __d1 ULONG,register __a0 ULONG *);
40 extern WORD __asm COMPRESSFROMZERO(register __a0 UWORD *,register __a1 UBYTE *,register __d0 ULONG);
44 LONG safedoio(UWORD action,UBYTE *buffer,ULONG blocks,ULONG blockoffset);
45 void display(void);
47 struct DosEnvec *dosenvec;
49 /* blocks_ = the number of blocks of something (blocks can contain 1 or more sectors)
50 block_ = a block number of something (relative to start of partition)
51 sectors_ = the number of sectors of something (1 or more sectors form a logical block)
52 sector_ = a sector number (relative to the start of the disk)
53 bytes_ = the number of bytes of something
54 byte_ = a byte number of something
55 shifts_ = the number of bytes written as 2^x of something
56 mask_ = a mask for something */
58 ULONG sectors_total; /* size of the partition in sectors */
59 UWORD sectors_block; /* number of sectors in a block */
60 UWORD pad4;
62 ULONG blocks_total; /* size of the partition in blocks */
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_used; /* number of blocks in use excluding reserved blocks
66 (=numblockused) */
67 ULONG blocks_bitmap; /* number of BTMP blocks for this partition */
68 ULONG blocks_inbitmap; /* number of blocks a single bitmap block can contain info on */
69 ULONG blocks_maxtransfer=1048576; /* max. blocks which may be transfered to the device at once (limits io_Length) */
71 ULONG block_root; /* the block offset of the root block */
72 ULONG block_extentbnoderoot; /* the block offset of the root of the extent bnode tree */
74 ULONG byte_low; /* the byte offset of our partition on the disk */
75 ULONG byte_lowh; /* high 32 bits */
76 ULONG byte_high; /* the byte offset of the end of our partition (excluding) on the disk */
77 ULONG byte_highh; /* high 32 bits */
79 ULONG bytes_block; /* size of a block in bytes */
80 ULONG bytes_sector; /* size of a sector in bytes */
82 ULONG mask_block;
83 ULONG mask_block32; /* masks the least significant bits of a BLCKf pointer */
84 ULONG mask_mask=0xFFFFFFFF; /* mask as specified by mountlist */
86 UWORD shifts_block; /* shift count needed to convert a blockoffset<->byteoffset */
87 UWORD shifts_block32; /* shift count needed to convert a blockoffset<->32byteoffset (only used by nodes.c!) */
89 ULONG disktype; /* the type of media inserted (same as id_DiskType in InfoData
90 structure) */
91 UBYTE newstyledevice=FALSE;
92 UBYTE does64bit=FALSE;
93 UBYTE is_casesensitive=FALSE;
94 UBYTE pad1;
95 UWORD cmdread=CMD_READ;
96 UWORD cmdwrite=CMD_WRITE;
99 struct MsgPort *msgport;
100 struct IOStdReq *ioreq;
101 void *pool;
103 ULONG block_objectnodesbase;
104 ULONG block_extentroot;
106 UBYTE *buffer;
107 ULONG *bitmap;
109 ULONG returncode=0;
111 LONG main() {
112 struct RDArgs *readarg;
113 UBYTE template[]="DEVICE=DRIVE/A\n";
115 struct {char *device;} arglist={NULL};
117 if((DOSBase=(struct DosLibrary *)OpenLibrary("dos.library",37))!=0) {
118 if((pool=CreatePool(0,16384,8192))!=0) {
119 if((readarg=ReadArgs(template,(LONG *)&arglist,0))!=0) {
120 struct MsgPort *msgport;
121 struct DeviceNode *dn;
122 UBYTE *devname=arglist.device;
124 while(*devname!=0) {
125 if(*devname==':') {
126 *devname=0;
127 break;
129 devname++;
132 dn=(struct DeviceNode *)LockDosList(LDF_DEVICES|LDF_READ);
133 if((dn=(struct DeviceNode *)FindDosEntry((struct DosList *)dn,arglist.device,LDF_DEVICES))!=0) {
134 struct FileSysStartupMsg *fssm;
136 fssm=(struct FileSysStartupMsg *)BADDR(dn->dn_Startup);
137 dosenvec=(struct DosEnvec *)BADDR(fssm->fssm_Environ);
139 UnLockDosList(LDF_DEVICES|LDF_READ);
141 if((msgport=CreateMsgPort())!=0) {
142 if((ioreq=CreateIORequest(msgport,sizeof(struct IOStdReq)))!=0) {
143 if(OpenDevice((UBYTE *)BADDR(fssm->fssm_Device)+1,fssm->fssm_Unit,(struct IORequest *)ioreq,fssm->fssm_Flags)==0) {
145 struct DosEnvec *de=dosenvec;
146 UWORD bs;
147 ULONG sectorspercilinder;
149 bytes_sector=de->de_SizeBlock<<2;
150 bytes_block=bytes_sector*de->de_SectorPerBlock;
152 bs=bytes_block;
154 shifts_block=0;
155 while((bs>>=1)!=0) {
156 shifts_block++;
158 shifts_block32=shifts_block-BLCKFACCURACY;
160 mask_block32=(1<<shifts_block32)-1;
161 mask_block=bytes_block-1;
163 /* Absolute offset on the entire disk are expressed in Sectors;
164 Offset relative to the start of the partition are expressed in Blocks */
166 sectorspercilinder=de->de_Surfaces*de->de_BlocksPerTrack; /* 32 bit */
167 sectors_total=sectorspercilinder*(de->de_HighCyl+1-de->de_LowCyl); /* 32 bit */
169 /* sectorspercilinder * bytes_sector cannot exceed 32-bit !! */
171 byte_lowh = MULU64(sectorspercilinder * bytes_sector, de->de_LowCyl, &byte_low);
172 byte_highh = MULU64(sectorspercilinder * bytes_sector, de->de_HighCyl+1, &byte_high);
174 sectors_block=de->de_SectorPerBlock;
176 blocks_total=sectors_total/de->de_SectorPerBlock;
177 blocks_reserved_start=de->de_Reserved;
178 blocks_reserved_end=de->de_PreAlloc;
180 if(blocks_reserved_start<1) {
181 blocks_reserved_start=1;
184 if(blocks_reserved_end<1) {
185 blocks_reserved_end=1;
188 blocks_inbitmap=(bytes_block-sizeof(struct fsBitmap))<<3; /* must be a multiple of 32 !! */
189 blocks_bitmap=(blocks_total+blocks_inbitmap-1)/blocks_inbitmap;
191 blocks_used=0;
193 printf("Partition start offset : 0x%08lx:%08lx End offset : 0x%08lx:%08lx\n",byte_lowh,byte_low,byte_highh,byte_high);
194 printf("sectors/block : %ld\n",de->de_SectorPerBlock);
195 printf("bytes/sector : %ld\n",bytes_sector);
196 printf("bytes/block : %ld\n",bytes_block);
197 printf("Total blocks in partition : %ld\n",blocks_total);
202 /* If the partition's high byte is beyond the 4 GB border we will
203 try and detect a 64-bit device. */
205 if(byte_highh!=0) {
206 struct NSDeviceQueryResult nsdqr;
207 UWORD *cmdcheck;
208 LONG errorcode;
210 /* Checks for newstyle devices and 64-bit support */
212 nsdqr.SizeAvailable=0;
213 nsdqr.DevQueryFormat=0;
215 ioreq->io_Command=NSCMD_DEVICEQUERY;
216 ioreq->io_Length=sizeof(nsdqr);
217 ioreq->io_Data=(APTR)&nsdqr;
219 if(DoIO((struct IORequest *)ioreq)==0 && (ioreq->io_Actual >= 16) && (nsdqr.SizeAvailable == ioreq->io_Actual) && (nsdqr.DeviceType == NSDEVTYPE_TRACKDISK)) {
220 /* This must be a new style trackdisk device */
222 newstyledevice=TRUE;
224 printf("Device is a new style device (NSD)\n");
226 /* Is it safe to use 64 bits with this driver? We can reject
227 bad mounts pretty easily via this check. */
229 for(cmdcheck=nsdqr.SupportedCommands; *cmdcheck; cmdcheck++) {
230 if(*cmdcheck == NSCMD_TD_READ64) {
231 /* This trackdisk style device supports the complete 64-bit
232 command set without returning IOERR_NOCMD! */
234 printf("Device supports 64-bit commands\n");
236 does64bit=TRUE;
237 cmdread=NSCMD_TD_READ64;
238 cmdwrite=NSCMD_TD_WRITE64;
242 else {
243 /* Checks for TD64 supporting devices */
245 ioreq->io_Command=24; /* READ64 */
246 ioreq->io_Length=0;
247 ioreq->io_Actual=0;
248 ioreq->io_Offset=0;
249 ioreq->io_Data=0;
251 errorcode=DoIO((struct IORequest *)ioreq);
252 if(errorcode!=-1 && errorcode!=IOERR_NOCMD) {
253 printf("Device supports 64-bit commands\n");
255 does64bit=TRUE;
256 cmdread=24;
257 cmdwrite=25;
262 if((buffer=AllocVec(bytes_block*2,0))!=0) {
263 display();
265 else {
266 printf("Not enough memory\n");
269 CloseDevice((struct IORequest *)ioreq);
271 DeleteIORequest(ioreq);
273 DeleteMsgPort(msgport);
276 else {
277 VPrintf("Unknown device %s\n",&arglist.device);
278 UnLockDosList(LDF_DEVICES|LDF_READ);
281 FreeArgs(readarg);
283 DeletePool(pool);
285 CloseLibrary((struct Library *)DOSBase);
287 return(returncode);
293 else if(SetSignal(0L,SIGBREAKF_CTRL_C) & SIGBREAKF_CTRL_C) {
294 PutStr("\n***Break\n");
295 break;
300 BOOL validblock(ULONG block) {
301 if(block<blocks_total) {
302 return(TRUE);
304 return(FALSE);
310 LONG doio(void) {
311 return(DoIO((struct IORequest *)ioreq));
317 LONG safedoio(UWORD action,UBYTE *buffer,ULONG blocks,ULONG blockoffset) {
318 ULONG command;
319 ULONG start,starthigh;
320 ULONG end,endhigh;
321 LONG errorcode;
323 if(action==DIO_READ) {
324 command=cmdread;
326 else if(action==DIO_WRITE) {
327 command=cmdwrite;
329 else {
330 return(-1);
334 start=(blockoffset<<shifts_block)+byte_low;
335 starthigh=(blockoffset>>(32-shifts_block))+byte_lowh; /* High offset */
336 if(start < byte_low) {
337 starthigh+=1; /* Add X bit :-) */
340 end=start+(blocks<<shifts_block);
341 endhigh=starthigh;
342 if(end < start) {
343 endhigh+=1; /* Add X bit */
346 ioreq->io_Data=buffer;
347 ioreq->io_Command=command;
348 ioreq->io_Length=blocks<<shifts_block;
349 ioreq->io_Offset=start;
350 ioreq->io_Actual=starthigh;
352 if( ( starthigh > byte_lowh || (starthigh == byte_lowh && start >= byte_low) ) &&
353 ( endhigh < byte_highh || (endhigh == byte_highh && end <= byte_high) ) ) {
355 /* We're about to do a physical disk access. (Re)set timeout. Since
356 the drive's motor will be turned off with the timeout as well we
357 always (re)set the timeout even if doio() would return an error. */
359 if((errorcode=doio())!=0) {
360 return(errorcode);
363 else {
364 // DEBUG(("byte_low = 0x%08lx:%08lx, byte_high = 0x%08lx:%08lx\n",byte_lowh,byte_low,byte_highh,byte_high));
365 // DEBUG(("start = 0x%08lx:%08lx, end = 0x%08lx:%08lx\n",starthigh,start,endhigh,end));
367 return(INTERR_OUTSIDE_PARTITION);
370 return(0);
376 BOOL checkchecksum(void *d) {
377 ULONG *data=(ULONG *)d;
379 if(CALCCHECKSUM(bytes_block,data)==0) {
380 return(TRUE);
382 return(FALSE);
387 struct fsObject *nextobject(struct fsObject *o) {
388 UBYTE *p;
390 /* skips the passed in fsObject and gives a pointer back to the place where
391 a next fsObject structure could be located */
393 p=(UBYTE *)&o->name[0];
395 /* skip the filename */
396 while(*p++!=0) {
399 /* skip the comment */
400 while(*p++!=0) {
403 /* ensure WORD boundary */
404 if((((ULONG)p) & 0x01)!=0) {
405 p++;
408 return((struct fsObject *)p);
413 WORD isobject(struct fsObject *o, struct fsObjectContainer *oc) {
414 UBYTE *endadr;
416 endadr=(UBYTE *)oc+bytes_block-sizeof(struct fsObject)-2;
418 if((UBYTE *)o<endadr && o->name[0]!=0) {
419 return(TRUE);
421 return(FALSE);
426 LONG read(ULONG block) {
427 return(safedoio(DIO_READ, buffer, 1, block));
432 struct BNode *searchforbnode(ULONG key, struct BTreeContainer *tc) {
433 struct BNode *tn;
434 WORD n=tc->nodecount-1;
436 tn=(struct BNode *)((UBYTE *)tc->bnode+n*tc->nodesize);
438 for(;;) {
439 if(n<=0 || key >= tn->key) {
440 return(tn);
442 tn=(struct BNode *)((UBYTE *)tn-tc->nodesize);
443 n--;
449 LONG findbnode(BLCK rootblock,ULONG key,struct BNode **returned_bnode) {
450 LONG errorcode;
452 while((errorcode=read(rootblock))==0) {
453 struct fsBNodeContainer *bnc=(struct fsBNodeContainer *)buffer;
454 struct BTreeContainer *btc=&bnc->btc;
456 if(btc->nodecount==0) {
457 *returned_bnode=0;
458 break;
461 *returned_bnode=searchforbnode(key,btc);
462 if(btc->isleaf==TRUE) {
463 break;
465 rootblock=(*returned_bnode)->data;
468 return(errorcode);
473 void display(void) {
474 struct fsExtentBNode *ebn;
475 LONG n=blocks_bitmap;
476 ULONG bitmapblock=34;
477 BLCK block=0;
478 LONG errorcode=0;
480 while(n-->0 && (errorcode=read(bitmapblock))==0) {
481 struct fsBitmap *b=(struct fsBitmap *)(buffer+bytes_block);
483 CopyMemQuick(buffer, b, bytes_block);
485 for(;;) {
486 if(block>=blocks_total) {
487 break;
490 if((block / blocks_inbitmap)!=bitmapblock-34) {
491 break;
494 if((errorcode=findbnode(6, block, (struct BNode **)&ebn))!=0) {
495 printf("Error %ld occured during scanning (findbnode).\n",errorcode);
497 return;
500 if(ebn==0 || ebn->key!=block) {
501 ULONG offset=(block % blocks_inbitmap);
503 if((b->bitmap[offset/32] & (1<<(31-(offset & 0x1F))))==0) {
504 printf("u");
506 else {
507 printf(".");
509 block++;
511 else {
512 UWORD blocks=ebn->blocks;
514 if(blocks==1) {
515 printf("H");
517 else {
518 if((ebn->prev & 0x80000000)==0) {
519 printf("<");
521 else {
522 printf("[");
525 blocks-=2;
527 while(blocks-->0) {
528 printf("o");
531 if(ebn->next==0) {
532 printf("]");
534 else {
535 printf(">");
539 block+=ebn->blocks;
543 bitmapblock++;
546 printf("\n");
548 if(errorcode!=0) {
549 printf("Error %ld occured during scanning.\n",errorcode);