📄 lowl.c
字号:
return (NO);
}
else
pc_free_buf(pbuff,NO);
}
return (YES);
}
/****************************************************************************
PC_DRNO2DR - Convert a drive number to a pointer to DDRIVE
Description
Given a drive number look up the DDRIVE structure associated with it.
Returns
Returns NULL if driveno is not an open drive.
****************************************************************************/
DDRIVE *pc_drno2dr(COUNT driveno) /*__fn__*/
{
DDRIVE *pdr;
/* Check drive number */
if ((driveno >= 0) && (driveno < NDRIVES))
{
pdr = mem_drives_structures+driveno;
if (pdr->opencount)
return(pdr);
}
return(NULL);
}
/***************************************************************************
PC_DSKFREE - Deallocate all core associated with a disk structure
Description
Given a valid drive number. If the drive open count goes to zero, free the
file allocation table and the block zero information associated with the
drive. If unconditional is true, ignore the open count and release the
drive.
If open count reaches zero or unconditional, all future accesses to
driveno will fail until re-opened.
Returns
Returns NO if driveno is not an open drive.
****************************************************************************/
/* free up all core associated with the drive
called by close. A drive restart would consist of
pc_dskfree(driveno, YES), pc_dskopen() */
BOOL pc_dskfree(COUNT driveno, BOOL unconditional) /*__fn__*/
{
DDRIVE *pdr;
/* DROBJ *pcwd; */
pdr = pc_drno2dr(driveno);
if (!pdr)
{
return(NO);
}
/* If unconditional close. Fake it out by setting open count to 1 */
if (unconditional)
pdr->opencount = 1;
if (pdr->opencount == 1)
{
/* Free the current working directory for this drive for all users */
pc_free_all_users(driveno);
/* Free all files, finodes & blocks associated with the drive */
pc_free_all_fil(pdr);
pc_free_all_i(pdr);
pc_free_all_blk(pdr);
/* Free fat blocks */
pc_memory_fat_blocks_free(driveno, pdr->fat_swap_structure.data_array, pdr->fat_swap_structure.n_blocks_total);
/* Tell the device driver we are done. */
pc_bdevsw[driveno].close_proc(driveno);
}
pdr->opencount -= 1;
return (YES);
}
/***************************************************************************
PC_IFREE - Count the number of free bytes remaining on a disk (internal)
Description
Given a drive number count the number of free bytes on the drive. (called
by pc_free).
Returns
The number of free bytes or zero if the drive is full or
it it not open or out of range.
NOTE: To speed up this operation we maintain a variable in the
drive structure. known_free_clusters. If this variable is
non zero a multiple of this value will be returned. To force
the free count to be recalculated just set field to zero
before calling this function.
****************************************************************************/
LONG pc_ifree(COUNT driveno) /*__fn__*/
{
DDRIVE *pdr;
UCOUNT i;
UCOUNT nxt;
UCOUNT freecount = 0;
LONG nbad = 0L;
LONG nres = 0L;
LONG ltemp;
pdr = pc_drno2dr(driveno);
if (!pdr)
{
return(0L);
}
if (pdr->known_free_clusters)
freecount = pdr->known_free_clusters;
else
{
for (i = 2 ; i <= pdr->maxfindex; i++)
{
if (!pc_faxx(pdr, i, &nxt))
{
return(0L);
}
if (nxt == 0)
freecount++;
if ( (pdr->fasize == 3 && nxt == 0xff7) ||
(pdr->fasize == 4 && nxt == 0xfff7) )
{
nbad += 1;
}
if (pdr->fasize == 4 && (nxt >= 0xfff0 && nxt <= 0xfff6))
nres += 1;
else if (pdr->fasize == 3 && (nxt >= 0xff0 && nxt <= 0xff6))
nres += 1;
}
pdr->known_free_clusters = freecount;
}
ltemp = (LONG) freecount;
ltemp *= pdr->bytespcluster;
return (ltemp);
}
/****************************************************************************
PC_SEC2CLUSTER - Convert a block number to its cluster representation.
Description
Convert blockno to its cluster representation if it is in cluster space.
Returns
Returns 0 if the block is not in cluster space, else returns the
cluster number associated with block.
****************************************************************************/
/* Cluster<->sector conversion routines */
/* Convert sector to cluster. 0 == s error */
UCOUNT pc_sec2cluster(DDRIVE *pdrive, BLOCKT blockno) /*__fn__*/
{
BLOCKT answer;
if (blockno >= pdrive->numsecs)
return (0);
else if ( pdrive->firstclblock > blockno)
return (0);
else
{
/* (2 + (blockno - pdrive->firstclblock)/pdrive->secpalloc) */
answer = blockno - pdrive->firstclblock;
answer = answer >> pdrive->log2_secpalloc;
answer += 2;
return ((UCOUNT) answer);
}
}
/****************************************************************************
PC_SEC2INDEX - Calculate the offset into a cluster for a block.
Description
Given a block number offset from the beginning of the drive, calculate
which block number within a cluster it will be. If the block number
coincides with a cluster boundary, the return value will be zero. If it
coincides with a cluster boundary + 1 block, the value will be 1, etc.
Returns
0,1,2 upto blockspcluster -1.
***************************************************************************/
/* Convert sector to index into a cluster . No error detection */
UCOUNT pc_sec2index(DDRIVE *pdrive, BLOCKT blockno) /*__fn__*/
{
BLOCKT answer;
/* ((blockno - pdrive->firstclblock) % pdrive->secpalloc) ); */
answer = blockno - pdrive->firstclblock;
answer = answer % pdrive->secpalloc;
return ( (UCOUNT) answer);
}
/***************************************************************************
PC_CL2SECTOR - Convert a cluster number to block number representation.
Description
Convert cluster number to a blocknumber.
Returns
Returns 0 if the cluster is out of range. else returns the
block number of the beginning of the cluster.
****************************************************************************/
/* Convert cluster. to sector */
BLOCKT pc_cl2sector(DDRIVE *pdrive, UCOUNT cluster) /*__fn__*/
{
BLOCKT blockno;
ULONG t;
if (cluster < 2)
return (BLOCKEQ0);
else
{
t = cluster - 2;
t = t << pdrive->log2_secpalloc;
blockno = pdrive->firstclblock + t;
}
if (blockno >= pdrive->numsecs)
return (BLOCKEQ0);
else
return (blockno);
}
/******************************************************************************
EXT_PARTITION_INIT - Partition table interpretor
Description
Given a physical drive number and the addresses of two tables,
partition start and partition end, this routine interprets the
partion tables on the physical drive and fills in the start and end
blocks of each partition. Extended partitions are supported. If there
are more than max partitions, only max will be returned.
Note: the physical drive must be in a raw state so no partition mapping
takes place.
Returns
The number of partitions found on the drive.
****************************************************************************/
COUNT ext_partition_init(COUNT driveno, ULONG *pstart, ULONG *pend, COUNT max) /*__fn__*/
{
COUNT nparts;
PTABLE *ppart;
char workbuf[256];
char buf[512];
char *pbuf;
ULONG ltemp;
ULONG ltemp2;
UCOUNT stemp;
UCOUNT i;
ULONG partition_address;
nparts = 0;
partition_address = 0L;
while(YES)
{
if (nparts == max)
goto done;
/* Read block zero */
if (!pc_bdevsw[driveno].io_proc(driveno, partition_address , buf , 1 , YES))
goto done;
/* Copy the table to a word alligned buffer so some compilers don't screw up */
pbuf = &buf[0];
pbuf += 0x1be; /* The info starts at buf[1be] */
copybuff(workbuf, pbuf, sizeof(PTABLE));
ppart = (PTABLE *) workbuf;
stemp = ppart->signature;
if (to_WORD((UTINY *) &stemp) != 0xAA55)
goto done;
/* Read through the partition table. Find the primary DOS partition */
for (i = 0; i < 4; i++)
{
if ( (ppart->ents[i].p_typ == 0x01) ||
(ppart->ents[i].p_typ == 0x04) ||
(ppart->ents[i].p_typ == 0x06) )
{
/* Get the relative start and size */
ltemp = ppart->ents[i].r_sec;
ltemp2 = to_DWORD ((UTINY *) <emp);
ltemp2 += partition_address;
*(pstart+nparts) = ltemp2;
ltemp = (ppart->ents[i].r_sec + ppart->ents[i].p_size) - 1L;
ltemp2 = to_DWORD ((UTINY *) <emp);
ltemp2 += partition_address;
*(pend+nparts) = ltemp2;
nparts++;
break;
}
}
/* Now see if we have an extended partion */
for (i = 0; i < 4; i++)
{
if ( (ppart->ents[i].p_typ == 0x05) )
{
/* Get the address of the extended partition. */
ltemp = ppart->ents[i].r_sec;
ltemp2 = to_DWORD ((UTINY *) <emp);
ltemp2 += partition_address;
partition_address = ltemp2;
break;
}
}
if (i == 4) /* No extended partitions, bail */
break;
}
done:
return(nparts);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -