📄 tfscli.c
字号:
/* 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 + -