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

📄 tfs.c

📁 uCOS-II for AT91M55800A完整实例
💻 C
📖 第 1 页 / 共 4 页
字号:
			if (retval == TFS_OKAY)				retval = flag;			break;		case TFS_FBTOA:			retval = (long)tfsflagsbtoa(arg1,(char *)arg2);			if (retval == 0)				retval = TFSERR_BADARG;			break;		case TFS_TELL:			retval = tfstell(arg1);			break;		case TFS_TIMEFUNCS:			tfsGetLtime = (long(*)(void))arg1;			tfsGetAtime = (char *(*)(long,char *,int))arg2;			retval = TFS_OKAY;			break;		case TFS_DOCOMMAND:			if (arg2)				*(long *)arg2 = (long)tfsDocommand;			if (arg1)				tfsDocommand = (void(*)(char *,int))arg1;			else				tfsDocommand = docommand;			retval = TFS_OKAY;			break;		default:			retval = TFSERR_BADARG;			break;	}	return(retval);}/* tfsadd(): *	Add a file to the current list. *	If the file already exists AND everything is identical between the *	old and the new (flags, info and data), then return and do nothing; *	else remove the old file prior to adding the new one. * *	Note: *	At the point when tfsadd is called for a file that currently exists, *	the old file must be removed and a new one is put in its place.  This *	opens up the possibility of losing the file if a power-hit or reset was *	to occur between the point at which the old file was removed and the new *	one was put in its place.  To overcome this problem, TFS files have a *	flag called TFS_NSTALE.  It is a bit that is normally 1, but cleared *	if it becomes stale (hence the name TFS_NSTALE).  A file is *	in this mode only for a short time... the time it takes to write the *	new file that replaces the file that was made stale. *	Now, if a reset occurs after the file is stale, depending on  *	whether or not the new file was written, it will either be removed or *	used to recreate the original file because the write of the new file *	was chopped off by the power hit.  Refer to the function tfsstalecheck() *	for details on the recovery after a reset or powerhit. *	MONLIB NOTICE: this function is accessible through monlib.c. */inttfsadd(char *name, char *info, char *flags, uchar *src, int size){	TDEV	*tdp;	TFILE	*fp, tf;	ulong	endoftfsflash, nextfileaddr, state_table_overhead;	int		ftot, cleanupcount, err, stale, ssize;	if (tfsTrace > 0)		printf("tfsadd(%s,%s,%s,0x%lx,%d)\n", name,info,flags,(ulong)src,size);	if ((size <= 0) || (!name))		return(TFSERR_BADARG);	if ((strlen(name) > TFSNAMESIZE) ||		((info) && (strlen(info) > TFSINFOSIZE)))		return(TFSERR_NAMETOOBIG);	/* If the file is currently opened, then don't allow the add... */	if (tfsFileIsOpened(name))		return(TFSERR_FILEINUSE);	stale = 0;	cleanupcount = 0;	/* Establish the device that is to be used for the incoming file	 * addition request...  The device used depends on the prefix of	 * the incoming file name.  If the incoming prefix doesn't match	 * any of the devices in the table, then place the file in the	 * first device in the table (assumed to be the default).	 */	for(tdp=tfsDeviceTbl;tdp->start != TFSEOT;tdp++) {		if (!strncmp(name,tdp->prefix,strlen(tdp->prefix)))			break;	}	if (tdp->start == TFSEOT)		tdp = tfsDeviceTbl;tryagain:	fp = (TFILE *)tdp->start;	/* Find end of current storage: */	ftot = 0;	while (fp) {		if (fp->hdrsize == ERASED16)			break;		if (TFS_FILEEXISTS(fp)) {			ftot++;			if (fp->flags & TFS_NSTALE) {				if (!strcmp(TFS_NAME(fp),name)) {					/* If file of the same name exists AND it is identical to					 * the new file to be added, then return TFS_OKAY and be					 * done; otherwise, remove the old one and continue.					 */					if (!tfscompare(fp,name,info,flags,src,size))						return(TFS_OKAY);										/* If a file of the same name exists but is different than					 * the new file, make the current file stale, then after 					 * the new file is added we will delete the stale one.					 */					stale = 1;					err = tfsmakeStale(fp);					if (err == TFS_OKAY)						goto tryagain;					else						return(err);				}			}		}		fp = nextfp(fp,tdp);	}	if (!fp)	/* If fp is 0, then nextfp() (above) detected corruption. */		return(TFSERR_CORRUPT);	/* Calculate location of next file (on mod16 address).  This will be 	 * initially used to see if we have enough space left in flash to store	 * the current request; then, if yes, it will become part of the new	 * file's header.	 */	nextfileaddr = ((ulong)(fp+1)) + size;	if (nextfileaddr & 0xf)		nextfileaddr = (nextfileaddr | 0xf) + 1;		/* Make sure that the space is available for writing to flash...	 * Remember that the end of useable flash space must take into	 * account the fact that some space must be left over for the	 * defragmentation state tables.  Also, the total space needed for	 * state tables cannot exceed the size of the sector that will contain	 * those tables.  	 */	state_table_overhead = ((ftot+1) * sizeof(struct defraghdr)) +		(tdp->sectorcount * sizeof(long));	if (addrtosector((uchar *)(tdp->end),0,&ssize,0) < 0)		return(TFSERR_MEMFAIL);	if (state_table_overhead >= (ulong)ssize)		return(TFSERR_FLASHFULL);	endoftfsflash = (tdp->end + 1) - state_table_overhead;	if ((nextfileaddr >= endoftfsflash) ||		(!tfsSpaceErased((uchar *)fp,size+TFSHDRSIZ))) {		if (!cleanupcount) {			err = tfsautoclean(0,0,0,0,tdp,0,0);			if (err != TFS_OKAY) {				printf("tfsadd autoclean failed: %s\n",					(char *)tfsctrl(TFS_ERRMSG,err,0));				return(err);			}			cleanupcount++;			goto tryagain;		}		else			return(TFSERR_FLASHFULL);	}	memset((char *)&tf,0,TFSHDRSIZ);	/* Copy name and info data to header. */	strcpy(tf.name, name);	if (info)		strcpy(tf.info, info);	tf.hdrsize = TFSHDRSIZ;	tf.hdrvrsn = TFSHDRVERSION;	tf.filsize = size;	if ((flags == (char *)0) || (*flags == 0))		tf.flags = 0;	else {		err = tfsflagsatob(flags,&tf.flags);		if (err != TFS_OKAY)			return(err);	}	tf.flags |= (TFS_ACTIVE | TFS_NSTALE);	if (!(tf.flags & TFS_IPMOD))		tf.filcrc = crc32(src, size);	else		tf.filcrc = ERASED32;	tf.modtime = tfsGetLtime();	tf.next = 0;	tf.hdrcrc = 0;	tf.hdrcrc = crc32((uchar *)&tf,TFSHDRSIZ);	tf.next = (TFILE *)nextfileaddr;	/* Now copy the file and header to flash.	 * Note1: the header is copied AFTER the file has been	 * successfully copied.  If the header was written successfully,	 * then the data write failed, the header would be incorrectly	 * pointing to an invalid file. To avoid this, simply write the	 * data first.	 * Note2: if the file is in-place-modifiable, then there is no	 * file data to be written to the flash.  It will be left as all FFs	 * so that the flash can be modified by tfsipmod() later.	 */	/* Write the file to flash if not TFS_IPMOD: */	if (!(tf.flags & TFS_IPMOD)) {		if (tfsflashwrite((ulong *)(fp+1),(ulong *)src,size) == -1)			return(TFSERR_FLASHFAILURE);	}	/* Write the file header to flash: */	if (tfsflashwrite((ulong *)fp,(ulong *)(&tf),TFSHDRSIZ) == -1)		return(TFSERR_FLASHFAILURE);	/* Double check the CRC now that it is in flash. */	if (!(tf.flags & TFS_IPMOD)) {		if (crc32((uchar *)(fp+1), size) != tf.filcrc)			return(TFSERR_BADCRC);	}	/* If the add was a file that previously existed, then the stale flag	 * will be set and the old file needs to be deleted...	 */	if (stale) {		err = _tfsunlink(name);		if (err != TFS_OKAY)			printf("%s: %s\n",name,tfserrmsg(err));	}	tfslog(TFSLOG_ADD,name);	return(TFS_OKAY);}/* tfsunlink(): *	Delete a file from the current list of files. Note that there *	is no attempt to de-fragment the flash; it simply nulls out the flags *	field of the file.  If successful return 0; else return error number. *	MONLIB NOTICE: this function is accessible through monlib.c. */inttfsunlink(char *name){	if (tfsTrace > 0)		printf("tfsunlink(%s)\n",name);	/* If the file is currently opened, then don't allow the deletion... */	if (tfsFileIsOpened(name))		return(TFSERR_FILEINUSE);	return(_tfsunlink(name));}int_tfsunlink(char *name){	TFILE *fp;	ulong flags_marked_deleted;	if (tfsTrace > 0)		printf("_tfsunlink(%s)\n",name);	fp = tfsstat(name);	if (!fp)		return(TFSERR_NOFILE);	if (TFS_USRLVL(fp) > getUsrLvl())		return(TFSERR_USERDENIED);	flags_marked_deleted = fp->flags & ~TFS_ACTIVE;	if (tfsflashwrite(&fp->flags,&flags_marked_deleted,sizeof(long)) < 0)		return(TFSERR_FLASHFAILURE);	tfslog(TFSLOG_DEL,name);	return (TFS_OKAY);}/* tfsrun(): *	Run the named file.  Based on the file flags, the file is either *	executed as a COFF/ELF file with all relocation data in the file *	or run as a simple script of monitor commands. *	MONLIB NOTICE: this function is accessible through monlib.c. */inttfsrun(char **arglist,int verbose){	int		i;	TFILE	*fp;	char	namebak[TFSNAMESIZE+8], *name;	name = arglist[0];	fp = tfsstat(name);	if (!fp)		return(TFSERR_NOFILE);	if (TFS_USRLVL(fp) > getUsrLvl())		return(TFSERR_USERDENIED);	/* Store away the argument list so that it is accessible by the script	 * or executable application about to be run:	 */	for(i=0;arglist[i];i++)		putargv(i,arglist[i]);	putargv(i,(char *)0);	/* If the incoming named file doesn't exist, and that incoming name is	 * the TFS_RCFILE string, then try TFS_RCFILE.bak as an alternative.	 * This allows the user to copy TFS_RCFILE to TFS_RCFILE.bak, then	 * delete/reload TFS_RCFILE.  Note that usually TFS_RCFILE is "monrc".	 */	if (!fp) {		if (!strcmp(name,TFS_RCFILE)) {			sprintf(namebak,"%s.bak",TFS_RCFILE);			fp = tfsstat(namebak);			if (!fp)				return(TFSERR_NOFILE);			name = namebak;			printf("Running %s...\n",namebak);		}		else			return (TFSERR_NOFILE);	}	/* Executable file can be script or binary... */	if (!(fp->flags & (TFS_EXEC|TFS_EBIN)))		return(TFSERR_NOTEXEC);	if (!(fp->flags & TFS_IPMOD)) {		if (crc32(TFS_BASE(fp), fp->filsize) != fp->filcrc)			return(TFSERR_BADCRC);	}	/* Machine code or script... */	if (fp->flags & TFS_EBIN)		return(tfsexec(fp,verbose));	else		return(tfsscript(fp,verbose));}/* tfsnext(): *	Called to retrieve the "next" file in the tfs list.  If *	incoming argument is NULL then return the first file in the list.  If no *	more files, return NULL; else return the tfshdr structure pointer to the *	next (or first) file in the tfs. *	MONLIB NOTICE: this function is accessible through monlib.c. */TFILE *tfsnext(TFILE *fp){	TDEV	*tdp;	TFILE *fpnext;	if (!fp) {		tdp = tfsDeviceTbl;		fpnext = (TFILE *) tfsDeviceTbl[0].start;	}	else {		tdp = gettfsdev(fp);		fpnext = nextfp(fp,0);	}	while(tdp->start != TFSEOT) {		while(validtfshdr(fpnext)) {			if (TFS_FILEEXISTS(fpnext))				return (fpnext);			fpnext = nextfp(fpnext,0);		}		tdp++;		fpnext = (TFILE *)tdp->start;	}	return ((TFILE *) 0);}/* tfsstat(): *	Steps through the list of files until it finds the specified *	filename or reaches the end of the list.  If found, a pointer to that *	file's structure is returned; else return 0. *	MONLIB NOTICE: this function is accessible through monlib.c. */TFILE *tfsstat(char *name){	TDEV	*tdp;	TFILE	*fp;	if (tfsTrace > 0)		printf("tfsstat(%s)\n",name);	for(tdp=tfsDeviceTbl;tdp->start != TFSEOT;tdp++) {		fp = (TFILE *) tdp->start;		while(validtfshdr(fp)) {			if (TFS_FILEEXISTS(fp) && (strcmp(name, fp->name) == 0))				return(fp);			fp = nextfp(fp,tdp);		}	}	return ((TFILE *) 0);}/* tfsfstat(): * Very similar in purpose to tfsstat().  This version is provided to the  * API as a "defrag-safe" version of tfsstat()... * If tfsstat() is called (returning a pointer into TFS memory space), then * a defragmentation occurs, that pointer is stale; hence, the need for  * an alternative that will load the content of the TFILE structure into * an application-supplied block of memory (usually a pointer to a local * TFILE structure).  Using tfsfstat avoids this because if a defrag occurs, * it does not affect the content of the locally stored TFILE structure. * NOTE: * addition of this function to the TFS API was due to the fact that * I did not consider the above described condition when first adding * tfsstat() to the TFS API.  In general, tfsfstat() should be considered * a replacement for all tfsstat() situations that will dereference the * pointer. * NOTE1: * The return value is similar to standard "stat"... Return 0 if * successful, else -1. */inttfsfstat(char *name, TFILE *apptfp){	TFILE	*tfp;	int		otrace;	otrace = tfsTrace;	if (tfsTrace > 0) {		tfsTrace = 0;		printf("tfsfstat(%s)\n",name);	}	tfp = tfsstat(name);	tfsTrace = otrace;		if (!tfp)		return(-1);	*apptfp = *tfp;	return(0);}intshowTfsError(int errno, char *msg){	if (msg)		printf("%s: %s\n",msg,tfserrmsg(errno));	else		printf("%s\n",tfserrmsg(errno));	return(errno);}voidexitscript(char *ignored){	ScriptExitFlag = EXIT_SCRIPT;}char *ExitHelp[] = {	"Exit a script",	"-[r]",	"Options:",	" -r   remove script after exit",	0,};intExit(int argc, char *argv[]){	ScriptExitFlag = EXIT_SCRIPT;	if ((argc == 2) && (!strcmp(argv[1],"-r")))		ScriptExitFlag |= REMOVE_SCRIPT;	return(0);}#else	/* INCLUDE_TFS */char *tfserrmsg(int errno){	return(0);}inttfsinit(void){	return(TFSERR_NOTAVAILABLE);}inttfsfstat(char *name, TFILE *apptfp){	return(TFSERR_NOTAVAILABLE);}TFILE *tfsstat(char *name){	return ((TFILE *) 0);}TFILE *tfsnext(TFILE *fp){	return ((TFILE *) 0);}inttfsrun(char **arglist,int verbose){	return(TFSERR_NOTAVAILABLE);}inttfsunlink(char *name){	return(TFSERR_NOTAVAILABLE);}inttfsadd(char *name, char *info, char *flags, uchar *src, int size){	return(TFSERR_NOTAVAILABLE);}longtfsctrl(int rqst,long arg1,long arg2){	return(TFSERR_NOTAVAILABLE);}#endif	/* INCLUDE_TFS else */

⌨️ 快捷键说明

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