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

📄 tfsclean.c

📁 极其轻量级的文件系统FAT16格式
💻 C
📖 第 1 页 / 共 3 页
字号:

				if (verbose > 1) {
					printf("    Middleof_copy (nda offset=0x%x, size=%d",
						offset,ssize);
					if (phc) 
						printf(", phc=0x%x)\n",phc);
					else
						printf(")\n");
				}

				TEST_EXIT_POINT(39,tfssector);

				/* On the first "middle-of-file" copy, if a PHC is active,
				 * then we don't copy a full sector (because the remaining
				 * portion of the header was copied in earlier).  We use
				 * the TFS_PHCDONE bit to indicate that this is the first
				 * middle-of-file copy in a phc condition...
				 */
				if (phc && (PHC_IS_COPIED(dp->phc))) {
					ulong	phctmp;

					if (tfsflashwrite((ulong *)(dp->nda+offset+phc),
						(ulong *)(tdp->spare+phc),ssize-phc) == -1) {
						printf("Sector-update8 (dp=0x%lx) failed\n",(ulong)dp);
						return(TFSERR_FLASHFAILURE);
					}

					phctmp = SET_PHC_DONE(dp->phc);
					if (tfsflashwrite(&dp->phc,&phctmp,sizeof(int)) == -1) {
						printf("Phc clear2 (dp=0x%lx) failed\n",(ulong)dp);
						return(TFSERR_FLASHFAILURE);
					}
				}
				else {
					if (tfsflashwrite((ulong *)(dp->nda+offset),
						(ulong *)(tdp->spare),ssize) == -1) {
						printf("Sector-update9 (dp=0x%lx) failed\n",(ulong)dp);
						return(TFSERR_FLASHFAILURE);
					}
				}

				TEST_EXIT_POINT(30,tfssector);
			}
			dp++;
		}

		TEST_EXIT_POINT(31,tfssector);

		if (setdefragstate(sidx,SECTOR_UPDATE_COMPLETE,verbose)!=TFS_OKAY)
			return(TFSERR_FLASHFAILURE);

		TEST_EXIT_POINT(32,tfssector);

sector_update_complete:
		/* Erase the SPARE sector, then update state. */
		if (tfssector != lasttfssector) {
			if (tfsflasherase(sparesnum) < 0) {
				printf("Flash SPARE sector erase failed\n");
				return(TFSERR_FLASHFAILURE);
			}
			TEST_EXIT_POINT(33,tfssector);
		}

		TEST_EXIT_POINT(34,tfssector);

sector_defrag_skip:
		if (setdefragstate(sidx,SECTOR_DEFRAG_COMPLETE,verbose)!=TFS_OKAY)
			return(TFSERR_FLASHFAILURE);

sector_defrag_complete:
		sbase += ssize;
		if (addrtosector(sbase,0,&ssize,0) < 0)
			return(TFSERR_MEMFAIL);
	}

	/* If the last file copy did not enter the last file sector,
	 * then erase the last tfssector...
	 */
	if (sectortoaddr(lasttfssector,0,(unsigned char **)&sbase) < 0)
		return(TFSERR_MEMFAIL);

	dp = (struct defraghdr *)DefragStateTbl - 1;
	if ((dp->nda + dp->fhdr.filsize + TFSHDRSIZ) < sbase) {

		/* Must use spare sector to record this state because this is
		 * the same sector that we were using to keep track of state.
		 */
		DefragStateTbl = (ulong *)(tdp->spare + tdp->sparesize - 4);
		if (setdefragstate(0,ERASING_LAST_SECTOR,verbose)!=TFS_OKAY)
			return(TFSERR_FLASHFAILURE);

		TEST_EXIT_POINT(35,-1);

erasing_last_sector:
		if (tfsflasherase(lasttfssector) < 0) {
			printf("Final sector erase (%d) failed\n",lasttfssector);
			return(TFSERR_FLASHFAILURE);
		}

		TEST_EXIT_POINT(36,-1);
	}

	/* All defragmentation is done, so verify sanity of files... */
	chkstat = tfscheck(tdp,verbose);

	TEST_EXIT_POINT(37,-1);

	/* Erase spare sector... */
	if (tfsflasherase(sparesnum) < 0) {
		printf("Final spare sector (%d) failed\n",sparesnum);
		return(TFSERR_FLASHFAILURE);
	}

	/* If resetwhendone flag is set, then reset here; else return result of
	 * the file system check.
	 */
	if (resetwhendone)
		monrestart(INITIALIZE);

	return(chkstat);
}

/* tfsclean():
 *	Wrapper for tfsclean so that we can enable a call to appexit() if there
 *	is an error returned by tfsclean().  This is used for testing TFS...
 *	If a script is running to try to cause tfsclean to break, then we want
 *	it to halt if tfsclean does return an error.
 */
int
tfsclean(int filtot,ulong *tbl1,struct defraghdr *tbl2,int snum,
	TDEV *tdp,int rwd,int verbose)
{
	extern	void appexit(int);
	int	cleanresult;

	cleanresult = _tfsclean(filtot,tbl1,tbl2,snum,tdp,rwd,verbose);
	if (cleanresult != TFS_OKAY) {
		if (getenv("APP_EXITONCLEANERROR"))
			appexit(0);
		if (getenv("SCR_EXITONCLEANERROR"))
			ScriptExitFlag = EXIT_SCRIPT;
	}
	return(cleanresult);
}

/* tfsfixup():
 *	See if a defragmentation was in progress.  If yes, finish it; else
 *	return.
 *	If 'dontquery' is set, then we won't query the user even on the first
 *	pass.
 */
int
tfsfixup(int verbose, int dontquery)
{
	struct	defraghdr	*dfhp;
	TFILE	thdr, *tfp;
	ulong	*statetbl, *spare_statetbl;
	int		ftot, i, tfssector, snum, query;
	TDEV	*tdp;

#if DEFRAG_TEST_ENABLED
	ExitPoint=0;
	ExitSector=0;
#endif
	query = dontquery;

	for(tdp=tfsDeviceTbl;tdp->start != TFSEOT;tdp++) {
	
		/* Set statetbl to point to what would be the first TFS sector's
		 * state information bitfield (if defrag were in progress).
		 */
		statetbl = (ulong *)(tdp->end+1);
		statetbl -= tdp->sectorcount;

		/* Set spare_statetbl to point to the last 'long' in spare sector.	*/
		spare_statetbl = (ulong *)(tdp->spare + tdp->sparesize) - 1;

		/* Check the end of the TFS space to see if a state table exists,
		 * and also check to see if the last location in the spare sector
		 * contains state.  If neither, then defragmentation was not in
		 * progress so just return here.
		 */
		if ((*statetbl == (ulong)ERASED32) &&
			(*spare_statetbl == (ulong)ERASED32)) {
			continue;
		}

		/* Allow the user to break out of the automatic cleanup... */
		if (!query) {
			if (pollConsole("TFS auto-cleanup?"))
				return(0);
			query = 1;
		}
		if (addrtosector((char *)tdp->start,&tfssector,0,0) < 0)
			return(TFSERR_MEMFAIL);

		/* Maybe only the last sector (and spare) needs to be erased...
		 * This means that all the files are up-to-date, but the
		 * final stages of sector cleanup didn't finish.
		 * This messiness is caused by the fact that the defragmentation
		 * could have been interrupted when it was erasing the same sector
		 * that it was storing state in.  For this sector, the defragmentor
		 * uses the spare sector to store state.
		 */
		if (*spare_statetbl == ERASING_LAST_SECTOR) {
			spare_statetbl -= (tdp->sectorcount-1);
			tfsclean(1,spare_statetbl,0,tdp->sectorcount-1,tdp,0,verbose);
			continue;
		}
	
		if (verbose)
			printf("Device %s fixup in progress\n",tdp->prefix);

		if (*statetbl == (ulong)ERASED32) {
			statetbl = (ulong *)(tdp->spare + tdp->sparesize);
			statetbl -= tdp->sectorcount;
		}
		dfhp = (struct defraghdr *)statetbl - 1;

		if (*statetbl == (ulong)BUILDING_HEADER_TABLE) {
			ftot = 0;
			tfp = (TFILE *) tdp->start;
			while(validtfshdr(tfp)) {
				if (TFS_FILEEXISTS(tfp)) {
					ftot++;
					dfhp--;
				}
				tfp = nextfp(tfp,tdp);
			}
			tfsclean(ftot,statetbl,dfhp,0,tdp,0,verbose);
			continue;
		}

		ftot = 0;
		while(1) {
			if (dfhp->fhdr.hdrsize == ERASED16)
				break;
			thdr = dfhp->fhdr;
			thdr.next = 0;
			thdr.hdrcrc = 0;
			if (crc32((uchar *)&thdr,TFSHDRSIZ) != dfhp->fhdr.hdrcrc)
				break;
			ftot++;
			dfhp--;
		}
		dfhp++;

		/* If ftot is zero, then we are fixing up an empty file system that
		 * was in the process of being defragmented, so just erase all
		 * sectors and be done...
		 */
		if (ftot == 0) {
			if (verbose)
				printf("Cleaning up empty device...\n");
			if (tfsflasheraseall(tdp) < 0)
				printf("Device erase-all failed\n");
			continue;
		}

		if (verbose)
			printf("%d files being defragmented\n",ftot);

		snum = -1;

		/* Find currently active sector by stepping through the state table
		 * until SECTOR_DEFRAG_INACTIVE state is detected, then step back 1.
		 */
		for(i=0;i<(int)tdp->sectorcount;i++) {
			if (verbose > 1) {
				printf("TFS Sector %d state: 0x%lx (%s)\n",
					tfssector+i, (ulong)(statetbl[i]),
					tfsdefragmsg(statetbl[i]));
			}
			if ((snum == -1) && (statetbl[i] == SECTOR_DEFRAG_INACTIVE))
				snum = i-1;	
		}
		if (snum == -1) {
			printf("*****Starting at last sector\n");
			snum = tdp->sectorcount-1;
			if (statetbl[snum] == COPY_HDRS_TO_SPARE) {
				spare_statetbl = (ulong *)(tdp->spare + tdp->sparesize) - 1;
				if ((*spare_statetbl == HDRS_IN_SPARE) ||
				    (*spare_statetbl == LASTSECTOR_IN_SPARE)) {
					printf("Adjusting statetbl from 0x%lx to 0x%lx\n",
						(ulong)statetbl,
						(ulong)(spare_statetbl - (tdp->sectorcount-1)));
					statetbl = spare_statetbl - (tdp->sectorcount-1);
				}
			}
		}
		if (verbose > 1)
			printf("Defrag restart at TFS sector %d\n",tfssector+snum);
		tfsclean(ftot,statetbl,dfhp,snum,tdp,0,verbose);
	}
	return(0);
}

#else

int
tfsfixup(int verbose, int dontquery)
{
	return(TFSERR_NOTAVAILABLE);
}

/* tfsclean():
 *	This is an alternative to the complicated defragmentation above.
 *	It simply scans through the file list and copies all valid files
 *	to RAM; then flash is erased and the RAM is copied back to flash.
 * <<< WARNING >>>
 * THIS FUNCTION SHOULD NOT BE INTERRUPTED AND IT WILL BLOW AWAY
 * ANY APPLICATION  CURRENTLY IN CLIENT RAM SPACE.
 */
int
tfsclean(int filtot,ulong *tbl1,struct defraghdr *tbl2,int snum,
	TDEV *tdp,int rwd,int verbose)
{
	extern	ulong APPLICATION_RAMSTART;
	TFILE	*tfp;
	uchar	*tbuf;
	int		dtot, nfadd, len, err;

	/* Determine how many "dead" files exist. */
	dtot = 0;
	tfp = (TFILE *)tdp->start;
	while(validtfshdr(tfp)) {
		if (!TFS_FILEEXISTS(tfp))
			dtot++;
		tfp = nextfp(tfp,tdp);
	}

	if (dtot == 0)
		return(TFS_OKAY);

	printf("Reconstructing device %s with %d dead file%s removed...\n",
		tdp->prefix, dtot,dtot>1 ? "s":"");

	tbuf = (char *)APPLICATION_RAMSTART;
	tfp = (TFILE *)(tdp->start);
	nfadd = tdp->start;
	while(validtfshdr(tfp)) {
		if (TFS_FILEEXISTS(tfp)) {
			len = TFS_SIZE(tfp) + sizeof(struct tfshdr);
			if (len % TFS_FSIZEMOD)
				len += TFS_FSIZEMOD - (len % TFS_FSIZEMOD);
			nfadd += len;
			err = tfsmemcpy(tbuf,(uchar *)tfp,len,0,0);
			if (err != TFS_OKAY)
				return(err);
			
			((struct tfshdr *)tbuf)->next = (struct tfshdr *)nfadd;
			tbuf += len;
		}
		tfp = nextfp(tfp,tdp);
	}

	/* Erase the flash device: */
	err = _tfsinit(tdp);
	if (err != TFS_OKAY)
		return(err);

	/* Copy data placed in RAM back to flash: */
	err = AppFlashWrite((ulong *)(tdp->start),(ulong *)APPLICATION_RAMSTART,
		(tbuf-(uchar*)APPLICATION_RAMSTART));
	if (err < 0)
		return(TFSERR_FLASHFAILURE);

	return(TFS_OKAY);
}

#endif /* INCLUDE_TFS */

/* If INCLUDE_TFSCLEAN is not defined, then we do not want to do any
 * automatic cleanup of the flash...
 */
int
tfsautoclean(int filtot,ulong *tbl1,struct defraghdr *tbl2,int snum,
	TDEV *tdp,int rwd,int verbose)
{
#if INCLUDE_TFSCLEAN
	return(_tfsclean(filtot,tbl1,tbl2,snum,tdp,rwd,verbose));
#else
	return(TFSERR_NOTAVAILABLE);
#endif
}

⌨️ 快捷键说明

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