예제 #1
0
파일: lflClose.c 프로젝트: disrvptor/xinu
/*------------------------------------------------------------------------
 * lflClose  --  close a file by flushing output and freeing device entry
 *------------------------------------------------------------------------
 */
devcall	lflClose (
	  struct dentry *devptr		/* entry in device switch table */
	)
{
	struct	lflcblk	*lfptr;		/* ptr to open file table entry	*/

	/* Obtain exclusive use of the file */

	lfptr = &lfltab[devptr->dvminor];
	wait(lfptr->lfmutex);

	/* If file is not open, return an error */

	if (lfptr->lfstate != LF_USED) {
		signal(lfptr->lfmutex);
		return SYSERR;
	}

	/* Write index or data blocks to disk if they have changed */

	if (Lf_data.lf_dirdirty || lfptr->lfdbdirty || lfptr->lfibdirty) {
		lfflush(lfptr);
	}

	/* Set device state to FREE and return to caller */

	lfptr->lfstate = LF_FREE;
	signal(lfptr->lfmutex);
	return OK;
}
예제 #2
0
파일: lflClose.c 프로젝트: sha8e/purdue
static status lflCloseHelper(char *fileName,struct lflcblk* lfptr)
{
    struct lflcblk * dirCblk = &lfltab[Nlfl+1];	/*last entry is used for modifying the directory in which file is getting created.*/
    struct lflcblk* parentDirCblk = &lfltab[Nlfl];	/*second last entry is used for parent of the directory in which file is getting created*/
    struct dentry devPtr;
    struct dentry parentDevPtr;
    struct ldentry tempEntry;
    struct ldentry*dirEntry = &tempEntry;
    devPtr.dvminor=Nlfl+1;
    parentDevPtr.dvminor=Nlfl;
    bool8 found = 0;
    while(lflRead(&devPtr,(char*)dirEntry,sizeof(struct ldentry)) == sizeof(struct ldentry))
    {
        if (strcmp(dirEntry->ld_name,fileName) && dirEntry->ld_used)
        {
            found = 1;
            break;
        }
    }
    if (!found)
    {
        dirCblk->lfstate = LF_FREE;
        parentDirCblk->lfstate = LF_FREE;
        return SYSERR;
    }

    dirEntry->ld_ilist = lfptr->lffirstib;
    dirEntry->ld_size = lfptr->lfsize;

    uint32 writePos = dirCblk->lfpos - sizeof(struct ldentry);

    lflSeek(&devPtr,writePos);

    if (lflWrite(&devPtr,(char*)dirEntry,sizeof(struct ldentry)) == SYSERR)
    {
        dirCblk->lfstate = LF_FREE;
        parentDirCblk->lfstate = LF_FREE;
        return SYSERR;
    }

    /*Close the directory*/
    if (lfflush(dirCblk) == SYSERR)
    {
        dirCblk->lfstate = LF_FREE;
        parentDirCblk->lfstate = LF_FREE;

        return SYSERR;
    }
    dirCblk->lfstate = LF_FREE;
    parentDirCblk->lfstate = LF_FREE;

    return OK;

}
예제 #3
0
/*------------------------------------------------------------------------
 * lfsetup  -  Set a file's index block and data block for the current
 *		 file position (assumes file mutex held)
 *------------------------------------------------------------------------
 */
status	lfsetup (
	  struct lflcblk  *lfptr	/* Pointer to slave file device	*/
	)
{
	dbid32	dnum;			/* Data block to fetch		*/
	ibid32	ibnum;			/* I-block number during search	*/
	struct	ldentry	*ldptr;		/* Ptr to file entry in dir.	*/
	struct	lfiblk	*ibptr;		/* Ptr to in-memory index block	*/
	uint32	newoffset;		/* Computed data offset for	*/
					/*   next index block		*/
	int32	dindex;			/* Index into array in an index	*/
					/*   block			*/


	/* Obtain exclusive access to the directory */

	wait(Lf_data.lf_mutex);

	/* Get pointers to in-memory directory, file's entry in the	*/
	/*	directory, and the in-memory index block		*/

	ldptr = lfptr->lfdirptr;
	ibptr = &lfptr->lfiblock;

	/* If existing index block or data block changed, write to disk	*/

	if (lfptr->lfibdirty || lfptr->lfdbdirty) {
		lfflush(lfptr);
	}
	ibnum = lfptr->lfinum;		/* Get ID of curr. index block	*/

	/* If there is no index block in memory (e.g., because the file	*/
	/*	was just opened), either load the first index block of	*/
	/*	the file or allocate a new first index block		*/

	if (ibnum == LF_INULL) {

		/* Check directory entry to see if index block exists	*/

		ibnum = ldptr->ld_ilist;
		if (ibnum == LF_INULL) { /* Empty file - get new i-block*/
			ibnum = lfiballoc();
			lfibclear(ibptr, 0);
			ldptr->ld_ilist = ibnum;
			lfptr->lfibdirty = TRUE;
		} else {		/* Nonempty - read first i-block*/
	 		lfibget(Lf_data.lf_dskdev, ibnum, ibptr);
		}
		lfptr->lfinum = ibnum;

	/* Otherwise, if current file position has been moved to an	*/
	/*   offset before the current index block, start at the	*/
	/*   beginning of the index list for the file			*/

	} else if (lfptr->lfpos < ibptr->ib_offset) {

		/* Load initial index block for the file (we know that	*/
		/*	at least one index block exists)		*/
	
		ibnum = ldptr->ld_ilist;
		lfibget(Lf_data.lf_dskdev, ibnum, ibptr);
		lfptr->lfinum = ibnum;
	}

	/* At this point, an index block is in memory, but may cover	*/
	/*  an offset less than the current file position.  Loop until	*/
	/*  the index block covers the current file position.		*/

	while ((lfptr->lfpos & ~LF_IMASK) > ibptr->ib_offset ) {
		ibnum = ibptr->ib_next;
		if (ibnum == LF_INULL) {
			/* Allocate new index block to extend file */
			ibnum = lfiballoc();
			ibptr->ib_next = ibnum;
			lfibput(Lf_data.lf_dskdev, lfptr->lfinum, ibptr);
			lfptr->lfinum = ibnum;
			newoffset = ibptr->ib_offset + LF_IDATA;
			lfibclear(ibptr, newoffset);
			lfptr->lfibdirty = TRUE;
		} else {
			lfibget(Lf_data.lf_dskdev, ibnum, ibptr);
			lfptr->lfinum = ibnum;
		}
		lfptr->lfdnum = LF_DNULL; /* Invalidate old data block */
	}

	/* At this point, the index block in lfiblock covers the	*/
	/*  current file position (i.e., position lfptr->lfpos).  The	*/
	/*  next step consists of loading the correct data block.	*/

	dindex = (lfptr->lfpos & LF_IMASK) >> 9;

	/* If data block index does not match current data block, read	*/
	/*   the correct data block from disk				*/

	dnum = lfptr->lfiblock.ib_dba[dindex];
	if (dnum == LF_DNULL) {		/* Allocate new data block */
		dnum = lfdballoc((struct lfdbfree *)&lfptr->lfdblock);
		lfptr->lfiblock.ib_dba[dindex] = dnum;
		lfptr->lfibdirty = TRUE;
	} else if ( dnum != lfptr->lfdnum) {
		read(Lf_data.lf_dskdev, (char *)lfptr->lfdblock, dnum);
		lfptr->lfdbdirty = FALSE;
	}
	lfptr->lfdnum = dnum;

	/* Use current file offset to set the pointer to the next byte	*/
	/*   within the data block					*/

	lfptr->lfbyte = &lfptr->lfdblock[lfptr->lfpos & LF_DMASK];
	signal(Lf_data.lf_mutex);
	return OK;
}
예제 #4
0
/*------------------------------------------------------------------------
 * lftruncate  -  truncate a file by freeing its index and data blocks
 *			(assumes directory mutex held)
 *------------------------------------------------------------------------
 */
status	lftruncate (
	  struct lflcblk *lfptr		/* ptr to file's cntl blk entry	*/
	)
{
	//struct	ldentry	*ldptr;		/* pointer to file's dir. entry	*/
	struct	lfiblk	iblock;		/* buffer for one index block	*/
	ibid32	ifree;			/* start of index blk free list	*/
	ibid32	firstib;		/* first index blk of the file	*/
	ibid32	nextib;			/* walks down list of the	*/
					/*   file's index blocks	*/
	dbid32	nextdb;			/* next data block to free	*/
	int32	i;			/* moves through data blocks in	*/
					/*   a given index block	*/

	//ldptr = lfptr->lfdirptr;	/* Get pointer to dir. entry	*/
	if (lfptr->lfsize == 0) {	/* file is already empty */
		return OK;
	}

	/* Clean up the open local file first */

	if ( (lfptr->lfibdirty) || (lfptr->lfdbdirty) ) {
		lfflush(lfptr);
	}
	lfptr->lfpos = 0;
	lfptr->lfinum = LF_INULL;
	lfptr->lfdnum = LF_DNULL;
	lfptr->lfbyte = &lfptr->lfdblock[LF_BLKSIZ];

	/* Obtain ID of first index block on free list */

	ifree = Lf_data.lf_dir.lfd_ifree;

	/* Record file's first i-block and clear directory entry */

	firstib = lfptr->lffirstib;
	lfptr->lffirstib= LF_INULL;
	lfptr->lfsize = 0;
	Lf_data.lf_dirdirty = TRUE;

	/* Walk along index block list, disposing of each data block	*/
	/*  and clearing the corresponding pointer.  A note on loop	*/
	/*  termination: last pointer is set to ifree below.		*/

	for (nextib=firstib; nextib!=ifree; nextib=iblock.ib_next) {

		/* Obtain a copy of current index block from disk	*/

		lfibget(Lf_data.lf_dskdev, nextib, &iblock);

		/* Free each data block in the index block		*/

		for (i=0; i<LF_IBLEN; i++) {	/* for each d-block	*/

			/* Free the data block */

			nextdb = iblock.ib_dba[i];
			if (nextdb != LF_DNULL) {
				lfdbfree(Lf_data.lf_dskdev, nextdb);
			}

			/* Clear entry in i-block for this d-block	*/

				iblock.ib_dba[i] = LF_DNULL;
		}

		/* Clear offset (just to make debugging easier)		*/

		iblock.ib_offset = 0;

		/* For the last index block on the list, make it point	*/
		/*	to the current free list			*/

		if (iblock.ib_next == LF_INULL) {
			iblock.ib_next = ifree;
		}

		/* Write cleared i-block back to disk */

		lfibput(Lf_data.lf_dskdev, nextib, &iblock);
	}

	/* Last index block on the file list now points to first node	*/
	/*   on the current free list.  Once we make the free list	*/
	/*   point to the first index block on the file list, the	*/
	/*   entire set of index blocks will be on the free list	*/

	Lf_data.lf_dir.lfd_ifree = firstib;

	/* Indicate that directory has changed and return */

	Lf_data.lf_dirdirty = TRUE;
	
	return OK;
}
예제 #5
0
파일: touchdir.c 프로젝트: BridgeNY/purdue
/*
 * Creates an entry for file/directory in the directory currently loaded in
 * lfltab[Nllfl+1] and updates the size of the parent directory.
 * name is the name of the file/directory,type identifies whether we are
 * creating a file or directory and isReplace tells us whether we are updating
 * an existing unused entry or adding a new entry
 */
