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

📄 drobj.c

📁 嵌入式操作系统Nucleus Plus中使用的文件系统
💻 C
📖 第 1 页 / 共 3 页
字号:
    BOOL ret_val;
    DOSINODE *pdinodes;
    FINODE lfinode;
    UCOUNT cluster;
    DATESTR crdate;
    BLKBUFF *pbuff;
    DDRIVE *pdrive;
    UTINY attr;

    pobj = NULL;
    ret_val = YES;
    
    if (!pmom)
        return (NULL);

    pdrive = pmom->pdrive;
    if (!pdrive)
        ret_val = NO;
    else if (attributes & ADIRENT)
    {
        /* Grab a new cluster and clear it. We optimize here (10/27/90).
           To minimize fragmentation we give clalloc a hint where to 
           start looking for new clusters */
        UCOUNT clbase = 0;
        if (!pc_isroot(pmom))
            clbase = pmom->finode->fcluster;

        /*Grab a cluster for a new dir and cleaer it */
        PC_FAT_ENTER(pdrive->driveno)
        cluster = pc_clalloc(pdrive, clbase);
        PC_FAT_EXIT(pdrive->driveno) 

         if (!cluster)
            ret_val = NO;
         else if (!pc_clzero( pdrive , cluster ) )
         {
            PC_FAT_ENTER(pdrive->driveno)
            pc_clrelease(pdrive , cluster);
            PC_FAT_EXIT(pdrive->driveno) 
            ret_val = NO;
         }
    }
    else
        cluster = 0;
    
    if (!ret_val)
    {
        return (NULL);
    }

    /* For a subdirectory. First make it a simple file. We will change the
       attribute after all is clean */

    attr = attributes;
    if (attr & ADIRENT)
        attr = ANORMAL;

    /* Allocate an empty DROBJ and FINODE to hold the new file */
    pobj = pc_allocobj();
    if (!pobj)
    {
        return (NULL);
    }
    /* Load the inode copy name,ext,attr,cluster, size,datetime*/
    pc_init_inode( pobj->finode, filename, fileext, 
                    attr, cluster, /*size*/ 0L ,pc_getsysdate(&crdate) );

    /* Convert pobj to native and stitch it in to mom */
    if (!pc_insert_inode(pobj , pmom))
    {
        PC_FAT_ENTER(pdrive->driveno)
        pc_clrelease(pdrive , cluster);
        PC_FAT_EXIT(pdrive->driveno) 
        pc_freeobj(pobj);
        return (NULL);
    }
        
    /* Now if we are creating subdirectory we have to make the DOT and DOT DOT
      inodes and then change pobj's attribute to ADIRENT
      The DOT and DOTDOT are not buffered inodes. We are simply putting
      the to disk  */
    if ( attributes & ADIRENT)
    {
        /* Set up a buffer to do surgery */
        pbuff = pc_init_blk( pdrive , pc_cl2sector(pdrive , cluster));
        if (!pbuff)
        {
            pc_freeobj(pobj);
            PC_FAT_ENTER(pdrive->driveno)    /* claim the fat for alloc */
            pc_clrelease(pdrive , cluster);
            PC_FAT_EXIT(pdrive->driveno) 
            return (NULL);
        }
        pdinodes = (DOSINODE *) &pbuff->data[0];
        /* Load DOT and DOTDOT in native form */
        /* DOT first. It points to the begining of this sector */
        pc_init_inode( &lfinode, ".", "", ADIRENT|ARCHIVE, 
                           cluster, /*size*/ 0L ,&crdate);
        /* And to the buffer in intel form */
        pc_ino2dos (pdinodes, &lfinode);

        /* Now DOTDOT points to mom's cluster */
        pc_init_inode( &lfinode, "..", "", ADIRENT|ARCHIVE, 
                      pc_sec2cluster( pdrive , pobj->blkinfo.my_frstblock),
                     /*size*/ 0L ,&crdate);
        /* And to the buffer in intel form */
        pc_ino2dos ( ++pdinodes, &lfinode );
        
        /* Write the cluster out */
        if ( !pc_write_blk ( pbuff ) )
        {
            pc_free_buf(pbuff,YES);         /* Error. Chuck the buffer */
            pc_freeobj(pobj);
            PC_FAT_ENTER(pdrive->driveno)   /* claim the fat for alloc */
            pc_clrelease(pdrive , cluster);
            PC_FAT_EXIT(pdrive->driveno) 
            return (NULL);
        }
        else
            pc_free_buf(pbuff,NO);

        /* And write the node out with the original attributes */
        pobj->finode->fattribute = attributes;
        pobj->finode->fattribute |= ARCHIVE;

        /* Convert to native and overwrite the existing inode*/
        if (!pc_update_inode(pobj))
        {
            pc_freeobj(pobj);
            PC_FAT_ENTER(pdrive->driveno)   /* claim the fat for alloc */
            pc_clrelease(pdrive , cluster);
            PC_FAT_EXIT(pdrive->driveno) 
            return (NULL);
        }
    }

    PC_FAT_ENTER(pdrive->driveno)
    ret_val = pc_flushfat(pdrive->driveno);
    PC_FAT_EXIT(pdrive->driveno) 

    if (ret_val)
    {
        return (pobj);
    }
    else
    {
        pc_freeobj(pobj);
        return (NULL);
    }
}

/***************************************************************************
    PC_INSERT_INODE - Insert a new inode into an existing directory inode.

Description
     Take mom , a fully defined DROBJ, and pobj, a DROBJ with a finode
     containing name, ext, etc, but not yet stitched into the inode buffer
     pool, and fill in pobj and its inode, write it to disk and make the inode
     visible in the inode buffer pool. (see also pc_mknode() )


Returns
    Returns YES if all went well, NO on a write error, disk full error or 
    root directory full.

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

BOOL pc_insert_inode( DROBJ *pobj, DROBJ *pmom)                      /*__fn__*/
{
    BLKBUFF *pbuff;
    DIRBLK *pd;
    DOSINODE *pi;
    COUNT i;
    BOOL retval;
    UCOUNT cluster;

    /* Set up pobj */   
    pobj->pdrive = pmom->pdrive;
    pobj->isroot = NO;
    pd = &pobj->blkinfo;

    /* Now get the start of the dir */
    pd->my_block = pd->my_frstblock = pc_firstblock(pmom);

    if (!pd->my_block)
    {
        return (NO);
    }
    else
        pd->my_index = 0;

    /* Read the data */
    pbuff = pc_read_obj(pobj);
    while (pbuff)
    {
        i = pd->my_index = 0;
        pi = (DOSINODE *) &pbuff->data[0];
        /* look for a slot */
        while ( i < INOPBLOCK )
        {
            /* End of dir if name is 0 */
            if ( (pi->fname[0] == '\0') || (pi->fname[0] == PCDELETE) )
            {
                pd->my_index = i;

                /* Update the DOS disk */
                pc_ino2dos( pi, pobj->finode );
                /* Write the data */
                retval =  pc_write_obj( pobj );
                /* Mark the inode in the inode buffer */
                if (retval)
                    pc_marki(pobj->finode , pobj->pdrive , pd->my_block, 
                             pd->my_index );

                pc_free_buf(pbuff, !retval);
                return (retval);
            }
            i++;
            pi++;
        }
        /* Not in that block. Try again */
        pc_free_buf(pbuff,NO);
        /* Update the objects block pointer */
        if (!pc_next_block(pobj))
            break;
        pbuff = pc_read_obj(pobj);
    }

    /* Hmmm - root full ??. This is a problem */
    if (pc_isroot(pmom))
        return (NO);

    /* Ok:There ar no slots in mom. We have to make one. And copy our stuf in*/
    PC_FAT_ENTER(pobj->pdrive->driveno)   /* claim the fat for alloc */
    cluster = pc_clgrow(pobj->pdrive , pmom->finode->fcluster);
    PC_FAT_EXIT(pobj->pdrive->driveno) 

    if (!cluster)
        return (NO);

    /* Zero out the cluster  */
    if (!pc_clzero( pobj->pdrive , cluster ) )
    {
        PC_FAT_ENTER(pobj->pdrive->driveno)  /* claim the fat for alloc */
        pc_clrelease(pobj->pdrive , cluster);
        PC_FAT_EXIT(pobj->pdrive->driveno) 
        return (NO);
    }

    /* Don't forget where the new item is */
    pd->my_block = pc_cl2sector(pobj->pdrive , cluster);
    pd->my_index = 0;

    /* Copy the item into the first block */
    pbuff = pc_init_blk( pobj->pdrive , pd->my_block);
    if (!pbuff)
    {
        PC_FAT_ENTER(pobj->pdrive->driveno)  /* claim the fat for alloc */
        pc_clrelease(pobj->pdrive , cluster);
        PC_FAT_EXIT(pobj->pdrive->driveno) 
        return (NO);
    }

    pc_ino2dos (  (DOSINODE *) &pbuff->data[0] ,  pobj->finode ) ;

    /* Write it out */
    if ( !pc_write_blk ( pbuff ) )
    {
        pc_free_buf(pbuff,YES);
        PC_FAT_ENTER(pobj->pdrive->driveno)   /* claim the fat for alloc */
        pc_clrelease(pobj->pdrive , cluster);
        PC_FAT_EXIT(pobj->pdrive->driveno) 
        return (NO);
    }

    /* We made a new slot. Mark the inode as belonging there */
    pc_marki(pobj->finode , pobj->pdrive , pd->my_block, pd->my_index );

    pc_free_buf(pbuff,NO);
    return (YES);
}


