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

📄 tfscli.c

📁 可移到ucos上的文件系统
💻 C
📖 第 1 页 / 共 2 页
字号:
/* tfscli.c:
 *	This file contains the TFS code that is only needed if the "tfs" command
 *	is included in the command set.
 *
 *	General notice:
 *	This code is part of a boot-monitor package developed as a generic base
 *	platform for embedded system designs.  As such, it is likely to be
 *	distributed to various projects beyond the control of the original
 *	author.  Please notify the author of any enhancements made or bugs found
 *	so that all may benefit from the changes.  In addition, notification back
 *	to the author will allow the new user to pick up changes that may have
 *	been made by other users after this version of the code was distributed.
 *
 *	Author:	Ed Sutter
 *	email:	esutter@lucent.com		(home: lesutter@worldnet.att.net)
 *	phone:	908-582-2351			(home: 908-889-5161)
 */
#include "config.h"
#include "stddefs.h"
#include "genlib.h"
#include "tfs.h"

#if INCLUDE_TFSCLI

/* tfsprflags():
 *   Print the specified set of flags.
 */
static void
tfsprflags(long flags, int verbose)
{
	struct	tfsflg	*tfp;

	if (verbose)
		printf(" Flags: ");
	tfp = tfsflgtbl;
	while(tfp->sdesc) {
		if ((flags & tfp->mask) == tfp->flag) {
			if (verbose) {
				printf("%s", tfp->ldesc);
				if ((tfp+1)->flag)
					printf(", ");
			}
			else
				putchar(tfp->sdesc);
		}
		tfp++;
	}
	if (verbose)
		printf("\n");
}

static char *
tfsmodebtoa(ulong mode,char *buf)
{
	char	*pipe, *bp;

	pipe = "";
	bp = buf;
	*bp = 0;
	if (mode & TFS_RDONLY) {
		bp += sprintf(bp,"rdonly");
		pipe = "|";
	}
	if (mode & TFS_CREATE) {
		bp += sprintf(bp,"%screate",pipe);
		pipe = "|";
	}
	if (mode & TFS_APPEND)
		sprintf(bp,"%sappend",pipe);

	return(buf);
}

/* tfsld():
 *	If the filename specified is AOUT, COFF or ELF, then load it.
 */
static int
tfsld(char *name,int verbose,int verifyonly)
{
	int		err;
	TFILE	*fp;

	err = TFS_OKAY;
	fp = tfsstat(name);

	if (!fp)
		return (TFSERR_NOFILE);

	if (TFS_USRLVL(fp) > getUsrLvl())
		return(TFSERR_USERDENIED);

	if (fp->flags & TFS_EBIN) {
		long	entry;

		err = tfsloadebin(fp,verbose,&entry,verifyonly);
		if (err == TFS_OKAY) {
			char buf[16];
			sprintf(buf,"0x%lx",entry);
			setenv("ENTRYPOINT",buf);
		}
		else
			setenv("ENTRYPOINT",0);
	}
	else
		err = TFSERR_BADHDR;
	
	return(err);
}

#if COMMENTS
listfilter():
	If the incoming filename (fname) passes the incoming filter, then
	return 1; else return 0.

	Examples:
		if filter is "*.html" and fname is "index.html" return 1.
		if filter is "dir/*" and fname is "dir/abc" return 1.
		if filter is "abc" and fname is "abc" return 1.

	Notes:
		* A valid filter will have the asterisk as either the first or last
		  character of the filter.  If first, assume filter is a suffix, 
		  if last (or none at all), assume filter is a prefix.
		* If there is an asterisk in the middle of the filter, it is chopped
		  at the asterisk without warning.
#endif
static int
listfilter(char *filter,char *fname)
{
	int		flen;
	char	*prefix, *suffix, *asterisk, *sp;

	if (!filter)		/* No filter means match everything. */
		return(1);

	flen = 0;
	prefix = suffix = (char *)0;
	asterisk = strchr(filter,'*');

	/* If no asterisk, then just compare filter to fname... */
	if (!asterisk) {
		if (!strcmp(filter,fname))
			return(1);
	}
	else if (asterisk == filter) {
		suffix = asterisk+1;
		flen = strlen(suffix);
		sp = fname + strlen(fname) - flen;
		if (!strcmp(suffix,sp))
			return(1);
	}
	else {
		*asterisk = 0;
		prefix = filter;
		flen = strlen(prefix);
		if (!strncmp(prefix,fname,flen)) {
			*asterisk = '*';
			return(1);
		}
		*asterisk = '*';
	}
	return(0);
}

/* tfsvlist():	verbose list...
 *	Display all files currently stored.  Do not put them in alphabetical
 *	order; display them as they are physically listed in the file system.
 *	Display complete structure of file header for each file.
 *	Note1: This version of file listing is only called if "tfs -vv ls"
 *	or "tfs -vvv ls" is called.  The first level of verbosity is handled
 *	by tfsqlist to simply display the "dot" files.
 */
static int
tfsvlist(char *filter[], int verbose, int more)
{
	TDEV	*tdp;
	TFILE	*fp;
	int		tot;
	char	tbuf[32], **fltrptr;

	tot = 0;
	for(tdp=tfsDeviceTbl;tdp->start != TFSEOT;tdp++) {
		fltrptr = filter;
		while(1) {
			fp = (TFILE *)tdp->start;
			while(validtfshdr(fp)) {
				if ((TFS_DELETED(fp)) && (verbose < 3)) {
					fp = nextfp(fp,tdp);
					continue;
				}
				if (!listfilter(*fltrptr,TFS_NAME(fp))) {
					fp = nextfp(fp,tdp);
					continue;
				}
				if ((fp->flags & TFS_UNREAD) && (TFS_USRLVL(fp)>getUsrLvl())) {
					fp = nextfp(fp,tdp);
					continue;
				}
				if (TFS_FILEEXISTS(fp))
					printf(" Name:  '%s'\n", fp->name);
				else
					printf(" Name:  '%s' (deleted)\n", fp->name);
				printf(" Info:  '%s'\n", fp->info);
				if (TFS_FILEEXISTS(fp))
					tfsprflags(fp->flags, 1);
				printf(" Addr:  0x%lx (hdr @ 0x%lx, nxtptr = 0x%lx)\n",
					(ulong)(TFS_BASE(fp)),(ulong)fp,(ulong)(fp->next));
				printf(" Size:  0x%lx (%ld) bytes\n", fp->filsize, fp->filsize);
				if (TFS_TIME(fp) != TIME_UNDEFINED)
					printf(" Time:  %s\n",
						tfsGetAtime(TFS_TIME(fp),tbuf,sizeof(tbuf)));
				printf("\n");
				tot++;
				fp = nextfp(fp,tdp);
				if ((more) && ((tot % more) == 0)) {
					if (!More())
						return(TFS_OKAY);
				}
			}
			/* If this or the next pointer is null, terminate loop now... */
			if (!*fltrptr) break;
			fltrptr++;
			if (!*fltrptr) break;
		}
	}
	printf("\nTotal: %d accessible file%s.\n",tot,tot == 1 ? "" : "s");
	return (TFS_OKAY);
}

/* tfsqlist():	quick list...
 *	Display list of files in alphabetical order.
 *	Display only the name and flag summary.
 *
 *	To support listing of files in a bit of an orderly manner, if this
 *	function sees that a filename has a slash in it, it will only print the
 *	characters upto and including the first slash.  This gives the appearance
 *	of a directory structure, even though there really isn't one.
 *	For example, if there are three files...
 *			CONFIG/file1
 *			CONFIG/file2
 *			CONFIG/file3
 *	then if no filter is specified, then that listing will be replaced with
 *			CONFIG/
 *	printed only once.  To display all the files prefixed with CONFIG/, the
 *	user must type "tfs ls CONFIG/\*".
 *	
 *	Note: a file with a leading dot ('.') is invisible unless verbose is set.
 */
static int
tfsqlist(char *filter[], int verbose, int more)
{
	TFILE	*fp;
	char	dirname[TFSNAMESIZE+1], tmpname[TFSNAMESIZE+1];
	char	*name, fbuf[16], **fltrptr, *slash, *flags;
	int		idx, sidx, filelisted, err;

	if ((err = tfsreorder()) < 0)
		return(err);

	filelisted = 0;
	dirname[0] = 0;
	fltrptr = filter;
	printf(" Name                        Size   Location   Flags  Info\n");
	while(1) {
		idx = 0;
		while((fp = tfsAlist[idx])) {
			name = TFS_NAME(fp);
			if (((name[0] == '.') && (!verbose)) ||
				(!listfilter(*fltrptr,name)) ||
				((fp->flags & TFS_UNREAD) && (TFS_USRLVL(fp) > getUsrLvl()))) {
				idx++;
				continue;
			}

			/* If name contains a slash, process it differently (but ignore */
			/* any leading slashes) */
			strcpy(tmpname,TFS_NAME(fp));
			for(sidx=0;sidx<TFSNAMESIZE;sidx++) {
				if (tmpname[sidx] != '/')
					break;
			}
			slash = strchr(&tmpname[sidx],'/');
			if (slash && !*fltrptr) {
				char tmp;

				tmp = *(slash+1);
				*(slash+1) = 0;
				if (strcmp(dirname,tmpname)) {
					filelisted++;
					printf(" %s\n",tmpname);
					strcpy(dirname,tmpname);
					*(slash+1) = tmp;
				}
				else {
					idx++;
					*(slash+1) = tmp;
					continue;
				}
			}
			else {
				filelisted++;
				flags = tfsflagsbtoa(TFS_FLAGS(fp),fbuf);
				if ((!flags) || (!fbuf[0]))
					flags = " ";
				printf(" %-23s  %7ld  0x%08lx  %-5s  %s\n",TFS_NAME(fp),
					TFS_SIZE(fp),(ulong)(TFS_BASE(fp)),flags,TFS_INFO(fp));
			}
			idx++;
			if ((more) && !(filelisted % more)) {
				if (!More())
					return(TFS_OKAY);
			}
		}
		/* If this or the next pointer is null, terminate loop now... */
		if (!*fltrptr) break;
		fltrptr++;
		if (!*fltrptr) break;
	}
	printf("\nTotal: %d item%s listed.\n",filelisted,
		filelisted == 1 ? "" : "s");
	return (TFS_OKAY);
}

/* tfsrm():
 *	Remove all files that pass the incoming filter.
 *	This replaces the older tfs rm stuff in Tfs().
 */
static int
tfsrm(char *filter[])
{
	TFILE	*fp;
	char	*name, **fltrptr;
	int		idx, err, rmtot;

	if ((err = tfsreorder()) < 0)
		return(err);

	fltrptr = filter;
	while (*fltrptr) {
		idx = rmtot = 0;
		while((fp = tfsAlist[idx])) {
			name = TFS_NAME(fp);
			if (listfilter(*fltrptr,name)) {
				if ((err = tfsunlink(name)) != TFS_OKAY) 
					printf("%s: %s\n",name,(char *)tfsctrl(TFS_ERRMSG,err,0));
				rmtot++;
			}
			idx++;
		}
		/* This function will potentially delete many files, but if the */
		/* filter doesn't match at least one file, indicate that... */
		if (!rmtot)
			printf("%s: file not found\n",*fltrptr);
		fltrptr++;
	}

	return(TFS_OKAY);
}

static int
tfscheckfile(name)
char	*name;
{
	TFILE	*fp;
	TDEV	*tdp;
	int		corrupted;

	corrupted = 0;

	for(tdp=tfsDeviceTbl;tdp->start != TFSEOT;tdp++) {
		fp = (TFILE *)tdp->start;
		while(validtfshdr(fp)) {
			if (TFS_FILEEXISTS(fp) && (!strcmp(name,fp->name)) &&
			   (!(fp->flags & TFS_IPMOD))) {
				if (crc32(TFS_BASE(fp),fp->filsize) != fp->filcrc) {
					printf("TFS crc check failure on '%s'\n",
					    fp->name);
					corrupted = 1;
				}
				break;
			}
			fp = nextfp(fp,tdp);
		}
	}
	if (corrupted) {
		putchar(0x07);	/* Keyboard beep */
		printf("Corrupt File System\n");
		printf("Refer to User Manual for Instructions\n");
		return(TFSERR_CORRUPT);
	}
	return(TFS_OKAY);
}

/* tfscat():
 *	Print each character of the file until NULL terminate. Replace
 *	each instance of CR or LF with CRLF.
 */
static void
tfscat(TFILE *fp, int more)
{
	int	i, lcnt;
	char	*cp;

⌨️ 快捷键说明

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