Mercurial > yaffs-ecoscentric
changeset 336:38a956139d12
Import tests from eCosPro
| author | Ross Younger <wry@ecoscentric.com> |
|---|---|
| date | Tue, 03 Nov 2009 18:00:39 +0000 |
| parents | 201205efa9e1 |
| children | b254764fbeac |
| files | packages/fs/yaffs/current/ChangeLog packages/fs/yaffs/current/cdl/yaffs.cdl packages/fs/yaffs/current/tests/mounttime.c packages/fs/yaffs/current/tests/yaffs1.c packages/fs/yaffs/current/tests/yaffs2.c packages/fs/yaffs/current/tests/yaffs4.c packages/fs/yaffs/current/tests/yaffs5.c packages/fs/yaffs/current/tests/yaffs6.c |
| diffstat | 8 files changed, 4846 insertions(+), 1 deletions(-) [+] |
line wrap: on
line diff
--- a/packages/fs/yaffs/current/ChangeLog +++ b/packages/fs/yaffs/current/ChangeLog @@ -1,3 +1,8 @@ +2009-11-03 Ross Younger <wry@ecoscentric.com> + + * tests: Import from eCosPro: mounttime, yaffs1, yaffs2, + yaffs4, yaffs5, yaffs6. + 2009-11-02 Ross Younger <wry@ecoscentric.com> * Update to latest snapshot from Aleph One CVS (mostly
--- a/packages/fs/yaffs/current/cdl/yaffs.cdl +++ b/packages/fs/yaffs/current/cdl/yaffs.cdl @@ -228,10 +228,62 @@ cdl_package CYGPKG_FS_YAFFS { display "YAFFS filesystem tests" flavor data no_define - calculated { "tests/fops" } + calculated { "tests/fops tests/mounttime" + . " tests/yaffs1 tests/yaffs2 tests/yaffs4" + . " tests/yaffs5 tests/yaffs6" + } description " This special option specifies the set of tests to build for YAFFS." } + cdl_component CYGPKG_FS_YAFFS_TESTING { + display "Testing configuration" + default_value 1 + + define_proc { + puts $::cdl_system_header "/***** Synthdisk driver proc output start *****/" + puts $::cdl_system_header "#define CYGDAT_DEVS_DISK_CFG <pkgconf/fs_yaffs.h>" + puts $::cdl_system_header "/***** Synthdisk driver proc output end *****/" + } + + + cdl_option CYGDAT_DEVS_DISK_TEST_DEVICE { + display "Test device driver" + flavor data + default_value { CYGPKG_DEVS_NAND_SYNTH?"\"synth/0\"":"\"onboard/0\"" } + } + + cdl_option CYGDAT_DEVS_DISK_TEST_MOUNTPOINT { + display "Test filesystem mountpoint" + flavor data + default_value {"\"/nand\"" } + } + + cdl_option CYGDAT_DEVS_DISK_TEST_DIRECTORY { + display "Test directory on test device" + flavor data + default_value {"\"/test\"" } + } + + + cdl_option CYGDAT_DEVS_DISK_TEST_DEVICE2 { + display "Second Test device driver" + flavor data + default_value { CYGPKG_DEVS_NAND_SYNTH?"\"synth/1\"":"\"onboard/1\"" } + } + + cdl_option CYGDAT_DEVS_DISK_TEST_MOUNTPOINT2 { + display "Second Test filesystem mountpoint" + flavor data + default_value {"\"/nand2\"" } + } + + cdl_option CYGDAT_DEVS_DISK_TEST_DIRECTORY2 { + display "Test directory on second test device" + flavor data + default_value {"\"/test\"" } + } + + } }
new file mode 100644 --- /dev/null +++ b/packages/fs/yaffs/current/tests/mounttime.c @@ -0,0 +1,303 @@ +//============================================================================= +// +// mounttime.c +// +// Mount timings exerciser, use on a filesystem filled by `makefiles' +// THIS DOES NOT CURRENTLY WORK ON non-PRO eCos! +// +//============================================================================= +// ####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 2009 Free Software Foundation, Inc. +// +// eCos is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 2 or (at your option) any later +// version. +// +// eCos is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License +// along with eCos; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +// +// As a special exception, if other files instantiate templates or use +// macros or inline functions from this file, or you compile this file +// and link it with other works to produce a work based on this file, +// this file does not by itself cause the resulting work to be covered by +// the GNU General Public License. However the source code for this file +// must still be made available in accordance with section (3) of the GNU +// General Public License v2. +// +// This exception does not invalidate any other reasons why a work based +// on this file might be covered by the GNU General Public License. +// ------------------------------------------- +// ####ECOSGPLCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): wry +// Date: 2009-06-29 +// Description: File system mount and unmount timing benchmark. +// Intended to be used on a complicated filesystem, e.g. +// one filled up by `makefiles'. +// Some timing code borrowed from mmfs tests. +// +//####DESCRIPTIONEND#### +//============================================================================= + +#include <cyg/infra/testcase.h> +#include <cyg/infra/diag.h> +#include <cyg/infra/cyg_ass.h> +#include <pkgconf/system.h> +#include <pkgconf/hal.h> +#include <cyg/hal/hal_intr.h> + +#ifndef HAL_CLOCK_READ +# error "HAL_CLOCK_READ not defined!" +#endif + +#if !defined(CYGPKG_LIBC_TIME) || !defined(CYGPKG_ERROR) || !defined(CYGPKG_LIBC_STDIO) || !defined(CYGPKG_KERNEL) + +void cyg_user_start(void) +{ + CYG_TEST_NA("Needs CYGPKG_KERNEL, CYGPKG_LIBC_TIME, CYGPKG_ERROR and CYGPKG_LIBC_STDIO"); +} + +#else + +#include <cyg/fileio/fileio.h> +#include <string.h> +#include <stdio.h> +#include <unistd.h> +#include <sys/types.h> +#include <dirent.h> +#include <stdlib.h> + +#include <cyg/kernel/kapi.h> + +#ifdef CYGPKG_DEVS_NAND_SYNTH +#define DEVICE "synth/0" +#else +#define DEVICE "onboard/0" +#endif + +#define MOUNTPOINT "/n" +#define FSTYPE "yaffs" +#define _NOCACHE "skip-checkpoint-read" + +#define FS_NOCACHE FSTYPE":"_NOCACHE + +//#define MUST(what) do { CYG_TEST_CHECK((what), #what); } while(0) + +#define MUST(what) do { \ + if (0 != what) { \ + perror(#what); \ + CYG_TEST_FAIL(#what); \ + cyg_test_exit(); \ + } \ +} while(0) + +#define min(a,b) ( (a) > (b) ? (b) : (a) ) + +// -------------------------------------------------------------- + +void RM_RF_work(const char *f, int recurse) +{ + MUST(chdir(f)); + DIR *d = opendir("."); + if (!d) { + diag_printf("opendir %s: %s\n", f, strerror(errno)); + return; + } + struct dirent de_stack; + struct dirent *de_res; + while (0==readdir_r(d, &de_stack, &de_res) && de_res) { + struct stat st; + if (0==strcmp(de_res->d_name,".")) continue; + if (0==strcmp(de_res->d_name,"..")) continue; + MUST(stat(de_res->d_name,&st)); + if (S_ISDIR(st.st_mode)) { + RM_RF_work(de_res->d_name, recurse+1); + if (rmdir(de_res->d_name)) + perror("rmdir"); + } else { + MUST(unlink(de_res->d_name)); + } + } + closedir(d); + MUST(chdir("..")); +} + +void RM_RF(const char *p) +{ + diag_printf("rm -rf %s\n",p); + RM_RF_work(p,0); + MUST(rmdir(p)); +} + +// -------------------------------------------------------------- +// Timing code cribbed from pvr5.c + +typedef struct +{ + cyg_int64 ticks; + cyg_uint32 halticks; +} timestamp; + +typedef struct +{ + timestamp start; + timestamp end; + cyg_int64 interval; // In HAL ticks + cyg_int64 us_interval; // Interval in microseconds +} timing; + +static cyg_int64 ticks_overhead = 0; +static cyg_int32 us_per_haltick = 0; +static cyg_int32 halticks_per_us = 0; + +static cyg_int64 rtc_resolution[] = CYGNUM_KERNEL_COUNTERS_RTC_RESOLUTION; +static cyg_int64 rtc_period = CYGNUM_KERNEL_COUNTERS_RTC_PERIOD; + +static void wait_for_tick( void ) +{ + cyg_tick_count_t now = cyg_current_time(); + + while( cyg_current_time() == now ) + continue; +} + +static void get_timestamp( timestamp *ts ) +{ + ts->ticks = cyg_current_time(); + HAL_CLOCK_READ( &ts->halticks ); +} + +static cyg_int64 ticks_to_us( cyg_int64 ticks ) +{ + cyg_int64 us; + + if( us_per_haltick != 0 ) + us = ticks * us_per_haltick; + else + us = ticks / halticks_per_us; + + return us; +} + +static void calculate_interval( timing *t ) +{ + t->interval = t->end.halticks - t->start.halticks; + + t->interval += (t->end.ticks - t->start.ticks) * rtc_period; + + t->interval -= ticks_overhead; + + t->us_interval = ticks_to_us( t->interval ); +} + +static void init_timing( void ) +{ + timing t; + cyg_thread_delay(2); // ensure clock running - asserts if not + + us_per_haltick = 1000000/(rtc_period * rtc_resolution[1]); + halticks_per_us = (rtc_period * rtc_resolution[1])/1000000; + + wait_for_tick(); + + get_timestamp( &t.start ); + get_timestamp( &t.end ); + + calculate_interval( &t ); + + ticks_overhead = t.interval; + + diag_printf("Timing overhead %lld ticks (%lluus), this will be factored out of all other measurements\n", ticks_overhead, t.us_interval ); +} + +static timing tm; + +#define START() do { \ + wait_for_tick(); \ + get_timestamp(&tm.start); \ +} while(0) + +static void report(const char *what, timing tm) +{ + if (tm.us_interval > 1100000) + diag_printf("%30s: %2d.%03d s\n", what, (int)(tm.us_interval/1000000), (int)(tm.us_interval/1000)%1000); + else + diag_printf("%30s: %2d.%03d ms\n", what, (int)(tm.us_interval/1000), (int)(tm.us_interval%1000)); + +} + +#define STOP(what) do { \ + get_timestamp(&tm.end); \ + calculate_interval(&tm); \ + report(what, tm); \ +} while(0) + +// -------------------------------------------------------------- + +void dumpmallinfo(void) +{ + struct mallinfo mi = mallinfo(); + int total_ord = mi.uordblks + mi.fordblks; + double pct = (double)mi.uordblks / (double)total_ord; + diag_printf("! Arena: size 0x%x, small blks %u/%u, ord blks used %u/%u (%u%%)\n", + mi.arena, + mi.usmblks, mi.fsmblks, + mi.uordblks, total_ord, (int)(100.0*pct)); +} + +// -------------------------------------------------------------- + +#define WORKDIR MOUNTPOINT "/" "test" + +void mounttime_main(void) +{ +#define NTIMES 3 + int i; + for (i=0; i<NTIMES; i++) { + START(); + MUST(mount(DEVICE, MOUNTPOINT, FSTYPE)); + STOP("remount"); + //if (i==0) dumpmallinfo(); + START(); + MUST(umount(MOUNTPOINT)); + STOP("unmount"); + + START(); + MUST(mount(DEVICE, MOUNTPOINT, FS_NOCACHE)); + // plain eCos does not support mount options, this test won't work there. + STOP("remount without checkpoint"); + //if (i==0) dumpmallinfo(); + START(); + MUST(umount(MOUNTPOINT)); + STOP("unmount"); + //if (i==0) dumpmallinfo(); + } + //dumpmallinfo(); + + // then consider repeats.. + + CYG_TEST_EXIT("Run complete"); +} + +int main(void) +{ + CYG_TEST_INIT(); + init_timing(); + + mounttime_main(); + return 0; +} + +#endif +
new file mode 100644 --- /dev/null +++ b/packages/fs/yaffs/current/tests/yaffs1.c @@ -0,0 +1,959 @@ +//========================================================================== +// +// yaffs1.c +// +// Test fileio system +// +//========================================================================== +// ####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 1998, 1999, 2000, 2001, 2002, 2004, 2006, 2007 Free Software Foundation, Inc. +// Copyright (C) 2004, 2006, 2007 eCosCentric Limited +// +// eCos is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 2 or (at your option) any later +// version. +// +// eCos is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License +// along with eCos; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +// +// As a special exception, if other files instantiate templates or use +// macros or inline functions from this file, or you compile this file +// and link it with other works to produce a work based on this file, +// this file does not by itself cause the resulting work to be covered by +// the GNU General Public License. However the source code for this file +// must still be made available in accordance with section (3) of the GNU +// General Public License v2. +// +// This exception does not invalidate any other reasons why a work based +// on this file might be covered by the GNU General Public License. +// ------------------------------------------- +// ####ECOSGPLCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): nickg +// Contributors: nickg +// Date: 2000-05-25 +// Purpose: Test fileio system +// Description: This test uses the testfs to check out the initialization +// and basic operation of the fileio system +// +// +// +// +// +// +// +//####DESCRIPTIONEND#### +// +//========================================================================== + +#include <pkgconf/hal.h> +#include <pkgconf/kernel.h> +#include <pkgconf/io_fileio.h> + +#include CYGDAT_DEVS_DISK_CFG // testing config defines + +#include <cyg/kernel/ktypes.h> // base kernel types +#include <cyg/infra/cyg_trac.h> // tracing macros +#include <cyg/infra/cyg_ass.h> // assertion macros + +#include <unistd.h> +#include <fcntl.h> +#include <sys/stat.h> +#include <errno.h> +#include <string.h> +#include <dirent.h> + +#include <cyg/fileio/fileio.h> + +#include <cyg/infra/testcase.h> +#include <cyg/infra/diag.h> // HAL polled output + +//========================================================================== +// Config options + +#define TEST_DEVICE CYGDAT_DEVS_DISK_TEST_DEVICE + +#define TEST_MOUNTPOINT CYGDAT_DEVS_DISK_TEST_MOUNTPOINT + +#define TEST_DIRECTORY CYGDAT_DEVS_DISK_TEST_DIRECTORY + +#define TEST_FSTYPE "yaffs" + +#ifdef CYGDAT_DEVS_DISK_TEST_MOUNTPOINT2 + +#define TEST_DEVICE2 CYGDAT_DEVS_DISK_TEST_DEVICE2 + +#define TEST_MOUNTPOINT2 CYGDAT_DEVS_DISK_TEST_MOUNTPOINT2 + +#define TEST_DIRECTORY2 CYGDAT_DEVS_DISK_TEST_DIRECTORY2 + +#define TEST_FSTYPE2 "yaffs" + +#endif + +//========================================================================== + +#define SHOW_RESULT( _fn, _res ) \ +{ \ + diag_printf("<FAIL>: " #_fn "() returned %ld %s\n", (long)_res, _res<0?strerror(errno):""); \ +} + +//========================================================================== + +#define IOSIZE 100 + +#define LONGNAME1 "long_file_name_that_should_take_up_more_than_one_directory_entry_1" +#define LONGNAME2 "long_file_name_that_should_take_up_more_than_one_directory_entry_2" + + +//========================================================================== + +#ifndef CYGPKG_LIBC_STRING + +char *strcat( char *s1, const char *s2 ) +{ + char *s = s1; + while( *s1 ) s1++; + while( (*s1++ = *s2++) != 0); + return s; +} + +#endif + +__externC int +rename( const char * /* oldpath */, const char * /* newpath */ ) __THROW; + +//========================================================================== + +static void listdir( char *name, int statp, int numexpected, int *numgot ) +{ + int err; + DIR *dirp; + int num=0; + + diag_printf("<INFO>: reading directory %s\n",name); + +// diag_printf("<INFO>: opendir(%s)\n",name); + dirp = opendir( name ); + if( dirp == NULL ) SHOW_RESULT( opendir, -1 ); + + for(;;) + { + struct dirent *entry = readdir( dirp ); + + if( entry == NULL ) + break; + num++; + diag_printf("<INFO>: entry %14s",entry->d_name); +#ifdef CYGPKG_FS_FAT_RET_DIRENT_DTYPE + diag_printf(" d_type %2x", entry->d_type); +#endif + if( statp ) + { + char fullname[PATH_MAX]; + struct stat sbuf; + + if( name[0] ) + { + strcpy(fullname, name ); + if( !(name[0] == '/' && name[1] == 0 ) ) + strcat(fullname, "/" ); + } + else fullname[0] = 0; + + strcat(fullname, entry->d_name ); + + err = stat( fullname, &sbuf ); + if( err < 0 ) + { + if( errno == ENOSYS ) + diag_printf(" <no status available>"); + else SHOW_RESULT( stat, err ); + } + else + { + diag_printf(" [mode %08x ino %08x nlink %d size %ld]", + sbuf.st_mode,sbuf.st_ino,sbuf.st_nlink,sbuf.st_size); + } +#ifdef CYGPKG_FS_FAT_RET_DIRENT_DTYPE + if ((entry->d_type & S_IFMT) != (sbuf.st_mode & S_IFMT)) + CYG_TEST_FAIL("File mode's don't match between dirent and stat"); +#endif + } + + diag_printf("\n"); + } + +// diag_printf("<INFO>: closedir(%s)\n",name); + err = closedir( dirp ); + if( err < 0 ) SHOW_RESULT( stat, err ); + if (numexpected >= 0 && num != numexpected) + CYG_TEST_FAIL("Wrong number of dir entries\n"); + if ( numgot != NULL ) + *numgot = num; +} + +//========================================================================== + +static void createfile( char *name, size_t size ) +{ + char buf[IOSIZE]; + int fd; + ssize_t wrote; + int i; + int err; + + diag_printf("<INFO>: create file %s size %zd\n",name,size); + + err = access( name, F_OK ); + if( err < 0 && errno != EACCES ) SHOW_RESULT( access, err ); + + for( i = 0; i < IOSIZE; i++ ) buf[i] = i%256; + + fd = open( name, O_WRONLY|O_CREAT ); + if( fd < 0 ) SHOW_RESULT( open, fd ); + + while( size > 0 ) + { + ssize_t len = size; + if ( len > IOSIZE ) len = IOSIZE; + + wrote = write( fd, buf, len ); + if( wrote != len ) SHOW_RESULT( write, wrote ); + + size -= wrote; + } + + err = close( fd ); + if( err < 0 ) SHOW_RESULT( close, err ); +} + +//========================================================================== + +#if 0 +static void maxfile( char *name ) +{ + char buf[IOSIZE]; + int fd; + ssize_t wrote; + int i; + int err; + size_t size = 0; + size_t prevsize = 0; + + diag_printf("<INFO>: create maximal file %s\n",name); + diag_printf("<INFO>: This may take a few minutes\n"); + + err = access( name, F_OK ); + if( err < 0 && errno != EACCES ) SHOW_RESULT( access, err ); + + for( i = 0; i < IOSIZE; i++ ) buf[i] = i%256; + + fd = open( name, O_WRONLY|O_CREAT ); + if( fd < 0 ) SHOW_RESULT( open, fd ); + + do + { + wrote = write( fd, buf, IOSIZE ); + //if( wrote < 0 ) SHOW_RESULT( write, wrote ); + + if( wrote >= 0 ) + size += wrote; + + if( (size-prevsize) > 100000 ) + { + diag_printf("<INFO>: size = %zd\n", size); + prevsize = size; + } + + } while( wrote == IOSIZE ); + + diag_printf("<INFO>: file size == %zd\n",size); + + err = close( fd ); + if( err < 0 ) SHOW_RESULT( close, err ); +} +#endif + +//========================================================================== + +static void checkfile( char *name ) +{ + char buf[IOSIZE]; + int fd; + ssize_t done; + int i; + int err; + off_t pos = 0; + + diag_printf("<INFO>: check file %s\n",name); + + err = access( name, F_OK ); + if( err != 0 ) SHOW_RESULT( access, err ); + + fd = open( name, O_RDONLY ); + if( fd < 0 ) SHOW_RESULT( open, fd ); + + for(;;) + { + done = read( fd, buf, IOSIZE ); + if( done < 0 ) SHOW_RESULT( read, done ); + + if( done == 0 ) break; + + for( i = 0; i < done; i++ ) + if( buf[i] != i%256 ) + { + diag_printf("buf[%ld+%d](%02x) != %02x\n",pos,i,buf[i],i%256); + CYG_TEST_FAIL("Data read not equal to data written\n"); + for(;;); + } + + pos += done; + } + + err = close( fd ); + if( err < 0 ) SHOW_RESULT( close, err ); +} + +//========================================================================== + +static void copyfile( char *name2, char *name1 ) +{ + + int err; + char buf[IOSIZE]; + int fd1, fd2; + ssize_t done, wrote; + + diag_printf("<INFO>: copy file %s -> %s\n",name2,name1); + + err = access( name1, F_OK ); + if( err < 0 && errno != EACCES ) SHOW_RESULT( access, err ); + + err = access( name2, F_OK ); + if( err != 0 ) SHOW_RESULT( access, err ); + + fd1 = open( name1, O_WRONLY|O_CREAT ); + if( fd1 < 0 ) SHOW_RESULT( open, fd1 ); + + fd2 = open( name2, O_RDONLY ); + if( fd2 < 0 ) SHOW_RESULT( open, fd2 ); + + for(;;) + { + done = read( fd2, buf, IOSIZE ); + if( done < 0 ) SHOW_RESULT( read, done ); + + if( done == 0 ) break; + + wrote = write( fd1, buf, done ); + if( wrote != done ) SHOW_RESULT( write, wrote ); + + if( wrote != done ) break; + } + + err = close( fd1 ); + if( err < 0 ) SHOW_RESULT( close, err ); + + err = close( fd2 ); + if( err < 0 ) SHOW_RESULT( close, err ); + +} + +//========================================================================== + +static void comparefiles( char *name2, char *name1 ) +{ + int err; + char buf1[IOSIZE]; + char buf2[IOSIZE]; + int fd1, fd2; + ssize_t done1, done2; + int i; + + diag_printf("<INFO>: compare files %s == %s\n",name2,name1); + + err = access( name1, F_OK ); + if( err != 0 ) SHOW_RESULT( access, err ); + + err = access( name1, F_OK ); + if( err != 0 ) SHOW_RESULT( access, err ); + + fd1 = open( name1, O_RDONLY ); + if( fd1 < 0 ) SHOW_RESULT( open, fd1 ); + + fd2 = open( name2, O_RDONLY ); + if( fd2 < 0 ) SHOW_RESULT( open, fd2 ); + + for(;;) + { + done1 = read( fd1, buf1, IOSIZE ); + if( done1 < 0 ) SHOW_RESULT( read, done1 ); + + done2 = read( fd2, buf2, IOSIZE ); + if( done2 < 0 ) SHOW_RESULT( read, done2 ); + + if( done1 != done2 ) + diag_printf("Files different sizes\n"); + + if( done1 == 0 ) break; + + for( i = 0; i < done1; i++ ) + if( buf1[i] != buf2[i] ) + { + diag_printf("buf1[%d](%02x) != buf1[%d](%02x)\n",i,buf1[i],i,buf2[i]); + CYG_TEST_FAIL("Data in files not equal\n"); + } + } + + err = close( fd1 ); + if( err < 0 ) SHOW_RESULT( close, err ); + + err = close( fd2 ); + if( err < 0 ) SHOW_RESULT( close, err ); + +} + +//========================================================================== + +void checkcwd( const char *cwd ) +{ + static char cwdbuf[PATH_MAX]; + char *ret; + + ret = getcwd( cwdbuf, sizeof(cwdbuf)); + if( ret == NULL ) SHOW_RESULT( getcwd, ret ); + + if( strcmp( cwdbuf, cwd ) != 0 ) + { + diag_printf( "cwdbuf %s cwd %s\n",cwdbuf, cwd ); + CYG_TEST_FAIL( "Current directory mismatch"); + } +} + +//========================================================================== +// main + +void fileio1_main( CYG_ADDRESS id ) +{ + int err; + int existingdirents=-1; + cyg_bool mp2 = false; + int fd; +#if defined(CYGSEM_FILEIO_BLOCK_USAGE) + struct cyg_fs_block_usage usage; +#endif + + char dirname[64]; + char filename1[64]; + char filename2[64]; + +#define NEW_FILENAME( fn, f ) \ +{ \ + fn[0]=0; \ + strcat(fn, dirname); \ + strcat(fn, "/"); \ + strcat(fn,f); \ +} + +#define NEW_FILENAME1( f ) NEW_FILENAME( filename1, f ) +#define NEW_FILENAME2( f ) NEW_FILENAME( filename2, f ) + + CYG_TEST_INIT(); + + // -------------------------------------------------------------- + + err = mount( TEST_DEVICE, TEST_MOUNTPOINT, TEST_FSTYPE ); + if( err < 0 ) { + SHOW_RESULT( mount, err ); + CYG_TEST_FAIL_FINISH("yaffs1"); + } + + err = access( TEST_MOUNTPOINT TEST_DIRECTORY, F_OK ); + if( err < 0 && errno != EACCES ) SHOW_RESULT( access, err ); + + if( err < 0 && errno == EACCES ) + { + diag_printf("<INFO>: create %s\n", + TEST_MOUNTPOINT TEST_DIRECTORY); + err = mkdir( TEST_MOUNTPOINT TEST_DIRECTORY, 0 ); + if( err < 0 ) SHOW_RESULT( mkdir, err ); + } + + err = chdir( TEST_MOUNTPOINT TEST_DIRECTORY ); + if( err < 0 ) SHOW_RESULT( chdir, err ); + + checkcwd( TEST_MOUNTPOINT TEST_DIRECTORY ); + + listdir( TEST_MOUNTPOINT TEST_DIRECTORY, true, -1, &existingdirents ); + + // -------------------------------------------------------------- +#if defined(CYGSEM_FILEIO_BLOCK_USAGE) + err = cyg_fs_getinfo(TEST_MOUNTPOINT, FS_INFO_BLOCK_USAGE, + &usage, sizeof(usage)); + if( err < 0 ) SHOW_RESULT( cyg_fs_getinfo, err ); + diag_printf("<INFO>: total size: %6lld blocks, %10lld bytes\n", + usage.total_blocks, usage.total_blocks * usage.block_size); + diag_printf("<INFO>: free size: %6lld blocks, %10lld bytes\n", + usage.free_blocks, usage.free_blocks * usage.block_size); + diag_printf("<INFO>: block size: %6u bytes\n", usage.block_size); +#endif + // -------------------------------------------------------------- + + dirname[0] = 0; + strcat(dirname, TEST_MOUNTPOINT ); + strcat(dirname, TEST_DIRECTORY ); + + // -------------------------------------------------------------- + + createfile( "foo", 20257 ); + checkfile( "foo" ); + copyfile( "foo", "fee"); + checkfile( "fee" ); + comparefiles( "foo", "fee" ); + diag_printf("<INFO>: mkdir bar\n"); + err = mkdir( "bar", 0 ); + if( err < 0 ) SHOW_RESULT( mkdir, err ); + + listdir( dirname , true, existingdirents+3, NULL ); + + copyfile( "fee", "bar/fum" ); + checkfile( "bar/fum" ); + comparefiles( "fee", "bar/fum" ); + diag_printf("<INFO>: cd bar\n"); + err = chdir( "bar" ); + if( err < 0 ) SHOW_RESULT( chdir, err ); + + // Create a further subdirectory and immediately remove it + // This should make no overall change, but may expose later + // node cache reference counting issues. + diag_printf("<INFO>: mkdir delme\n"); + err = mkdir( "delme", 0); + if( err < 0 ) SHOW_RESULT( mkdir, err ); + diag_printf("<INFO>: cd delme\n"); + err = chdir( "delme"); + if( err < 0 ) SHOW_RESULT( chdir, err ); + diag_printf("<INFO>: cd ..\n"); + err = chdir( ".." ); + if( err < 0 ) SHOW_RESULT( chdir, err ); + diag_printf("<INFO>: rmdir delme\n"); + err = rmdir( "delme" ); + if( err < 0 ) SHOW_RESULT( rmdir, err ); + NEW_FILENAME1( "bar/delme1" ); + diag_printf("<INFO>: mkdir %s\n",filename1); + err = mkdir( filename1, 0); + if( err < 0 ) SHOW_RESULT( mkdir, err ); + diag_printf("<INFO>: rmdir %s\n",filename1); + err = rmdir( filename1 ); + if( err < 0 ) SHOW_RESULT( rmdir, err ); + + + NEW_FILENAME1( "bar" ); + checkcwd( filename1 ); + + diag_printf("<INFO>: rename ../foo bundy\n"); + err = rename( "../foo", "bundy" ); + if( err < 0 ) SHOW_RESULT( rename, err ); + + listdir( dirname, true, existingdirents+2, NULL ); + listdir( "." , true, 4, NULL ); + + checkfile( "../bar/bundy" ); + comparefiles("../fee", "bundy" ); + +#if defined(CYGSEM_FILEIO_BLOCK_USAGE) + err = cyg_fs_getinfo(TEST_MOUNTPOINT, FS_INFO_BLOCK_USAGE, + &usage, sizeof(usage)); + if( err < 0 ) SHOW_RESULT( cyg_fs_getinfo, err ); + diag_printf("<INFO>: total size: %6lld blocks, %10lld bytes\n", + usage.total_blocks, usage.total_blocks * usage.block_size); + diag_printf("<INFO>: free size: %6lld blocks, %10lld bytes\n", + usage.free_blocks, usage.free_blocks * usage.block_size); + diag_printf("<INFO>: block size: %6u bytes\n", usage.block_size); +#endif + // -------------------------------------------------------------- + // Check for some common error cases + + + // First make some directories + diag_printf("<INFO>: mkdir doo\n"); + err = mkdir( "doo", 0 ); + if( err < 0 ) SHOW_RESULT( mkdir, err ); + + diag_printf("<INFO>: mkdir fie\n"); + err = mkdir( "fie", 0 ); + if( err < 0 ) SHOW_RESULT( mkdir, err ); + + diag_printf("<INFO>: mkdir fie/foe\n"); + err = mkdir( "fie/foe", 0 ); + if( err < 0 ) SHOW_RESULT( mkdir, err ); + + + diag_printf("<INFO>: rename fum doo -- should fail\n"); + err = rename( "fum", "doo" ); + if( err < 0 && errno != EISDIR ) SHOW_RESULT( rename, err ); + + diag_printf("<INFO>: rename doo fum -- should fail\n"); + err = rename( "doo", "fum" ); + if( err < 0 && errno != ENOTDIR ) SHOW_RESULT( rename, err ); + + diag_printf("<INFO>: rename doo fie -- should fail\n"); + err = rename( "doo", "fie" ); + // FATFS returns ENOTEMPTY, since fie has foe within it + if( err < 0 && errno != EIO ) SHOW_RESULT( rename, err ); + + diag_printf("<INFO>: open floop for reading -- should fail\n"); + err = open( "floop", O_RDONLY ); + if( err < 0 && errno != ENOENT ) SHOW_RESULT( open, err ); + + NEW_FILENAME1( "x/y" ) + diag_printf("<INFO>: rename fum %s -- should fail\n",filename1); + err = rename( "fum", filename1 ); + if( err < 0 && errno != ENOENT ) SHOW_RESULT( rename, err ); + + diag_printf("<INFO>: rename fum fum -- should succeed\n"); + err = rename( "fum", "fum" ); + if( err < 0 ) SHOW_RESULT( rename, err ); + + diag_printf("<INFO>: unlink fee -- should fail\n"); + err = unlink( "fee" ); + if( err < 0 && errno != ENOENT ) SHOW_RESULT( unlink, err ); + + NEW_FILENAME1( "bar" ); + diag_printf("<INFO>: rmdir %s -- should fail\n",filename1); + err = rmdir( filename1 ); + // FATFS gives EBUSY here, since bar is the current dir + if( err < 0 && errno != ENOTEMPTY ) SHOW_RESULT( rmdir, err ); + + diag_printf("<INFO>: unlink %s -- should fail\n",filename1); + err = unlink( filename1 ); + // FATFS returns EBUSY here, also because bar is current dir + if( err < 0 && errno != EISDIR ) SHOW_RESULT( unlink, err ); + + NEW_FILENAME1( "bar/fum" ); + diag_printf("<INFO>: rmdir %s -- should fail\n",filename1); + err = rmdir( filename1 ); + if( err < 0 && errno != ENOTDIR ) SHOW_RESULT( rmdir, err ); + + diag_printf("<INFO>: mkdir %s -- should fail\n",filename1); + err = mkdir( filename1, 0 ); + if( err < 0 && errno != EEXIST ) SHOW_RESULT( mkdir, err ); + + diag_printf("<INFO>: open bundy exclusive -- should fail\n"); + fd = open( "bundy", O_WRONLY|O_CREAT|O_EXCL ); + if( fd < 0 && errno != EEXIST ) SHOW_RESULT( open, fd ); + + diag_printf("<INFO>: open %s -- should fail\n",dirname); + fd = open( dirname, O_WRONLY ); + if( fd < 0 && errno != EISDIR ) SHOW_RESULT( open, fd ); + + + listdir( dirname, true, existingdirents+2, NULL ); + listdir( "." , true, 6, NULL ); + + // -------------------------------------------------------------- + + diag_printf("<INFO>: rename fie doo\n"); + err = rename( "fie", "doo" ); + if( err < 0 ) SHOW_RESULT( unlink, err ); + + diag_printf("<INFO>: rmdir doo/foe\n"); + err = rmdir("doo/foe"); + if( err < 0 ) SHOW_RESULT( unlink, err ); + + diag_printf("<INFO>: rmdir doo\n"); + err = rmdir("doo"); + if( err < 0 ) SHOW_RESULT( unlink, err ); + + diag_printf("<INFO>: unlink ../fee\n"); + err = unlink( "../fee" ); + if( err < 0 ) SHOW_RESULT( unlink, err ); + + diag_printf("<INFO>: unlink fum\n"); + err = unlink( "fum" ); + if( err < 0 ) SHOW_RESULT( unlink, err ); + + diag_printf("<INFO>: unlink ../bar/bundy\n"); + err = unlink( "../bar/bundy" ); + if( err < 0 ) SHOW_RESULT( unlink, err ); + + diag_printf("<INFO>: cd ..\n"); + err = chdir( ".." ); + if( err < 0 ) SHOW_RESULT( chdir, err ); + + checkcwd( dirname ); + + diag_printf("<INFO>: rmdir bar\n"); + err = rmdir( "bar" ); + if( err < 0 ) SHOW_RESULT( rmdir, err ); + + listdir( dirname, false, existingdirents, NULL ); + + // -------------------------------------------------------------- + +#ifdef TEST_MOUNTPOINT2 + diag_printf("<INFO>: mount %s\n", TEST_MOUNTPOINT2); + err = mount( TEST_DEVICE2, TEST_MOUNTPOINT2, TEST_FSTYPE2 ); + + if( err == 0 ) + { + mp2 = true; + diag_printf("<INFO>: mount %s succeeded\n", TEST_MOUNTPOINT2); + err = access( TEST_MOUNTPOINT2 TEST_DIRECTORY2, F_OK ); + if( err < 0 && errno != EACCES ) SHOW_RESULT( access, err ); + + if( err < 0 && errno == EACCES ) + { + diag_printf("<INFO>: create %s\n", + TEST_MOUNTPOINT2 TEST_DIRECTORY2); + err = mkdir( TEST_MOUNTPOINT2 TEST_DIRECTORY2, 0 ); + if( err < 0 ) SHOW_RESULT( mkdir, err ); + } + + err = chdir( TEST_MOUNTPOINT2 TEST_DIRECTORY2 ); + if( err < 0 ) SHOW_RESULT( chdir, err ); + + checkcwd( TEST_MOUNTPOINT2 TEST_DIRECTORY2 ); + + dirname[0] = 0; + strcat(dirname, TEST_MOUNTPOINT2 ); + strcat(dirname, TEST_DIRECTORY2 ); + + } + else + { + mp2 = false; + diag_printf("<INFO>: mount %s failed, ", TEST_MOUNTPOINT2); + diag_printf("using %s instead\n", dirname ); + } + +#endif + + listdir( dirname , true, -1, &existingdirents); + + NEW_FILENAME1( "tinky" ); + NEW_FILENAME2( "laalaa" ); + + createfile( filename1, 4567 ); + copyfile( filename1, filename2 ); + checkfile( filename1); + checkfile( filename2); + comparefiles( filename1, filename2 ); + + diag_printf("<INFO>: cd %s\n",dirname); + err = chdir( dirname ); + if( err < 0 ) SHOW_RESULT( chdir, err ); + + checkcwd( dirname ); + + diag_printf("<INFO>: mkdir noonoo\n"); + err = mkdir( "noonoo", 0 ); + if( err < 0 ) SHOW_RESULT( mkdir, err ); + + listdir( dirname , true, existingdirents+3, NULL); + + diag_printf("<INFO>: cd noonoo\n"); + err = chdir( "noonoo" ); + if( err < 0 ) SHOW_RESULT( chdir, err ); + + NEW_FILENAME1( "noonoo" ); + checkcwd( filename1 ); + + createfile( "tinky", 6789 ); + checkfile( "tinky" ); + + createfile( "dipsy", 34567 ); + checkfile( "dipsy" ); + copyfile( "dipsy", "po" ); + checkfile( "po" ); + comparefiles( "dipsy", "po" ); + + listdir( ".", true, 5, NULL ); + listdir( "..", true, existingdirents+3, NULL ); + + // -------------------------------------------------------------- + + diag_printf("<INFO>: unlink tinky\n"); + err = unlink( "tinky" ); + if( err < 0 ) SHOW_RESULT( unlink, err ); + + diag_printf("<INFO>: unlink dipsy\n"); + err = unlink( "dipsy" ); + if( err < 0 ) SHOW_RESULT( unlink, err ); + + diag_printf("<INFO>: unlink po\n"); + err = unlink( "po" ); + if( err < 0 ) SHOW_RESULT( unlink, err ); + + diag_printf("<INFO>: cd ..\n"); + err = chdir( ".." ); + if( err < 0 ) SHOW_RESULT( chdir, err ); + checkcwd( dirname ); + + diag_printf("<INFO>: rmdir noonoo\n"); + err = rmdir( "noonoo" ); + if( err < 0 ) SHOW_RESULT( rmdir, err ); + + // -------------------------------------------------------------- + + diag_printf("<INFO>: mkdir x\n"); + err = mkdir( "x", 0 ); + if( err < 0 ) SHOW_RESULT( mkdir, err ); + + diag_printf("<INFO>: mkdir x/y\n"); + err = mkdir( "x/y", 0 ); + if( err < 0 ) SHOW_RESULT( mkdir, err ); + + diag_printf("<INFO>: mkdir x/y/z\n"); + err = mkdir( "x/y/z", 0 ); + if( err < 0 ) SHOW_RESULT( mkdir, err ); + + diag_printf("<INFO>: mkdir x/y/z/w\n"); + err = mkdir( "x/y/z/w", 0 ); + if( err < 0 ) SHOW_RESULT( mkdir, err ); + + NEW_FILENAME1( "x/y/z/w" ); + diag_printf("<INFO>: cd %s\n",filename1); + err = chdir( filename1 ); + if( err < 0 ) SHOW_RESULT( chdir, err ); + checkcwd( filename1 ); + + NEW_FILENAME1( "x/y/z" ); + diag_printf("<INFO>: cd ..\n"); + err = chdir( ".." ); + if( err < 0 ) SHOW_RESULT( chdir, err ); + checkcwd( filename1 ); + + NEW_FILENAME1( "x/y/z" ); + diag_printf("<INFO>: cd .\n"); + err = chdir( "." ); + if( err < 0 ) SHOW_RESULT( chdir, err ); + checkcwd( filename1 ); + + NEW_FILENAME1( "x/y" ); + diag_printf("<INFO>: cd ../../y\n"); + err = chdir( "../../y" ); + if( err < 0 ) SHOW_RESULT( chdir, err ); + checkcwd( filename1 ); + + diag_printf("<INFO>: cd ../..\n"); + err = chdir( "../.." ); + if( err < 0 ) SHOW_RESULT( chdir, err ); + checkcwd( dirname ); + + diag_printf("<INFO>: rmdir x/y/z/w\n"); + err = rmdir( "x/y/z/w" ); + if( err < 0 ) SHOW_RESULT( rmdir, err ); + + diag_printf("<INFO>: rmdir x/y/z\n"); + err = rmdir( "x/y/z" ); + if( err < 0 ) SHOW_RESULT( rmdir, err ); + + diag_printf("<INFO>: rmdir x/y\n"); + err = rmdir( "x/y" ); + if( err < 0 ) SHOW_RESULT( rmdir, err ); + + diag_printf("<INFO>: rmdir x\n"); + err = rmdir( "x" ); + if( err < 0 ) SHOW_RESULT( rmdir, err ); + + // -------------------------------------------------------------- + + checkcwd( dirname ); + + diag_printf("<INFO>: unlink tinky\n"); + err = unlink( "tinky" ); + if( err < 0 ) SHOW_RESULT( unlink, err ); + + diag_printf("<INFO>: unlink laalaa\n"); + err = unlink( "laalaa" ); + if( err < 0 ) SHOW_RESULT( unlink, err ); + + // -------------------------------------------------------------- + + diag_printf("<INFO>: cd %s\n", TEST_MOUNTPOINT TEST_DIRECTORY); + err = chdir( TEST_MOUNTPOINT TEST_DIRECTORY); + if( err < 0 ) SHOW_RESULT( chdir, err ); + checkcwd( TEST_MOUNTPOINT TEST_DIRECTORY ); + + listdir( ".", true, -1, NULL ); + +#ifdef TEST_MOUNTPOINT2 + if( mp2 ) + { + diag_printf("<INFO>: umount %s\n",TEST_MOUNTPOINT2); + err = umount( TEST_MOUNTPOINT2 ); + if( err < 0 ) SHOW_RESULT( umount, err ); + } +#endif + + // -------------------------------------------------------------- + +#if 0 + maxfile("file.max"); + + listdir( "/", true, -1, NULL ); + + diag_printf("<INFO>: unlink file.max\n"); + err = unlink( "file.max" ); + if( err < 0 ) SHOW_RESULT( unlink, err ); +#endif + + // -------------------------------------------------------------- + + diag_printf("<INFO>: cd /\n"); + err = chdir( "/" ); + if( err == 0 ) + { + checkcwd( "/" ); + + diag_printf("<INFO>: umount %s\n",TEST_MOUNTPOINT); + err = umount( TEST_MOUNTPOINT ); + if( err < 0 ) SHOW_RESULT( umount, err ); + } + + diag_printf("<INFO>: syncing\n"); + sync(); + + CYG_TEST_PASS_FINISH("yaffs1"); +} + +// ------------------------------------------------------------------------- + +#include <cyg/kernel/kapi.h> + +static cyg_handle_t thread_handle; +static cyg_thread thread; +static char stack[CYGNUM_HAL_STACK_SIZE_TYPICAL+1024]; + +externC void +cyg_start( void ) +{ + cyg_thread_create(3, // Priority - just a number + fileio1_main, // entry + 0, // index + 0, // no name + &stack[0], // Stack + sizeof(stack), // Size + &thread_handle, // Handle + &thread // Thread data structure + ); + cyg_thread_resume(thread_handle); + + cyg_scheduler_start(); +} + +// ------------------------------------------------------------------------- +// EOF yaffs1.c
new file mode 100644 --- /dev/null +++ b/packages/fs/yaffs/current/tests/yaffs2.c @@ -0,0 +1,809 @@ +//========================================================================== +// +// yaffs2.c +// +// Test fileio system +// +//========================================================================== +// ####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 1998, 1999, 2000, 2001, 2002, 2004, 2006, 2007 Free Software Foundation, Inc. +// Copyright (C) 2004, 2006, 2007 eCosCentric Limited +// +// eCos is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 2 or (at your option) any later +// version. +// +// eCos is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License +// along with eCos; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +// +// As a special exception, if other files instantiate templates or use +// macros or inline functions from this file, or you compile this file +// and link it with other works to produce a work based on this file, +// this file does not by itself cause the resulting work to be covered by +// the GNU General Public License. However the source code for this file +// must still be made available in accordance with section (3) of the GNU +// General Public License v2. +// +// This exception does not invalidate any other reasons why a work based +// on this file might be covered by the GNU General Public License. +// ------------------------------------------- +// ####ECOSGPLCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): nickg +// Contributors: nickg +// Date: 2000-05-25 +// Purpose: Test fileio system +// Description: This test uses the testfs to check out the initialization +// and basic operation of the fileio system +// +// +// +// +// +// +// +//####DESCRIPTIONEND#### +// +//========================================================================== + +#include <pkgconf/hal.h> +#include <pkgconf/kernel.h> +#include <pkgconf/io_fileio.h> +#include <pkgconf/io_fileio.h> + +#include CYGDAT_DEVS_DISK_CFG // testing config defines + +#include <cyg/kernel/ktypes.h> // base kernel types +#include <cyg/infra/cyg_trac.h> // tracing macros +#include <cyg/infra/cyg_ass.h> // assertion macros + +#include <unistd.h> +#include <fcntl.h> +#include <sys/stat.h> +#include <errno.h> +#include <string.h> +#include <dirent.h> + +#include <cyg/fileio/fileio.h> + +#include <cyg/infra/testcase.h> +#include <cyg/infra/diag.h> // HAL polled output + +#include <cyg/kernel/instrmnt.h> + +//========================================================================== +// Config options + +#define TEST_DEVICE CYGDAT_DEVS_DISK_TEST_DEVICE + +#define TEST_MOUNTPOINT CYGDAT_DEVS_DISK_TEST_MOUNTPOINT + +#define TEST_DIRECTORY CYGDAT_DEVS_DISK_TEST_DIRECTORY + +#define TEST_FSTYPE "yaffs" + +#ifdef CYGDAT_DEVS_DISK_TEST_MOUNTPOINT2 + +#define TEST_DEVICE2 CYGDAT_DEVS_DISK_TEST_DEVICE2 + +#define TEST_MOUNTPOINT2 CYGDAT_DEVS_DISK_TEST_MOUNTPOINT2 + +#define TEST_DIRECTORY2 CYGDAT_DEVS_DISK_TEST_DIRECTORY2 + +#define TEST_FSTYPE2 "yaffs" + +#endif + +//========================================================================== + +#if 0 +# define X(_args_) \ +{ \ + cyg_drv_isr_lock(); \ + diag_printf("%08x: ",cyg_thread_self()); \ + diag_printf _args_; \ + cyg_drv_isr_unlock(); \ + \ +} +#else +# define X(_args_) CYG_EMPTY_STATEMENT +#endif + +#ifdef JNGPKG_USB_STACK +extern int usb_stack_init(void); +#endif + +//========================================================================== + +#define SHOW_RESULT( _fn, _res ) \ +diag_printf("<FAIL>: " #_fn "() returned %ld %s\n", (long)_res, _res<0?strerror(errno):""); + +//========================================================================== + +#define IOSIZE 100 + +#define NTHREAD 6 + + +//========================================================================== + +#ifndef CYGPKG_LIBC_STRING + +char *strcat( char *s1, const char *s2 ) +{ + char *s = s1; + while( *s1 ) s1++; + while( (*s1++ = *s2++) != 0); + return s; +} + +#endif + +__externC int +rename( const char * /* oldpath */, const char * /* newpath */ ) __THROW; + +//========================================================================== + + +static cyg_mutex_t db_lock; + +#define db_printf( args... ) \ +{ \ + cyg_mutex_lock( &db_lock ); \ + diag_printf("%d: ",id); \ + diag_printf( args ); \ + cyg_mutex_unlock( &db_lock ); \ +} + +//========================================================================== + +static void listdir( char *name, int statp, int numexpected, int *numgot, int id ) +{ + int err; + DIR *dirp; + int num=0; + + db_printf("<INFO>: reading directory %s\n",name); + + dirp = opendir( name ); + if( dirp == NULL ) SHOW_RESULT( opendir, -1 ); + + for(;;) + { + struct dirent entry_data; + struct dirent *entry; + + err = readdir_r( dirp, &entry_data, &entry ); + + if( err < 0 || entry == NULL ) + break; + num++; + + cyg_mutex_lock( &db_lock ); + diag_printf("%d: <INFO>: entry %14s",id, entry->d_name); + + if( statp ) + { + char fullname[PATH_MAX]; + struct stat sbuf; + + if( name[0] ) + { + strcpy(fullname, name ); + if( !(name[0] == '/' && name[1] == 0 ) ) + strcat(fullname, "/" ); + } + else fullname[0] = 0; + + strcat(fullname, entry->d_name ); + + err = stat( fullname, &sbuf ); + if( err < 0 ) + { + if( errno == ENOSYS ) + diag_printf(" <no status available>"); + else + { + SHOW_RESULT( stat, err ); + cyg_scheduler_lock(); + CYG_INSTRUMENT_USER(0xff,err,errno); + for(;;); + } + } + else + { + diag_printf(" [mode %08x ino %08x nlink %d size %ld]", + sbuf.st_mode,sbuf.st_ino,sbuf.st_nlink,sbuf.st_size); + } + } + + diag_printf("\n"); + cyg_mutex_unlock( &db_lock ); + } + + err = closedir( dirp ); + if( err < 0 ) SHOW_RESULT( stat, err ); + if (numexpected >= 0 && num != numexpected) + CYG_TEST_FAIL("Wrong number of dir entries\n"); + if ( numgot != NULL ) + *numgot = num; +} + +//========================================================================== + +static void createfile( char *name, size_t size, int id ) +{ + char buf[IOSIZE]; + int fd; + ssize_t wrote; + int i; + int err; + + db_printf("<INFO>: create file %s size %ld\n",name, (long)size); + + err = access( name, F_OK ); + if( err < 0 && errno == EEXIST ) + { + err = unlink( name ); + if( err < 0 ) SHOW_RESULT( unlink, err ); + } + else + if( err < 0 && errno != EACCES ) SHOW_RESULT( access, err ); + + for( i = 0; i < IOSIZE; i++ ) buf[i] = i%256; + + fd = open( name, O_WRONLY|O_CREAT ); + if( fd < 0 ) SHOW_RESULT( open, fd ); + + while( size > 0 ) + { + ssize_t len = size; + if ( len > IOSIZE ) len = IOSIZE; + + wrote = write( fd, buf, len ); + if( wrote != len ) SHOW_RESULT( write, wrote ); + + size -= wrote; + + cyg_thread_yield(); + } + + err = close( fd ); + if( err < 0 ) SHOW_RESULT( close, err ); +} + +//========================================================================== + +#if 0 +static void maxfile( char *name, int id ) +{ + char buf[IOSIZE]; + int fd; + ssize_t wrote; + int i; + int err; + size_t size = 0; + size_t prevsize = 0; + + db_printf("<INFO>: create maximal file %s\n",name); + db_printf("<INFO>: This may take a few minutes\n"); + + err = access( name, F_OK ); + if( err < 0 && errno != EACCES ) SHOW_RESULT( access, err ); + + for( i = 0; i < IOSIZE; i++ ) buf[i] = i%256; + + fd = open( name, O_WRONLY|O_CREAT ); + if( fd < 0 ) SHOW_RESULT( open, fd ); + + do + { + wrote = write( fd, buf, IOSIZE ); + //if( wrote < 0 ) SHOW_RESULT( write, wrote ); + + if( wrote >= 0 ) + size += wrote; + + if( (size-prevsize) > 100000 ) + { + db_printf("<INFO>: size = %ld \n", size); + prevsize = size; + } + + } while( wrote == IOSIZE ); + + db_printf("<INFO>: file size == %ld\n",size); + + err = close( fd ); + if( err < 0 ) SHOW_RESULT( close, err ); +} +#endif + +//========================================================================== + +static void checkfile( char *name, int id ) +{ + char buf[IOSIZE]; + int fd; + ssize_t done; + int i; + int err; + off_t pos = 0; + + db_printf("<INFO>: check file %s\n",name); + + err = access( name, F_OK ); + if( err != 0 ) SHOW_RESULT( access, err ); + + fd = open( name, O_RDONLY ); + if( fd < 0 ) SHOW_RESULT( open, fd ); + + for(;;) + { + done = read( fd, buf, IOSIZE ); + if( done < 0 ) SHOW_RESULT( read, done ); + + if( done == 0 ) break; + + for( i = 0; i < done; i++ ) + if( buf[i] != i%256 ) + { +// db_printf("buf[%d+%d](%02x) != %02x\n",pos,i,buf[i],i%256); +// CYG_TEST_FAIL("Data read not equal to data written\n"); + X(("buf[%ld+%d](%02x) != %02x\n",pos,i,buf[i],i%256)); + cyg_scheduler_lock(); + CYG_INSTRUMENT_USER(0xf0,err,errno); + for(;;); + } + + pos += done; + + cyg_thread_yield(); + } + + err = close( fd ); + if( err < 0 ) SHOW_RESULT( close, err ); +} + +//========================================================================== + +static void copyfile( char *name2, char *name1, int id ) +{ + + int err; + char buf[IOSIZE]; + int fd1, fd2; + ssize_t done, wrote; + + db_printf("<INFO>: copy file %s -> %s\n",name2,name1); + + err = access( name1, F_OK ); + if( err < 0 && errno != EACCES ) SHOW_RESULT( access, err ); + + err = access( name2, F_OK ); + if( err != 0 ) SHOW_RESULT( access, err ); + + fd1 = open( name1, O_WRONLY|O_CREAT ); + if( fd1 < 0 ) SHOW_RESULT( open, fd1 ); + + fd2 = open( name2, O_RDONLY ); + if( fd2 < 0 ) SHOW_RESULT( open, fd2 ); + + for(;;) + { + done = read( fd2, buf, IOSIZE ); + if( done < 0 ) SHOW_RESULT( read, done ); + + if( done == 0 ) break; + + wrote = write( fd1, buf, done ); + if( wrote != done ) SHOW_RESULT( write, wrote ); + + if( wrote != done ) break; + + cyg_thread_yield(); + } + + err = close( fd1 ); + if( err < 0 ) SHOW_RESULT( close, err ); + + err = close( fd2 ); + if( err < 0 ) SHOW_RESULT( close, err ); + +} + +//========================================================================== + +static void comparefiles( char *name2, char *name1, int id ) +{ + int err; + char buf1[IOSIZE]; + char buf2[IOSIZE]; + int fd1, fd2; + ssize_t done1, done2; + int i; + + db_printf("<INFO>: compare files %s == %s\n",name2,name1); + + err = access( name1, F_OK ); + if( err != 0 ) SHOW_RESULT( access, err ); + + err = access( name1, F_OK ); + if( err != 0 ) SHOW_RESULT( access, err ); + + fd1 = open( name1, O_RDONLY ); + if( fd1 < 0 ) SHOW_RESULT( open, fd1 ); + + fd2 = open( name2, O_RDONLY ); + if( fd2 < 0 ) SHOW_RESULT( open, fd2 ); + + for(;;) + { + done1 = read( fd1, buf1, IOSIZE ); + if( done1 < 0 ) SHOW_RESULT( read, done1 ); + + done2 = read( fd2, buf2, IOSIZE ); + if( done2 < 0 ) SHOW_RESULT( read, done2 ); + + if( done1 != done2 ) + db_printf("Files different sizes\n"); + + if( done1 == 0 ) break; + + for( i = 0; i < done1; i++ ) + if( buf1[i] != buf2[i] ) + { +// db_printf("buf1[%d](%02x) != buf1[%d](%02x)\n",i,buf1[i],i,buf2[i]); +// CYG_TEST_FAIL("Data in files not equal\n"); + X(("%s[%d](%02x) != %s[%d](%02x)\n",name1,i,buf1[i],name2,i,buf2[i])); + cyg_scheduler_lock(); + CYG_INSTRUMENT_USER(0xf1,err,errno); + for(;;); + } + + cyg_thread_yield(); + } + + err = close( fd1 ); + if( err < 0 ) SHOW_RESULT( close, err ); + + err = close( fd2 ); + if( err < 0 ) SHOW_RESULT( close, err ); + +} + +//========================================================================== + +void checkcwd( const char *cwd, int id ) +{ + static char cwdbuf[PATH_MAX]; + char *ret; + + ret = getcwd( cwdbuf, sizeof(cwdbuf)); + if( ret == NULL ) SHOW_RESULT( getcwd, ret ); + + if( strcmp( cwdbuf, cwd ) != 0 ) + { + db_printf( "cwdbuf %s cwd %s\n",cwdbuf, cwd ); + CYG_TEST_FAIL( "Current directory mismatch"); + } +} + +//========================================================================== +// main + +static cyg_sem_t sem; + +void fileio2_main( CYG_ADDRESS id ) +{ + int err; + int existingdirents=-1; + + char dirname[64]; + char filename1[64]; + char filename2[64]; + +#define NEW_FILENAME( fn, f ) \ +{ \ + fn[0]=0; \ + strcat(fn, dirname); \ + strcat(fn, "/"); \ + strcat(fn,f); \ +} + +#define NEW_FILENAME1( f ) NEW_FILENAME( filename1, f ) +#define NEW_FILENAME2( f ) NEW_FILENAME( filename2, f ) + + // -------------------------------------------------------------- + + if( id == 0 ) + { + int i; + +#ifdef JNGPKG_USB_STACK + err = usb_stack_init(); + cyg_thread_delay( 1000 ); +#endif + + CYG_TEST_INIT(); + + err = mount( TEST_DEVICE, TEST_MOUNTPOINT, TEST_FSTYPE ); + if( err < 0 ) { + SHOW_RESULT( mount, err ); + CYG_TEST_FAIL_FINISH("yaffs2"); + } + + err = access( TEST_MOUNTPOINT TEST_DIRECTORY, F_OK ); + if( err < 0 && errno != EACCES ) SHOW_RESULT( access, err ); + + if( err < 0 && errno == EACCES ) + { + db_printf("<INFO>: create %s\n", + TEST_MOUNTPOINT TEST_DIRECTORY); + err = mkdir( TEST_MOUNTPOINT TEST_DIRECTORY, 0 ); + if( err < 0 ) SHOW_RESULT( mkdir, err ); + } + + err = chdir( TEST_MOUNTPOINT TEST_DIRECTORY ); + if( err < 0 ) SHOW_RESULT( chdir, err ); + + checkcwd( TEST_MOUNTPOINT TEST_DIRECTORY, id ); + + for( i = 0; i < NTHREAD-1; i++ ) + cyg_semaphore_post( &sem ); + } + else + { + cyg_semaphore_wait( &sem ); + } + + // -------------------------------------------------------------- + + dirname[0] = 0; + strcat(dirname, TEST_MOUNTPOINT ); + strcat(dirname, TEST_DIRECTORY ); + strcat(dirname, "/dirX"); + dirname[sizeof(TEST_MOUNTPOINT) + + sizeof(TEST_DIRECTORY) - 2 + + 4] = '0' + id; +// dirname[5] = 0; + + + db_printf("<INFO>: create %s\n",dirname); + err = mkdir( dirname, 0 ); + if( err < 0 && errno != EEXIST ) SHOW_RESULT( mkdir, err ); + + listdir( dirname, true, -1, &existingdirents, id ); + + db_printf("<INFO>: existingdirents %d\n",existingdirents); + + // -------------------------------------------------------------- + + NEW_FILENAME1( "foo" ); + createfile( filename1, 20257, id ); + checkfile( filename1, id ); + + NEW_FILENAME1( "foo" ); + NEW_FILENAME2( "fee" ); + + copyfile( filename1, filename2, id); + checkfile( filename2, id ); + comparefiles( filename1, filename2, id ); + + NEW_FILENAME1( "bar" ); + db_printf("<INFO>: mkdir bar\n"); + err = mkdir( filename1, 0 ); + if( err < 0 ) SHOW_RESULT( mkdir, err ); + + listdir( dirname , true, existingdirents+3, NULL, id ); + + NEW_FILENAME1( "bar/fum" ); + copyfile( filename2, filename1, id ); + checkfile( filename1, id ); + comparefiles( filename2, filename1, id ); + + NEW_FILENAME1( "foo" ); + NEW_FILENAME2( "bar/bundy" ); + db_printf("<INFO>: rename %s -> %s\n",filename1,filename2); + err = rename( filename1, filename2 ); + if( err < 0 ) SHOW_RESULT( rename, err ); + + NEW_FILENAME1( "bar" ); + + listdir( dirname, true, existingdirents+2, NULL, id ); + listdir( filename1 , true, 4, NULL, id ); + + NEW_FILENAME1( "fee" ); + checkfile( filename2, id ); + comparefiles( filename1, filename2, id ); + +// db_printf("spinning\n"); for(;;) cyg_thread_delay(10); + + + // -------------------------------------------------------------- + + db_printf("<INFO>: unlink %s\n",filename1); + err = unlink( filename1 ); + if( err < 0 ) SHOW_RESULT( unlink, err ); + + NEW_FILENAME1( "bar/fum" ); + db_printf("<INFO>: unlink %s\n",filename1); + err = unlink( filename1 ); + if( err < 0 ) SHOW_RESULT( unlink, err ); + + NEW_FILENAME1( "bar/bundy" ); + db_printf("<INFO>: unlink %s\n",filename1); + err = unlink( filename1 ); + if( err < 0 ) SHOW_RESULT( unlink, err ); + + NEW_FILENAME1( "bar" ); + db_printf("<INFO>: rmdir %s\n",filename1); + err = rmdir( filename1 ); + if( err < 0 ) SHOW_RESULT( rmdir, err ); + +// listdir( dirname, false, existingdirents, NULL, id ); + + listdir( dirname, true, existingdirents, NULL, id ); + + // -------------------------------------------------------------- + + + listdir( dirname , true, -1, &existingdirents, id); + + NEW_FILENAME1( "tinky" ); + NEW_FILENAME2( "laalaa" ); + createfile( filename1, 4567, id ); + copyfile( filename1, filename2, id ); + checkfile( filename1, id); + checkfile( filename2, id); + comparefiles( filename1, filename2, id ); + + NEW_FILENAME1( "noonoo" ); + db_printf("<INFO>: mkdir %s\n",filename1); + err = mkdir( filename1, 0 ); + if( err < 0 ) SHOW_RESULT( mkdir, err ); + + listdir( dirname , true, existingdirents+3, NULL, id); + + NEW_FILENAME1( "noonoo/tinky" ); + createfile( filename1, 6789, id ); + checkfile( filename1, id ); + + NEW_FILENAME1( "noonoo/dipsy" ); + NEW_FILENAME2( "noonoo/po" ); + createfile( filename1, 34567, id ); + checkfile( filename1, id ); + copyfile( filename1, filename2, id ); + checkfile( filename2, id ); + comparefiles( filename1, filename2, id ); + + NEW_FILENAME1( "noonoo" ); + listdir( filename1, true, 5, NULL, id ); + listdir( dirname, true, existingdirents+3, NULL, id ); + + // -------------------------------------------------------------- + + NEW_FILENAME1( "noonoo/tinky" ); + db_printf("<INFO>: unlink %s\n",filename1); + err = unlink( filename1 ); + if( err < 0 ) SHOW_RESULT( unlink, err ); + + NEW_FILENAME1( "noonoo/dipsy" ); + db_printf("<INFO>: unlink %s\n",filename1); + err = unlink( filename1 ); + if( err < 0 ) SHOW_RESULT( unlink, err ); + + NEW_FILENAME1( "noonoo/po" ); + db_printf("<INFO>: unlink %s\n",filename1); + err = unlink( filename1 ); + if( err < 0 ) SHOW_RESULT( unlink, err ); + + NEW_FILENAME1( "noonoo" ); + db_printf("<INFO>: rmdir %s\n",filename1); + err = rmdir( filename1 ); + if( err < 0 ) SHOW_RESULT( rmdir, err ); + + listdir( dirname, true, existingdirents+2, NULL, id ); + + // -------------------------------------------------------------- + + + NEW_FILENAME1( "tinky" ); + db_printf("<INFO>: unlink %s\n",filename1); + err = unlink( filename1 ); + if( err < 0 ) SHOW_RESULT( unlink, err ); + + NEW_FILENAME1( "laalaa" ); + db_printf("<INFO>: unlink %s\n",filename1); + err = unlink( filename1 ); + if( err < 0 ) SHOW_RESULT( unlink, err ); + + listdir( dirname, true, -1, NULL, id ); + +#if 0 + NEW_FILENAME1( "file.max" ); + maxfile( filename1, id ); + + listdir( dirname, true, -1, NULL, id ); + + db_printf("<INFO>: unlink %s\n",filename1); + err = unlink( filename1 ); + if( err < 0 ) SHOW_RESULT( unlink, err ); +#endif + + db_printf("<INFO>: rmdir %s\n",dirname); + err = rmdir( dirname ); + if( err < 0 ) SHOW_RESULT( unlink, err ); + + db_printf("<INFO>: syncing\n"); + sync(); + + if( id == 0 ) + { + int i; + db_printf("<INFO>: waiting for other threads to finish\n"); + for( i = 0; i < NTHREAD-1; i++ ) + cyg_semaphore_wait( &sem ); + + CYG_TEST_PASS_FINISH("yaffs2"); + } + else + { + db_printf("<INFO>: thread finished\n"); + cyg_semaphore_post( &sem ); + } + + cyg_thread_exit(); +} + +// ------------------------------------------------------------------------- + +#include <cyg/kernel/kapi.h> + +#define STACK_SIZE (CYGNUM_HAL_STACK_SIZE_TYPICAL*2) + +static char stack[NTHREAD][STACK_SIZE]; +static cyg_handle_t thread_handle[NTHREAD]; +static cyg_thread thread[NTHREAD]; + +externC void +cyg_start( void ) +{ + int i; + + CYG_INSTRUMENT_USER(0x01,0,0); + + cyg_mutex_init( &db_lock ); + + cyg_semaphore_init( &sem, 0 ); + + for( i = 0; i < NTHREAD; i++ ) + { + cyg_thread_create(3, // Priority - just a number + fileio2_main, // entry + i, // index + 0, // no name + &stack[i][0], // Stack + STACK_SIZE, // Size + &thread_handle[i], // Handle + &thread[i] // Thread data structure + ); + cyg_thread_resume(thread_handle[i]); + } + + cyg_scheduler_start(); +} + +// ------------------------------------------------------------------------- +// EOF yaffs2.c
new file mode 100644 --- /dev/null +++ b/packages/fs/yaffs/current/tests/yaffs4.c @@ -0,0 +1,934 @@ +//========================================================================== +// +// yaffs4.c +// +// Test fileio system +// +//========================================================================== +// ####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 1998, 1999, 2000, 2001, 2002, 2004, 2005, 2006, 2007 Free Software Foundation, Inc. +// Copyright (C) 2004, 2005, 2006, 2007 eCosCentric Limited +// +// eCos is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 2 or (at your option) any later +// version. +// +// eCos is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License +// along with eCos; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +// +// As a special exception, if other files instantiate templates or use +// macros or inline functions from this file, or you compile this file +// and link it with other works to produce a work based on this file, +// this file does not by itself cause the resulting work to be covered by +// the GNU General Public License. However the source code for this file +// must still be made available in accordance with section (3) of the GNU +// General Public License v2. +// +// This exception does not invalidate any other reasons why a work based +// on this file might be covered by the GNU General Public License. +// ------------------------------------------- +// ####ECOSGPLCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): nickg +// Contributors: nickg +// Date: 2005-07-25 +// Purpose: Test fileio system +// Description: This test uses the testfs to check out the initialization +// and basic operation of the fileio system. +// This is essentially a copy of yaffs1 but using long +// file names. +// +// +// +// +// +// +//####DESCRIPTIONEND#### +// +//========================================================================== + +#include <pkgconf/hal.h> +#include <pkgconf/kernel.h> +#include <pkgconf/io_fileio.h> + +#include CYGDAT_DEVS_DISK_CFG // testing config defines + +#include <cyg/kernel/ktypes.h> // base kernel types +#include <cyg/infra/cyg_trac.h> // tracing macros +#include <cyg/infra/cyg_ass.h> // assertion macros + +#include <unistd.h> +#include <fcntl.h> +#include <sys/stat.h> +#include <errno.h> +#include <string.h> +#include <dirent.h> + +#include <cyg/fileio/fileio.h> + +#include <cyg/infra/testcase.h> +#include <cyg/infra/diag.h> // HAL polled output + +//========================================================================== +// Config options + +#define TEST_DEVICE CYGDAT_DEVS_DISK_TEST_DEVICE + +#define TEST_MOUNTPOINT CYGDAT_DEVS_DISK_TEST_MOUNTPOINT + +#define TEST_DIRECTORY CYGDAT_DEVS_DISK_TEST_DIRECTORY + +#define TEST_FSTYPE "yaffs" + +#ifdef CYGDAT_DEVS_DISK_TEST_MOUNTPOINT2 + +#define TEST_DEVICE2 CYGDAT_DEVS_DISK_TEST_DEVICE2 + +#define TEST_MOUNTPOINT2 CYGDAT_DEVS_DISK_TEST_MOUNTPOINT2 + +#define TEST_DIRECTORY2 CYGDAT_DEVS_DISK_TEST_DIRECTORY2 + +#define TEST_FSTYPE2 "yaffs" + +#endif + +//========================================================================== + +#define SHOW_RESULT( _fn, _res ) \ +{ \ + diag_printf("<FAIL>: " #_fn "() returned %ld %s\n", (long)_res, _res<0?strerror(errno):""); \ +} + +//========================================================================== + +#define IOSIZE 100 + +#define CLEANUP + +#define LONGNAME1 "long_file_name_that_should_take_up_more_than_one_directory_entry_1" +#define LONGNAME2 "long_file_name_that_should_take_up_more_than_one_directory_entry_2" + +// 123456789012345678901234567890 +#define FOO "foo_longer_file_x.filename" +//#define FEE "fee_.filename" +//#define BAR "bar_long_directory_name.dirname" +#define FEE "a234567890123" +#define BAR "a2345678901234" +#define BUNDY "bundy_long_file_name_ccccccccccccccccccccccccccccccc.filename" +#define FUM "bundy_long_file_name_fum.filename" +#define DOO "doo_aaaaaaaaaabbbbbbbbbbbccccccccccccc" +#define FIE "fie.rrrrrrrrrrrrllllllllllllvvvvvvvvvvvvv" +#define FOE "foe_xxxxxxxxxxllllll.xxxxxxeeeeeeeeee" + +#define TINKY "tinky_long_file_name.filename" +#define LAALAA "laalaa_long_file_name.filename" +#define NOONOO "noonoo_long_directory_name.dirname" +#define DIPSY "dipsy_long_file_name.filename" +#define PO "po_long_file_name.filename" + +#define XXXX "xxxx_long_directory_name.dirname" +#define YYYY "yyyy_long_directory_name.dirname" +#define ZZZZ "zzzz_long_directory_name.dirname" +#define WWWW "wwww_long_directory_name.dirname" + + +//========================================================================== + +#ifndef CYGPKG_LIBC_STRING + +char *strcat( char *s1, const char *s2 ) +{ + char *s = s1; + while( *s1 ) s1++; + while( (*s1++ = *s2++) != 0); + return s; +} + +#endif + +__externC int +rename( const char * /* oldpath */, const char * /* newpath */ ) __THROW; + +//========================================================================== + +static void listdir( char *name, int statp, int numexpected, int *numgot ) +{ + int err; + DIR *dirp; + int num=0; + + diag_printf("<INFO>: reading directory %s\n",name); + +// diag_printf("<INFO>: opendir(%s)\n",name); + dirp = opendir( name ); + if( dirp == NULL ) SHOW_RESULT( opendir, -1 ); + + for(;;) + { + struct dirent *entry = readdir( dirp ); + + if( entry == NULL ) + break; + num++; + diag_printf("<INFO>: entry"); + if( statp ) + { + char fullname[PATH_MAX]; + struct stat sbuf; + + if( name[0] ) + { + strcpy(fullname, name ); + if( !(name[0] == '/' && name[1] == 0 ) ) + strcat(fullname, "/" ); + } + else fullname[0] = 0; + + strcat(fullname, entry->d_name ); + + err = stat( fullname, &sbuf ); + if( err < 0 ) + { + if( errno == ENOSYS ) + diag_printf(" <no status available>"); + else SHOW_RESULT( stat, err ); + } + else + { + diag_printf(" [mode %08x ino %08x nlink %d size %6ld]", + sbuf.st_mode,sbuf.st_ino,sbuf.st_nlink,sbuf.st_size); + } + } + + diag_printf(" %s\n",entry->d_name); + } + +// diag_printf("<INFO>: closedir(%s)\n",name); + err = closedir( dirp ); + if( err < 0 ) SHOW_RESULT( stat, err ); + if (numexpected >= 0 && num != numexpected) + CYG_TEST_FAIL("Wrong number of dir entries"); + if ( numgot != NULL ) + *numgot = num; +} + +//========================================================================== + +static void createfile( char *name, size_t size ) +{ + char buf[IOSIZE]; + int fd; + ssize_t wrote; + int i; + int err; + + diag_printf("<INFO>: create file %s size %ld\n",name, (long)size); + + err = access( name, F_OK ); + if( err < 0 && errno != EACCES ) SHOW_RESULT( access, err ); + + for( i = 0; i < IOSIZE; i++ ) buf[i] = i%256; + + fd = open( name, O_WRONLY|O_CREAT ); + if( fd < 0 ) SHOW_RESULT( open, fd ); + + while( size > 0 ) + { + ssize_t len = size; + if ( len > IOSIZE ) len = IOSIZE; + + wrote = write( fd, buf, len ); + if( wrote != len ) SHOW_RESULT( write, wrote ); + + size -= wrote; + } + + err = close( fd ); + if( err < 0 ) SHOW_RESULT( close, err ); +} + +//========================================================================== + +#if 0 +static void maxfile( char *name ) +{ + char buf[IOSIZE]; + int fd; + ssize_t wrote; + int i; + int err; + size_t size = 0; + size_t prevsize = 0; + + diag_printf("<INFO>: create maximal file %s\n",name); + diag_printf("<INFO>: This may take a few minutes\n"); + + err = access( name, F_OK ); + if( err < 0 && errno != EACCES ) SHOW_RESULT( access, err ); + + for( i = 0; i < IOSIZE; i++ ) buf[i] = i%256; + + fd = open( name, O_WRONLY|O_CREAT ); + if( fd < 0 ) SHOW_RESULT( open, fd ); + + do + { + wrote = write( fd, buf, IOSIZE ); + //if( wrote < 0 ) SHOW_RESULT( write, wrote ); + + if( wrote >= 0 ) + size += wrote; + + if( (size-prevsize) > 100000 ) + { + diag_printf("<INFO>: size = %ld \n", size); + prevsize = size; + } + + } while( wrote == IOSIZE ); + + diag_printf("<INFO>: file size == %ld\n",size); + + err = close( fd ); + if( err < 0 ) SHOW_RESULT( close, err ); +} +#endif + +//========================================================================== + +static void checkfile( char *name ) +{ + char buf[IOSIZE]; + int fd; + ssize_t done; + int i; + int err; + off_t pos = 0; + + diag_printf("<INFO>: check file %s\n",name); + + err = access( name, F_OK ); + if( err != 0 ) SHOW_RESULT( access, err ); + + fd = open( name, O_RDONLY ); + if( fd < 0 ) SHOW_RESULT( open, fd ); + + for(;;) + { + done = read( fd, buf, IOSIZE ); + if( done < 0 ) SHOW_RESULT( read, done ); + + if( done == 0 ) break; + + for( i = 0; i < done; i++ ) + if( buf[i] != i%256 ) + { + diag_printf("buf[%ld+%d](%02x) != %02x\n",pos,i,buf[i],i%256); + CYG_TEST_FAIL("Data read not equal to data written\n"); + for(;;); + } + + pos += done; + } + + err = close( fd ); + if( err < 0 ) SHOW_RESULT( close, err ); +} + +//========================================================================== + +static void copyfile( char *name2, char *name1 ) +{ + + int err; + char buf[IOSIZE]; + int fd1, fd2; + ssize_t done, wrote; + + diag_printf("<INFO>: copy file %s -> %s\n",name2,name1); + + err = access( name1, F_OK ); + if( err < 0 && errno != EACCES ) SHOW_RESULT( access, err ); + + err = access( name2, F_OK ); + if( err != 0 ) SHOW_RESULT( access, err ); + + fd1 = open( name1, O_WRONLY|O_CREAT ); + if( fd1 < 0 ) SHOW_RESULT( open, fd1 ); + + fd2 = open( name2, O_RDONLY ); + if( fd2 < 0 ) SHOW_RESULT( open, fd2 ); + + for(;;) + { + done = read( fd2, buf, IOSIZE ); + if( done < 0 ) SHOW_RESULT( read, done ); + + if( done == 0 ) break; + + wrote = write( fd1, buf, done ); + if( wrote != done ) SHOW_RESULT( write, wrote ); + + if( wrote != done ) break; + } + + err = close( fd1 ); + if( err < 0 ) SHOW_RESULT( close, err ); + + err = close( fd2 ); + if( err < 0 ) SHOW_RESULT( close, err ); + +} + +//========================================================================== + +static void comparefiles( char *name2, char *name1 ) +{ + int err; + char buf1[IOSIZE]; + char buf2[IOSIZE]; + int fd1, fd2; + ssize_t done1, done2; + int i; + + diag_printf("<INFO>: compare files %s == %s\n",name2,name1); + + err = access( name1, F_OK ); + if( err != 0 ) SHOW_RESULT( access, err ); + + err = access( name1, F_OK ); + if( err != 0 ) SHOW_RESULT( access, err ); + + fd1 = open( name1, O_RDONLY ); + if( fd1 < 0 ) SHOW_RESULT( open, fd1 ); + + fd2 = open( name2, O_RDONLY ); + if( fd2 < 0 ) SHOW_RESULT( open, fd2 ); + + for(;;) + { + done1 = read( fd1, buf1, IOSIZE ); + if( done1 < 0 ) SHOW_RESULT( read, done1 ); + + done2 = read( fd2, buf2, IOSIZE ); + if( done2 < 0 ) SHOW_RESULT( read, done2 ); + + if( done1 != done2 ) + diag_printf("Files different sizes\n"); + + if( done1 == 0 ) break; + + for( i = 0; i < done1; i++ ) + if( buf1[i] != buf2[i] ) + { + diag_printf("buf1[%d](%02x) != buf1[%d](%02x)\n",i,buf1[i],i,buf2[i]); + CYG_TEST_FAIL("Data in files not equal\n"); + } + } + + err = close( fd1 ); + if( err < 0 ) SHOW_RESULT( close, err ); + + err = close( fd2 ); + if( err < 0 ) SHOW_RESULT( close, err ); + +} + +//========================================================================== + +void checkcwd( const char *cwd ) +{ + static char cwdbuf[PATH_MAX]; + char *ret; + + ret = getcwd( cwdbuf, sizeof(cwdbuf)); + if( ret == NULL ) SHOW_RESULT( getcwd, ret ); + + if( strcmp( cwdbuf, cwd ) != 0 ) + { + diag_printf( "cwdbuf %s cwd %s\n",cwdbuf, cwd ); + CYG_TEST_FAIL( "Current directory mismatch"); + } +} + +//========================================================================== +// main + +void fileio4_main( CYG_ADDRESS id ) +{ + int err; + int existingdirents=-1; + cyg_bool mp2 = false; + int fd; + + char dirname[256]; + char filename1[256]; + char filename2[256]; + +#define NEW_FILENAME( fn, f ) \ +{ \ + fn[0]=0; \ + strcat(fn, dirname); \ + strcat(fn, "/"); \ + strcat(fn,f); \ +} + +#define NEW_FILENAME1( f ) NEW_FILENAME( filename1, f ) +#define NEW_FILENAME2( f ) NEW_FILENAME( filename2, f ) + + CYG_TEST_INIT(); + + // -------------------------------------------------------------- + + err = mount( TEST_DEVICE, TEST_MOUNTPOINT, TEST_FSTYPE ); + if( err < 0 ) { + SHOW_RESULT( mount, err ); + CYG_TEST_FAIL_FINISH("yaffs4"); + } + + err = access( TEST_MOUNTPOINT TEST_DIRECTORY, F_OK ); + if( err < 0 && errno != EACCES ) SHOW_RESULT( access, err ); + + if( err < 0 && errno == EACCES ) + { + diag_printf("<INFO>: create %s\n", + TEST_MOUNTPOINT TEST_DIRECTORY); + err = mkdir( TEST_MOUNTPOINT TEST_DIRECTORY, 0 ); + if( err < 0 ) SHOW_RESULT( mkdir, err ); + } + + err = chdir( TEST_MOUNTPOINT TEST_DIRECTORY ); + if( err < 0 ) SHOW_RESULT( chdir, err ); + + checkcwd( TEST_MOUNTPOINT TEST_DIRECTORY ); + + listdir( TEST_MOUNTPOINT TEST_DIRECTORY, true, -1, &existingdirents ); + + // -------------------------------------------------------------- + + dirname[0] = 0; + strcat(dirname, TEST_MOUNTPOINT ); + strcat(dirname, TEST_DIRECTORY ); + + // -------------------------------------------------------------- + + createfile( FOO, 20257 ); + checkfile( FOO ); + copyfile( FOO, FEE); + checkfile( FEE ); + comparefiles( FOO, FEE ); + diag_printf("<INFO>: mkdir " BAR "\n"); + err = mkdir( BAR, 0 ); + if( err < 0 ) SHOW_RESULT( mkdir, err ); + + listdir( dirname , true, existingdirents+3, NULL ); + + copyfile( FEE, BAR "/" FUM ); + checkfile( BAR "/" FUM ); + comparefiles( FEE, BAR "/" FUM ); + + diag_printf("<INFO>: cd " BAR "\n"); + err = chdir( BAR ); + if( err < 0 ) SHOW_RESULT( chdir, err ); + + NEW_FILENAME1( BAR ); + checkcwd( filename1 ); + + diag_printf("<INFO>: rename ../" FOO " " BUNDY "\n"); + err = rename( "../" FOO, BUNDY ); + if( err < 0 ) SHOW_RESULT( rename, err ); + + listdir( dirname, true, existingdirents+2, NULL ); + listdir( "." , true, 4, NULL ); + + checkfile( "../" BAR "/" BUNDY ); + comparefiles("../" FEE, BUNDY ); + + // -------------------------------------------------------------- + // Check for some common error cases + + // First make some directories + diag_printf("<INFO>: mkdir " DOO "\n"); + err = mkdir( DOO, 0 ); + if( err < 0 ) SHOW_RESULT( mkdir, err ); + + diag_printf("<INFO>: mkdir " FIE" \n"); + err = mkdir( FIE, 0 ); + if( err < 0 ) SHOW_RESULT( mkdir, err ); + + diag_printf("<INFO>: mkdir " FIE "/" FOE "\n"); + err = mkdir( FIE "/" FOE, 0 ); + if( err < 0 ) SHOW_RESULT( mkdir, err ); + + + diag_printf("<INFO>: rename " FUM " " DOO " -- should fail\n"); + err = rename( FUM, DOO ); + if( err < 0 && errno != EISDIR ) SHOW_RESULT( rename, err ); + + diag_printf("<INFO>: rename " DOO " " FUM " -- should fail\n"); + err = rename( DOO, FUM ); + if( err < 0 && errno != ENOTDIR ) SHOW_RESULT( rename, err ); + + diag_printf("<INFO>: rename " DOO " " FIE " -- should fail\n"); + err = rename( DOO, FIE ); + if( err < 0 && errno != EIO ) SHOW_RESULT( rename, err ); + + NEW_FILENAME1( XXXX "/" YYYY ) + diag_printf("<INFO>: rename " FUM " %s -- should fail\n",filename1); + err = rename( FUM, filename1 ); + if( err < 0 && errno != ENOENT ) SHOW_RESULT( rename, err ); + + diag_printf("<INFO>: rename " FUM " " FUM " -- should fail\n"); + err = rename( FUM, FUM ); + if( err < 0 && errno != ENOENT ) SHOW_RESULT( rename, err ); + + diag_printf("<INFO>: unlink " FEE " -- should fail\n"); + err = unlink( FEE ); + if( err < 0 && errno != ENOENT ) SHOW_RESULT( unlink, err ); + + NEW_FILENAME1( BAR ); + diag_printf("<INFO>: rmdir %s -- should fail\n",filename1); + err = rmdir( filename1 ); + if( err < 0 && errno != ENOTEMPTY ) SHOW_RESULT( rmdir, err ); + + diag_printf("<INFO>: unlink %s -- should fail\n",filename1); + err = unlink( filename1 ); + if( err < 0 && errno != EISDIR ) SHOW_RESULT( unlink, err ); + + NEW_FILENAME1( BAR "/" FUM ); + diag_printf("<INFO>: rmdir %s -- should fail\n",filename1); + err = rmdir( filename1 ); + if( err < 0 && errno != ENOTDIR ) SHOW_RESULT( rmdir, err ); + + diag_printf("<INFO>: mkdir %s -- should fail\n",filename1); + err = mkdir( filename1, 0 ); + if( err < 0 && errno != EEXIST ) SHOW_RESULT( mkdir, err ); + + diag_printf("<INFO>: open " BUNDY " exclusive -- should fail\n"); + fd = open( BUNDY, O_WRONLY|O_CREAT|O_EXCL ); + if( fd < 0 && errno != EEXIST ) SHOW_RESULT( open, fd ); + + diag_printf("<INFO>: open %s -- should fail\n",dirname); + fd = open( dirname, O_WRONLY ); + if( fd < 0 && errno != EISDIR ) SHOW_RESULT( open, fd ); + + + listdir( dirname, true, existingdirents+2, NULL ); + listdir( "." , true, 6, NULL ); + + // -------------------------------------------------------------- + +#ifdef CLEANUP + + diag_printf("<INFO>: rename " FIE " " DOO "\n"); + err = rename( FIE, DOO ); + if( err < 0 ) SHOW_RESULT( unlink, err ); + + diag_printf("<INFO>: rmdir " DOO "/" FOE "\n"); + err = rmdir(DOO "/" FOE); + if( err < 0 ) SHOW_RESULT( unlink, err ); + + diag_printf("<INFO>: rmdir " DOO "\n"); + err = rmdir(DOO); + if( err < 0 ) SHOW_RESULT( unlink, err ); + + diag_printf("<INFO>: unlink ../" FEE "\n"); + err = unlink( "../" FEE ); + if( err < 0 ) SHOW_RESULT( unlink, err ); + + diag_printf("<INFO>: unlink " FUM "\n"); + err = unlink( FUM ); + if( err < 0 ) SHOW_RESULT( unlink, err ); + + diag_printf("<INFO>: unlink ../" BAR "/" BUNDY "\n"); + err = unlink( "../" BAR "/" BUNDY ); + if( err < 0 ) SHOW_RESULT( unlink, err ); +#endif + + diag_printf("<INFO>: cd ..\n"); + err = chdir( ".." ); + if( err < 0 ) SHOW_RESULT( chdir, err ); + + checkcwd( dirname ); + +#ifdef CLEANUP + diag_printf("<INFO>: rmdir " BAR "\n"); + err = rmdir( BAR ); + if( err < 0 ) SHOW_RESULT( rmdir, err ); + + listdir( dirname, false, existingdirents, NULL ); +#endif + + // -------------------------------------------------------------- + +#ifdef TEST_MOUNTPOINT2 + diag_printf("<INFO>: mount %s\n", TEST_MOUNTPOINT2); + err = mount( TEST_DEVICE2, TEST_MOUNTPOINT2, TEST_FSTYPE2 ); + + if( err == 0 ) + { + mp2 = true; + diag_printf("<INFO>: mount %s succeeded\n", TEST_MOUNTPOINT2); + err = access( TEST_MOUNTPOINT2 TEST_DIRECTORY2, F_OK ); + if( err < 0 && errno != EACCES ) SHOW_RESULT( access, err ); + + if( err < 0 && errno == EACCES ) + { + diag_printf("<INFO>: create %s\n", + TEST_MOUNTPOINT2 TEST_DIRECTORY2); + err = mkdir( TEST_MOUNTPOINT2 TEST_DIRECTORY2, 0 ); + if( err < 0 ) SHOW_RESULT( mkdir, err ); + } + + err = chdir( TEST_MOUNTPOINT2 TEST_DIRECTORY2 ); + if( err < 0 ) SHOW_RESULT( chdir, err ); + + checkcwd( TEST_MOUNTPOINT2 TEST_DIRECTORY2 ); + + dirname[0] = 0; + strcat(dirname, TEST_MOUNTPOINT2 ); + strcat(dirname, TEST_DIRECTORY2 ); + + } + else + { + mp2 = false; + diag_printf("<INFO>: mount %s failed, ", TEST_MOUNTPOINT2); + diag_printf("using %s instead\n", dirname ); + } + +#endif + + listdir( dirname , true, -1, &existingdirents); + + NEW_FILENAME1( TINKY ); + NEW_FILENAME2( LAALAA ); + + createfile( filename1, 4567 ); + copyfile( filename1, filename2 ); + checkfile( filename1); + checkfile( filename2); + comparefiles( filename1, filename2 ); + + diag_printf("<INFO>: cd %s\n",dirname); + err = chdir( dirname ); + if( err < 0 ) SHOW_RESULT( chdir, err ); + + checkcwd( dirname ); + + diag_printf("<INFO>: mkdir " NOONOO "\n"); + err = mkdir( NOONOO, 0 ); + if( err < 0 ) SHOW_RESULT( mkdir, err ); + + listdir( dirname , true, existingdirents+3, NULL); + + diag_printf("<INFO>: cd " NOONOO "\n"); + err = chdir( NOONOO ); + if( err < 0 ) SHOW_RESULT( chdir, err ); + + NEW_FILENAME1( NOONOO ); + checkcwd( filename1 ); + + createfile( TINKY, 6789 ); + checkfile( TINKY ); + + createfile( DIPSY, 34567 ); + checkfile( DIPSY ); + copyfile( DIPSY, PO ); + checkfile( PO ); + comparefiles( DIPSY, PO ); + + listdir( ".", true, 5, NULL ); + listdir( "..", true, existingdirents+3, NULL ); + + // -------------------------------------------------------------- + +#ifdef CLEANUP + diag_printf("<INFO>: unlink " TINKY "\n"); + err = unlink( TINKY ); + if( err < 0 ) SHOW_RESULT( unlink, err ); + + diag_printf("<INFO>: unlink " DIPSY "\n"); + err = unlink( DIPSY ); + if( err < 0 ) SHOW_RESULT( unlink, err ); + + diag_printf("<INFO>: unlink " PO "\n"); + err = unlink( PO ); + if( err < 0 ) SHOW_RESULT( unlink, err ); +#endif + + diag_printf("<INFO>: cd ..\n"); + err = chdir( ".." ); + if( err < 0 ) SHOW_RESULT( chdir, err ); + checkcwd( dirname ); + +#ifdef CLEANUP + diag_printf("<INFO>: rmdir " NOONOO "\n"); + err = rmdir( NOONOO ); + if( err < 0 ) SHOW_RESULT( rmdir, err ); +#endif + + // -------------------------------------------------------------- + + diag_printf("<INFO>: mkdir " XXXX "\n"); + err = mkdir( XXXX, 0 ); + if( err < 0 ) SHOW_RESULT( mkdir, err ); + + diag_printf("<INFO>: mkdir " XXXX "/" YYYY "\n"); + err = mkdir( XXXX "/" YYYY, 0 ); + if( err < 0 ) SHOW_RESULT( mkdir, err ); + + diag_printf("<INFO>: mkdir " XXXX "/" YYYY "/" ZZZZ "\n"); + err = mkdir( XXXX "/" YYYY "/" ZZZZ, 0 ); + if( err < 0 ) SHOW_RESULT( mkdir, err ); + + diag_printf("<INFO>: mkdir " XXXX "/" YYYY "/" ZZZZ "/" WWWW "\n"); + err = mkdir( XXXX "/" YYYY "/" ZZZZ "/" WWWW, 0 ); + if( err < 0 ) SHOW_RESULT( mkdir, err ); + + NEW_FILENAME1( XXXX "/" YYYY "/" ZZZZ "/" WWWW ); + diag_printf("<INFO>: cd %s\n",filename1); + err = chdir( filename1 ); + if( err < 0 ) SHOW_RESULT( chdir, err ); + checkcwd( filename1 ); + + NEW_FILENAME1( XXXX "/" YYYY "/" ZZZZ ); + diag_printf("<INFO>: cd ..\n"); + err = chdir( ".." ); + if( err < 0 ) SHOW_RESULT( chdir, err ); + checkcwd( filename1 ); + + NEW_FILENAME1( XXXX "/" YYYY "/" ZZZZ ); + diag_printf("<INFO>: cd .\n"); + err = chdir( "." ); + if( err < 0 ) SHOW_RESULT( chdir, err ); + checkcwd( filename1 ); + + NEW_FILENAME1( XXXX "/" YYYY ); + diag_printf("<INFO>: cd ../../" YYYY "\n"); + err = chdir( "../../" YYYY ); + if( err < 0 ) SHOW_RESULT( chdir, err ); + checkcwd( filename1 ); + + diag_printf("<INFO>: cd ../..\n"); + err = chdir( "../.." ); + if( err < 0 ) SHOW_RESULT( chdir, err ); + checkcwd( dirname ); + + diag_printf("<INFO>: rmdir " XXXX "/" YYYY "/" ZZZZ "/" WWWW "\n"); + err = rmdir( XXXX "/" YYYY "/" ZZZZ "/" WWWW ); + if( err < 0 ) SHOW_RESULT( rmdir, err ); + + diag_printf("<INFO>: rmdir "XXXX "/" YYYY "/" ZZZZ "\n"); + err = rmdir( XXXX "/" YYYY "/" ZZZZ ); + if( err < 0 ) SHOW_RESULT( rmdir, err ); + + diag_printf("<INFO>: rmdir " XXXX "/" YYYY "\n"); + err = rmdir( XXXX "/" YYYY ); + if( err < 0 ) SHOW_RESULT( rmdir, err ); + + diag_printf("<INFO>: rmdir "XXXX "\n"); + err = rmdir( XXXX ); + if( err < 0 ) SHOW_RESULT( rmdir, err ); + + // -------------------------------------------------------------- + + checkcwd( dirname ); + +#ifdef CLEANUP + diag_printf("<INFO>: unlink "TINKY "\n"); + err = unlink( TINKY ); + if( err < 0 ) SHOW_RESULT( unlink, err ); + + diag_printf("<INFO>: unlink " LAALAA" \n"); + err = unlink( LAALAA ); + if( err < 0 ) SHOW_RESULT( unlink, err ); +#endif + + // -------------------------------------------------------------- + + diag_printf("<INFO>: cd %s\n", TEST_MOUNTPOINT TEST_DIRECTORY); + err = chdir( TEST_MOUNTPOINT TEST_DIRECTORY); + if( err < 0 ) SHOW_RESULT( chdir, err ); + checkcwd( TEST_MOUNTPOINT TEST_DIRECTORY ); + + listdir( ".", true, -1, NULL ); + +#ifdef TEST_MOUNTPOINT2 + if( mp2 ) + { + diag_printf("<INFO>: umount %s\n",TEST_MOUNTPOINT2); + err = umount( TEST_MOUNTPOINT2 ); + if( err < 0 ) SHOW_RESULT( umount, err ); + } +#endif + + // -------------------------------------------------------------- + +#if 0 + maxfile("file.max"); + + listdir( "/", true, -1, NULL ); + + diag_printf("<INFO>: unlink file.max\n"); + err = unlink( "file.max" ); + if( err < 0 ) SHOW_RESULT( unlink, err ); +#endif + + // -------------------------------------------------------------- + + diag_printf("<INFO>: cd /\n"); + err = chdir( "/" ); + if( err == 0 ) + { + checkcwd( "/" ); + + diag_printf("<INFO>: umount %s\n",TEST_MOUNTPOINT); + err = umount( TEST_MOUNTPOINT ); + if( err < 0 ) SHOW_RESULT( umount, err ); + } + + diag_printf("<INFO>: syncing\n"); + sync(); + + CYG_TEST_PASS_FINISH("yaffs4"); +} + +// ------------------------------------------------------------------------- + +#include <cyg/kernel/kapi.h> + +static cyg_handle_t thread_handle; +static cyg_thread thread; +static char stack[CYGNUM_HAL_STACK_SIZE_TYPICAL+1024*4]; + +externC void +cyg_start( void ) +{ + cyg_thread_create(3, // Priority - just a number + fileio4_main, // entry + 0, // index + 0, // no name + &stack[0], // Stack + sizeof(stack), // Size + &thread_handle, // Handle + &thread // Thread data structure + ); + cyg_thread_resume(thread_handle); + + cyg_scheduler_start(); +} + +// ------------------------------------------------------------------------- +// EOF yaffs4.c
new file mode 100644 --- /dev/null +++ b/packages/fs/yaffs/current/tests/yaffs5.c @@ -0,0 +1,815 @@ +//========================================================================== +// +// yaffs5.c +// +// Test FAT filesystem +// +//========================================================================== +// ####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 1998, 1999, 2000, 2001, 2002, 2004, 2006, 2007 Free Software Foundation, Inc. +// Copyright (C) 2004, 2006, 2007 eCosCentric Limited +// +// eCos is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 2 or (at your option) any later +// version. +// +// eCos is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License +// along with eCos; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +// +// As a special exception, if other files instantiate templates or use +// macros or inline functions from this file, or you compile this file +// and link it with other works to produce a work based on this file, +// this file does not by itself cause the resulting work to be covered by +// the GNU General Public License. However the source code for this file +// must still be made available in accordance with section (3) of the GNU +// General Public License v2. +// +// This exception does not invalidate any other reasons why a work based +// on this file might be covered by the GNU General Public License. +// ------------------------------------------- +// ####ECOSGPLCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): nickg +// Contributors: nickg +// Date: 2007-03-28 +// Purpose: Test FAT system +// Description: This test gets some performance figures from the +// FAT filesystem. +// +//####DESCRIPTIONEND#### +// +//========================================================================== + +#include <pkgconf/hal.h> +#include <pkgconf/kernel.h> +#include <pkgconf/io_fileio.h> + +#include CYGDAT_DEVS_DISK_CFG // testing config defines + +#include <cyg/kernel/ktypes.h> // base kernel types +#include <cyg/infra/cyg_trac.h> // tracing macros +#include <cyg/infra/cyg_ass.h> // assertion macros + +#include <unistd.h> +#include <fcntl.h> +#include <sys/stat.h> +#include <errno.h> +#include <string.h> +#include <dirent.h> +#include <stdlib.h> + +#include <cyg/fileio/fileio.h> + +#include <cyg/infra/testcase.h> +#include <cyg/infra/diag.h> // HAL polled output + +//========================================================================== +// Config options + +#define TEST_DEVICE CYGDAT_DEVS_DISK_TEST_DEVICE + +#define TEST_MOUNTPOINT CYGDAT_DEVS_DISK_TEST_MOUNTPOINT + +#define TEST_DIRECTORY CYGDAT_DEVS_DISK_TEST_DIRECTORY + +#define TEST_FSTYPE "yaffs" + +#ifdef CYGDAT_DEVS_DISK_TEST_MOUNTPOINT2 + +#define TEST_DEVICE2 CYGDAT_DEVS_DISK_TEST_DEVICE2 + +#define TEST_MOUNTPOINT2 CYGDAT_DEVS_DISK_TEST_MOUNTPOINT2 + +#define TEST_DIRECTORY2 CYGDAT_DEVS_DISK_TEST_DIRECTORY2 + +#define TEST_FSTYPE2 "yaffs" + +#endif + +//========================================================================== + +#define SHOW_RESULT( _fn, _res ) \ +{ \ + diag_printf("<FAIL>: " #_fn "() returned %ld %s\n", (long)_res, _res<0?strerror(errno):""); \ +} + +//========================================================================== + +typedef struct +{ + cyg_int64 ticks; + cyg_int32 halticks; +} timestamp; + +typedef struct +{ + timestamp start; + timestamp end; + cyg_int64 interval; // In HAL ticks + cyg_int64 us_interval; // Interval in microseconds +} timing; + +static cyg_int64 ticks_overhead = 0; +static cyg_int32 us_per_haltick = 0; +static cyg_int32 halticks_per_us = 0; + +static cyg_int64 rtc_resolution[] = CYGNUM_KERNEL_COUNTERS_RTC_RESOLUTION; +static cyg_int64 rtc_period = CYGNUM_KERNEL_COUNTERS_RTC_PERIOD; +static cyg_int32 ticks_per_second; + +//========================================================================== + +static char date_string[] = __DATE__; +static char time_string[] = __TIME__; + +cyg_uint32 timehash; + +//========================================================================== + +static void wait_for_tick( void ) +{ + cyg_tick_count_t now = cyg_current_time(); + + while( cyg_current_time() == now ) + continue; +} + +static void get_timestamp( timestamp *ts ) +{ + ts->ticks = cyg_current_time(); + HAL_CLOCK_READ( (cyg_uint32 *)&ts->halticks ); +} + +static cyg_int64 ticks_to_us( cyg_int64 ticks ) +{ + cyg_int64 us; + + if( us_per_haltick != 0 ) + us = ticks * us_per_haltick; + else + us = ticks / halticks_per_us; + + return us; +} + +static void calculate_interval( timing *t ) +{ + t->interval = t->end.halticks - t->start.halticks; + + t->interval += (t->end.ticks - t->start.ticks) * rtc_period; + + t->interval -= ticks_overhead; + + t->us_interval = ticks_to_us( t->interval ); +} + +static void init_timing( void ) +{ + timing t; + + ticks_per_second = (1000000000ULL*rtc_resolution[1])/rtc_resolution[0]; + us_per_haltick = 1000000/(rtc_period * rtc_resolution[1]); + halticks_per_us = (rtc_period * rtc_resolution[1])/1000000; + + wait_for_tick(); + + get_timestamp( &t.start ); + get_timestamp( &t.end ); + + calculate_interval( &t ); + + ticks_overhead = t.interval; + + diag_printf("Timing overhead %lld ticks\n", ticks_overhead ); + +} + +//========================================================================== + +#ifndef CYGPKG_LIBC_STRING + +char *strcat( char *s1, const char *s2 ) +{ + char *s = s1; + while( *s1 ) s1++; + while( (*s1++ = *s2++) != 0); + return s; +} + +#endif + +__externC int +rename( const char * /* oldpath */, const char * /* newpath */ ) __THROW; + +//========================================================================== + +static void listdir( char *name, int statp, int numexpected, int *numgot ) +{ + int err; + DIR *dirp; + int num=0; + + diag_printf("<INFO>: reading directory %s\n",name); + +// diag_printf("<INFO>: opendir(%s)\n",name); + dirp = opendir( name ); + if( dirp == NULL ) SHOW_RESULT( opendir, -1 ); + + for(;;) + { + struct dirent *entry = readdir( dirp ); + + if( entry == NULL ) + break; + num++; + diag_printf("<INFO>: entry %14s",entry->d_name); + if( statp ) + { + char fullname[PATH_MAX]; + struct stat sbuf; + + if( name[0] ) + { + strcpy(fullname, name ); + if( !(name[0] == '/' && name[1] == 0 ) ) + strcat(fullname, "/" ); + } + else fullname[0] = 0; + + strcat(fullname, entry->d_name ); + + err = stat( fullname, &sbuf ); + if( err < 0 ) + { + if( errno == ENOSYS ) + diag_printf(" <no status available>"); + else SHOW_RESULT( stat, err ); + } + else + { + diag_printf(" [mode %08x ino %08x nlink %d size %ld]", + sbuf.st_mode,sbuf.st_ino,sbuf.st_nlink,sbuf.st_size); + } + } + + diag_printf("\n"); + } + +// diag_printf("<INFO>: closedir(%s)\n",name); + err = closedir( dirp ); + if( err < 0 ) SHOW_RESULT( stat, err ); + if (numexpected >= 0 && num != numexpected) + CYG_TEST_FAIL("Wrong number of dir entries\n"); + if ( numgot != NULL ) + *numgot = num; +} + +//========================================================================== + +static void createfile( char *name, size_t asize, size_t block_size ) +{ + size_t size = asize; + cyg_uint8 *buf; + cyg_uint32 *b; + int fd; + ssize_t wrote; + int i; + int err; + timing opent, writet; + + diag_printf("\n--------------------------------------------------------------------\n"); + diag_printf("<INFO>: create file %s size %ld block_size %ld\n",name, (long)size, (long)block_size); + + buf = malloc( block_size ); + if( buf == NULL ) + { + SHOW_RESULT( malloc, -1 ); + return; + } + b = (cyg_uint32 *)buf; + + err = access( name, F_OK ); + if( err < 0 && errno != EACCES ) SHOW_RESULT( access, err ); + + i = 0; + while( i < block_size/sizeof(cyg_uint32) ) + { + b[i] = i; + i++; + b[i++] = 0; + b[i++] = timehash; + b[i++] = 0x12345678; + } + + + get_timestamp( &opent.start ); + fd = open( name, O_WRONLY|O_CREAT ); + get_timestamp( &opent.end ); + if( fd < 0 ) SHOW_RESULT( open, fd ); + + get_timestamp( &writet.start ); + while( size > 0 ) + { + ssize_t len = size; + if ( len > block_size ) len = block_size; + + b[1] = asize-size; + b[block_size/sizeof(cyg_uint32)-3] = asize-size; + wrote = write( fd, buf, len ); + if( wrote != len ) SHOW_RESULT( write, wrote ); + + size -= wrote; + } + get_timestamp( &writet.end ); + + free( buf ); + + err = close( fd ); + if( err < 0 ) SHOW_RESULT( close, err ); + + calculate_interval( &opent ); + calculate_interval( &writet ); + + diag_printf("CreateFile Results: %s size %ld\n", name, (long)asize); + diag_printf(" Open %8d.%03d ms\n", (int)(opent.us_interval/1000), (int)(opent.us_interval%1000) ); + diag_printf(" Write %8d.%03d ms\n", (int)(writet.us_interval/1000), (int)(writet.us_interval%1000) ); + diag_printf(" Data Rate %10lld KiB/s\n", (1000000LL*asize)/1024/writet.us_interval); +} + +//========================================================================== + +static void checkfile( char *name, size_t block_size ) +{ + cyg_uint8 *buf; + cyg_uint32 *b; + int fd; + ssize_t done; + int err; + off_t pos = 0; + timing opent, readt; + + diag_printf("\n--------------------------------------------------------------------\n"); + diag_printf("<INFO>: check file %s\n",name); + + buf = malloc( block_size ); + if( buf == NULL ) + { + SHOW_RESULT( malloc, -1 ); + return; + } + b = (cyg_uint32 *)buf; + + err = access( name, F_OK ); + if( err != 0 ) SHOW_RESULT( access, err ); + + get_timestamp( &opent.start ); + fd = open( name, O_RDONLY ); + get_timestamp( &opent.end ); + if( fd < 0 ) SHOW_RESULT( open, fd ); + + get_timestamp( &readt.start ); + for(;;) + { + done = read( fd, buf, block_size ); + if( done < 0 ) SHOW_RESULT( read, done ); + + if( done == 0 ) break; + + // Check that this is the block we wrote + if( b[0] != 0 ) + diag_printf("b[%d] != %08x\n", 0, 0 ); + + if( b[1] != pos ) + diag_printf("b[%d] != %08x\n", 1, (unsigned)pos ); + + if( b[2] != timehash ) + diag_printf("b[%d] != %08x\n", 2, timehash ); + + if( b[3] != 0x12345678 ) + diag_printf("b[%d] != %08x\n", 3, 0x12345678 ); + + if( b[(block_size/sizeof(cyg_uint32))-4] != (block_size/sizeof(cyg_uint32)-4) ) + diag_printf("b[%lu](%08x) != %08x\n", (long)block_size/sizeof(cyg_uint32)-4, + b[(block_size/sizeof(cyg_uint32))-4], + (unsigned)(block_size/sizeof(cyg_uint32)-4) ); + + if( b[block_size/sizeof(cyg_uint32)-3] != pos ) + diag_printf("b[%lu] != %08x\n", (long)block_size/sizeof(cyg_uint32)-3, (unsigned)pos ); + + if( b[block_size/sizeof(cyg_uint32)-2] != timehash ) + diag_printf("b[%lu] != %08x\n", (long)block_size/sizeof(cyg_uint32)-2, timehash ); + + if( b[block_size/sizeof(cyg_uint32)-1] != 0x12345678 ) + diag_printf("b[%lu] != %08x\n", (long)block_size/sizeof(cyg_uint32)-1, 0x12345678 ); + + pos += done; + } + get_timestamp( &readt.end ); + + free( buf ); + + err = close( fd ); + if( err < 0 ) SHOW_RESULT( close, err ); + + calculate_interval( &opent ); + calculate_interval( &readt ); + + diag_printf("CheckFile Results: %s size %ld\n", name, pos); + diag_printf(" Open %8d.%03d ms\n", (int)(opent.us_interval/1000), (int)(opent.us_interval%1000) ); + diag_printf(" Read %8d.%03d ms\n", (int)(readt.us_interval/1000), (int)(readt.us_interval%1000) ); + diag_printf(" Data Rate %10lld KiB/s\n", (1000000LL*pos)/1024/readt.us_interval); +} + +//========================================================================== + +#define TIME_DATA_MAX 20 + +static void checkfile1( char *name, size_t block_size ) +{ + cyg_uint8 *buf; + cyg_uint32 *b; + int fd; + ssize_t done; + int err; + off_t pos = 0; + timing totalt; + + struct + { + int valid; + timing mountt; + timing opent; + timing seekt; + timing readt; + timing closet; + timing umountt; + } time_data[TIME_DATA_MAX]; + int td; + + for( td = 0; td < TIME_DATA_MAX; td++ ) + time_data[td].valid = 0; + td = 0; + + diag_printf("\n--------------------------------------------------------------------\n"); + diag_printf("<INFO>: check file1 %s\n",name); + + buf = malloc( block_size ); + if( buf == NULL ) + { + SHOW_RESULT( malloc, -1 ); + return; + } + b = (cyg_uint32 *)buf; + + get_timestamp( &totalt.start ); + for(;;) + { + get_timestamp( &time_data[td].mountt.start ); + err = mount( TEST_DEVICE, TEST_MOUNTPOINT, TEST_FSTYPE ); + get_timestamp( &time_data[td].mountt.end ); + if( err < 0 ) SHOW_RESULT( mount, err ); + + get_timestamp( &time_data[td].opent.start ); + fd = open( name, O_RDONLY ); + get_timestamp( &time_data[td].opent.end ); + if( fd < 0 ) SHOW_RESULT( open, fd ); + + get_timestamp( &time_data[td].seekt.start ); + err = lseek( fd, pos, SEEK_SET ); + get_timestamp( &time_data[td].seekt.end ); + if( err < 0 ) SHOW_RESULT( lseek, err ); + + get_timestamp( &time_data[td].readt.start ); + done = read( fd, buf, block_size ); + get_timestamp( &time_data[td].readt.end ); + if( done < 0 ) SHOW_RESULT( read, done ); + + get_timestamp( &time_data[td].closet.start ); + err = close( fd ); + get_timestamp( &time_data[td].closet.end ); + if( err < 0 ) SHOW_RESULT( close, err ); + + get_timestamp( &time_data[td].umountt.start ); + err = umount( TEST_MOUNTPOINT ); + get_timestamp( &time_data[td].umountt.end ); + if( err < 0 ) SHOW_RESULT( umount, err ); + + if( done == 0 ) break; + + // Check that this is the block we wrote + if( b[0] != 0 ) + diag_printf("b[%d] != %08x\n", 0, 0 ); + + if( b[1] != pos ) + diag_printf("b[%d] != %08x\n", 1, (unsigned)pos ); + +// if( b[2] != timehash ) +// diag_printf("b[%d] != %08x\n", 2, timehash ); + + if( b[3] != 0x12345678 ) + diag_printf("b[%d] != %08x\n", 3, 0x12345678 ); + + if( b[(block_size/sizeof(cyg_uint32))-4] != (block_size/sizeof(cyg_uint32)-4) ) + diag_printf("b[%lu](%08x) != %08x\n", (long)block_size/sizeof(cyg_uint32)-4, + b[(block_size/sizeof(cyg_uint32))-4], + (unsigned)(block_size/sizeof(cyg_uint32)-4) ); + + if( b[block_size/sizeof(cyg_uint32)-3] != pos ) + diag_printf("b[%lu] != %08x\n", (long)block_size/sizeof(cyg_uint32)-3, (unsigned)pos ); + +// if( b[block_size/sizeof(cyg_uint32)-2] != timehash ) +// diag_printf("b[%d] != %08x\n", block_size/sizeof(cyg_uint32)-2, timehash ); + + if( b[block_size/sizeof(cyg_uint32)-1] != 0x12345678 ) + diag_printf("b[%lu] != %08x\n", (long)block_size/sizeof(cyg_uint32)-1, 0x12345678 ); + + pos += done; + + time_data[td].valid = 1; + if( td < (TIME_DATA_MAX-1) ) + td++; + } + get_timestamp( &totalt.end ); + + free( buf ); + + diag_printf("Block Mount Open Seek Read Close Umount\n"); + + for( td = 0; td < TIME_DATA_MAX; td++ ) + { + if( !time_data[td].valid ) + continue; + + calculate_interval( &time_data[td].mountt ); + calculate_interval( &time_data[td].opent ); + calculate_interval( &time_data[td].seekt ); + calculate_interval( &time_data[td].readt ); + calculate_interval( &time_data[td].closet ); + calculate_interval( &time_data[td].umountt ); + + diag_printf("%2d:", td); + diag_printf(" %8d.%03d", (int)(time_data[td].mountt.us_interval/1000), (int)(time_data[td].mountt.us_interval%1000) ); + diag_printf(" %8d.%03d", (int)(time_data[td].opent.us_interval/1000), (int)(time_data[td].opent.us_interval%1000) ); + diag_printf(" %8d.%03d", (int)(time_data[td].seekt.us_interval/1000), (int)(time_data[td].seekt.us_interval%1000) ); + diag_printf(" %8d.%03d", (int)(time_data[td].readt.us_interval/1000), (int)(time_data[td].readt.us_interval%1000) ); + diag_printf(" %8d.%03d", (int)(time_data[td].closet.us_interval/1000), (int)(time_data[td].closet.us_interval%1000) ); + diag_printf(" %8d.%03d", (int)(time_data[td].umountt.us_interval/1000), (int)(time_data[td].umountt.us_interval%1000) ); + diag_printf("\n"); + } + + calculate_interval( &totalt ); + diag_printf("CheckFile1 Results: %s size %ld\n", name, pos); + diag_printf(" Total %8d.%03d ms\n", (int)(totalt.us_interval/1000), (int)(totalt.us_interval%1000) ); + diag_printf(" Data Rate %10lld KiB/s\n", (1000000LL*pos)/1024/totalt.us_interval); + +} + +//========================================================================== + +void checkcwd( const char *cwd ) +{ + static char cwdbuf[PATH_MAX]; + char *ret; + + ret = getcwd( cwdbuf, sizeof(cwdbuf)); + if( ret == NULL ) SHOW_RESULT( getcwd, ret ); + + if( strcmp( cwdbuf, cwd ) != 0 ) + { + diag_printf( "cwdbuf %s cwd %s\n",cwdbuf, cwd ); + CYG_TEST_FAIL( "Current directory mismatch"); + } +} + +//========================================================================== + +void fs_callback( cyg_int32 event, CYG_ADDRWORD data ) +{ +#if 1 + diag_printf("Filesystem %sSAFE\n", + event==CYG_FS_CALLBACK_UNSAFE?"UN":""); +#endif +} + + +//========================================================================== +// main + +void yaffs5_main( CYG_ADDRESS id ) +{ + int err; + int existingdirents=-1; + int i; + timing mountt, umountt; + +#if defined(CYGSEM_FILEIO_BLOCK_USAGE) + struct cyg_fs_block_usage usage; +#endif +// struct cyg_fs_callback_info callback; + + CYG_TEST_INIT(); + + init_timing(); + + for( i = 0 ; date_string[i] != 0 ; i++ ) + timehash = (timehash<<1) ^ date_string[i]; + for( i = 0 ; time_string[i] != 0 ; i++ ) + timehash = (timehash<<1) ^ time_string[i]; + + // -------------------------------------------------------------- + +#if 1 +#define DO_UMOUNT + get_timestamp( &mountt.start ); + err = mount( TEST_DEVICE, TEST_MOUNTPOINT, TEST_FSTYPE ); +// err = mount( TEST_DEVICE, TEST_MOUNTPOINT, "yaffs:sync=write" ); +// err = mount( TEST_DEVICE, TEST_MOUNTPOINT, "yaffs:sync=close" ); +// err = mount( TEST_DEVICE, TEST_MOUNTPOINT, "yaffs:sync=data" ); + get_timestamp( &mountt.end ); + if( err < 0 ) { + SHOW_RESULT( mount, err ); + CYG_TEST_FAIL_FINISH("yaffs5"); + } + +#if 0 + callback.callback = fs_callback; + callback.data = 0; + err = cyg_fs_setinfo(TEST_MOUNTPOINT, FS_INFO_CALLBACK, + &callback, sizeof(callback)); + if( err < 0 ) SHOW_RESULT( cyg_fs_setinfo, err ); +#endif + + calculate_interval( &mountt ); + diag_printf(" Mount %8d.%03d ms\n", (int)(mountt.us_interval/1000), (int)(mountt.us_interval%1000) ); + + err = access( TEST_MOUNTPOINT TEST_DIRECTORY, F_OK ); + if( err < 0 && errno != EACCES ) SHOW_RESULT( access, err ); + + if( err < 0 && errno == EACCES ) + { + diag_printf("<INFO>: create %s\n", + TEST_MOUNTPOINT TEST_DIRECTORY); + err = mkdir( TEST_MOUNTPOINT TEST_DIRECTORY, 0 ); + if( err < 0 ) SHOW_RESULT( mkdir, err ); + } + + err = chdir( TEST_MOUNTPOINT TEST_DIRECTORY ); + if( err < 0 ) SHOW_RESULT( chdir, err ); + + checkcwd( TEST_MOUNTPOINT TEST_DIRECTORY ); + + listdir( TEST_MOUNTPOINT TEST_DIRECTORY, true, -1, &existingdirents ); + + // -------------------------------------------------------------- +#if defined(CYGSEM_FILEIO_BLOCK_USAGE) + err = cyg_fs_getinfo(TEST_MOUNTPOINT, FS_INFO_BLOCK_USAGE, + &usage, sizeof(usage)); + if( err < 0 ) SHOW_RESULT( cyg_fs_getinfo, err ); + diag_printf("<INFO>: total size: %6lld blocks, %10lld bytes\n", + usage.total_blocks, usage.total_blocks * usage.block_size); + diag_printf("<INFO>: free size: %6lld blocks, %10lld bytes\n", + usage.free_blocks, usage.free_blocks * usage.block_size); + diag_printf("<INFO>: block size: %6u bytes\n", usage.block_size); +#endif + // -------------------------------------------------------------- + +#endif + +#if 1 + createfile( "yaffs5.0", 1024*1024, 16*1024 ); + checkfile( "yaffs5.0",16*1024 ); + err = unlink( "yaffs5.0" ); + sync(); +#endif + +#if 1 + createfile( "yaffs5.0", 200*1024, 1024 ); + checkfile( "yaffs5.0", 1024 ); + err = unlink( "yaffs5.0" ); +#endif + +#if 1 + createfile( "yaffs5.1", 1024*1024, 1024 ); + createfile( "yaffs5.2", 1024*1024, 4*1024 ); + sync(); + createfile( "yaffs5.3", 8*1024*1024, 32*1024 ); + + checkfile( "yaffs5.1", 1024 ); + checkfile( "yaffs5.2", 4*1024 ); + checkfile( "yaffs5.3", 32*1024 ); + + diag_printf("\n--------------------------------------------------------------------\n"); + + listdir( "." , true, existingdirents+3, NULL ); + + // -------------------------------------------------------------- + + diag_printf("<INFO>: unlink yaffs5.1\n"); + err = unlink( "yaffs5.1" ); + if( err < 0 ) SHOW_RESULT( unlink, err ); + + diag_printf("<INFO>: unlink yaffs5.2\n"); + err = unlink( "yaffs5.2" ); + if( err < 0 ) SHOW_RESULT( unlink, err ); + + diag_printf("<INFO>: unlink yaffs5.3\n"); + err = unlink( "yaffs5.3" ); + if( err < 0 ) SHOW_RESULT( unlink, err ); +#endif + + // -------------------------------------------------------------- + +#if 1 && defined(DO_UMOUNT) + + diag_printf("<INFO>: unlink yaffs5.4\n"); + err = unlink( "yaffs5.4" ); + + createfile( "yaffs5.4", 5*1024*1024, 32*1024 ); +#endif + + // -------------------------------------------------------------- + +#ifdef DO_UMOUNT + diag_printf("<INFO>: cd /\n"); + err = chdir( "/" ); + if( err == 0 ) + { + checkcwd( "/" ); + + diag_printf("<INFO>: umount %s\n",TEST_MOUNTPOINT); + get_timestamp( &umountt.start ); + err = umount( TEST_MOUNTPOINT ); + get_timestamp( &umountt.end ); + if( err < 0 ) SHOW_RESULT( umount, err ); + + calculate_interval( &umountt ); + diag_printf(" Umount %8d.%03d ms\n", (int)(umountt.us_interval/1000), (int)(umountt.us_interval%1000) ); + + } +#endif + +#if 1 + + diag_printf("<INFO>: syncing\n"); + sync(); + + checkfile1(TEST_MOUNTPOINT TEST_DIRECTORY "/yaffs5.4", 32*1024 ); + + // Remount just to remove yaffs5.4 + err = mount( TEST_DEVICE, TEST_MOUNTPOINT, TEST_FSTYPE ); + if( err < 0 ) { + SHOW_RESULT( mount, err ); + CYG_TEST_FAIL_FINISH("yaffs5"); + } + err = unlink( TEST_MOUNTPOINT TEST_DIRECTORY "/yaffs5.4" ); + if( err < 0 ) SHOW_RESULT( unlink, err ); + err = umount( TEST_MOUNTPOINT ); + if( err < 0 ) SHOW_RESULT( umount, err ); + +#endif + + diag_printf("<INFO>: syncing\n"); + sync(); + + CYG_TEST_PASS_FINISH("yaffs5"); +} + +// ------------------------------------------------------------------------- + +#include <cyg/kernel/kapi.h> + +static cyg_handle_t thread_handle; +static cyg_thread thread; +static char stack[CYGNUM_HAL_STACK_SIZE_TYPICAL+8*1024]; +//static char stack[64*1024]; + +externC void +cyg_start( void ) +{ + cyg_thread_create(3, // Priority - just a number + yaffs5_main, // entry + 0, // index + 0, // no name + &stack[0], // Stack + sizeof(stack), // Size + &thread_handle, // Handle + &thread // Thread data structure + ); + cyg_thread_resume(thread_handle); + + cyg_scheduler_start(); +} + +// ------------------------------------------------------------------------- +// EOF yaffs5.c
new file mode 100644 --- /dev/null +++ b/packages/fs/yaffs/current/tests/yaffs6.c @@ -0,0 +1,968 @@ +//========================================================================== +// +// yaffs6.c +// +// Test FAT UTF-8 support +// +//========================================================================== +// ####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 1998, 1999, 2000, 2001, 2002, 2004, 2005, 2006, 2007 Free Software Foundation, Inc. +// Copyright (C) 2004, 2005, 2006, 2007 eCosCentric Limited +// +// eCos is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 2 or (at your option) any later +// version. +// +// eCos is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License +// along with eCos; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +// +// As a special exception, if other files instantiate templates or use +// macros or inline functions from this file, or you compile this file +// and link it with other works to produce a work based on this file, +// this file does not by itself cause the resulting work to be covered by +// the GNU General Public License. However the source code for this file +// must still be made available in accordance with section (3) of the GNU +// General Public License v2. +// +// This exception does not invalidate any other reasons why a work based +// on this file might be covered by the GNU General Public License. +// ------------------------------------------- +// ####ECOSGPLCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): nickg +// Contributors: nickg +// Date: 2007-06-20 +// Purpose: Test fileio system +// Description: This test uses the testfs to check out the initialization +// and basic operation of the fileio system. +// This is essentially a copy of yaffs4 with UTF8 encoded +// file names. +// +//####DESCRIPTIONEND#### +// +//========================================================================== + +#include <pkgconf/hal.h> +#include <pkgconf/kernel.h> +#include <pkgconf/io_fileio.h> + +#include CYGDAT_DEVS_DISK_CFG // testing config defines + +#include <cyg/kernel/ktypes.h> // base kernel types +#include <cyg/infra/cyg_trac.h> // tracing macros +#include <cyg/infra/cyg_ass.h> // assertion macros + +#include <unistd.h> +#include <fcntl.h> +#include <sys/stat.h> +#include <errno.h> +#include <string.h> +#include <dirent.h> + +#include <cyg/fileio/fileio.h> + +#include <cyg/infra/testcase.h> +#include <cyg/infra/diag.h> // HAL polled output + +//========================================================================== +// Config options + +#define TEST_DEVICE CYGDAT_DEVS_DISK_TEST_DEVICE + +#define TEST_MOUNTPOINT CYGDAT_DEVS_DISK_TEST_MOUNTPOINT + +#define TEST_DIRECTORY CYGDAT_DEVS_DISK_TEST_DIRECTORY + +#define TEST_FSTYPE "yaffs" + +#ifdef CYGDAT_DEVS_DISK_TEST_MOUNTPOINT2 + +#define TEST_DEVICE2 CYGDAT_DEVS_DISK_TEST_DEVICE2 + +#define TEST_MOUNTPOINT2 CYGDAT_DEVS_DISK_TEST_MOUNTPOINT2 + +#define TEST_DIRECTORY2 CYGDAT_DEVS_DISK_TEST_DIRECTORY2 + +#define TEST_FSTYPE2 "yaffs" + +#endif + +//========================================================================== + +#define SHOW_RESULT( _fn, _res ) \ +{ \ + diag_printf("<FAIL>: " #_fn "() returned %ld %s\n", (long)_res, _res<0?strerror(errno):""); \ +} + +//========================================================================== + +#define IOSIZE 100 + +#define CLEANUP + +//========================================================================== +// The following filenames are in Cyrillic and are UTF-8 encoded. +// +// WARNING: Only edit this file with an editor that is UTF-8 aware (I +// use EMACS on Linux, but Notepad on Windows also works). Saving this +// file from an unaware editor could cause these strings to be +// corrupted and make this test fail. If the strings below do not +// appear as clean Cyrillic characters then exit now without saving +// and look for a better editor. + +#if 1 + +#define FOO "Фоо" +#define FEE "Спутник" +#define BAR "Байконур" +#define BUNDY "СергеЬй ПаЬвлович Королёв" +#define FUM "Юрий Гагаринский" +#define DOO "Константин Эдуардович Циолковский" +//#define FIE "Федеральное космическое агентство России" +#define FIE "Федеральное космическое" +#define FOE "Валентин Петрович Глушко" + +#define TINKY "Восток" +#define LAALAA "Восход" +#define NOONOO "Салют" +#define DIPSY "Космодром" +#define PO "Лайка" + +#define XXXX "Гласность" +#define YYYY "перестройка" +#define ZZZZ "Калашникова" +#define WWWW "матрёшка" + +#else + +#define FOO "foo" +#define FEE "fee" +#define BAR "bar" +#define BUNDY "bundy" +#define FUM "fum" +#define DOO "doo" +#define FIE "fie" +#define FOE "foe" + +#define TINKY "tinky" +#define LAALAA "laalaa" +#define NOONOO "noonoo" +#define DIPSY "dipsy" +#define PO "po" + +#define XXXX "xxxx" +#define YYYY "yyyy" +#define ZZZZ "zzzz" +#define WWWW "wwww" + +#endif + + +//========================================================================== + +#ifndef CYGPKG_LIBC_STRING + +char *strcat( char *s1, const char *s2 ) +{ + char *s = s1; + while( *s1 ) s1++; + while( (*s1++ = *s2++) != 0); + return s; +} + +#endif + +__externC int +rename( const char * /* oldpath */, const char * /* newpath */ ) __THROW; + +//========================================================================== + +static void listdir( char *name, int statp, int numexpected, int *numgot ) +{ + int err; + DIR *dirp; + int num=0; + + diag_printf("<INFO>: reading directory %s\n",name); + +// diag_printf("<INFO>: opendir(%s)\n",name); + dirp = opendir( name ); + if( dirp == NULL ) SHOW_RESULT( opendir, -1 ); + + for(;;) + { + struct dirent *entry = readdir( dirp ); + + if( entry == NULL ) + break; + num++; + + diag_printf("<INFO>: entry "); + + if( statp ) + { + char fullname[PATH_MAX]; + struct stat sbuf; + + if( name[0] ) + { + strcpy(fullname, name ); + if( !(name[0] == '/' && name[1] == 0 ) ) + strcat(fullname, "/" ); + } + else fullname[0] = 0; + + strcat(fullname, entry->d_name ); + + err = stat( fullname, &sbuf ); + if( err < 0 ) + { + if( errno == ENOSYS ) + diag_printf(" <no status available>"); + else SHOW_RESULT( stat, err ); + } + else + { + diag_printf(" [mode %08x ino %08x nlink %d size %6ld]", + sbuf.st_mode,sbuf.st_ino,sbuf.st_nlink,sbuf.st_size); + } + } + + diag_printf(" %s\n",entry->d_name); + } + +// diag_printf("<INFO>: closedir(%s)\n",name); + err = closedir( dirp ); + if( err < 0 ) SHOW_RESULT( stat, err ); + if (numexpected >= 0 && num != numexpected) + CYG_TEST_FAIL("Wrong number of dir entries"); + if ( numgot != NULL ) + *numgot = num; +} + +//========================================================================== + +static void createfile( char *name, size_t size ) +{ + char buf[IOSIZE]; + int fd; + ssize_t wrote; + int i; + int err; + + diag_printf("<INFO>: create file %s size %ld\n",name, (long)size); + + err = access( name, F_OK ); + if( err < 0 && errno != EACCES ) SHOW_RESULT( access, err ); + + for( i = 0; i < IOSIZE; i++ ) buf[i] = i%256; + + fd = open( name, O_WRONLY|O_CREAT ); + if( fd < 0 ) SHOW_RESULT( open, fd ); + + while( size > 0 ) + { + ssize_t len = size; + if ( len > IOSIZE ) len = IOSIZE; + + wrote = write( fd, buf, len ); + if( wrote != len ) SHOW_RESULT( write, wrote ); + + size -= wrote; + } + + err = close( fd ); + if( err < 0 ) SHOW_RESULT( close, err ); +} + +//========================================================================== + +#if 0 +static void maxfile( char *name ) +{ + char buf[IOSIZE]; + int fd; + ssize_t wrote; + int i; + int err; + size_t size = 0; + size_t prevsize = 0; + + diag_printf("<INFO>: create maximal file %s\n",name); + diag_printf("<INFO>: This may take a few minutes\n"); + + err = access( name, F_OK ); + if( err < 0 && errno != EACCES ) SHOW_RESULT( access, err ); + + for( i = 0; i < IOSIZE; i++ ) buf[i] = i%256; + + fd = open( name, O_WRONLY|O_CREAT ); + if( fd < 0 ) SHOW_RESULT( open, fd ); + + do + { + wrote = write( fd, buf, IOSIZE ); + //if( wrote < 0 ) SHOW_RESULT( write, wrote ); + + if( wrote >= 0 ) + size += wrote; + + if( (size-prevsize) > 100000 ) + { + diag_printf("<INFO>: size = %ld \n", size); + prevsize = size; + } + + } while( wrote == IOSIZE ); + + diag_printf("<INFO>: file size == %ld\n",size); + + err = close( fd ); + if( err < 0 ) SHOW_RESULT( close, err ); +} +#endif + +//========================================================================== + +static void checkfile( char *name ) +{ + char buf[IOSIZE]; + int fd; + ssize_t done; + int i; + int err; + off_t pos = 0; + + diag_printf("<INFO>: check file %s\n",name); + + err = access( name, F_OK ); + if( err != 0 ) SHOW_RESULT( access, err ); + + fd = open( name, O_RDONLY ); + if( fd < 0 ) SHOW_RESULT( open, fd ); + + for(;;) + { + done = read( fd, buf, IOSIZE ); + if( done < 0 ) SHOW_RESULT( read, done ); + + if( done == 0 ) break; + + for( i = 0; i < done; i++ ) + if( buf[i] != i%256 ) + { + diag_printf("buf[%ld+%d](%02x) != %02x\n",pos,i,buf[i],i%256); + CYG_TEST_FAIL("Data read not equal to data written\n"); + for(;;); + } + + pos += done; + } + + err = close( fd ); + if( err < 0 ) SHOW_RESULT( close, err ); +} + +//========================================================================== + +static void copyfile( char *name2, char *name1 ) +{ + + int err; + char buf[IOSIZE]; + int fd1, fd2; + ssize_t done, wrote; + + diag_printf("<INFO>: copy file %s -> %s\n",name2,name1); + + err = access( name1, F_OK ); + if( err < 0 && errno != EACCES ) SHOW_RESULT( access, err ); + + err = access( name2, F_OK ); + if( err != 0 ) SHOW_RESULT( access, err ); + + fd1 = open( name1, O_WRONLY|O_CREAT ); + if( fd1 < 0 ) SHOW_RESULT( open, fd1 ); + + fd2 = open( name2, O_RDONLY ); + if( fd2 < 0 ) SHOW_RESULT( open, fd2 ); + + for(;;) + { + done = read( fd2, buf, IOSIZE ); + if( done < 0 ) SHOW_RESULT( read, done ); + + if( done == 0 ) break; + + wrote = write( fd1, buf, done ); + if( wrote != done ) SHOW_RESULT( write, wrote ); + + if( wrote != done ) break; + } + + err = close( fd1 ); + if( err < 0 ) SHOW_RESULT( close, err ); + + err = close( fd2 ); + if( err < 0 ) SHOW_RESULT( close, err ); + +} + +//========================================================================== + +static void comparefiles( char *name2, char *name1 ) +{ + int err; + char buf1[IOSIZE]; + char buf2[IOSIZE]; + int fd1, fd2; + ssize_t done1, done2; + int i; + + diag_printf("<INFO>: compare files %s == %s\n",name2,name1); + + err = access( name1, F_OK ); + if( err != 0 ) SHOW_RESULT( access, err ); + + err = access( name1, F_OK ); + if( err != 0 ) SHOW_RESULT( access, err ); + + fd1 = open( name1, O_RDONLY ); + if( fd1 < 0 ) SHOW_RESULT( open, fd1 ); + + fd2 = open( name2, O_RDONLY ); + if( fd2 < 0 ) SHOW_RESULT( open, fd2 ); + + for(;;) + { + done1 = read( fd1, buf1, IOSIZE ); + if( done1 < 0 ) SHOW_RESULT( read, done1 ); + + done2 = read( fd2, buf2, IOSIZE ); + if( done2 < 0 ) SHOW_RESULT( read, done2 ); + + if( done1 != done2 ) + diag_printf("Files different sizes\n"); + + if( done1 == 0 ) break; + + for( i = 0; i < done1; i++ ) + if( buf1[i] != buf2[i] ) + { + diag_printf("buf1[%d](%02x) != buf1[%d](%02x)\n",i,buf1[i],i,buf2[i]); + CYG_TEST_FAIL("Data in files not equal\n"); + } + } + + err = close( fd1 ); + if( err < 0 ) SHOW_RESULT( close, err ); + + err = close( fd2 ); + if( err < 0 ) SHOW_RESULT( close, err ); + +} + +//========================================================================== + +void checkcwd( const char *cwd ) +{ + static char cwdbuf[PATH_MAX]; + char *ret; + + ret = getcwd( cwdbuf, sizeof(cwdbuf)); + if( ret == NULL ) SHOW_RESULT( getcwd, ret ); + + if( strcmp( cwdbuf, cwd ) != 0 ) + { + diag_printf( "cwdbuf %s cwd %s\n",cwdbuf, cwd ); + CYG_TEST_FAIL( "Current directory mismatch"); + } +} + +//========================================================================== +// main + +void yaffs6_main( CYG_ADDRESS id ) +{ + int err; + int existingdirents=-1; + cyg_bool mp2 = false; + int fd; + + char dirname[256]; + char filename1[256]; + char filename2[256]; + +#define NEW_FILENAME( fn, f ) \ +{ \ + fn[0]=0; \ + strcat(fn, dirname); \ + strcat(fn, "/"); \ + strcat(fn,f); \ +} + +#define NEW_FILENAME1( f ) NEW_FILENAME( filename1, f ) +#define NEW_FILENAME2( f ) NEW_FILENAME( filename2, f ) + + CYG_TEST_INIT(); + +#ifdef CYGDBG_INFRA_DIAG_CHECK_STRINGS + diag_printf("WARNING: CYGDBG_INFRA_DIAG_CHECK_STRINGS is defined, Cyrillic file names will not be printed.\n"); +#else + diag_printf("WARNING: Cyrillic file names printed in UTF-8 may not be readable in some environments.\n"); +#endif + + // -------------------------------------------------------------- + + err = mount( TEST_DEVICE, TEST_MOUNTPOINT, TEST_FSTYPE ); + if( err < 0 ) { + SHOW_RESULT( mount, err ); + CYG_TEST_FAIL_FINISH("yaffs6"); + } + + err = access( TEST_MOUNTPOINT TEST_DIRECTORY, F_OK ); + if( err < 0 && errno != EACCES ) SHOW_RESULT( access, err ); + + if( err < 0 && errno == EACCES ) + { + diag_printf("<INFO>: create %s\n", + TEST_MOUNTPOINT TEST_DIRECTORY); + err = mkdir( TEST_MOUNTPOINT TEST_DIRECTORY, 0 ); + if( err < 0 ) SHOW_RESULT( mkdir, err ); + } + + err = chdir( TEST_MOUNTPOINT TEST_DIRECTORY ); + if( err < 0 ) SHOW_RESULT( chdir, err ); + + checkcwd( TEST_MOUNTPOINT TEST_DIRECTORY ); + + listdir( TEST_MOUNTPOINT TEST_DIRECTORY, true, -1, &existingdirents ); + + // -------------------------------------------------------------- + + dirname[0] = 0; + strcat(dirname, TEST_MOUNTPOINT ); + strcat(dirname, TEST_DIRECTORY ); + + // -------------------------------------------------------------- + + createfile( FOO, 20257 ); + checkfile( FOO ); + copyfile( FOO, FEE); + checkfile( FEE ); + comparefiles( FOO, FEE ); + + diag_printf("<INFO>: mkdir " BAR "\n"); + err = mkdir( BAR, 0 ); + if( err < 0 ) SHOW_RESULT( mkdir, err ); + + listdir( dirname , true, existingdirents+3, NULL ); + + copyfile( FEE, BAR "/" FUM ); + checkfile( BAR "/" FUM ); + comparefiles( FEE, BAR "/" FUM ); + + diag_printf("<INFO>: cd " BAR "\n"); + err = chdir( BAR ); + if( err < 0 ) SHOW_RESULT( chdir, err ); + + NEW_FILENAME1( BAR ); + checkcwd( filename1 ); + + diag_printf("<INFO>: rename ../" FOO " " BUNDY "\n"); + err = rename( "../" FOO, BUNDY ); + if( err < 0 ) SHOW_RESULT( rename, err ); + + listdir( dirname, true, existingdirents+2, NULL ); + listdir( "." , true, 4, NULL ); + + checkfile( "../" BAR "/" BUNDY ); + comparefiles("../" FEE, BUNDY ); + +#if 1 + + // -------------------------------------------------------------- + // Check for some common error cases + + // First make some directories + diag_printf("<INFO>: mkdir " DOO "\n"); + err = mkdir( DOO, 0 ); + if( err < 0 ) SHOW_RESULT( mkdir, err ); + + diag_printf("<INFO>: mkdir " FIE" \n"); + err = mkdir( FIE, 0 ); + if( err < 0 ) SHOW_RESULT( mkdir, err ); + + diag_printf("<INFO>: mkdir " FIE "/" FOE "\n"); + err = mkdir( FIE "/" FOE, 0 ); + if( err < 0 ) SHOW_RESULT( mkdir, err ); + + + diag_printf("<INFO>: rename " FUM " " DOO " -- should fail\n"); + err = rename( FUM, DOO ); + if( err < 0 && errno != EISDIR ) SHOW_RESULT( rename, err ); + + diag_printf("<INFO>: rename " DOO " " FUM " -- should fail\n"); + err = rename( DOO, FUM ); + if( err < 0 && errno != ENOTDIR ) SHOW_RESULT( rename, err ); + + diag_printf("<INFO>: rename " DOO " " FIE " -- should fail\n"); + err = rename( DOO, FIE ); + if( err < 0 && errno != EIO ) SHOW_RESULT( rename, err ); + + NEW_FILENAME1( XXXX "/" YYYY ) + diag_printf("<INFO>: rename " FUM " %s -- should fail\n",filename1); + err = rename( FUM, filename1 ); + if( err < 0 && errno != ENOENT ) SHOW_RESULT( rename, err ); + + diag_printf("<INFO>: rename " FUM " " FUM " -- should fail\n"); + err = rename( FUM, FUM ); + if( err < 0 ) SHOW_RESULT( rename, err ); + + diag_printf("<INFO>: unlink " FEE " -- should fail\n"); + err = unlink( FEE ); + if( err < 0 && errno != ENOENT ) SHOW_RESULT( unlink, err ); + + NEW_FILENAME1( BAR ); + diag_printf("<INFO>: rmdir %s -- should fail\n",filename1); + err = rmdir( filename1 ); + if( err < 0 && errno != ENOTEMPTY ) SHOW_RESULT( rmdir, err ); + + diag_printf("<INFO>: unlink %s -- should fail\n",filename1); + err = unlink( filename1 ); + if( err < 0 && errno != EISDIR ) SHOW_RESULT( unlink, err ); + + NEW_FILENAME1( BAR "/" FUM ); + diag_printf("<INFO>: rmdir %s -- should fail\n",filename1); + err = rmdir( filename1 ); + if( err < 0 && errno != ENOTDIR ) SHOW_RESULT( rmdir, err ); + + diag_printf("<INFO>: mkdir %s -- should fail\n",filename1); + err = mkdir( filename1, 0 ); + if( err < 0 && errno != EEXIST ) SHOW_RESULT( mkdir, err ); + + diag_printf("<INFO>: open " BUNDY " exclusive -- should fail\n"); + fd = open( BUNDY, O_WRONLY|O_CREAT|O_EXCL ); + if( fd < 0 && errno != EEXIST ) SHOW_RESULT( open, fd ); + + diag_printf("<INFO>: open %s -- should fail\n",dirname); + fd = open( dirname, O_WRONLY ); + if( fd < 0 && errno != EISDIR ) SHOW_RESULT( open, fd ); + + + listdir( dirname, true, existingdirents+2, NULL ); + listdir( "." , true, 6, NULL ); + + // -------------------------------------------------------------- + +#ifdef CLEANUP + + diag_printf("<INFO>: rename " FIE " " DOO "\n"); + err = rename( FIE, DOO ); + if( err < 0 ) SHOW_RESULT( unlink, err ); + + diag_printf("<INFO>: rmdir " DOO "/" FOE "\n"); + err = rmdir(DOO "/" FOE); + if( err < 0 ) SHOW_RESULT( unlink, err ); + + diag_printf("<INFO>: rmdir " DOO "\n"); + err = rmdir(DOO); + if( err < 0 ) SHOW_RESULT( unlink, err ); + + diag_printf("<INFO>: unlink ../" FEE "\n"); + err = unlink( "../" FEE ); + if( err < 0 ) SHOW_RESULT( unlink, err ); + + diag_printf("<INFO>: unlink " FUM "\n"); + err = unlink( FUM ); + if( err < 0 ) SHOW_RESULT( unlink, err ); + + diag_printf("<INFO>: unlink ../" BAR "/" BUNDY "\n"); + err = unlink( "../" BAR "/" BUNDY ); + if( err < 0 ) SHOW_RESULT( unlink, err ); +#endif + + diag_printf("<INFO>: cd ..\n"); + err = chdir( ".." ); + if( err < 0 ) SHOW_RESULT( chdir, err ); + + checkcwd( dirname ); + +#ifdef CLEANUP + diag_printf("<INFO>: rmdir " BAR "\n"); + err = rmdir( BAR ); + if( err < 0 ) SHOW_RESULT( rmdir, err ); + + listdir( dirname, false, existingdirents, NULL ); +#endif + + // -------------------------------------------------------------- + +#ifdef TEST_MOUNTPOINT2 + diag_printf("<INFO>: mount %s\n", TEST_MOUNTPOINT2); + err = mount( TEST_DEVICE2, TEST_MOUNTPOINT2, TEST_FSTYPE2 ); + + if( err == 0 ) + { + mp2 = true; + diag_printf("<INFO>: mount %s succeeded\n", TEST_MOUNTPOINT2); + err = access( TEST_MOUNTPOINT2 TEST_DIRECTORY2, F_OK ); + if( err < 0 && errno != EACCES ) SHOW_RESULT( access, err ); + + if( err < 0 && errno == EACCES ) + { + diag_printf("<INFO>: create %s\n", + TEST_MOUNTPOINT2 TEST_DIRECTORY2); + err = mkdir( TEST_MOUNTPOINT2 TEST_DIRECTORY2, 0 ); + if( err < 0 ) SHOW_RESULT( mkdir, err ); + } + + err = chdir( TEST_MOUNTPOINT2 TEST_DIRECTORY2 ); + if( err < 0 ) SHOW_RESULT( chdir, err ); + + checkcwd( TEST_MOUNTPOINT2 TEST_DIRECTORY2 ); + + dirname[0] = 0; + strcat(dirname, TEST_MOUNTPOINT2 ); + strcat(dirname, TEST_DIRECTORY2 ); + + } + else + { + mp2 = false; + diag_printf("<INFO>: mount %s failed, ", TEST_MOUNTPOINT2); + diag_printf("using %s instead\n", dirname ); + } + +#endif + + listdir( dirname , true, -1, &existingdirents); + + NEW_FILENAME1( TINKY ); + NEW_FILENAME2( LAALAA ); + + createfile( filename1, 4567 ); + copyfile( filename1, filename2 ); + checkfile( filename1); + checkfile( filename2); + comparefiles( filename1, filename2 ); + + diag_printf("<INFO>: cd %s\n",dirname); + err = chdir( dirname ); + if( err < 0 ) SHOW_RESULT( chdir, err ); + + checkcwd( dirname ); + + diag_printf("<INFO>: mkdir " NOONOO "\n"); + err = mkdir( NOONOO, 0 ); + if( err < 0 ) SHOW_RESULT( mkdir, err ); + + listdir( dirname , true, existingdirents+3, NULL); + + diag_printf("<INFO>: cd " NOONOO "\n"); + err = chdir( NOONOO ); + if( err < 0 ) SHOW_RESULT( chdir, err ); + + NEW_FILENAME1( NOONOO ); + checkcwd( filename1 ); + + createfile( TINKY, 6789 ); + checkfile( TINKY ); + + createfile( DIPSY, 34567 ); + checkfile( DIPSY ); + copyfile( DIPSY, PO ); + checkfile( PO ); + comparefiles( DIPSY, PO ); + + listdir( ".", true, 5, NULL ); + listdir( "..", true, existingdirents+3, NULL ); + + // -------------------------------------------------------------- + +#ifdef CLEANUP + diag_printf("<INFO>: unlink " TINKY "\n"); + err = unlink( TINKY ); + if( err < 0 ) SHOW_RESULT( unlink, err ); + + diag_printf("<INFO>: unlink " DIPSY "\n"); + err = unlink( DIPSY ); + if( err < 0 ) SHOW_RESULT( unlink, err ); + + diag_printf("<INFO>: unlink " PO "\n"); + err = unlink( PO ); + if( err < 0 ) SHOW_RESULT( unlink, err ); +#endif + + diag_printf("<INFO>: cd ..\n"); + err = chdir( ".." ); + if( err < 0 ) SHOW_RESULT( chdir, err ); + checkcwd( dirname ); + +#ifdef CLEANUP + diag_printf("<INFO>: rmdir " NOONOO "\n"); + err = rmdir( NOONOO ); + if( err < 0 ) SHOW_RESULT( rmdir, err ); +#endif + + // -------------------------------------------------------------- + + err = mkdir( XXXX, 0 ); + if( err < 0 ) SHOW_RESULT( mkdir, err ); + + err = mkdir( XXXX "/" YYYY, 0 ); + if( err < 0 ) SHOW_RESULT( mkdir, err ); + + err = mkdir( XXXX "/" YYYY "/" ZZZZ, 0 ); + if( err < 0 ) SHOW_RESULT( mkdir, err ); + + err = mkdir( XXXX "/" YYYY "/" ZZZZ "/" WWWW, 0 ); + if( err < 0 ) SHOW_RESULT( mkdir, err ); + + NEW_FILENAME1( XXXX "/" YYYY "/" ZZZZ "/" WWWW ); + diag_printf("<INFO>: cd %s\n",filename1); + err = chdir( filename1 ); + if( err < 0 ) SHOW_RESULT( chdir, err ); + checkcwd( filename1 ); + + NEW_FILENAME1( XXXX "/" YYYY "/" ZZZZ ); + diag_printf("<INFO>: cd ..\n"); + err = chdir( ".." ); + if( err < 0 ) SHOW_RESULT( chdir, err ); + checkcwd( filename1 ); + + NEW_FILENAME1( XXXX "/" YYYY "/" ZZZZ ); + diag_printf("<INFO>: cd .\n"); + err = chdir( "." ); + if( err < 0 ) SHOW_RESULT( chdir, err ); + checkcwd( filename1 ); + + NEW_FILENAME1( XXXX "/" YYYY ); + diag_printf("<INFO>: cd ../../" YYYY "\n"); + err = chdir( "../../" YYYY ); + if( err < 0 ) SHOW_RESULT( chdir, err ); + checkcwd( filename1 ); + + diag_printf("<INFO>: cd ../..\n"); + err = chdir( "../.." ); + if( err < 0 ) SHOW_RESULT( chdir, err ); + checkcwd( dirname ); + + diag_printf("<INFO>: rmdir " XXXX "/" YYYY "/" ZZZZ "/" WWWW "\n"); + err = rmdir( XXXX "/" YYYY "/" ZZZZ "/" WWWW ); + if( err < 0 ) SHOW_RESULT( rmdir, err ); + + diag_printf("<INFO>: rmdir "XXXX "/" YYYY "/" ZZZZ "\n"); + err = rmdir( XXXX "/" YYYY "/" ZZZZ ); + if( err < 0 ) SHOW_RESULT( rmdir, err ); + + diag_printf("<INFO>: rmdir " XXXX "/" YYYY "\n"); + err = rmdir( XXXX "/" YYYY ); + if( err < 0 ) SHOW_RESULT( rmdir, err ); + + diag_printf("<INFO>: rmdir "XXXX "\n"); + err = rmdir( XXXX ); + if( err < 0 ) SHOW_RESULT( rmdir, err ); + + // -------------------------------------------------------------- + + checkcwd( dirname ); + +#ifdef CLEANUP + diag_printf("<INFO>: unlink "TINKY "\n"); + err = unlink( TINKY ); + if( err < 0 ) SHOW_RESULT( unlink, err ); + + diag_printf("<INFO>: unlink " LAALAA" \n"); + err = unlink( LAALAA ); + if( err < 0 ) SHOW_RESULT( unlink, err ); +#endif + + // -------------------------------------------------------------- + + diag_printf("<INFO>: cd %s\n", TEST_MOUNTPOINT TEST_DIRECTORY); + err = chdir( TEST_MOUNTPOINT TEST_DIRECTORY); + if( err < 0 ) SHOW_RESULT( chdir, err ); + checkcwd( TEST_MOUNTPOINT TEST_DIRECTORY ); + + listdir( ".", true, -1, NULL ); + +#ifdef TEST_MOUNTPOINT2 + if( mp2 ) + { + diag_printf("<INFO>: umount %s\n",TEST_MOUNTPOINT2); + err = umount( TEST_MOUNTPOINT2 ); + if( err < 0 ) SHOW_RESULT( umount, err ); + } +#endif + + // -------------------------------------------------------------- + +#if 0 + maxfile("file.max"); + + listdir( "/", true, -1, NULL ); + + diag_printf("<INFO>: unlink file.max\n"); + err = unlink( "file.max" ); + if( err < 0 ) SHOW_RESULT( unlink, err ); +#endif + + // -------------------------------------------------------------- + +#endif + diag_printf("<INFO>: cd /\n"); + err = chdir( "/" ); + if( err == 0 ) + { + checkcwd( "/" ); + + diag_printf("<INFO>: umount %s\n",TEST_MOUNTPOINT); + err = umount( TEST_MOUNTPOINT ); + if( err < 0 ) SHOW_RESULT( umount, err ); + } + + diag_printf("<INFO>: syncing\n"); + sync(); + + CYG_TEST_PASS_FINISH("yaffs6"); +} + +// ------------------------------------------------------------------------- + +#include <cyg/kernel/kapi.h> + +static cyg_handle_t thread_handle; +static cyg_thread thread; +static char stack[CYGNUM_HAL_STACK_SIZE_TYPICAL+1024*4]; + +externC void +cyg_start( void ) +{ + cyg_thread_create(3, // Priority - just a number + yaffs6_main, // entry + 0, // index + 0, // no name + &stack[0], // Stack + sizeof(stack), // Size + &thread_handle, // Handle + &thread // Thread data structure + ); + cyg_thread_resume(thread_handle); + + cyg_scheduler_start(); +} + +// ------------------------------------------------------------------------- +// EOF yaffs6.c
