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

📄 drobj.c

📁 嵌入式操作系统Nucleus Plus中使用的文件系统
💻 C
📖 第 1 页 / 共 3 页
字号:
/****************************************************************************
    PC_FIRSTBLOCK -  Return the absolute block number of a directory's 
                     contents.
 Description
    Returns the block number of the first inode in the subdirectory. If
    pobj is the root directory the first block of the root will be returned.

 Returns
    Returns 0 if the obj does not point to a directory, otherwise the
    first block in the directory is returned.

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

/* Get  the first block of a root or subdir */
BLOCKT pc_firstblock( DROBJ *pobj)                                   /*__fn__*/
{
    if (!pc_isadir(pobj))
        return (BLOCKEQ0);

    /* Root dir ? */
    if (pobj->isroot)
        return (pobj->blkinfo.my_frstblock);
    else
        return (pc_cl2sector(pobj->pdrive , pobj->finode->fcluster) );
}

/***************************************************************************
    PC_NEXT_BLOCK - Calculate the next block owned by an object.

 Description
    Find the next block owned by an object in either the root or a cluster
    chain and update the blockinfo section of the object.

 Returns
    Returns YES or NO on end of chain.
                
*****************************************************************************/


/* Calculate the next block in an object */
BOOL pc_next_block( DROBJ *pobj)                                    /*__fn__*/
{
    BLOCKT nxt;

    nxt = pc_l_next_block(pobj->pdrive, pobj->blkinfo.my_block);

    if (nxt)
    {
        pobj->blkinfo.my_block = nxt;
        return (YES);
    }
    else
        return (NO);
}

/**************************************************************************
    PC_L_NEXT_BLOCK - Calculate the next block in a chain.

 Description
    Find the next block in either the root or a cluster chain.

 Returns
    Returns 0 on end of root dir or chain.

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

    /* Return the next block in a chain */
BLOCKT pc_l_next_block(DDRIVE *pdrive, BLOCKT curblock)               /*__fn__*/
{
    UCOUNT cluster;

    /* If the block is in the root area */
    if (curblock < pdrive->firstclblock)
    {
        if (curblock < pdrive->rootblock)
            return (BLOCKEQ0);
        else if (++curblock < pdrive->firstclblock)
            return (curblock);
        else
            return (BLOCKEQ0);
    }
        /* In cluster space */
    else
    {
        if (curblock >= pdrive->numsecs)
            return (BLOCKEQ0);
        /* Get the next block */
        curblock += 1;

        /* If the next block is not on a cluster edge then it must be
           in the same cluster as the current. - otherwise we have to
           get the firt block from the next cluster in the chain */
        if (pc_sec2index(pdrive, curblock))
            return (curblock);
        else
        {
            curblock -= 1;
            /* Get the old cluster number - No error test needed */
            cluster = pc_sec2cluster(pdrive,curblock);
            /* Consult the fat for the next cluster */
            PC_FAT_ENTER(pdrive->driveno)  /* claim the fat for alloc */
            cluster = pc_clnext(pdrive, cluster);
            PC_FAT_EXIT(pdrive->driveno) 
            if (!cluster)
                return (BLOCKEQ0); /* End of chain */
            else
                return (pc_cl2sector(pdrive, cluster));
        }
    }
}
 
/**************************************************************************
    PC_MARKI -  Set dr:sec:index info and stitch a FINODE into the inode list


Description
    Each inode is uniquely determined by DRIVE, BLOCK and Index into that 
    block. This routine takes an inode structure assumed to contain the
    equivalent of a DOS directory entry. And stitches it into the current
    active inode list. Drive block and index are stored for later calls
    to pc_scani and the inode's opencount is set to one.

Returns
    Nothing

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

/* Take an unlinked inode and link it in to the inode chain. Initialize
   the open count and sector locater info. */   
VOID pc_marki( FINODE *pfi, DDRIVE *pdrive, BLOCKT sectorno, COUNT  index)/*__fn__*/
{
    pfi->my_drive = pdrive;
    pfi->my_block = sectorno;
    pfi->my_index = index;
    pfi->opencount = 1;

    /* Stitch the inode at the front of the list */
    if (inoroot)
        inoroot->pprev = pfi;

    pfi->pprev = NULL;
    pfi->pnext = inoroot;

    inoroot = pfi;
}


/**************************************************************************
    PC_SCANI -  Search for an inode in the internal inode list.

Description
    Each inode is uniquely determined by DRIVE, BLOCK and Index into that 
    block. This routine searches the current active inode list to see
    if the inode is in use. If so the opencount is changed and a pointer is 
    returned. This guarantees that two processes will work on the same 
    information when manipulating the same file or directory.

Returns
    A pointer to the FINODE for pdrive:sector:index or NULL if not found

****************************************************************************/
        
/* See if the inode for drive,sector , index is in the list. If so..
   bump its open count and return it. Else return NULL */

FINODE *pc_scani( DDRIVE *pdrive, BLOCKT sectorno, COUNT index)      /*__fn__*/
{
    FINODE *pfi;

    pfi = inoroot;
    while (pfi)
    {
        if ( (pfi->my_drive == pdrive) &&
             (pfi->my_block == sectorno) &&
             (pfi->my_index == index) )
        {
            pfi->opencount += 1;
            return (pfi);
        }
        pfi = pfi->pnext;
    }
    return (NULL);
}

/**************************************************************************
    PC_ALLOCOBJ -  Allocate a DROBJ structure
 Description
    Allocates and zeroes the space needed to store a DROBJ structure. Also
    allocates and zeroes a FINODE structure and links the two via the
    finode field in the DROBJ structure.

 Returns
    Returns a valid pointer or NULL if no more core.

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

DROBJ *pc_allocobj()                                                /*__fn__*/
{
    DROBJ *pobj;

    /* Alloc a DROBJ */
    pobj = pc_memory_drobj(NULL);
    if (!pobj)
        return (NULL);
    else
    {
        pobj->finode = pc_alloci();
        if (!pobj->finode)
        {
            /* Free the DROBJ */
            pc_memory_drobj(pobj);
            return(NULL);
        }
        else
        {
            return (pobj);
        }
    }
}           

/**************************************************************************
    PC_ALLOCI -  Allocate a FINODE structure
                       
 Description
    Allocates and zeroes a FINODE structure.

 Returns
    Returns a valid pointer or NULL if no more core.

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

FINODE *pc_alloci()                                                 /*__fn__*/
{
    return(pc_memory_finode(NULL));
}


/**************************************************************************
    PC_FREE_ALL_I -  Release all inode buffers associated with a drive.
Description
    Called by pc_dskclose().
    For each internally buffered finode (dirent) check if it exists on
    pdrive. If so delete it. In debug mode print a message since all
    finodes should be freed before pc_dskclose is called.
Returns
    Nothing
****************************************************************************/

VOID pc_free_all_i( DDRIVE *pdrive)                                 /*__fn__*/
{
    FINODE *pfi;

    pfi = inoroot;
    while (pfi)
    {
        if (pfi->my_drive == pdrive)
        {
            /* Set the opencount to 1 so freei releases the inode */
            pfi->opencount = 1;
            pc_report_error(PCERR_FREEINODE);
            pc_freei(pfi);
            /* Since we changed the list go back to the top */
            pfi = inoroot;
        }
        else
            pfi = pfi->pnext;
    }
}

/*****************************************************************************
    PC_FREEI -  Release an inode from service

Description
    If the FINODE structure is only being used by one file or DROBJ, unlink it
    from the internal active inode list and return it to the heap; otherwise
    reduce its open count.

 Returns
    Nothing
    
****************************************************************************/

VOID pc_freei( FINODE *pfi)                                         /*__fn__*/
{
    if (!pfi)
    {
        pc_report_error(PCERR_FREEINODE);
        return;
    }
    if (pfi->opencount)
    {
        if (--pfi->opencount)/* Decrement opencount and return if non zero */
            return;
        else
        {
            if (pfi->pprev)     /* Pont the guy behind us at the guy in front*/
            {
                pfi->pprev->pnext = pfi->pnext;
            }
            else
            {
                inoroot = pfi->pnext; /* No prev, we were at the front so 
                                         make the next guy the front */
            }

            if (pfi->pnext)           /* Make the next guy point behind */
            {
                pfi->pnext->pprev = pfi->pprev;
            }
        }
    }
    /* release the core */
    pc_memory_finode(pfi);
}


/***************************************************************************
    PC_FREEOBJ -  Free a DROBJ structure
                       
 Description
    Return a drobj structure to the heap. Calls pc_freei to reduce the
    open count of the finode structure it points to and return it to the
    heap if appropriate.

 Returns
    Nothing

    
****************************************************************************/
    
VOID pc_freeobj( DROBJ *pobj)                                    /*__fn__*/
{
    if (pobj)
    {
        pc_freei(pobj->finode);
        /* Release the core */
        pc_memory_drobj(pobj);
    }
    else
        pc_report_error(PCERR_FREEDROBJ);
}

/***************************************************************************
    PC_DOS2INODE - Convert a dos disk entry to an in memory inode.

 Description
    Take the data from pbuff which is a raw disk directory entry and copy
    it to the inode at pdir. The data goes from INTEL byte ordering to 
    native during the transfer.

 Returns
    Nothing
****************************************************************************/

/* Convert a dos inode to in mem form.*/
VOID pc_dos2inode (FINODE *pdir, DOSINODE *pbuff)                   /*__fn__*/
{
    copybuff(&pdir->fname[0],&pbuff->fname[0],8);
    copybuff(&pdir->fext[0],&pbuff->fext[0],3);
    pdir->fattribute = pbuff->fattribute;
    copybuff(&pdir->resarea[0],&pbuff->resarea[0], 10);
    pdir->ftime = to_WORD((UTINY *) &pbuff->ftime);
    pdir->fdate = to_WORD((UTINY *) &pbuff->fdate);
    pdir->fcluster = to_WORD((UTINY *) &pbuff->fcluster);
    pdir->fsize = to_DWORD((UTINY *) &pbuff->fsize);
}

/**************************************************************************
    PC_INIT_INODE -  Load an in memory inode up with user supplied values.

 Description
    Take an uninitialized inode (pdir) and fill in some fields. No other
    processing is done. This routine simply copies the arguments into the
    FINODE structure. 

    Note: filename & fileext do not need null termination.

 Returns
    Nothing
****************************************************************************/

    /* Load an in memory inode up with user supplied values*/
VOID pc_init_inode(FINODE *pdir, TEXT *filename, TEXT *fileext, UTINY attr, UCOUNT cluster, ULONG size, DATESTR *crdate)       /*__fn__*/
{
    /* Copy the file names and pad with ' ''s */
    pc_cppad(pdir->fname,(UTEXT*)filename,8);
    pc_cppad(pdir->fext,(UTEXT*)fileext,3);
    pdir->fattribute = attr;
    pc_memfill(&pdir->resarea[0],10, '\0');

    pdir->ftime = crdate->time;
    pdir->fdate = crdate->date;
    pdir->fcluster = cluster;
    pdir->fsize = size;
}

/***************************************************************************
    PC_INO2DOS - Convert  an in memory inode to a dos disk entry.

 Description
    Take in memory native format inode information and copy it to a
    buffer. Translate the inode to INTEL byte ordering during the transfer.

 Returns
    Nothing

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

/* Un-Make a disk directory entry */
/* Convert an inmem inode to dos  form.*/
VOID pc_ino2dos (DOSINODE *pbuff, FINODE *pdir)                     /*__fn__*/
{
    copybuff(&pbuff->fname[0],&pdir->fname[0],8);
    if (pbuff->fname[0] == (UTINY) 0xE5)
        pbuff->fname[0] = PCDELETE;
    copybuff(&pbuff->fext[0],&pdir->fext[0],3);
    pbuff->fattribute = pdir->fattribute;
    copybuff(&pbuff->resarea[0],&pdir->resarea[0], 10);
    fr_WORD((UTINY *) &pbuff->ftime,pdir->ftime);
    fr_WORD((UTINY *) &pbuff->fdate,pdir->fdate);
    fr_WORD((UTINY *) &pbuff->fcluster,pdir->fcluster);
    fr_DWORD((UTINY *) &pbuff->fsize,pdir->fsize);
}


/**************************************************************************
    PC_ISADIR -  Test a DROBJ to see if it is a root or subdirectory

 Description
    Looks at the appropriate elements in pobj and determines if it is a root
    or subdirectory.

 Returns
    Returns NO if the obj does not point to a directory.

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

BOOL pc_isavol( DROBJ *pobj)                                        /*__fn__*/
{
    return(pobj->finode->fattribute & AVOLUME);
}

/**************************************************************************
    PC_ISADIR -  Test a DROBJ to see if it is a root or subdirectory

 Description
    Looks at the appropriate elements in pobj and determines if it is a root
    or subdirectory.

 Returns
    Returns NO if the obj does not point to a directory.

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

BOOL pc_isadir( DROBJ *pobj)                                         /*__fn__*/
{
    return ( (pobj->isroot) || (pobj->finode->fattribute & ADIRENT)  );
}

/**************************************************************************
    PC_ISROOT -  Test a DROBJ to see if it is the root directory

 Description
    Looks at the appropriate elements in pobj and determines if it is a root
    directory.

 Returns
    Returns NO if the obj does not point to the root directory.

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

/* Get  the first block of a root or subdir */
BOOL pc_isroot( DROBJ *pobj)                                        /*__fn__*/
{
    return(pobj->isroot);
}

⌨️ 快捷键说明

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