Example #1
0
/*------------------------------------------------------------------------
 * lflControl - Provide control functions for a local file pseudo-device
 *------------------------------------------------------------------------
 */
devcall	lflControl (
	 struct dentry	*devptr,	/* entry in device switch table	*/
	 int32	func,			/* a control function		*/
	 int32	arg1,			/* argument #1			*/
	 int32	arg2			/* argument #2			*/
	)
{
	struct	lflcblk	*lfptr;		/* ptr to open file table entry	*/
	int32	retval;			/* return value from func. call	*/

	/* 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;
	}

	switch (func) {

	/* Truncate a file */

	case LF_CTL_TRUNC:
		wait(Lf_data.lf_mutex);
		retval = lftruncate(lfptr);
		signal(Lf_data.lf_mutex);
		signal(lfptr->lfmutex);
		return retval;	

	default:
		kprintf("lfControl: function %d not valid\n\r", func);
		signal(lfptr->lfmutex);
		return SYSERR;
	}
}
Example #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;
    }
}