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

📄 tfs.c

📁 可移到ucos上的文件系统
💻 C
📖 第 1 页 / 共 4 页
字号:
				}
				else {
					tinfo->deadftot++;
					tinfo->deaddata += TFS_SIZE(tfp);
					tinfo->deadovrhd += TFSHDRSIZ;
				}
				tfp = nextfp(tfp,tdp);
			}
		}
	}
	tinfo->memused = tinfo->livedata + tinfo->liveovrhd +
			tinfo->deaddata + tinfo->deadovrhd + tinfo->pso + tinfo->sos;
	tinfo->memfree = tinfo->memtot - tinfo->memused; 

	/* Remaining space may not even be big enough to contain the
	 * file overhead, if this is the case, show a remaining space
	 * of zero rather than a negative number...
	 */
	tinfo->memfordata =
		tinfo->memfree - (devtot * (TFSHDRSIZ + sizeof(struct defraghdr)));
	if (tinfo->memfordata < 0)
		tinfo->memfordata = 0;

	if (verbose) {
		printf("\n Total memory: %d bytes (used=%d, avail=%d (%d for data)).\n",
			tinfo->memtot,tinfo->memused,tinfo->memfree, tinfo->memfordata);
		printf(" Per-device overhead: %d bytes ",tinfo->pso+tinfo->sos);
		printf("(defrag-state=%d spare-sector=%d).\n",tinfo->pso,tinfo->sos);
		printf(" File data space: %d bytes (live=%d, dead=%d).\n",
			tinfo->livedata+tinfo->deaddata,
			tinfo->livedata,tinfo->deaddata);
		printf(" File overhead space: %d bytes (live=%d, dead=%d).\n",
			tinfo->liveovrhd+tinfo->deadovrhd,
			tinfo->liveovrhd,tinfo->deadovrhd);
		printf(" File count: %d (live=%d, dead=%d).\n",
			tinfo->liveftot+tinfo->deadftot,tinfo->liveftot,tinfo->deadftot);
		printf(" Defrag will release %d bytes\n",
			tinfo->deadovrhd+tinfo->deaddata);
		printf("\n");
	}
	return(tinfo->liveftot + tinfo->deadftot);
}

/* tfscheck():
 *	Step through each file in a particular device making a few checks...
 *	- First look at the header.  If hdrsize is erased, it "should" indicate
 *	  the end of the linear list of files.  To be anal about it, verify that
 *	  the entire header is erased.  If it is, we truly are at the end of the
 *	  list; otherwise, header error.
 *	- Second, do a crc32 on the header. 
 *	- Third, if the file is not deleted, then do a crc32 on the data portion
 *	  of the file (if the file is deleted, then it really doesn't matter if
 *	  there is a crc32 error on that data).
 *	- Finally, if the header is not corrupted, index to the next pointer and
 *	  continue.  If the header is corrupt, see if enough information
 *	  in the header is valid to allow us to step to the next file.  Do this
 *	  by calculating where the next pointer should be (using current pointer,
 *	  file+header size and mod16 adjustment) and then see if that matches the
 *	  value stored in the actual "next" pointer.  If yes, go to next file;
 *	  else break out of the loop.
 *	
 *	The purpose is to do more sophisticated file system checks than are
 *	done in normal TFS operations.
 */
#define TFS_CORRUPT		1
#define HDR_CORRUPT		2
#define DATA_CORRUPT	4

int
tfscheck(TDEV *tdp, int verbose)
{
	ulong	hdrcrc;
	int		tfscorrupt, filtot;
	TFILE	*fp, *fp1, hdrcpy;

	if (!tdp)
		return(TFSERR_BADARG);

	if (verbose)
		printf("TFS device %s check:\n",tdp->prefix);

	filtot = tfscorrupt = 0;

	fp = (TFILE *)tdp->start;
	while(1) {
		tfscorrupt &= ~(HDR_CORRUPT | DATA_CORRUPT);

		/* If hdrsize is ERASED16, then verify that the whole header is
		 * also ERASED16, if yes, we're at the end of the linear list of
		 * files; otherwise, we have a corrupt header.
		 */
		if (fp->hdrsize == ERASED16) {
			int		i;
			ushort	*sp;

			/* If this is right at the edge of the end of the TFS device,
			 * then break with no further checks to this header.
			 */
			if ((fp+1) > (TFILE *)tdp->end)
				break;

			/* Make sure the entire header is erased... */
			sp = (ushort *)fp;
			for(i=0;i<TFSHDRSIZ;i+=2,sp++) {
				if (*sp != ERASED16) {
					if (verbose)
						printf(" Corrupt hdr @ 0x%lx",(ulong)fp);
					tfscorrupt = HDR_CORRUPT | TFS_CORRUPT;
				}
			}
			if (!(tfscorrupt & HDR_CORRUPT))
				break;
			else
				goto nextfile;
		}

		/* Run a crc check on the header even if file is deleted...			*/
		hdrcpy = *fp;
		hdrcrc = fp->hdrcrc;
		hdrcpy.next = 0;
		hdrcpy.hdrcrc = 0;
		hdrcpy.flags |= (TFS_NSTALE | TFS_ACTIVE);
		if (crc32((uchar *)&hdrcpy,TFSHDRSIZ) != hdrcrc) {
			if (verbose)
				printf(" CRC error in hdr @ 0x%lx",(ulong)fp);
			tfscorrupt = HDR_CORRUPT | TFS_CORRUPT;
			goto nextfile;
		}

		/* If file exists, and it's not IPMOD, run a crc check on data...	*/
		if (TFS_FILEEXISTS(fp) && !(fp->flags & TFS_IPMOD)) { 
			filtot++;
			if (verbose)
				printf(" %s...",fp->name);
		
			if ((!(fp->flags & TFS_IPMOD)) &&
				(crc32(TFS_BASE(fp),fp->filsize) != fp->filcrc)) {
					if (verbose)
						printf(" CRC error in data");
					tfscorrupt = DATA_CORRUPT | TFS_CORRUPT;
			}
			else {
				if (verbose)
					printf(" ok");
			}
		}

		/* Prior to incrementing to the next file pointer, if the header
		 * is corrupted, attempt to salvage the next pointer...
		 * If the value of the next pointer matches what is	calculated
		 * from the file size and header size, then assume it is ok
		 * and allow the tfscheck() loop to continue; otherwise break.
		 */
nextfile:
		if (tfscorrupt & HDR_CORRUPT) {
			if (fp->next) {
				ulong modnext;				

				modnext = (ulong)((int)(fp+1) + fp->filsize);
				if (modnext & 0xf) {
					modnext += 16;
					modnext &= ~0xf;
				}
				if (verbose)
					printf(" (next ptr ");
				if (fp->next != (TFILE *)modnext) {
					if (verbose)
						printf("damaged)\n");
					break;
				}
				else {
					if (verbose)
						printf("salvaged)");
				}
			}
		}
		fp1 = nextfp(fp,tdp);
		if (!fp1) {
			tfscorrupt = HDR_CORRUPT | TFS_CORRUPT;
			break;
		}
		if ((verbose) && (TFS_FILEEXISTS(fp) || tfscorrupt))
			putchar('\n');
		fp = fp1;
	}
	if (tfscorrupt || !tfsflasherased(tdp,verbose))
		return(TFSERR_CORRUPT);
	if (verbose)
		printf(" PASSED\n");
	return (TFS_OKAY);
}

void
tfsclear(TDEV *tdp)
{
	int i;

	/* Clear the fileslot[] table indicating that no files are opened.
	 * Only clear the slots applicable to the incoming TDEV pointer.
	 */
	for (i = 0; i < TFS_MAXOPEN; i++) {
		ulong offset;

		offset = tfsSlots[i].offset;
		if (offset != (ulong)-1) {
			if ((tdp == (TDEV *)0) ||
				((offset >= tdp->start) && (offset <= tdp->end)))
				tfsSlots[i].offset = -1;
		}
	}

	/* If the incoming TDEV pointer is NULL, then we can assume a global
	 * clear and go ahead and cleanup everything; otherwise, we just return
	 * here.
	 */
	if (tdp != (TDEV *)0)
		return;

	/* Turn off tracing. */
	tfsTrace = 0;

	/* Init the time retrieval function pointers to their dummy values. */
	tfsGetAtime = dummyAtime;
	tfsGetLtime = dummyLtime;

	/* Default to using standard docommand() within scripts. */
	tfsDocommand = docommand;

	/* Start off with a buffer for 16 files.  This is probably more than
	 * will be used, so it avoids reallocations in tfsreorder().
	 */
	tfsAlistSize = 16;
	tfsAlist = (TFILE **)malloc((tfsAlistSize+1) * sizeof(TFILE **));
	if (!tfsAlist) {
		printf("tfsclear(): tfsAlist allocation failed\n");
		tfsAlistSize = 0;
	}
}

/* tfsstalecheck():
 *	Called at startup to clean up any file that may be in STALE mode.
 *	A file is stale if it was in the process of being modified
 *	and a power hit occurred.  Refer to notes in tfsadd() for details.
 *	There are a few cases to be covered here...
 *	1. there is no stale file; so there is nothing to do.
 *	2. there is a stale file, but no other file with the same name...
 *		In this case, the stale file must be copied to another file (with the
 *		TFS_NSTALE flag set) and the stale file is deleted.
 *	3. there is stale file and another file with the same name...
 *		In this case, the stale file is simply deleted because the other file
 *		with the same name is newer.
 */ 
static void
tfsstalecheck()
{
	int		err;
	ulong	flags;
	TDEV	*tdp;
	TFILE	*tfp, *tfpa;
	char	buf[16];

	tfpa = (TFILE *)0;
	for(tdp=tfsDeviceTbl;tdp->start != TFSEOT;tdp++) {
		tfp = (TFILE *)tdp->start;
		tfpa = (TFILE *)0;
		while(validtfshdr(tfp)) {
			if (TFS_FILEEXISTS(tfp)) {
				if (tfpa) {
					if (!strcmp(TFS_NAME(tfp),TFS_NAME(tfpa))) {
						_tfsunlink(TFS_NAME(tfpa));
						return;
					}
				}
				else if (TFS_STALE(tfp)) {
					tfpa = tfp;
				}
			}
			tfp = nextfp(tfp,tdp);
		}
	}
	if (tfpa) {
		flags = TFS_FLAGS(tfpa) | TFS_NSTALE;
		err = tfsadd(TFS_NAME(tfpa),TFS_INFO(tfpa),tfsflagsbtoa(flags,buf),
			(char *)(TFS_BASE(tfpa)),TFS_SIZE(tfpa));
		if (err != TFS_OKAY)
			printf("%s: %s\n",TFS_NAME(tfpa),tfserrmsg(err));
		
		_tfsunlink(TFS_NAME(tfpa));
	}
}

/* tfsoldstyleflagcheck():
 *	This function is called once at startup to make a clean transition
 *	to a version of TFS that deletes a file by ONLY clearing the TFS_ACTIVE
 *	bit in the flags field (older method cleared the whole flag).
 *	This new deletion method makes it possible to run a crc32 check on the
 *	header of a deleted file; this change was made around Sept 1999.
 */
void
tfsoldstyleflagcheck(void)
{
#ifdef INCLUDE_OLDSTYLE_FLAGCHECK
	static	int alreadyran;
	int		printonce;
	TDEV	*tdp;
	TFILE	*tfp;

	/* This should only occur once at startup. */
	if (alreadyran)
		return;

	printonce = 1;
	tfsOldDelFlagCheckActive = 1;

	for (tdp=tfsDeviceTbl;tdp->start != TFSEOT;tdp++) {
		tfp = (TFILE *)tdp->start;
		while(validtfshdr(tfp)) {
			/* If old-style deletion flag is detected, just run tfsclean	*/
			/* (with tfsOldDelFlagCheckActive set) on the device to			*/
			/* eliminate the delted file.									*/
			if (tfp->flags == 0) {	
				if (printonce) {
					printf("Cleaning up old style deletion flags...\n");
					printonce = 0;
				}
				tfsautoclean(0,0,0,0,tdp,0,1);
				break;	
			}
			tfp = nextfp(tfp,tdp);
		}
	}
	tfsOldDelFlagCheckActive = 0;
	alreadyran = 1;
#endif
}

/* tfsdevtblinit():
 *	Transfer the information in tfsdevtbl (in tfsdev.h) to tfsDeviceTbl[].
 *	In most cases, this will be a simple copy.  If the device flag is set
 *	to indicate that the initalization is dynamic, then use the flash 
 *	ops to retrieve the information from the specified bank.
 *
 *	For dynamic configuration, the "start" member of the tfsdev structure
 *	must be set in tfsdev.h and the "devinfo & TFS_DEVINFO_BANKMASK" area
 *	must contain the number of the last flash bank that is to be part of
 *	the TFS device.  Typically this value is the same bank number as the
 *	starting bank, but it could span across multiple contiguous banks
 *	if the hardware is set up that way.
 *
 *	To support the use of top-boot devices, plus the TFS requirement that
 *	the SPARE sector be at-least as large as any other sector in the device,
 *	this code will automatically step down the sector list until it finds
 *	the first large sector below all the small ones usually at the top of
 *	a top-boot device.  The call to lastlargesector() takes care of this.
 *
 *	NOTE:
 *	 This dynamic configuration assumes that the end of the TFS space is
 *	 just below the beginning of the spare space.
 *
 */
void
tfsdevtblinit(void)
{
	int		i, startsector, endsector, bank;
	TDEV	*tDp, *tdp;

	for(i=0;i<TFSDEVTOT;i++) {
		tdp = &tfsdevtbl[i];
		tDp = &tfsDeviceTbl[i];
		*tDp = *tdp;
		if (i == TFSDEVTOT-1)
			break;
		if (tdp->devinfo & TFS_DEVINFO_DYNAMIC) {
			bank = tDp->devinfo & TFS_DEVINFO_BANKMASK;

			/* The spare sector may not be the last sector in the device...
			 * device.  Especially if the device is TopBoot type.
			 */
			if (lastlargesector(bank,&endsector,
				(int *)&tDp->sparesize,(uchar **)&tDp->spare) == -1)
				break;

			tDp->end = tDp->spare - 1;
			if (addrtosector((uchar *)tDp->start,&startsector,0,0) == -1)
				break;
			tDp->sectorcount = endsector - startsector;
		}
	}
}

/* tfsstartup():
 *	Called at system startup to get things properly initialized.
 */
void
tfsstartup()
{
	tfsdevtblinit();
	tfsclear((TDEV *)0);
	tfsfixup(3,0);
	tfsstalecheck();
	tfsoldstyleflagcheck();
}

/* tfsexec: Treat the file as machine code that is COFF or ELF. */

static int
tfsexec(fp,verbose)
int	verbose;
TFILE *fp;
{
	extern	int ctxMON(), ctxAPP();
	int err, (*entry)(), octx;
	long	address;

	err = tfsloadebin(fp,verbose,&address,0);
	if (err != TFS_OKAY)
		return(err);

	entry = (int(*)())address;
	octx = ctxAPP();	/* Change context to APPLICATION. */
	entry();			/* Call entrypoint (may not return). */
	ctxMON(octx);		/* Change context to APPLICATION. */
	return(TFS_OKAY);
}

/* tfsmemset():
 *	Superset of memset().  Includes verbose option plus verification after
 *	set.
 */
int
tfsmemset(uchar *to,uchar val,int count,int verbose,int verifyonly)
{
	int		failed;
	uchar	*end;

	failed = 0;

	if (verbose) {
		printf("%s %7d bytes  at  0x%08lx to 0x%02x",
			verifyonly ? "vrfy" : "set ",count,(ulong)to,val);
	}

	if (count == 0)
		goto done;

	end = to+count;

	if (verifyonly) {
		while(to < end) {
			if (*to++ != val) {
				failed = 1;
				break;
			}
		}
	}
	else {
		while(to < end) {
			*to = val;
			if (*to++ != val) {
				failed = 1;
				break;
			}
		}
	}
done:
	if (verbose) {
		if (failed)
			printf(" failed");
		else if (verifyonly)
			printf(" OK");
		printf("\n");
	}
	if (failed)
		return(TFSERR_MEMFAIL);
	else
		return(TFS_OKAY);
}

/* tfsmemcpy():
 *	Superset of memcpy().  Includes verbose option plus verification after
 *	copy.  Takes advantage of address alignment when possible.
 */
int
tfsmemcpy(uchar *to,uchar *from,int count,int verbose,int verifyonly)
{
	int	err;
	register uchar	*end;

	if (verbose)
		printf("%s %7d bytes from 0x%08lx to 0x%08lx",
			verifyonly ? "vrfy" : "copy", count,(ulong)from,(ulong)to);

	if (verifyonly) {
		while(count) {
			if (*to != *from)
				break;
			to++;
			from++;
			count--;
		}
		if (count) {
			if (verbose) {
				printf(" FAILED\n");
				printf("            (0x%02x @ 0x%08lx should be 0x%02x)\n",
					*to,(ulong)to,*from);
			}
			return(TFSERR_MEMFAIL);
		}
		else
			if (verbose)
				printf(" OK\n");
			return(TFS_OKAY);
	}

	if (count == 0)
		goto done;

	if (to != from) {
		err = 0;
		if (!((int)to & 3) && !((int)from & 3) && !(count & 3)) {
			register ulong	*lto, *lfrom, *lend;
	
			count >>= 2;
			lto = (ulong *)to;
			lfrom = (ulong *)from;
			lend = lto + count;
			while(lto < lend) {
				*lto = *lfrom;
				if (*lto != *lfrom) {
					err = 1;
					break;
				}
				lto++;
				lfrom++;
			}
		}
		else if (!((int)to & 1) && !((int)from & 1) && !(count & 1)) {

⌨️ 快捷键说明

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