📄 lowl.c
字号:
/************************************************************************
*
* Copyright (c) 2001 by Accelerated Technology, Inc.
*
* PROPRIETARY RIGHTS of Accelerated Technology are involved in
* the subject matter of this material. All manufacturing,
* reproduction, use, and sales rights pertaining to this subject
* matter are governed by the license agreement. The recipient of
* this software implicitly accepts the terms of the license.
*
*
*************************************************************************
*************************************************************************
* FILE NAME VERSION
*
* LOWL.C FILE 2.3
*
* COMPONENT
*
* Nucleus File
*
* DESCRIPTION
*
* Low level File allocation table management functions.
*
* DATA STRUCTURES
*
* None.
*
* FUNCTIONS
*
* pc_alloc_chain Allocate a chain from the
* FAT.
* pc_find_free_cluster Find the first free cluster
* in a given range.
* pc_clalloc Allocate a single cluster
* in the fragmented region.
* pc_clgrow Grow a directory chain in
* the fragmented region.
* pc_clnext Get the next cluster in a
* chain.
* pc_clrelease Return a cluster to the free
* list.
* pc_faxx Get a value from the FAT.
* pc_flushfat Make sure the FAT is up to
* date on disk.
* pc_freechain Release a chain to the free
* list.
* pc_get_chain Return contiguous clusters
* in a chain.
* pc_pfaxx Put a value to the FAT.
* pc_pfswap Swap a block of the FAT into
* the cache.
* pc_pfpword Get a value from the swap
* cache.
* pc_pfgword Put a value to the swap
* cache.
* pc_pfflush Flush the swap cache to disk.
* pc_clzero Write zeroes to a cluster on
* disk.
* pc_drno2dr Convert a drive number to a
* drive structure.
* pc_dskfree Free resources associated
* with a drive.
* pc_ifree Calculate free space from
* the FAT.
* pc_sec2cluster Convert a sector number to
* a cluster value.
* pc_sec2index Given a block number offset
* from the beginning of the
* drive.
* pc_cl2sector Convert cluster number to a
* blocknumber.
*
* DEPENDENCIES
*
* pcdisk.h File common definitions
*
*************************************************************************/
#include "file\pcdisk.h"
extern _PC_BDEVSW pc_bdevsw[];
extern UNSIGNED *NUF_Drive_Pointers[];
extern INT NUF_Drive_Fat_Size[];
/************************************************************************
* FUNCTION
*
* pc_alloc_chain
*
* DESCRIPTION
*
* Reserve up to n_clusters contiguous clusters from the FAT and
* set the number of contiguous clusters reserved.
* If pstart_cluster points to a valid cluster link the new chain
* to it.
*
* AUTHOR
*
* Kyoichiro Toda
*
* INPUTS
*
* *n_contig Contiguous clusters pointer
* *pdr Drive object
* *pstart_cluster Search start cluster
* n_clusters Process clusters
*
* OUTPUTS
*
* NU_SUCCESS If service is successful.
* NUF_NOSPC No free cluster.
* NUF_IO_ERROR Driver IO error.
* NUF_INTERNAL Nucleus FILE internal error.
*************************************************************************/
STATUS pc_alloc_chain(UINT32 *n_contig, DDRIVE *pdr,
UINT32 *pstart_cluster, UINT32 n_clusters)
{
STATUS ret_stat;
UINT32 start_cluster;
UINT32 first_new_cluster;
UINT32 clno;
UINT32 value;
start_cluster = *pstart_cluster;
if (start_cluster)
{
if (start_cluster < 2L)
{
#ifdef DEBUG
DEBUG_PRINT("Invalid cluster number specified %d %s \r\n"
, __LINE__, __FILE__);
#endif
return(NUF_INTERNAL);
}
if (start_cluster > pdr->maxfindex)
{
#ifdef DEBUG
DEBUG_PRINT("Invalid cluster number specified %d %s \r\n"
, __LINE__, __FILE__);
#endif
return(NUF_INTERNAL);
}
}
/* If the user provided a cluster we find the next cluster beyond that
one. Otherwise we look at the disk structure and find the next
free cluster in the free cluster region after the current best guess
of the region. If that fails we look to the beginning of the region
and if that fails we look in the non-contiguous region. */
ret_stat = pc_find_free_cluster(&clno, pdr, pdr->free_contig_pointer, pdr->maxfindex);
/* Check the beginning of the disk where we typically write fragments */
if (ret_stat == NUF_NOSPC)
ret_stat = pc_find_free_cluster(&clno, pdr, 2L, pdr->free_contig_pointer);
if (ret_stat != NU_SUCCESS)
return(ret_stat);
first_new_cluster = clno;
value = 0;
*n_contig = 1;
/* look up the FAT. If the next cluster is free we link to it
and up the contig count. */
while ( (*n_contig < n_clusters) && (clno < pdr->maxfindex) )
{
ret_stat = pc_faxx(pdr, clno+1, &value);
if (ret_stat != NU_SUCCESS)
return(ret_stat);
/* If the next cluster is in-use we're done. */
if (value)
break;
/* Link the current cluster to the next one */
ret_stat = pc_pfaxx(pdr, clno, clno+1);
if (ret_stat != NU_SUCCESS)
return(ret_stat);
*n_contig += 1; /* Yep.. we got another */
clno += 1; /* Up the FAT table */
}
/* Terminate the list we just made */
ret_stat = pc_pfaxx(pdr, clno, ((UINT32) -1));
if (ret_stat != NU_SUCCESS)
return(ret_stat);
/* Update the hint of most likeley place to find a free cluster */
if (clno < pdr->maxfindex)
{
if (pdr->fasize <= 4)
{
if (clno >= pdr->free_contig_pointer)
{
pdr->free_contig_pointer = clno + 1;
}
}
else
pdr->free_contig_pointer = clno;
}
/* If we were handed a starting cluster we have to stitch our new
chain after it. */
if (start_cluster)
{
ret_stat = pc_pfaxx(pdr, start_cluster, first_new_cluster);
if (ret_stat != NU_SUCCESS)
return(ret_stat);
}
*pstart_cluster = first_new_cluster;
if (pdr->free_clusters_count)
pdr->free_clusters_count -= *n_contig;
return(NU_SUCCESS);
}
/************************************************************************
* FUNCTION
*
* pc_find_free_cluster
*
* DESCRIPTION
*
* Find the first free cluster in a range.
*
* AUTHOR
*
* Kyoichiro Toda
*
* INPUTS
*
* *freecl Free cluster number.
* *pdr Drive information
* startpt Search start cluster
* endpt Search end cluster
*
* OUTPUTS
*
* NU_SUCCESS If service is successful.
* NUF_NOSPC No free cluster.
* NUF_IO_ERROR Driver IO error.
* NUF_INTERNAL Nucleus FILE internal error.
*
*************************************************************************/
STATUS pc_find_free_cluster(UINT32 *freecl, DDRIVE *pdr, UINT32 startpt,
UINT32 endpt)
{
UINT32 i;
UINT32 value;
STATUS ret_stat;
for (i = startpt; i < endpt; i++)
{
ret_stat = pc_faxx(pdr, i, &value);
if (ret_stat != NU_SUCCESS)
return(ret_stat);
if (value == 0)
{
*freecl = i;
return(NU_SUCCESS);
}
}
return(NUF_NOSPC);
}
/************************************************************************
* FUNCTION
*
* pc_clalloc
*
* DESCRIPTION
*
* Given a DDRIVE, mark the next available cluster in the file
* allocation table as used and return the associated cluster
* number.Clhint provides a means of selecting clusters that are
* near eachother. This should reduce fragmentation.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -