# HG changeset patch # User asl # Date 1140115566 0 # Node ID 8eb72dcf503acb3b3ba31bb70d3935cd6c4ea346 # Parent 06a1f8221912582c879d1e4b2bc32ca74b43ceab * src/misc.cxx (cyg_mtab_lookup): Corrected implementation for relative paths crossing mount points. * tests/fileio1.c (cyg_user_start): Add a test for the above fix. diff --git a/packages/io/fileio/current/ChangeLog b/packages/io/fileio/current/ChangeLog --- a/packages/io/fileio/current/ChangeLog +++ b/packages/io/fileio/current/ChangeLog @@ -1,3 +1,9 @@ +2006-02-16 Peter Korsgaard + + * src/misc.cxx (cyg_mtab_lookup): Corrected implementation for + relative paths crossing mount points. + * tests/fileio1.c (cyg_user_start): Add a test for the above fix. + 2005-10-20 Andrew Lunn * src/select.cxx: Needs sys/time.h for struct timeval. diff --git a/packages/io/fileio/current/src/misc.cxx b/packages/io/fileio/current/src/misc.cxx --- a/packages/io/fileio/current/src/misc.cxx +++ b/packages/io/fileio/current/src/misc.cxx @@ -222,6 +222,16 @@ static int matchlen( const char *s1, con } // ------------------------------------------------------------------------- +// Simple strlen implementation + +static int my_strlen(const char *c) +{ + int l = 0; + while (*c++) l++; + return l; +} + +// ------------------------------------------------------------------------- // Search the mtab for the entry that matches the longest substring of // **name. @@ -230,35 +240,64 @@ static int matchlen( const char *s1, con cyg_mtab_entry *m, *best = NULL; int best_len = 0; - // Unrooted file names go straight to current dir + // Unrooted file names start from current dir if( **name != '/' ) { + int cwd_len; if (*mte == (cyg_mtab_entry *)NULL) { // No known current directory return -1; } - // Current directory is well known - return 0; + + best = *mte; + cwd_len = my_strlen((*mte)->name); + + // current dir is not the correct mte if the relative path crosses + // mount points - search for best matching mount point + for( m = &cyg_mtab[0]; m != &cyg_mtab_end; m++ ) + { + if( m->name != NULL && m->valid ) + { + int len = matchlen(m->name, (*mte)->name); + // mount point under cwd? + if (len == cwd_len) + { + if (m->name[len] == '/') + len++; + + len = matchlen(*name, &m->name[len]); + if (len > best_len) + best = m, best_len = len; + } + } + } + + // did we find a better match? + if (best != *mte) + *dir = best->root; + } + else + { + // Otherwise search the mount table. + for( m = &cyg_mtab[0]; m != &cyg_mtab_end; m++ ) + { + if( m->name != NULL && m->valid ) + { + int len = matchlen(*name,m->name); + if( len > best_len ) + best = m, best_len = len; + } + } + + // No match found, bad path name... + if( best_len == 0 ) return -1; + + *dir = best->root; } - // Otherwise search the mount table. - for( m = &cyg_mtab[0]; m != &cyg_mtab_end; m++ ) - { - if( m->name != NULL && m->valid ) - { - int len = matchlen(*name,m->name); - if( len > best_len ) - best = m, best_len = len; - } - } - - // No match found, bad path name... - if( best_len == 0 ) return -1; - *name += best_len; if( **name == '/' ) (*name)++; *mte = best; - *dir = best->root; return 0; } diff --git a/packages/io/fileio/current/tests/fileio1.c b/packages/io/fileio/current/tests/fileio1.c --- a/packages/io/fileio/current/tests/fileio1.c +++ b/packages/io/fileio/current/tests/fileio1.c @@ -422,6 +422,8 @@ int cyg_user_start(void) checkfile( "/ram/tinky"); checkfile( "/ram/laalaa"); comparefiles( "/ram/tinky", "/ram/laalaa" ); + comparefiles( "/ram/tinky", "ram/laalaa" ); + comparefiles( "ram/tinky", "/ram/laalaa" ); err = chdir( "/ram" ); if( err < 0 ) SHOW_RESULT( chdir, err );