📄 api.c
字号:
/*
* EBS - RTFS (Real Time File Manager)
*
* Copyright EBS Inc. 1996
* All rights reserved.
* This code may not be redistributed in source or linkable object form
* without the consent of its author.
*/
/* API.C - Contains user api level source code.
The following routines are included:
po_open - Open a file.
po_read - Read bytes from a file.
po_write - Write Bytes to a file.
po_lseek - Move the file pointer.
po_close - Close a file and flush the file allocation table.
po_flush - Flush an open file
po_trunc - Truncate an open file
pc_mv - Rename a file.
pc_unlink - Delete a file.
pc_mkdir - Create a directory.
pc_rmdir - Delete a directory.
pc_deltree - Delete an entire directory tree.
pc_fat_size - Calculate blocks required for a volume's Allocation Table.
pc_free - Calculate and return the free space on a disk.
pc_gfirst - Get stats on the first file to match a pattern.
pc_gnext - Get stats on the next file to match a pattern.
pc_gdone - Free resources used by pc_gfirst/pc_gnext.
pc_set_default_drive - Set the default drive number.
pc_setdfltdrvno - Set the default drive number.
pc_getdfltdrvno - Get the default drive number.
pc_set_cwd - Set the current working directory.
pc_isdir - Determine if a path is a directory.
pc_isvol - Determine if a path is a volume
pc_pwd - Get string representation of current working dir.
pc_cluster_size - Get the cluster size of a drive
po_extend_file - Extend a file by N contiguous clusters.
pc_find_contig_clusters - Find at least MIN_CLUSTER clusters.
*/
#include <pcdisk.h>
RTFS_FILE(dskopen.c, pc_dskopen)
#ifndef __PCDISK__ /* This allows us to build the lib with subroutines split */
#include <pcdisk.h>
#endif
/******************************************************************************
PC_I_DSKOPEN - Open a disk for business.
Description
Called by lower level code in chkmedia to open the disk
THIS ROUTINE MUST BE CALLED BEFORE ANY OTHERS.
Returns
Returns TRUE if the disk was successfully initialized.
****************************************************************************/
int pc_log_base_2(word n) /*__fn__*/
{
int log;
log = 0;
if (n <= 1)
return(log);
while(n)
{
log += 1;
n >>= 1;
}
return((int)(log-1));
}
/*
* Note: This routine is called with the drive already locked so
* in several cases there is no need for critical section code handling
* This is a helper function for pc_i_dskopen()
*/
BOOLEAN pc_dskinit(int driveno) /*__fn__*/
{
DDRIVE *pdr;
struct pcblk0 bl0;
/* Check drive number */
if (!pc_validate_driveno(driveno))
{
pc_report_error(PCERR_INITDRNO);
return(FALSE);
}
if (!mem_drives_structures)
{
/* Failed: pc_meminit() must not have been called */
pc_report_error(PCERR_INITCORE);
return (FALSE);
}
pdr = pc_drno_to_drive_struct(driveno);
/* Don't do anything on reopens */
if (pdr->mount_valid)
{
return(TRUE);
}
else
{
/* Zero the structure so all of our initial values are right */
OS_CLAIM_FSCRITICAL()
{
PFBYTE p1, p2;
p1 = (PFBYTE) pdr;
p2 = (PFBYTE) &pdr->begin_user_area;
while(p1 < p2) *p1++ = 0;
}
OS_RELEASE_FSCRITICAL()
}
/* Set this to true now so check media doesn't try to mount */
pdr->mount_valid = TRUE;
if (pdr->drive_flags & DRIVE_FLAGS_PARTITIONED)
{
if (pc_read_partition_table(driveno, pdr) != READ_PARTION_OK)
{
pc_report_error(PCERR_INITDEV);
return_error:
pdr->mount_valid = FALSE;
return(FALSE);
}
}
/* Read block 0 */
if (!pc_gblk0((word) driveno, &bl0 ))
{
pc_report_error(PCERR_INITREAD);
goto return_error;
}
/* Verify that we have a good dos formatted disk */
if ( (bl0.jump != (byte) 0xE9) && (bl0.jump !=(byte) 0xEB) )
{
pc_report_error(PCERR_INITMEDI);
goto return_error;
}
/* set up the drive structur from block 0 */
pdr->bytspsector = bl0.bytspsector; /* bytes/sector */
pdr->secpalloc = bl0.secpalloc; /* sectors / cluster */
pdr->secpfat = (CLUSTERTYPE) bl0.secpfat; /* sectors / fat */
pdr->numfats = bl0.numfats; /* Number of fat copies */
pdr->numroot = bl0.numroot; /* Maximum number of root entries */
pdr->numsecs = (BLOCKT) bl0.numsecs; /* Total sectors on the disk */
pdr->mediadesc = bl0.mediadesc; /* Media descriptor byte */
pdr->secreserved = bl0.secreserved; /* sectors reserved */
pdr->secptrk = bl0.secptrk; /* sectors per track */
pdr->numhead = bl0.numhead; /* number of heads */
pdr->numhide =bl0.numhide; /* # hidden sectors */
/* Check if running on a DOS (4.0) huge partition */
/* If traditional total # sectors is zero, use value in extended BPB */
if (pdr->numsecs == 0L)
pdr->numsecs = bl0.numsecs2; /* (4.0) */
/* derive some things */
/* beginning of fat is just past reserved sectors */
#if (FAT32)
if (pdr->secpfat == 0L)
pdr->secpfat = bl0.secpfat2;
if (bl0.flags & NOFATMIRROR)
{
pdr->fatblock = (BLOCKT) bl0.secreserved +
((bl0.flags & ACTIVEFAT) * pdr->secpfat);
pdr->numfats = 1;
}
else
pdr->fatblock = (BLOCKT) bl0.secreserved;
#else
pdr->fatblock = (BLOCKT) bl0.secreserved;
#endif
/* The first block of the root is just past the fat copies */
#if (FAT32)
if (pdr->numroot==0) /* Drive must be FAT32 */
{
pdr->firstclblock = pdr->fatblock + pdr->secpfat * pdr->numfats;
/* DM: 7-6-99: BUG FIX: */
pdr->rootblock = (bl0.rootbegin-2) * pdr->secpalloc + pdr->firstclblock;
/* WRONG: pdr->rootblock = bl0.rootbegin-2 + pdr->firstclblock; */
}
else
#endif
{
pdr->rootblock = pdr->fatblock + pdr->secpfat * pdr->numfats;
pdr->secproot = (word)((pdr->numroot + INOPBLOCK - 1)/INOPBLOCK);
/* The first block of the cluster area is just past the root */
/* Round up if we have to */
pdr->firstclblock = pdr->rootblock +
(pdr->numroot + INOPBLOCK - 1)/INOPBLOCK;
}
pdr->bytespcluster = (word) (512 * pdr->secpalloc);
/* bits to mask in to calculate byte offset in cluster from file pointer.
AND file pointer with this to get byte offset in cluster a shift right
9 to get block offset in cluster */
pdr->byte_into_cl_mask = (dword) pdr->bytespcluster;
pdr->byte_into_cl_mask -= 1L;
/* save away log of sectors per alloc */
pdr->log2_secpalloc = (word)pc_log_base_2((word)pdr->secpalloc);
/* Calculate the largest index in the file allocation table.
Total # block in the cluster area)/Blockpercluster =='s total
Number of clusters. Entries 0 & 1 are reserved so the highest
valid fat index is 1 + total # clusters.
*/
pdr->maxfindex = (CLUSTERTYPE) /* FAT32 */
(1 + ((pdr->numsecs - pdr->firstclblock)/pdr->secpalloc));
#if (!FAT32)
/* if calculated size > fff0 set it to one less. fff0 to ffff are
reserved values. */
if (pdr->maxfindex >= 0xfff0)
pdr->maxfindex = 0xffef;
#endif
/* Create a hint for where we should write file data. We do this
because directories are allocated in one cluster chunks while
file may allocate larger chunks. We Try to put directory
data at the beginning of the disk in a seperate region so we
don't break the contiguous space further out */
/* guess that 1/32nd of the disk will store directory info and the
rest will be data. */
#if (FAT32)
if (pdr->maxfindex > (CLUSTERTYPE)65526ul)
{
pdr->known_free_clusters = bl0.free_alloc;
pdr->free_contig_base = bl0.next_alloc;
pdr->free_contig_pointer = pdr->free_contig_base;
pdr->infosec = bl0.infosec;
}
else
#endif
{
pdr->free_contig_base = (word) (pdr->maxfindex >> 5);
if (pdr->free_contig_base < 2)
pdr->free_contig_base = 2;
/* set the pointer to where to look for free clusters to the contiguous
area. On the first call to write this will hunt for the real free
blocks. */
pdr->free_contig_pointer = pdr->free_contig_base;
/* Keep track of how much free space is on the drive. (This will
speed up pc_free()) when calculating free space */
pdr->known_free_clusters = 0;
}
/* Initialize the fat management code */
/* Nibbles/fat entry if < 4087 clusters then 12 bit else 16 */
pdr->fasize = (word) ((pdr->maxfindex < 4087) ? 3 : 4);
#if (FAT32)
pdr->fasize = (word) ((pdr->maxfindex > (CLUSTERTYPE)65526ul) ?
8 : pdr->fasize);
#endif
if (driveno == 0)
pdr->fat_swap_structure.data_array = (PFBYTE)fat_drive_0;
#if (NDRIVES > 1) /* B: */
if (driveno == 1)
pdr->fat_swap_structure.data_array = (PFBYTE)fat_drive_1;
#endif
#if (NDRIVES > 2) /* C: */
if (driveno == 2)
pdr->fat_swap_structure.data_array = (PFBYTE)fat_drive_2;
#endif
#if (NDRIVES > 3) /* D: */
if (driveno == 3)
pdr->fat_swap_structure.data_array = (PFBYTE)fat_drive_3;
#endif
#if (NDRIVES > 4) /* E: */
if (driveno == 4)
pdr->fat_swap_structure.data_array = (PFBYTE)fat_drive_4;
#endif
#if (NDRIVES > 5) /* E: */
if (driveno == 5)
pdr->fat_swap_structure.data_array = (PFBYTE)fat_drive_5;
#endif
#if (NDRIVES > 6) /* E: */
if (driveno == 6)
pdr->fat_swap_structure.data_array = (PFBYTE)fat_drive_6;
#endif
#if (NDRIVES > 7) /* E: */
if (driveno == 7)
pdr->fat_swap_structure.data_array = (PFBYTE)fat_drive_7;
#endif
#if (NDRIVES > 8) /* E: */
if (driveno == 8)
pdr->fat_swap_structure.data_array = (PFBYTE)fat_drive_8;
#endif
#if (NDRIVES > 9) /* E: */
if (driveno == 9)
pdr->fat_swap_structure.data_array = (PFBYTE)fat_drive_9;
#endif
#if (NDRIVES > 10)
#error Please add fat_drive_10
#endif
/* Remember how many blocks we alloced */
pdr->fat_swap_structure.n_blocks_total = FAT_BUFFER_SIZE;
/* Set driveno now becuse the drive structure is valid */
pdr->driveno = (word)driveno;
/* Swap in item 0. (ie read the first page of the FAT) */
if (!pc_pfswap(pdr, (word) 0, FALSE))
{
pc_report_error(PCERR_FATREAD);
goto return_error;
}
pdr->mount_valid = TRUE;
return(TRUE);
}
RTFS_FILE(dskflush.c, pc_diskflush)
#if (RTFS_WRITE)
/****************************************************************************
PC_DISKFLUSH - Flush the FAT and all files on a disk
Description
If an application may call this functions to force all files
to be flushed and the fat to be flushed. After this call returns
the disk image is synchronized with RTFS's internal view of the
voulme.
Returns
TRUE if the disk flushed else no
*****************************************************************************/
/* Free all resources belonging to a drive without flushing anything */
BOOLEAN pc_diskflush(char *path) /*__fn__*/
{
int driveno;
DDRIVE *pdrive;
BOOLEAN ret_val;
CHECK_MEM(BOOLEAN, 0) /* Make sure memory is initted */
OS_FS_ENTER()
ret_val = FALSE;
driveno = check_drive(path);
if (driveno >= 0)
{
if (pc_parsedrive( &driveno, path ))
{
/* Find the drive */
pdrive = pc_drno2dr(driveno);
if (pdrive)
{
OS_CLAIM_LOGDRIVE(driveno) /* Grab exclusive access to the drive */
if (pc_flush_all_fil(pdrive))
if (pc_flushfat(driveno))
ret_val = TRUE;
OS_RELEASE_LOGDRIVE(driveno)
}
}
}
/* Restore the kernel state */
OS_FS_EXIT()
return(ret_val);
}
#endif
RTFS_FILE(mkdir.c, pc_mkdir)
#ifndef __PCDISK__ /* This allows us to build the lib with subroutines split */
#include <pcdisk.h>
#endif
#if (RTFS_WRITE)
#if (RTFS_SUBDIRS)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -