$modcal$

$linenum 11000$
$lines 54$

$partial_eval on$

$range off$
$ovflcheck off$
$debug off$

{
{ Low-level calculation routines for getting byte offsets,
{ fragment sizes, etc. etc.  Largely a Pascal implementation of
{ the routines in fs.h, plus a few from param.h and sysmacros.h.
}

module hfscalc;


$search 'hfstuff'$
import hfstuff, iocomasm;

export

{
{ calculate starting byte of various objects
}
function inode_start(fs: super_block_ptr_type;
		     inode_num: integer): integer;
function data_start(fs: super_block_ptr_type;
		    dblock_num: integer): integer;
function cgroup_start(fs: super_block_ptr_type;
		      cgroup_num: integer): integer;

{
{ miscellany
}
function min(a, b: integer): integer;
function max(a, b: integer): integer;
function howmany(x: integer; y: integer): integer;
function roundup(x: integer; y: integer): integer;
function rounddownp2(x: integer; y: integer): integer;
function freespace(fs: super_block_ptr_type;
		   percentreserved: integer): integer;

{
{ bitmap manipulation
}
procedure setbit(anyvar a: freemap_type; i: integer);
procedure clrbit(anyvar a: freemap_type; i: integer);
function isset(anyvar a: freemap_type; i: integer): boolean;
function isclr(anyvar a: freemap_type; i: integer): boolean;
function blkmap(fs: super_block_ptr_type;
		 anyvar map: freemap_type; loc: integer): integer;

{
{ conversion
}
function btodb(i: integer): integer;
function fragstoblks(fs: super_block_ptr_type; frags: integer): integer;
function blkstofrags(fs: super_block_ptr_type; blks: integer): integer;
function cgtod(fs: super_block_ptr_type; c: integer): integer;
function dtog(fs: super_block_ptr_type; d: integer): integer;
function dtogd(fs: super_block_ptr_type; d: integer): integer;
function cbtocylno(fs: super_block_ptr_type; bno: integer): integer;
function cbtorpos(fs: super_block_ptr_type; bno: integer): integer;
function itog(fs: super_block_ptr_type; x: integer): integer;
function fragstobytes(fs: super_block_ptr_type; frags: integer): integer;

{
{ X per Y
}
function nspb(fs: super_block_ptr_type): integer;
function nspf(fs: super_block_ptr_type): integer;
function maxbpc: integer;

{
{ offset calculation
}
function fs_cs(fs: super_block_ptr_type; indx: integer): csumm_ptr_type;
function blkoff(fs: super_block_ptr_type; loc: integer): integer;
function fragoff(fs: super_block_ptr_type; loc: integer): integer;
function lblkno(fs: super_block_ptr_type; loc: integer): integer;
function numfrags(fs: super_block_ptr_type; loc: integer): integer;
function fragroundup(fs: super_block_ptr_type; size: integer): integer;
function blksize(fs: super_block_ptr_type;
		  ip: inode_ptr_type; lbn: integer): integer;
function cgsblock(fs: super_block_ptr_type; c: integer): integer;


implement


{
{ set bit i in bitmap a
{ #define setbit(a,i)     ((a)[(i)/NBBY] |= 1<<((i)%NBBY))
}
procedure setbit(anyvar a: freemap_type; i: integer);
var
    index: integer;
begin
    index := i div NBBY;
    a[index] := binior(a[index], binasl(1, i mod NBBY));
end;


{
{ clr bit i in bitmap a
{ #define clrbit(a,i)     ((a)[(i)/NBBY] &= ~(1<<((i)%NBBY)))
}
procedure clrbit(anyvar a: freemap_type; i: integer);
var
    index: integer;
begin
    index := i div NBBY;
    a[index] := binand(a[index], bincmp(binasl(1, i mod NBBY)));
end;


{
{ is bit i set in bitmap a?
{ #define isset(a,i)      ((a)[(i)/NBBY] & (1<<((i)%NBBY)))
}
function isset(anyvar a: freemap_type; i: integer): boolean;
var
    index: integer;
begin
    index := i div NBBY;
    isset := binand(a[index], binasl(1, i mod NBBY)) <> 0;
end;


{
{ is bit i clr in bitmap a?
{ #define isclr(a,i)      (((a)[(i)/NBBY] & (1<<((i)%NBBY))) == 0)
}
function isclr(anyvar a: freemap_type; i: integer): boolean;
var
    index: integer;
begin
    index := i div NBBY;
    isclr := binand(a[index], binasl(1, i mod NBBY)) = 0;
end;


{
{ bytes to device blocks
{ #define btodb(bytes) ((unsigned)(bytes) >> DEV_BSHIFT)
}
function btodb(i: integer): integer;
begin
    btodb := binlsr(i, DEV_BSHIFT);
end;


{
{ inodes per big block
{ #define INOPB(fs)      ((fs)->fs_inopb)
}
function inopb(fs: super_block_ptr_type): integer;
begin
    inopb := fs^.inopb;
end;


{
{ inodes per fragment
{ #define INOPF(fs)      ((fs)->fs_inopb >>(fs)->fs_fragshift)
}
function inopf(fs: super_block_ptr_type): integer;
begin
    inopf := binasr(fs^.inopb, fs^.fragshift);
end;


{
{ how many things of size y cover a thing of size x?
{ #define howmany(x, y)  (((x)+((y)-1))/(y))
}
function howmany(x: integer; y: integer): integer;
begin
    howmany := (x + (y - 1)) DIV y;
end;


{
{ round x up to the next multiple of y
{ #define roundup(x, y)  ((((x)+((y)-1))/(y))*(y))
}
function roundup(x: integer; y: integer): integer;
begin
    roundup := ((x + y - 1) DIV y) * y;
end;


{
{ round x down to the next multiple of y
{ y must be a power of 2
}
function rounddownp2(x: integer; y: integer): integer;
begin
    rounddownp2 := binand(x, bincmp(y - 1));
end;


{
{ number of sectors per big block
{ #define NSPB(fs)       ((fs)->fs_nspf <<(fs)->fs_fragshift)
}
function nspb(fs: super_block_ptr_type): integer;
begin
    nspb := binasl(fs^.nspf, fs^.fragshift);
end;


{
{ number of sectors per fragment
{ #define NSPF(fs)       ((fs)->fs_nspf)
}
function nspf(fs: super_block_ptr_type): integer;
begin
    nspf := fs^.nspf;
end;


{
{ fragments to big blocks }
{ #define fragstoblks(fs, frags)  /* calculates(frags / fs->fs_frag) */ \
{  ((frags) >>(fs)->fs_fragshift)
}
function fragstoblks(fs: super_block_ptr_type; frags: integer): integer;
begin
    fragstoblks := binasr(frags, fs^.fragshift);
end;


{
{ big blocks to fragments }
{ #define blkstofrags(fs, blks)   /* calculates(blks * fs->fs_frag) */ \
{  ((blks) <<(fs)->fs_fragshift)
}
function blkstofrags(fs: super_block_ptr_type; blks: integer): integer;
begin
    blkstofrags := binasl(blks, fs^.fragshift);
end;


{
{ ptr to cylinder summary info for given cg
{ #define fs_cs(fs, indx) \
{     fs_csp[(indx) >>(fs)->fs_csshift][(indx) & ~(fs)->fs_csmask]
{     /*      first index       *//*     second index      */
}
function fs_cs(fs: super_block_ptr_type; indx: integer): csumm_ptr_type;
begin
    with fs^ do
	fs_cs :=
	    addr(csp[binasr(indx,csshift)]^[binand(indx,bincmp(csmask))]);
end;


{
{ max frags per cylinder cycle
/*
 * MAXBPC bounds the size of the rotational layout tables and
 * is limited by the fact that the super block is of size SBSIZE.
 * The size of these tables is INVERSELY proportional to the block
 * size of the file system. It is aggravated by sector sizes that
 * are not powers of two, as this increases the number of cylinders
 * included before the rotational pattern repeats(fs_cpc).
 * Its size is derived from the number of bytes remaining in(struct fs)
 */
{ #define MAXBPC (SBSIZE - sizeof(struct fs))
}
function maxbpc: integer;
begin
    maxbpc := SBSIZE - sizeof(super_block_type);
end;


{
{ max frags per cylinder group
/*
 * MAXBPG bounds the number of blocks of data per cylinder group,
 * and is limited by the fact that cylinder groups are at most one block.
 * Its size is derived from the size of blocks and the(struct cg) size,
 * by the number of remaining bits.
 */
{ #define MAXBPG(fs) \
{   (fragstoblks((fs),(NBBY *((fs)->fs_bsize -(sizeof(struct cg))))))
}
function maxbpg(fs: super_block_ptr_type): integer;
begin
    maxbpg := fragstoblks(fs,
		 NBBY *(fs^.bsize - sizeof(cylinder_group_block_type)));
end;


{
{ fragments to device blocks
{ #define fsbtodb(fs, b) ((b) <<(fs)->fs_fsbtodb)
}
function fsbtodb(fs: super_block_ptr_type; b: integer): integer;
begin
    fsbtodb := binasl(b, fs^.fsbtodb);
end;


{
{ device blocks to fragments
{ #define dbtofsb(fs, b) ((b) >>(fs)->fs_fsbtodb)
}
function dbtofsb(fs: super_block_ptr_type; b: integer): integer;
begin
    dbtofsb := binasr(b, fs^.fsbtodb);
end;


{
{ start address of entire cylinder group, in frags
{ #define cgbase(fs, c)  ((daddr_t)((fs)->fs_fpg *(c)))
}
function cgbase(fs: super_block_ptr_type; c: integer): integer;
begin
    cgbase := fs^.fpg * c;
end;


{
{ start of control area, in frags
{ #define cgstart(fs, c) \
{    (cgbase(fs, c) +(fs)->fs_cgoffset *((c) & ~((fs)->fs_cgmask)))
}
function cgstart(fs: super_block_ptr_type; c: integer): integer;
begin
    cgstart := cgbase(fs, c) + fs^.cgoffset*binand(c, bincmp(fs^.cgmask));
end;


{
{ start of superblock copy, in frags
{ #define cgsblock(fs, c)(cgstart(fs, c) +(fs)->fs_sblkno)
}
function cgsblock(fs: super_block_ptr_type; c: integer): integer;
begin
    cgsblock := cgstart(fs, c) + fs^.sblkno;
end;


{
{ start of cgroup structure, in frags
{ #define cgtod(fs, c)   (cgstart(fs, c) +(fs)->fs_cblkno)
}
function cgtod(fs: super_block_ptr_type; c: integer): integer;
begin
    cgtod := cgstart(fs, c) + fs^.cblkno;
end;


{
{ start of inode section, in frags }
{ #define cgimin(fs, c)  (cgstart(fs, c) +(fs)->fs_iblkno)
}
function cgimin(fs: super_block_ptr_type; c: integer): integer;
begin
    cgimin := cgstart(fs, c) + fs^.iblkno;
end;


{
{ start of data after inode area, in frags }
{ #define cgdmin(fs, c)  (cgstart(fs, c) +(fs)->fs_dblkno)
}
function cgdmin(fs: super_block_ptr_type; c: integer): integer;
begin
    cgdmin := cgstart(fs, c) + fs^.dblkno;
end;


{
{ frag to cylinder group
{ #define dtog(fs, d)    ((d) /(fs)->fs_fpg)
}
function dtog(fs: super_block_ptr_type; d: integer): integer;
begin
    dtog := d DIV fs^.fpg;
end;


{
{ frag offset in fs to frag offset in cg
{ #define dtogd(fs, d)   ((d) %(fs)->fs_fpg)
}
function dtogd(fs: super_block_ptr_type; d: integer): integer;
begin
    dtogd := d MOD fs^.fpg;
end;


{
{ freemap bits for big block loc
/*
 * Extract the bits for a block from a map.
 */
{ #define blkmap(fs, map, loc) \
{  (((map)[loc / NBBY] >>(loc % NBBY)) &(0xff >>(NBBY -(fs)->fs_frag)))
}
function blkmap(fs: super_block_ptr_type;
		anyvar map: freemap_type; loc: integer): integer;
begin
    blkmap := binand(binasr(map[loc div NBBY], (loc MOD NBBY)),
		     binasr(HEXFF, (NBBY - fs^.frag)));
end;


{
{ frag in cylinder group to cylinder in cylinder group
{ #define cbtocylno(fs, bno) \
{     ((bno) * NSPF(fs) /(fs)->fs_spc)
}
function cbtocylno(fs: super_block_ptr_type; bno: integer): integer;
begin
    cbtocylno := (bno * nspf(fs)) DIV fs^.spc;
end;


{
{ frag in cg to rotational position
{ #define cbtorpos(fs, bno) \
{  ((bno) * NSPF(fs) %(fs)->fs_nsect * NRPOS /(fs)->fs_nsect)
}
function cbtorpos(fs: super_block_ptr_type; bno: integer): integer;
begin
    cbtorpos := (((bno * nspf(fs)) MOD fs^.nsect) * NRPOS) DIV fs^.nsect;
end;


{
{ byte offset of loc within big block
{ #define blkoff(fs, loc)         /* calculates(loc % fs->fs_bsize) */ \
{    ((loc) & ~(fs)->fs_bmask)
}
function blkoff(fs: super_block_ptr_type; loc: integer): integer;
begin
    blkoff := binand(loc, bincmp(fs^.bmask));
end;


{
{ byte offset of loc within frag
{ #define fragoff(fs, loc)        /* calculates(loc % fs->fs_fsize) */ \
{     ((loc) & ~(fs)->fs_fmask)
}
function fragoff(fs: super_block_ptr_type; loc: integer): integer;
begin
    fragoff := binand(loc, bincmp(fs^.fmask));
end;


{
{ big block number of byte offset loc
{ #define lblkno(fs, loc)         /* calculates(loc / fs->fs_bsize) */ \
{     ((loc) >>(fs)->fs_bshift)
}
function lblkno(fs: super_block_ptr_type; loc: integer): integer;
begin
	lblkno := binasr(loc, fs^.bshift);
end;


{
{ number of frags in loc bytes(truncated)
{ #define numfrags(fs, loc)       /* calculates(loc / fs->fs_fsize) */ \
{     ((loc) >>(fs)->fs_fshift)
}
function numfrags(fs: super_block_ptr_type; loc: integer): integer;
begin
    numfrags := binasr(loc, fs^.fshift);
end;


{
{ round size bytes up to next big block
{ #define blkroundup(fs, size)   /* calculates roundup(size, fs->fs_bsize) */ \
{      (((size) +(fs)->fs_bsize - 1) &(fs)->fs_bmask)
}
function blkroundup(fs: super_block_ptr_type; size: integer): integer;
begin
    blkroundup := binand((size + fs^.bsize - 1), fs^.bmask);
end;


{
{ round size bytes up to next big block
{ #define fragroundup(fs, size)  /* calculates roundup(size, fs->fs_fsize) */ \
{    (((size) +(fs)->fs_fsize - 1) &(fs)->fs_fmask)
}
function fragroundup(fs: super_block_ptr_type; size: integer): integer;
begin
    fragroundup := binand((size + fs^.fsize - 1), fs^.fmask);
end;


{
{ free space in frags
/*
 * Determine the number of available frags given a
 * percentage to hold in reserve
 */
{ #define freespace(fs, percentreserved) \
{     (blkstofrags((fs),(fs)->fs_cstotal.cs_nbfree) + \
{     (fs)->fs_cstotal.cs_nffree -((fs)->fs_dsize *(percentreserved) / 100))
}
function freespace(fs: super_block_ptr_type;
		   percentreserved: integer): integer;
begin
    freespace := blkstofrags(fs, fs^.cstotal.nbfree)
			+ fs^.cstotal.nffree
			- ((fs^.dsize * percentreserved) DIV 100);
end;


{
{ size in frags of logical block lbn in this file
{ #define blksize(fs, ip, lbn) \
{     (((lbn) >= NDADDR ||(ip)->i_size >=((lbn) + 1) <<(fs)->fs_bshift) \
{     ?(fs)->fs_bsize \
{     : (fragroundup(fs, blkoff(fs,(ip)->i_size))))
}
function blksize(fs: super_block_ptr_type; ip: inode_ptr_type;
		 lbn: integer): integer;
begin
    if (lbn >= NDADDR)
    or (ip^.size.ls >= binasl(lbn + 1, fs^.bshift)) then
	blksize := fs^.bsize
    else
	blksize := fragroundup(fs, blkoff(fs, ip^.size.ls));
end;


{
{ inumber to inumber offset within block
{ #define itoo(fs,x)     ((x) % INOPB(fs))
}
function itoo(fs: super_block_ptr_type; x: integer): integer;
begin
    itoo := x MOD inopb(fs);
end;


{
{ inumber to cg number
{ #define itog(fs,x)     ((x) /(fs) -> fs_ipg)
}
function itog(fs: super_block_ptr_type; x: integer): integer;
begin
    itog := x DIV fs^.ipg;
end;


{
{ fragment number to byte address
}
function fragstobytes(fs: super_block_ptr_type; frags: integer): integer;
begin
    fragstobytes := binasl(frags, fs^.fshift);
end;


{
{ inumber to frag containing it
{ #define itod(fs,x)      \
{     ((daddr_t)(cgimin(fs, itog(fs, x)) + \
{     (blkstofrags((fs),(((x) %(fs) -> fs_ipg) / INOPB(fs))))))
}
function itod(fs: super_block_ptr_type; x: integer): integer;
begin
    itod := cgimin(fs, itog(fs, x))
       + blkstofrags(fs, (x MOD fs^.ipg) DIV inopb(fs));
end;


{
{ byte offset of inode
}
function inode_start(fs: super_block_ptr_type;
		     inode_num: integer): integer;
begin
    inode_start := fsbtodb(fs, itod(fs, inode_num)) * DEV_BSIZE +
		   itoo(fs, inode_num) * sizeof(inode_type);
end;


{
{ byte offset of fragment
}
function data_start(fs: super_block_ptr_type;
		    dblock_num: integer): integer;
begin
    data_start := fsbtodb(fs, dblock_num) * DEV_BSIZE;
end;


{
{ byte offset of cgroup
}
function cgroup_start(fs: super_block_ptr_type;
		      cgroup_num: integer): integer;
begin
    cgroup_start := DEV_BSIZE * fsbtodb(fs, cgtod(fs, cgroup_num));
end;


function min(a, b: integer): integer;
begin
 if a < b then min := a else min := b;
end;


function max(a, b: integer): integer;
begin
 if a > b then max := a else max := b;
end;

end.






