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

📄 nu_file.c

📁 NUcleus plus 支持的文件系统。 是学习文件系统的很好参考资料。
💻 C
📖 第 1 页 / 共 5 页
字号:
                {
                    /* Set the file sharing flags in the shared finode structure */
                    /* clear flags if we just opened it . */
                    if (pobj->finode->opencount == 1)
                        pobj->finode->openflags = 0;
                    if (open_for_write)
                    {
                        pobj->finode->openflags |= OF_WRITE;
                        if (flag & PO_NOSHAREWRITE)
                            pobj->finode->openflags |= OF_WRITEEXCLUSIVE;
                    }
                    if (flag & PO_NOSHAREANY)
                        pobj->finode->openflags |= OF_EXCLUSIVE;

                    pfile->flag = flag;            /* Access flags */
                    pfile->fptr = 0L;             /* File pointer */

                    /* Set the cluster and block file pointers */
                    _synch_file_ptrs(pfile);

                    if (flag & PO_APPEND)
                    {
                        /* Call the internal seek routine to set file pointer to file end  */
                         _po_lseek(pfile, 0, PSEEK_END);
                    }
                    fs_user->p_errno = 0;

                }
                PC_INODE_EXIT(parent_obj->finode)
                pc_freeobj(parent_obj);
            }
        }
        PC_DRIVE_EXIT(driveno)
    }
    /* Restore the kernel state */
    PC_FS_EXIT()
    return(fd);
}


/************************************************************************
* FUNCTION                                                              
*                                                                       
*       NU_Read                                                         
*                                                                       
* DESCRIPTION                                                           
*                                                                       
*       Attempt to read count bytes from the current file pointer of    
*       file at fd and put them in buf. The file pointer is updated.    
*                                                                       
* AUTHOR                                                                
*                                                                       
*       Takahiro Takahashi
*                                                                       
* INPUTS                                                                
*                                                                       
*       fd                                  File descriptor             
*       buf                                 Buffer to read data.        
*       count                               Number of read bytes.       
*                                                                       
* OUTPUTS                                                               
*                                                                       
*       Returns the number of bytes read or negative value on error.    
*                                                                       
*       INT32                               A non-negative integer to be
*                                            used as a number of bytes  
*                                            read.                      
*       NUF_BAD_USER                        Not a file user.            
*       NUF_BADPARM                         Invalid parameter specified.
*       NUF_BADFILE                         Invalid file descriptor.    
*       NUF_ACCES                           Open flag is  PO_WRONLY.    
*       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.    
*       PENOSPC                             Create failed.              
*                                                                       
*************************************************************************/
INT32 NU_Read(INT fd, CHAR *buf, INT32 count)
{
PC_FILE     *pfile;
UINT32      block_in_cluster;
UINT16      byte_offset_in_block;
UINT32      n_bytes;
UINT32      next_cluster;
UINT32      n_clusters;
UINT32      block_to_read;
DDRIVE      *pdrive;
UINT32      saved_ptr;
UINT32      saved_ptr_block;
UINT32      saved_ptr_cluster;
INT32       n_left;
UINT32      n_to_read;
UINT32      utemp;
UINT16      nblocks;
UINT8       local_buf[512];
INT32       ret_val;


    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;
    ret_val = 0;

    /* Get the FILE. Second argument is ignored */
    if ((pfile = pc_fd2file(fd)) == NULL)
    {
        fs_user->p_errno = PEBADF;
        ret_val = NUF_BADFILE;
    }
    /* Opened for read ? */
    else if (pfile->flag & PO_WRONLY)
    {
        fs_user->p_errno = PEACCES;
        ret_val = NUF_ACCES;
    }
    /* return -1 if bad arguments */
    else if ( !buf || count < 0)
    {
        ret_val = NUF_BADPARM;
    }
    /* Dont read if done */
    else if ( (pfile->fptr < pfile->pobj->finode->fsize) && (count) )
    {
        /* Move ddrive pointer to local. */
        pdrive = pfile->pobj->pdrive;
        /* Register Drive in use */
        PC_DRIVE_ENTER(pdrive->driveno, NO)  
        /* Grab exclusive access to the drobj */
        PC_INODE_ENTER(pfile->pobj->finode, YES)

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


        /* Truncate the read count if we need to */
        if ( (pfile->fptr + count) >= pfile->pobj->finode->fsize )
            count = (INT32) (pfile->pobj->finode->fsize - pfile->fptr);

        ret_val = n_left =  count;

        while (n_left) /* Loop until read specified count bytes */
        {
           block_in_cluster = (UINT32) (pfile->fptr & pdrive->byte_into_cl_mask);
           block_in_cluster >>= 9;
           block_to_read = pfile->fptr_block + block_in_cluster;

            /* how many clusters are left */
           n_to_read = (UINT32) ( (n_left + 511) >> 9 );
           n_clusters =(UINT32) ((n_to_read+pdrive->secpalloc-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)

            if (ret_val < 0)
            {
                fs_user->p_errno = PENOSPC;
                break;
            }

            n_clusters = ret_val;

            /* Are we inside a block */
            if ( (pfile->fptr & 0x1ffL) || (n_left < 512) )
            {
                byte_offset_in_block = (UINT16) (pfile->fptr & 0x1ffL);
                /* READ */
                PC_DRIVE_IO_ENTER(pdrive->driveno)
                if ( !pc_bdevsw[pdrive->driveno].io_proc(pdrive->driveno, block_to_read, local_buf, (UINT16) 1, YES) )
                {
                    PC_DRIVE_IO_EXIT(pdrive->driveno)
                    fs_user->p_errno = PENOSPC;
                    ret_val = NUF_IO_ERROR;
                    break;
                }
                PC_DRIVE_IO_EXIT(pdrive->driveno)
                /* Copy source data to the local buffer */
                n_bytes = (UINT32) (512 - byte_offset_in_block);
                if (n_bytes > (UINT32)n_left)
                    n_bytes = (UINT32)n_left;
                copybuff((UINT8 *)buf, &local_buf[byte_offset_in_block], (INT)n_bytes);

                buf += n_bytes;
                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 += 1;
                    }
                    else
                    {
                        pfile->fptr_cluster = next_cluster;
                        pfile->fptr_block = pc_cl2sector(pdrive, next_cluster);
                    }   /* if (--nclusters) {} else {}; */
                }       /* if (!(pfile->fptr & pdrive->byte_into_cl_mask)) */
            }           /* if ( (pfile->fptr & 0x1ff) || (n_left < 512) ) */
            else
            {
                /* Read as many blocks as possible */
                    /* How many blocks in the current chain */
                n_to_read = (UINT32) (n_clusters << pdrive->log2_secpalloc);
                   /* subtract out any leading blocks */
                n_to_read -= block_in_cluster;
                    /* How many blocks yet to read */
                utemp = (UINT32) (n_left >> 9);
                    /* take the smallest of the two */
                if (n_to_read > utemp)
                    n_to_read = utemp;

                if (n_to_read)
                {
                /* If we get here we need to read contiguous blocks */
                    block_to_read = pfile->fptr_block + block_in_cluster;

                    utemp = n_to_read;
                    while(utemp)
                    {
                        if (utemp > MAXSECTORS)
                            nblocks = MAXSECTORS;
                        else
                            nblocks = (UINT16) utemp;

                        /* READ */
                        PC_DRIVE_IO_ENTER(pdrive->driveno)
                        if ( !pc_bdevsw[pdrive->driveno].io_proc(pdrive->driveno, block_to_read, (UINT8 *)buf, nblocks, YES))
                        {
                            PC_DRIVE_IO_EXIT(pdrive->driveno)
                            fs_user->p_errno = PENOSPC;
                            ret_val = NUF_IO_ERROR;
                            break;
                        }
                        PC_DRIVE_IO_EXIT(pdrive->driveno)

                        utemp -= nblocks;
                        block_to_read += nblocks;
                        buf += (nblocks << 9);
                    }

                    n_bytes = (UINT32) (n_to_read << 9);
                    n_left -= n_bytes;
                    pfile->fptr += n_bytes;

                    /* if we advanced to a cluster boundary advance the 
                       cluster pointer */
                    /* utemp ==s how many clusters we read */
                    utemp =(UINT32) ((n_to_read+block_in_cluster) >> pdrive->log2_secpalloc);

                    if (utemp == n_clusters)
                    {
                        pfile->fptr_cluster = next_cluster;
                    }
                    else
                    {
                        /* advance the pointer as many as we read */
                        pfile->fptr_cluster += utemp;
                    }
                    pfile->fptr_block = pc_cl2sector(pdrive, pfile->fptr_cluster);
                }
            }
        }       /* while n_left */
        if (ret_val < 0)
        {

⌨️ 快捷键说明

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