home *** CD-ROM | disk | FTP | other *** search
- /*
- ** This is a further modification to the Bformat program developed by
- ** Bob Bush. This generation now allows the formatting of any device
- ** using either file system. It still maps out bad sectors, but does it
- ** a sector at a time instead of a track at a time. This is particularly
- ** useful for the formatting of hard disks.
- **
- ** The command format is:
- ** BFormat DRIVE <drive> NAME <name> [FFS|NOFFS] [FAST|QUICK|SLOW] [QuIeT]
- ** please note that the format is strictly enforced. All field must be
- ** specified in the specified order.
- */
-
- /* bformat.c */
-
- /*
- When you format a diskette dos grabs 2 blocks for its own use.
- Block 880 is the Root block. Block 881 (normally on a fresh format) is
- the bitmap which in itself indicates the blocks that are available for use
- or currently in use. Generally, a '1' bit means the corresponding block
- is available. A '0' bit means that the block is in use. This sounds
- relatively simple but the AmigaDos implementation needs some
- explanation.
-
- AmigaDos Block Allocation Map (512 bytes -or- 128 longwords)
- ------------------------------------------------------------
- LongWord Usage
- -------- -----
- 0 location of the block checksum
- 1 first bitmap allocation longword, which breaks down as follows:
-
- hi-order bit (31) lo-order bit (0)
- / /
- | |
- 11111111111111111111111111111111 (32 bit longword)
- \\ \\\
- \\_block #32 \\\_block #2
- \_block #33 \\_block #3
- \_block #4
-
- (The above example indicates that blocks 2 thru 33 are available for use)
-
- You might wonder why the bitmap starts at block #2 and not block #0?
- I suppose since the first 2 blocks of every disk are not available for
- file storage, AmigaDos simply chooses to ignore the fact that they exist.
- Another reason could be that if the bitmap included blocks zero and one,
- it might be too easy to figure out.. Hmmmmm..
- Actually I think it corresponds to the well documented (ha) Mountlist
- parameter named 'Reserved' which can be used to segment a hard disk into
- more than one logical drive If you look at it in that light, the first
- bit in the bitmap corresponds to a block number which is the same as the
- number of 'Reserved' blocks in the Mountlist file.. Have yet to verify
- this on my hard disk but it sounds logical. ( Note from Tom Nery -
- Unfortunately the 2 block offset is not related to the 'Reserved'
- parameter, It was a good guess though).
-
- Inany case, the remainder of the bitmap looks the same e.g. the next
- longword (lo order bit) starts the map for block #34 -- and so on, until
- the map terminates at block #1760...
-
- With the above info, you should be able to figure out how this program
- works.
- */
-
- /*
- Date Programmer Modification
- ========= ========== =============================================
- 91-Feb-10 T.A.Nery Removed support for '-C' option but added
- support for all mounted disk type devices,
- including FFS. Also added support for various
- levels of disk verificaition.
- 88-Aug-18 R.W.Bowers Created this header, added Execute "code" above
- 88-Aug-15 R.W.Bowers Fixed a "minor" BUG! Using the -C[heck]
- option "erased" the entire disk!!
- 88-Aug-14 R.W.Bowers Changed reporting from "Track xx" to
- "Cyl yy, Head z"
- 88-Jul-10 R.W.Bowers Changed # tracks from 160 to "Tracks"
- 88-Jul-10 R.W.Bowers Compiles under Lattice 4.0 or, with -dMANX,
- under MANX
- 88-Mar-28 Bob Bush cpu-73105,1332 - compiled with Lattice 4.0
- */
-
- #include "exec/types.h"
- #include "exec/nodes.h"
- #include "exec/lists.h"
- #include "exec/memory.h"
- #include "exec/interrupts.h"
- #include "exec/ports.h"
- #include "exec/libraries.h"
- #include "exec/io.h"
- #include "exec/tasks.h"
- #include "exec/execbase.h"
- #include "exec/devices.h"
- #include "devices/trackdisk.h"
- #include "intuition/intuition.h"
- #include "libraries/dos.h"
- #include "libraries/dosextens.h"
- #include "libraries/filehandler.h"
- #include "stdio.h"
- #include <string.h>
-
- #define DONE 0
- #define CONT 1
-
- #define FAILURE 0
- #define SUCCESS 1
-
- #define OLD 0x444f5300L
- #define FFS 0x444f5301L
-
- #define FAST 1
- #define QUICK 2
- #define SLOW 3
-
- #define NEXT_DEVICE(device) ((struct DosList *) BADDR(device->dol_Next))
-
- struct INFO {
- char Drive[80]; /* Drive Name (eg. df0:) */
- char Label[80]; /* Disk Label (eg. Empty) */
- char Device[80]; /* Device Name (eg. trackdisk.device) */
- int Unit; /* Device's unit number, per mountlist */
- long Sectors; /* Number of Sectors per track */
- long Surfaces; /* Number of Surfaces */
- long LoCyl; /* Starting Cylinder number */
- long HiCyl; /* Ending Cylinder number */
- long FileSystem; /* File system being used */
- /* 0x444f5300 - Old File System */
- /* 0x444f5301 - Fast File System */
- };
-
- extern struct DosLibrary *DOSBase;
-
- struct INFO Info;
-
- BOOL formatting = FALSE;
-
- ULONG bitmap_size; /* Number of bytes allocated to init the bitmaps */
- long *buffer,*bitmap,*track = NULL;
- short abort;
- long TestPattern[4] ={0xFFFFFFFFL, 0xAAAAAAAAL, 0x55555555L, 0x00000000L};
- struct IOStdReq *mreq = NULL;
- struct MsgPort *mport,*dosport = NULL;
- struct StandardPacket *dpacket; /* packet for dos */
- int Verify_mode;
- int Quiet;
-
-
- /*
- ** Convert a BPCL string to a 'C' style string
- */
- int convert_bstr(out,in,colon)
- BYTE *in;
- char *out;
- int colon;
- {
- if ((*in >= 59) || (*in == 0))
- return(FALSE);
-
- memcpy(out, in+1, *in);
- if (colon == TRUE)
- {
- out[*in] = ':';
- out[(*in)+1] = '\0';
- }
- else
- out[*in] = '\0';
-
- return(TRUE);
- }
-
-
- void write_block(block,buff)
- long block;
- long *buff;
- {
- mreq->io_Length = 512;
- mreq->io_Data = (APTR)buff;
- mreq->io_Command = CMD_WRITE;
- mreq->io_Offset = block * 512;
- DoIO(mreq);
- }
-
-
- void Update()
- {
- mreq->io_Length = 1;
- mreq->io_Command = CMD_UPDATE;
- DoIO(mreq);
- }
-
-
- int Clear()
- {
- mreq->io_Length = 0;
- mreq->io_Command = CMD_CLEAR;
- DoIO(mreq);
- return(0);
- }
-
-
- /*
- ** Check for the existence of the specified device. If found, set the
- ** default format parameters for the specific mountlist entry.
- */
-
- int check_dev(dev,drive)
- struct DeviceNode *dev;
- char drive[];
- {
- struct FileSysStartupMsg *startup;
- char Name[80];
- ULONG *dosenv;
-
-
- if (convert_bstr(Name,BADDR(dev->dn_Name),TRUE) == TRUE)
- {
- if (stricmp(Name,drive) == 0)
- {
- strcpy(Info.Drive,Name);
- }
- else
- return(FAILURE);
- }
- else
- return(FAILURE);
-
- startup = (struct FileSysStartupMsg *)(BADDR(dev->dn_Startup));
- Info.Unit = startup->fssm_Unit;
-
- if (convert_bstr(Name,BADDR(startup->fssm_Device),FALSE) == TRUE)
- {
- strcpy(Info.Device,Name);
- }
-
- dosenv = (ULONG *) (BADDR(startup->fssm_Environ));
-
- Info.Sectors = dosenv[5];
- Info.Surfaces = dosenv[3];
- Info.LoCyl = dosenv[9];
- Info.HiCyl = dosenv[10];
-
- Info.FileSystem = OLD;
- if (dosenv[16] == FFS)
- Info.FileSystem = FFS;
-
- return(SUCCESS);
- }
-
-
- void cmd_error()
- {
- printf("\nCommand Format Error. Command Syntax is:\n");
- printf(" BFormat DRIVE <drive> NAME <name> [FFS|NOFFS] [FAST|QUICK|SLOW] [QuIeT]\n");
- exit(10);
- }
-
-
- int check_struct(dev,drive)
- struct DosList *dev;
- char drive[];
- {
- if ((dev->dol_Type) == DLT_DEVICE)
- if (check_dev(dev,drive) == SUCCESS)
- return(DONE);
-
- return(CONT);
- }
-
-
- int verify(drive)
- char drive[];
- {
- struct RootNode *rootNode;
- struct DosInfo *dosInfo;
- struct DosList *firstDevice, *device;
-
- rootNode = (struct RootNode *) DOSBase->dl_Root;
- dosInfo = (struct DosInfo *) BADDR(rootNode->rn_Info);
- firstDevice = (struct DosList *) BADDR(dosInfo->di_DevInfo);
-
- for (device = firstDevice ; device ; device = NEXT_DEVICE(device))
- {
- if (check_struct(device,drive) == DONE)
- return(SUCCESS);
- }
- printf("\nDrive %s Not Found", drive);
- return(FAILURE);
- }
-
-
- int chk_params(cnt,args)
- int cnt;
- char *args[];
- {
- int i;
-
- /* Check if the correct number of arguments */
- if (cnt < 5)
- return(FAILURE);
-
- /* Make sure all keywords are valid */
- if (stricmp(args[1],"DRIVE"))
- return(FAILURE);
- else if (verify(args[2]) != SUCCESS)
- return(FAILURE);
-
- if (stricmp(args[3],"NAME"))
- return(FAILURE);
- else
- strcpy(Info.Label,args[4]);
-
- Verify_mode = QUICK;
- Quiet = FALSE;
- for (i = 5 ; i < cnt ; ++i)
- {
- if (stricmp(args[i],"FFS") == 0)
- Info.FileSystem = FFS;
- else if (stricmp(args[i],"NOFFS") == 0)
- Info.FileSystem = OLD;
- else if (stricmp(args[i],"SLOW") == 0)
- Verify_mode = SLOW;
- else if (stricmp(args[i],"QUICK") == 0)
- Verify_mode = QUICK;
- else if (stricmp(args[i],"FAST") == 0)
- Verify_mode = FAST;
- else if (strcmp(args[i],"QuIeT") == 0)
- Quiet = TRUE;
- else
- return(FAILURE);
- }
-
- return(SUCCESS);
- }
-
-
- void inhibit(t)
- long t; /* true or false */
- {
- struct MsgPort *handler;
- struct StandardPacket *packet = dpacket ;
-
- handler = (struct MsgPort *)DeviceProc(Info.Drive);
- if (!((handler == NULL) || (dosport == NULL)))
- {
- packet->sp_Msg.mn_Node.ln_Name = (char *)&(packet->sp_Pkt);
- packet->sp_Pkt.dp_Link = &(packet->sp_Msg);
- packet->sp_Pkt.dp_Port = dosport;
- packet->sp_Pkt.dp_Type = ACTION_INHIBIT;
- packet->sp_Pkt.dp_Arg1 = t;
- PutMsg(handler, packet);
- WaitPort(dosport);
- GetMsg(dosport);
- }
- }
-
-
- void cleanup(err)
- int err;
- {
- inhibit(FALSE);
- if(mreq)
- {
- CloseDevice(mreq);
- DeleteStdIO(mreq);
- }
-
- if(mport)
- DeletePort(mport);
- if(dosport)
- DeletePort(dosport);
- if(dpacket)
- FreeMem(dpacket,sizeof(struct StandardPacket));
- if(bitmap)
- FreeMem(bitmap,bitmap_size);
- if(buffer)
- FreeMem(buffer,512);
- if(track)
- FreeMem(track,512 * Info.Sectors);
- exit(0);
- }
-
-
- /* handle ctrl-c, ctrl-d aborts */
- int brk()
- {
- int c;
- char buf[20];
-
- if(formatting)
- {
- printf("\n*** Break ***");
- printf("\nDo you really want to abort (y/n)? ");
- gets(buf); c = buf[0];
- if (c == 'y' || c == 'Y')
- {
- printf(
- "\nWarning! Disk may be unusable.\n\n");
- cleanup(0); /* Was cleanup(999); */
- }
- else
- abort = 0;
-
- return(0);
- }
- }
-
-
- void format_track(tnum)
- int tnum;
- {
-
- mreq->io_Length = 512 * Info.Sectors;
- mreq->io_Data = (APTR)track;
- mreq->io_Command = TD_FORMAT;
- mreq->io_Offset = tnum * Info.Sectors * 512;
- DoIO(mreq);
- }
-
-
- void write_track(tnum)
- int tnum;
- {
- mreq->io_Length = 512 * Info.Sectors;
- mreq->io_Data = (APTR)track;
- mreq->io_Command = CMD_WRITE;
- mreq->io_Offset = tnum * Info.Sectors * 512;
- DoIO(mreq);
- }
-
-
- void set_fbuff(buff,sectors,value)
- ULONG buff[];
- int sectors;
- long value;
- {
- int j;
-
- for(j = 0; j < (128 * sectors);j++)
- buff[j] = value;
- }
-
-
- /* verify track with abort on critical tracks */
- int verify_track(tnum)
- int tnum;
- {
- int test;
- int length;
-
- length = 512 * Info.Sectors;
-
- if (Verify_mode == SLOW)
- {
- for (test = 0 ; test < 4 ; ++test)
- {
- set_fbuff(track,Info.Sectors,TestPattern[test]);
- write_track(tnum);
-
- mreq->io_Length = length;
- mreq->io_Data = (APTR)track;
- mreq->io_Command = CMD_READ;
- mreq->io_Offset = tnum * Info.Sectors * 512;
- DoIO(mreq);
- if ((mreq->io_Error) || (mreq->io_Actual != length))
- return(0);
- }
- }
- else if (Verify_mode == QUICK)
- {
- mreq->io_Length = length;
- mreq->io_Data = (APTR)track;
- mreq->io_Command = CMD_READ;
- mreq->io_Offset = tnum * Info.Sectors * 512;
- DoIO(mreq);
- if ((mreq->io_Error) || (mreq->io_Actual != length))
- return(0);
- }
- else
- {
- mreq->io_Length = 512;
- mreq->io_Data = (APTR)track;
- mreq->io_Command = CMD_READ;
- mreq->io_Offset = tnum * Info.Sectors * 512;
- DoIO(mreq);
- if ((mreq->io_Error) || (mreq->io_Actual != 512))
- return(0);
- }
-
- return(1);
- }
-
-
- void chk_abort()
- {
- if (SetSignal(0L, (ULONG) (SIGBREAKF_CTRL_C)) & (SIGBREAKF_CTRL_C))
- brk();
- }
-
-
- void validate_required()
- {
- int fstat;
- int sel_track;
-
- /* chk_abort(); */
-
- /*
- ** First calculate the starting track number
- */
- sel_track = Info.LoCyl * Info.Surfaces;
- /*
- ** Verify that track 0 is usable.
- */
- set_fbuff(track,Info.Sectors,Info.FileSystem);
- format_track(sel_track);
- /* chk_abort(); */
-
- formatting = TRUE;
- if (!(fstat = verify_track(sel_track)))
- {
- printf("\nUnable to format track #0. ");
- printf("Disk not useable.\n\n");
- cleanup(100);
- }
-
- /*
- ** Now calculate the Root Block's track number
- */
- sel_track += (((Info.HiCyl - Info.LoCyl + 1) * Info.Surfaces)/2);
- /*
- ** Verify that root block track is usable.
- */
- format_track(sel_track);
- if (!(fstat = verify_track(sel_track)))
- {
- printf("\nUnable to format root block. ");
- printf("Disk not useable.\n\n");
- cleanup(100);
- }
- }
-
-
- /* mark block as allocated (in use) */
- void clear_bitmap(block)
- long block;
- {
- long lindex;
-
- if ((block - 2) > -1)
- {
- lindex = (block - 2) / 32;
- bitmap[lindex] = bitmap[lindex] & (~(1 << ((block-2) % 32)));
- }
- }
-
-
- /* mark block as available for use */
- void set_bitmap(block)
- int block;
- {
- int lindex;
-
- if ((block - 2) > -1)
- {
- lindex = (block - 2) / 32;
- bitmap[lindex] = bitmap[lindex] | (1 << ((block-2) % 32));
- }
- }
-
-
- /* mark track as available */
- int set_track(tnum)
- int tnum;
- {
- int j;
-
- mreq->io_Command = TD_PROTSTATUS;
- DoIO(mreq);
- if(mreq->io_Actual)
- {
- printf("Disk Write Protected!\n");
- printf("\nWarning! Disk may be unusable.\n\n");
- cleanup(0); /* Was cleanup(999); */
- return(0);
- }
-
- for(j = (tnum * Info.Sectors) ;
- j < (tnum * Info.Sectors + Info.Sectors);j++)
- set_bitmap(j);
- }
-
-
- /* set volume name into root block (BCPL string) */
- void set_name(dest,vname)
- char *dest,*vname;
- {
- *dest = (char)strlen(vname);
- dest++;
- while(*vname)
- {
- *dest = *vname;
- dest++; vname++;
- }
- }
-
-
- void zblock(wp) /* clear buffer to zeros */
- ULONG wp[];
- {
- int j;
-
- for(j = 0; j < 128; j++)
- wp[j] = 0;
- }
-
-
- /* checksum= 2's complement of sum of all words in block */
- ULONG check_sum(buff)
- ULONG buff[];
- {
- int j;
- ULONG cksum;
-
- cksum = 0;
- for(j = 0; j < 128; j++)
- cksum += buff[j]; /* sum all words in block */
- return(-cksum);
- }
-
-
- /* build initialized root block */
- void init_root(wp,vname,blk)
- ULONG wp[];
- char *vname;
- long blk;
- {
- int i, bit_blks;
- ULONG temp;
-
- temp = 0;
- bit_blks = bitmap_size/512;
- wp[5] = 0;
-
- zblock(wp);
-
- wp[0] = 0x02; /* type */
- wp[3] = 0x48; /* hashtable size */
- wp[78] = 0xffffffff; /* 'true' bitmap flag */
- for (i = 1 ; i <= bit_blks ; ++i)
- wp[78+i] = blk + i;
- DateStamp(&wp[105]); /* datestamp */
- set_name(&wp[108],vname); /* disk name (BCPL) string */
- DateStamp(&wp[121]); /* datestamp */
- wp[127] = 0x01; /* secondary type = root */
-
- wp[5] = check_sum(wp); /* create root block checksum */
-
- }
-
-
- void init_bitmap(wp,root_block)
- ULONG wp[];
- long root_block;
- {
- int i, bit_blks;
-
- bit_blks = bitmap_size/512;
-
- clear_bitmap(root_block); /* set root block to allocated */
-
- for (i = 1; i <= bit_blks ; ++i)
- clear_bitmap(root_block + i);
- }
-
-
- /*
- ** Inhibits dos from trying to access drive while we have control. Also puts
- ** up DF0:BUSY message, causes dos to re-read disk info on termination.
- */
- int Checkstat()
- {
- mreq->io_Command = TD_CHANGESTATE;
- DoIO(mreq);
-
- if(mreq->io_Actual)
- {
- printf("No Disk In Drive!\n");
- return(1);
- }
- mreq->io_Command = TD_PROTSTATUS;
- DoIO(mreq);
-
- if (mreq->io_Actual)
- {
- printf("Disk Write Protected!\n");
- return(1);
- }
- return(0);
- }
-
- void format_it()
- {
- int error,fstat,badcount;
- int bytes, i, j;
- int block_cnt, cyl_cnt;
- int block_start, cyl, head, trk;
- char c;
- long *map_p, block_num, track_size;
-
-
- badcount = 0;
- cyl_cnt = Info.HiCyl - Info.LoCyl + 1;
- block_cnt = cyl_cnt * Info.Sectors * Info.Surfaces;
- track_size = Info.Sectors * 512;
- block_start = Info.LoCyl * Info.Sectors * Info.Surfaces;
-
- if (Quiet != TRUE)
- {
- printf("\nDrive = %s Name = %s\n",
- Info.Drive, Info.Label);
-
- printf("Insert Disk to be FORMATTED in drive %s.\n",
- Info.Drive);
- printf("Press Return when ready: ");
- c = getchar();
- }
- chkabort();
-
- if(!(mport = (struct MsgPort *)CreatePort("FLOPPY0",0)))
- cleanup(100);
- if(!(dosport = (struct MsgPort *)CreatePort("DOSPORT",0)))
- cleanup(100);
- if(!(mreq = (struct IOStdReq *)CreateStdIO(mport)))
- cleanup(100);
- if(!(dpacket=(struct StandardPacket *)
- AllocMem(sizeof(struct StandardPacket), MEMF_PUBLIC|MEMF_CLEAR)))
- cleanup(100);
-
- if(error = OpenDevice(Info.Device,Info.Unit,mreq,0))
- cleanup(1);
-
- inhibit(TRUE);
- /* chk_abort(); */
-
- /*
- ** Determine how many blocks are required for bitmap, then allocate them
- ** Block size calculations based upon 508 byte blocks, since the first
- ** four bytes of each block are for checksum.
- */
- bytes = block_cnt/8;
- for (bitmap_size = 508 ; bitmap_size < bytes ; bitmap_size += 508) ;
-
- /*
- printf("\nBitmap_size = %d Bytes or %d Blocks\n",
- bitmap_size,bitmap_size/508);
- */
-
- bitmap_size = bitmap_size / 508 * 512;
- if(!(bitmap = (long *)AllocMem(bitmap_size, MEMF_CLEAR | MEMF_CHIP)))
- cleanup(8);
- if(!(buffer = (long *)AllocMem(512,MEMF_CLEAR | MEMF_CHIP)))
- cleanup(8);
- if(!(track = (long *)AllocMem(track_size,MEMF_CLEAR | MEMF_CHIP)))
- cleanup(8);
-
- if (Checkstat())
- cleanup(100);
-
- /* chk_abort(); */
- validate_required();
-
- for (cyl = Info.LoCyl ; cyl <= Info.HiCyl ; ++cyl)
- {
- if (Quiet != TRUE)
- printf("Formatting Cylinder %d\n",cyl);
- for (head = 0 ; head < Info.Surfaces ; ++head)
- {
- trk = cyl * Info.Surfaces + head;
-
- format_track(trk);
- /* chk_abort(); */
- }
-
- if (Quiet != TRUE)
- printf("Verifying Cylinder %d\n",cyl);
- for (head = 0 ; head < Info.Surfaces ; ++head)
- {
- trk = cyl * Info.Surfaces + head;
-
- if (!(fstat = verify_track(trk)))
- {
- badcount += Info.Sectors;
- }
- else
- {
- trk = (cyl - Info.LoCyl)
- * Info.Surfaces + head;
- set_track(trk);
- }
-
- /* chk_abort(); */
- }
- }
- if (Quiet != TRUE)
- printf("\n%d Sectors Allocated as Bad\n",badcount);
-
- /* init boot/root/bitmap blocks and write to disk.. */
- set_fbuff(buffer,1,Info.FileSystem);
- write_block(block_start, buffer);
- set_fbuff(buffer,1,Info.FileSystem);
- write_block(block_start+1, buffer);
-
- /* Root block is middle of device */
- block_num = block_cnt/2 + block_start;
- init_root(buffer,Info.Label,(long)(block_cnt/2));
- /* printf("Writing Root Block, #%d\n",block_num); */
- write_block(block_num, buffer);
-
- init_bitmap(bitmap,block_cnt/2);
- for (i = 1, map_p = (long *)bitmap ;
- i <= (bitmap_size/512) ; ++i, map_p += 128)
- {
- /* calculate checksum for each block and insert */
- for (j = 0 ; j < 127 ; ++j)
- buffer[j + 1] = map_p[j];
-
- buffer[0] = 0;
- buffer[0] = check_sum(buffer);
-
- /* printf("Writing Bitmap Block, #%d\n",block_num+i); */
- write_block((long)(block_num + i), buffer);
- }
-
- Update();
- Clear();
-
- mreq->io_Length = 0;
- mreq->io_Command = TD_MOTOR; /* turn off motor */
- DoIO(mreq);
-
- cleanup(0);
- }
-
-
- main(cnt,argi l;
- );
- Clea );
- n( Ino; ++head)
- {
- "p ;
- to (ean.o*/
- DoIcnt, cyl_cn);
-
- rrum 2Tj)
- bufferu
-
- main" 8d\n",al)8 *|f ,tSC3f (!(&rack(
- initor>.ºh128)
- Lotor */
- D ,tSCu
- {dlock and insert */
- for (j = 0 ; j mea ));
- lida,ru
-
- c (bitmap_size x ));
- lida,rmapu0= 0o"p ru Bytes crify_t(0)*culate<, #Q(eaQ(ea*at *0)))
- ck aÐ4C3f (!(&¤(
- inj = bl = bl = bl aÐ4j(block_startn
-
- LId1T 0 ,();8i; bitmapap =gngtha iniblock10= gc0i)8 *|f e fice= bl = bl = bl aÐ4jÆoitm; + m; Rgc+ m; Rgco,;nbym(!(eeeck(bl)u8to (map_size)8 *|f gck.. * .ºh128)
- Lotock0_u#Q(eaQ(7t
-
- riteingtha