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

📄 tfs.c

📁 完整的Bell实验室的嵌入式文件系统TFS
💻 C
📖 第 1 页 / 共 5 页
字号:
 * to be set prior to crc calculation. * Note also that earlier versions of TFS deleted a file by clearing * the entire flags field.  This made it impossible to do a header crc * check on a deleted file; deletion has been changed to simply clear * the TFS_ACTIVE bit in the flags, so now a deleted file's header can * can be crc tested by simply forcing the TFS_ACTIVE bit high as was * mentioned above. */ulongtfshdrcrc(TFILE *hdr){    TFILE hdrcpy;    hdrcpy = *hdr;    hdrcpy.next = 0;    hdrcpy.hdrcrc = 0;    hdrcpy.flags |= (TFS_NSTALE | TFS_ACTIVE);    return(crc32((uchar *)&hdrcpy,TFSHDRSIZ));}/* validtfshdr(): *  Return 1 if the header pointed to by the incoming header pointer is valid. *  Else return 0.  The header crc is calculated based on the hdrcrc *  and next members of the structure being zero. *  Note that if the file is deleted, then just ignore the crc and return 1. */intvalidtfshdr(TFILE *hdr){    /* A few quick checks... */    if (!hdr || hdr->hdrsize == ERASED16)        return(0);    if (tfshdrcrc(hdr) == hdr->hdrcrc) {        return(1);    }    else {        /* Support transition to new deletion flag method... */        if ((hdr->flags == 0) && tfsOldDelFlagCheckActive)            return(1);                          printf("Bad TFS hdr crc @ 0x%lx\n",(ulong)hdr);        return(0);    }}/* nextfp(): *  Used as a common means of retrieving the next file header pointer.  It *  does some sanity checks based on the fact that all pointers must fall *  within the TFSSTART<->TFSEND memory range and since each file is placed *  just after the previous one in linear memory space, fp->next should *  always be greater than fp. */TFILE *nextfp(TFILE *fp, TDEV *tdp){    if (!tdp)        tdp = gettfsdev(fp);    /* Make some basic in-range checks... */    if ((!tdp) || (fp < (TFILE *)tdp->start) || (fp > (TFILE *)tdp->end) ||        (fp->next < (TFILE *)tdp->start) || (fp->next > (TFILE *)tdp->end)  ||        (fp->next <= fp)) {        printf("Bad TFS hdr ptr @ 0x%lx\n",(ulong)fp);        return(0);    }    return(fp->next);}/* tfsflasherased(): *  Jump to the point in flash after the last file in TFS, then verify *  that all remaining flash  that is dedicated to TFS is erased (0xff). *  If erased, return 1; else return 0. */inttfsflasherased(TDEV *tdp, int verbose){    ulong   *lp;    TFILE   *tfp;    tfp = (TFILE *)tdp->start;    while(validtfshdr(tfp))        tfp = nextfp(tfp,tdp);    lp = (ulong *)tfp;    while (lp < (ulong *)tdp->end) {        if (*lp != ERASED32) {            if (verbose)                printf("End of TFS on %s not erased at 0x%lx\n",                    tdp->prefix,(ulong)lp);            return(0);        }#ifdef WATCHDOG_MACRO        WATCHDOG_MACRO();#endif        lp++;    }    return(1);}static inttfsftot(TDEV *tdpin){    int     ftot;    TFILE   *tfp;    TDEV    *tdp;    ftot = 0;    for (tdp=tfsDeviceTbl;tdp->start != TFSEOT;tdp++) {        if (!tdpin || (tdpin == tdp)) {            tfp = (TFILE *)tdp->start;            while(validtfshdr(tfp)) {                if (TFS_FILEEXISTS(tfp))                    ftot++;                tfp = nextfp(tfp,tdp);            }        }    }    return(ftot);}/* tfsmemuse(): *  Step through one (or all) TFS devices and tally up various memory usage *  totals.  See definition of tfsmem structure for more details. *  If incoming tdpin pointer is NULL, then tally up for all TFS devices; *  otherwise, tally up for only the one device pointed to by tdpin. */inttfsmemuse(TDEV *tdpin, TINFO *tinfo, int verbose){    int     devtot;    char    *cfgerr;    TFILE   *tfp;    TDEV    *tdp;    /* Start by clearing incoming structure... */    tinfo->pso = 0;    tinfo->sos = 0;    tinfo->memtot = 0;    tinfo->liveftot = 0;    tinfo->deadftot = 0;    tinfo->livedata = 0;    tinfo->deaddata = 0;    tinfo->liveovrhd = 0;    tinfo->deadovrhd = 0;    if (verbose) {        printf("TFS Memory Usage...\n     ");        printf(" name    start       end       spare     spsize  scnt type\n");    }    devtot = 0;    for (tdp=tfsDeviceTbl;tdp->start != TFSEOT;tdp++) {        if (!tdpin || (tdpin == tdp)) {            devtot++;            tfp = (TFILE *)tdp->start;            cfgerr = (char *)0;            /* Do some sanity checks on the configuration... */            if ((tdp->spare >= tdp->start) && (tdp->spare <= tdp->end)) {                cfgerr = "spare within storage space";            }            if (cfgerr) {                printf("Bad %s TFS config: %s.\n",tdp->prefix,cfgerr);            }            if (verbose) {                printf("%10s: 0x%08lx|0x%08lx|0x%08lx|0x%06lx|%4ld|0x%lx\n",                    tdp->prefix,(ulong)(tdp->start),(ulong)(tdp->end),                    (ulong)(tdp->spare),tdp->sparesize,                    tdp->sectorcount,(ulong)(tdp->devinfo));            }            tinfo->memtot += ((tdp->end - tdp->start) + 1) + tdp->sparesize;            tinfo->pso += (tdp->sectorcount * 4) + 16;            tinfo->sos += tdp->sparesize;            while(validtfshdr(tfp)) {                if (TFS_FILEEXISTS(tfp)) {                    tinfo->liveftot++;                    tinfo->livedata += TFS_SIZE(tfp);                    tinfo->liveovrhd += (TFSHDRSIZ + DEFRAGHDRSIZ);                }                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 + DEFRAGHDRSIZ));    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){    int     tfscorrupt, filtot;    TFILE   *fp, *fp1;    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;                    break;                }            }            if (!(tfscorrupt & HDR_CORRUPT))                break;            else                goto nextfile;        }        /* Run a crc check on the header even if file is deleted...         */        if (tfshdrcrc(fp) != fp->hdrcrc) {            if (verbose)                printf(" CRC error in hdr @ 0x%lx\n",(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;    }    tfsflasherased(tdp,verbose);    if (tfscorrupt)        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;

⌨️ 快捷键说明

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