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

📄 api.c

📁 ertfs文件系统里面既有完整ucos程序
💻 C
📖 第 1 页 / 共 5 页
字号:
            ltemp = n_clusters << pdrive->log2_secpalloc; ltemp <<= 9;
            alloced_size += ltemp;
        }
        else        /* Not extending the file. (writing inside the file) */
        {
            n_blocks_left = (word) ((n_left + 511) >> 9);

            /* how many clusters are left-
            *  assume 1 for the current cluster.
            *   subtract out the blocks in the current
            *   round up by adding secpalloc-1 and then
            *   divide by sectors per cluster

            |  n_clusters = 1 + 
            |   (n_blocks_left-
            |       (pdrive->secpalloc-block_in_cluster)
            |       + pdrive->secpalloc-1) >> pdrive->log2_secpalloc;
                ==>
            */
           n_clusters = (CLUSTERTYPE) (1 + /* FAT32 */
               ((n_blocks_left + block_in_cluster -1) >> pdrive->log2_secpalloc));/* FAT32 */
                
            /* how many contiguous clusters can we get ? <= n_clusters   */
            n_clusters = pc_get_chain(pdrive, pfile->fptr_cluster,
                                        &next_cluster, n_clusters);
            if (!n_clusters)
                goto ret_bad_f;
        }

        /* Are we inside a block   */
        if ( (pfile->fptr & 0x1ffL) || (n_left < 512) )
        {
            block_in_cluster = (word) (pfile->fptr & pdrive->byte_into_cl_mask);
            block_in_cluster >>= 9;
            block_to_write = pfile->fptr_block + block_in_cluster;

            byte_offset_in_block = (word) (pfile->fptr & 0x1ffL);

            /* Copy source data to the local buffer   */
            n_bytes = (word) (512 - byte_offset_in_block);
            if (n_bytes > n_left)
                n_bytes = n_left;

            /* Read                                               */
            /* READ - Use the block buffer pool to read for us    */
            local_buf = pc_read_blk(pdrive,  block_to_write);
            if (!local_buf)
                   goto ret_bad_f;
            copybuff(&(local_buf->data[byte_offset_in_block]), buf, n_bytes);
            /* Write   */
            if (!pc_write_blk(local_buf))
            {
            /* Release the buffer. and discard it   */
                pc_free_buf(local_buf, TRUE);
                goto ret_bad_f;
            }
            /* Release the buffer. and discard it   */
            pc_free_buf(local_buf, TRUE);
            buf += n_bytes;

            n_left = (word) (n_left - n_bytes);
            pfile->fptr += n_bytes;

            /* Are we on a cluster boundary  ?   */
            if (!(pfile->fptr & pdrive->byte_into_cl_mask))
            {
                if (--n_clusters)           /* If contiguous */
                {
                    pfile->fptr_block += pdrive->secpalloc;
                    pfile->fptr_cluster += (CLUSTERTYPE)1;
                }
                else
                {
/* NOTE:            Put the next cluster into the pointer. If we had
                    alloced a chain this value is the last cluster in 
                    the chain and does not concur with the byte file pointer.
                    This is not a problem since the cluster pointer is known 
                    to be off at this point any (fptr>=alloced_size) */
                    pfile->fptr_cluster = next_cluster;
                    pfile->fptr_block = pc_cl2sector(pdrive, next_cluster);
                }   /* if (--nclusters) {} else {}; */
            }       /* if (!(pfile->fptr & byte_into_cl_mask)) */
        }           /* if ( (pfile->fptr & 0x1ff) || (n_left < 512) ) */

        if (n_clusters && (n_left>511))
        {
            /* If we get here we need to write contiguous blocks   */
            block_in_cluster = (word) (pfile->fptr & pdrive->byte_into_cl_mask);
            block_in_cluster >>= 9;
            block_to_write = pfile->fptr_block + block_in_cluster;
            /* how many do we write ?   */
            n_blocks_left = (word) (n_left >> 9);
            n_to_write = (word) ((n_clusters << pdrive->log2_secpalloc) - block_in_cluster);

            if (n_to_write > n_blocks_left)
            {
                n_to_write = n_blocks_left;

            /* If we are not writing to the end of the chain we may not
                advance the cluster pointer to the beginning of the next
                chain. We add in block_in_cluster so we account for the
                partial cluster we've already seen */
                next_cluster = (CLUSTERTYPE) (pfile->fptr_cluster +
                                ((n_to_write+block_in_cluster) >>  pdrive->log2_secpalloc));
            }
            if (!devio_write(pdrive->driveno, block_to_write, buf, n_to_write, FALSE))
                    goto ret_bad_f;
            n_bytes = (word) (n_to_write << 9);
            
            buf = buf + n_bytes; 
            n_left = (word) (n_left - n_bytes);
            pfile->fptr += n_bytes;

/* See note above   */
            pfile->fptr_cluster = next_cluster;
            pfile->fptr_block   = pc_cl2sector(pdrive, next_cluster);
        }
    }       /* while n_left */

    if (pfile->fptr > pfile->pobj->finode->fsize)
    {
        pfile->needs_flush = TRUE;
        pfile->pobj->finode->fsize = pfile->fptr;
    }
    /* 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;
        
    OS_RELEASE_LOGDRIVE(pdrive->driveno)

    /* Restore the kernel state   */
    set_errno(p_errno);
    OS_FS_EXIT()
    return(count);

ret_bad_f:
    /* 11-20-99 - Bug fix: even on error make sure we fix up the size */ 
    if (pfile->fptr > pfile->pobj->finode->fsize)
    {
        pfile->needs_flush = TRUE;
        pfile->pobj->finode->fsize = pfile->fptr;
    }
    /* 11-20-99 - End Bug fix: even on error make sure we fix up the size */ 

    /* Restore pointers and return   */
    pfile->fptr = saved_ptr;
    pfile->fptr_block = saved_ptr_block;        
    pfile->fptr_cluster = saved_ptr_cluster;        

    /* 11-20-99 - Bug fix - */
    if (pfile->fptr >= alloced_size)
        pfile->at_eof = TRUE;
    else
        pfile->at_eof = FALSE;
    /* 11-20-99 - End Bug fix */

    p_errno = PENOSPC;
    OS_RELEASE_LOGDRIVE(pdrive->driveno)        /* Release non-excl use of drive */
    ret_val = (word) ~0;
return_error:
    /* Restore the kernel state   */
    set_errno(p_errno);
    OS_FS_EXIT()
    return(ret_val);
}
#endif
#endif
RTFS_FILE(lseek.c, po_lseek)

#ifndef __PCDISK__  /* This allows us to build the lib with subroutines split */
#include <pcdisk.h>
#endif

/**************************************************************************
    PO_LSEEK    -  Move file pointer

 Description
    Move the file pointer offset bytes from the origin described by 
    origin. The file pointer is set according to the following rules.

    Origin              Rule
    PSEEK_SET           offset from begining of file
    PSEEK_CUR           offset from current file pointer
    PSEEK_END           offset from end of file

    Attempting to seek beyond end of file puts the file pointer one
    byte past eof. 

 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.

*****************************************************************************/

long po_lseek(PCFD fd, long offset, int origin)                 /*__fn__*/
{
    PC_FILE *pfile;
    DDRIVE *pdrive;
    long    ret_val;
    int p_errno;
    CHECK_MEM(long, -1) /* Make sure memory is initted */
    OS_FS_ENTER()

    p_errno = 0;    

    /* Get the FILE     */
    pfile = pc_fd2file(fd, 0);
    if (!pfile)
    {
        p_errno = PEBADF;
        ret_val = -1L;
        goto return_error;
    }

    pdrive = pfile->pobj->pdrive;
    OS_CLAIM_LOGDRIVE(pdrive->driveno)  /* Register drive in use */
    /* Grab exclusive access to the drobj   */
    /* 
    * Note the file's finode is LOCKED below so the code needn't be 
    * reentrant relative to the finode. 
    */
    /* Set the cluster and block file pointers if not already set   */
    _synch_file_ptrs(pfile);

    /* Call the internal seek routine that we share with po_trunc   */
    ret_val =  _po_lseek(pfile, offset, origin);

    OS_RELEASE_LOGDRIVE(pdrive->driveno)
return_error:   /* No only errors return through here. Everything does. */
    /* Restore the kernel state   */
    set_errno(p_errno);
    OS_FS_EXIT()
    return(ret_val);
}
RTFS_FILE(truncate.c, po_truncate)

#ifndef __PCDISK__  /* This allows us to build the lib with subroutines split */
#include <pcdisk.h>
#endif
#if (RTFS_WRITE)

/**************************************************************************
    PO_TRUNCATE -  Truncate an open file.

 Description
    Move the file pointer offset bytes from the beginning of the file
    and truncate the file beyond that point by adjusting the file size
    and freeing the cluster chain past the file pointer.
 
 Returns
    Returns TRUE if successful otherwise FALSE

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

    PENBADF     - File descriptor invalid or open read only
    PENOSPC     - IO error
    PEINVAL     - Invalid offset
    PESHARE     - Can not truncate a file open by more than one handle.

*****************************************************************************/

