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

📄 nu_file.c

📁 nucleus 文件系统,内核和彩色图形系统,在小系统上非常好用
💻 C
📖 第 1 页 / 共 5 页
字号:
    parent_is_locked = 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 */
    if (!pc_parsedrive( &driveno, name))
    {
        fs_user->p_errno = PENOENT;
        goto errex1;
    }
    if ( (fd = pc_allocfile()) < 0 )     /* Grab a file */
    {
        fs_user->p_errno = PEMFILE;
        goto errex1;
    }
    
    /* Get the FILE. This will never fail */
    pfile = pc_fd2file(fd, NO);
    /* Paranoia. Set the obj to null until we have one */
    pfile->pobj = NULL;

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

    /* Get out the filename and d:parent */
    if (!pc_parsepath(path,filename,fileext,name))
    {
        fs_user->p_errno = PENOENT;
        goto errex;
    }

    /* Find the parent */
    parent_obj = pc_fndnode(path);

    if (!parent_obj || !pc_isadir(parent_obj) ||  pc_isavol(parent_obj))
    {
        fs_user->p_errno = PENOENT;
        goto errex;
    }
        
    PC_INODE_ENTER(parent_obj->finode, YES)
    parent_is_locked = YES;

    pobj =  pc_get_inode(NULL, parent_obj,(UTEXT*)filename,(UTEXT*)fileext);

    if (pobj)
    {
        /* If we goto exit: we want them linked so we can clean up */
        pfile->pobj = pobj;            /* Link the file to the object */

        /* check the sharing conditions */
        if (pobj->finode->opencount != 1)
        {
            /* The file is already open by someone. Lets see if we are
               compatible */
            sharing_error = NO;
                /* 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;
                goto errex;
            }
        }

        if( pc_isadir(pobj) || pc_isavol(pobj) )
        {
            fs_user->p_errno = PEACCES;        /* is a directory */
            goto errex;
        }
        if ( (flag & (PO_EXCL|PO_CREAT)) == (PO_EXCL|PO_CREAT) )
        {
            fs_user->p_errno = PEEXIST;        /* Exclusive fail */
            goto errex;
        }
        if(open_for_write && (pobj->finode->fattribute & ARDONLY) )
        {
            fs_user->p_errno = PEACCES;        /* read only file */
            goto errex;
        }
        if (flag & PO_TRUNC)
        {
            cluster = pobj->finode->fcluster;
            ltemp   = pobj->finode->fsize;

            pobj->finode->fcluster = 0;
            pobj->finode->fsize = 0L;
            if (pc_update_inode(pobj))
            {
                /* And clear up the space */
                PC_FAT_ENTER(pobj->pdrive->driveno)
                pc_freechain(pobj->pdrive,cluster);
                pc_flushfat(pobj->pdrive->driveno);
                PC_FAT_EXIT(pobj->pdrive->driveno) 
            }
            else
            {
                pobj->finode->fcluster = cluster;
                pobj->finode->fsize = ltemp;
                fs_user->p_errno = PEACCES;
                goto errex;
            }
        }
    }
    else    /* File not found */
    {
        if (!(flag & PO_CREAT))
        {
            fs_user->p_errno = PENOENT;        /* File does not exist */
            goto errex;
        }
            /* Do not allow create if write bits not set */
        if(!open_for_write)
        {
            fs_user->p_errno = PEACCES;        /* read only file */
            goto errex;
        }
            /* Create for read only if write perm not allowed */            
        pobj = pc_mknode( parent_obj, filename, fileext, (UTINY) ((mode == PS_IREAD) ? ARDONLY : 0));
        if (!pobj)
        {
            fs_user->p_errno = PENOSPC;
            goto errex;
        }
        else
            pfile->pobj = pobj;            /* Link the file to the object */
    }

    /* 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);
    fs_user->p_errno = 0;
    if (parent_obj)
    {
        if (parent_is_locked)
            PC_INODE_EXIT(parent_obj->finode)
        pc_freeobj(parent_obj);
    }
    PC_DRIVE_EXIT(driveno)
    /* Restore the kernel state */
    PC_FS_EXIT()
    return(fd);
errex:
    pc_freefile(fd);
    if (parent_obj)
    {
        if (parent_is_locked)
            PC_INODE_EXIT(parent_obj->finode)
        pc_freeobj(parent_obj);
    }
    PC_DRIVE_EXIT(driveno)
errex1:
    /* Restore the kernel state */
    PC_FS_EXIT()
    return(-1);
}

/****************************************************************************
    PO_READ    -  Read from a file.

 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.

 Returns
    Returns the    number of bytes read or -1 on error.
    If the return value is ((UCOUNT) ~0) (UCOUNT) -1 fs_user->p_errno will be set
    with one of the following:

    PENBADF        - File descriptor invalid
    PENOSPC        - File IO error
*****************************************************************************/

COUNT NU_Read(PCFD fd,  UTINY *buf, UCOUNT count)					 /*__fn__*/
{
    PC_FILE *pfile;
    UCOUNT block_in_cluster;
    UCOUNT byte_offset_in_block;
    UCOUNT n_bytes;
    UCOUNT next_cluster;
    UCOUNT n_clusters;
    ULONG  block_to_read;
    DDRIVE *pdrive;
    ULONG  saved_ptr;
    ULONG  saved_ptr_block;        
    UCOUNT saved_ptr_cluster;        
    UCOUNT n_left;
    UCOUNT n_to_read;
    UCOUNT utemp;
    char   local_buf[512];
    UCOUNT ret_val;
    PC_FS_ENTER()     /* Must be last line in declarations */
    CHECK_USER(UCOUNT, ~0) /* Check if a valid user if multitasking */

    fs_user->p_errno = 0;    

    /* Get the FILE. Second argument is ignored */
    if ( (pfile = pc_fd2file(fd, NO)) == NULL)
    {
        fs_user->p_errno = PEBADF;
        ret_val = (UCOUNT) ~0;
        goto return_error;
    }
    /* return 0 bytes read if bad arguments */
    if (!count || !buf)
    {
        ret_val = 0;
        goto return_error;
    }

    if (pfile->fptr >= pfile->pobj->finode->fsize)    /* Dont read if done */
    {
        ret_val = 0;
        goto return_error;
    }

    pdrive = pfile->pobj->pdrive;
    PC_DRIVE_ENTER(pdrive->driveno, NO)  /* Register Drive in use */
    /* 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 = (UCOUNT) (pfile->pobj->finode->fsize - pfile->fptr);

    n_left = count;

    while (n_left)
    {
       block_in_cluster = (UCOUNT) (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 = (UCOUNT) ( (n_left + 511) >> 9 );
       n_clusters =(UCOUNT) ((n_to_read+pdrive->secpalloc-1) >> pdrive->log2_secpalloc);

        /* how many contiguous clusters can we get ? <= n_clusters */
       PC_FAT_ENTER(pdrive->driveno) 
       n_clusters = pc_get_chain(pdrive, pfile->fptr_cluster,
                                          &next_cluster, n_clusters);
       PC_FAT_EXIT(pdrive->driveno) 

       if (!n_clusters)
          goto ret_bad_f;

        /* Are we inside a block */
       if ( (pfile->fptr & 0x1ffL) || (n_left < 512) )
       {
           byte_offset_in_block = (UCOUNT) (pfile->fptr & 0x1ffL);
           /* READ */
           PC_DRIVE_IO_ENTER(pdrive->driveno)
           if (!pc_bdevsw[pdrive->driveno].io_proc(pdrive->driveno, block_to_read, local_buf, 1, YES) )
           {
                PC_DRIVE_IO_EXIT(pdrive->driveno)
                goto ret_bad_f;
           }
           PC_DRIVE_IO_EXIT(pdrive->driveno)
           /* Copy source data to the local buffer */
           n_bytes = (UCOUNT) (512 - byte_offset_in_block);
           if (n_bytes > n_left)
               n_bytes = n_left;
           copybuff(buf, &local_buf[byte_offset_in_block], 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 = (UCOUNT) (n_clusters << pdrive->log2_secpalloc);
               /* subtract out any leading blocks */
            n_to_read -= block_in_cluster;
                /* How many blocks yet to read */
            utemp = (UCOUNT) (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;

           /* READ */
                PC_DRIVE_IO_ENTER(pdrive->driveno)
                if (!pc_bdevsw[pdrive->driveno].io_proc(pdrive->driveno, block_to_read, buf, n_to_read,YES))
                {
                    PC_DRIVE_IO_EXIT(pdrive->driveno)
                    goto ret_bad_f;
                }
                PC_DRIVE_IO_EXIT(pdrive->driveno)
                n_bytes = (UCOUNT) (n_to_read << 9);
                buf += n_bytes;
                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 =(UCOUNT) ((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 */

    PC_INODE_EXIT(pfile->pobj->finode)
    PC_DRIVE_EXIT(pdrive->driveno)

    /* Restore the kernel state */
    PC_FS_EXIT()
    return(count);

ret_bad_f:
    /* Restore pointers and return */
    pfile->fptr = saved_ptr;
    pfile->fptr_block = saved_ptr_block;        
    pfile->fptr_cluster = saved_ptr_cluster;        
    fs_user->p_errno = PENOSPC;
    PC_INODE_EXIT(pfile->pobj->finode)
    PC_DRIVE_EXIT(pdrive->driveno)
    ret_val = (UCOUNT) ~0;
return_error:
    /* Restore the kernel state */
    PC_FS_EXIT()

⌨️ 快捷键说明

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