status touchdir(char*name,byte type,struct ldentry*dirEntry,bool8 isReplace)
{
	struct lflcblk * dirCblk = &lfltab[Nlfl+1];	/*last entry is used for modifying the directory in which file is getting created.*/
	struct lflcblk* parentDirCblk = &lfltab[Nlfl];	/*second last entry is used for parent of the directory in which file is getting created*/
	struct dentry devPtr;
	struct dentry parentDevPtr;

	devPtr.dvminor=Nlfl+1;	
	parentDevPtr.dvminor=Nlfl;	

	/*
	 * Initialize the entry
	 */
	dirEntry->ld_size = 0;
	dirEntry->ld_ilist = LF_INULL;
	dirEntry->ld_type = type;
	dirEntry->ld_used = true;
	strcpy(dirEntry->ld_name,name);

	if (lflWrite(&devPtr,(char*)dirEntry,sizeof(struct ldentry)) == SYSERR)
	{
		dirCblk->lfstate = LF_FREE;
		parentDirCblk->lfstate = LF_FREE;
		return SYSERR;
	}
	/*Close the current directory*/
	if (lfflush(dirCblk) == SYSERR)
	{
		dirCblk->lfstate = LF_FREE;
		parentDirCblk->lfstate = LF_FREE;
		return SYSERR;
	}
	/*
	 * If we reused an existing entry then we are done.
	 */
	if (isReplace)
	{
		dirCblk->lfstate = LF_FREE;
		parentDirCblk->lfstate = LF_FREE;
		return OK;
	}
	/* 
	 * Othewise increment the size of the parent directory
	 */
	/*
	 * entry got added in the root directory so there is no
	 * grandparent.
	 */
	if (LF_FREE == parentDirCblk->lfstate)
	{
		/*One entry got added to the root directory*/
		dirCblk->lfstate = LF_FREE;

		wait(Lf_data.lf_mutex);
		Lf_data.lf_dir.lfd_size += sizeof(struct ldentry);
		Lf_data.lf_dirdirty = TRUE;
		signal(Lf_data.lf_mutex);
		return OK;
	}
	
	/*As we have created a new entry in this non-root directory update its entry in
	 * the parent directory to reflect the increased size of this directory.
	 * The lfPos of the parent directory is pointing to the location just
	 * after this directory's entry.
	 */
	
	struct ldentry parentDirEntry;
	/*
	 * Move to the poistion in grandparent at which the entry for the parent
	 * begins.
	 */
	lflSeek(&parentDevPtr,parentDirCblk->lfpos - sizeof(struct ldentry));
	if (lflRead(&parentDevPtr,(char*)&parentDirEntry,sizeof(struct ldentry)) ==SYSERR)
	{
		dirCblk->lfstate = LF_FREE;
		parentDirCblk->lfstate = LF_FREE;
		return SYSERR;
	}
	/*
	 * Update that entry.
	 */
	parentDirEntry.ld_size += sizeof(struct ldentry);
	parentDirEntry.ld_ilist = dirCblk->lffirstib;
	
	/* 
	 * As we have just read that entry move back again so that 
	 * we can overwrite it.
	 */
	lflSeek(&parentDevPtr,parentDirCblk->lfpos - sizeof(struct ldentry));
	
	/*
	 * Write to the grandparent.
	 */
	if (lflWrite(&parentDevPtr,(char*)&parentDirEntry,sizeof(struct ldentry)) == SYSERR)
	{
		dirCblk->lfstate = LF_FREE;
		parentDirCblk->lfstate = LF_FREE;
		return SYSERR;
	}
	/*Close the parent directory*/
	if (lfflush(parentDirCblk) == SYSERR)
	{
		dirCblk->lfstate = LF_FREE;
		parentDirCblk->lfstate = LF_FREE;
		
		return SYSERR;
	}
	dirCblk->lfstate = LF_FREE;
	parentDirCblk->lfstate = LF_FREE;
	return OK;
}
예제 #6
0
파일: dirEntCreat.c 프로젝트: fybecks/XINU
status createDirEntry(char *name, byte type, struct ldentry *dirEntry, bool8 isReplace)
{
	struct lflcblk * dirCblk = &lfltab[Nlfl+1];	
	struct lflcblk* parentDirCblk = &lfltab[Nlfl];	
	struct dentry devPtr;
	struct dentry parentDevPtr;

	devPtr.dvminor=Nlfl+1;	
	parentDevPtr.dvminor=Nlfl;	

	dirEntry->ld_size = 0;
	dirEntry->ld_ilist = LF_INULL;
	dirEntry->type = type;
	dirEntry->isUsed = (bool8)1;
	strcpy(dirEntry->ld_name,name);

	if(lflWrite(&devPtr,(char*)dirEntry,sizeof(struct ldentry)) == SYSERR)
	{

		dirCblk->lfstate = LF_FREE;
		parentDirCblk->lfstate = LF_FREE;
		return SYSERR;
	}

	/*Close the current directory*/
	if(lfflush(dirCblk) == SYSERR)
	{

		dirCblk->lfstate = LF_FREE;
		parentDirCblk->lfstate = LF_FREE;
		return SYSERR;
	}
	
	if(isReplace)
	{
		dirCblk->lfstate = LF_FREE;
		parentDirCblk->lfstate = LF_FREE;
		return OK;
	}

	if(LF_FREE == parentDirCblk->lfstate)
	{
		dirCblk->lfstate = LF_FREE;

		wait(Lf_data.lf_mutex);
		Lf_data.lf_dir.lfd_size += sizeof(struct ldentry);
		Lf_data.lf_dirdirty = TRUE;
		signal(Lf_data.lf_mutex);
		return OK;
	}

	struct ldentry parentDirEntry;
	
	lflSeek(&parentDevPtr,parentDirCblk->lfpos - sizeof(struct ldentry));
	if(lflRead(&parentDevPtr,(char*)&parentDirEntry,sizeof(struct ldentry)) ==SYSERR)
	{

		dirCblk->lfstate = LF_FREE;
		parentDirCblk->lfstate = LF_FREE;
		return SYSERR;
	}
	
	parentDirEntry.ld_size += sizeof(struct ldentry);
	parentDirEntry.ld_ilist = dirCblk->firstIbId;

	lflSeek(&parentDevPtr,parentDirCblk->lfpos - sizeof(struct ldentry));

	if(lflWrite(&parentDevPtr,(char*)&parentDirEntry,sizeof(struct ldentry)) == SYSERR)
	{

		dirCblk->lfstate = LF_FREE;
		parentDirCblk->lfstate = LF_FREE;
		return SYSERR;
	}
	
	if(lfflush(parentDirCblk) == SYSERR)
	{

		dirCblk->lfstate = LF_FREE;
		parentDirCblk->lfstate = LF_FREE;
		
		return SYSERR;
	}
	dirCblk->lfstate = LF_FREE;
	parentDirCblk->lfstate = LF_FREE;
	return OK;
}