📄 tfs.c
字号:
} 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 4inttfscheck(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);}voidtfsclear(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 voidtfsstalecheck(){ 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. */voidtfsoldstyleflagcheck(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. * */voidtfsdevtblinit(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. */voidtfsstartup(){ tfsdevtblinit(); tfsclear((TDEV *)0); tfsfixup(3,0); tfsstalecheck(); tfsoldstyleflagcheck();}/* tfsexec: Treat the file as machine code that is COFF or ELF. */static inttfsexec(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. */inttfsmemset(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. */inttfsmemcpy(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 + -