📄 wy__dirhandle.cpp
字号:
#define WYLIB_SOURCE#include "wy__dirhandle.h"#include "wysysfile.h" // for WySysFile::wy_close(int)#include "wy_atdestroy.h"#include <sys/stat.h>#include <fcntl.h>const char Wy__DirHandEnt::DirNameOfEmpty[]="./";WyRet Wy__DirHandEnt::_reset(void){ if(_rcnt<=0) { return(Ok); } Wy__Base::cancel_point(); Wy__Base::NoCancel noc; _rcnt=0; if(::closedir(_dirp)!=0) { const int en=errno; WySysFile::wy_close(_fd); // errno ignored, for already had one if((en==EBADF)||(en==0)) { // closedir(_dirp) error should not return this WY_THROW( WyRet(WyReply(en)) ); } WY_RETURN(WyReply(en)); } while(::close(_fd)!=0) { const int en=errno; if((en==EINTR)||(en==EAGAIN)) { } else { if((en==EBADF)||(en==0)) { // error should not return this // should not return this WY_THROW( WyRet(WyReply(en)) ); } WY_RETURN(WyReply(en)); } }; return(Ok);};Wy__DirHandEnt::Wy__DirHandEnt(const Wy__DirHandEnt& src) WY__TSPC(){ _rcnt=0; if(src._rcnt!=0) { // src only supposed to be default WY_TERMINATE(""); }};WyRet Wy__DirHandEnt::open(const char* dirname){ if(_rcnt>0) { WY_RETURN(Wym_EACCES); // added by library, app should avoid this } if(dirname==0) { WY_RETURN(Wym_EFAULT); } Wy__Base::cancel_point(); Wy__Base::NoCancel noc; _dirp=NULL; _fd=WY__DEFAULT_FD; try { // open _dirp _dirp=::opendir((*dirname==0)? DirNameOfEmpty:dirname); if(_dirp==NULL) { if(errno==0) { WY_THROW( WyRet(WyReply(errno)) ); } WY_RETURN(errno); } // open _fd _fd=::open((*dirname==0)? DirNameOfEmpty:dirname,O_RDONLY|O_DIRECTORY); if(_fd<0) { ::closedir(_dirp); WY_RETURN(errno); } } catch(const WyRet& e) { if(_dirp!=NULL) { ::closedir(_dirp); } if(_fd>=0) { WySysFile::wy_close(_fd); // errno ignored, for already had one } _rcnt=0; throw; }; _rcnt=1; return(Ok);};WyRet Wy__DirHandEnt::check_in(void) WY__TSPC(){ if(_rcnt<=0) { return(Wym_ENOENT); } if(_rcnt>=std::numeric_limits<size_t>::max()) { return(Wym_ENFILE); } ++_rcnt; return(Ok);};WyRet Wy__DirHandEnt::check_out(void) WY__TSPC(){ if(_rcnt<=1) { if(_rcnt==0) { WY_RETURN(Wym_ENOENT); } WY_RETURN( _reset() ); // reset will zero the count } --_rcnt; return(Ok);};//--------------------------------------------------------------------const char Wy__DirHandle::class_name[]="Wy__DirHandle";Wy_Array<Wy__DirHandEnt> Wy__DirHandle::wy_tab(8,Wy__DirHandEnt());WyMutex Wy__DirHandle::wy_tab_mtx;Wy__DirHandle::Wy__DirHandle(const Wy__DirHandle& src) WY__TSPC(WyRet)try { if(src._idx==DefaultIdx) { // src is defaut _idx=DefaultIdx; return; } WyLock aa(wy_tab_mtx); _idx=src._idx; if(_idx>=int(wy_tab.size())) { WY_THROW(WyRet()); // src._idx out of range } const WyRet r=wy_tab[_idx].check_in(); if(r!=Ok) { if(r==Wym_ENFILE) { WY_THROW( Reply(r) ); // only this possible } WY_THROW(WyRet()); }}catch(const WyLock::Reply& e) { WY_THROW( WyRet(e) );}catch(const Wy__DirHandle::Reply&) { throw;}catch(const WyRet& e) { WY_THROW(WyRet(e));}catch(...) { WY_THROW(WyRet());};Wy__DirHandle::~Wy__DirHandle() WY__TSPC()try { if(_idx==DefaultIdx) { return; } WyLock aa(wy_tab_mtx); if(_idx>=int(wy_tab.size())) { WY_TERMINATE(""); // _idx out of range } wy_tab[_idx].check_out(); // error ignored}catch(const WyLock::Reply& e) { WY_TERMINATE("");}catch(...) { WY_TERMINATE("");};WyFileHandle Wy__DirHandle::fh(void) const WY__NOTHROW__try { if(_idx==DefaultIdx) { return WyFileHandle(); } WyLock aa(wy_tab_mtx); if(_idx>=int(wy_tab.size())) { // _idx out of range WY_THROW( WyRet(Wym_ERANGE) ); } return WyFileHandle(wy_tab[_idx].fd());}catch(const WyLock::Reply& e) { WY_THROW( WyRet(e) );}catch(...) { WY_TERMINATE("");};WyRet Wy__DirHandle::fstat(WyFileStat& filestat) consttry { if(_idx==DefaultIdx) { WY_RETURN(Wym_EBADF); } WyLock aa(wy_tab_mtx); if(_idx>=int(wy_tab.size())) { // _idx out of range WY_THROW( WyRet(Wym_ERANGE) ); } if(::fstat(wy_tab[_idx].fd(),filestat.wy_stat_ptr())!=0) { if(errno==0) { WY_THROW( WyRet(WyReply(errno)) ); } WY_RETURN(errno); } return(Ok);}catch(const WyLock::Reply& e) { WY_THROW( WyRet(e) );}catch(...) { std::unexpected();};WyRet Wy__DirHandle::reset(void)try { if(_idx==DefaultIdx) { return(Ok); } WyLock aa(wy_tab_mtx); if(_idx>=int(wy_tab.size())) { // _idx out of range WY_THROW( WyRet(Wym_ERANGE) ); } WyRet r=wy_tab[_idx].check_out(); _idx=DefaultIdx; WY_RETURN(r);}catch(const WyLock::Reply& e) { WY_THROW( WyRet(e) );};WyRet Wy__DirHandle::read(WyDirEnt& dirent)try { if(_idx==DefaultIdx) { WY_RETURN(Wym_EBADF); } WyLock aa(wy_tab_mtx); if(_idx>=int(wy_tab.size())) { // _idx out of range WY_THROW( WyRet(Wym_ERANGE) ); } Wy__Base::cancel_point(); Wy__Base::NoCancel noc; struct ::dirent* ptr=dirent.wy_dent_ptr(); const int v=::readdir_r(wy_tab[_idx].dirp(),ptr,&ptr); if(v!=0) { if(v==EBADF) { // should not get this WY_THROW( WyRet(Wym_EBADF) ); } WY_RETURN(WyReply(v)); } if(ptr==NULL) { // end of directory dirent.reset(); } return(Ok);}catch(const WyLock::Reply& e) { WY_THROW( WyRet(e) );};WyRet Wy__DirHandle::rewind(void)try { if(_idx==DefaultIdx) { WY_RETURN(Wym_EBADF); } WyLock aa(wy_tab_mtx); if(_idx>=int(wy_tab.size())) { // _idx out of range WY_THROW( WyRet(Wym_ERANGE) ); } Wy__Base::NoCancel noc; ::rewinddir(wy_tab[_idx].dirp()); return(Ok);}catch(const WyLock::Reply& e) { WY_THROW( WyRet(e) );};WyRet Wy__DirHandle::open(const char* pathname)try { if(_idx!=DefaultIdx) { WY_RETURN(Wym_EACCES); } WyLock aa(wy_tab_mtx); // // Locate an empty entry of wy_tab (from 0) // size_t nidx; for(nidx=0; nidx<wy_tab.size(); ++nidx) { if(wy_tab[nidx].is_default()) { break; } } if(nidx>=wy_tab.size()) { wy_tab.push_back(Wy__DirHandEnt()); // push a default entry and use it } // // Open the entry wy_tab[_idx]; // const WyRet r=wy_tab[nidx].open(pathname); if(r!=Ok) { WY_RETURN(r); } _idx=nidx; return(Ok);}catch(const WyStr::Reply& e) { WY_RETURN(e);}catch(const WyLock::Reply& e) { WY_THROW( WyRet(e) );}catch(const WyRet& e) { WY_THROW( WyRet(e) );}catch(const std::exception&) { WY_THROW( WyRet() );};WyRet Wy__DirHandle::open(const WyStr& pathname){ WY_RETURN( this->open(pathname.c_str()) );};WyRet Wy__DirHandle::reset(const Wy__DirHandle& src)try { if(&src==this) { return(Ok); } if(_idx!=DefaultIdx) { WY_RETURN(Wym_EACCES); } if(src._idx==DefaultIdx) { // src is defaut _idx=DefaultIdx; return(Ok); } WyLock aa(wy_tab_mtx); const int ridx=src._idx; if(ridx>=int(wy_tab.size())) { // src._idx out of range WY_THROW( WyRet(Wym_ERANGE) ); } WyRet r=wy_tab[ridx].check_in(); if(r!=Ok) { if(r==Wym_ENFILE) { WY_RETURN(r); // only this possible } WY_THROW(r); } _idx=ridx; return(Ok);}catch(const WyLock::Reply& e) { WY_THROW( WyRet(e) );};size_t Wy__DirHandle::ref_count(void) consttry { if(_idx==DefaultIdx) { return(0); } WyLock aa(wy_tab_mtx); if(_idx>=int(wy_tab.size())) { WY_THROW( WyRet() ); // _idx out of range } return(wy_tab[_idx].ref_count());}catch(const WyLock::Reply& e) { WY_THROW( WyRet(e) );}catch(const WyRet& e) { WY_THROW( WyRet(e) );};
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -