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

📄 nu_file.c

📁 NUcleus plus 支持的文件系统。 是学习文件系统的很好参考资料。
💻 C
📖 第 1 页 / 共 5 页
字号:
*       Returns a non-negative integer to be used as a file descriptor. 
*       Returns a negative integer indicates an error as follows.       
*       NUF_BAD_USER                        Not a file user.            
*       NUF_BADDRIVE                        Invalid drive specified.    
*       NUF_NOSPC                           No space to create directory
*       NUF_LONGPATH                        Path or directory name too  
*                                            long.                      
*       NUF_INVNAME                         Path or filename includes   
*                                            invalid character.         
*		NUF_INVPARM		                    Invalid Flag/Mode is specified.
*		NUF_INVPARCMB		                Invalid Flag/Mode combination
*       NUF_PEMFILE                         No file descriptors.        
*                                            available.                 
*                                           (too many files open)       
*       NUF_ACCES                           You can't open the file     
*                                            which has Directory or     
*                                            VOLLABEL attributes.       
*       NUF_NOSPC                           No space to create directory
*                                            in this disk.              
*       NUF_SHARE                           The access conflict from    
*                                            multiple task to a specific
*                                            file.                      
*       NUF_NOFILE                          The specified file not      
*                                            found.                     
*       NUF_EXIST                           The directory already exists.
*       NUF_NO_BLOCK                        No block buffer available.  
*       NUF_NO_FINODE                       No FINODE buffer available. 
*       NUF_NO_DROBJ                        No DROBJ buffer available.  
*       NUF_IO_ERROR                        IO error occured.           
*       NUF_INTERNAL                        Nucleus FILE internal error.
*                                                                       
*       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.   
*       PEACCES                             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.      
*                                                                       
*************************************************************************/
INT NU_Open(CHAR *name, UINT16 flag, UINT16 mode)
{
INT         fd;
PC_FILE     *pfile;
UINT32      cluster;
DROBJ       *parent_obj;
DROBJ       *pobj;
VOID        *path;
VOID        *filename;
VOID        *fileext;
INT16       driveno;
INT         open_for_write;
INT         sharing_error;
STATUS      ret_stat;


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

    sharing_error = NO;
    parent_obj = NULL;
    pobj = NULL;

    /* We'll need to know this in a few places. */
    if ( flag & (PO_WRONLY | PO_RDWR ) )
        open_for_write = YES;
    else
        open_for_write = NO;

    fs_user->p_errno = 0;

    /* Get the drive number */
    pc_parsedrive(&driveno, (UINT8 *)name);

    if( flag & (~(PO_WRONLY|PO_RDWR|PO_APPEND|
                    PO_CREAT|PO_TRUNC|PO_EXCL|PO_TEXT|
                PO_BINARY|PO_NOSHAREANY|PO_NOSHAREWRITE)))
    {
        /* Invalid parameter is specified. */
        fd = NUF_INVPARM;
    }
    else if ((flag & PO_TRUNC) && (! open_for_write))
    {
        /* Invalid parameter combination is specified. */
        fd = NUF_INVPARCMB;
    }
    else if ((flag & PO_APPEND) && (!open_for_write))
    {
        /* Invalid parameter combination is specified. */
        fd = NUF_INVPARCMB;
    }
    else if ((flag & PO_EXCL) && (!(flag & PO_CREAT)))
    {
        /* Invalid parameter combination is specified. */
        fd = NUF_INVPARCMB;
    }
    else if ((flag & PO_WRONLY) && (flag & PO_RDWR))
    {
        /* Invalid parameter combination is specified. */
        fd = NUF_INVPARCMB;
    }
    else if ((flag & PO_TRUNC) && (flag & PO_APPEND))
    {
        /* Invalid parameter combination is specified. */
        fd = NUF_INVPARCMB;
    }
    else if((mode & (~(PS_IWRITE|PS_IREAD)))||(!(mode)))
    {
        /* Invalid parameter is specified. */
        fd = NUF_INVPARM;
    }
    else if ((fd = pc_allocfile()) < 0)     /* Grab a file */
    {
        /* File descriptor is not available */
        fs_user->p_errno = PEMFILE;
        fd = NUF_PEMFILE;
    }
    else
    {
        /* Get the FILE. This will never fail */
        pfile = pc_fd2file(fd);
        /* Paranoia. Set the obj to null until we have one */
        pfile->pobj = NULL;
        /* Clear the File update flag */
        pfile->fupdate = NO;

        PC_DRIVE_ENTER(driveno, NO)   /* Register drive in use */

        /* Get out the filename and d:parent */
        ret_stat = pc_parsepath(&path, &filename, &fileext, (UINT8 *)name);
        if (ret_stat != NU_SUCCESS)
        {
            fs_user->p_errno = PENOENT;
            pc_freefile(fd);
            fd = (INT)ret_stat;
        }
        else
        {
            /* Find the parent */
            ret_stat = pc_fndnode(driveno, &parent_obj, (UINT8 *)path);
            if (ret_stat != NU_SUCCESS)
            {
                fs_user->p_errno = PENOENT;
                pc_freefile(fd);
                fd = (INT)ret_stat;
            }
            else if ( (!pc_isadir(parent_obj)) || (pc_isavol(parent_obj)) )
            {
                fs_user->p_errno = PENOENT;
                pc_freefile(fd);
                fd = NUF_ACCES;
                pc_freeobj(parent_obj);
            }
            else
            {
                PC_INODE_ENTER(parent_obj->finode, YES)
                pobj = NULL;
                ret_stat =  pc_get_inode(&pobj, parent_obj, (UINT8 *)filename);
                if (ret_stat == NU_SUCCESS)
                {
                    /* If we goto exit: we want them linked so we can clean up */
                    pfile->pobj = pobj;            /* Link the file to the object */

                    /* The file is already open by someone. Lets see if we are
                           compatible */
                    sharing_error = NO;

                    /* Check the sharing conditions */
                    if (pobj->finode->opencount != 1)
                    {
                        /* 1. We don't want to share with anyone */
                        if (flag & PO_NOSHAREANY)
                            sharing_error = YES;
                        /* 2. Someone else doesn't want to share */
                        if (pobj->finode->openflags & OF_EXCLUSIVE)
                            sharing_error = YES;
                        /* 3. We want exclusive write but already open for write */
                        if ( open_for_write && (flag & PO_NOSHAREWRITE) &&
                             (pobj->finode->openflags & OF_WRITE) )
                            sharing_error = YES;
                        /* 4. We want open for write but it's already open for
                              exclusive */
                        if ( (open_for_write) && 
                             (pobj->finode->openflags & OF_WRITEEXCLUSIVE) )
                            sharing_error = YES;
                        /* 5. Open for trunc when already open */
                        if (flag & PO_TRUNC)
                            sharing_error = YES;
                    }
                    if (sharing_error)
                    {
                        fs_user->p_errno = PESHARE;
                        pc_freefile(fd);
                        fd = NUF_SHARE;
                    }
                    else if ( pc_isadir(pobj) || pc_isavol(pobj) )
                    {
                        fs_user->p_errno = PEACCES;        /* is a directory */
                        pc_freefile(fd);
                        fd = NUF_ACCES;
                    }
                    else if ( (flag & (PO_EXCL | PO_CREAT)) == (PO_EXCL | PO_CREAT) )
                    {
                        fs_user->p_errno = PEEXIST;        /* Exclusive fail */
                        pc_freefile(fd);
                        fd = NUF_EXIST;
                    }
                    else if (flag & PO_TRUNC)
                    {
                        cluster = pobj->finode->fcluster;
                        pobj->finode->fcluster = 0L;
                        pobj->finode->fsize = 0L;

                        /* Update an inode to disk. */
                        ret_stat = pc_update_inode(pobj, DSET_UPDATE);
                        if (ret_stat == NU_SUCCESS)
                        {
                            /* And clear up the space */
                            PC_FAT_ENTER(pobj->pdrive->driveno)
                            ret_stat = pc_freechain(pobj->pdrive,cluster);
                            if (ret_stat == NU_SUCCESS)
                                ret_stat = pc_flushfat(pobj->pdrive);
                            PC_FAT_EXIT(pobj->pdrive->driveno)
                        }
                    }
                    if (ret_stat != NU_SUCCESS)
                    {
                        fs_user->p_errno = PEACCES;
                        pc_freefile(fd);
                        fd = (INT)ret_stat;
                    }
                }
                else if (ret_stat == NUF_NOFILE)   /* File not found */
                {
                    if (!(flag & PO_CREAT))
                    {
                        fs_user->p_errno = PENOENT;        /* File does not exist */
                        pc_freefile(fd);
                        fd = NUF_NOFILE;
                    }
                    /* Do not allow create if write bits not set */
                    else if (!open_for_write)
                    {
                        fs_user->p_errno = PEACCES;        /* read only file */
                        pc_freefile(fd);
                        fd = NUF_ACCES;
                    }
                    else
                    {
                        /* Create for read only if write perm not allowed */
                        ret_stat = pc_mknode(&pobj, parent_obj, (UINT8 *)filename, (UINT8 *)fileext, 
                                            (UINT8) ((mode == PS_IREAD) ? (ARDONLY | ARCHIVE) : ARCHIVE));
                        if (ret_stat == NU_SUCCESS)
                        {
                            pfile->pobj = pobj;            /* Link the file to the object */
                        }
                        else
                        {
                            fs_user->p_errno = PENOSPC;
                            pc_freefile(fd);
                            fd = (INT)ret_stat;
                        }
                    }
                }
                else  /* IO Error */
                    fd = (INT)ret_stat;

                if (fd >= 0) /* No error */

⌨️ 快捷键说明

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