📄 lowl.c
字号:
/* If fat32 is not defined the nxt is always <= 0xffff. picky compilers
notice this and emit a warning */
if (nxt >= (CLUSTERTYPE)0xfff7)
#endif
nxt = 0; /* end of chain */
}
return(nxt);
}
RTFS_FILE(clreleas.c, pc_clrelease)
#ifndef __PCDISK__ /* This allows us to build the lib with subroutines split */
#include <pcdisk.h>
#endif
#if (RTFS_WRITE)
/****************************************************************************
PC_CLRELEASE - Return a cluster to the pool of free space on a disk
Description
Given a DDRIVE and a cluster, mark the cluster in the file allocation
table as free. It will be used again by calls to pc_clalloc().
Returns
Nothing
***************************************************************************/
/* Return a cluster to the free list */
/* Note: The caller locks the fat before calling this routine */
void pc_clrelease(DDRIVE *pdr, CLUSTERTYPE clno) /*__fn__*/
{
if (clno < 2)
return;
/* Don't catch any lower level errors here. You'll catch them soon enough */
#if (FAT32)
if (pc_pfaxx(pdr, clno, 0x00000000)) /* Mark it as free */
#else
if (pc_pfaxx(pdr, clno, 0x0000)) /* Mark it as free */
#endif
{
/* If freeing in the "contiguous" region reset the "hint" if we
free space earlier than it. */
if (clno >= pdr->free_contig_base && clno <= pdr->free_contig_pointer)
pdr->free_contig_pointer = clno;
if (pdr->known_free_clusters)
#if (FAT32)
pdr->known_free_clusters = (long) (pdr->known_free_clusters + (long)1);
#else
pdr->known_free_clusters = (word) (pdr->known_free_clusters + (word)1);
#endif
}
}
#endif
RTFS_FILE(faxx.c, pc_faxx)
#ifndef __PCDISK__ /* This allows us to build the lib with subroutines split */
#include <pcdisk.h>
#endif
/***************************************************************************
PC_FAXX - Get the value store in the FAT at clno.
Description
Given a DDRIVE and a cluster number. Get the value in the fat at clusterno
(the next cluster in a chain.) Handle 16 and 12 bit fats correctly.
Returns
Returns the the value at clno. In pvalue.
If any error occured while FAT swapping return FALSE else return TRUE.
***************************************************************************/
/* Retrieve a value from the fat */
BOOLEAN pc_faxx(DDRIVE *pdr, CLUSTERTYPE clno, CLUSTERTYPE *pvalue) /*__fn__*/
{
CLUSTERTYPE nibble,index, offset, result;
byte c;
union align1 {
byte wrdbuf[4]; /* Temp storage area */
word fill[2];
} u;
union align2 {
byte wrdbuf2[4]; /* Temp storage area */
word fill[2];
} u2;
result = 0;
if (pdr->fasize == 3) /* 3 nibble ? */
{
nibble = (word)(clno * 3);
index = (word)(nibble >> 2);
offset = (word)(clno & 0x03);
/* Read the first word */
if (!pc_fword( pdr, index, (word *) &u.wrdbuf[0], FALSE ))
return(FALSE);
/*
| W0 | W1 | W2 |
A1 A0 B0 A2 B2 B1 C1 C0 D0 C2 D2 D1
xx xx xx
*/
if (offset == 0) /* (A2 << 8) | A1 A2 */
{
/* BYTE 0 =='s Low byte, byte 1 low nibble =='s high byte */
u.wrdbuf[1] &= 0x0f;
result = u.wrdbuf[1];
result <<= 8;
result |= u.wrdbuf[0];
}
/*
| W0 | W1 | W2 |
A1 A0 B0 A2 B2 B1 C1 C0 D0 C2 D2 D1
xx xx xx
*/
else if (offset == 1) /* (B1 B2 << 4) | B0 */
{
/* BYTE 2 == High byte Byte 1 high nibb == low nib */
if (!pc_fword( pdr, (word)(index+1), (word *) &u2.wrdbuf2[0], FALSE ))
return(FALSE);
c = (byte) (u.wrdbuf[1] >> 4);
result = u2.wrdbuf2[0];
result <<= 4;
result |= c;
}
/*
| W0 | W1 | W2 |
A1 A0 B0 A2 B2 B1 C1 C0 D0 C2 D2 D1
xx xx xx
*/
else if (offset == 2) /*(C2 << 8) | C1 C2 */
{
if (!pc_fword( pdr, (word)(index+1), (word *) &u2.wrdbuf2[0], FALSE ))
return(FALSE);
/* BYTE 1 =='s Low byte, byte 2 low nibble =='s high byte */
result = (word) (u2.wrdbuf2[0] & 0x0f);
result <<= 8;
result |= u.wrdbuf[1];
}
/*
| W0 | W1 | W2 |
A1 A0 B0 A2 B2 B1 C1 C0 D0 C2 D2 D1
xx xx xx
*/
else if (offset == 3) /* (D2 D1) << 4 | D0 */
{
result = u.wrdbuf[1];
result <<= 4;
c = u.wrdbuf[0];
c >>= 4;
result |= c;
}
}
else if (pdr->fasize == 8) /* 32 BIT fat. ret the value at 4 * clno */
{
#if (FAT32)
#if KS_LITTLE_ENDIAN
if (!pc_pfgdword( pdr, clno, (dword *) &result ))
return (FALSE);
#else
if ( pc_pfgdword( pdr, clno, (dword *) &u.wrdbuf[0] ))
result = (CLUSTERTYPE) to_DWORD(&u.wrdbuf[0]);
else
return (FALSE);
#endif
#else
return (FALSE); /* no FAT32 */
#endif /* FAT32 */
}
else /* 16 BIT fat. ret the value at 2 * clno */
{
if ( pc_fword( pdr, clno, (word *) &u.wrdbuf[0], FALSE ))
result = (CLUSTERTYPE) to_WORD(&u.wrdbuf[0]); /*X*/ /* And use the product as index */
else
return (FALSE);
}
*pvalue = result;
return (TRUE);
}
RTFS_FILE(flushfat.c, pc_flushfat)
#ifndef __PCDISK__ /* This allows us to build the lib with subroutines split */
#include <pcdisk.h>
#endif
#if (RTFS_WRITE)
/****************************************************************************
PC_FLUSHFAT - Write any dirty FAT blocks to disk
Description
Given a valid drive number. Write any fat blocks to disk that
have been modified. Updates all copies of the fat.
Returns
Returns FALSE if driveno is not an open drive. Or a write failed.
****************************************************************************/
#if (FAT32)
/* Update a fat32 voulme's info sector */
BOOLEAN pc_flushinfo(DDRIVE *pdr) /*__fn__*/
{
byte KS_FAR *pf;
int j; /*FAT32*/
BLKBUFF *buf;
if (pdr->fasize == 8)
{
buf = pc_scratch_blk();
if (!buf)
{
pc_report_error(PCERR_FAT_FLUSH);
return(FALSE);
}
else
{
pf = buf->data; /* Now we don't have to use the stack */
/* READ IT */
if(!devio_read(pdr->driveno,(BLOCKT)(pdr->infosec) ,pf , 1, FALSE))
goto info_error;
/* Merge in the new values */
#if KS_LITTLE_ENDIAN
for (j=0; *((dword*)pf)!=FSINFOSIG && j<512; pf++,j++);
((struct fat32_info *)pf)->free_alloc = pdr->known_free_clusters;
((struct fat32_info *)pf)->next_alloc = pdr->free_contig_pointer;
#else
for (j=0; to_DWORD(pf)!=FSINFOSIG && j<512; pf++,j++);
fr_DWORD((byte *) (&((struct fat32_info *)pf)->free_alloc), pdr->known_free_clusters );
fr_DWORD((byte *) (&((struct fat32_info *)pf)->next_alloc), pdr->free_contig_pointer );
#endif
pf = buf->data; /* Now we don't have to use the stack */
/* WRITE IT */
if(!devio_write(pdr->driveno,(BLOCKT)(pdr->infosec) ,pf , 1, FALSE))
{
info_error:
pc_free_buf(buf, TRUE);
pc_report_error(PCERR_FAT_FLUSH);
return(FALSE);
}
pc_free_buf(buf, TRUE);
}
}
return (TRUE);
}
#endif /* FAT32 */
/* Consult the dirty fat block list and write any. write all copies
of the fat */
/* Note: The caller locks the fat before calling this routine */
BOOLEAN pc_flushfat(int driveno) /*__fn__*/
{
DDRIVE *pdr;
pdr = pc_drno2dr(driveno);
if (!pdr)
{
return(FALSE);
}
if (!pdr->fat_is_dirty)
return(TRUE);
#if (FAT32)
/* write the alloc hints into the info block */
if (!pc_flushinfo(pdr))
return(FALSE);
#endif
if (pc_pfflush(pdr))
{
pdr->fat_is_dirty = FALSE;
return(TRUE);
}
else
return(FALSE);
}
#endif
RTFS_FILE(freech.c, pc_freechain)
#ifndef __PCDISK__ /* This allows us to build the lib with subroutines split */
#include <pcdisk.h>
#endif
#if (RTFS_WRITE)
/****************************************************************************
PC_FREECHAIN - Free a cluster chain associated with an inode.
Description
Trace the cluster chain starting at cluster and return all the clusters to
the free state for re-use. The FAT is not flushed.
Returns
Nothing.
****************************************************************************/
/* Note: The caller locks the fat before calling this routine */
void pc_freechain(DDRIVE *pdr, CLUSTERTYPE cluster) /*__fn__*/
{
CLUSTERTYPE nextcluster;
nextcluster = pc_clnext(pdr , cluster);
while (cluster)
{
pc_clrelease(pdr , cluster);
cluster = nextcluster;
nextcluster = pc_clnext(pdr , nextcluster);
}
}
#endif
RTFS_FILE(cltrunc.c, pc_cl_truncate)
#ifndef __PCDISK__ /* This allows us to build the lib with subroutines split */
#include <pcdisk.h>
#endif
#if (RTFS_WRITE)
#if (RTFS_SUBDIRS)
/****************************************************************************
PC_CL_TRUNCATE - Truncate a cluster chain.
Description
Trace the cluster chain starting at cluster until l_cluster is reached.
Then terminate the chain and free from l_cluster on.
The FAT is not flushed.
If cluster == l_cluster does nothing. This condition should be handled
higher up by updating dirents appropriately and then calling pc_freechain.
Returns
The last cluster in the chain after truncation.
****************************************************************************/
/* Note: The caller locks the fat before calling this routine */
CLUSTERTYPE pc_cl_truncate(DDRIVE *pdr, CLUSTERTYPE cluster, CLUSTERTYPE l_cluster)/*__fn__*/
{
CLUSTERTYPE nextcluster;
nextcluster = pc_clnext(pdr , cluster);
while (nextcluster)
{
if (nextcluster == l_cluster)
{
if (!pc_pfaxxterm(pdr, cluster)) /* Terminate the chain */ /* FAT32 */
break; /* Error break to ret 0 */
pc_freechain(pdr, l_cluster);
return(cluster);
}
else
{
cluster = nextcluster;
nextcluster = pc_clnext(pdr , nextcluster);
}
}
return(0);
}
#endif
#endif
RTFS_FILE(getchain.c, pc_get_chain)
#ifndef __PCDISK__ /* This allows us to build the lib with subroutines split */
#include <pcdisk.h>
#endif
/******************************************************************************
PC_GET_CHAIN - Return as many contiguous clusters as possible.
Description
Starting at start_cluster return the number of contiguous clusters
allocated in the chain containing start_cluster or n_clusters,
whichever is less.
Returns
Returns the number of contiguous clusters found. Or zero on an error.
This function should always return at least one. (start_cluster). Unless
an error occurs.
The word at *pnext_cluster is filled with on of the following:
. If we went beyond a contiguous section it contains
the first cluster in the next segment of the chain.
. If we are still in a section it contains
the next cluster in the current segment of the chain.
. If we are at the end of the chain it contains the last cluster
in the chain.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -