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

📄 api.c

📁 ertfs文件系统里面既有完整ucos程序
💻 C
📖 第 1 页 / 共 5 页
字号:
    
    po_lseek and po_truncate.

 Returns
    Returns the new offset or -1 on error.

    If the return value is -1 xn_getlasterror() will be set with one of the following:

    PENBADF     - File descriptor invalid
    PEINVAL     - Seek to negative file pointer attempted.

*****************************************************************************/
/* 
* Note: when this routine is caled the file's finode is LOCKED so the code
* needn't be reentrant relative to the finode. 
*/

long _po_lseek(PC_FILE *pfile, long offset, int origin)         /*__fn__*/
{
    long    file_pointer;
    DDRIVE *pdrive;
    BOOLEAN past_file;
    int  log2_bytespcluster;
    dword  ltemp;
    dword  ltemp2;
    CLUSTERTYPE  n_clusters_to_seek;    /* FAT32 */
    CLUSTERTYPE  n_clusters;/* FAT32 */
    CLUSTERTYPE  first_cluster;      /* FAT32 */
    long    ret_val;
    dword  alloced_size;
    int p_errno;

    p_errno = 0;    

    pdrive = pfile->pobj->pdrive;
    /* If file is zero size'd. were there   */
    if (!(pfile->pobj->finode->fsize))
    {
        ret_val = 0L;
        goto errex;
    }

    if (origin == PSEEK_SET)        /*  offset from begining of file */
        file_pointer = offset;
    else if (origin == PSEEK_CUR)   /* offset from current file pointer */
    {
        file_pointer = (long) pfile->fptr;
        file_pointer += offset;
    }
    else if (origin == PSEEK_END)   /*  offset from end of file */
    {
        file_pointer = (long) pfile->pobj->finode->fsize;
        file_pointer += offset;
    }
    else    /* Illegal origin */
    {
        p_errno = PEINVAL;
        ret_val = -1L;
        goto errex;
    }

    if (file_pointer < 0L)
    {
        p_errno = PEINVAL;
        ret_val = -1L;
        goto errex;
    }

    if (file_pointer >= (long) pfile->pobj->finode->fsize)
    {
        file_pointer = (long) pfile->pobj->finode->fsize;
        past_file = TRUE;
    }
    else
        past_file = FALSE;

    log2_bytespcluster = (int) (pdrive->log2_secpalloc + 9);

    /* How many clusters do we need to seek                       */
    /* use the current cluster as the starting point if we can    */
    if (file_pointer >= (long)pfile->fptr)
    {
        first_cluster = pfile->fptr_cluster;

        ltemp =  file_pointer;
        if (past_file)
        {
            /* If seeking past eof reduce the seek count by one since we can't 
                really seek past EOF */
            ltemp -= 1;
        }
        ltemp >>= log2_bytespcluster;
        ltemp2 = pfile->fptr  >> log2_bytespcluster;
        /* If this algorithm was run twice n_clusters_to_seek would
            end up -1. Which would still work but spin 64K times.
            Thanks top Morgan Woodson of EMU systems for the patch */
        if (ltemp >= ltemp2)
            n_clusters_to_seek = (CLUSTERTYPE) (ltemp - ltemp2); /* FAT32 */
        else
            n_clusters_to_seek = (word) 0;
    }
    else
    {
        /* seek from the beginning    */
        /* seek from the beginning    */
        first_cluster = pc_finode_cluster(pdrive,pfile->pobj->finode);/* FAT32 */
        ltemp = file_pointer >> log2_bytespcluster;
        n_clusters_to_seek = (CLUSTERTYPE) ltemp; /* FAT32 */
    }

    while (n_clusters_to_seek)
    {
        n_clusters = pc_get_chain(pdrive, first_cluster,
                                &first_cluster, n_clusters_to_seek);

        if (!n_clusters)
        {
            p_errno = PEINVAL;
            ret_val = -1L;
            goto errex;
        }
    
        n_clusters_to_seek = (CLUSTERTYPE) (n_clusters_to_seek - n_clusters);
    }

    pfile->fptr_cluster = first_cluster;
    pfile->fptr_block = pc_cl2sector(pdrive, first_cluster);
    pfile->fptr= file_pointer;

    /* If seeking to the end of file see if we are beyond the allocated size of 
        the file. If we are we set the at_eof flag so we know to try to move the
        cluster pointer in case another file instance extends the file */
    if (past_file)
    {
        /* Round the file size up to its cluster size by adding in clustersize-1
            and masking off the low bits */
        alloced_size =  (pfile->pobj->finode->fsize + pdrive->byte_into_cl_mask) &
                        ~(pdrive->byte_into_cl_mask);
        /* If the file pointer is beyond the space allocated to the file note it
            since we may need to adjust this file's cluster and block pointers
            later if someone else extends the file behind our back */
        if (pfile->fptr >= alloced_size)
            pfile->at_eof = TRUE;
        else
            pfile->at_eof = FALSE;
    }
    else
        pfile->at_eof = FALSE;

    ret_val = pfile->fptr;
errex:
                    /* No only errors return through here. Everything does.   */
    set_errno(p_errno);
    return(ret_val);
}


#if (RTFS_WRITE)
/* 
* Note: when this routine is caled the file's finode is LOCKED so the code
* needn't be reentrant relative to the finode. 
*/
/* Internal version of po_flush() called by po_flush and po_close   */
BOOLEAN _po_flush(PC_FILE *pfile)                                       /*__fn__*/
{
    BOOLEAN ret_val;
    ret_val = TRUE;
    /* Convert to native. Overwrite the existing inode.Set archive/date  */
    if (pfile->needs_flush)
    {
        if (pc_update_inode(pfile->pobj, TRUE, TRUE))
        {
            pfile->needs_flush = FALSE;
            /* Flush the file allocation table   */
            if (!pc_flushfat(pfile->pobj->pdrive->driveno))
                ret_val = FALSE;
        }
    }
    return(ret_val);
}

#endif


#if (RTFS_WRITE)
/****************************************************************************
    PO_FLUSH  -  Flush a file.

 Description
    Flush the file updating the disk.

 Returns
    Returns TRUE if all went well otherwise it returns FALSE and xn_getlasterror() is set to
    one of these values

    PENBADF - Invalid file descriptor
    PENOSPC - IO error occured
****************************************************************************/

BOOLEAN po_flush(PCFD fd)                                           /*__fn__*/
{
    PC_FILE *pfile;
    BOOLEAN ret_val;
    int  p_errno;
    CHECK_MEM(BOOLEAN, 0)   /* Make sure memory is initted */
    OS_FS_ENTER()

    /* Start by assuming failure   */
    ret_val = FALSE;
    p_errno = PEBADF;   

    /* Get the FILE. must be open for write   */
    pfile = pc_fd2file(fd, PO_WRONLY|PO_RDWR);
    if (pfile)
    {
        OS_CLAIM_LOGDRIVE(pfile->pobj->pdrive->driveno)  /* Register drive in use */
        /* Claim exclusive access on flush   */
        ret_val = _po_flush(pfile);
        if (!ret_val)
            p_errno = PENOSPC;  
        OS_RELEASE_LOGDRIVE(pfile->pobj->pdrive->driveno)
    }
    /* Restore the kernel state   */
    set_errno(p_errno);

    OS_FS_EXIT()
    return(ret_val);
}
#endif


/****************************************************************************
    PO_CLOSE  -  Close a file.

 Description
    Close the file updating the disk and freeing all core associated with FD.

 Returns
    Returns 0 if all went well otherwise it returns -1 and xn_getlasterror() is set to
    one of these values

    PENBADF - Invalid file descriptor
    PENOSPC - IO error occured
****************************************************************************/

int po_close(PCFD fd)                                               /*__fn__*/
{
    PC_FILE *pfile;
    int ret_val;
    int driveno;
    int  p_errno;
    CHECK_MEM(int, -1)  /* Make sure memory is initted */
    OS_FS_ENTER()


    if ( (pfile = pc_fd2file(fd, 0)) == 0)
    {
        p_errno = PEBADF;
        ret_val = -1;
    }
    else
    {
        driveno = pfile->pobj->pdrive->driveno;
        OS_CLAIM_LOGDRIVE(driveno)  /* Register drive in use */
        ret_val = 0;
        p_errno = 0;    
#if (RTFS_WRITE)
        if (pfile->flag & ( PO_RDWR | PO_WRONLY ) )
        {
            if (!_po_flush(pfile))
            {
                p_errno = PENOSPC;  
                ret_val = -1;
            }
        }
#endif
        /* Release the FD and its core   */
        pc_freefile(fd);
        OS_RELEASE_LOGDRIVE(driveno)
    }
    set_errno(p_errno);
    /* Restore the kernel state   */
    OS_FS_EXIT()
    return(ret_val);
}


/***************************************************************************
    PC_MV -  Rename a file.

 Description
    Renames the file in path (name) to newname. Fails if name is invalid,
    newname already exists or path not found. 

    01-07-99 - Rewrote to support moving files between subdirectories
               no longer supports renaming subdirectories or volumes
 Returns
    Returns TRUE if the file was renamed. Or no if the name not found.

***************************************************************************/
#if (RTFS_WRITE)

/* Rename a file */
BOOLEAN pc_mv(char *old_name, char *new_name)                                /*__fn__*/
{
    int old_driveno;
    DROBJ *old_obj;
    DROBJ *old_parent_obj;
    char path[EMAXPATH];
    char filename[FILENAMESIZE];
    char fileext[4];
    int new_driveno;
    DROBJ *new_obj;
    DROBJ *new_parent_obj;
    BOOLEAN ret_val;   
    CLUSTERTYPE  cluster;   /* FAT32 */

    int  p_errno;
    CHECK_MEM(BOOLEAN, 0)   /* Make sure memory is initted */
    OS_FS_ENTER()     /* Must be last line in declarations */

    /* Get the drive and make sure it is mounted   */
    old_driveno = check_drive(old_name);
    if (old_driveno < 0)
    {
        OS_FS_EXIT()
        return(FALSE);
    }


    old_obj         = 0;
    old_parent_obj  = 0;
    new_obj         = 0;
    new_parent_obj  = 0;

    ret_val = FALSE;
    p_errno = PENOENT;
  
    if (!pc_parsedrive( &old_driveno, old_name ))
        goto return_error;
    if (!pc_parsedrive( &new_driveno, new_name ))
        goto return_error;
    /* Drives must be the same */  
    if (old_driveno != new_driveno)
        goto return_error;

    OS_CLAIM_LOGDRIVE(old_driveno)      /* Grab exclusive access to the drive */

    /* Get out the filename and d:parent */
    if (!pc_parsepath(path,filename,fileext,old_name))
        goto errex;
    /* Find the parent and make sure it is a directory  */
    old_parent_obj = pc_fndnode(path);
    if (!old_parent_obj || !pc_isadir(old_parent_obj) ||  pc_isavol(old_parent_obj))
        goto errex;
    /* Find the file */
    old_obj = pc_get_inode(0, old_parent_obj, (byte*)filename, (byte*)fileext, FALSE);

     /* Be sure it exists and is a normal file and is not open */
    if (!old_obj || pc_isroot(old_obj) || (old_obj->finode->opencount > 1) ||
       (old_obj->finode->fattribute&(ARDONLY|AVOLUME|ADIRENT)))
        goto errex;

    /* At this point old_obj contains the file we are renaming */

    /* See if the new directory entry already exists */
    new_obj = pc_fndnode(new_name);
    if (new_obj)
    {
        p_errno = PEEXIST;
        goto errex;
    }

    /* Get out the filename and d:parent */
    if (!pc_parsepath(path,filename,fileext,new_name))
        goto errex;
    /* Find the parent and make sure it is a directory  */
    new_parent_obj = pc_fndnode(path);
    if (!new_parent_obj || !pc_isadir(new_parent_obj) ||  pc_isavol(new_parent_obj))
        goto errex;

    /* Set errno to EINVAL if we fail file validation */
    p_errno = PEINVAL;
#if (VFAT)
    if (!validate_filename(filename, tc_strlen(filename)))
        goto errex;
#else
    if (!validate_filename(filename, 8))
        goto errex;
    if (!validate_filename(fileext, 3))
        goto errex;

#endif

    p_errno = PENOSPC;
    /* Create

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -