예제 #1
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;
}
예제 #2
0
/*------------------------------------------------------------------------
 * lfstruncate  -  truncate a file by freeing its index and data blocks
 *			(assumes directory mutex held)
 *------------------------------------------------------------------------
 */
status	lfstruncate (
    char *name				/* file name to truncate		*/
)
{
    char	*nam, *cmp;			/* ptrs used during comparison	*/
    int32	i;					/* general loop index			*/
    struct	lflcblk	*lfptr;		/* ptr to open file table entry	*/
    struct	lfdir	*dirptr;	/* ptr to in-memory directory	*/
    bool8	found;				/* was the name found?			*/
    int32	retval;				/* value returned from function	*/
    struct	ldentry	*ldptr;		/* ptr to an entry in directory	*/
    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		*/
    struct	lfiblk	iblock;		/* buffer for one index block	*/

    /* Check length of name file (leaving space for NULLCH 	*/
    nam = name;
    for (i=0; i< LF_NAME_LEN; i++) {
        if (*nam++ == NULLCH) {
            break;
        }
    }
    if (i >= LF_NAME_LEN) {		/* name is too long */
        //kprintf("Name is too long\r\n");
        return SYSERR;
    }

    /* Check if named file is open */
    for (i=0; i<Nlfl; i++) {	/* search file pseudo-devices	*/
        lfptr = &lfltab[i];
        if (lfptr->lfstate == LF_USED) {
            /* Compare requested name to name of open file 		*/
            nam = name;
            cmp = lfptr->lfname;
            while(*nam != NULLCH) {
                if (*nam != *cmp) {
                    break;
                }
                nam++;
                cmp++;
            }
            /* if named file is open, call lftruncate directly	*/
            if ( (*nam==NULLCH) && (*cmp == NULLCH) ) {
                //kprintf("file to truncate is open\r\n");
                wait(lfptr->lfmutex);
                retval = lftruncate(lfptr);
                signal(lfptr->lfmutex);
                //kprintf("truncated the open file\r\n");
                return retval;
            }
        }
    }

    /* Named file is not open	*/
    /* Obtain copy of directory if not already present in memory	*/
    dirptr = &Lf_data.lf_dir;
    if (! Lf_data.lf_dirpresent) {
        retval = read(Lf_data.lf_dskdev,(char *)dirptr,LF_AREA_DIR);
        if (retval == SYSERR ) {
            //kprintf("Cannot not read directory into memory\r\n");
            return SYSERR;
        }
        Lf_data.lf_dirpresent = TRUE;
    }

    /* Search directory to see if file exists */
    found = FALSE;
    for (i=0; i<dirptr->lfd_nfiles; i++) {
        ldptr = &dirptr->lfd_files[i];
        nam = name;
        cmp = ldptr->ld_name;
        while(*nam != NULLCH) {
            if (*nam != *cmp) {
                break;
            }
            nam++;
            cmp++;
        }
        if ( (*nam==NULLCH) && (*cmp==NULLCH) ) { /* name found	*/
            found = TRUE;
            break;
        }
    }

    /* if file does not exist, return SYSERR	*/
    if (! found) {
        signal(Lf_data.lf_mutex);
        //kprintf("Named file to truncate does not exist\r\n");
        return SYSERR;
    }
    /* if file is in directory, free its index and data blocks	*/
    else {
        if (ldptr->ld_size == 0) {	/* file is already empty */
            return OK;
        }
        /* 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 = ldptr->ld_ilist;
        ldptr->ld_ilist = LF_INULL;
        ldptr->ld_size = 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;
    }
}