📄 nu_file.c
字号:
/*
* EBS - RTFS (Real Time File Manager)
* Accelerated Technology, Inc. - Nucleus FILE Extensions, Copyright 1993
*
* Copyright Peter Van Oudenaren , 1993
* 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:
NU_Open_Disk - Open a disk for business.
NU_Close_Disk - Flush all buffers for a disk and free all core.
NU_Disk_Abort - Abort all operations on a disk.
NU_Open - Open a file.
NU_Read - Read bytes from a file.
NU_Write - Write Bytes to a file.
NU_Seek - Move the file pointer.
NU_Close - Close a file and flush the file allocation table.
NU_Flush - Flush an open file
NU_Truncate - Truncate an open file
NU_Rename - Rename a file.
NU_Delete - Delete a file.
NU_Make_Dir - Create a directory.
NU_Remove_Dir - Delete a directory.
pc_fat_size - Calculate blocks required for a volume's
Allocation Table.
NU_Format - Create a file system. Supports huge file systems.
NU_FreeSpace - Calculate and return the free space on a disk.
NU_Get_First - Get stats on the first file to match a pattern.
NU_Get_Next - Get stats on the next file to match a pattern.
NU_Done - Free resources used by NU_Get_First/NU_Get_Next.
pc_set_default_drive - Set the default drive number.
NU_Set_Default_Drive - Set the default drive number.
NU_Get_Default_Drive - Get the default drive number.
NU_Set_Current_Dir - Set the current working directory.
NU_Is_Dir - Determine if a path is a directory.
pc_isvol - Determine if a path is a volume
NU_Current_Dir - Get string representation of current working dir.
-------
S. Murrill 10-21-96 Changed return type of NU_Read and
NU_Write to COUNT (SPR199)
S. Murrill 11/14/96 Changed _po_lseek() so that a seek to end of
file works correctly when the file ends at the
end of a cluster (SPR216)
BobB 2/17/99 Modified to add a test for a NULL return by
NU_Get_First in NU_Done (CSR2170)
BobB 2/18/99 Changed name of po_truncate to NU_Truncate
BobB 2/19/99 Fixed cd.. problem (SPR183)
BobB 2/19/99 Changed name of NU_Free to NU_FreeSpace (SPR420)
*/
#include "pcdisk.h"
IMPORT PFILE_SYSTEM_USER fs_user;
LOCAL BOOL pc_l_pwd(TEXT *, DROBJ *);
LOCAL BOOL pc_gm_name(TEXT *path, DROBJ *pmom, DROBJ *pdotdot);
IMPORT _PC_BDEVSW pc_bdevsw[];
/******************************************************************************
PC_DSKOPEN - Open a disk for business.
Description
Given a path spec containing a valid drive specifier open the disk by
reading all of the block zero information and converting it to native
byte order, and then reading the file allocation table
THIS ROUTINE MUST BE CALLED BEFORE ANY OTHERS.
Returns
Returns YES if the disk was successfully initialized.
****************************************************************************/
/* Make sure the drive in a path specifier is initialized */
BOOL NU_Open_Disk(TEXT *path) /*__fn__*/
{
COUNT driveno;
BOOL ret_val;
PC_FS_ENTER() /* Must be last line in declarations */
CHECK_USER(BOOL, 0) /* Check if a valid user if multitasking */
ret_val = NO;
if (pc_parsedrive( &driveno, path ))
{
PC_DRIVE_ENTER(driveno, YES) /* Grab exclusive access to the drive */
ret_val = pc_dskinit(driveno);
PC_DRIVE_EXIT(driveno)
}
/* Restore the kernel state */
PC_FS_EXIT()
return(ret_val);
}
/****************************************************************************
PC_DSKCLOSE - Flush all buffers for a disk and free all core.
Description
Given a path name containing a valid drive specifier. Flush the
file allocation table and purge any buffers or objects associated
with the drive.
Returns
Returns YES if all went well.
*****************************************************************************/
/* Flush a disk's fat and free up all core associated with the drive */
BOOL NU_Close_Disk(TEXT *path) /*__fn__*/
{
COUNT driveno;
BOOL ret_val;
PC_FS_ENTER() /* Must be last line in declarations */
CHECK_USER(BOOL, 0) /* Check if a valid user if multitasking */
ret_val = NO;
if (pc_parsedrive( &driveno, path ))
{
PC_DRIVE_ENTER(driveno, YES) /* Grab exclusive access to the drive */
ret_val = pc_idskclose(driveno);
PC_DRIVE_EXIT(driveno)
}
/* Restore the kernel state */
PC_FS_EXIT()
return(ret_val);
}
/****************************************************************************
PC_DISKABORT - Abort all operations on a disk
Description
If an application senses that there are problems with a disk, it
should call NU_Disk_Abort("D:"). This will cause all resources
associated with that drive to be freed, but no disk writes will
be attempted. All file descriptors associated with the drive
become invalid. After correcting the problem call pc_diskopen("D:")
to re-mount the disk and re-open your files.
Returns
Nothing
*****************************************************************************/
/* Free all resources belonging to a drive without flushing anything */
VOID NU_Disk_Abort(TEXT *path) /*__fn__*/
{
COUNT driveno;
PC_FS_ENTER() /* Must be last line in declarations */
VOID_CHECK_USER() /* Check if a valid user if multitasking */
if (pc_parsedrive( &driveno, path ))
{
PC_DRIVE_ENTER(driveno, YES) /* Grab exclusive access to the drive */
/* Release the drive unconditionally */
pc_dskfree(driveno,YES);
PC_DRIVE_EXIT(driveno)
}
/* Restore the kernel state */
PC_FS_EXIT()
return;
}
/***************************************************************************
PC_MKDIR - Create a directory.
Description
Create a sudirectory in the path specified by name. Fails if a
file or directory of the same name already exists or if the path
is not found.
Returns
Returns YES if it was able to create the directory, otherwise
it returns NO.
If NU_Make_Dir fails, fs_user->p_errno will be set to one of the following:
PENOENT - path to new directory not found
PEEXIST - File or Dir already exists by this name.
PENOSPC - Drectory create failed
****************************************************************************/
BOOL NU_Make_Dir(TEXT *name) /*__fn__*/
{
DROBJ *pobj;
DROBJ *parent_obj;
TEXT path[EMAXPATH];
TEXT filename[9];
TEXT fileext[4];
BOOL ret_val;
COUNT driveno;
BOOL parent_is_locked;
PC_FS_ENTER() /* Must be last line in declarations */
CHECK_USER(BOOL, 0) /* Check if a valid user if multitasking */
ret_val = NO;
parent_obj = NULL;
pobj = NULL;
parent_is_locked = NO;
fs_user->p_errno = 0;
if (!pc_parsedrive( &driveno, name))
{
fs_user->p_errno = PENOENT;
ret_val = NO;
goto return_error;
}
PC_DRIVE_ENTER(driveno, NO) /* Register drive in use */
/* Get out the filename and d:parent */
if (!pc_parsepath(path,filename,fileext,name))
{
fs_user->p_errno = PENOENT;
goto errex;
}
/* Find the parent and make sure it is a directory \ */
parent_obj = pc_fndnode(path);
if (!parent_obj || !pc_isadir(parent_obj) || pc_isavol(parent_obj))
{
fs_user->p_errno = PENOENT;
goto errex;
}
/* Lock the parent */
PC_INODE_ENTER(parent_obj->finode, YES)
parent_is_locked = YES;
/* Fail if the directory exists */
pobj = pc_get_inode(NULL, parent_obj, (UTEXT*)filename,(UTEXT*) fileext);
if (pobj)
{
fs_user->p_errno = PEEXIST; /* Exclusive fail */
goto errex;
}
else
{
pobj = pc_mknode( parent_obj, filename, fileext, ADIRENT);
if (pobj)
{
ret_val = YES;
}
else
{
fs_user->p_errno = PENOSPC;
goto errex;
}
}
errex:
if (pobj)
pc_freeobj(pobj);
if (parent_obj)
{
if (parent_is_locked)
PC_INODE_EXIT(parent_obj->finode)
pc_freeobj(parent_obj);
}
PC_DRIVE_EXIT(driveno)
return_error: /* Doesn't have to be an error to get here */
/* Restore the kernel state */
PC_FS_EXIT()
return(ret_val);
}
/* Synchronize file pointers. Read write Seek and close all call here.
This fixes the following BUGS:
1. If a file is created and left open and then opened again with a new
file handle before any writing takes place. Neither file will get
its fptr_cluster set correctly initially. The first one to write
would get set up correctly but the other wouldn't. Thus if fptr_cluster
is zero we see if we can set it.
2. If one file seeked to the end of the file or has written to the end of
the file its file pointer will point beyond the last cluster in the
chain, the next call to write will notice the fptr is beyond the
file size and extend the file by allocating a new cluster to the
chain. During this time the cluster/block and byte offsets are
out of synch. If another instance extends the file during this time
the next call to write will miss this condition since fptr is not
>= fsize any more. To fix this we note in the file when this
condition is true AND, afterwards each time we work with the file
we see if the file has grown and adjust the cluster pointer and block
pointer if needed.
*/
VOID _synch_file_ptrs(PC_FILE *pfile) /*__fn__*/
{
UCOUNT clno;
if (!pfile->fptr_cluster)
{
pfile->fptr_cluster = pfile->pobj->finode->fcluster; /* Current cluster
- note on a new
file this will be zero */
if (pfile->fptr_cluster)
pfile->fptr_block = pc_cl2sector(pfile->pobj->pdrive, pfile->fptr_cluster);
else
pfile->fptr_block = 0;
}
if (pfile->at_eof)
{
if (pfile->fptr_cluster)
{
clno = pc_clnext(pfile->pobj->pdrive, pfile->fptr_cluster);
if (clno)
{
pfile->fptr_cluster = clno;
pfile->fptr_block = pc_cl2sector(pfile->pobj->pdrive, pfile->fptr_cluster);
pfile->at_eof = NO;
}
}
}
}
/****************************************************************************
PO_OPEN - Open a file.
Description
Open the file for access as specified in flag. If creating use mode to
set the access permissions on the file.
Flag values are
PO_BINARY - Ignored. All file access is binary
PO_TEXT - Ignored
PO_RDONLY - Open for read only
PO_RDWR - Read/write access allowed.
PO_WRONLY - Open for write only
PO_CREAT - Create the file if it does not exist. Use mode to
specify the permission on the file.
PO_EXCL - If flag contains (PO_CREAT | PO_EXCL) and the file already
exists fail and set fs_user->p_errno to EEXIST
PO_TRUNC - Truncate the file if it already exists
PO_NOSHAREANY - Fail if the file is already open. If the open succeeds
no other opens will succeed until it is closed.
PO_NOSHAREWRITE- Fail if the file is already open for write. If the open
succeeds no other opens for write will succeed until it
is closed.
Mode values are
PS_IWRITE - Write permitted
PS_IREAD - Read permitted. (Always true anyway)
Returns
Returns a non-negative integer to be used as a file descriptor for
calling read/write/seek/close otherwise it returns -1 and fs_user->p_errno is set to
one of these values
PENOENT - File not found or path to file not found
PEMFILE - No file descriptors available (too many files open)
PEEXIST - Exclusive access requested but file already exists.
PEACCESS - Attempt to open a read only file or a special (directory)
file.
PENOSPC - Create failed
PESHARE - Already open in exclusive mode or we want exclusive
and its already open
****************************************************************************/
PCFD NU_Open(TEXT *name, UCOUNT flag, UCOUNT mode) /*__fn__*/
{
PCFD fd;
PC_FILE *pfile;
UCOUNT cluster;
DROBJ *parent_obj;
DROBJ *pobj;
TEXT path[EMAXPATH];
TEXT filename[9];
TEXT fileext[4];
COUNT driveno;
BOOL parent_is_locked;
BOOL open_for_write;
BOOL sharing_error;
ULONG ltemp;
PC_FS_ENTER() /* Must be last line in declarations */
CHECK_USER(PCFD, -1) /* Check if a valid user if multitasking */
sharing_error = NO;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -