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

📄 nu_file.c

📁 NUcleus plus 支持的文件系统。 是学习文件系统的很好参考资料。
💻 C
📖 第 1 页 / 共 5 页
字号:
            /* Restore pointers and return */
            pfile->fptr = saved_ptr;
            pfile->fptr_block = saved_ptr_block;
            pfile->fptr_cluster = saved_ptr_cluster;
        }
        else
        {
            ret_val = count;
        }
        PC_INODE_EXIT(pfile->pobj->finode)
        PC_DRIVE_EXIT(pdrive->driveno)
    }

    /* Restore the kernel state */
    PC_FS_EXIT()
    return(ret_val);
}


/************************************************************************
* FUNCTION                                                              
*                                                                       
*       NU_Write                                                        
*                                                                       
* DESCRIPTION                                                           
*                                                                       
*       Attempt to write count bytes from buf to the current file       
*       pointer of file at fd. The file pointer is updated.             
*                                                                       
* AUTHOR                                                                
*                                                                       
*       Takahiro Takahashi
*                                                                       
* INPUTS                                                                
*                                                                       
*       fd                                  File descriptor.            
*       *buf                                Pointer of buffer to write. 
*       count                               Write byte count.           
*                                                                       
* OUTPUTS                                                               
*                                                                       
*       Returns the number of bytes written or negative value on error. 
*       If the return value is negative, the meaning is follows:        
*                                                                       
*       INT32                               A non-negative integer to be
*                                            used as a number of bytes  
*                                            written.                   
*       NUF_BAD_USER                        Not a file user.            
*       NUF_BADPARM                         Invalid parameter specified.
*       NUF_BADFILE                         File descriptor invalid.    
*       NUF_ACCES                           Not a PO_WRONLY or PO_RDWR  
*                                            open flag or file          
*                                            attributes is ARDONLY.     
*       NUF_NOSPC                           Write failed. Presumably    
*                                            because of no space.       
*       NUF_IO_ERROR                        IO error occured.           
*       NUF_INTERNAL                        Nucleus FILE internal error.
*                                                                       
*       fs_user->p_errno is set to one of these values                  
*                                                                       
*       PEBADF                              Invalid file descriptor.    
*       PEACCES                             Attempt to open a read only 
*                                            file or a special          
*                                            (directory) file.          
*       PENOSPC                             Create failed.              
*                                                                       
*************************************************************************/
INT32 NU_Write(INT fd, CHAR *buf, INT32 count)
{
PC_FILE     *pfile;
DDRIVE      *pdrive;
UINT32      block_in_cluster;
UINT16      byte_offset_in_block;
UINT32      next_cluster;
UINT32      saved_ptr;
UINT32      saved_ptr_block;
UINT32      saved_ptr_cluster;
UINT32      ltemp;
UINT32      n_bytes;
UINT32      n_to_write;
UINT32      n_left;
UINT32      n_blocks_left;
UINT16      nblocks;
UINT32      n_clusters;
UINT32      alloced_size;
UINT32      block_to_write;
UINT8       local_buf[512];
INT32       ret_val;
STATUS      status;


    PC_FS_ENTER()     /* Must be last line in declarations */
    CHECK_USER(INT32, NUF_BAD_USER) /* Check if a valid user if multitasking */

    fs_user->p_errno = 0;

    /* Get the FILE. Second argument is ignored */
    if ( (pfile = pc_fd2file(fd)) == NULL )
    {
        fs_user->p_errno = PEBADF;
        ret_val = NUF_BADFILE;
    }
    /* Check the file attributes */
    else if (pfile->pobj->finode->fattribute & ARDONLY)
    {
        fs_user->p_errno = PEACCES;
        ret_val = NUF_ACCES;
    }
    /* Opened for write ? */
    else if ( !((pfile->flag & PO_WRONLY) || (pfile->flag & PO_RDWR)) )
    {
        fs_user->p_errno = PEACCES;
        ret_val = NUF_ACCES;
    }
    /* Return 0 (none written) on bad args */
    else if (!count)
    {
        ret_val = 0;
    }
    /* Return -1 bad parameter */
    else if ( count < 0 || !buf )
    {
        ret_val = NUF_BADPARM;
    }
    else
    {
        pdrive = pfile->pobj->pdrive;
        PC_DRIVE_ENTER(pdrive->driveno, NO)  /* Register drive in use (non excl) */

        /* Only one process may write at a time */
        PC_INODE_ENTER(pfile->pobj->finode, YES)

        /* if the  file is zero sized make sure the current cluster pointer
           is invalid */
        if (!pfile->pobj->finode->fsize)
            pfile->fptr_cluster = 0L;

        /* Set the cluster and block file pointers if not already set */
        _synch_file_ptrs(pfile);
        saved_ptr = pfile->fptr;
        saved_ptr_block = pfile->fptr_block;
        saved_ptr_cluster = pfile->fptr_cluster;

        /* calculate initial values */
        n_left = count;

        /* 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);

        while (n_left)
        {
            block_in_cluster = (UINT32) (pfile->fptr & pdrive->byte_into_cl_mask);
            block_in_cluster >>= 9;

            if (pfile->fptr >= alloced_size)
            {
                /* Extending the file */

                n_blocks_left = (UINT32) ((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 = ( UINT32) (1 + 
                ((n_blocks_left + block_in_cluster - 1) >> pdrive->log2_secpalloc));

                if (pdrive->fasize == 8)    /* FAT32 */
                {
                    /* Calculate file total size */
                    ltemp = alloced_size >> pdrive->log2_secpalloc;
                    ltemp >>= 9;  /* Divide by 512 */
                    ltemp += n_clusters;

                    /* Chech the maximum file size(4GB) */
                    if (pdrive->maxfsize_cluster < ltemp)
                    {
                        ret_val = NUF_MAXFILE_SIZE;
                        break;  /* Exit from write loop */
                    }
                }

                /* Call pc_alloc_chain to build a chain up to n_cluster clusters
                   long. Return the first cluster in pfile->fptr_cluster and
                   return the # of clusters in the chain. If pfile->fptr_cluster
                   is non zero link the current cluster to the new one */

                PC_FAT_ENTER(pdrive->driveno)
                status = pc_alloc_chain(&n_clusters, pdrive, &(pfile->fptr_cluster), n_clusters);
                PC_FAT_EXIT(pdrive->driveno)

                if (status != NU_SUCCESS)
                {
                    ret_val = (INT32)status;
                    break;  /* Exit from write loop */
                }
                /* Calculate the last cluster in this chain. */
                next_cluster = (UINT32) (pfile->fptr_cluster + n_clusters - 1);

                /* link the chain to the directory object if just starting */
               if (!pfile->pobj->finode->fcluster)
                    pfile->pobj->finode->fcluster = pfile->fptr_cluster;

                /* calculate the new block pointer */
                pfile->fptr_block = pc_cl2sector(pdrive, pfile->fptr_cluster);

                /* calculate amount of space used by the file */
                ltemp = n_clusters << pdrive->log2_secpalloc; ltemp <<= 9;
                alloced_size += ltemp;
            }
            else        /* Not extending the file. (writing inside the file) */
            {
                n_blocks_left = (UINT32) ((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 = (UINT32) (1 + 
                   ((n_blocks_left + block_in_cluster - 1) >> pdrive->log2_secpalloc));
                    
                /* how many contiguous clusters can we get ? <= n_clusters */
                PC_FAT_ENTER(pdrive->driveno)

                ret_val = pc_get_chain(pdrive, pfile->fptr_cluster,
                                              &next_cluster, n_clusters);
                PC_FAT_EXIT(pdrive->driveno)

                /* IO error occuered */
                if (ret_val <= 0)
                {
                    break;  /* Exit from write loop */
                }

                n_clusters = ret_val;
            }

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

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

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

                PC_DRIVE_IO_ENTER(pdrive->driveno)
                /* File pointer is not at block boundary, then we need to read the block. */
                /* Read */
                if ( !pc_bdevsw[pdrive->driveno].io_proc(pdrive->driveno, 
                                                    block_to_write, local_buf, (UINT16) 1, YES) )
                {
       

⌨️ 快捷键说明

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