/* * trunctest(): * Test file truncation. Verify that file truncates to expected size * and that the data in the file is as expected. */ int trunctest(char *fname, char *data) { int tfd, err, size; TFILE *tfp; /* Copy incoming file name to a tempoary file... */ cp(TMPFILE,fname); /* Open the temporary file and truncate it. * First verify that a truncation size too big will fail, then * do a real truncation. Close the file then verify that the * file has been trunated. */ tfd = mon_tfsopen(TMPFILE,TFS_APPEND,buffer1); if (tfd < 0) tfsdie(tfd); err = mon_tfstruncate(tfd,9999999); if (err != TFSERR_BADARG) tfsdie(err); err = mon_tfstruncate(tfd,TRUNCATE_SIZE); if (err != TFS_OKAY) tfsdie(err); err = mon_tfsclose(tfd,0); if (err < 0) tfsdie(err); /* Make sure that the file was truncated to the proper size. */ tfp = mon_tfsstat(TMPFILE); if (!tfp) die(); if (TFS_SIZE(tfp) != TRUNCATE_SIZE) die(); /* Now reopen the file and verify that the data is correct... */ tfd = mon_tfsopen(TMPFILE,TFS_RDONLY,0); if (tfd < 0) tfsdie(tfd); size = mon_tfsread(tfd,buffer1,TFS_SIZE(tfp)); if (size != TFS_SIZE(tfp)) tfsdie(size); if (memcmp(buffer1,data,TRUNCATE_SIZE)) die(); /* Close and remove the temporary file. */ mon_tfsclose(tfd,0); err = mon_tfsunlink(TMPFILE); if (err != TFS_OKAY) tfsdie(err); return(0); }
/* * cp(): * File Copy... * Use standard TFS facilities to copy one file to another. * If successful, return the size of the copy; else die. */ int cp(char *to, char *from) { TFILE finfo, *tfp; int ffd, tfd, size, ret; char *buffer; /* Open the source file: */ ffd = mon_tfsopen(from,TFS_RDONLY,0); if (ffd < 0) tfsdie(ffd); /* Retrieve stats of the source file: */ tfp = &finfo; if (mon_tfsfstat(from,tfp) == -1) die(); /* The buffer used to open the destination file must be as large as * the source file ... */ buffer = mon_malloc(TFS_SIZE(tfp)); if (!buffer) die(); /* Open the destination file for creation with the same flags * as the source file: */ tfd = mon_tfsopen(to,TFS_CREATE | finfo.flags,buffer); if (tfd < 0) tfsdie(tfd); /* Read the entire source file into buffer, then write the entire * buffer to the destination file... */ size = mon_tfsread(ffd,buffer,TFS_SIZE(tfp)); if (size < 0) tfsdie(size); ret = mon_tfswrite(tfd,buffer,TFS_SIZE(tfp)); if (ret != TFS_OKAY) tfsdie(ret); mon_tfsclose(ffd,0); mon_tfsclose(tfd,finfo.info); mon_free(buffer); return(TFS_SIZE(tfp)); }
/* * cmp(): * File Compare... * Use the standard TFS facilities to compare two different incoming files. * Return 0 if files match, else -1. */ int cmp(char *f1, char *f2) { TFILE finfo1, *tfp1; TFILE finfo2, *tfp2; int fd1, fd2, size, ret; char *buf1, *buf2; /* Check sizes first: */ tfp1 = &finfo1; if (mon_tfsfstat(f1,tfp1) == -1) die(); tfp2 = &finfo2; if (mon_tfsfstat(f2,tfp2) == -1) die(); if (tfp1->filsize != tfp2->filsize) return(-1); /* Copy f1 to buffer: */ buf1 = mon_malloc(TFS_SIZE(tfp1)); if (!buf1) die(); fd1 = mon_tfsopen(f1,TFS_RDONLY,0); if (fd1 < 0) tfsdie(fd1); size = mon_tfsread(fd1,buf1,TFS_SIZE(tfp1)); if (size != TFS_SIZE(tfp1)) tfsdie(size); ret = mon_tfsclose(fd1,0); if (ret != TFS_OKAY) tfsdie(ret); /* Copy f2 to buffer: */ buf2 = mon_malloc(TFS_SIZE(tfp2)); if (!buf2) die(); fd2 = mon_tfsopen(f2,TFS_RDONLY,0); if (fd2 < 0) tfsdie(fd2); size = mon_tfsread(fd2,buf2,TFS_SIZE(tfp2)); if (size != TFS_SIZE(tfp2)) tfsdie(size); ret = mon_tfsclose(fd2,0); if (ret != TFS_OKAY) tfsdie(ret); /* Compare the buffers: */ if (memcmp(buf1,buf2,TFS_SIZE(tfp2))) ret = -1; else ret = 0; mon_free(buf1); mon_free(buf2); return(ret); }
/* fatfsPut(): * Copy data or file to a FATFS file. * * Input: * char *fatfspath * Pointer to FATFS file and path. * char *src * Pointer to TFS filename or a addr,len string. * The expected "addr,len" syntax is 0xADDR,LEN or 0xADDR,0xLEN. */ static int fatfsPut(char *src, char *fatfspath) { FILEINFO fi; char tfs, *p, *cp; uint32_t successcount, len, size, rc; if (strncmp(src,"0x",2) == 0) { tfs = 0; p = (char *)strtoul(src,&cp,0); cp++; len = strtoul(cp,0,0); } else { #if INCLUDE_TFS TFILE *tfp; tfs = 1; if ((tfp = tfsstat(src)) == 0) { printf("Can't find file '%s' in TFS\n",src); return(CMD_FAILURE); } p = TFS_BASE(tfp); len = TFS_SIZE(tfp); #else printf("TFS not built in\n"); return(-1); #endif } /* Copy 'len' bytes from 'p' to DOSFS file 'fatfspath'... */ if (DFS_OpenFile(&vi, (uint8_t *)fatfspath, DFS_WRITE, sector, &fi)) { printf("error opening '%s'\n",fatfspath); return(-1); } while(len > 0) { if (len >= SECTOR_SIZE) size = SECTOR_SIZE; else size = len; rc = DFS_WriteFile(&fi, sector2, (uint8_t *)p, &successcount, size); if ((rc != DFS_OK) || (successcount != size)) { printf("error writing '%s'\n",fatfspath); return(-1); } p += size; len -= size; } return(0); }
int fs_open(char *name, struct fs_file *file) { TFILE *tfp; char *prefix, namebuf[TFSNAMESIZE+1]; char *origname; /* Look for the specified file in TFS. If found, then * return it; else return the nofile string above. */ origname = name; prefix = mon_getenv(HTTP_PREFIX_VARNAME); if (prefix) { if ((strlen(name) + strlen(prefix) + 1) < sizeof(namebuf)) { mon_sprintf(namebuf,"%s%s",prefix,name); name = namebuf; } } tfp = mon_tfsstat(name); if (!tfp) { file->data = (char *)nofile; file->len = strlen(nofile); } else { /* If the file ends with ".html", then parse it for ${XXX} tokens. * and whenver XXX is a valid shell variable in uMon, replace the * ${XXX} with the content of the variable (see convert_vars() above). */ if (strstr(name,".html")) { file->len = convert_vars(TFS_BASE(tfp),TFS_SIZE(tfp)); file->data = filebuf; } else { file->data = TFS_BASE(tfp); file->len = TFS_SIZE(tfp); } } return(1); }
/* appendtest(): * Create a file, then append to it and verify content after * closing the file. */ int appendtest(char *fname, char *data1, char *data2) { TFILE finfo, *tfp; int err, tfd, len; /* Create the first version of the file: */ err = mon_tfsadd(fname,0,0,data1,strlen(data1)); if (err != TFS_OKAY) tfsdie(err); /* Append to that first file: */ tfd = mon_tfsopen(fname,TFS_APPEND,buffer1); if (tfd < 0) tfsdie(tfd); err = mon_tfswrite(tfd,data2,strlen(data2)); if (err != TFS_OKAY) tfsdie(err); err = mon_tfsclose(tfd,0); if (err != TFS_OKAY) tfsdie(err); /* Verify that the file was properly appended to: */ tfp = &finfo; if (mon_tfsfstat(fname,tfp) == -1) die(); len = strlen(data1) + strlen(data2); if (len != TFS_SIZE(tfp)) die(); tfd = mon_tfsopen(fname,TFS_RDONLY,0); if (tfd < 0) tfsdie(tfd); err = mon_tfsread(tfd,buffer1,len); if (err != len) tfsdie(err); strcpy(buffer2,data1); strcat(buffer2,data2); if (memcmp(buffer1,buffer2,len) != 0) die(); mon_tfsclose(tfd,0); return(0); }
int nandCmd(int argc,char *argv[]) { unsigned long addr; char *cmd, *dest, *src; int opt, len, rc; rc = 0; nandVerbose = 0; while((opt=getopt(argc,argv,"v")) != -1) { switch(opt) { case 'v': nandVerbose++; break; default: return(CMD_PARAM_ERROR); } } if(argc < optind+1) { return(CMD_PARAM_ERROR); } cmd = argv[optind]; if(nandVerbose) { printf("CMD: %s\n",cmd); } if(strcmp(cmd,"init") == 0) { nandInit(); } else if(strcmp(cmd,"info") == 0) { nandInfo(); } else if(strcmp(cmd,"erase") == 0) { if(argc != optind+3) { return(CMD_PARAM_ERROR); } addr = strtoul(argv[optind+1],0,0); len = (int)strtol(argv[optind+2],0,0); nandEraseChunk((char *)addr,len); } else if(strcmp(cmd,"write") == 0) { if(argc != optind+4) { return(CMD_PARAM_ERROR); } addr = strtoul(argv[optind+1],0,0); src = (char *)strtoul(argv[optind+2],0,0); len = (int)strtol(argv[optind+3],0,0); nandWriteChunk((char *)addr,src,len); } else if(strcmp(cmd,"read") == 0) { if(argc != optind+4) { return(CMD_PARAM_ERROR); } addr = strtoul(argv[optind+1],0,0); dest = (char *)strtoul(argv[optind+2],0,0); len = (int)strtol(argv[optind+3],0,0); nandReadChunk((char *)addr,dest,len); } #ifdef FLASHRAM_BASE else if(strcmp(cmd,"tfsload") == 0) { } else if(strcmp(cmd,"tfsstore") == 0) { } else if(strcmp(cmd,"tfserase") == 0) { } else if(strcmp(cmd, "tfsls") == 0) { int ftot; char *addr; TFILE tfshdr, *fp; ftot = 0; fp = &tfshdr; addr = (char *)BASE_OF_NAND; while(addr < (char *)END_OF_NAND) { char fbuf[32], *flags; if((rc = nandReadChunk(addr,(char *)fp,TFSHDRSIZ)) < 0) { printf("nandReadChunk failed %d\n",rc); break; } if(fp->hdrsize == 0xffff) { break; } if(TFS_FILEEXISTS(fp)) { if(ftot == 0) { printf(" Name Size Offset Flags Info\n"); } ftot++; flags = tfsflagsbtoa(TFS_FLAGS(fp),fbuf); if((!flags) || (!fbuf[0])) { flags = " "; } printf(" %-23s %7ld 0x%08lx %-5s %s\n",TFS_NAME(fp), TFS_SIZE(fp),(unsigned long)(addr+TFSHDRSIZ), flags,TFS_INFO(fp)); } addr += TFS_SIZE(fp); addr += TFSHDRSIZ; while((long)addr & 0xf) { addr++; } } } else if(strcmp(cmd, "tfsrm") == 0) { char *addr; TFILE tfshdr, *fp; char *arg2 = argv[optind+1]; fp = &tfshdr; addr = (char *)BASE_OF_NAND; while(addr < (char *)END_OF_NAND) { if((rc = nandReadChunk(addr,(char *)fp,TFSHDRSIZ)) < 0) { printf("nandReadChunk failed %d\n",rc); break; } if(fp->hdrsize == 0xffff) { printf("%s not found\n",arg2); break; } if(strcmp(TFS_NAME(fp),arg2) == 0) { if(TFS_FILEEXISTS(fp)) { fp->flags &= ~TFS_ACTIVE; if((rc = nandWriteChunk(addr,(char *)fp,TFSHDRSIZ)) < 0) { printf(" write_hdr failed %d\n",rc); } break; } } addr += TFS_SIZE(fp); addr += TFSHDRSIZ; while((long)addr & 0xf) { addr++; } } } else if(strcmp(cmd, "tfsadd") == 0) { int size; long bflags; TFILE tfshdr, *fp; char *addr; char *src, *name, *info; char *arg2 = argv[optind+1]; char *arg3 = argv[optind+2]; char *arg4 = argv[optind+3]; char *icomma, *fcomma; info = ""; bflags = 0; name = arg2; addr = (char *)BASE_OF_NAND; /* The incoming arguments can be either just the filename (in which * case we assume the source is the file in TFS with the same name), * or the filename, source address and size... */ if(argc == optind+2) { // Just filename? if((fp = tfsstat(name)) == (TFILE *)0) { printf("File '%s' not in TFS\n",name); return(CMD_FAILURE); } name = fp->name; info = fp->info; bflags = fp->flags; size = fp->filsize; src = (char *)(fp + 1); fp = &tfshdr; memset((char *)fp,0,TFSHDRSIZ); } else if(argc == optind+4) { // Filename with addr and len // Extract flags and info fields (if any) from the name... fcomma = strchr(name,','); if(fcomma) { icomma = strchr(fcomma+1,','); if(icomma) { *icomma = 0; info = icomma+1; } *fcomma = 0; bflags = tfsctrl(TFS_FATOB,(long)(fcomma+1),0); } fp = &tfshdr; memset((char *)fp,0,TFSHDRSIZ); size = (int)strtol(arg4,0,0); src = (char *)strtoul(arg3,0,0); } else { return(CMD_PARAM_ERROR); } while(addr < (char *)END_OF_NAND) { if((rc = nandReadChunk(addr,(char *)fp,TFSHDRSIZ)) < 0) { break; } if(fp->hdrsize == 0xffff) { unsigned long nextfileaddr; /* We're at the address in NAND where we can add the new * file, but first we need to make sure there's enough * room... */ if((TFSHDRSIZ + size + 16) >= ((char *)END_OF_NAND - addr)) { printf(" not enough space\n"); return(CMD_FAILURE); } /* Copy name and info data to header. */ strcpy(fp->name, name); strcpy(fp->info, info); fp->hdrsize = TFSHDRSIZ; fp->hdrvrsn = TFSHDRVERSION; fp->filsize = size; fp->flags = bflags; fp->flags |= (TFS_ACTIVE | TFS_NSTALE); fp->filcrc = crc32((unsigned char *)src,size); fp->modtime = tfsGetLtime(); #if TFS_RESERVED { int rsvd; for(rsvd=0; rsvd<TFS_RESERVED; rsvd++) { fp->rsvd[rsvd] = 0xffffffff; } } #endif fp->next = 0; fp->hdrcrc = 0; fp->hdrcrc = crc32((unsigned char *)fp,TFSHDRSIZ); nextfileaddr = NAND_TFSRAM_BASE - NAND_TFS_BASE + (long)addr + TFSHDRSIZ + size; if(nextfileaddr & 0xf) { nextfileaddr = (nextfileaddr | 0xf) + 1; } fp->next = (TFILE *)nextfileaddr; printf(" writing %s...\n",arg2); if((rc = nandWriteChunk(addr,(char *)fp,TFSHDRSIZ)) < 0) { printf(" write_hdr failed %d\n",rc); } if((rc = nandWriteChunk(addr+TFSHDRSIZ,src,size)) < 0) { printf(" write_file failed %d\n",rc); } break; } if(strcmp(TFS_NAME(fp),arg2) == 0) { if(TFS_FILEEXISTS(fp)) { printf(" removing %s...\n",arg2); fp->flags &= ~TFS_ACTIVE; if((rc = nandWriteChunk(addr,(char *)fp,TFSHDRSIZ)) < 0) { printf(" write_hdr failed %d\n",rc); } } } addr += TFS_SIZE(fp); addr += TFSHDRSIZ; while((long)addr & 0xf) { addr++; } } } else if(strcmp(cmd, "tfsstat") == 0) { char *addr, *oaddr; TFILE tfshdr, *fp; unsigned long meminuse, memdead; fp = &tfshdr; meminuse = memdead = 0; addr = (char *)BASE_OF_NAND; while(addr < (char *)END_OF_NAND) { if((rc = nandReadChunk(addr,(char *)fp,TFSHDRSIZ)) < 0) { printf("nandReadChunk failed %d\n",rc); break; } if(fp->hdrsize == 0xffff) { break; } oaddr = addr; addr += TFS_SIZE(fp); addr += TFSHDRSIZ; while((long)addr & 0xf) { addr++; } if(TFS_FILEEXISTS(fp)) { meminuse += addr - oaddr; } else { memdead += addr - oaddr; } } printf("Total: 0x%x, used: 0x%x, dead: 0x%x, avail: 0x%x\n", SIZE_OF_NAND, meminuse, memdead, SIZE_OF_NAND - (meminuse + memdead)); } #endif else { return(CMD_PARAM_ERROR); } return(CMD_SUCCESS); }
/* _tfsclean(): * This is an alternative to the complicated defragmentation above. * It simply scans through the file list and copies all valid files * to RAM; then flash is erased and the RAM is copied back to flash. * <<< WARNING >>> * THIS FUNCTION SHOULD NOT BE INTERRUPTED AND IT WILL BLOW AWAY * ANY APPLICATION CURRENTLY IN CLIENT RAM SPACE. */ int _tfsclean(TDEV *tdp, int notused, int verbose) { ulong appramstart; TFILE *tfp, *lasttfp; uchar *tbuf, *cp1, *cp2; int dtot, nfadd, len, err, chkstat; if (TfsCleanEnable < 0) return(TFSERR_CLEANOFF); appramstart = getAppRamStart(); /* Determine how many "dead" files exist. */ dtot = 0; tfp = (TFILE *)tdp->start; while(validtfshdr(tfp)) { if (!TFS_FILEEXISTS(tfp)) dtot++; tfp = nextfp(tfp,tdp); } if (dtot == 0) return(TFS_OKAY); printf("TFS device '%s' non-powersafe defragmentation\n",tdp->prefix); tbuf = (uchar *)appramstart; lasttfp = tfp = (TFILE *)(tdp->start); nfadd = tdp->start; while(validtfshdr(tfp)) { if (TFS_FILEEXISTS(tfp)) { len = TFS_SIZE(tfp) + sizeof(struct tfshdr); if (len % TFS_FSIZEMOD) len += TFS_FSIZEMOD - (len % TFS_FSIZEMOD); nfadd += len; if (s_memcpy((char *)tbuf,(char *)tfp,len,0,0) != 0) return(TFSERR_MEMFAIL); ((struct tfshdr *)tbuf)->next = (struct tfshdr *)nfadd; tbuf += len; } lasttfp = tfp; tfp = nextfp(tfp,tdp); } /* We've now copied all of the active files from flash to ram. * Now we want to see how much of the flash space needs to be * erased. We only need to erase the sectors that have changed... */ cp1 = (uchar *)tdp->start; cp2 = (uchar *)appramstart; while(cp2 < tbuf) { if (*cp1 != *cp2) break; cp1++; cp2++; } #if INCLUDE_FLASH if ((cp2 != tbuf) || (!TFS_FILEEXISTS(lasttfp))) { int first, last; if (addrtosector(cp1,&first,0,0) == -1) return(TFSERR_FLASHFAILURE); if (addrtosector((uchar *)tdp->end,&last,0,0) == -1) return(TFSERR_FLASHFAILURE); printf("Erasing sectors %d-%d...\n",first,last); while(first<last) { if (flasherase(first++) == 0) return(TFSERR_FLASHFAILURE); } } #endif /* Copy data placed in RAM back to flash: */ printf("Restoring flash...\n"); if (TFS_DEVTYPE_ISRAM(tdp)) { memcpy((char *)(tdp->start),(char *)appramstart, (tbuf-(uchar*)appramstart)); } else { #if INCLUDE_FLASH err = AppFlashWrite((uchar *)(tdp->start),(uchar *)appramstart, (tbuf-(uchar*)appramstart)); if (err < 0) #endif return(TFSERR_FLASHFAILURE); } /* All defragmentation is done, so verify sanity of files... */ chkstat = tfscheck(tdp,verbose); return(chkstat); }
/* _tfsclean(): * This is an alternative to the complicated defragmentation above. * It simply scans through the file list and copies all valid files * to RAM; then flash is erased and the RAM is copied back to flash. * <<< WARNING >>> * THIS FUNCTION SHOULD NOT BE INTERRUPTED AND IT WILL BLOW AWAY * ANY APPLICATION CURRENTLY IN CLIENT RAM SPACE. */ int _tfsclean(TDEV *tdp, int notused, int verbose) { TFILE *tfp; uchar *tbuf; ulong appramstart; int dtot, nfadd, len, err, chkstat; if (TfsCleanEnable < 0) return(TFSERR_CLEANOFF); appramstart = getAppRamStart(); /* Determine how many "dead" files exist. */ dtot = 0; tfp = (TFILE *)tdp->start; while(validtfshdr(tfp)) { if (!TFS_FILEEXISTS(tfp)) dtot++; tfp = nextfp(tfp,tdp); } if (dtot == 0) return(TFS_OKAY); printf("Reconstructing device %s with %d dead file%s removed...\n", tdp->prefix, dtot,dtot>1 ? "s":""); tbuf = (char *)appramstart; tfp = (TFILE *)(tdp->start); nfadd = tdp->start; while(validtfshdr(tfp)) { if (TFS_FILEEXISTS(tfp)) { len = TFS_SIZE(tfp) + sizeof(struct tfshdr); if (len % TFS_FSIZEMOD) len += TFS_FSIZEMOD - (len % TFS_FSIZEMOD); nfadd += len; if (s_memcpy(tbuf,(uchar *)tfp,len,0,0) != 0) return(TFSERR_MEMFAIL); ((struct tfshdr *)tbuf)->next = (struct tfshdr *)nfadd; tbuf += len; } tfp = nextfp(tfp,tdp); } /* Erase the flash device: */ err = _tfsinit(tdp); if (err != TFS_OKAY) return(err); /* Copy data placed in RAM back to flash: */ err = AppFlashWrite((ulong *)(tdp->start),(ulong *)appramstart, (tbuf-(uchar*)appramstart)); if (err < 0) return(TFSERR_FLASHFAILURE); /* All defragmentation is done, so verify sanity of files... */ chkstat = tfscheck(tdp,verbose); return(chkstat); }
/* writetest(): * Open the specified file in APPEND (modify) mode. Seek into the file * and read 1 byte. Increment that byte by one and then write it back * to the same location from which it was read. Then, close the file. * Build a new file that is what "should" be the content of the file we * just modified and compare the two files. They better match. * This function also verifies TFS_HEADROOM. */ int writetest(char *fname, char *newdata) { TFILE *tfp; char c; long headroom; int size, tfd, err; /* Open the source file: */ tfp = mon_tfsstat(fname); if (!tfp) die(); size = TFS_SIZE(tfp); tfd = mon_tfsopen(fname,TFS_APPEND,buffer1); if (tfd < 0) tfsdie(tfd); headroom = mon_tfsctrl(TFS_HEADROOM,tfd,0); if (headroom != 0) die(); err = mon_tfsseek(tfd,3,TFS_BEGIN); if (err != 3) tfsdie(err); headroom = mon_tfsctrl(TFS_HEADROOM,tfd,0); if (headroom != (size-3)) die(); err = mon_tfsread(tfd,&c,1); if (err != 1) tfsdie(err); headroom = mon_tfsctrl(TFS_HEADROOM,tfd,0); if (headroom != (size-4)) die(); c++; err = mon_tfsseek(tfd,-1,TFS_CURRENT); if (err != 3) tfsdie(err); headroom = mon_tfsctrl(TFS_HEADROOM,tfd,0); if (headroom != (size-3)) die(); err = mon_tfswrite(tfd,&c,1); if (err != TFS_OKAY) tfsdie(err); headroom = mon_tfsctrl(TFS_HEADROOM,tfd,0); if (headroom != (size-4)) die(); mon_tfsclose(tfd,0); /* Add a new file that "should" be identical to the modified file; * then compare them and delete the newfile... */ err = mon_tfsadd(TMPFILE,"newdata1","2",newdata,strlen(newdata)); if (err != TFS_OKAY) tfsdie(err); if (cmp(fname,TMPFILE) != 0) die(); err = mon_tfsunlink(TMPFILE); if (err != TFS_OKAY) tfsdie(err); return(0); }
/* seektest(): * Run some tests on tfsseek(). * Verify that the character in the file specified at the incoming offset * is as expected. Seek to beyond the end of file and verify error, etc... */ int seektest(char *fname, int offset, char value) { char c, buf1[16], buf2[16]; TFILE *tfp; int tfd, end, err; /* Open the source file: */ tfd = mon_tfsopen(fname,TFS_RDONLY,0); if (tfd < 0) tfsdie(tfd); if (mon_tfsseek(tfd,offset,TFS_BEGIN) != offset) tfsdie(tfd); if (mon_tfsread(tfd,&c,1) != 1) tfsdie(tfd); if (c != value) die(); tfp = mon_tfsstat(fname); if (!tfp) die(); end = TFS_SIZE(tfp); /* * Seek to various limits in the file and verify proper return * value... */ err = mon_tfsseek(tfd,0,TFS_BEGIN); if (err != 0) tfsdie(err); err = mon_tfsseek(tfd,end,TFS_CURRENT); if (err != end) tfsdie(err); err = mon_tfsseek(tfd,1,TFS_CURRENT); if (err != TFSERR_EOF) tfsdie(err); err = mon_tfsseek(tfd,end,TFS_BEGIN); if (err != end) tfsdie(err); err = mon_tfsseek(tfd,end+1,TFS_BEGIN); if (err != TFSERR_EOF) tfsdie(err); err = mon_tfsseek(tfd,0,TFS_BEGIN); if (err != 0) tfsdie(err); err = mon_tfsseek(tfd,-1,TFS_CURRENT); if (err != TFSERR_EOF) tfsdie(err); err = mon_tfsseek(tfd,end,TFS_BEGIN); if (err != end) tfsdie(err); err = mon_tfsseek(tfd,-1,TFS_CURRENT); if (err != end-1) tfsdie(err); err = mon_tfsseek(tfd,2,TFS_CURRENT); if (err != TFSERR_EOF) tfsdie(err); /* Seek to beginning, read 10, seek to beginning again read 10 again. * Verify that both reads have same data. */ err = mon_tfsseek(tfd,0,TFS_BEGIN); if (err != 0) tfsdie(err); err = mon_tfsread(tfd,buf1,10); if (err != 10) tfsdie(err); err = mon_tfsseek(tfd,0,TFS_BEGIN); if (err != 0) tfsdie(err); err = mon_tfsread(tfd,buf2,10); if (err != 10) tfsdie(err); if (memcmp(buf1,buf2,10)) die(); /* * Seek to end, then verify that read() returns EOF and tfs_eof() * returns true. */ err = mon_tfsseek(tfd,end,TFS_BEGIN); if (err != end) tfsdie(err); err = mon_tfsread(tfd,buf1,1); if (err != TFSERR_EOF) tfsdie(err); if (mon_tfseof(tfd) != 1) die(); mon_tfsclose(tfd,0); return(0); }