⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 nu_file.c

📁 nucleus 文件系统,内核和彩色图形系统,在小系统上非常好用
💻 C
📖 第 1 页 / 共 5 页
字号:
/*
* 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 + -