1 //==========================================================================
7 //==========================================================================
8 //####ECOSGPLCOPYRIGHTBEGIN####
9 // -------------------------------------------
10 // This file is part of eCos, the Embedded Configurable Operating System.
11 // Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
12 // Copyright (C) 2004 eCosCentric Limited
14 // eCos is free software; you can redistribute it and/or modify it under
15 // the terms of the GNU General Public License as published by the Free
16 // Software Foundation; either version 2 or (at your option) any later version.
18 // eCos is distributed in the hope that it will be useful, but WITHOUT ANY
19 // WARRANTY; without even the implied warranty of MERCHANTABILITY or
20 // FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
23 // You should have received a copy of the GNU General Public License along
24 // with eCos; if not, write to the Free Software Foundation, Inc.,
25 // 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
27 // As a special exception, if other files instantiate templates or use macros
28 // or inline functions from this file, or you compile this file and link it
29 // with other works to produce a work based on this file, this file does not
30 // by itself cause the resulting work to be covered by the GNU General Public
31 // License. However the source code for this file must still be made available
32 // in accordance with section (3) of the GNU General Public License.
34 // This exception does not invalidate any other reasons why a work based on
35 // this file might be covered by the GNU General Public License.
37 // Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
38 // at http://sources.redhat.com/ecos/ecos-license/
39 // -------------------------------------------
40 //####ECOSGPLCOPYRIGHTEND####
41 //==========================================================================
42 //#####DESCRIPTIONBEGIN####
45 // Contributors: nickg
47 // Purpose: Test fileio system
48 // Description: This test uses the testfs to check out the initialization
49 // and basic operation of the fileio system
57 //####DESCRIPTIONEND####
59 //==========================================================================
61 #include <pkgconf/hal.h>
62 #include <pkgconf/io_fileio.h>
63 #include <pkgconf/fs_fat.h>
65 #include <cyg/infra/cyg_trac.h> // tracing macros
66 #include <cyg/infra/cyg_ass.h> // assertion macros
76 #include <cyg/fileio/fileio.h>
78 #include <cyg/infra/testcase.h>
79 #include <cyg/infra/diag.h> // HAL polled output
80 #include <cyg/fs/fatfs.h>
84 //==========================================================================
86 #define SHOW_RESULT( _fn, _res ) \
87 diag_printf("<FAIL>: " #_fn "() returned %d %s\n", _res, _res<0?strerror(errno):"");
89 //==========================================================================
93 #define LONGNAME1 "long_file_name_that_should_take_up_more_than_one_directory_entry_1"
94 #define LONGNAME2 "long_file_name_that_should_take_up_more_than_one_directory_entry_2"
97 //==========================================================================
99 #ifndef CYGPKG_LIBC_STRING
101 char *strcat( char *s1, const char *s2 )
105 while( (*s1++ = *s2++) != 0);
111 //==========================================================================
113 static void listdir( char *name, int statp, int numexpected, int *numgot )
119 diag_printf("<INFO>: reading directory %s\n",name);
121 dirp = opendir( name );
122 if( dirp == NULL ) SHOW_RESULT( opendir, -1 );
126 struct dirent *entry = readdir( dirp );
131 diag_printf("<INFO>: entry %14s",entry->d_name);
134 char fullname[PATH_MAX];
139 strcpy(fullname, name );
140 if( !(name[0] == '/' && name[1] == 0 ) )
141 strcat(fullname, "/" );
143 else fullname[0] = 0;
145 strcat(fullname, entry->d_name );
147 err = stat( fullname, &sbuf );
150 if( errno == ENOSYS )
151 diag_printf(" <no status available>");
152 else SHOW_RESULT( stat, err );
156 diag_printf(" [mode %08x ino %08x nlink %d size %ld]",
157 sbuf.st_mode,sbuf.st_ino,sbuf.st_nlink,(long)sbuf.st_size);
164 err = closedir( dirp );
165 if( err < 0 ) SHOW_RESULT( stat, err );
166 if (numexpected >= 0 && num != numexpected)
167 CYG_TEST_FAIL("Wrong number of dir entries\n");
168 if ( numgot != NULL )
172 //==========================================================================
174 static void createfile( char *name, size_t size )
182 diag_printf("<INFO>: create file %s size %d\n",name,size);
184 err = access( name, F_OK );
185 if( err < 0 && errno != EACCES ) SHOW_RESULT( access, err );
187 for( i = 0; i < IOSIZE; i++ ) buf[i] = i%256;
189 fd = open( name, O_WRONLY|O_CREAT );
190 if( fd < 0 ) SHOW_RESULT( open, fd );
195 if ( len > IOSIZE ) len = IOSIZE;
197 wrote = write( fd, buf, len );
198 if( wrote != len ) SHOW_RESULT( write, (int)wrote );
204 if( err < 0 ) SHOW_RESULT( close, err );
207 //==========================================================================
209 static void maxfile( char *name )
219 diag_printf("<INFO>: create maximal file %s\n",name);
220 diag_printf("<INFO>: This may take a few minutes\n");
222 err = access( name, F_OK );
223 if( err < 0 && errno != EACCES ) SHOW_RESULT( access, err );
225 for( i = 0; i < IOSIZE; i++ ) buf[i] = i%256;
227 fd = open( name, O_WRONLY|O_CREAT );
228 if( fd < 0 ) SHOW_RESULT( open, fd );
232 wrote = write( fd, buf, IOSIZE );
233 //if( wrote < 0 ) SHOW_RESULT( write, wrote );
238 if( (size-prevsize) > 100000 )
240 diag_printf("<INFO>: size = %d \n", size);
244 } while( wrote == IOSIZE );
246 diag_printf("<INFO>: file size == %d\n",size);
249 if( err < 0 ) SHOW_RESULT( close, err );
252 //==========================================================================
254 static void checkfile( char *name )
263 diag_printf("<INFO>: check file %s\n",name);
265 err = access( name, F_OK );
266 if( err != 0 ) SHOW_RESULT( access, err );
268 fd = open( name, O_RDONLY );
269 if( fd < 0 ) SHOW_RESULT( open, fd );
273 done = read( fd, buf, IOSIZE );
274 if( done < 0 ) SHOW_RESULT( read, (int)done );
276 if( done == 0 ) break;
278 for( i = 0; i < done; i++ )
279 if( buf[i] != i%256 )
281 diag_printf("buf[%ld+%d](%02x) != %02x\n",pos,i,buf[i],i%256);
282 CYG_TEST_FAIL("Data read not equal to data written\n");
289 if( err < 0 ) SHOW_RESULT( close, err );
292 #ifdef CYGCFG_FS_FAT_USE_ATTRIBUTES
293 //==========================================================================
295 static void checkattrib(const char *name,
296 const cyg_fs_attrib_t test_attrib )
299 cyg_fs_attrib_t file_attrib;
301 diag_printf("<INFO>: check attrib %s\n",name);
303 err = cyg_fs_get_attrib(name, &file_attrib);
304 if( err != 0 ) SHOW_RESULT( stat, err );
306 if ( (file_attrib & S_FATFS_ATTRIB) != test_attrib )
307 diag_printf("<FAIL>: attrib %s incorrect\n\tExpected %x Was %x\n",
308 name,test_attrib,(file_attrib & S_FATFS_ATTRIB));
310 #endif // CYGCFG_FS_FAT_USE_ATTRIBUTES
312 //==========================================================================
314 static void copyfile( char *name2, char *name1 )
322 diag_printf("<INFO>: copy file %s -> %s\n",name2,name1);
324 err = access( name1, F_OK );
325 if( err < 0 && errno != EACCES ) SHOW_RESULT( access, err );
327 err = access( name2, F_OK );
328 if( err != 0 ) SHOW_RESULT( access, err );
330 fd1 = open( name1, O_WRONLY|O_CREAT );
331 if( fd1 < 0 ) SHOW_RESULT( open, fd1 );
333 fd2 = open( name2, O_RDONLY );
334 if( fd2 < 0 ) SHOW_RESULT( open, fd2 );
338 done = read( fd2, buf, IOSIZE );
339 if( done < 0 ) SHOW_RESULT( read, (int)done );
341 if( done == 0 ) break;
343 wrote = write( fd1, buf, done );
344 if( wrote != done ) SHOW_RESULT( write, (int) wrote );
346 if( wrote != done ) break;
350 if( err < 0 ) SHOW_RESULT( close, err );
353 if( err < 0 ) SHOW_RESULT( close, err );
357 //==========================================================================
359 static void comparefiles( char *name2, char *name1 )
365 ssize_t done1, done2;
368 diag_printf("<INFO>: compare files %s == %s\n",name2,name1);
370 err = access( name1, F_OK );
371 if( err != 0 ) SHOW_RESULT( access, err );
373 err = access( name1, F_OK );
374 if( err != 0 ) SHOW_RESULT( access, err );
376 fd1 = open( name1, O_RDONLY );
377 if( fd1 < 0 ) SHOW_RESULT( open, fd1 );
379 fd2 = open( name2, O_RDONLY );
380 if( fd2 < 0 ) SHOW_RESULT( open, fd2 );
384 done1 = read( fd1, buf1, IOSIZE );
385 if( done1 < 0 ) SHOW_RESULT( read, (int)done1 );
387 done2 = read( fd2, buf2, IOSIZE );
388 if( done2 < 0 ) SHOW_RESULT( read, (int)done2 );
391 diag_printf("Files different sizes\n");
393 if( done1 == 0 ) break;
395 for( i = 0; i < done1; i++ )
396 if( buf1[i] != buf2[i] )
398 diag_printf("buf1[%d](%02x) != buf1[%d](%02x)\n",i,buf1[i],i,buf2[i]);
399 CYG_TEST_FAIL("Data in files not equal\n");
404 if( err < 0 ) SHOW_RESULT( close, err );
407 if( err < 0 ) SHOW_RESULT( close, err );
411 //==========================================================================
413 void checkcwd( const char *cwd )
415 static char cwdbuf[PATH_MAX];
418 ret = getcwd( cwdbuf, sizeof(cwdbuf));
419 if( ret == NULL ) SHOW_RESULT( getcwd, (int)ret );
421 if( strcmp( cwdbuf, cwd ) != 0 )
423 diag_printf( "cwdbuf %s cwd %s\n",cwdbuf, cwd );
424 CYG_TEST_FAIL( "Current directory mismatch");
428 //==========================================================================
431 int main( int argc, char **argv )
434 int existingdirents=-1;
438 // --------------------------------------------------------------
440 err = mount( "/dev/disk0/1", "/", "fatfs" );
441 if( err < 0 ) SHOW_RESULT( mount, err );
444 if( err < 0 ) SHOW_RESULT( chdir, err );
448 listdir( "/", true, -1, &existingdirents );
450 // --------------------------------------------------------------
452 createfile( "/foo", 20257 );
454 copyfile( "foo", "fee");
456 comparefiles( "foo", "/fee" );
457 diag_printf("<INFO>: mkdir bar\n");
458 err = mkdir( "/bar", 0 );
459 if( err < 0 ) SHOW_RESULT( mkdir, err );
461 listdir( "/" , true, existingdirents+3, NULL );
463 copyfile( "fee", "/bar/fum" );
464 checkfile( "bar/fum" );
465 comparefiles( "/fee", "bar/fum" );
467 diag_printf("<INFO>: cd bar\n");
468 err = chdir( "bar" );
469 if( err < 0 ) SHOW_RESULT( chdir, err );
473 diag_printf("<INFO>: rename /foo bundy\n");
474 err = rename( "/foo", "bundy" );
475 if( err < 0 ) SHOW_RESULT( rename, err );
477 listdir( "/", true, existingdirents+2, NULL );
478 listdir( "" , true, 4, NULL );
480 checkfile( "/bar/bundy" );
481 comparefiles("/fee", "bundy" );
483 // --------------------------------------------------------------
485 diag_printf("<INFO>: unlink fee\n");
486 err = unlink( "/fee" );
487 if( err < 0 ) SHOW_RESULT( unlink, err );
489 diag_printf("<INFO>: unlink fum\n");
490 err = unlink( "fum" );
491 if( err < 0 ) SHOW_RESULT( unlink, err );
493 diag_printf("<INFO>: unlink /bar/bundy\n");
494 err = unlink( "/bar/bundy" );
495 if( err < 0 ) SHOW_RESULT( unlink, err );
497 diag_printf("<INFO>: cd /\n");
499 if( err < 0 ) SHOW_RESULT( chdir, err );
503 diag_printf("<INFO>: rmdir /bar\n");
504 err = rmdir( "/bar" );
505 if( err < 0 ) SHOW_RESULT( rmdir, err );
507 listdir( "/", false, existingdirents, NULL );
509 // --------------------------------------------------------------
512 diag_printf("<INFO>: mkdir disk2\n");
513 err = mkdir( "/disk2", 0 );
514 if( err < 0 ) SHOW_RESULT( mkdir, err );
516 diag_printf("<INFO>: mount /disk2\n");
517 err = mount( "/dev/disk0/2", "/disk2", "fatfs" );
518 if( err < 0 ) SHOW_RESULT( mount, err );
521 listdir( "/disk2" , true, -1, &existingdirents);
523 createfile( "/disk2/tinky", 4567 );
524 copyfile( "/disk2/tinky", "/disk2/laalaa" );
525 checkfile( "/disk2/tinky");
526 checkfile( "/disk2/laalaa");
527 comparefiles( "/disk2/tinky", "/disk2/laalaa" );
529 diag_printf("<INFO>: cd /disk2\n");
530 err = chdir( "/disk2" );
531 if( err < 0 ) SHOW_RESULT( chdir, err );
533 checkcwd( "/disk2" );
535 diag_printf("<INFO>: mkdir noonoo\n");
536 err = mkdir( "noonoo", 0 );
537 if( err < 0 ) SHOW_RESULT( mkdir, err );
539 listdir( "/disk2" , true, existingdirents+3, NULL);
541 diag_printf("<INFO>: cd noonoo\n");
542 err = chdir( "noonoo" );
543 if( err < 0 ) SHOW_RESULT( chdir, err );
545 checkcwd( "/disk2/noonoo" );
547 createfile( "tinky", 6789 );
548 checkfile( "tinky" );
550 createfile( "dipsy", 34567 );
551 checkfile( "dipsy" );
552 copyfile( "dipsy", "po" );
554 comparefiles( "dipsy", "po" );
556 listdir( ".", true, 5, NULL );
557 listdir( "", true, 5, NULL );
558 listdir( "..", true, existingdirents+3, NULL );
560 // --------------------------------------------------------------
562 diag_printf("<INFO>: unlink tinky\n");
563 err = unlink( "tinky" );
564 if( err < 0 ) SHOW_RESULT( unlink, err );
566 diag_printf("<INFO>: unlink dipsy\n");
567 err = unlink( "dipsy" );
568 if( err < 0 ) SHOW_RESULT( unlink, err );
570 diag_printf("<INFO>: unlink po\n");
571 err = unlink( "po" );
572 if( err < 0 ) SHOW_RESULT( unlink, err );
574 diag_printf("<INFO>: cd ..\n");
576 if( err < 0 ) SHOW_RESULT( chdir, err );
577 checkcwd( "/disk2" );
579 diag_printf("<INFO>: rmdir noonoo\n");
580 err = rmdir( "noonoo" );
581 if( err < 0 ) SHOW_RESULT( rmdir, err );
583 // --------------------------------------------------------------
585 err = mkdir( "x", 0 );
586 if( err < 0 ) SHOW_RESULT( mkdir, err );
588 err = mkdir( "x/y", 0 );
589 if( err < 0 ) SHOW_RESULT( mkdir, err );
591 err = mkdir( "x/y/z", 0 );
592 if( err < 0 ) SHOW_RESULT( mkdir, err );
594 err = mkdir( "x/y/z/w", 0 );
595 if( err < 0 ) SHOW_RESULT( mkdir, err );
597 diag_printf("<INFO>: cd /disk2/x/y/z/w\n");
598 err = chdir( "/disk2/x/y/z/w" );
599 if( err < 0 ) SHOW_RESULT( chdir, err );
600 checkcwd( "/disk2/x/y/z/w" );
602 diag_printf("<INFO>: cd ..\n");
604 if( err < 0 ) SHOW_RESULT( chdir, err );
605 checkcwd( "/disk2/x/y/z" );
607 diag_printf("<INFO>: cd .\n");
609 if( err < 0 ) SHOW_RESULT( chdir, err );
610 checkcwd( "/disk2/x/y/z" );
612 diag_printf("<INFO>: cd ../../y\n");
613 err = chdir( "../../y" );
614 if( err < 0 ) SHOW_RESULT( chdir, err );
615 checkcwd( "/disk2/x/y" );
617 diag_printf("<INFO>: cd ../..\n");
618 err = chdir( "../.." );
619 if( err < 0 ) SHOW_RESULT( chdir, err );
620 checkcwd( "/disk2" );
622 diag_printf("<INFO>: rmdir x/y/z/w\n");
623 err = rmdir( "x/y/z/w" );
624 if( err < 0 ) SHOW_RESULT( rmdir, err );
626 diag_printf("<INFO>: rmdir x/y/z\n");
627 err = rmdir( "x/y/z" );
628 if( err < 0 ) SHOW_RESULT( rmdir, err );
630 diag_printf("<INFO>: rmdir x/y\n");
631 err = rmdir( "x/y" );
632 if( err < 0 ) SHOW_RESULT( rmdir, err );
634 diag_printf("<INFO>: rmdir x\n");
636 if( err < 0 ) SHOW_RESULT( rmdir, err );
638 // --------------------------------------------------------------
640 checkcwd( "/disk2" );
642 diag_printf("<INFO>: unlink tinky\n");
643 err = unlink( "tinky" );
644 if( err < 0 ) SHOW_RESULT( unlink, err );
646 diag_printf("<INFO>: unlink laalaa\n");
647 err = unlink( "laalaa" );
648 if( err < 0 ) SHOW_RESULT( unlink, err );
650 diag_printf("<INFO>: cd /\n");
652 if( err < 0 ) SHOW_RESULT( chdir, err );
655 listdir( "/disk2", true, -1, NULL );
658 diag_printf("<INFO>: rmdir dir\n");
659 err = rmdir( "disk2" );
660 if( err < 0 ) SHOW_RESULT( rmdir, err );
662 diag_printf("<INFO>: umount /disk2\n");
663 err = umount( "/disk2" );
664 if( err < 0 ) SHOW_RESULT( umount, err );
667 #ifdef CYGCFG_FS_FAT_USE_ATTRIBUTES
669 diag_printf("<INFO>: create /foo\n");
670 createfile( "/foo", 20257 );
672 // Verify it is created with archive bit set
673 checkattrib( "/foo", S_FATFS_ARCHIVE );
676 diag_printf("<INFO>: attrib -A+S /foo\n");
677 err = cyg_fs_set_attrib( "/foo", S_FATFS_SYSTEM );
678 if( err < 0 ) SHOW_RESULT( chmod system , err );
680 // Verify it is now System
681 checkattrib( "/foo", S_FATFS_SYSTEM );
684 diag_printf("<INFO>: attrib -S+H /foo\n");
685 err = cyg_fs_set_attrib( "/foo", S_FATFS_HIDDEN );
686 if( err < 0 ) SHOW_RESULT( chmod system , err );
688 // Verify it is now Hidden
689 checkattrib( "/foo", S_FATFS_HIDDEN );
692 diag_printf("<INFO>: attrib -H+R /foo\n");
693 err = cyg_fs_set_attrib( "/foo", S_FATFS_RDONLY );
694 if( err < 0 ) SHOW_RESULT( chmod system , err );
696 // Verify it is now Read-only
697 checkattrib( "/foo", S_FATFS_RDONLY );
699 // Verify we cannot unlink a read-only file
700 diag_printf("<INFO>: unlink /foo\n");
701 err = unlink( "/foo" );
702 if( (err != -1) || (errno != EPERM) ) SHOW_RESULT( unlink, err );
704 // Verify we cannot rename a read-only file
705 diag_printf("<INFO>: rename /foo bundy\n");
706 err = rename( "/foo", "bundy" );
707 if( (err != -1) || (errno != EPERM) ) SHOW_RESULT( rename, err );
709 // Verify we cannot open read-only file for writing
711 diag_printf("<INFO>: create file /foo\n");
712 fd = open( "/foo", O_WRONLY );
713 if( (err != -1) || (errno != EACCES) ) SHOW_RESULT( open, err );
714 if( err > 0 ) close(fd);
717 diag_printf("<INFO>: attrib -H /foo\n");
718 err = cyg_fs_set_attrib( "/foo", 0 );
719 if( err < 0 ) SHOW_RESULT( chmod none , err );
721 // Verify it is now nothing
722 checkattrib( "/foo", 0 );
724 // Now delete our test file
725 diag_printf("<INFO>: unlink /foo\n");
726 err = unlink( "/foo" );
727 if( err < 0 ) SHOW_RESULT( unlink, err );
729 #endif // CYGCFG_FS_FAT_USE_ATTRIBUTES
733 listdir( "/", true, -1, NULL );
735 diag_printf("<INFO>: unlink file.max\n");
736 err = unlink( "file.max" );
737 if( err < 0 ) SHOW_RESULT( unlink, err );
738 diag_printf("<INFO>: umount /\n");
740 if( err < 0 ) SHOW_RESULT( umount, err );
742 CYG_TEST_PASS_FINISH("fatfs1");
745 // -------------------------------------------------------------------------