Add ability to optionally *not* resolve uid/gid to name, to accomodate the Linux static binary vs. nsswitch name resolution issue; add RESOLVE_IDS_TO_NAMES config option to control this feature; avoid redundant lstats when turning IDs into names, since the lstat is to fetch the ID we already have; remove a bunch of unused code in UnixFSServices

This commit is contained in:
Brian Cox 2016-11-24 17:26:02 -08:00
parent 3d304eb1af
commit f9aa5de896
6 changed files with 93 additions and 208 deletions

View File

@ -112,10 +112,10 @@ typedef int64 cFSType;
// filesystem access control lists
// it is the union of MAX(elem) for all the file systems that we support
class cACLElem {
/*class cACLElem {
// TODO this is just a place holder
// uint32 mUid;
};
};*/
// this class is used only to pass arguments to iFSServices
// it is the union of MAX(elem) for all the file systems that we support
@ -155,8 +155,8 @@ struct cFSStatArgs {
FileType mFileType; // redundant with other information in this struct, but
// broken out for convenience
// access control list should go here, too
std::list <cACLElem> mACL; // indep
//TODO: access control list should go here, too
//std::list <cACLElem> mACL; // indep
};
@ -252,16 +252,6 @@ class iFSServices
// TSTRING must have the form ("baseXXXXXX"), where the X's are replaced with
// characters to make it a unique file. There must be at least 6 Xs.
// TODO: remove this function
// Matt theorized that this is no longer used - dmb Aug 23 1999
// virtual int CreateLockedTemporaryFile( const TCHAR* szFilename, int perm ) const = 0;
// creates a temporary file to which only the current process has read or write access.
// returns an open C file descriptor on success and -1 on error. Returns error if filename already exists on the filesystem.
// the file will automatically be deleted when the file descriptor is closed.
// perm should be zero or more of:
// O_WRONLY: create with read write only permission
// O_RDWR: create with read and write permission
////////////////////////////////////////
// minor filesystem functions
@ -286,29 +276,29 @@ class iFSServices
// short names.
virtual void GetCurrentDir( TSTRING& strCurDir ) const throw( eFSServices ) = 0;
// returns the current working directory
virtual void ChangeDir( const TSTRING& strName ) const throw( eFSServices ) = 0;
// sets the current working directory
virtual void Mkdir( const TSTRING& strName ) const throw( eFSServices ) = 0;
virtual bool Rmdir( const TSTRING& strName ) const = 0;
////////////////////////////////////////
// file specific functions
////////////////////////////////////////
virtual bool FileDelete( const TSTRING& name ) const = 0;
////////////////////////////////////////
// directory and file functions
////////////////////////////////////////
virtual bool Rename( const TSTRING& strOldName, const TSTRING& strNewName, bool fOverWrite = true ) const = 0;
// rename a file
virtual bool GetOwnerForFile( const TSTRING& tstrFilename, TSTRING& tstrUser ) const = 0;
virtual bool GetGroupForFile( const TSTRING& tstrFilename, TSTRING& tstrGroup ) const = 0;
virtual bool GetUserName( uid_t user_id, TSTRING& tstrUser ) const = 0;
virtual bool GetGroupName( gid_t group_id, TSTRING& tstrGroup ) const = 0;
//Set whether we try to resolve uid/gid to a name, since Linux static binaries can
//have trouble (read: segfaulting) with name resolution given the right nsswitch.conf setup.
//This defaults to true if not specified.
virtual void SetResolveNames(bool resolve)=0;
////////////////////////////////////////
// miscellaneous utility functions
////////////////////////////////////////
@ -347,44 +337,6 @@ class iFSServices
///////////////////////////////////////////////////////////////
private:
static iFSServices* mpInstance;
//virtual cFSStatArgs::FileType GetFileType(const cFCOName &filename) throw(eFSServices) = 0;
// returns the type of the file specified by filename. Separated from Stat() for convenience
// and potential efficiency (if a file system doesn't need to do a stat to get the file type)
//virtual char*& MakeTempFile( char*& name) throw(eFSServices) = 0;
//virtual wchar_t*& MakeTempFile( wchar_t*& name) throw(eFSServices) = 0;
//
// file ops
//
// these are commented out for timeliness reasons; we should uncomment and implement as needed...
// -- mdb
/*
virtual int Create(cFSName &name, Mode mode = MODE_DEFAULT) = 0;
virtual bool Mkdir(cFSName &name, Mode mode = MODE_DEFAULT) = 0;
virtual bool Delete(cFSName &name) = 0;
virtual bool Link(cFSName &src, cFSName &dest) = 0;
virtual bool Chmod(cFSName &name, Mode mode) = 0;
virtual Mode Umask(Mode mode) = 0;
// file system types (e.g., "FAT", "NTFS", "UFS", "NFS")
virtual bool FSTypeAsString(cFSName &name, TSTRING &str) = 0;
// file type (e.g., "file", "symbolic link", "block device")
// TODO -- this should either be static or in another utility class, since it does not rely on the
// instance of the class (there is a global enumeration of file types; this fn should take a
// cFSStatArgs::FileType instead of a name.
virtual bool FileTypeAsString(cFSName &filename, TSTRING &str) = 0;
// TODO -- does this beling here? Is it always true that st_dev defines the file system? If not, then the
// Stat() call should add some extra piece of data that identifies the file system.
virtual bool IsSameFileSystem(cFSStatArgs &file1, cFSStatArgs &file2) = 0;
// to determine whether to recurse - musn't traverse mount points
// capabilities
virtual bool IsUnicodeFilename(cFSName &name) = 0;
virtual bool IsACLCapable(cFSName &name) = 0;
virtual bool Is8bitFilename(cFSName &name) = 0;
*/
};

View File

@ -138,7 +138,7 @@ template< typename T > static inline void util_ZeroMemory( T& obj );
// PUBLIC METHOD CODE
//=========================================================================
cUnixFSServices::cUnixFSServices()
cUnixFSServices::cUnixFSServices() : mResolveNames(true)
{}
cUnixFSServices::~cUnixFSServices()
@ -257,12 +257,6 @@ void cUnixFSServices::GetCurrentDir( TSTRING& strCurDir ) const throw(eFSService
strCurDir = pathname;
}
void cUnixFSServices::ChangeDir( const TSTRING& strDir ) const throw(eFSServices)
{
if( chdir( strDir.c_str() ) < 0 )
throw eFSServicesGeneric( strDir, iFSServices::GetInstance()->GetErrString() );
}
TSTRING& cUnixFSServices::MakeTempFilename( TSTRING& strName ) const throw(eFSServices)
{
@ -296,29 +290,11 @@ TSTRING& cUnixFSServices::MakeTempFilename( TSTRING& strName ) const throw(eFSSe
// Linux creates the file!! Doh!
// So I'll always attempt to delete it -bam
FileDelete( strName );
FileDelete( strName.c_str() );
return( strName );
}
void cUnixFSServices::Mkdir( const TSTRING& strName ) const throw ( eFSServices )
{
if( 0 != _tmkdir( strName.c_str(), 0777 ) )
{
// if mkdir failed because the dir existed, that's OK
if( errno != EEXIST )
throw eFSServicesGeneric( strName, iFSServices::GetInstance()->GetErrString() );
}
}
bool cUnixFSServices::Rmdir( const TSTRING& strName ) const
{
if( 0 == rmdir( strName.c_str() ) )
return true;
return false;
}
void cUnixFSServices::GetTempDirName( TSTRING& strName ) const throw(eFSServices)
{
strName = mTempPath;
@ -516,35 +492,27 @@ bool cUnixFSServices::IsCaseSensitive() const
}
void cUnixFSServices::SetResolveNames(bool resolve)
{
mResolveNames=resolve;
}
bool cUnixFSServices::GetOwnerForFile( const TSTRING& tstrFilename, TSTRING& tstrUser ) const
{
bool fSuccess = true;
struct stat statbuf;
int ret = lstat(tstrFilename.c_str(), &statbuf);
if(ret < 0)
{
fSuccess = false;
}
if( fSuccess )
else
{
struct passwd* pp = getpwuid( statbuf.st_uid );
//ASSERT( pp );
// We shouldn't assert this, because it might be the case that a file
// is associated with some old user that no longer exists... we should
// not fail this case. Instead, the method will just return false per
// the test below.
if( pp == NULL )
{
fSuccess = false;
}
else
tstrUser = pp->pw_name;
fSuccess = GetUserName(statbuf.st_uid, tstrUser);
}
return( fSuccess );
}
@ -558,12 +526,48 @@ bool cUnixFSServices::GetGroupForFile( const TSTRING& tstrFilename, TSTRING& tst
{
fSuccess = false;
}
if( fSuccess )
else
{
struct group* pg = getgrgid( statbuf.st_gid );
//ASSERT( pg ); this assert stops everything in debug mode if we can't lookup a groupid
fSuccess = GetGroupName(statbuf.st_gid, tstrGroup);
}
return( fSuccess );
}
bool cUnixFSServices::GetUserName( uid_t user_id, TSTRING& tstrUser ) const
{
bool fSuccess = true;
if( mResolveNames )
{
struct passwd* pp = getpwuid( user_id );
if( pp == NULL )
{
fSuccess = false;
tstrUser = TSS_GetString(cCore, core::STR_UNKNOWN);
}
else
tstrUser = pp->pw_name;
}
else
{
std::stringstream sstr;
sstr << user_id;
tstrUser = sstr.str();
}
return( fSuccess );
}
bool cUnixFSServices::GetGroupName( gid_t group_id, TSTRING& tstrGroup ) const
{
bool fSuccess = true;
if( mResolveNames )
{
struct group* pg = getgrgid( group_id );
if( pg == NULL )
{
fSuccess = false;
@ -571,11 +575,19 @@ bool cUnixFSServices::GetGroupForFile( const TSTRING& tstrFilename, TSTRING& tst
}
else
tstrGroup = pg->gr_name;
}
}
else
{
std::stringstream sstr;
sstr << group_id;
tstrGroup = sstr.str();
}
return( fSuccess );
}
#ifndef S_ISVTX // DOS/DJGPP doesn't have this
# define S_ISVTX 0
#endif
@ -750,7 +762,7 @@ bool cUnixFSServices::GetExecutableFilename( TSTRING& strFullPath, const TSTRING
// a bool? I think it is ... mdb
///////////////////////////////////////////////////////////////////////////////
bool cUnixFSServices::FullPath( TSTRING& strFullPath, const TSTRING& strRelPathC, const TSTRING& pathRelFromC ) const
{
{
// don't do anything with an empty path
if( strRelPathC.empty() )
return false;
@ -843,39 +855,6 @@ const TCHAR* cUnixFSServices::GetStandardBackupExtension() const
}
// TODO: remove this function
// Matt theorized that this is no longer used - dmb Aug 23 1999
/*
int cUnixFSServices::CreateLockedTemporaryFile( const TCHAR* szFilename, int perm ) const
{
// make sure perm is AT LEAST one of: O_RDWR, O_WRONLY
ASSERT( 0 != ( perm & ( O_RDWR | O_WRONLY ) ) );
// make sure perm is ONLY composed of: O_RDWR, O_WRONLY
ASSERT( 0 == ( perm & ~( O_RDWR | O_WRONLY ) ) );
// get rid of any unsupported bits caller may have supplied
perm &= ( O_RDWR | O_WRONLY );
// set flags
int oflags = perm |
O_CREAT | O_EXCL; // only create a new file -- error if it exists already
// create file
int fh = _topen( szFilename, oflags, 0666 );
if( fh >= 0 )
{
// file was created. Now unlink it
if( 0 != unlink( szFilename ) )
{
// we weren't able to unlink file, so close handle and fail
close( fh );
fh = -1;
}
}
return( fh );
}
*/
void cUnixFSServices::Sleep( int nSeconds ) const
{
sleep( nSeconds );

View File

@ -54,38 +54,8 @@
// DECLARATION OF CLASSES
//=========================================================================
//Set up in constructor. Stores pertinent information about the filesystem
//serviced by each instantiation.
struct UnixSysInfo
{
uint32 maxcomplen;
//max name length of a file on filesystem
uint32 fsflags;
//bitmask of flags
TSTRING fsname;
//The filesystem basename
uint32 fsid;
//unique indentifier for the filesystem
};
class cUnixFSServices : public iFSServices
{
///////////////////////////////////////////////////////////////
// ENUMS
///////////////////////////////////////////////////////////////
////////////////////////////////////////
// file system types
////////////////////////////////////////
enum FSType
{
FS_UFS = 0,
FS_NFS,
FS_HSFS,
FS_PCFS
};
///////////////////////////////////////////////////////////////
// MEMBER FUNCTIONS
///////////////////////////////////////////////////////////////
@ -127,10 +97,6 @@ class cUnixFSServices : public iFSServices
// strName must have the form ("baseXXXXXX"), where the X's are replaced with
// characters to make it a unique file. There must be at least 6 Xs.
// TODO: remove this function
// Matt theorized that this is no longer used - dmb Aug 23 1999
//virtual int CreateLockedTemporaryFile( const TCHAR* szFilename, int perm ) const;
////////////////////////////////////////
// minor filesystem functions
@ -153,29 +119,29 @@ class cUnixFSServices : public iFSServices
// puts the contents of the specified directory, except for . and .., into the supplied vector.
virtual void GetCurrentDir( TSTRING& strCurDir ) const throw( eFSServices );
// returns the current working directory
virtual void ChangeDir( const TSTRING& strName ) const throw( eFSServices );
// sets the current working directory
virtual void Mkdir( const TSTRING& strName ) const throw( eFSServices );
virtual bool Rmdir( const TSTRING& strName ) const;
////////////////////////////////////////
// file specific functions
////////////////////////////////////////
virtual bool FileDelete( const TSTRING& name ) const;
////////////////////////////////////////
// directory and file functions
////////////////////////////////////////
virtual bool Rename( const TSTRING& strOldName, const TSTRING& strNewName, bool fOverWrite = true ) const;
// rename a file
virtual bool GetOwnerForFile( const TSTRING& tstrFilename, TSTRING& tstrUser ) const;
virtual bool GetGroupForFile( const TSTRING& tstrFilename, TSTRING& tstrGroup ) const;
virtual bool GetUserName( uid_t user_id, TSTRING& tstrUser ) const;
virtual bool GetGroupName( gid_t group_id, TSTRING& tstrGroup ) const;
//Set whether we try to resolve uid/gid to a name, since Linux static binaries can
//have trouble (read: segfaulting) with name resolution given the right nsswitch.conf setup.
//This defaults to true if not specified.
virtual void SetResolveNames(bool resolve);
////////////////////////////////////////
// miscellaneous utility functions
////////////////////////////////////////
@ -195,11 +161,9 @@ class cUnixFSServices : public iFSServices
virtual TSTRING GetErrString() const;
private:
UnixSysInfo info;
//struct stores pertinent system info. to be used by member functions
TSTRING mTempPath;
bool mResolveNames;
};
#endif //__UNIXFSSERVICES_H

View File

@ -270,7 +270,7 @@ void cFSPropDisplayer::InitForProp( const iFCO* const pFCO, const int propIdx)
if( ! GetUsername( i64UID, tstrDummy ) )
{
TSTRING tstrUsername;
if( iFSServices::GetInstance()->GetOwnerForFile( pFCO->GetName().AsString(), tstrUsername ) )
if( iFSServices::GetInstance()->GetUserName( i64UID, tstrUsername ) )
AddUsernameMapping ( i64UID, tstrUsername );
else
AddUsernameMapping ( i64UID, _T("") ); // on failure, enter error value into mapping so we don't search for this value again.
@ -286,7 +286,7 @@ void cFSPropDisplayer::InitForProp( const iFCO* const pFCO, const int propIdx)
if( ! GetGroupname( i64GID, tstrDummy ) )
{
TSTRING tstrGroupname;
if( iFSServices::GetInstance()->GetGroupForFile( pFCO->GetName().AsString(), tstrGroupname ) )
if( iFSServices::GetInstance()->GetGroupName( i64GID, tstrGroupname ) )
AddGroupnameMapping( i64GID, tstrGroupname );
else
AddGroupnameMapping( i64GID, _T("") ); // on failure, enter error value into mapping so we don't search for this value again.

View File

@ -455,7 +455,14 @@ static void FillOutConfigInfo(cTWModeCommon* pModeInfo, const cConfigFile& cf)
#else
throw eTWDirectIONotSupported();
#endif
}
if(cf.Lookup(TSTRING(_T("RESOLVE_IDS_TO_NAMES")), str))
{
if (_tcsicmp(str.c_str(), _T("true")) == 0)
iFSServices::GetInstance()->SetResolveNames(true);
else
iFSServices::GetInstance()->SetResolveNames(false);
}
//

View File

@ -119,23 +119,6 @@ void TestUnixFSServices()
d.TraceDetail("Testing MakeTempFilename: \n");
d.TraceDetail("%s \n", _template.c_str() );
//Test ChangeDir
d.TraceDetail("Testing ChangeDir: (should be /usr)\n");
TSTRING newdir(_T("/usr"));
pFSServices->ChangeDir(newdir);
pFSServices->GetCurrentDir(currpath);
d.TraceDetail("%s \n", currpath.c_str() );
//Did we get there??
//Test Mkdir:
d.TraceDetail("Testing Mkdir: \n");
TSTRING makedir(_T("/tmp/tw_mkdir"));
pFSServices->Mkdir(makedir); // throws on error
//Test Rmdir
d.TraceDetail("Testing Rmdir:\n");
TEST( pFSServices->Rmdir(makedir) );
// Test GetMachineName
d.TraceDetail("Testing GetMachineName:\n");
TSTRING uname;