diff src/cs/drivers/drv_app/ffs/board/tffs.c @ 0:4e78acac3d88

src/{condat,cs,gpf,nucleus}: import from Selenite
author Mychaela Falconia <falcon@freecalypso.org>
date Fri, 16 Oct 2020 06:23:26 +0000
parents
children
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/cs/drivers/drv_app/ffs/board/tffs.c	Fri Oct 16 06:23:26 2020 +0000
@@ -0,0 +1,767 @@
+  /******************************************************************************
+ * Flash File System (ffs)
+ * Idea, design and coding by Mads Meisner-Jensen, mmj@ti.com
+ *
+ * ffs test scaffold/framework
+ *
+ * $Id: tffs.c 1.12.1.1.1.20 Fri, 19 Dec 2003 12:00:13 +0100 tsj $
+ *
+ ******************************************************************************/
+
+#ifndef TARGET
+#include "ffs.cfg"
+#endif
+
+#include "ffs/ffs.h"
+#include "ffs/board/core.h"
+#include "ffs/board/tffs.h"
+#include "ffs/board/tdata.h"
+#include "ffs/board/tmffs.h"
+#include "ffs/board/ffstrace.h"
+
+#if (TARGET == 1)
+#include "ffs/board/task.h"
+#endif
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <ctype.h>
+
+
+/******************************************************************************
+ * Prototypes and Globals
+ ******************************************************************************/
+
+struct dir_s dir;
+struct stat_s stat;
+struct xstat_s xstat;
+
+int error;
+#if (TARGET == 1)
+int smallbuf_size = 512;
+int bigbuf_size = 65536;
+
+#else
+int smallbuf_size = 1024;
+int bigbuf_size = 1024*1024*8;
+#endif
+
+char *smallbuf = 0;
+char *bigbuf = 0;
+
+
+/******************************************************************************
+ * Globals and Main
+ ******************************************************************************/
+
+extern struct testcase_s testcase[];
+
+struct test_s {
+    char *name;     // name of currently executing test case
+    int  numcases;  // number of test cases run so far
+    int  numcalls;  // total number of ffs function calls so far
+    int  numfails;  // total number of failed test cases
+    int  keepgoing; // keep going when a test case fails
+} test;
+
+struct ffs_params_s param;
+
+
+/******************************************************************************
+ * Main Functions
+ ******************************************************************************/
+
+effs_t ffs_initialize(void);
+effs_t ffs_exit(void);
+
+// Each test case returns zero on success, non-zero on failure.
+// test_execute() decides whether to continue with remaining test cases or
+// not.
+
+#if (TARGET == 0)
+void test_listall(void)
+{
+    struct testcase_s *p;
+
+    printf("Test Cases:\n");
+    for (p = testcase; p->name != 0; p++) {
+        printf("%8s: %s\n", p->name, p->comment);
+    }
+}
+#endif
+
+// <tests> is a comma-separated string of names of the test cases to
+// run. Return number of test cases that failed. This is typically only 1,
+// unless arg_keepgoing is set in which case it can be several.
+int test_run(char *tests)
+{
+    struct testcase_s *ptc;
+    int i, failed, tparams[FFS_TESTCASE_PARAMS_MAX];
+    struct this_test_s this;
+    char *pname, *testsnew;
+
+    failed = 0;
+
+    while (*tests != 0 && (failed == 0 || test.keepgoing))
+    {
+        // Make local copy of test case name. We have to make local copies
+        // because we can be recursively called
+        pname = this.name;
+        while (isalpha(*tests) && *tests != 0 && *tests != ';')
+            *pname++ = *tests++;
+        *pname = 0;
+
+        // Reset test case parameter(s)
+        for (i = 0; i < FFS_TESTCASE_PARAMS_MAX; i++)
+            tparams[i] = 0;
+
+        // Collect parameter(s) for test case
+        i = 0;
+        while (isdigit(*tests)) {
+            tparams[i] = strtol(tests, &testsnew, 0);
+            if (tests == testsnew)
+                break;
+            tests = testsnew;
+            if (*tests == ',')
+                tests++;
+            i++;
+            if (i > FFS_TESTCASE_PARAMS_MAX) {
+                ttw(ttr(TTrTest, "TEST %s has TOO MANY PARAMS" NL, this.name));
+                tw(tr(TR_FUNC, TrTest, "TEST %s TOO MANY PARAMS\n", this.name));
+                return 1;
+            }
+        }
+                
+        if (*tests == ';')
+            tests++;
+
+        // Lookup the test name in the array of test cases
+        for (ptc = testcase; ptc->name != 0; ptc++) {
+            if (strcmp(this.name, ptc->name) == 0)
+                break;
+        }
+        if (ptc->name == 0) {
+            ttw(ttr(TTrTest, "TEST %s UNKNOWN" NL, this.name));
+            tw(tr(TR_FUNC, TrTest, "TEST %s UNKNOWN\n", this.name));
+            return 1;
+        }
+
+        this.numcalls = test.numcalls;
+        test_begin(this.name, tparams);
+        i = ptc->function(tparams[0], tparams[1]);
+        if (i != 0) {
+            failed++;
+            test_error(&this, test.numcalls);
+        }
+        test_end(&this, test.numcalls);
+    }
+
+    return failed;
+}
+
+// Overall test initialization. Read static ffs params with ffs_query()
+void test_init(int keepgoing)
+{
+    test.numcases = 0;
+    test.numcalls = 0;
+    test.numfails = 0;
+    test.keepgoing = keepgoing;
+
+    memset(&param, 0, sizeof(struct ffs_params_s));
+
+    if (smallbuf == 0) {
+#if (TARGET == 1)
+        smallbuf = (char*)target_malloc(smallbuf_size);
+#else
+        smallbuf = malloc(smallbuf_size);
+#endif
+        tw(tr(TR_FUNC, TrTest, "smallbuf = 0x%X, %d\n",
+              smallbuf, smallbuf_size));
+    }
+    if (bigbuf == 0) {
+#if (TARGET == 1)
+        // We continuously halve the buffer size until we succeed to allocate
+        // it.
+        while(1) {
+            if ((bigbuf = (char*)target_malloc(bigbuf_size)) != 0)
+                break;
+            bigbuf_size /= 2;
+        } 
+#else
+        bigbuf = malloc(bigbuf_size);
+#endif
+        tw(tr(TR_FUNC, TrTest, "bigbuf   = 0x%X, %d\n", bigbuf, bigbuf_size));
+    }
+
+    test_tdata_init();
+
+    tffs_initialize();
+}
+
+void test_exit(void)
+{
+    test_state_print(0);
+}
+
+
+// Begin new test case
+void test_begin(char *name, int *params)
+{
+    test.numcases++;
+
+    tw(tr(TR_BEGIN, TrTest, "TEST %s(%d,%d)\n", name, params[0], params[1]));
+    ttw(ttr(TTrTest, "TEST %s(%d,%d)" NL, name, params[0], params[1]));
+}
+
+void test_end(struct this_test_s *test, int n)
+{
+    int objects = 0;
+
+    ffs_query(Q_TOTAL_OBJECTS, (uint16 *) &objects);
+    tw(tr(TR_FUNC, TrTestHigh, "(total objects = %d)\n", objects));
+    tw(tr(TR_END, TrTest, ""));
+    //tw(tr(TR_END, TrTest, "TEST END   %s (calls = %d)\n",
+    //      test->name, n - test->numcalls));
+}
+
+void test_error(struct this_test_s *test, int n)
+{
+    ttw(ttr(TTrTest, "TEST FAIL %s, call %d" NL,
+            test->name, n - test->numcalls));
+    tw(tr(TR_FUNC, TrTest, "TEST FAIL %s, call %d\n",
+          test->name, n - test->numcalls));
+}
+
+
+/******************************************************************************
+ * Miscellaneous
+ ******************************************************************************/
+
+int test_ffs_state_get(struct ffs_state_s *s)
+{
+    memset(s, 0, sizeof(struct ffs_state_s));
+
+    error  = ffs_query(Q_INODES_USED,  (uint16 *) &s->inodes_used);
+    error += ffs_query(Q_INODES_LOST,  (uint16 *) &s->inodes_lost);
+    error += ffs_query(Q_OBJECTS_FREE,  (uint16 *) &s->objects_free);
+    error += ffs_query(Q_TOTAL_OBJECTS, (uint16 *) &s->objects_total);
+
+    error += ffs_query(Q_BYTES_USED, (uint16 *) &s->bytes_used);
+    error += ffs_query(Q_BYTES_LOST, (uint16 *) &s->bytes_lost);
+    error += ffs_query(Q_BYTES_FREE, (uint16 *) &s->bytes_free);
+
+    error += ffs_query(Q_BLOCKS_FREE, (uint16 *) &s->blocks_free);
+
+    return error;
+}
+
+void test_ffs_state_copy(struct ffs_state_s *dst, struct ffs_state_s *src)
+{
+    memcpy(dst, src, sizeof(struct ffs_state_s));
+}
+
+void test_state_print(struct ffs_state_s *state)
+{
+    struct ffs_state_s mystate;
+
+    if (state == 0) {
+        state = &mystate;
+        test_ffs_state_get(state);
+    }
+
+    tw(tr(TR_FUNC, TrTest, "\nFFS State Summary:\n\n"));
+    ttw(str(TTrTest, NL "FFS State Summary:" NL NL));
+
+    tw(tr(TR_FUNC, TrTest, "  block_size = %d\n", param.block_size));
+    tw(tr(TR_FUNC, TrTest, "  bytes_avail = %d\n\n", param.bytes_avail));
+
+    ttw(ttr(TTrTest, "  block_size = %d" NL, param.block_size));
+    ttw(ttr(TTrTest, "  bytes_avail = %d" NL NL, param.bytes_avail));
+
+    test_state_bytes_print(state, 0);
+    test_state_objects_print(state, 0);
+
+}
+
+void test_state_objects_print(struct ffs_state_s *old, struct ffs_state_s *new)
+{
+    ttw(str(TTrTest, "              inodes            objects" NL));
+    ttw(str(TTrTest, "  -------------------------------------------" NL));
+    ttw(str(TTrTest, "  objects:    used     lost     free    total" NL));
+    ttw(ttr(TTrTest, "  old:      %6d   %6d   %6d   %6d" NL,
+          old->inodes_used, old->inodes_lost,
+          old->objects_free, old->objects_total));
+
+    tw(tr(TR_FUNC, TrTest, "              inodes            objects\n"));
+    tw(tr(TR_FUNC, TrTest, "  -------------------------------------------\n"));
+    tw(tr(TR_FUNC, TrTest, "  objects:    used     lost     free    total\n"));
+    tw(tr(TR_FUNC, TrTest, "  old:      %6d   %6d   %6d   %6d\n",
+          old->inodes_used, old->inodes_lost,
+          old->objects_free, old->objects_total));
+
+    if (new != NULL)
+    {
+        ttw(ttr(TTrTest,
+              "  new:      %6d   %6d   %6d   %6d" NL,
+              new->inodes_used, new->inodes_lost,
+              new->objects_free, new->objects_total));
+        ttw(ttr(TTrTest,
+              "  diff:     %6d   %6d   %6d   %6d" NL,
+              new->inodes_used - old->inodes_used,
+              new->inodes_lost - old->inodes_lost,
+              new->objects_free - old->objects_free,
+              new->objects_total - old->objects_total));
+
+        tw(tr(TR_FUNC, TrTest,
+              "  new:      %6d   %6d   %6d   %6d\n",
+              new->inodes_used, new->inodes_lost,
+              new->objects_free, new->objects_total));
+        tw(tr(TR_FUNC, TrTest,
+              "  diff:     %6d   %6d   %6d   %6d\n",
+              new->inodes_used - old->inodes_used,
+              new->inodes_lost - old->inodes_lost,
+              new->objects_free - old->objects_free,
+              new->objects_total - old->objects_total));
+    }
+    ttw(str(TTrTest, "" NL));
+    tw(tr(TR_FUNC, TrTest, "\n"));
+}
+
+void test_state_bytes_print(struct ffs_state_s *old, struct ffs_state_s *new)
+{
+    tw(tr(TR_FUNC, TrTest, "  bytes:      used     lost     free    total\n"));
+    tw(tr(TR_FUNC, TrTest, "  old:    %8d %8d %8d %8d\n",
+          old->bytes_used, old->bytes_lost,
+          old->bytes_free, param.bytes_max));
+    tw(tr(TR_FUNC, TrTest, "  +/-:    %8d          %8d\n",
+          old->bytes_used - old->bytes_lost,
+          old->bytes_free + old->bytes_lost));
+
+    ttw(str(TTrTest, "  bytes:      used     lost     free    total" NL));
+    ttw(ttr(TTrTest, "  old:    %8d %8d %8d %8d" NL,
+          old->bytes_used, old->bytes_lost,
+          old->bytes_free, param.bytes_max));
+    ttw(ttr(TTrTest, "  +/-:    %8d          %8d" NL,
+          old->bytes_used - old->bytes_lost,
+          old->bytes_free + old->bytes_lost));
+
+    if (new != NULL) {
+        tw(tr(TR_FUNC, TrTest, "  new:    %8d %8d %8d\n",
+              new->bytes_used, new->bytes_lost,
+              new->bytes_free));
+        tw(tr(TR_FUNC, TrTest, "  diff:   %8d %8d %8d\n",
+              new->bytes_used - old->bytes_used,
+              new->bytes_lost - old->bytes_lost,
+              new->bytes_free - old->bytes_free));
+
+        ttw(ttr(TTrTest, "  new:    %8d %8d %8d" NL,
+              new->bytes_used, new->bytes_lost,
+              new->bytes_free));
+        ttw(ttr(TTrTest, "  diff:   %8d %8d %8d" NL,
+              new->bytes_used - old->bytes_used,
+              new->bytes_lost - old->bytes_lost,
+              new->bytes_free - old->bytes_free));
+    }
+    tw(tr(TR_FUNC, TrTest, "\n"));
+    ttw(str(TTrTest, "" NL));
+}
+
+
+// Retrieve all static ffs parameters with ffs_query()
+int test_ffs_params_get(void)
+{
+    error  = ffs_query(Q_FILENAME_MAX,    &param.filename_max);
+    error += ffs_query(Q_PATH_DEPTH_MAX,  &param.pathdepth_max);
+    error += ffs_query(Q_INODES_MAX,      &param.inodes_max);
+    error += ffs_query(Q_BYTES_MAX,       &param.bytes_max);
+    error += ffs_query(Q_DEV_BLOCKS,      &param.numblocks);
+    error += ffs_query(Q_DEV_ATOMSIZE,    &param.atomsize);
+    error += ffs_query(Q_BLOCKS_FREE_MIN, &param.blocks_free_min);
+
+    // Compute block size
+    param.block_size = param.bytes_max / param.numblocks;
+
+    // Compute total number of available storage space, subtracting
+    // fs.blocks_free_min plus one block for inodes
+    param.bytes_avail =
+        param.bytes_max - (param.block_size * (1 + param.blocks_free_min));
+
+    // Compute number of blocks available for data storage
+    param.data_blocks = param.numblocks - (1 + param.blocks_free_min);
+
+    return error;
+}
+
+void test_statistics_print(void)
+{
+    tw(tr(TR_FUNC, TrTest, "Data allocated(%dMB)\n", stats.data_allocated>>20)); 
+    tw(tr(TR_FUNC, TrTest, "Reclaim candidates: most-lost(%d), most-unused(%d), youngest(%d)\n", stats.drec.most_lost, stats.drec.most_unused, stats.drec.youngest)); 
+
+    tw(tr(TR_FUNC, TrTest, "Data reclaimed:     lost(%dMB), valid(%dMB)\n", 
+          stats.drec.lost[0]>>20 , stats.drec.valid[0]>>20)); 
+
+    tw(tr(TR_FUNC, TrTest, "Inodes reclaimed:   num(%d), valid(%d), lost(%d)\n",
+          stats.irec.num, stats.irec.valid, stats.irec.lost));
+
+    ttw(ttr(TTrTest, "Data allocated(%dMB)\n" NL, stats.data_allocated>>20)); 
+    ttw(ttr(TTrTest, "Reclaim candidates: most-lost(%d), most-unused(%d), youngest(%d)\n" NL, stats.drec.most_lost, stats.drec.most_unused, stats.drec.youngest)); 
+
+    ttw(ttr(TTrTest, "Data reclaimed:     lost(%dMB), valid(%dMB)\n" NL, 
+          stats.drec.lost[0]>>20 , stats.drec.valid[0]>>20)); 
+
+    ttw(ttr(TTrTest, "Inodes reclaimed:   num(%d), valid(%d), lost(%d)\n" NL,
+          stats.irec.num, stats.irec.valid, stats.irec.lost));
+}
+
+/******************************************************************************
+ * Test and Expect Functions
+ ******************************************************************************/
+
+int test_expect(int n, int xn)
+{
+    if (n == xn)
+        return 0;
+
+    tw(tr(TR_FUNC, TrTest,
+          "ERROR: expect(%d,%d): got %d, '%s', expected %d, '%s'\n",
+          n, xn, n, ffs_strerror(n), xn, ffs_strerror(xn)));
+    ttw(ttr(TTrTest, "ERROR: expect(%d,%d)" NL, n, xn));
+
+    return -1;
+}
+
+// Expect a return code >= 0 meaning EFFS_OK.
+int test_expect_ok(int n)
+{
+    if (n >= 0)
+        return 0;
+
+    tw(tr(TR_FUNC, TrTest,
+          "ERROR: expect_ok(%d) got %d, '%s', expected >= EFFS_OK\n",
+          n, ffs_strerror(n)));
+    ttw(ttr(TTrTest, "ERROR: expect_ok(%d)" NL, n));
+
+    return -1;
+}
+
+int test_expect_equal(int n, int xn)
+{
+    if (n == xn)
+        return 0;
+
+    tw(tr(TR_FUNC, TrTest, "ERROR: got %d, expected %d\n", n, xn));
+    ttw(ttr(TTrTest, "ERROR: expect_eq(%d,%d" NL, n, xn));
+
+    return -1;
+}
+
+int test_expect_not_equal(int n, int xn)
+{
+    if (n != xn)
+        return 0;
+
+    tw(tr(TR_FUNC, TrTest, "ERROR: expect_ne(%d)\n", n));
+    ttw(ttr(TTrTest, "ERROR: expect_ne(%d)" NL, n));
+
+    return -1;
+}
+
+int test_expect_greater_than(int n, int xn)
+{
+    if (n > xn)
+        return 0;
+
+    tw(tr(TR_FUNC, TrTest, "ERROR: expect_gt(%d,%d) got %d but expected > %d\n",
+          n, xn, n, xn));
+    ttw(ttr(TTrTest, "ERROR: expect_gt(%d,%d)" NL, n, xn));
+
+    return -1;
+}
+
+int test_expect_data(const void *data1, const void *data2, int size)
+{
+    if (memcmp(data1, data2, size) == 0)
+        return 0;
+    
+    tw(tr(TR_FUNC, TrTest,
+          "ERROR: expect_data(%d) got unexpected data\n", size));
+    ttw(ttr(TTrTest, "ERROR: expect_data(%d)" NL, size));
+
+    return -1;
+}
+
+// Check that contents of file with name <name> is the same as <data> of
+// size <size>.
+int test_expect_file(const char *name, const void *data, int size)
+{
+    test.numcalls++;
+    if (size > bigbuf_size) {
+        tw(tr(TR_FUNC, TrTest, "WARNING: expect_file(%d) buffer too small\n",
+              size));
+        ttw(ttr(TTrTest, "WARNING: expect_file(%d) buffer too small" NL, size));
+#if (TARGET == 1)
+        return 0;
+#endif
+        return -1;
+    }
+        
+    error = ffs_file_read(name, bigbuf, size);
+    if (test_expect_greater_than(error, EFFS_OK - 1))
+        return -1;
+    return test_expect_data(bigbuf, data, size);
+}
+
+int test_expect_state(struct ffs_state_s *old, struct ffs_state_s *new)
+{
+    int old_total, new_total;
+
+    old_total = old->inodes_used - old->inodes_lost;
+    new_total = new->inodes_used - new->inodes_lost;
+
+    if (old->objects_total == new->objects_total &&
+        old->objects_total == new_total &&
+        new->objects_total == old_total &&
+        old->bytes_used == new->bytes_used &&
+        old->bytes_lost == new->bytes_lost &&
+        old->bytes_free == new->bytes_free) {
+        return 0;
+    }
+
+    ttw(str(TTrTest, "ERROR: ffs state mismatch:" NL NL));
+    tw(tr(TR_FUNC, TrTest, "ERROR: ffs state mismatch:\n\n"));
+    test_state_objects_print(old, new);
+    test_state_bytes_print(old, new);
+
+    return -1;
+}
+
+// Check if number of objects is unchanged
+int test_expect_objects(struct ffs_state_s *old, struct ffs_state_s *new)
+{
+    int old_total, new_total;
+
+    test_ffs_state_get(new);
+
+    old_total = old->inodes_used - old->inodes_lost;
+    new_total = new->inodes_used - new->inodes_lost;
+
+    if (old->objects_total == new->objects_total &&
+        old->objects_total == new_total &&
+        new->objects_total == old_total) {
+        return 0;
+    }
+
+    ttw(ttr(TTrTest, "ERROR: expect_objects(%d, %d, %d, %d, %d, %d)" NL));
+    tw(tr(TR_FUNC, TrTest, "ERROR: ffs state mismatch:\n\n"));
+    test_state_objects_print(old, new);
+
+    return -1;
+}
+
+
+/******************************************************************************
+ * FFS Functions
+ ******************************************************************************/
+
+effs_t tffs_fcreate(const char *name, void *addr, int size)
+{
+    test.numcalls++;
+    return ffs_fcreate(name, addr, size);
+}
+
+effs_t tffs_fupdate(const char *name, void *addr, int size)
+{
+    test.numcalls++;
+    return ffs_fupdate(name, addr, size);
+}
+
+effs_t tffs_fwrite(const char *name, void *addr, int size)
+{
+    test.numcalls++;
+    return ffs_fwrite(name, addr, size);
+}
+
+effs_t tffs_file_write(const char *name, void *addr, int size, uint16 option)
+{
+    test.numcalls++;
+    return ffs_file_write(name, addr, size, option);
+}
+
+effs_t tffs_mkdir(const char *name)
+{
+    test.numcalls++;
+    return ffs_mkdir(name);
+}
+
+effs_t tffs_symlink(const char *name, const char *actualpath)
+{
+    test.numcalls++;
+    return ffs_symlink(name, actualpath);
+}
+
+effs_t tffs_remove(const char *name)
+{
+    test.numcalls++;
+    return ffs_remove(name);
+}
+
+effs_t tffs_fcontrol(const char *name, int8 action, uint16 param)
+{
+    test.numcalls++;
+    return ffs_fcontrol(name, action, param);
+}
+
+effs_t tffs_preformat(uint16 magic)
+{
+    test.numcalls++;
+    return ffs_preformat(magic);
+}
+
+effs_t tffs_format(const char *name, uint16 magic)
+{
+    test.numcalls++;
+    return ffs_format(name, magic);
+}
+
+
+int tffs_fread(const char *name, void *addr, int size)
+{
+    test.numcalls++;
+    return ffs_file_read(name, addr, size);
+}
+
+int tffs_file_read(const char *name, void *addr, int size)
+{
+    test.numcalls++;
+    return ffs_file_read(name, addr, size);
+}
+
+int tffs_opendir(const char *name, struct dir_s *dir)
+{
+    test.numcalls++;
+    return ffs_opendir(name, dir);
+}
+
+int tffs_readdir (struct dir_s *dir, char *name, int8 size)
+{
+    test.numcalls++;
+    return ffs_readdir(dir, name, size);
+}
+
+int tffs_readlink(const char *name, char *addr, int size)
+{
+    test.numcalls++;
+    return ffs_readlink(name, addr, size);
+}
+
+int tffs_rename(const char *oldname, const char *newname)
+{
+    test.numcalls++;
+    return ffs_rename(oldname, newname);
+}
+
+effs_t tffs_stat(const char *name, struct stat_s *stat)
+{
+    test.numcalls++;
+    return ffs_stat(name, stat);
+}
+
+effs_t tffs_fstat(fd_t fdi, struct stat_s *stat)
+{
+    test.numcalls++;
+    return ffs_fstat(fdi, stat);
+}
+
+effs_t tffs_linkstat(const char *name, struct stat_s *stat)
+{
+    test.numcalls++;
+    return ffs_lstat(name, stat);
+}
+
+effs_t tffs_lstat(const char *name, struct stat_s *stat)
+{
+    test.numcalls++;
+    return ffs_lstat(name, stat);
+}
+
+effs_t tffs_xlstat(const char *name, struct xstat_s *stat)
+{
+    test.numcalls++;
+    return ffs_xlstat(name, stat);
+}
+
+effs_t tffs_query(int8 query, void *p)
+{
+    return ffs_query(query, p);
+}
+
+
+effs_t tffs_initialize(void)
+{
+    effs_t myerror;
+    struct ffs_stats_s old_stats;
+
+    test.numcalls++;
+
+    memcpy(&old_stats, &stats, sizeof(struct ffs_stats_s));
+    myerror = ffs_initialize();
+    memcpy(&stats, &old_stats, sizeof(struct ffs_stats_s));
+
+    test_ffs_params_get();
+    return myerror;
+}
+
+effs_t tffs_exit(void)
+{
+    test.numcalls++;
+    return ffs_exit();
+}
+
+fd_t tffs_open(const char *pathname, ffs_options_t options)
+{
+    test.numcalls++;
+    return ffs_open(pathname, options);
+}
+
+effs_t tffs_close(fd_t fdi)
+{
+    test.numcalls++;
+    return ffs_close(fdi);
+}
+
+int tffs_write(fd_t fdi, void *addr, int size)
+{
+   test.numcalls++;
+   return ffs_write(fdi, addr, size);
+}
+
+int tffs_read(fd_t fdi, void *addr, int size)
+{
+   test.numcalls++;
+   return ffs_read(fdi, addr, size);
+}
+
+int tffs_seek(fd_t fdi, int offset, int whence)
+{
+  test.numcalls++;
+  return ffs_seek(fdi, offset, whence);
+}
+
+effs_t tffs_truncate(const char *path, offset_t length) 
+{
+    test.numcalls++;
+    return ffs_truncate(path, length); 
+}
+
+effs_t tffs_ftruncate(fd_t fdi, offset_t length) 
+{
+    test.numcalls++;
+    return ffs_ftruncate(fdi, length); 
+}
+
+effs_t tffs_fdatasync(fd_t fdi) 
+{
+    test.numcalls++;
+    return ffs_fdatasync(fdi); 
+}