/* * 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); }
/* * inusetest(): * Open a file, then try to remove it or add a file with the same name. * This should fail... */ int inusetest(char *fname) { int tfd, err; /* Open a file, then try to run tfsadd() on it or try to remove it... */ tfd = mon_tfsopen(fname,TFS_RDONLY,0); if (tfd < 0) tfsdie(tfd); err = mon_tfsunlink(fname); if (err != TFSERR_FILEINUSE) tfsdie(err); err = mon_tfsadd(fname,0,0,buffer1,10); if (err != TFSERR_FILEINUSE) tfsdie(err); mon_tfsclose(tfd,0); return(0); }
int main(int argc,char *argv[]) { int err, opt, removefiles, list; char *file1, *file2; verbose = 0; list = 0; removefiles = 1; getoptinit(); while((opt=getopt(argc,argv,"lrv")) != -1) { switch(opt) { case 'l': list = 1; break; case 'r': removefiles = 0; break; case 'v': verbose++; break; default: usage(0); } } if (argc != optind+2) usage("Bad arg count"); /* Test all aspects of TFS API calls: */ file1 = argv[optind]; file2 = argv[optind+1]; if ((!strcmp(file1,TMPFILE)) || (!strcmp(file2,TMPFILE))) usage(TMPFILE); if (verbose) mon_printf("tfstest %s %s...\n",file1,file2); /* * Start by removing files to be created later... */ if (mon_tfsstat(TMPFILE)) { if (verbose) mon_printf("Removing %s...\n",TMPFILE); err = mon_tfsunlink(TMPFILE); if (err != TFS_OKAY) tfsdie(err); } if (mon_tfsstat(file1)) { if (verbose) mon_printf("Removing %s...\n",file1); err = mon_tfsunlink(file1); if (err != TFS_OKAY) tfsdie(err); } if (mon_tfsstat(file2)) { if (verbose) mon_printf("Removing %s...\n",file2); err = mon_tfsunlink(file2); if (err != TFS_OKAY) tfsdie(err); } /* * Create a file... */ if (verbose) mon_printf("Creating %s...\n",file1); err = mon_tfsadd(file1,"data1","2",data1,strlen(data1)); if (err != TFS_OKAY) tfsdie(err); /* * Basic getline test... */ if (verbose) mon_printf("Checking 'getline'...\n"); getlinetest(file1,data1); /* * Now copy the file... */ if (verbose) mon_printf("Copying %s to %s...\n",file1,file2); cp(file2,file1); /* * Now compare the two... * (they should be identical) */ if (verbose) mon_printf("Comparing %s to %s...\n",file1,file2); if (cmp(file1,file2) != 0) die(); /* * Seek test... * Verify that data at a specified offset is as expected based on the * file (file1) initially created from the data1 array... */ if (verbose) mon_printf("Running seek test on %s...\n",file1); seektest(file1,38,data1[38]); /* * Truncateion test... * Truncate a file and verify. */ if (verbose) mon_printf("Running truncation test on %s...\n",file1); trunctest(file1,data1); /* * Tfsctrl() function test... */ if (verbose) mon_printf("Running tfsctrl test...\n"); ctrltest(file1,data1); /* * Write test... * Modify a file in a few different ways and verify the modification... * Note that after this point, file1 and data1 are not the same. * The content of file1 will be the same as the new_data1 array. */ if (verbose) mon_printf("Running write test on %s...\n",file1); writetest(file1,new_data1); /* * File in-use test... * Verify that if a file is in-use, it cannot be removed. */ if (verbose) mon_printf("Running in-use test on %s...\n",file1); inusetest(file1); /* * Append test... * Verify that a file can be properly appended to. */ if (verbose) mon_printf("Running append test on %s...\n",file1); appendtest(file1,"this_is_some_data","this_is_the_appended_data"); /* * If the -r option is not set, then remove the files... */ if (removefiles) { if (mon_tfsstat(file1)) { err = mon_tfsunlink(file1); if (err != TFS_OKAY) tfsdie(err); } if (mon_tfsstat(file2)) { err = mon_tfsunlink(file2); if (err != TFS_OKAY) tfsdie(err); } if (mon_tfsstat(TMPFILE)) { err = mon_tfsunlink(TMPFILE); if (err != TFS_OKAY) tfsdie(err); } } if (list) ls(); /* All error cases checked above would have resulted in an exit * of this application, so if we got here, the testing must * have succeeded... */ mon_printf("TFS test on %s & %s PASSED\n",file1,file2); mon_appexit(0); return(0); }
/* * ctrltest(): * Test various aspects of the tfsctrl() function. */ void ctrltest(char *fname, char *data) { int tfd, ret; char flags[16]; /* Copy fname to TMPFILE... */ cp (TMPFILE,fname); /* Verify TFS_UNOPEN... * Open a file, modify it, then prior to calling tfsclose(), call * tfsctrl(TFS_UNOPEN) on that file descriptor and make sure the * file is in its original state and the file descriptor has been * closed... */ tfd = mon_tfsopen(fname,TFS_APPEND,buffer1); if (tfd < 0) tfsdie(tfd); ret = mon_tfswrite(tfd,"abcdefg",7); if (ret != TFS_OKAY) tfsdie(ret); ret = mon_tfsctrl(TFS_UNOPEN,tfd,0); if (ret != TFS_OKAY) tfsdie(ret); ret = mon_tfsclose(tfd,0); if (ret != TFSERR_BADFD) tfsdie(ret); if (cmp(TMPFILE,fname)) die(); /* Verify TFS_TELL... * Open a file, seek to a known point, then make sure that * tfsctrl(TFS_TELL) returns the expected offset. */ tfd = mon_tfsopen(fname,TFS_RDONLY,0); if (tfd < 0) tfsdie(tfd); ret = mon_tfsseek(tfd,5,TFS_BEGIN); if (ret != 5) tfsdie(ret); ret = mon_tfsctrl(TFS_TELL,tfd,0); if (ret != 5) tfsdie(ret); ret = mon_tfsread(tfd,buffer1,3); if (ret != 3) tfsdie(ret); ret = mon_tfsctrl(TFS_TELL,tfd,0); if (ret != 5+3) tfsdie(ret); ret = mon_tfsclose(tfd,0); if (ret != TFS_OKAY) tfsdie(ret); /* Test all "flag-ascii-to-binary" conversions... */ if ((ret = mon_tfsctrl(TFS_FATOB,(long)"e",0)) != TFS_EXEC) tfsdie(ret); if ((ret = mon_tfsctrl(TFS_FATOB,(long)"b",0)) != TFS_BRUN) tfsdie(ret); if ((ret = mon_tfsctrl(TFS_FATOB,(long)"B",0)) != TFS_QRYBRUN) tfsdie(ret); #if 0 if ((ret = mon_tfsctrl(TFS_FATOB,(long)"C",0)) != TFS_COFF) tfsdie(ret); if ((ret = mon_tfsctrl(TFS_FATOB,(long)"E",0)) != TFS_ELF) tfsdie(ret); if ((ret = mon_tfsctrl(TFS_FATOB,(long)"A",0)) != TFS_AOUT) tfsdie(ret); #else if ((ret = mon_tfsctrl(TFS_FATOB,(long)"E",0)) != TFS_EBIN) tfsdie(ret); #endif if ((ret = mon_tfsctrl(TFS_FATOB,(long)"c",0)) != TFS_CPRS) tfsdie(ret); if ((ret = mon_tfsctrl(TFS_FATOB,(long)"i",0)) != TFS_IPMOD) tfsdie(ret); if ((ret = mon_tfsctrl(TFS_FATOB,(long)"u",0)) != TFS_UNREAD) tfsdie(ret); if ((ret = mon_tfsctrl(TFS_FATOB,(long)"1",0)) != TFS_ULVL1) tfsdie(ret); if ((ret = mon_tfsctrl(TFS_FATOB,(long)"2",0)) != TFS_ULVL2) tfsdie(ret); if ((ret = mon_tfsctrl(TFS_FATOB,(long)"3",0)) != TFS_ULVL3) tfsdie(ret); /* Test all "flag-binary-to-ascii" conversions... */ ret = mon_tfsctrl(TFS_FBTOA,TFS_EXEC,(long)flags); if ((ret == TFSERR_BADARG) || (strcmp(flags,"e"))) tfsdie(ret); ret = mon_tfsctrl(TFS_FBTOA,TFS_BRUN,(long)flags); if ((ret == TFSERR_BADARG) || (strcmp(flags,"b"))) tfsdie(ret); ret = mon_tfsctrl(TFS_FBTOA,TFS_QRYBRUN,(long)flags); if ((ret == TFSERR_BADARG) || (strcmp(flags,"B"))) tfsdie(ret); #if 0 ret = mon_tfsctrl(TFS_FBTOA,TFS_COFF,(long)flags); if ((ret == TFSERR_BADARG) || (strcmp(flags,"C"))) tfsdie(ret); ret = mon_tfsctrl(TFS_FBTOA,TFS_ELF,(long)flags); if ((ret == TFSERR_BADARG) || (strcmp(flags,"E"))) tfsdie(ret); ret = mon_tfsctrl(TFS_FBTOA,TFS_AOUT,(long)flags); if ((ret == TFSERR_BADARG) || (strcmp(flags,"A"))) tfsdie(ret); #else ret = mon_tfsctrl(TFS_FBTOA,TFS_EBIN,(long)flags); if ((ret == TFSERR_BADARG) || (strcmp(flags,"E"))) tfsdie(ret); #endif ret = mon_tfsctrl(TFS_FBTOA,TFS_CPRS,(long)flags); if ((ret == TFSERR_BADARG) || (strcmp(flags,"c"))) tfsdie(ret); ret = mon_tfsctrl(TFS_FBTOA,TFS_IPMOD,(long)flags); if ((ret == TFSERR_BADARG) || (strcmp(flags,"i"))) tfsdie(ret); ret = mon_tfsctrl(TFS_FBTOA,TFS_UNREAD,(long)flags); if ((ret == TFSERR_BADARG) || (strcmp(flags,"u"))) tfsdie(ret); ret = mon_tfsctrl(TFS_FBTOA,TFS_ULVL1,(long)flags); if ((ret == TFSERR_BADARG) || (strcmp(flags,"1"))) tfsdie(ret); ret = mon_tfsctrl(TFS_FBTOA,TFS_ULVL2,(long)flags); if ((ret == TFSERR_BADARG) || (strcmp(flags,"2"))) tfsdie(ret); ret = mon_tfsctrl(TFS_FBTOA,TFS_ULVL3,(long)flags); if ((ret == TFSERR_BADARG) || (strcmp(flags,"3"))) tfsdie(ret); ret = mon_tfsunlink(TMPFILE); if (ret != TFS_OKAY) tfsdie(ret); }
/* 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); }
/* * The routine which does most of the work for the IMFS open handler * The full_path_name here is all text AFTER the TFS_PATHNAME_PREFIX * string, so if the filename is "/TFS/abc", the full_path_name string * is "abc"... * * Attempts to remap the incoming flags to TFS equivalent. * Its not a perfect mapping, but gets pretty close. * A comma-delimited path is supported to allow the user * to specify TFS-stuff (flag string, info string, and a buffer). * For example: * abc,e,script,0x400000 * This is a file called "abc" that will have the TFS 'e' flag * and the TFS info field of "script". The storage buffer is * supplied by the user at 0x400000. */ static int rtems_tfs_open_worker( rtems_libio_t *iop, char *path, int oflag, mode_t mode ) { static int beenhere = 0; long flagmode; int tfdidx, tfd; struct tfdinfo *tip; char *buf, *fstr, *istr, *bstr, pathcopy[TFSNAMESIZE*3+1]; if (RTEMS_TFS_DEBUG) printk("_open_r(%s,0x%" PRIx32 ",0x%" PRIx32 ")\n",path,oflag,mode); if (!beenhere) { newlib_tfdlock(); for(tfdidx=0; tfdidx<MAXTFDS; tfdidx++) tfdtable[tfdidx].inuse = 0; tfdtable[0].inuse = 1; /* fake entry for stdin */ tfdtable[1].inuse = 1; /* fake entry for stdout */ tfdtable[2].inuse = 1; /* fake entry for stderr */ newlib_tfdunlock(); beenhere = 1; } istr = fstr = bstr = buf = (char *)0; /* Copy the incoming path to a local array so that we can safely * modify the string... */ if (strlen(path) > TFSNAMESIZE*3) { return(ENAMETOOLONG); } strcpy(pathcopy,path); /* The incoming string may have commas that are used to delimit the * name from the TFS flag string, TFS info string and buffer. * Check for the commas and test for maximum string length... */ fstr = strchr(pathcopy,','); if (fstr) { *fstr++ = 0; istr = strchr(fstr,','); if (istr) { *istr++ = 0; bstr = strchr(istr,','); if (bstr) *bstr++ = 0; } } if (strlen(pathcopy) > TFSNAMESIZE) { return(ENAMETOOLONG); } if (istr) { if (strlen(istr) > TFSNAMESIZE) { return(ENAMETOOLONG); } } /* If O_EXCL and O_CREAT are set, then fail if the file exists... */ if ((oflag & (O_CREAT | O_EXCL)) == (O_CREAT | O_EXCL)) { if (mon_tfsstat((char *)pathcopy)) { return(EEXIST); } } /* Only a few flag combinations are supported... * O_RDONLY Simple read-only * O_WRONLY | O_APPEND Each write starts at end of file * O_WRONLY | O_TRUNC If file exists, truncate it * O_WRONLY | O_CREAT Create if it doesn't exist * O_WRONLY | O_CREAT | O_EXCL Fail if file exists */ switch(oflag & O_ACCMODE) { case O_RDONLY: flagmode = TFS_RDONLY; break; case O_WRONLY|O_APPEND: flagmode = TFS_APPEND; break; case O_WRONLY|O_TRUNC: case O_WRONLY|O_CREAT|O_TRUNC: mon_tfsunlink((char *)pathcopy); flagmode = TFS_CREATE|TFS_APPEND; break; case O_WRONLY|O_CREAT: case O_WRONLY|O_CREAT|O_APPEND: flagmode = TFS_CREATE|TFS_APPEND; break; case O_RDWR: case O_WRONLY|O_CREAT|O_EXCL: flagmode = TFS_CREATE|TFS_APPEND; break; default: printk("_open_r(): flag 0x%i not supported\n",oflag); return(ENOTSUP); } /* Find an open slot in our tfd table: */ newlib_tfdlock(); for(tfdidx=0; tfdidx<MAXTFDS; tfdidx++) { if (tfdtable[tfdidx].inuse == 0) break; } if (tfdidx == MAXTFDS) { newlib_tfdunlock(); return(EMFILE); } tip = &tfdtable[tfdidx]; tip->inuse = 1; newlib_tfdunlock(); /* If file is opened for something other than O_RDONLY, then * we need to allocate a buffer for the file.. * WARNING: It is the user's responsibility to make sure that * the file size does not exceed this buffer. Note that the * buffer may be specified as part of the comma-delimited path. */ if (flagmode == TFS_RDONLY) { buf = (char *)0; } else { if (bstr) buf = (char *)strtol(bstr,0,0); else buf = malloc(MAXFILESIZE); if (!buf) { newlib_tfdlock(); tip->inuse = 0; newlib_tfdunlock(); return(ENOMEM); } } /* Deal with tfs flags and tfs info fields if necessary: */ if (fstr) { long bflag; bflag = mon_tfsctrl(TFS_FATOB,(long)fstr,0); if (bflag == -1) { return(EINVAL); } flagmode |= bflag; } if (istr) strcpy(tip->info,istr); else tip->info[0] = 0; tfd = mon_tfsopen((char *)pathcopy,flagmode,buf); if (tfd >= 0) { tip->tfd = tfd; tip->buf = buf; strcpy(tip->name,pathcopy); iop->data0 = (uint32_t)tfdidx; return(0); } else { printk("%s: %s\n",pathcopy, (char *)mon_tfsctrl(TFS_ERRMSG,tfd,0)); } if (buf) free(buf); newlib_tfdlock(); tip->inuse = 0; newlib_tfdunlock(); return(EINVAL); }