bool ParzeLink( FSPath& path, FSString& link ) { FSPath t( link ); if ( !path.IsAbsolute() && !t.IsAbsolute() ) { return false; } //не абсолютный путь int first = 0; if ( t.IsAbsolute() ) { path.Clear(); path.PushStr( FSString( "" ) ); first = 1; } for ( int i = first; i < t.Count(); i++ ) { FSString p = *( t.GetItem( i ) ); if ( p.IsDot() ) { continue; } if ( p.Is2Dot() ) { if ( path.Count() > 1 ) { path.Pop(); } } else { path.PushStr( p ); } } return true; }
void OperRDThread::Run() { if ( !fs.Ptr() ) { return; } int n = 8; int ret_err; int havePostponedStatError = 0; FSString postponedStrError; while ( true ) { if ( !( fs->Flags() & FS::HAVE_SYMLINK ) ) { break; } FSStat st; // if path is inaccessible, try .. path. Throw the exception later // This makes panel at least having some valid folder while ( fs->Stat( path, &st, &ret_err, Info() ) ) { havePostponedStatError = 1; postponedStrError = fs->StrError( ret_err ); if ( !path.IsAbsolute() || path.Count() <= 1 || !path.Pop() ) { throw_msg( "%s", postponedStrError.GetUtf8() ); } } // yell immediately if the path is inaccessible (orig behavior) //if (fs->Stat(path, &st, &ret_err, Info())) // throw_msg("%s", fs->StrError(ret_err).GetUtf8()); if ( !st.IsLnk() ) { break; } n--; if ( n < 0 ) { throw_msg( "too many symbolic links '%s'", path.GetUtf8() ); } path.Pop(); if ( !ParzeLink( path, st.link ) ) { throw_msg( "invalid symbolic link '%s'", path.GetUtf8() ); } } clPtr<FSList> list = new FSList; int havePostponedReadError = 0; // if directory is not readable, try .. path. Throw the exception later // "Stat" call above does not catch this: it checks only folder existence, but not accessibilly while ( fs->ReadDir( list.ptr(), path, &ret_err, Info() ) ) { havePostponedReadError = 1; postponedStrError = fs->StrError( ret_err ); if ( !path.IsAbsolute() || path.Count() <= 1 || !path.Pop() ) { throw_msg( "%s", postponedStrError.GetUtf8() ); } } // yell immediately if the dir is unreadable (orig behavior) //int ret = fs->ReadDir(list.ptr(), path, &ret_err, Info()); //if (ret) // throw_msg("%s", fs->StrError(ret_err).GetUtf8()); FSStatVfs vst; fs->StatVfs( path, &vst, &ret_err, Info() ); MutexLock lock( Node().GetMutex() ); //!!! if ( Node().NBStopped() ) { return; } OperRDData* data = ( ( OperRDData* )Node().Data() ); data->list = list; data->path = path; data->executed = true; data->vst = vst; if ( havePostponedReadError || havePostponedStatError ) { data->nonFatalErrorString = postponedStrError; } }