1 //==========================================================================
5 // Fileio miscellaneous functions
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) 2003 Gary Thomas
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: Fileio miscellaneous functions
48 // Description: This file contains various miscellaneous functions
49 // for use with the fileio system. These include startup,
50 // table management, and other service routines.
52 //####DESCRIPTIONEND####
54 //==========================================================================
56 #include <pkgconf/system.h>
57 #include <pkgconf/hal.h>
58 #include <pkgconf/io_fileio.h>
59 #ifdef CYGPKG_LIBC_TIME
60 #include <pkgconf/libc_time.h>
64 #include <cyg/infra/cyg_trac.h> // tracing macros
65 #include <cyg/infra/cyg_ass.h> // assertion macros
66 #include <string.h> // strcmp()
67 #include <time.h> // time()
69 #ifdef CYGPKG_IO_WALLCLOCK
70 # include <cyg/io/wallclock.hxx> // Wallclock class
74 #include <pkgconf/kernel.h>
75 #include <cyg/kernel/ktypes.h> // base kernel types
76 #include <cyg/kernel/clock.inl> // Clock inlines
79 #include "fio.h" // Private header
81 //==========================================================================
82 // forward definitions
84 static void cyg_mtab_init();
86 __externC int chdir( const char *path );
88 //==========================================================================
91 // -------------------------------------------------------------------------
94 // This array contains entries for all filesystem that are installed in
96 __externC cyg_fstab_entry cyg_fstab[];
97 CYG_HAL_TABLE_BEGIN( cyg_fstab, fstab );
99 // end of filesystem table, set in linker script.
100 __externC cyg_fstab_entry cyg_fstab_end;
101 CYG_HAL_TABLE_END( cyg_fstab_end, fstab );
104 // Array of mutexes for locking the fstab entries
105 static Cyg_Mutex fstab_lock[CYGNUM_FILEIO_FSTAB_MAX] CYGBLD_ATTRIB_INIT_PRI(CYG_INIT_IO_FS);
108 // -------------------------------------------------------------------------
111 // This array contains entries for all valid running filesystems.
112 __externC cyg_mtab_entry cyg_mtab[];
113 CYG_HAL_TABLE_BEGIN( cyg_mtab, mtab );
115 // Extra entries at end of mtab for dynamic mount points.
116 #if CYGNUM_FILEIO_MTAB_EXTRA > 0
117 cyg_mtab_entry cyg_mtab_extra[CYGNUM_FILEIO_MTAB_EXTRA] CYG_HAL_TABLE_EXTRA(mtab) = { { NULL } };
119 // End of mount table, set in the linker script.
120 __externC cyg_mtab_entry cyg_mtab_end;
121 CYG_HAL_TABLE_END( cyg_mtab_end, mtab );
124 // Array of mutexes for locking the mtab entries
125 static Cyg_Mutex mtab_lock[CYGNUM_FILEIO_MTAB_MAX] CYGBLD_ATTRIB_INIT_PRI(CYG_INIT_IO_FS);
128 //==========================================================================
131 cyg_mtab_entry *cyg_cdir_mtab_entry = NULL;
132 cyg_dir cyg_cdir_dir = CYG_DIR_NULL;
134 //==========================================================================
135 // Initialization object
137 class Cyg_Fileio_Init_Class
140 Cyg_Fileio_Init_Class();
143 static Cyg_Fileio_Init_Class fileio_initializer CYGBLD_ATTRIB_INIT_PRI(CYG_INIT_IO_FS);
145 Cyg_Fileio_Init_Class::Cyg_Fileio_Init_Class()
154 //==========================================================================
155 // Mount table initializer
157 static void cyg_mtab_init()
161 for( m = &cyg_mtab[0]; m != &cyg_mtab_end; m++ )
163 const char *fsname = m->fsname;
166 // Ignore empty entries
167 if( m->name == NULL )
170 // stop if there are more than the configured maximum
171 if( m-&cyg_mtab[0] >= CYGNUM_FILEIO_MTAB_MAX )
174 for( f = &cyg_fstab[0]; f != &cyg_fstab_end; f++ )
176 // stop if there are more than the configured maximum
177 if( f-&cyg_fstab[0] >= CYGNUM_FILEIO_FSTAB_MAX )
180 if( strcmp( fsname, f->name) == 0 )
184 if( f->mount( f, m ) == 0 )
188 // m->root installed by fs.
201 //==========================================================================
202 // Mount table matching
204 // -------------------------------------------------------------------------
205 // matchlen() compares two strings and returns the number of bytes by which
208 static int matchlen( const char *s1, const char *s2 )
211 while( s1[len] == s2[len] && s1[len] && s2[len] ) len++;
213 // Return length only if s2 is an initial substring of s1,
214 // and it terminates in s1 at end-of-string or a '/'.
216 // Special case for s2 == "/"
217 if( len == 1 && s2[0] == '/' && s2[1] == 0 )
220 if( (s2[len] == 0) && (s1[len] == 0 || s1[len] == '/'))
225 // -------------------------------------------------------------------------
226 // Simple strlen implementation
228 static int my_strlen(const char *c)
235 // -------------------------------------------------------------------------
236 // Search the mtab for the entry that matches the longest substring of
239 __externC int cyg_mtab_lookup( cyg_dir *dir, const char **name, cyg_mtab_entry **mte)
241 cyg_mtab_entry *m, *best = NULL;
244 // Unrooted file names start from current dir
245 if( **name != '/' ) {
247 if (*mte == (cyg_mtab_entry *)NULL) {
248 // No known current directory
253 cwd_len = my_strlen((*mte)->name);
255 // current dir is not the correct mte if the relative path crosses
256 // mount points - search for best matching mount point
257 for( m = &cyg_mtab[0]; m != &cyg_mtab_end; m++ )
259 if( m->name != NULL && m->valid )
261 int len = matchlen(m->name, (*mte)->name);
262 // mount point under cwd?
265 if (m->name[len] == '/')
268 len = matchlen(*name, &m->name[len]);
270 best = m, best_len = len;
275 // did we find a better match?
281 // Otherwise search the mount table.
282 for( m = &cyg_mtab[0]; m != &cyg_mtab_end; m++ )
284 if( m->name != NULL && m->valid )
286 int len = matchlen(*name,m->name);
288 best = m, best_len = len;
292 // No match found, bad path name...
293 if( best_len == 0 ) return -1;
306 //==========================================================================
309 __externC int mount( const char *devname,
320 // Search the mount table for an empty entry
321 for( m = &cyg_mtab[0]; m != &cyg_mtab_end; m++ )
323 // stop if there are more than the configured maximum
324 if( m-&cyg_mtab[0] >= CYGNUM_FILEIO_MTAB_MAX )
330 if( m->name == NULL ) break;
333 if( m == &cyg_mtab_end )
334 FILEIO_RETURN(ENOMEM);
336 // Now search the fstab for the filesystem implementation
337 for( f = &cyg_fstab[0]; f != &cyg_fstab_end; f++ )
339 // stop if there are more than the configured maximum
340 if( f-&cyg_fstab[0] >= CYGNUM_FILEIO_FSTAB_MAX )
343 if( strcmp( fsname, f->name) == 0 )
347 if( f == &cyg_fstab_end )
348 FILEIO_RETURN(ENODEV);
354 m->devname = devname;
356 if( (result = f->mount( f, m )) == 0 )
360 // m->root installed by fs.
368 // Make sure that there is something to search (for open)
370 if (cyg_cdir_mtab_entry == (cyg_mtab_entry *)NULL) {
371 cyg_cdir_mtab_entry = m;
374 FILEIO_RETURN(result);
377 //==========================================================================
378 // unmount filesystem
380 __externC int umount( const char *name)
388 // Search the mount table for a matching entry
389 for( m = &cyg_mtab[0]; m != &cyg_mtab_end; m++ )
391 // stop if there are more than the configured maximum
392 if( m-&cyg_mtab[0] >= CYGNUM_FILEIO_MTAB_MAX )
398 // Ignore empty or invalid entries
399 if( m->name == NULL || !m->valid ) continue;
402 if( strcmp(name,m->name) == 0 ) break;
404 // Match device name too?
407 if( m == &cyg_mtab_end )
408 FILEIO_RETURN(EINVAL);
410 // We have a match, call the umount function
412 err = m->fs->umount( m );
423 //==========================================================================
424 // Implement filesystem locking protocol.
426 void cyg_fs_lock( cyg_mtab_entry *mte, cyg_uint32 syncmode )
428 CYG_ASSERT(mte != NULL, "Bad mount table entry");
430 if( syncmode & CYG_SYNCMODE_FILE_FILESYSTEM ) {
431 CYG_ASSERT(mte->fs-&cyg_fstab[0] < CYGNUM_FILEIO_FSTAB_MAX, "Bad file system");
432 FILEIO_MUTEX_LOCK( fstab_lock[mte->fs-&cyg_fstab[0]] );
435 if( syncmode & CYG_SYNCMODE_FILE_MOUNTPOINT ) {
436 CYG_ASSERT(mte-&cyg_mtab[0] < CYGNUM_FILEIO_MTAB_MAX, "Bad mount point");
437 FILEIO_MUTEX_LOCK( mtab_lock[mte-&cyg_mtab[0]] );
441 void cyg_fs_unlock( cyg_mtab_entry *mte, cyg_uint32 syncmode )
443 CYG_ASSERT(mte != NULL, "Bad mount table entry");
445 if( syncmode & CYG_SYNCMODE_FILE_FILESYSTEM ) {
446 CYG_ASSERT(mte->fs-&cyg_fstab[0] < CYGNUM_FILEIO_FSTAB_MAX, "Bad file system");
447 FILEIO_MUTEX_UNLOCK( fstab_lock[mte->fs-&cyg_fstab[0]] );
450 if( syncmode & CYG_SYNCMODE_FILE_MOUNTPOINT ) {
451 CYG_ASSERT(mte-&cyg_mtab[0] < CYGNUM_FILEIO_MTAB_MAX, "Bad mount point");
452 FILEIO_MUTEX_UNLOCK( mtab_lock[mte-&cyg_mtab[0]] );
456 //==========================================================================
457 // Search mount table for a filesystems root.
459 __externC cyg_mtab_entry * cyg_fs_root_lookup( cyg_dir *root )
463 for( m = &cyg_mtab[0]; m != &cyg_mtab_end; m++ )
465 if( (cyg_dir *)m->root == root )
473 //==========================================================================
475 // This provides access to the current time/date, expressed as a
476 // time_t. It uses a number of mechanisms to do this, selecting
477 // whichever is available in the current configuration.
479 __externC time_t cyg_timestamp()
481 #if defined(CYGPKG_IO_WALLCLOCK)
483 // First, try to get the time from the wallclock device.
485 return (time_t) Cyg_WallClock::wallclock->get_current_time();
487 #elif defined(CYGINT_ISO_POSIX_TIMERS)
489 // If POSIX is present, use the current value of the realtime
494 clock_gettime( CLOCK_REALTIME, &tp );
496 return (time_t) tp.tv_sec;
498 #elif defined(CYGPKG_KERNEL)
500 // If all else fails, get the current realtime clock value and
501 // convert it to seconds ourself.
503 static struct Cyg_Clock::converter sec_converter;
504 static cyg_bool initialized = false;
505 cyg_tick_count ticks;
509 Cyg_Clock::real_time_clock->get_clock_to_other_converter( 1000000000, &sec_converter );
513 ticks = Cyg_Clock::real_time_clock->current_value();
515 return (time_t) Cyg_Clock::convert( ticks, &sec_converter );
517 /* No clock support at all. */
523 //==========================================================================
526 __externC int cyg_fileio_enosys() { return ENOSYS; }
527 __externC int cyg_fileio_erofs() { return EROFS; }
528 __externC int cyg_fileio_enoerr() { return ENOERR; }
529 __externC int cyg_fileio_enotdir() { return ENOTDIR; }
531 __externC cyg_bool cyg_fileio_seltrue (struct CYG_FILE_TAG *fp, int which, CYG_ADDRWORD info)
534 // -------------------------------------------------------------------------