📄 tfsapi.c
字号:
/* tfsapi.c: * This file contains the portion of TFS that provides the function-level * API to the application. If this is not being used by the application * then it can be omitted from the monitor build. * Note that not all of the api-specific code is here; some of it is in * tfs.c. This is because the the MicroMonitor uses some of the api itself, * so it cannot be omitted from the TFS package without screwing up some * other monitor functionality that needs it. * * 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 "cpu.h"#include "stddefs.h"#include "genlib.h"#include "tfs.h"#if INCLUDE_TFSAPI/* tfstruncate(): * To support the ability to truncate a file (make it smaller); this * function allows the user to adjust the high-water point of the currently * opened (and assumed to be opened for modification) file and replaces * that with the incoming argument. This replacement is only done if the * current high-water point is higher than the incoming length. * MONLIB NOTICE: this function is accessible through monlib.c. */inttfstruncate(int fd, long len){ struct tfsdat *tdat; /* Verify valid range of incoming file descriptor. */ if ((fd < 0) || (fd >= TFS_MAXOPEN)) return(TFSERR_BADFD); tdat = &tfsSlots[fd]; /* Make sure the file pointed to by the incoming descriptor is active * and that the incoming length is greater than the current high-water * point... */ if (tdat->offset == -1) return(TFSERR_BADFD); if (len > tdat->hwp) return(TFSERR_BADARG); /* Make the adjustment... */ tdat->hwp = len; return(TFS_OKAY);}/* tfseof(): * Return 1 if at the end of the file, else 0 if not at end; else negative * if error. * MONLIB NOTICE: this function is accessible through monlib.c. */inttfseof(int fd){ struct tfsdat *tdat; /* Verify valid range of incoming file descriptor. */ if ((fd < 0) || (fd >= TFS_MAXOPEN)) return(TFSERR_BADARG); tdat = &tfsSlots[fd]; /* Make sure the file pointed to by the incoming descriptor is active. */ if (tdat->offset == -1) return(TFSERR_BADFD); if (tdat->offset >= tdat->hdr.filsize) return(1); else return(0);}/* tfsread(): * Similar to a standard read call to a file. * MONLIB NOTICE: this function is accessible through monlib.c. */inttfsread(int fd, char *buf, int cnt){ struct tfsdat *tdat; uchar *from; if (tfsTrace > 1) printf("tfsread(%d,0x%lx,%d)\n",fd,(ulong)buf,cnt); /* Verify valid range of incoming file descriptor. */ if ((cnt < 1) || (fd < 0) || (fd >= TFS_MAXOPEN)) return(TFSERR_BADARG); tdat = &tfsSlots[fd]; /* Make sure the file pointed to by the incoming descriptor is active. */ if (tdat->offset == -1) return(TFSERR_BADFD); if (tdat->offset >= tdat->hdr.filsize) return(TFSERR_EOF); from = (uchar *) tdat->base + tdat->offset; /* If request size is within the range of the file and current * then copy the data to the requestors buffer, increment offset * and return the count. */ if ((tdat->offset + cnt) <= tdat->hdr.filsize) { if (tfsmemcpy(buf, from, cnt,0,0) != 0) return(TFSERR_MEMFAIL); } /* If request size goes beyond the size of the file, then copy * to the end of the file and return that smaller count. */ else { cnt = tdat->hdr.filsize - tdat->offset; if (tfsmemcpy(buf, from, cnt, 0, 0) != 0) return(TFSERR_MEMFAIL); } tdat->offset += cnt; tdat->wptr += cnt; return(cnt);}/* tfswrite(): * Similar to a standard write call to a file. * MONLIB NOTICE: this function is accessible through monlib.c. */inttfswrite(int fd, char *buf, int cnt){ struct tfsdat *tdat; if (tfsTrace > 1) printf("tfswrite(%d,0x%lx,%d)\n", fd,(ulong)buf,cnt); /* Verify valid range of incoming file descriptor. */ if ((cnt < 1) || (fd < 0) || (fd >= TFS_MAXOPEN)) return(TFSERR_BADARG); /* Make sure the file pointed to by the incoming descriptor is active. */ if (tfsSlots[fd].offset == -1) return(TFSERR_BADARG); tdat = &tfsSlots[fd]; /* Make sure file is not opened as read-only */ if (tdat->flagmode & TFS_RDONLY) return(TFSERR_RDONLY); if (tfsmemcpy(tdat->wptr,buf,cnt,0,0) != 0) return(TFSERR_MEMFAIL); tdat->wptr += cnt; tdat->offset += cnt; /* If new offset is greater than current high-water point, then * adjust the high water point so that it is always reflecting the * highest offset into which the file has had some data written. */ if (tdat->offset > tdat->hwp) tdat->hwp = tdat->offset; return(TFS_OKAY);}/* tfsseek(): * Adjust the current pointer into the specified file. * If file is read-only, then the offset cannot exceed the file size; * otherwise, the only check made to the offset is that it is positive. * MONLIB NOTICE: this function is accessible through monlib.c. */inttfsseek(int fd, int offset, int whence){ int o_offset; uchar *o_wptr; struct tfsdat *tdat; if ((fd < 0) || (fd >= TFS_MAXOPEN)) return(TFSERR_BADARG); tdat = &tfsSlots[fd]; o_offset = tdat->offset; o_wptr = tdat->wptr; switch (whence) { case TFS_BEGIN: tdat->offset = offset; tdat->wptr = tdat->base+offset; break; case TFS_CURRENT: tdat->offset += offset; tdat->wptr += offset; break; default: return(TFSERR_BADARG); } /* If new offset is less than zero or if the file is read-only and the * new offset is greater than the file size, return EOF... */ if ((tdat->offset < 0) || ((tdat->flagmode & TFS_RDONLY) && (tdat->offset > tdat->hdr.filsize))){ tdat->offset = o_offset; tdat->wptr = o_wptr; return(TFSERR_EOF); } return(TFS_OKAY);}/* tfsgetline(): * Read into the buffer a block of characters upto the next CR or LF in * the file. After the CR/LF, or after max-1 chars are loaded, terminate * with a NULL. Return the number of characters loaded. * At end of file return 0. * MONLIB NOTICE: this function is accessible through monlib.c. */inttfsgetline(int fd,char *buf,int max){ int cnt; uchar *from, *fromtmp; struct tfsdat *tdat; max--; if (tfsTrace > 1) printf("tfsgetline(%d,0x%lx,%d)\n",fd,(ulong)buf,max); /* Verify valid range of incoming file descriptor. */ if ((max < 1) || (fd < 0) || (fd >= TFS_MAXOPEN)) return(TFSERR_BADARG); /* Make sure the file pointed to by the incoming descriptor is active. */ if (tfsSlots[fd].offset == -1) return(TFSERR_BADARG); tdat = &tfsSlots[fd]; if (tdat->offset == -1) return(TFSERR_BADFD); if (tdat->offset >= tdat->hdr.filsize) return(0); from = (uchar *) tdat->base + tdat->offset; /* Determine the count based on the presence (or lack thereof) of a * carriage return or line feed... */ for(fromtmp=from,cnt=0;cnt<max && *fromtmp;cnt++,fromtmp++) { if ((*fromtmp == '\r') || (*fromtmp == '\n')) { cnt++; break; } } /* If request size is within the range of the file and current * then copy the data to the requestors buffer, increment offset * and return the count. */ if ((tdat->offset + cnt) <= tdat->hdr.filsize) { if (tfsmemcpy(buf, from, cnt,0,0) != 0) return(TFSERR_MEMFAIL); } /* If request size goes beyond the size of the file, then copy * to the end of the file and return that smaller count. */ else { cnt = tdat->hdr.filsize - tdat->offset; if (tfsmemcpy(buf, from, cnt, 0, 0) != 0) return(TFSERR_MEMFAIL); } buf[cnt] = 0; tdat->offset += cnt; return(cnt);}/* tfsipmod(): * Modify "in-place" a portion of a file in TFS. * This is a cheap and dirty way to modify a file... * The idea is that a file is created with a lot of writeable flash space * (data = 0xff). This function can then be called to immediately modify * blocks of space in that flash. It will not do any tfsunlink/tfsadd, and * it doesn't even require a tfsopen() tfsclose() wrapper. Its a fast and * efficient way to modify flash in the file system. * Arguments: * name = name of the file to be in-place-modified; * buf = new data to be written to flash; * offset = offset into file into which new data is to be written; * size = size of new data (in bytes). * * With offset of -1, set offset to location containing first 0xff value. * MONLIB NOTICE: this function is accessible through monlib.c. */inttfsipmod(char *name,char *buf,int offset,int size){ TFILE *fp; uchar *cp; fp = tfsstat(name); if (!fp) return (TFSERR_NOFILE); if (!(fp->flags & TFS_IPMOD)) return(TFSERR_NOTIPMOD); if (offset == -1) { cp = (uchar *)(TFS_BASE(fp)); for (offset=0;offset<fp->filsize;offset++,cp++) { if (*cp == 0xff) break; } } else if (offset < -1) return(TFSERR_BADARG); if ((offset + size) > fp->filsize) return(TFSERR_WRITEMAX); if (tfsflashwrite((ulong *)(TFS_BASE(fp))+offset,(ulong *)buf,size) == -1) return (TFSERR_FLASHFAILURE); tfslog(TFSLOG_IPM,name); return(TFS_OKAY);}/* tfsopen(): * Open a file for reading or creation. If file is opened for writing, * then the caller must provide a RAM buffer pointer to be used for * the file storage until it is transferred to flash by tfsclose(). * Note that the "buf" pointer is only needed for opening a file for * creation or append (writing). * MONLIB NOTICE: this function is accessible through monlib.c. */inttfsopen(char *file,long flagmode,char *buf){ register int i; int errno, retval; long fmode; TFILE *fp; struct tfsdat *slot; /* See if file exists... */ fp = tfsstat(file); /* If file exists, do a crc32 on the data... */ if (fp) { if (crc32(TFS_BASE(fp),fp->filsize) != fp->filcrc) { retval = TFSERR_BADCRC; goto done; } } errno = TFS_OKAY; fmode = flagmode & (TFS_RDONLY | TFS_APPEND | TFS_CREATE); /* This switch verifies... * - that the file exists if TFS_RDONLY or TFS_APPEND * - that the file does not exist if TFS_CREATE */ switch(fmode) { case TFS_RDONLY: /* Read existing file only, no change to file at all. */ if (!fp) errno = TFSERR_NOFILE; else { if ((fp->flags & TFS_UNREAD) && (TFS_USRLVL(fp) > getUsrLvl())) errno = TFSERR_USERDENIED; } break; case TFS_APPEND: /* Append to the end of the current file. */ if (!fp) errno = TFSERR_NOFILE; else { if (TFS_USRLVL(fp) > getUsrLvl()) errno = TFSERR_USERDENIED; } break; case TFS_CREATE: /* Create a new file */ if (fp) errno = TFSERR_FILEEXISTS; break; case (TFS_APPEND|TFS_CREATE): /* If both mode bits are set, clear one */ if (fp) { /* based on the presence of the file. */ if (TFS_USRLVL(fp) > getUsrLvl()) errno = TFSERR_USERDENIED; fmode = TFS_APPEND; } else { fmode = TFS_CREATE; } break; default: errno = TFSERR_BADARG; break; } if (errno != TFS_OKAY) { retval = errno; goto done; } slot = tfsSlots; for (i=0;i<TFS_MAXOPEN;i++,slot++) { if (slot->offset == -1) { slot->hwp = 0; slot->offset = 0; slot->flagmode = fmode; if (fmode & TFS_CREATE) { strncpy(slot->hdr.name,file,TFSNAMESIZE); slot->flagmode |= (flagmode & TFS_FLAGMASK); slot->base = (uchar *)buf; slot->wptr = (uchar *)buf; } else if (fmode & TFS_APPEND) { slot->hdr = *fp; if (tfsmemcpy(buf,(uchar *)(TFS_BASE(fp)), fp->filsize,0,0) != 0) { retval = TFSERR_MEMFAIL; goto done; } slot->flagmode = fp->flags; slot->flagmode |= TFS_APPEND; slot->base = (uchar *)buf; slot->wptr = (uchar *)buf+fp->filsize; slot->hwp = fp->filsize; slot->offset = fp->filsize; } else { slot->base = (uchar *) (TFS_BASE(fp)); slot->wptr = 0; slot->hdr = *fp; } break; } } if (i == TFS_MAXOPEN) retval = TFSERR_NOSLOT; else retval = i;done: if (tfsTrace > 0) printf("tfsopen(%s,0x%lx,0x%lx)=%d\n",file,flagmode,(ulong)buf,retval); return(retval);}/* tfsclose(): * If the file was opened for reading only, then just close out the * entry in the tfsSlots table. If the file was opened for creation, * then add it to the tfs list. Note the additional argument is * only needed for tfsclose() of a newly created file. * info = additional text describing the file. * MONLIB NOTICE: this function is accessible through monlib.c. */inttfsclose(int fd,char *info){ int err; struct tfsdat *tdat; if (tfsTrace > 0) printf("tfsclose(%d,%s)\n",fd,info); if ((fd < 0) || (fd >= TFS_MAXOPEN)) return(TFSERR_BADARG); tdat = &tfsSlots[fd]; if (tdat->offset == -1) return(TFSERR_BADFD); /* Mark the file as closed by setting the offset to -1. * Note that this is done prior to potentially calling tfsadd() so * that tfsadd() will not think the file is opened and reject the add... */ tdat->offset = -1; /* If the file was opened for creation or append, then add it now. */ if (tdat->flagmode & (TFS_CREATE | TFS_APPEND)) { char buf[16]; err = tfsadd(tdat->hdr.name, info, tfsflagsbtoa(tdat->flagmode,buf), tdat->base, tdat->hwp); if (err != TFS_OKAY) { printf("%s: %s\n",tdat->hdr.name,tfserrmsg(err)); return(err); } } return(TFS_OKAY);}#else /* INCLUDE_TFSAPI */inttfstruncate(int fd, long len){ return(TFSERR_NOTAVAILABLE);}inttfseof(int fd){ return(TFSERR_NOTAVAILABLE);}inttfsread(int fd, char *buf, int cnt){ return(TFSERR_NOTAVAILABLE);}inttfswrite(int fd, char *buf, int cnt){ return(TFSERR_NOTAVAILABLE);}inttfsseek(int fd, int offset, int whence){ return(TFSERR_NOTAVAILABLE);}inttfsopen(char *file,long flagmode,char *buf){ return(TFSERR_NOTAVAILABLE);}inttfsclose(int fd,char *info){ return(TFSERR_NOTAVAILABLE);}inttfsgetline(int fd,char *buf,int max){ return(TFSERR_NOTAVAILABLE);}inttfsipmod(char *name,char *buf,int offset,int size){ return(TFSERR_NOTAVAILABLE);}#endif /* INCLUDE_TFSAPI else */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -