?? tfsapi.c
字號(hào):
/* 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.
*/
int
tfstruncate(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.
*/
int
tfseof(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.
*/
int
tfsread(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.
*/
int
tfswrite(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.
*/
int
tfsseek(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.
*/
int
tfsgetline(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.
*/
int
tfsipmod(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.
*/
int
tfsopen(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.
*/
int
tfsclose(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 */
int
tfstruncate(int fd, long len)
{
return(TFSERR_NOTAVAILABLE);
}
int
tfseof(int fd)
{
return(TFSERR_NOTAVAILABLE);
}
int
tfsread(int fd, char *buf, int cnt)
{
return(TFSERR_NOTAVAILABLE);
}
int
tfswrite(int fd, char *buf, int cnt)
{
return(TFSERR_NOTAVAILABLE);
}
int
tfsseek(int fd, int offset, int whence)
{
return(TFSERR_NOTAVAILABLE);
}
int
tfsopen(char *file,long flagmode,char *buf)
{
return(TFSERR_NOTAVAILABLE);
}
int
tfsclose(int fd,char *info)
{
return(TFSERR_NOTAVAILABLE);
}
int
tfsgetline(int fd,char *buf,int max)
{
return(TFSERR_NOTAVAILABLE);
}
int
tfsipmod(char *name,char *buf,int offset,int size)
{
return(TFSERR_NOTAVAILABLE);
}
#endif /* INCLUDE_TFSAPI else */
?? 快捷鍵說(shuō)明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號(hào)
Ctrl + =
減小字號(hào)
Ctrl + -