513 lines
17 KiB
C++
513 lines
17 KiB
C++
//
|
|
// The developer of the original code and/or files is Tripwire, Inc.
|
|
// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire,
|
|
// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights
|
|
// reserved.
|
|
//
|
|
// This program is free software. The contents of this file are subject
|
|
// to the terms of the GNU General Public License as published by the
|
|
// Free Software Foundation; either version 2 of the License, or (at your
|
|
// option) any later version. You may redistribute it and/or modify it
|
|
// only in compliance with the GNU General Public License.
|
|
//
|
|
// This program is distributed in the hope that it will be useful.
|
|
// However, this program is distributed AS-IS WITHOUT ANY
|
|
// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS
|
|
// FOR A PARTICULAR PURPOSE. Please see the GNU General Public License
|
|
// for more details.
|
|
//
|
|
// You should have received a copy of the GNU General Public License
|
|
// along with this program; if not, write to the Free Software
|
|
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
|
|
// USA.
|
|
//
|
|
// Nothing in the GNU General Public License or any other license to use
|
|
// the code or files shall permit you to use Tripwire's trademarks,
|
|
// service marks, or other intellectual property without Tripwire's
|
|
// prior written consent.
|
|
//
|
|
// If you have any questions, please contact Tripwire, Inc. at either
|
|
// info@tripwire.org or www.tripwire.org.
|
|
//
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
// fspropdisplayer.cpp
|
|
//
|
|
|
|
#include "stdfs.h"
|
|
|
|
//=========================================================================
|
|
// INCLUDES
|
|
//=========================================================================
|
|
|
|
#include "fspropdisplayer.h"
|
|
#include "fspropset.h"
|
|
#include "core/fsservices.h"
|
|
#include "core/serializer.h"
|
|
#include "core/timeconvert.h"
|
|
#include "fco/fconame.h"
|
|
#include "fco/fco.h"
|
|
#include "core/twlocale.h"
|
|
#include "core/displayencoder.h"
|
|
#include "fco/fcoundefprop.h"
|
|
#include "core/errorutil.h"
|
|
|
|
//=========================================================================
|
|
// STANDARD LIBRARY INCLUDES
|
|
//=========================================================================
|
|
|
|
#include <iomanip>
|
|
|
|
//=========================================================================
|
|
// DEFINES AND MACROS
|
|
//=========================================================================
|
|
|
|
//=========================================================================
|
|
// OTHER DIRECTIVES
|
|
//=========================================================================
|
|
|
|
#if !IS_AIX
|
|
// For some stupid linker reason, this object does not get constructed under
|
|
// AIX. The cheap fix is to move this call to fs.cpp.
|
|
IMPLEMENT_TYPEDSERIALIZABLE( cFSPropDisplayer, _T("FSPropDisplayer"), 0, 1 );
|
|
#endif
|
|
|
|
//=========================================================================
|
|
// GLOBALS
|
|
//=========================================================================
|
|
|
|
//=========================================================================
|
|
// UTIL FUNCTION PROTOTYES
|
|
//=========================================================================
|
|
|
|
//=========================================================================
|
|
// METHOD CODE
|
|
//=========================================================================
|
|
|
|
cFSPropDisplayer::cFSPropDisplayer()
|
|
: mbLazy( false )
|
|
{
|
|
mpvPropsWeDisplay.AddItemAndGrow( cFSPropSet::PROP_UID );
|
|
mpvPropsWeDisplay.AddItemAndGrow( cFSPropSet::PROP_GID );
|
|
mpvPropsWeDisplay.AddItemAndGrow( cFSPropSet::PROP_ATIME );
|
|
mpvPropsWeDisplay.AddItemAndGrow( cFSPropSet::PROP_MTIME );
|
|
mpvPropsWeDisplay.AddItemAndGrow( cFSPropSet::PROP_CTIME );
|
|
mpvPropsWeDisplay.AddItemAndGrow( cFSPropSet::PROP_MODE );
|
|
|
|
mpvPropsWeDisplay.AddItemAndGrow( cFSPropSet::PROP_BLOCK_SIZE );
|
|
mpvPropsWeDisplay.AddItemAndGrow( cFSPropSet::PROP_BLOCKS );
|
|
mpvPropsWeDisplay.AddItemAndGrow( cFSPropSet::PROP_SIZE );
|
|
mpvPropsWeDisplay.AddItemAndGrow( cFSPropSet::PROP_NLINK );
|
|
}
|
|
|
|
iFCOPropDisplayer* cFSPropDisplayer::Clone() const
|
|
{
|
|
iFCOPropDisplayer* pNew = new cFSPropDisplayer;
|
|
pNew->Merge( this );
|
|
return pNew;
|
|
}
|
|
|
|
bool cFSPropDisplayer::IsMultiLineProp( int propID ) const
|
|
{
|
|
// no FS props are multiline
|
|
return false;
|
|
}
|
|
|
|
cFSPropDisplayer::~cFSPropDisplayer()
|
|
{
|
|
cDebug d("~cFSPropDisplayer");
|
|
d.TraceNever( "Destructor called on object %x\n", (ptr_size_type)this);
|
|
}
|
|
|
|
const cFCOPropVector& cFSPropDisplayer::GetPropsConverted() const
|
|
{
|
|
return mpvPropsWeDisplay;
|
|
}
|
|
|
|
void cFSPropDisplayer::SetLazy( const bool bLazy /* = true */ )
|
|
{
|
|
mbLazy = bLazy;
|
|
}
|
|
|
|
bool cFSPropDisplayer::GetLazy() const
|
|
{
|
|
return mbLazy;
|
|
}
|
|
|
|
// adds all prop display info from rhs to this
|
|
void cFSPropDisplayer::Merge( const iFCOPropDisplayer* const ppd )
|
|
{
|
|
ASSERT( ppd != 0);
|
|
|
|
// should only merge two prop displayers of the same type
|
|
if( ppd->GetType() != this->GetType() )
|
|
ASSERT( false );
|
|
|
|
const cFSPropDisplayer* const pfspd = static_cast<const cFSPropDisplayer* const >( ppd );
|
|
|
|
// merge propvectors
|
|
mpvPropsWeDisplay |= pfspd->GetPropsConverted();
|
|
|
|
|
|
// merge mapping info
|
|
for( INT64_TO_STRING_MAP::const_iterator iterUID = pfspd->uidToUsername.begin();
|
|
iterUID != pfspd->uidToUsername.end();
|
|
++iterUID
|
|
)
|
|
{
|
|
AddUsernameMapping( iterUID->first, iterUID->second );
|
|
}
|
|
|
|
for( INT64_TO_STRING_MAP::const_iterator iterGID = pfspd->gidToGroupname.begin();
|
|
iterGID != pfspd->gidToGroupname.end();
|
|
++iterGID
|
|
)
|
|
{
|
|
AddGroupnameMapping( iterGID->first, iterGID->second );
|
|
}
|
|
|
|
// keep lazy flag the same
|
|
}
|
|
|
|
|
|
TSTRING& cFSPropDisplayer::GetDetailsHeader( TSTRING& strBuf, int iMargin ) const
|
|
{
|
|
static cFSPropSet set;
|
|
TOSTRINGSTREAM sstr;
|
|
|
|
sstr << std::left;
|
|
sstr << _T(" ") << std::setw( PROP_MODE_WIDTH ) << set.GetPropName( cFSPropSet::PROP_MODE );
|
|
sstr << _T(" ") << std::setw( PROP_OWNER_WIDTH ) << set.GetPropName( cFSPropSet::PROP_UID );
|
|
sstr << _T(" ") << std::setw( PROP_SIZE_WIDTH ) << set.GetPropName( cFSPropSet::PROP_SIZE );
|
|
sstr << _T(" ") << std::setw( PROP_MTIME_WIDTH ) << set.GetPropName( cFSPropSet::PROP_MTIME );
|
|
sstr << _T("\n");
|
|
for( int i = 0; i < iMargin; i++ )
|
|
sstr << _T(" ");
|
|
sstr << _T(" ") << std::setw( PROP_MODE_WIDTH ) << _T("------");
|
|
sstr << _T(" ") << std::setw( PROP_OWNER_WIDTH ) << _T("----------");
|
|
sstr << _T(" ") << std::setw( PROP_SIZE_WIDTH ) << _T("----------");
|
|
sstr << _T(" ") << std::setw( PROP_MTIME_WIDTH ) << _T("----------");
|
|
|
|
strBuf = sstr.str();
|
|
return strBuf;
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
// Function name : cFSPropDisplayer::GetDetails
|
|
// Description : takes a TSTRING and fills it with an "ls -l" representation
|
|
// of the object's permission bits ( e.g. "drwxr-x--x" ), UID,
|
|
// size, and last access time. Does not add the name of the FSO
|
|
//
|
|
// Return type : TSTRING& -- reference to input buffer
|
|
//
|
|
// Argument : TSTRING& strBuf -- buffer. GetDesription will use it to allocate space.
|
|
//
|
|
TSTRING& cFSPropDisplayer::GetDetails( const iFCO* const pfco, TSTRING& strBuf ) const
|
|
{
|
|
TOSTRINGSTREAM sstr;
|
|
const cFCOPropVector pv = pfco->GetPropSet()->GetValidVector();
|
|
|
|
sstr << std::left;
|
|
|
|
sstr << _T(" ") << std::setw( PROP_MODE_WIDTH );
|
|
if( pv.ContainsItem( cFSPropSet::PROP_MODE ) )
|
|
sstr << PropAsString( pfco, cFSPropSet::PROP_MODE ).c_str();
|
|
else
|
|
sstr << _T("XXXXXXXXX");
|
|
|
|
sstr << _T(" ") << std::setw( PROP_OWNER_WIDTH );
|
|
if( pv.ContainsItem( cFSPropSet::PROP_UID ) )
|
|
sstr << PropAsString( pfco, cFSPropSet::PROP_UID ).c_str();
|
|
else
|
|
sstr << _T("XXXXXXXXX");
|
|
|
|
sstr << _T(" ") << std::setw( PROP_SIZE_WIDTH );
|
|
if( pv.ContainsItem( cFSPropSet::PROP_SIZE ) )
|
|
sstr << PropAsString( pfco, cFSPropSet::PROP_SIZE ).c_str();
|
|
else
|
|
sstr << _T("XXX");
|
|
|
|
sstr << _T(" ") << std::setw( PROP_MTIME_WIDTH );
|
|
if( pv.ContainsItem( cFSPropSet::PROP_MTIME ) )
|
|
sstr << PropAsString( pfco, cFSPropSet::PROP_MTIME ).c_str();
|
|
else
|
|
sstr << _T("XXXXXXXXXXXXXXXXX");
|
|
|
|
strBuf = sstr.str();
|
|
return strBuf;
|
|
}
|
|
|
|
|
|
|
|
void cFSPropDisplayer::InitForFCO( const iFCO* const ifco )
|
|
{
|
|
ASSERT( ifco != 0);
|
|
|
|
cFCOPropVector v = ifco->GetPropSet()->GetValidVector();
|
|
int vSize = v.GetSize();
|
|
for( int i = 0; i < vSize; i++ )
|
|
{
|
|
if( v.ContainsItem( i ) )
|
|
{
|
|
InitForProp( ifco, i );
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
void cFSPropDisplayer::InitForProp( const iFCO* const pFCO, const int propIdx)
|
|
{
|
|
ASSERT( pFCO != 0);
|
|
|
|
switch( propIdx )
|
|
{
|
|
case cFSPropSet::PROP_UID:
|
|
{
|
|
const int64& i64UID = static_cast<const cFCOPropInt64* const>( pFCO->GetPropSet()->GetPropAt( cFSPropSet::PROP_UID ) )->GetValue();
|
|
|
|
// check if prop is in table. if it is, then don't hit the FS
|
|
TSTRING tstrDummy;
|
|
if( ! GetUsername( i64UID, tstrDummy ) )
|
|
{
|
|
TSTRING 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.
|
|
}
|
|
}
|
|
break;
|
|
case cFSPropSet::PROP_GID:
|
|
{
|
|
const int64& i64GID = static_cast<const cFCOPropInt64* const>( pFCO->GetPropSet()->GetPropAt( cFSPropSet::PROP_GID ) )->GetValue();
|
|
|
|
// check if prop is in table. if it is, then don't hit the FS
|
|
TSTRING tstrDummy;
|
|
if( ! GetGroupname( i64GID, tstrDummy ) )
|
|
{
|
|
TSTRING 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.
|
|
}
|
|
}
|
|
break;
|
|
default:
|
|
// right now nothing else needs to be done for the other props
|
|
break;
|
|
}
|
|
}
|
|
|
|
TSTRING cFSPropDisplayer::PropAsString( const iFCO* const pFCO, const int propIdx, int iOffset, int iWidth )
|
|
{
|
|
if( mpvPropsWeDisplay.ContainsItem( propIdx ) && mbLazy )
|
|
{
|
|
InitForProp( pFCO, propIdx );
|
|
}
|
|
// run the const version of PropAsString
|
|
return ((const cFSPropDisplayer*)this)->PropAsString(pFCO, propIdx, iOffset, iWidth);
|
|
}
|
|
|
|
TSTRING cFSPropDisplayer::PropAsString( const iFCO* const pFCO, const int propIdx, int iOffset, int iWidth ) const
|
|
{
|
|
TSTRING strProp = _T("");
|
|
|
|
ASSERT( pFCO != 0);
|
|
|
|
// get prop pointer
|
|
const iFCOProp* pProp = pFCO->GetPropSet()->GetPropAt( propIdx );
|
|
|
|
// if we know how to display prop
|
|
if( pProp->GetType() != cFCOUndefinedProp::GetInstance()->GetType() &&
|
|
mpvPropsWeDisplay.ContainsItem( propIdx ) )
|
|
{
|
|
switch( propIdx )
|
|
{
|
|
case cFSPropSet::PROP_BLOCK_SIZE:
|
|
case cFSPropSet::PROP_BLOCKS:
|
|
case cFSPropSet::PROP_SIZE:
|
|
case cFSPropSet::PROP_NLINK:
|
|
{
|
|
const cFCOPropInt64* const pTypedProp = static_cast<const cFCOPropInt64* const>(pProp);
|
|
cTWLocale::FormatNumber( pTypedProp->GetValue(), strProp );
|
|
}
|
|
break;
|
|
case cFSPropSet::PROP_ATIME:
|
|
case cFSPropSet::PROP_MTIME:
|
|
case cFSPropSet::PROP_CTIME:
|
|
{
|
|
const cFCOPropInt64* const pTypedProp = static_cast<const cFCOPropInt64* const>(pProp);
|
|
int64 i64 = pTypedProp->GetValue();
|
|
cTWLocale::FormatTime( i64, strProp );
|
|
}
|
|
break;
|
|
case cFSPropSet::PROP_MODE:
|
|
{
|
|
const cFCOPropUint64* const pTypedProp = static_cast<const cFCOPropUint64* const>(pProp);
|
|
ASSERT( pTypedProp != 0);
|
|
|
|
iFSServices::GetInstance()->ConvertModeToString( pTypedProp->GetValue(), strProp );
|
|
}
|
|
break;
|
|
case cFSPropSet::PROP_UID:
|
|
{
|
|
const cFCOPropInt64* const pTypedProp = static_cast<const cFCOPropInt64* const>(pProp);
|
|
ASSERT( pTypedProp != 0);
|
|
if( GetUsername( pTypedProp->GetValue(), strProp ) )
|
|
{
|
|
TSTRINGSTREAM ostr;
|
|
ostr << strProp << _T(" (") << (int32) pTypedProp->GetValue() << _T(")");
|
|
strProp = ostr.str();
|
|
}
|
|
else
|
|
strProp = pProp->AsString();
|
|
}
|
|
break;
|
|
case cFSPropSet::PROP_GID:
|
|
{
|
|
const cFCOPropInt64* const pTypedProp = static_cast<const cFCOPropInt64* const>(pProp);
|
|
ASSERT( pTypedProp != 0);
|
|
if( GetGroupname( pTypedProp->GetValue(), strProp ) )
|
|
{
|
|
TSTRINGSTREAM ostr;
|
|
ostr << strProp << _T(" (") << (int32) pTypedProp->GetValue() << _T(")");
|
|
strProp = ostr.str();
|
|
}
|
|
else
|
|
strProp = pProp->AsString();
|
|
}
|
|
break;
|
|
default:
|
|
ASSERT( false ); // mpvPropsWeDisplay should contain one of the above
|
|
break;
|
|
}
|
|
}
|
|
else // we don't know how to display prop, so let prop display itself
|
|
{
|
|
strProp = pProp->AsString();
|
|
}
|
|
|
|
return( strProp );
|
|
}
|
|
|
|
void cFSPropDisplayer::Write( iSerializer* pSerializer ) const
|
|
{
|
|
mpvPropsWeDisplay.Write( pSerializer );
|
|
pSerializer->WriteInt32( mbLazy ? 1 : 0 );
|
|
|
|
|
|
// stuff
|
|
{
|
|
// write UID mapping
|
|
pSerializer->WriteInt32( uidToUsername.size() );
|
|
for( INT64_TO_STRING_MAP::const_iterator iterUid = uidToUsername.begin(); iterUid != uidToUsername.end(); ++iterUid )
|
|
{
|
|
pSerializer->WriteInt64( iterUid->first );
|
|
pSerializer->WriteString( iterUid->second );
|
|
}
|
|
|
|
// write GID mapping
|
|
pSerializer->WriteInt32( gidToGroupname.size() );
|
|
for( INT64_TO_STRING_MAP::const_iterator iterGid = gidToGroupname.begin(); iterGid != gidToGroupname.end(); ++iterGid )
|
|
{
|
|
pSerializer->WriteInt64( iterGid->first );
|
|
pSerializer->WriteString( iterGid->second );
|
|
}
|
|
}
|
|
}
|
|
|
|
void cFSPropDisplayer::Read(iSerializer* pSerializer, int32 version)
|
|
{
|
|
if (version > Version())
|
|
ThrowAndAssert(eSerializerVersionMismatch(_T("Property Displayer Read")));
|
|
|
|
mpvPropsWeDisplay.Read( pSerializer );
|
|
|
|
int32 iDummy;
|
|
pSerializer->ReadInt32( iDummy );
|
|
mbLazy = iDummy == 0 ? false : true;
|
|
|
|
// stuff
|
|
{
|
|
int32 nValues;
|
|
int64 key;
|
|
TSTRING val;
|
|
int i;
|
|
|
|
// read UID hashtable
|
|
pSerializer->ReadInt32( nValues );
|
|
for( i = 0; i < nValues; i++ )
|
|
{
|
|
pSerializer->ReadInt64( key );
|
|
pSerializer->ReadString( val );
|
|
AddUsernameMapping( key, val );
|
|
}
|
|
|
|
// read GID hashtable
|
|
pSerializer->ReadInt32( nValues );
|
|
for( i = 0; i < nValues; i++ )
|
|
{
|
|
pSerializer->ReadInt64( key );
|
|
pSerializer->ReadString( val );
|
|
AddGroupnameMapping( key, val );
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//////////////////////////////////////////////
|
|
// Lookup functions
|
|
//////////////////////////////////////////////
|
|
|
|
bool cFSPropDisplayer::GetUsername( const int64& i64uid, TSTRING& tstrUsername ) const
|
|
{
|
|
bool fFound = false;
|
|
|
|
INT64_TO_STRING_MAP::const_iterator iter = uidToUsername.find( i64uid );
|
|
|
|
if( iter != uidToUsername.end() )
|
|
{
|
|
fFound = true;
|
|
tstrUsername = iter->second;
|
|
}
|
|
|
|
return( fFound && !tstrUsername.empty() );
|
|
}
|
|
|
|
bool cFSPropDisplayer::GetGroupname( const int64& i64gid, TSTRING& tstrGroupname ) const
|
|
{
|
|
bool fFound = false;
|
|
|
|
INT64_TO_STRING_MAP::const_iterator iter = gidToGroupname.find( i64gid );
|
|
|
|
if( iter != gidToGroupname.end() )
|
|
{
|
|
fFound = true;
|
|
tstrGroupname = iter->second;
|
|
}
|
|
|
|
return( fFound && !tstrGroupname.empty() );
|
|
}
|
|
|
|
//////////////////////////////////////////////
|
|
// Addition functions
|
|
//////////////////////////////////////////////
|
|
|
|
bool cFSPropDisplayer::AddUsernameMapping( const int64& i64uid, const TSTRING& tstrUsername )
|
|
{
|
|
std::pair<INT64_TO_STRING_MAP::iterator, bool> ret = uidToUsername.insert( INT64_TO_STRING_MAP::value_type( i64uid, tstrUsername ) );
|
|
return( ret.second = false ); // returns true if key didn't exist before
|
|
}
|
|
|
|
bool cFSPropDisplayer::AddGroupnameMapping( const int64& i64gid, const TSTRING& tstrGroupname )
|
|
{
|
|
std::pair<INT64_TO_STRING_MAP::iterator, bool> ret = gidToGroupname.insert( INT64_TO_STRING_MAP::value_type( i64gid, tstrGroupname ) );
|
|
return( ret.second = false ); // returns true if key didn't exist before
|
|
}
|
|
|
|
|