BOOLEAN po_truncate(PCFD fd, long offset)                               /*__fn__*/
{
    PC_FILE *pfile;
    DDRIVE *pdrive;
    BOOLEAN ret_val;
    CLUSTERTYPE first_cluster_to_release;/* FAT32 */
    CLUSTERTYPE last_cluster_in_chain;/* FAT32 */
    CLUSTERTYPE clno;/* FAT32 */
    int p_errno;
    CHECK_MEM(BOOLEAN, 0)   /* Make sure memory is initted */
    OS_FS_ENTER()

    p_errno = 0;    

    /* Assume success until something fails   */
    ret_val = TRUE;

    /* Get the FILE. must be open for write   */
    pfile = pc_fd2file(fd, PO_WRONLY|PO_RDWR);
    /* Make sure we have write privilages   */
    if (!pfile)
    {
        p_errno = PEBADF;
        ret_val = FALSE;
        goto return_error;
    }

    pdrive = pfile->pobj->pdrive;
    OS_CLAIM_LOGDRIVE(pdrive->driveno)  /* Register drive in use */

    /* Grab exclusive access to the file   */
    /* 
    * Note the file's finode is LOCKED below so the code needn't be 
    * reentrant relative to the finode. 
    */

    /* Can only truncate a file that you hold exclusively   */
    if (pfile->pobj->finode->opencount > 1)
    {
        ret_val = FALSE;
        p_errno = PESHARE;
        goto errex;
    }

    /* Set the cluster and block file pointers if not already set   */
    _synch_file_ptrs(pfile);

    /* Call the internal seek routine that we share with po_lseek. Seek to 
        offset from the origin of zero. */
    offset = _po_lseek(pfile, offset, PSEEK_SET);

    if (offset == -1 || ((dword)offset > pfile->pobj->finode->fsize))
    {
        ret_val = FALSE;
        p_errno = PEINVAL;
    }
    else if ((dword)offset == pfile->pobj->finode->fsize)
    {
    /*  ret_val = TRUE; - already set */
    }
    else
    {
        pfile->needs_flush = TRUE;

        /* Are we on a cluster boundary ?   */
        if (!(offset & pdrive->byte_into_cl_mask))
        {
        /* Free the current cluster and beyond since we're on a cluster boundary.   */
            first_cluster_to_release = pfile->fptr_cluster; 

            /* Find the previous cluster so we can terminate the chain   */

            
            clno = pc_finode_cluster(pfile->pobj->pdrive,pfile->pobj->finode);/* FAT32 */
            last_cluster_in_chain = clno;
            while (clno != first_cluster_to_release)
            {
                last_cluster_in_chain = clno;
                clno = pc_clnext(pdrive , clno);
                if (clno == 0)
                {
                    ret_val = FALSE;
                    p_errno = PENOSPC;
                    goto errex;
                }
            }
            /* Set ptr_cluster to last in chain so read&write will work right   */
            pfile->fptr_cluster = last_cluster_in_chain;
            if (last_cluster_in_chain)
                pfile->fptr_block = pc_cl2sector(pdrive, last_cluster_in_chain);
            else
                pfile->fptr_block = 0;
            pfile->at_eof = TRUE;
        }
        else        /* Simple case. we aren't on a cluster boundary. Just free*/
        {           /* The chain beyond us and terminate the list */
            last_cluster_in_chain = pfile->fptr_cluster;
            first_cluster_to_release = pc_clnext(pdrive, pfile->fptr_cluster);
            pfile->at_eof = TRUE;
        }

        /*  Now update the directory entry.   */
        pfile->pobj->finode->fsize = offset;
        if (!offset)    /* If the file goes to zero size unlink the chain */
        {
            pc_pfinode_cluster(pfile->pobj->pdrive,pfile->pobj->finode,0);/* FAT32 */
            pfile->fptr_cluster = 0;
            pfile->fptr_block = 0;
            pfile->fptr = 0;
            pfile->at_eof = FALSE;
            /* We're freeing the whole chain so we don't mark last_cluster in chain   */
            last_cluster_in_chain = 0;
        }
        /* Convert to native. Overwrite the existing inode.Set archive/date  */
        if (!pc_update_inode(pfile->pobj, TRUE, TRUE))
        {
            ret_val = FALSE;
            p_errno = PENOSPC;
            goto errex;
        }

        /* Terminate the chain and free the lost chain part   */

        /* Free the rest of the chain   */
        if (first_cluster_to_release)
        {
            /* Release the chain   */
            pc_freechain(pfile->pobj->pdrive, first_cluster_to_release);
        }
        /* Null terminate the chain   */
        if (last_cluster_in_chain)

⌨️ 快捷键说明

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