/***************************************************************************
    PC_RMNODE - Delete an inode unconditionally.

 Description
    Delete the inode at pobj and flush the file allocation table. Does not
    check file permissions or if the file is already open. (see also pc_unlink
    and pc_rmdir). The inode is marked deleted on the disk and the cluster
    chain associated with the inode is freed. (Un-delete won't work)

 Returns
    Returns YES if it successfully deleted the inode an flushed the fat.

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

/* Delete a file / dir or volume. Don't check for write access et al */
BOOL pc_rmnode( DROBJ *pobj)                                          /*__fn__*/
{
    UCOUNT cluster;
    BOOL   ret_val;

    /* Don't delete anything that has multiple links */
    if (pobj->finode->opencount > 1)
    {
        pc_report_error(PCERR_REMINODE);
        return (NO);
    }

    /* Mark it deleted and unlink the cluster chain */
    pobj->finode->fname[0] = PCDELETE;
    cluster = pobj->finode->fcluster;

    /* We free up store right away. Don't leave cluster pointer 
    hanging around to cause problems. */
    pobj->finode->fcluster = 0;
    if (pc_update_inode(pobj))
    {
        /* And clear up the space */
        PC_FAT_ENTER(pobj->pdrive->driveno)
        pc_freechain(pobj->pdrive, cluster);
        ret_val = pc_flushfat(pobj->pdrive->driveno);
        PC_FAT_EXIT(pobj->pdrive->driveno) 

        return (ret_val);
    }
     /* If it gets here we had a probblem */
    return(NO);
}

/**************************************************************************
    PC_UPDATE_INODE - Flush an inode to disk
                       
Summary

Description
    Read the disk inode information stored in pobj and write it to
    the block and offset on the disk where it belongs. The disk is
    first read to get the block and then the inode info is merged in
    and the block is written. (see also pc_mknode() )

Returns
    Returns YES if all went well, no on a write error.

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

/* Take a DROBJ that contains correct my_index & my_block. And an inode.
   Load the block. Copy the inode in and write it back out */
BOOL pc_update_inode( DROBJ *pobj)                                   /*__fn__*/
{
    BLKBUFF *pbuff;
    DOSINODE *pi;
    COUNT i;
    BOOL retval;
    DIRBLK *pd;
    DATESTR crdate;

    pd = &pobj->blkinfo;
    i   = pd->my_index;
    if ( i >= INOPBLOCK || i < 0 )  /* Index into block */
        return (NO);

    /* Set the archive bit and the date */
    pobj->finode->fattribute |= ARCHIVE;
    pc_getsysdate(&crdate);
    pobj->finode->ftime = crdate.time;
    pobj->finode->fdate = crdate.date;

    /* Read the data */
    pbuff = pc_read_obj(pobj);
    if (pbuff)
    {
        pi = (DOSINODE *) &pbuff->data[0];
        /* Copy it off and write it */
        pc_ino2dos( (pi+i), pobj->finode );
        retval =  pc_write_obj( pobj );
        /* Free the buff. If retval == NO(fail), pass a yes to
           freebuf so it will discard the buffer. */
        pc_free_buf(pbuff, !retval);
        return (retval);
    }
    return (NO);
}

/***************************************************************************
    PC_READ_OBJ - Assign an initialized BLKBUFF to a DROBJ

Description
    Use the pdrive and myblock fields of pobj to determine what block to 
    read. Add block to the buffer pool, if needed, point pobj at the
    buffer and return the buffer.

    Note: After reading, you "own" the buffer. You must release it by
    calling pc_free_buff() before others can use it.

 Returns
    Returns a valid pointer or NULL if block not found and not readable.
****************************************************************************/


BLKBUFF *pc_read_obj(DROBJ *pobj)                                     /*__fn__*/
{
    if (!pobj)
        return (NULL);
    pobj->pblkbuff = pc_read_blk(pobj->pdrive, pobj->blkinfo.my_block);
    return(pobj->pblkbuff);
}

/***************************************************************************
    PC_WRITE_OBJ - Write a DROBJ's BLKBUFF to disk

Description
    Write the data in the BLKBUFF for pobj to disk.

 Returns
    Returns YES if the write succeeded.

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

BOOL pc_write_obj(DROBJ *pobj)                                     /*__fn__*/
{
    if (!pobj)
        return (NO);
    return (pc_write_blk(pobj->pblkbuff));
}



/*************************************************************************
    PC_GET_ROOT -  Create the special ROOT object for a drive.
 Description
    Use the information in pdrive to create a special object for accessing
    files in the root directory.

 Returns
    Returns a pointer to a DROBJ, or NULL if no core available.
****************************************************************************/

/* Initialize the special "root" object 
   Note: We do not read any thing in here we just set up 
   the block pointers. */

DROBJ *pc_get_root( DDRIVE *pdrive)                                   /*__fn__*/
{
    DIRBLK *pd;
    DROBJ *pobj;
    FINODE *pfi;

    pobj = pc_allocobj();
    if (!pobj)
        return (NULL);

    pfi = pc_scani(pdrive, 0, 0);

    if (pfi)
    {
        pc_freei(pobj->finode);
        pobj->finode = pfi;
    }
    else    /* No inode in the inode list. Copy the data over
               and mark where it came from */
    {
        pc_marki(pobj->finode , pdrive , 0, 0);
    }
    /* Add a TEST FOR DRIVE INIT Here later */
    pobj->pdrive = pdrive;
    /* Set up the tree stuf so we know it is the root */
    pd = &pobj->blkinfo;
    pd->my_frstblock = pdrive->rootblock;
    pd->my_block = pdrive->rootblock;
    pd->my_index = 0;
    pobj->isroot = YES;

    return (pobj);
}

⌨️ 快捷键说明

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