]> git.karo-electronics.de Git - karo-tx-redboot.git/blob - packages/io/fileio/v2_0/src/misc.cxx
f878cf6f993c6c7d9f7dba40a2c5ee70d447803d
[karo-tx-redboot.git] / packages / io / fileio / v2_0 / src / misc.cxx
1 //==========================================================================
2 //
3 //      misc.cxx
4 //
5 //      Fileio miscellaneous functions
6 //
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
13 //
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.
17 //
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
21 // for more details.
22 //
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.
26 //
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.
33 //
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.
36 //
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####
43 //
44 // Author(s):           nickg
45 // Contributors:        nickg
46 // Date:                2000-05-25
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.
51 //
52 //####DESCRIPTIONEND####
53 //
54 //==========================================================================
55
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>
61 #endif
62
63
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()
68
69 #ifdef CYGPKG_IO_WALLCLOCK
70 # include <cyg/io/wallclock.hxx>       // Wallclock class
71 #endif
72
73 #ifdef CYGPKG_KERNEL
74 #include <pkgconf/kernel.h>
75 #include <cyg/kernel/ktypes.h>         // base kernel types
76 #include <cyg/kernel/clock.inl>         // Clock inlines
77 #endif
78
79 #include "fio.h"                       // Private header
80
81 //==========================================================================
82 // forward definitions
83
84 static void cyg_mtab_init();
85
86 __externC int chdir( const char *path );
87
88 //==========================================================================
89 // Filesystem tables
90
91 // -------------------------------------------------------------------------
92 // Filesystem table.
93
94 // This array contains entries for all filesystem that are installed in
95 // the system.
96 __externC cyg_fstab_entry cyg_fstab[];
97 CYG_HAL_TABLE_BEGIN( cyg_fstab, fstab );
98
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 );
102
103 #ifdef CYGPKG_KERNEL
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);
106 #endif
107
108 // -------------------------------------------------------------------------
109 // Mount table.
110
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 );
114
115 // Extra entries at end of mtab for dynamic mount points.
116 cyg_mtab_entry cyg_mtab_extra[CYGNUM_FILEIO_MTAB_EXTRA] CYG_HAL_TABLE_EXTRA(mtab) = { { NULL } };
117
118 // End of mount table, set in the linker script.
119 __externC cyg_mtab_entry cyg_mtab_end;
120 CYG_HAL_TABLE_END( cyg_mtab_end, mtab );
121
122 #ifdef CYGPKG_KERNEL
123 // Array of mutexes for locking the mtab entries
124 static Cyg_Mutex mtab_lock[CYGNUM_FILEIO_MTAB_MAX] CYGBLD_ATTRIB_INIT_PRI(CYG_INIT_IO_FS);
125 #endif
126
127 //==========================================================================
128 // Current directory
129
130 cyg_mtab_entry *cyg_cdir_mtab_entry = NULL;
131 cyg_dir cyg_cdir_dir = CYG_DIR_NULL;
132
133 //==========================================================================
134 // Initialization object
135
136 class Cyg_Fileio_Init_Class
137 {
138 public:    
139     Cyg_Fileio_Init_Class();
140 };
141
142 static Cyg_Fileio_Init_Class fileio_initializer CYGBLD_ATTRIB_INIT_PRI(CYG_INIT_IO_FS);
143
144 Cyg_Fileio_Init_Class::Cyg_Fileio_Init_Class()
145 {
146     cyg_fd_init();
147
148     cyg_mtab_init();
149
150     chdir("/");
151 }
152
153 //==========================================================================
154 // Mount table initializer
155
156 static void cyg_mtab_init()
157 {
158     cyg_mtab_entry *m;
159     
160     for( m = &cyg_mtab[0]; m != &cyg_mtab_end; m++ )
161     {
162         const char *fsname = m->fsname;
163         cyg_fstab_entry *f;
164
165         // Ignore empty entries
166         if( m->name == NULL )
167             continue;
168         
169         // stop if there are more than the configured maximum
170         if( m-&cyg_mtab[0] >= CYGNUM_FILEIO_MTAB_MAX )
171             break;
172         
173         for( f = &cyg_fstab[0]; f != &cyg_fstab_end; f++ )
174         {
175             // stop if there are more than the configured maximum
176             if( f-&cyg_fstab[0] >= CYGNUM_FILEIO_FSTAB_MAX )
177                 break;
178             
179             if( strcmp( fsname, f->name) == 0 )
180             {
181                 // We have a match.
182
183                 if( f->mount( f, m ) == 0 )
184                 {
185                     m->valid    = true;
186                     m->fs       = f;
187                     // m->root installed by fs.
188                 }
189                 else
190                 {
191                     m->valid = false;
192                 }
193                 
194                 break;
195             }
196         }
197     }
198 }
199
200 //==========================================================================
201 // Mount table matching
202
203 // -------------------------------------------------------------------------
204 // matchlen() compares two strings and returns the number of bytes by which
205 // they match.
206
207 static int matchlen( const char *s1, const char *s2 )
208 {
209     int len = 0;
210     while( s1[len] == s2[len] && s1[len] && s2[len] ) len++;
211
212     // Return length only if s2 is an initial substring of s1,
213     // and it terminates in s1 at end-of-string or a '/'.
214
215     // Special case for s2 == "/"
216     if( len == 1 && s2[0] == '/' && s2[1] == 0 )
217         return len;
218     
219     if( (s2[len] == 0) && (s1[len] == 0 || s1[len] == '/'))
220          return len;
221     else return 0;
222 }
223
224 // -------------------------------------------------------------------------
225 // Search the mtab for the entry that matches the longest substring of
226 // **name. 
227
228 __externC int cyg_mtab_lookup( cyg_dir *dir, const char **name, cyg_mtab_entry **mte)
229 {
230     cyg_mtab_entry *m, *best = NULL;
231     int best_len = 0;
232
233     // Unrooted file names go straight to current dir
234     if( **name != '/' ) {
235         if (*mte == (cyg_mtab_entry *)NULL) {
236             // No known current directory
237             return -1;
238         }
239         // Current directory is well known
240         return 0;
241     }
242
243     // Otherwise search the mount table.
244     for( m = &cyg_mtab[0]; m != &cyg_mtab_end; m++ )
245     {
246         if( m->name != NULL && m->valid )
247         {
248             int len = matchlen(*name,m->name);
249             if( len > best_len )
250                 best = m, best_len = len;
251         }
252     }
253
254     // No match found, bad path name...
255     if( best_len == 0 ) return -1;
256     
257     *name += best_len;
258     if( **name == '/' )
259         (*name)++;
260     *mte = best;
261     *dir = best->root;
262
263     return 0;
264 }
265
266 //==========================================================================
267 // mount filesystem
268
269 __externC int mount( const char *devname,
270                      const char *dir,
271                      const char *fsname)
272 {
273
274     FILEIO_ENTRY();
275     
276     cyg_mtab_entry *m;
277     cyg_fstab_entry *f;
278     int result = ENOERR;
279
280     // Search the mount table for an empty entry
281     for( m = &cyg_mtab[0]; m != &cyg_mtab_end; m++ )
282     {
283         // stop if there are more than the configured maximum
284         if( m-&cyg_mtab[0] >= CYGNUM_FILEIO_MTAB_MAX )
285         {
286             m = &cyg_mtab_end;
287             break;
288         }
289
290          if( m->name == NULL ) break;
291     }
292
293     if( m == &cyg_mtab_end )
294         FILEIO_RETURN(ENOMEM);
295
296     // Now search the fstab for the filesystem implementation
297     for( f = &cyg_fstab[0]; f != &cyg_fstab_end; f++ )
298     {
299         // stop if there are more than the configured maximum
300         if( f-&cyg_fstab[0] >= CYGNUM_FILEIO_FSTAB_MAX )
301             break;
302             
303         if( strcmp( fsname, f->name) == 0 )
304             break;
305     }
306
307     if( f == &cyg_fstab_end )
308         FILEIO_RETURN(ENODEV);
309             
310     // We have a match.
311
312     m->name = dir;
313     m->fsname = fsname;
314     m->devname = devname;
315     
316     if( (result = f->mount( f, m )) == 0 )
317     {
318         m->valid    = true;
319         m->fs       = f;
320         // m->root installed by fs.
321     }
322     else
323     {
324         m->valid = false;
325         m->name = NULL;
326     }
327
328     // Make sure that there is something to search (for open)
329
330     if (cyg_cdir_mtab_entry == (cyg_mtab_entry *)NULL) {
331         cyg_cdir_mtab_entry = m;
332     }
333
334     FILEIO_RETURN(result);
335 }
336
337 //==========================================================================
338 // unmount filesystem
339
340 __externC int umount( const char *name)
341 {
342     int err = ENOERR;
343     
344     FILEIO_ENTRY();
345     
346     cyg_mtab_entry *m;
347
348     // Search the mount table for a matching entry
349     for( m = &cyg_mtab[0]; m != &cyg_mtab_end; m++ )
350     {
351         // stop if there are more than the configured maximum
352         if( m-&cyg_mtab[0] >= CYGNUM_FILEIO_MTAB_MAX )
353         {
354             m = &cyg_mtab_end;
355             break;
356         }
357
358         // Ignore empty or invalid entries
359          if( m->name == NULL || !m->valid ) continue;
360
361          // match names.
362          if( strcmp(name,m->name) == 0 ) break;
363
364          // Match device name too?
365     }
366
367     if( m == &cyg_mtab_end )
368         FILEIO_RETURN(EINVAL);
369
370     // We have a match, call the umount function
371
372     err = m->fs->umount( m );
373
374     if( err == ENOERR )
375     {
376         m->valid        = false;
377         m->name         = NULL;
378     }
379     
380     FILEIO_RETURN(err);
381 }
382
383 //==========================================================================
384 // Implement filesystem locking protocol. 
385
386 void cyg_fs_lock( cyg_mtab_entry *mte, cyg_uint32 syncmode )
387 {
388     CYG_ASSERT(mte != NULL, "Bad mount table entry");
389
390     if( syncmode & CYG_SYNCMODE_FILE_FILESYSTEM ) {
391         CYG_ASSERT(mte->fs-&cyg_fstab[0] < CYGNUM_FILEIO_FSTAB_MAX, "Bad file system");
392         FILEIO_MUTEX_LOCK( fstab_lock[mte->fs-&cyg_fstab[0]] );
393     }
394
395     if( syncmode & CYG_SYNCMODE_FILE_MOUNTPOINT ) {
396         CYG_ASSERT(mte-&cyg_mtab[0] < CYGNUM_FILEIO_MTAB_MAX, "Bad mount point");
397         FILEIO_MUTEX_LOCK( mtab_lock[mte-&cyg_mtab[0]] );
398     }
399 }
400
401 void cyg_fs_unlock( cyg_mtab_entry *mte, cyg_uint32 syncmode )
402 {
403     CYG_ASSERT(mte != NULL, "Bad mount table entry");
404
405     if( syncmode & CYG_SYNCMODE_FILE_FILESYSTEM ) {
406         CYG_ASSERT(mte->fs-&cyg_fstab[0] < CYGNUM_FILEIO_FSTAB_MAX, "Bad file system");
407         FILEIO_MUTEX_UNLOCK( fstab_lock[mte->fs-&cyg_fstab[0]] );
408     }
409
410     if( syncmode & CYG_SYNCMODE_FILE_MOUNTPOINT ) {
411         CYG_ASSERT(mte-&cyg_mtab[0] < CYGNUM_FILEIO_MTAB_MAX, "Bad mount point");
412         FILEIO_MUTEX_UNLOCK( mtab_lock[mte-&cyg_mtab[0]] );
413     }
414 }
415
416 //==========================================================================
417 // Search mount table for a filesystems root. 
418
419 __externC cyg_mtab_entry * cyg_fs_root_lookup( cyg_dir *root ) 
420 {
421      cyg_mtab_entry *m;
422
423      for( m = &cyg_mtab[0]; m != &cyg_mtab_end; m++ ) 
424      {
425           if( (cyg_dir *)m->root == root )
426           {
427                return m;
428           }
429      }
430      return NULL;
431 }
432
433 //==========================================================================
434 // Timestamp support
435 // This provides access to the current time/date, expressed as a
436 // time_t.  It uses a number of mechanisms to do this, selecting
437 // whichever is available in the current configuration.
438
439 __externC time_t cyg_timestamp()
440 {
441 #if defined(CYGPKG_IO_WALLCLOCK)
442
443     // First, try to get the time from the wallclock device.
444     
445     return (time_t) Cyg_WallClock::wallclock->get_current_time();
446
447 #elif defined(CYGINT_ISO_POSIX_TIMERS)
448
449     // If POSIX is present, use the current value of the realtime
450     // clock.
451     
452     struct timespec tp;
453
454     clock_gettime( CLOCK_REALTIME, &tp );
455
456     return (time_t) tp.tv_sec;
457     
458 #elif defined(CYGPKG_KERNEL) 
459
460     // If all else fails, get the current realtime clock value and
461     // convert it to seconds ourself.
462     
463     static struct Cyg_Clock::converter sec_converter;
464     static cyg_bool initialized = false;
465     cyg_tick_count ticks;
466     
467     if( !initialized )
468     {
469         Cyg_Clock::real_time_clock->get_clock_to_other_converter( 1000000000, &sec_converter );
470         initialized = true;
471     }
472
473     ticks = Cyg_Clock::real_time_clock->current_value();
474     
475     return (time_t) Cyg_Clock::convert( ticks, &sec_converter );
476 #else    
477     /* No clock support at all. */
478     return (time_t) 0;
479 #endif    
480     
481 }
482
483 //==========================================================================
484 // Default functions
485
486 __externC int cyg_fileio_enosys() { return ENOSYS; }
487 __externC int cyg_fileio_erofs() { return EROFS; }
488 __externC int cyg_fileio_enoerr() { return ENOERR; }
489 __externC int cyg_fileio_enotdir() { return ENOTDIR; }
490
491 __externC cyg_bool cyg_fileio_seltrue (struct CYG_FILE_TAG *fp, int which, CYG_ADDRWORD info)
492 { return 1; }
493
494 // -------------------------------------------------------------------------
495 // EOF misc.cxx