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

📄 tfs.c

📁 完整的Bell实验室的嵌入式文件系统TFS
💻 C
📖 第 1 页 / 共 5 页
字号:
                retval = tfsclean(tdp,0);            break;        case TFS_DEFRAG:            for(tdp=tfsDeviceTbl;tdp->start != TFSEOT;tdp++)                 tfsclean(tdp,(int)arg1);            retval = 0;            break;        case TFS_FCOUNT:            if (arg1) {                tdp = gettfsdev_fromprefix((char *)arg1,0);                if (!tdp)                    retval = TFSERR_BADARG;                else                    retval = tfsftot(tdp);            }            else {                retval = tfsftot(0);            }            break;        case TFS_DEFRAGON:            retval = tfsclean_on();            break;        case TFS_DEFRAGOFF:            retval = tfsclean_off();            break;        case TFS_UNOPEN:            retval = tfsunopen((int)arg1);            break;        case TFS_FATOB:            retval = tfsflagsatob((char *)arg1,&flag);            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_HEADROOM:            retval = tfsheadroom(arg1);            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 = (int(*)(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, *sfp;    long    bflags;    ulong   endoftfsflash, nextfileaddr, thisfileaddr;    ulong   crc_pass1, crc_pass2, state_table_overhead;    int     ftot, cleanupcount, err, stale, ssize;    if (!info) info = "";    if (!flags) flags = "";    if (tfsTrace > 0)        printf("tfsadd(%s,%s,%s,0x%lx,%d)\n", name,info,flags,(ulong)src,size);    /* Check for valid size and name: */    if ((size <= 0) || (!name))        return(TFSERR_BADARG);    /* If name or info field length is too long, abort now... */    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);    /* If incoming flags are illegal, abort now... */    if (*flags == 0) {        bflags = 0;    }    else {        err = tfsflagsatob(flags,&bflags);        if (err != TFS_OKAY)            return(err);    }    stale = 0;    cleanupcount = 0;    /* Take snapshot of source crc. */    crc_pass1 = crc32(src, size);    /* 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;#if INCLUDE_TFSAUTODEFRAGtryagain:#endif    fp = (TFILE *)tdp->start;    /* Find end of current storage: */    ftot = 0;    while (fp) {        if (fp->hdrsize == ERASED16)            break;        if (TFS_FILEEXISTS(fp)) {            ftot++;            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.                 * Two exceptions to this:                 * 1. If the current file is stale, then we are here                 *    because of a stale-file fixup at system startup.                 * 2. If the src file is in-place-modify then source                  *    data is undefined.                 */                if (!(TFS_STALE(fp))) {                    if (!(bflags & TFS_IPMOD) &&                         (!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, set a flag to indicate that the                     * file should be marked stale just prior to                     * adding the new file.                     */                    stale = 1;                }            }        }        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.     */    thisfileaddr = (ulong)(fp+1);    nextfileaddr = thisfileaddr + 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) * DEFRAGHDRSIZ) +        (tdp->sectorcount * sizeof(struct sectorcrc));    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) ||        (nextfileaddr < thisfileaddr) ||        (!tfsSpaceErased((uchar *)fp,size+TFSHDRSIZ))) {#if INCLUDE_TFSAUTODEFRAG        if (!cleanupcount) {            err = tfsclean(tdp,0);            if (err != TFS_OKAY) {                printf("tfsadd autoclean failed: %s\n",                    (char *)tfsctrl(TFS_ERRMSG,err,0));                return(err);            }            cleanupcount++;            goto tryagain;        }        else#endif            return(TFSERR_FLASHFULL);    }    memset((char *)&tf,0,TFSHDRSIZ);    /* Do another crc on the source data.  If crc_pass1 != crc_pass2 then     * somehow the source is changing.  This is typically caused by the fact     * that the source address is within TFS space that was automatically     * defragmented above.  There is no need to check source data if the     * source is in-place-modifiable.     */    if (!(bflags & TFS_IPMOD)) {        crc_pass2 = crc32(src,size);        if (crc_pass1 != crc_pass2)            return(TFSERR_FLAKEYSOURCE);    }    else        crc_pass2 = ERASED32;    /* Now that we have determined that we have enough space to do the      * copy, if the "stale" flag was set (indicating that there is already     * a file in TFS with the same name as the incoming file), we must now     * mark the file stale...     */    if (stale) {        sfp = (TFILE *)tdp->start;        while (sfp) {            if (sfp->hdrsize == ERASED16)                break;            if (TFS_FILEEXISTS(sfp)) {                if (!strcmp(TFS_NAME(sfp),name)) {                    err = tfsmakeStale(sfp);                    if (err != TFS_OKAY)                        return(err);                    break;                }            }            sfp = nextfp(sfp,tdp);        }        if (!sfp)            return(TFSERR_CORRUPT);    }    /* Copy name and info data to header. */    strcpy(tf.name, name);    strcpy(tf.info, info);    tf.hdrsize = TFSHDRSIZ;    tf.hdrvrsn = TFSHDRVERSION;    tf.filsize = size;    tf.flags = bflags;    tf.flags |= (TFS_ACTIVE | TFS_NSTALE);    tf.filcrc = crc_pass2;    tf.modtime = tfsGetLtime();#if TFS_RESERVED    {    int rsvd;    for(rsvd=0;rsvd<TFS_RESERVED;rsvd++)        tf.rsvd[rsvd] = 0xffffffff;    }#endif    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,0);    if (!fp)        return(TFSERR_NOFILE);    if (TFS_USRLVL(fp) > getUsrLvl())        return(TFSERR_USERDENIED);    flags_marked_deleted = fp->flags & ~TFS_ACTIVE;    if (tfsflashwrite((ulong *)&fp->flags,&flags_marked_deleted,        sizeof(long)) < 0)        return(TFSERR_FLASHFAILURE);    tfslog(TFSLOG_DEL,name);    return (TFS_OKAY);}            inttfslink(char *src, char *target){    TFILE   *tfp;    char    linfo[TFSINFOSIZE+1];    tfp = tfsstat(src);    if (tfp) {        tfp = tfsstat(src);        strcpy(linfo,"->");        strncpy(linfo+2,src,TFSINFOSIZE-1);        linfo[TFSINFOSIZE] = 0;        return(tfsadd(target,linfo,"l",src,strlen(src)+1));    }    return(TFSERR_NOFILE);}/* 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 

⌨️ 快捷键说明

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