//-*-c++-*--------------------------------------------------------------
//  nsrEA.cpp
//   Extended Attributes
//
//      Unpublished Confidential Information of Hewlett-Packard
//      Company. Do not disclose.  Copyright (c) Hewlett-Packard
//      Company 1995. All rights reserved
// 
// The contents of this software are proprietary and confidential to
// the Hewlett- Packard Company, and are limited in distribution to
// those with a direct need to know.  Individuals having access to
// this software are responsible for maintaining the confidentiality
// of the content and for keeping the software secure when not in use.
// Transfer to any party is strictly forbidden other than as expressly
// permitted in writing by Hewlett-Packard Company.  Unauthorized
// transfer to or possession by any unauthorized party may be a
// criminal offense.
//
//                  RESTRICTED RIGHTS LEGEND
//
//      Use,  duplication,  or disclosure by the U. S. Government is
//      subject to restrictions as set forth in subparagraph (c) (1)
//      (ii) in the Rights in Technical Data and Computer Software
//      clause in DFARS 252.227-7013 or any other successor clause.
//
//                      HEWLETT-PACKARD COMPANY
//                      3000 Hanover St.
//                      Palo Alto, CA  94304 U.S.A.
//
//      Rights for non-DOD U.S. Government Departments and Agencies
//      are as set forth in FAR 52.227-19 (c) (1,2) or any other
//      successor clause.
//
//  CLASSES:
//   ExtendedAttrHeaderDesc
//  PREFIX CLASSES
//   EAPrefix
//   ImplEAPrefix
//   UDFEAPrefix
//   ApplEAPrefix
//  ISO EXTENDED ATTRIBUTES
//   CharSetInfoEA
//   AlternatePermsEA
//   FileTimesEA
//   InfoTimesEA
//   DeviceSpecEA
//   ImplementUseEA
//   ApplicationUseEA
//  UDF EXTENDED ATTRIBUTES
//   FreeEASpaceEA
//   OS2FullEA
//   OS2FEATable
//   OS2EA
//   OS2EALengthEA
//   MacVolumeInfoEA
//   MacPoint
//   MacRect
//   MacDInfo
//   MacDXInfo
//   MacFInfo
//   MacFXInfo
//   MacDirFinderInfoEA
//   MacFileFinderInfoEA
//   SmallAD
//   MacUniqueIDTableEA
//   MacResourceForkEA
//  HP EXTENDED ATTRIBUTES
//   NovellAttrFlags
//   NovellAttrEA
//   NovellRights
//   NovellRightsAssign
//   NovellRightsTable
//   NovellTrusteeEA
//   ICBTableEA
//  EXTENDED ATTRIBUTES UTILITY CLASSES
//   EAInspector
//   SearchEA
//  
//----------------------------------------------------------------------
//
// $Source: /projects/HMS/nsr/udfCore/descr/nsrEA.cpp,v $
// $Revision: 1.30 $    $Author: hmgr $
// $State: Exp $        $Locker:  $
// $Date: 96/05/21 23:27:15 $
//

#include "nsrLib.h"

NSR::String NSR::UDFFreeEASpaceID       ("*UDF FreeEASpace" );
NSR::String NSR::UDFOS2ID               ("*UDF OS/2 EA" );
NSR::String NSR::UDFOS2EALengthID       ("*UDF OS/2 EALength" );
NSR::String NSR::UDFMacVolumeInfoID     ("*UDF Mac VolumeInfo" );
NSR::String NSR::UDFMacFinderInfoID     ("*UDF Mac FinderInfo" );
NSR::String NSR::UDFMacUniqueIDTableID  ("*UDF Mac UniqueIDTable" );
NSR::String NSR::UDFMacResourceForkID   ("*UDF Mac ResourceFork" );

NSR::String NSR::HPNovellAttrID         ("*HP Novell Attributes" );
NSR::String NSR::HPNovellTrusteeID      ("*HP Novell Trustee" );

NSR::String NSR::HPEarlyICBTableID      ("*HP ICB Table" );

// ExtendedAttrHeaderDesc

NSR::ExtendedAttrHeaderDesc::ExtendedAttrHeaderDesc() : 

    TaggedDescriptor(tag_EAHD, 24),
    implAttrLocation_ (  16 ),
    applAttrLocation_ (  20 )
{
    bodyInit();
}

#ifdef NSR_VERIFY
NSR::Boolean
NSR::ExtendedAttrHeaderDesc::operator != ( const ExtendedAttrHeaderDesc & obj ) const
{
    UINT16 bad = 0;

    bad += ( implAttrLocation_  != obj.implAttrLocation_  );
    bad += ( applAttrLocation_  != obj.applAttrLocation_  );

    return bad != 0 ? True : False;
}

NSR::Error
NSR::ExtendedAttrHeaderDesc::bodyVerifyISO( CONST_BYTE_PTR rbp )
{
    ExtendedAttrHeaderDesc tmp;
    tmp.bodyFromISO(rbp);
    if (tmp != *this) {
        return Error(error_VerifyEAHD);
    } else {
        return Error(error_None);
    }
}
#endif

void
NSR::ExtendedAttrHeaderDesc::bodyClear()
{
    implAttrLocation_  .clear();
    applAttrLocation_  .clear();
}

void
NSR::ExtendedAttrHeaderDesc::bodyToISO( BYTE_PTR rbp )
{
    implAttrLocation_  .toISO( rbp );
    applAttrLocation_  .toISO( rbp );
}

void
NSR::ExtendedAttrHeaderDesc::bodyFromISO( CONST_BYTE_PTR rbp )
{
    implAttrLocation_  .fromISO( rbp );
    applAttrLocation_  .fromISO( rbp );
}

// EAPrefix

void
NSR::EAPrefix::init( void )
{
    attrSubtype_ = 1;
}

NSR::EAPrefix::EAPrefix( UINT16 o ) :
    field_(o,12),
    attrType_    ( 0 ),
    attrSubtype_ ( 4 ),
    reserved_    ( 5,3 ),
    attrLen_     ( 8 )
{
    init();
}

#ifdef NSR_VERIFY
NSR::Boolean
NSR::EAPrefix::operator !=( const EAPrefix  & obj ) const
{
    UINT16 bad = 0;

    bad += ( attrType_    != obj.attrType_     );
    bad += ( attrSubtype_ != obj.attrSubtype_  );
    bad += ( reserved_    != obj.reserved_     );
    bad += ( attrLen_     != obj.attrLen_      );

    return bad != 0 ? True : False;
}
#endif

void
NSR::EAPrefix::clear( void )
{
//  attrType_    .clear( ); // not here???
    attrSubtype_ .clear( );
    reserved_    .clear( );
    attrLen_     .clear( );

    init ();
}

void
NSR::EAPrefix::toISO( BYTE_PTR rbp )
{
    rbp += field_.start();

    attrType_    .toISO( rbp );
    attrSubtype_ .toISO( rbp );
    reserved_    .toISO( rbp );
    attrLen_     .toISO( rbp );
}
    
void
NSR::EAPrefix::fromISO( CONST_BYTE_PTR rbp )
{
    rbp += field_.start();

    attrType_    .fromISO( rbp );
    attrSubtype_ .fromISO( rbp );
    reserved_    .fromISO( rbp );
    attrLen_     .fromISO( rbp );
}
    
NSR::EAType
NSR::EAPrefix::attrType( void ) const
{
    if      (attrType_ == (UINT32)ea_CharSetInfo    ) return ea_CharSetInfo    ;
    else if (attrType_ == (UINT32)ea_AlternatePerms ) return ea_AlternatePerms ;
    else if (attrType_ == (UINT32)ea_FileTimes      ) return ea_FileTimes      ;
    else if (attrType_ == (UINT32)ea_InfoTimes      ) return ea_InfoTimes      ;
    else if (attrType_ == (UINT32)ea_DeviceSpec     ) return ea_DeviceSpec     ;
    else if (attrType_ == (UINT32)ea_ImplementUse   ) return ea_ImplementUse   ;
    else if (attrType_ == (UINT32)ea_ApplicationUse ) return ea_ApplicationUse ;
    else return ea_Unknown;
}
void
NSR::EAPrefix::attrType( EAType eat )
{
    attrType_ = (UINT32) eat;
}

NSR::Error
NSR::EAPrefix::checkValidity( void ) const
{
    if (attrType_ == (UINT32)ea_Unknown)
        return Error(error_EA_Unknown_EA_type);
    if ( attrSubtype_ != 1 )
        return Error(error_EA_Invalid_EA_subtype);
    if ( attrLen_ < field_.len() )
        return Error(error_EA_Invalid_EA_length);
    return Error(error_None);
}

// ImplEAPrefix

void
NSR::ImplEAPrefix::init( void )
{
    prefix_ .attrType ( ea_ImplementUse );
    prefix_ .attrLen  ( field_.len() );
}

NSR::ImplEAPrefix::ImplEAPrefix( UINT16 o ) :
    field_(o,48),
    prefix_     ( 0 ),
    implUseLen_ ( 12 ),
    implID_     ( 16 )
{
    init();
}

#ifdef NSR_VERIFY
NSR::Boolean
NSR::ImplEAPrefix::operator !=( const ImplEAPrefix  & obj ) const
{
    UINT16 bad = 0;

    bad += ( prefix_      != obj.prefix_      );
    bad += ( implUseLen_  != obj.implUseLen_  );
    bad += ( implID_      != obj.implID_      );

    return bad != 0 ? True : False;
}
#endif

void
NSR::ImplEAPrefix::clear( void )
{
    prefix_     .clear( );
    implUseLen_ .clear( );
    implID_     .clear( );

    init();
}

void
NSR::ImplEAPrefix::toISO( BYTE_PTR rbp )
{
    rbp += field_.start();

    prefix_     .toISO( rbp );
    implUseLen_ .toISO( rbp );
    implID_     .toISO( rbp );
}
    
void
NSR::ImplEAPrefix::fromISO( CONST_BYTE_PTR rbp )
{
    rbp += field_.start();

    prefix_     .fromISO( rbp );
    implUseLen_ .fromISO( rbp );
    implID_     .fromISO( rbp );
}
    
NSR::Error
NSR::ImplEAPrefix::checkValidity() const
{
    if ( prefix_.checkValidity() )
        return prefix_.checkValidity();
    if ( attrLen() < field_.len() + implUseLen_ )
        return Error(error_EA_Invalid_EA_length);
    return Error(error_None);
}

// UDFEAPrefix

void
NSR::UDFEAPrefix::init( void )
{
    prefix_ .attrType ( ea_ImplementUse );
    prefix_ .attrLen  ( field_.len() );
    implUseLen_ = checksum_.field.len();
}

NSR::UINT16
NSR::UDFEAPrefix::checksum( CONST_BYTE_PTR rbp ) const
{
    UINT16 i = 0,cksum = 0;
    UINT16 end = checksum_.field.start();
        
    while ( i < end )
        cksum += rbp[i++];
    return cksum;
}

NSR::UDFEAPrefix::UDFEAPrefix( UINT16 o ) :
    field_(o,50),
    prefix_     (  0 ),
    implUseLen_ ( 12 ),
    implID_     ( 16 ),
    checksum_   ( 48 )
{
    init();
}

#ifdef NSR_VERIFY
NSR::Boolean
NSR::UDFEAPrefix::operator !=( const UDFEAPrefix  & obj ) const
{
    UINT16 bad = 0;

    bad += ( prefix_      != obj.prefix_      );
    bad += ( implUseLen_  != obj.implUseLen_  );
    bad += ( implID_      != obj.implID_      );
    bad += ( checksum_    != obj.checksum_    );

    return bad != 0 ? True : False;
}
#endif

void
NSR::UDFEAPrefix::clear( void )
{
    prefix_     .clear( );
    implUseLen_ .clear( );
    implID_     .clear( );
    checksum_   .clear( );

    init();
}

void
NSR::UDFEAPrefix::toISO( BYTE_PTR rbp )
{
    rbp += field_.start();

    prefix_       .toISO( rbp );
    implUseLen_   .toISO( rbp );
    implID_       .toISO( rbp );

    checksum_ = checksum( rbp );
    checksum_     .toISO( rbp );
}
    
void
NSR::UDFEAPrefix::fromISO( CONST_BYTE_PTR rbp )
{
    rbp += field_.start();

    prefix_     .fromISO( rbp );
    implUseLen_ .fromISO( rbp );
    implID_     .fromISO( rbp );
    checksum_   .fromISO( rbp );
}
    
NSR::Error
NSR::UDFEAPrefix::checkValidity( CONST_BYTE_PTR rbp ) const
{
    if ( prefix_.checkValidity() )
        return prefix_.checkValidity();
    if ( attrLen() < field_.len() + implUseLen_ )
        return Error(error_EA_Invalid_EA_length);
    if ( checksum_ != checksum(rbp) )
        return Error(error_EA_Bad_checksum);
    return Error(error_None);
}

// ---------- ISO EAs --------------
// CharSetInfoEA

const NSR::UINT16 NSR::CharSetInfoEA::fixedLen_ = 17;

// AlternatePermsEA

const NSR::UINT16 NSR::AlternatePermsEA::fixedLen_ = 18;

// FileTimesEA

const NSR::UINT16 NSR::FileTimesEA::fixedLen_ = 20;

void
NSR::FileTimesEA::init(void)
{
    prefix_.attrType ( ea_FileTimes );
    prefix_.attrLen  ( minAttrLen() );
    
    dataLen_           = fileCreation_.field.len();
    fileTimeExistence_ = 0x00000001; // Creation time only
}

NSR::FileTimesEA::FileTimesEA( void ) :
    prefix_            ( 0 ),
    dataLen_           ( 12 ),
    fileTimeExistence_ ( 16 ),
    fileCreation_      ( 20 )
{
    init();
}

NSR::Error
NSR::FileTimesEA::error(void) const 
{
    Error err;

    if ( fileTimeExistence_ != 0x00000001 )
        err = error_EA_Bad_file_times_type;
    return err;
}

NSR::UINT32
NSR::FileTimesEA::minAttrLen(void) const
{
    // round up
    return ((((UINT32)fileCreation_.field.after() + 3) / 4) * 4);
}

void
NSR::FileTimesEA::attrLen( UINT32 len, Error & err )
{
    err = error_None;
    if ( len < minAttrLen() || (len % 4) != 0 ) {
        err = error_EA_Invalid_EA_length ;
        return;
    }
    prefix_.attrLen(len);
    return;
}

NSR::UINT32
NSR::FileTimesEA::attrLen(void) const
{
    return prefix_.attrLen();
}

void
NSR::FileTimesEA::clear(void)
{
    prefix_            .clear();
    dataLen_           .clear();
    fileTimeExistence_ .clear();
    fileCreation_      .clear();

    init();
}

void
NSR::FileTimesEA::toISO( BYTE_PTR rbp )
{
    prefix_            .toISO( rbp );
    dataLen_           .toISO( rbp );
    fileTimeExistence_ .toISO( rbp );
    fileCreation_      .toISO( rbp );
}

void
NSR::FileTimesEA::fromISO( CONST_BYTE_PTR rbp )
{
    prefix_            .fromISO( rbp );
    dataLen_           .fromISO( rbp );
    fileTimeExistence_ .fromISO( rbp );
    fileCreation_      .fromISO( rbp );
}

#ifdef NSR_VERIFY
NSR::Boolean
NSR::FileTimesEA::operator != ( const FileTimesEA& obj ) const
{
    UINT16 bad = 0;

    bad += ( prefix_            != obj.prefix_            );
    bad += ( dataLen_           != obj.dataLen_           );
    bad += ( fileTimeExistence_ != obj.fileTimeExistence_ );
    bad += ( fileCreation_      != obj.fileCreation_      );

    return bad != 0 ? True : False;
}

NSR::Error
NSR::FileTimesEA::verifyISO( CONST_BYTE_PTR rbp ) const
{
    FileTimesEA tmp;
    tmp.fromISO(rbp);
    if (tmp != *this) {
        return Error(error_VerifyFileTimesEA);
    } else {
        return Error(error_None);
    }
}
#endif

// InfoTimesEA

const NSR::UINT16 NSR::InfoTimesEA::fixedLen_ = 20;

// DeviceSpecEA

const NSR::UINT16 NSR::DeviceSpecEA::fixedLen_ = 24;

// ImplementUseEA

const NSR::UINT16 NSR::ImplementUseEA::fixedLen_ = 48;

// ApplicationUseEA

const NSR::UINT16 NSR::ApplicationUseEA::fixedLen_ = 48;


// ---------- UDF EAs --------------
// FreeEASpaceEA

void
NSR::FreeEASpaceEA::init( void )
{
    prefix_ .id(UDFFreeEASpaceID);
    prefix_ .implUseLen ( prefix_    .implUseLen() +
                          freeSpace_ .field.len() );
    prefix_ .attrLen ( minAttrLen() );
}

NSR::FreeEASpaceEA::FreeEASpaceEA( UINT32 size ) :
    prefix_         ( 0 ),
    freeSpace_      ( 50, 0 )
{
    // Has already rounded up to 50 bytes - a zero length freeSpace_
    // field. If a longer length has been supplied, change the length
    // of the freeSpace_ field.
    if ( size > freeSpace_.field.after())
        freeSpace_.setFieldLen( size - freeSpace_.field.start() );

    init();                     // Rounds attrLen up to mult of 4
}

NSR::Error
NSR::FreeEASpaceEA::error( void ) const 
{
    Error err;

    if (( err = prefix_ .error()) ) return err;
    return err;
}

NSR::UINT32
NSR::FreeEASpaceEA::minAttrLen(void) const
{
    return ((((UINT32)freeSpace_.field.after() + 3) / 4) * 4); // round up
}

void
NSR::FreeEASpaceEA::attrLen( UINT32 len, Error & err )
{
    err = error_None;
    if ( len < minAttrLen() || len % 4 != 0 ) {
        err = error_EA_Invalid_EA_length ;
        return;
    }
    prefix_.attrLen(len);
    return;
}

NSR::UINT32
NSR::FreeEASpaceEA::attrLen( void ) const
{
    return prefix_.attrLen();
}

void
NSR::FreeEASpaceEA::reinit( UINT32 size )
{
    prefix_         .clear();
    freeSpace_      .clear();

    freeSpace_.setFieldLen(0);
    if ( size > freeSpace_.field.after()) {
        freeSpace_.setFieldLen( size - freeSpace_.field.start() );
    }
    init();                     // Rounds attrLen up to mult of 4
}

void
NSR::FreeEASpaceEA::clear( void )
{
    prefix_         .clear();
    freeSpace_      .clear();

    init();                     // Rounds attrLen up to mult of 4
}

void
NSR::FreeEASpaceEA::toISO( BYTE_PTR rbp )
{
    prefix_         .toISO( rbp );
    freeSpace_      .toISO( rbp );
}

void
NSR::FreeEASpaceEA::fromISO( CONST_BYTE_PTR rbp )
{
    prefix_         .fromISO( rbp );
    freeSpace_      .fromISO( rbp );
}

#ifdef NSR_VERIFY
NSR::Boolean
NSR::FreeEASpaceEA::operator != ( const FreeEASpaceEA& obj ) const
{
    UINT16 bad = 0;

    bad += ( prefix_    != obj.prefix_    );
    bad += ( freeSpace_ != obj.freeSpace_ );

    return bad != 0 ? True : False;
}

NSR::Error
NSR::FreeEASpaceEA::verifyISO( CONST_BYTE_PTR rbp ) const
{
    FreeEASpaceEA tmp(1);
    tmp.fromISO(rbp);
    if (tmp != *this) {
        return Error(error_VerifyFreeEASpaceEA);
    } else {
        return Error(error_None);
    }
}
#endif

#ifdef _INCL_OS2_EATTRS_
// OS2FullEA
// OS2FEATable
// OS2EA
// OS2EALengthEA
#endif // _INCL_OS2_EATTRS_

#ifdef _INCL_MAC_EATTRS_

// MacVolumeInfoEA

void
NSR::MacVolumeInfoEA::init(void)
{
    prefix_ .id(UDFMacVolumeInfoID);
    prefix_ .implUseLen ( prefix_           .implUseLen() +
                          lastModifyDate_   .field.len()  +
                          lastBackupDate_   .field.len()  +
                          volumeFinderInfo_ .field.len()  );
    prefix_ .attrLen ( minAttrLen() );
}

NSR::MacVolumeInfoEA::MacVolumeInfoEA( void ) :
    prefix_           ( 0 ),
    lastModifyDate_   ( 50 ),
    lastBackupDate_   ( 62 ),
    volumeFinderInfo_ ( 74, 8 )
{ 
    init();
}

NSR::Error
NSR::MacVolumeInfoEA::error(void) const 
{
    Error err;

    if (( err = prefix_           .error()) ) return err;
    if (( err = volumeFinderInfo_ .error()) ) return err;
    return err;
}

NSR::UINT32
NSR::MacVolumeInfoEA::minAttrLen(void) const
{
    // round up
    return ((((UINT32)volumeFinderInfo_.field.after() + 3) / 4) * 4);
}

void
NSR::MacVolumeInfoEA::attrLen( UINT32 len, Error & err )
{
    err = error_None;
    if ( len < minAttrLen() || (len % 4) != 0 ) {
        err = error_EA_Invalid_EA_length ;
        return;
    }
    prefix_.attrLen(len);
    return;
}

NSR::UINT32
NSR::MacVolumeInfoEA::attrLen(void) const
{
    return prefix_.attrLen();
}

void
NSR::MacVolumeInfoEA::clear(void)
{
    prefix_           .clear();
    lastModifyDate_   .clear();
    lastBackupDate_   .clear();
    volumeFinderInfo_ .clear();

    init();
}

void
NSR::MacVolumeInfoEA::toISO( BYTE_PTR rbp )
{
    prefix_           .toISO( rbp );
    lastModifyDate_   .toISO( rbp );
    lastBackupDate_   .toISO( rbp );
    volumeFinderInfo_ .toISO( rbp );
}

void
NSR::MacVolumeInfoEA::fromISO( CONST_BYTE_PTR rbp )
{
    prefix_           .fromISO( rbp );
    lastModifyDate_   .fromISO( rbp );
    lastBackupDate_   .fromISO( rbp );
    volumeFinderInfo_ .fromISO( rbp );
}

#ifdef NSR_VERIFY
NSR::Boolean
NSR::MacVolumeInfoEA::operator != ( const MacVolumeInfoEA& obj ) const
{
    UINT16 bad = 0;

    bad += ( prefix_           != obj.prefix_           );
    bad += ( lastModifyDate_   != obj.lastModifyDate_   );
    bad += ( lastBackupDate_   != obj.lastBackupDate_   );
    bad += ( volumeFinderInfo_ != obj.volumeFinderInfo_ );

    return bad != 0 ? True : False;
}

NSR::Error
NSR::MacVolumeInfoEA::verifyISO( CONST_BYTE_PTR rbp ) const
{
    MacVolumeInfoEA tmp;
    tmp.fromISO(rbp);
    if (tmp != *this) {
        return Error(error_VerifyMacVolumeInfoEA);
    } else {
        return Error(error_None);
    }
}
#endif

// MacPoint

NSR::MacPoint::MacPoint ( UINT16 o ) :
    field(o,4),
    v  (  0 ),
    h  (  2 )
{
}

#ifdef NSR_VERIFY
NSR::Boolean
NSR::MacPoint::operator != ( const MacPoint & obj ) const
{
    UINT16 bad = 0;

    bad += ( v  != obj.v  );
    bad += ( h  != obj.h  );

    return bad != 0 ? True : False;
}
#endif

void
NSR::MacPoint::clear( void )
{
    v  .clear();
    h  .clear();
}

void
NSR::MacPoint::toISO( BYTE_PTR rbp )
{
    rbp += field.start();

    v  .toISO(rbp);
    h  .toISO(rbp);
}

void
NSR::MacPoint::fromISO( CONST_BYTE_PTR rbp )
{
    rbp += field.start();

    v  .fromISO(rbp);
    h  .fromISO(rbp);
}

// MacRect

NSR::MacRect::MacRect ( UINT16 o ) :
    field(o,8),
    top    (  0 ),
    left   (  2 ),
    bottom (  4 ),
    right  (  6 )
{
}

#ifdef NSR_VERIFY
NSR::Boolean
NSR::MacRect::operator != ( const MacRect & obj ) const
{
    UINT16 bad = 0;

    bad += ( top    != obj.top    );
    bad += ( left   != obj.left   );
    bad += ( bottom != obj.bottom );
    bad += ( right  != obj.right  );

    return bad != 0 ? True : False;
}
#endif

void
NSR::MacRect::clear( void )
{
    top    .clear();
    left   .clear();
    bottom .clear();
    right  .clear();
}

void
NSR::MacRect::toISO( BYTE_PTR rbp )
{
    rbp += field.start();

    top    .toISO(rbp);
    left   .toISO(rbp);
    bottom .toISO(rbp);
    right  .toISO(rbp);
}

void
NSR::MacRect::fromISO( CONST_BYTE_PTR rbp )
{
    rbp += field.start();

    top    .fromISO(rbp);
    left   .fromISO(rbp);
    bottom .fromISO(rbp);
    right  .fromISO(rbp);
}

// MacDInfo

NSR::MacDInfo::MacDInfo ( UINT16 o ) :
    field(o,16),
    frRect     (  0 ),
    frFlags    (  8 ),
    frLocation (  10 ),
    frView     (  14 )
{
}

#ifdef NSR_VERIFY
NSR::Boolean
NSR::MacDInfo::operator != ( const MacDInfo & obj ) const
{
    UINT16 bad = 0;

    bad += ( frRect     != obj.frRect     );
    bad += ( frFlags    != obj.frFlags    );
    bad += ( frLocation != obj.frLocation );
    bad += ( frView     != obj.frView     );

    return bad != 0 ? True : False;
}
#endif

void
NSR::MacDInfo::clear( void )
{
    frRect     .clear();
    frFlags    .clear();
    frLocation .clear();
    frView     .clear();
}

void
NSR::MacDInfo::toISO( BYTE_PTR rbp )
{
    rbp += field.start();

    frRect     .toISO(rbp);
    frFlags    .toISO(rbp);
    frLocation .toISO(rbp);
    frView     .toISO(rbp);
}

void
NSR::MacDInfo::fromISO( CONST_BYTE_PTR rbp )
{
    rbp += field.start();

    frRect     .fromISO(rbp);
    frFlags    .fromISO(rbp);
    frLocation .fromISO(rbp);
    frView     .fromISO(rbp);
}

// MacDXInfo

NSR::MacDXInfo::MacDXInfo ( UINT16 o ) :
    field(o,16),
    frScroll    (  0 ),
    frOpenChain (  4 ),
    frScript    (  8 ),
    frXflags    (  9 ),
    frComment   (  10 ),
    frPutAway   (  12 )
{
}

#ifdef NSR_VERIFY
NSR::Boolean
NSR::MacDXInfo::operator != ( const MacDXInfo & obj ) const
{
    UINT16 bad = 0;

    bad += ( frScroll    != obj.frScroll    );
    bad += ( frOpenChain != obj.frOpenChain );
    bad += ( frScript    != obj.frScript    );
    bad += ( frXflags    != obj.frXflags    );
    bad += ( frComment   != obj.frComment   );
    bad += ( frPutAway   != obj.frPutAway   );

    return bad != 0 ? True : False;
}
#endif

void
NSR::MacDXInfo::clear( void )
{
    frScroll    .clear();
    frOpenChain .clear();
    frScript    .clear();
    frXflags    .clear();
    frComment   .clear();
    frPutAway   .clear();
}

void
NSR::MacDXInfo::toISO( BYTE_PTR rbp )
{
    rbp += field.start();

    frScroll    .toISO(rbp);
    frOpenChain .toISO(rbp);
    frScript    .toISO(rbp);
    frXflags    .toISO(rbp);
    frComment   .toISO(rbp);
    frPutAway   .toISO(rbp);
}

void
NSR::MacDXInfo::fromISO( CONST_BYTE_PTR rbp )
{
    rbp += field.start();

    frScroll    .fromISO(rbp);
    frOpenChain .fromISO(rbp);
    frScript    .fromISO(rbp);
    frXflags    .fromISO(rbp);
    frComment   .fromISO(rbp);
    frPutAway   .fromISO(rbp);
}

// MacFInfo

NSR::MacFInfo::MacFInfo ( UINT16 o ) :
    field(o,16),
    fdType     (  0 ),
    fdCreator  (  4 ),
    fdFlags    (  8 ),
    fdLocation (  10 ),
    fdFldr     (  14 )
{
}

#ifdef NSR_VERIFY
NSR::Boolean
NSR::MacFInfo::operator != ( const MacFInfo & obj ) const
{
    UINT16 bad = 0;

    bad += ( fdType     != obj.fdType     );
    bad += ( fdCreator  != obj.fdCreator  );
    bad += ( fdFlags    != obj.fdFlags    );
    bad += ( fdLocation != obj.fdLocation );
    bad += ( fdFldr     != obj.fdFldr     );

    return bad != 0 ? True : False;
}
#endif

void
NSR::MacFInfo::clear( void )
{
    fdType     .clear();
    fdCreator  .clear();
    fdFlags    .clear();
    fdLocation .clear();
    fdFldr     .clear();
}

void
NSR::MacFInfo::toISO( BYTE_PTR rbp )
{
    rbp += field.start();

    fdType     .toISO(rbp);
    fdCreator  .toISO(rbp);
    fdFlags    .toISO(rbp);
    fdLocation .toISO(rbp);
    fdFldr     .toISO(rbp);
}

void
NSR::MacFInfo::fromISO( CONST_BYTE_PTR rbp )
{
    rbp += field.start();

    fdType     .fromISO(rbp);
    fdCreator  .fromISO(rbp);
    fdFlags    .fromISO(rbp);
    fdLocation .fromISO(rbp);
    fdFldr     .fromISO(rbp);
}

// MacFXInfo

NSR::MacFXInfo::MacFXInfo ( UINT16 o ) :
    field(o,16),
    fdIconID  (  0 ),
    fdUnused  (  2, 6 ),
    fdScript  (  8 ),
    fdXflags  (  9 ),
    fdComment (  10 ),
    fdPutAway (  12 )
{
}

#ifdef NSR_VERIFY
NSR::Boolean
NSR::MacFXInfo::operator != ( const MacFXInfo & obj ) const
{
    UINT16 bad = 0;

    bad += ( fdIconID  != obj.fdIconID  );
    bad += ( fdUnused  != obj.fdUnused  );
    bad += ( fdScript  != obj.fdScript  );
    bad += ( fdXflags  != obj.fdXflags  );
    bad += ( fdComment != obj.fdComment );
    bad += ( fdPutAway != obj.fdPutAway );

    return bad != 0 ? True : False;
}
#endif

void
NSR::MacFXInfo::clear( void )
{
    fdIconID  .clear();
    fdUnused  .clear();
    fdScript  .clear();
    fdXflags  .clear();
    fdComment .clear();
    fdPutAway .clear();
}

void
NSR::MacFXInfo::toISO( BYTE_PTR rbp )
{
    rbp += field.start();

    fdIconID  .toISO(rbp);
    fdUnused  .toISO(rbp);
    fdScript  .toISO(rbp);
    fdXflags  .toISO(rbp);
    fdComment .toISO(rbp);
    fdPutAway .toISO(rbp);
}

void
NSR::MacFXInfo::fromISO( CONST_BYTE_PTR rbp )
{
    rbp += field.start();

    fdIconID  .fromISO(rbp);
    fdUnused  .fromISO(rbp);
    fdScript  .fromISO(rbp);
    fdXflags  .fromISO(rbp);
    fdComment .fromISO(rbp);
    fdPutAway .fromISO(rbp);
}

// MacDirFinderInfoEA

void
NSR::MacDirFinderInfoEA::init(void)
{
    prefix_ .id(UDFMacFinderInfoID);
    prefix_ .implUseLen ( prefix_      .implUseLen() +
                          pad_         .field.len()  +
                          parentDirID_ .field.len()  +
                          dirInfo_     .field.len()  +
                          dirXInfo_    .field.len()  );
    prefix_ .attrLen ( minAttrLen() );
}

NSR::MacDirFinderInfoEA::MacDirFinderInfoEA( void ) :
    prefix_      ( 0 ),
    pad_         ( 50, 2 ),
    parentDirID_ ( 52 ),
    dirInfo_     ( 56 ),
    dirXInfo_    ( 72 )
{
    init();
}

NSR::Error
NSR::MacDirFinderInfoEA::error(void) const 
{
    Error err;

    if (( err = prefix_ .error()) ) return err;
    return err;
}

NSR::UINT32
NSR::MacDirFinderInfoEA::minAttrLen(void) const
{
    // round up
    return ((((UINT32)dirXInfo_.field.after() + 3) / 4) * 4);
}

void
NSR::MacDirFinderInfoEA::attrLen( UINT32 len, Error & err )
{
    err = error_None;
    if ( len < minAttrLen() || (len % 4) != 0 ) {
        err = error_EA_Invalid_EA_length ;
        return;
    }
    prefix_.attrLen(len);
    return;
}

NSR::UINT32
NSR::MacDirFinderInfoEA::attrLen(void) const
{
    return prefix_.attrLen();
}

void
NSR::MacDirFinderInfoEA::clear(void)
{
    prefix_      .clear();
    pad_         .clear();
    parentDirID_ .clear();
    dirInfo_     .clear();
    dirXInfo_    .clear();

    init();
}

void
NSR::MacDirFinderInfoEA::toISO( BYTE_PTR rbp )
{
    prefix_      .toISO( rbp );
    pad_         .toISO( rbp );
    parentDirID_ .toISO( rbp );
    dirInfo_     .toISO( rbp );
    dirXInfo_    .toISO( rbp );
}

void
NSR::MacDirFinderInfoEA::fromISO( CONST_BYTE_PTR rbp )
{
    prefix_      .fromISO( rbp );
    pad_         .fromISO( rbp );
    parentDirID_ .fromISO( rbp );
    dirInfo_     .fromISO( rbp );
    dirXInfo_    .fromISO( rbp );
}

#ifdef NSR_VERIFY
NSR::Boolean
NSR::MacDirFinderInfoEA::operator != ( const MacDirFinderInfoEA& obj ) const
{
    UINT16 bad = 0;

    bad += ( prefix_      != obj.prefix_      );
    bad += ( pad_         != obj.pad_         );
    bad += ( parentDirID_ != obj.parentDirID_ );
    bad += ( dirInfo_     != obj.dirInfo_     );
    bad += ( dirXInfo_    != obj.dirXInfo_    );

    return bad != 0 ? True : False;
}

NSR::Error
NSR::MacDirFinderInfoEA::verifyISO( CONST_BYTE_PTR rbp ) const
{
    MacDirFinderInfoEA tmp;
    tmp.fromISO(rbp);
    if (tmp != *this) {
        return Error(error_VerifyMacDirFinderInfoEA);
    } else {
        return Error(error_None);
    }
}
#endif

// MacFileFinderInfoEA

void
NSR::MacFileFinderInfoEA::init(void)
{
    prefix_ .id(UDFMacFinderInfoID);
    prefix_ .implUseLen ( prefix_          .implUseLen() +
                          pad_             .field.len()  +
                          parentDirID_     .field.len()  +
                          fileInfo_        .field.len()  +
                          fileXInfo_       .field.len()  +
                          resForkDataLen_  .field.len()  +
                          resForkAllocLen_ .field.len()  );
    prefix_ .attrLen ( minAttrLen() );
}

NSR::MacFileFinderInfoEA::MacFileFinderInfoEA( void ) :
    prefix_          ( 0 ),
    pad_             ( 50, 2 ),
    parentDirID_     ( 52 ),
    fileInfo_        ( 56 ),
    fileXInfo_       ( 72 ),
    resForkDataLen_  ( 88 ),
    resForkAllocLen_ ( 92 )
{
    init();
}

NSR::Error
NSR::MacFileFinderInfoEA::error(void) const 
{
    Error err;

    if (( err = prefix_ .error()) ) return err;
    return err;
}

NSR::UINT32
NSR::MacFileFinderInfoEA::minAttrLen(void) const
{
    // round up
    return ((((UINT32)resForkAllocLen_.field.after() + 3) / 4) * 4);
}

void
NSR::MacFileFinderInfoEA::attrLen( UINT32 len, Error & err )
{
    err = error_None;
    if ( len < minAttrLen() || (len % 4) != 0 ) {
        err = error_EA_Invalid_EA_length ;
        return;
    }
    prefix_.attrLen(len);
    return;
}

NSR::UINT32
NSR::MacFileFinderInfoEA::attrLen(void) const
{
    return prefix_.attrLen();
}

void
NSR::MacFileFinderInfoEA::clear(void)
{
    prefix_          .clear();
    pad_             .clear();
    parentDirID_     .clear();
    fileInfo_        .clear();
    fileXInfo_       .clear();
    resForkDataLen_  .clear();
    resForkAllocLen_ .clear();

    init();
}

void
NSR::MacFileFinderInfoEA::toISO( BYTE_PTR rbp )
{
    prefix_          .toISO( rbp );
    pad_             .toISO( rbp );
    parentDirID_     .toISO( rbp );
    fileInfo_        .toISO( rbp );
    fileXInfo_       .toISO( rbp );
    resForkDataLen_  .toISO( rbp );
    resForkAllocLen_ .toISO( rbp );
}

void
NSR::MacFileFinderInfoEA::fromISO( CONST_BYTE_PTR rbp )
{
    prefix_          .fromISO( rbp );
    pad_             .fromISO( rbp );
    parentDirID_     .fromISO( rbp );
    fileInfo_        .fromISO( rbp );
    fileXInfo_       .fromISO( rbp );
    resForkDataLen_  .fromISO( rbp );
    resForkAllocLen_ .fromISO( rbp );
}

#ifdef NSR_VERIFY
NSR::Boolean
NSR::MacFileFinderInfoEA::operator != ( const MacFileFinderInfoEA& obj ) const
{
    UINT16 bad = 0;

    bad += ( prefix_          != obj.prefix_          );
    bad += ( pad_             != obj.pad_             );
    bad += ( parentDirID_     != obj.parentDirID_     );
    bad += ( fileInfo_        != obj.fileInfo_        );
    bad += ( fileXInfo_       != obj.fileXInfo_       );
    bad += ( resForkDataLen_  != obj.resForkDataLen_  );
    bad += ( resForkAllocLen_ != obj.resForkAllocLen_ );

    return bad != 0 ? True : False;
}

NSR::Error
NSR::MacFileFinderInfoEA::verifyISO( CONST_BYTE_PTR rbp ) const
{
    MacFileFinderInfoEA tmp;
    tmp.fromISO(rbp);
    if (tmp != *this) {
        return Error(error_VerifyMacFileFinderInfoEA);
    } else {
        return Error(error_None);
    }
}
#endif

// SmallAD
    
NSR::SmallAD::SmallAD( void ) :
    extLength_   (  0 ),
    extLocation_ (  2 )
{}

#ifdef _INCL_SSOBJS_                                     
void
NSR::SmallAD::toLogExtent(LogicalVolume * lvp,
                          LogExtent & le,
                          Error& err) const
{
    // ISSUE:  SmallAD.toLogExtent - Turn on null ptr err.
#ifdef FUTURE
    if (lvp == NULL) {
        err = error_Null_pointer;
        return;
    }
#endif
    le.reinit(lvp->partitionp(partRefNo()),
              logBlockNo(),
              extLength(),
              err);
    if (!err) {
        le.extentType(Recorded);
        err = le.error();
    }
}
                                                     
void
NSR::SmallAD::fromLogExtent(const LogExtent & le,
                             Error & err)
{
    if ( le.extentType() == Imaginary ) {
        err = error_EA_No_imaginary_SmallADs;
    } else {
        err = error_None;
        clear();
        logBlockNo(le.startBlock());
        extLength(le.infoLen());
        partRefNo(le.logVolumep()->partRefNo(le.partitionp()));
    }
}

#endif // _INCL_SSOBJS_                                  
                                                     
#ifdef NSR_VERIFY                                        
NSR::Boolean
NSR::SmallAD::operator != ( const SmallAD & obj ) const
{
    UINT16 bad = 0;

    bad += ( extLength_   != obj.extLength_   );
    bad += ( extLocation_ != obj.extLocation_ );

    return bad != 0 ? True : False;
}
#endif                                                   

void
NSR::SmallAD::clear( void )
{
    extLength_   .clear();
    extLocation_ .clear();
}

void
NSR::SmallAD::toISO( BYTE_PTR rbp )
{
    extLength_   .toISO( rbp );
    extLocation_ .toISO( rbp );
}

void
NSR::SmallAD::fromISO( CONST_BYTE_PTR rbp )
{
    extLength_   .fromISO( rbp );
    extLocation_ .fromISO( rbp );
}

// MacUniqueIDTableEA

void
NSR::MacUniqueIDTableEA::init( UINT32 nuidm )
{
    numUIDMaps_ = nuidm;
    prefix_ .id(UDFMacUniqueIDTableID);
    prefix_ .implUseLen ( prefix_     .implUseLen() +
                          reserved_   .field.len()  +
                          numUIDMaps_ .field.len()  +
                          numUIDMaps_ * SmallAD::fieldLen() );
    prefix_ .attrLen ( minAttrLen() );
}

NSR::MacUniqueIDTableEA::MacUniqueIDTableEA( UINT32 nuidm ) :
    prefix_     ( 0 ),
    reserved_   ( 50, 2 ),
    numUIDMaps_ ( 52 )
{
    init(nuidm);
}

void
NSR::MacUniqueIDTableEA::numUIDMaps(UINT32 n)
{
    UINT32 isol = attrLen();     // Save off current attrLen
    init(n);                    // sets appropriate field, and sets
                                // attrLen to minAttrLen
    if ( isol > attrLen() ) {    // If was bigger, grow it back
        Error cannotErr;
        attrLen(isol, cannotErr);
    }
}

NSR::Error
NSR::MacUniqueIDTableEA::error(void) const 
{
    Error err;

    if (( err = prefix_ .error()) ) return err;
    return err;
}

NSR::UINT32
NSR::MacUniqueIDTableEA::minAttrLen(void) const
{
    // round up
    return ((((UINT32)numUIDMaps_.field.after() +
              (numUIDMaps_ * SmallAD::fieldLen()) + 3) / 4) * 4);
}

void
NSR::MacUniqueIDTableEA::attrLen( UINT32 len, Error & err )
{
    err = error_None;
    if ( len < minAttrLen() || (len % 4) != 0 ) {
        err = error_EA_Invalid_EA_length ;
        return;
    }
    prefix_.attrLen(len);
    return;
}

NSR::UINT32
NSR::MacUniqueIDTableEA::attrLen(void) const
{
    return prefix_.attrLen();
}

void
NSR::MacUniqueIDTableEA::clear(void)
{
    UINT32 nuidm = numUIDMaps_;

    prefix_     .clear();
    reserved_   .clear();
    numUIDMaps_ .clear();

    init(nuidm);
}

void
NSR::MacUniqueIDTableEA::toISO( BYTE_PTR rbp )
{
    prefix_     .toISO( rbp );
    reserved_   .toISO( rbp );
    numUIDMaps_ .toISO( rbp );
}

void
NSR::MacUniqueIDTableEA::fromISO( CONST_BYTE_PTR rbp )
{
    prefix_     .fromISO( rbp );
    reserved_   .fromISO( rbp );
    numUIDMaps_ .fromISO( rbp );
}

#ifdef NSR_VERIFY
NSR::Boolean
NSR::MacUniqueIDTableEA::operator != ( const MacUniqueIDTableEA& obj ) const
{
    UINT16 bad = 0;

    bad += ( prefix_     != obj.prefix_     );
    bad += ( reserved_   != obj.reserved_   );
    bad += ( numUIDMaps_ != obj.numUIDMaps_ );

    return bad != 0 ? True : False;
}

NSR::Error
NSR::MacUniqueIDTableEA::verifyISO( CONST_BYTE_PTR rbp ) const
{
    MacUniqueIDTableEA tmp(1);
    tmp.fromISO(rbp);
    if (tmp != *this) {
        return Error(error_VerifyMacUniqueIDTableEA);
    } else {
        return Error(error_None);
    }
}
#endif

// MacResourceForkEA

void
NSR::MacResourceForkEA::init(UINT32 dataLen)
{
    prefix_ .id(UDFMacResourceForkID);
    prefix_ .implUseLen ( prefix_  .implUseLen() +  // i.e., 2 +
                          dataLen );
    prefix_ .attrLen ( minAttrLen() );
}

NSR::MacResourceForkEA::MacResourceForkEA( UINT32 dataLen ) :
    prefix_ ( 0 )
{
    init(dataLen);
}

void
NSR::MacResourceForkEA::dataLen(UINT32 len)
{
    prefix_.implUseLen(len+2);
    if ( attrLen() < minAttrLen() ) {
        Error cannotErr;        // Needs an err arg.
        attrLen(minAttrLen(),cannotErr);
    }
}

NSR::UINT32
NSR::MacResourceForkEA::dataLen(void) const
{
    return prefix_.implUseLen()-2;
}
    
NSR::Error
NSR::MacResourceForkEA::error(void) const 
{
    Error err;

    if (( err = prefix_ .error()) ) return err;
    return err;
}

NSR::UINT32
NSR::MacResourceForkEA::minAttrLen(void) const
{
    // round up
    return (((prefix_.field_.after() + dataLen() + 3) / 4) * 4);
}

void
NSR::MacResourceForkEA::attrLen( UINT32 len, Error & err )
{
    err = error_None;
    if ( len < minAttrLen() || (len % 4) != 0 ) {
        err = error_EA_Invalid_EA_length ;
        return;
    }
    prefix_.attrLen(len);
    return;
}

NSR::UINT32
NSR::MacResourceForkEA::attrLen(void) const
{
    return prefix_.attrLen();
}

void
NSR::MacResourceForkEA::clear(void)
{
    UINT32 dl = dataLen();

    prefix_ .clear();

    init(dl);
}

void
NSR::MacResourceForkEA::toISO( BYTE_PTR rbp )
{
    prefix_ .toISO( rbp );
}

void
NSR::MacResourceForkEA::fromISO( CONST_BYTE_PTR rbp )
{
    prefix_ .fromISO( rbp );
}

#ifdef NSR_VERIFY
NSR::Boolean
NSR::MacResourceForkEA::operator != ( const MacResourceForkEA& obj ) const
{
    UINT16 bad = 0;

    bad += ( prefix_ != obj.prefix_ );

    return bad != 0 ? True : False;
}

NSR::Error
NSR::MacResourceForkEA::verifyISO( CONST_BYTE_PTR rbp ) const
{
    MacResourceForkEA tmp(0);
    tmp.fromISO(rbp);
    if (tmp != *this) {
        return Error(error_VerifyMacResourceForkEA);
    } else {
        return Error(error_None);
    }
}
#endif


#endif // _INCL_MAC_EATTRS_

#ifdef _INCL_NOVELL_EATTRS_
// NovellAttrFlags

NSR::NovellAttrFlags::NovellAttrFlags( UINT16 o ) :
    field_ ( o, 1 ),
    copyInhibit_   ( 0 ),
    indexed_       ( 1 ),
    purge_         ( 2 ),
    readAudit_     ( 3 ),
    renameInhibit_ ( 4 ),
    shareable_     ( 5 ),
    transactional_ ( 6 ),
    writeAudit_    ( 7 )
{
}

void
NSR::NovellAttrFlags::clear( void )
{
    copyInhibit_   .clear();
    indexed_       .clear();
    purge_         .clear();
    readAudit_     .clear();
    renameInhibit_ .clear();
    shareable_     .clear();
    transactional_ .clear();
    writeAudit_    .clear();
}

void
NSR::NovellAttrFlags::toISO( BYTE_PTR rbp )
{
    rbp += field_.start();

    copyInhibit_   .toISO( rbp );
    indexed_       .toISO( rbp );
    purge_         .toISO( rbp );
    readAudit_     .toISO( rbp );
    renameInhibit_ .toISO( rbp );
    shareable_     .toISO( rbp );
    transactional_ .toISO( rbp );
    writeAudit_    .toISO( rbp );
}

void
NSR::NovellAttrFlags::fromISO( CONST_BYTE_PTR rbp )
{
    rbp += field_.start();

    copyInhibit_   .fromISO( rbp );
    indexed_       .fromISO( rbp );
    purge_         .fromISO( rbp );
    readAudit_     .fromISO( rbp );
    renameInhibit_ .fromISO( rbp );
    shareable_     .fromISO( rbp );
    transactional_ .fromISO( rbp );
    writeAudit_    .fromISO( rbp );
}

#ifdef NSR_VERIFY
NSR::Boolean
NSR::NovellAttrFlags::operator != ( const NovellAttrFlags  & obj ) const
{
    UINT16 bad = 0;

    bad += ( copyInhibit_   != obj.copyInhibit_   );
    bad += ( indexed_       != obj.indexed_       );
    bad += ( purge_         != obj.purge_         );
    bad += ( readAudit_     != obj.readAudit_     );
    bad += ( renameInhibit_ != obj.renameInhibit_ );
    bad += ( shareable_     != obj.shareable_     );
    bad += ( transactional_ != obj.transactional_ );
    bad += ( writeAudit_    != obj.writeAudit_    );

    return bad != 0 ? True : False;
}
#endif

// NovellAttrEA

NSR::NovellAttrEA::NovellAttrEA() :
    prefix_   ( 0 ),
    flags_    ( 50 ),
    reserved_ ( 51, 3 )
{
    init();
}

#ifdef NSR_VERIFY
NSR::Boolean
NSR::NovellAttrEA::operator != ( const NovellAttrEA& obj ) const
{
    UINT16 bad = 0;

    bad += ( prefix_   != obj.prefix_   );
    bad += ( flags_    != obj.flags_    );
    bad += ( reserved_ != obj.reserved_ );

    return bad != 0 ? True : False;
}

NSR::Error
NSR::NovellAttrEA::verifyISO( CONST_BYTE_PTR rbp ) const
{
    NovellAttrEA tmp;
    tmp.fromISO(rbp);
    if (tmp != *this) {
        return Error(error_VerifyNovellAttrEA);
    } else {
        return Error(error_None);
    }
}
#endif

NSR::Error
NSR::NovellAttrEA::error( void ) const 
{
    return prefix_.error();
}

void
NSR::NovellAttrEA::clear( void )
{
    prefix_   .clear();
    flags_    .clear();
    reserved_ .clear();

    init();
}

NSR::UINT32
NSR::NovellAttrEA::minAttrLen(void) const
{
    // round up
    return ((((UINT32)reserved_.field.after() + 3) / 4) * 4);
}

void
NSR::NovellAttrEA::attrLen( UINT32 len, Error & err )
{
    err = error_None;
    if ( len < minAttrLen() || (len % 4) != 0 ) {
        err = error_EA_Invalid_EA_length ;
        return;
    }
    prefix_.attrLen(len);
    return;
}

NSR::UINT32
NSR::NovellAttrEA::attrLen( void ) const
{
    return prefix_.attrLen();
}

void
NSR::NovellAttrEA::init( void )
{
    prefix_   .id(HPNovellAttrID);
}

void
NSR::NovellAttrEA::toISO( BYTE_PTR rbp )
{
    prefix_   .toISO( rbp );
    flags_    .toISO( rbp );
    reserved_ .toISO( rbp );
}

void
NSR::NovellAttrEA::fromISO( CONST_BYTE_PTR rbp )
{
    prefix_   .fromISO( rbp );
    flags_    .fromISO( rbp );
    reserved_ .fromISO( rbp );
}

#ifdef TRUSTEES
// NovellRights

NSR::NovellRights::NovellRights( UINT16 o ) :
    field_ ( o, 4 ),
    accessControl_ ( 0 ),
    fileScan_      ( 1 ),
    modify_        ( 2 ),
    erase_         ( 3 ),
    create_        ( 4 ),
    write_         ( 5 ),
    read_          ( 6 ),
    supervisory_   ( 7 ),
    reserved_      ( 1, 3 )
{
}

void
NSR::NovellRights::setInhRights( const NetwareTrusteeInfo::Inh_Rights & ir )
{
    accessControl_ = (UINT8) ir.A();
    fileScan_      = (UINT8) ir.F();
    modify_        = (UINT8) ir.M();
    erase_         = (UINT8) ir.E();
    create_        = (UINT8) ir.C();
    write_         = (UINT8) ir.W();
    read_          = (UINT8) ir.R();
    supervisory_   = (UINT8) ir.S();
}

NSR::NetwareTrusteeInfo::Inh_Rights
NSR::NovellRights::getInhRights( ) const
{
    NetwareTrusteeInfo::Inh_Rights ir;

    ir.A( accessControl_ ? True : False );
    ir.F( fileScan_      ? True : False );
    ir.M( modify_        ? True : False );
    ir.E( erase_         ? True : False );
    ir.C( create_        ? True : False );
    ir.W( write_         ? True : False );
    ir.R( read_          ? True : False );
    ir.S( supervisory_   ? True : False );

    return ir;
}

void
NSR::NovellRights::setRights( const NetwareTrusteeInfo::Rights & r )
{
    accessControl_ = (UINT8) r.A();
    fileScan_      = (UINT8) r.F();
    modify_        = (UINT8) r.M();
    erase_         = (UINT8) r.E();
    create_        = (UINT8) r.C();
    write_         = (UINT8) r.W();
    read_          = (UINT8) r.R();
    supervisory_   = (UINT8) r.S();
}

NSR::NetwareTrusteeInfo::Rights
NSR::NovellRights::getRights( ) const
{
    NetwareTrusteeInfo::Rights r;

    r.A( accessControl_ ? True : False );
    r.F( fileScan_      ? True : False );
    r.M( modify_        ? True : False );
    r.E( erase_         ? True : False );
    r.C( create_        ? True : False );
    r.W( write_         ? True : False );
    r.R( read_          ? True : False );
    r.S( supervisory_   ? True : False );

    return r;
}

void
NSR::NovellRights::clear( void )
{
    accessControl_ .clear();
    fileScan_      .clear();
    modify_        .clear();
    erase_         .clear();
    create_        .clear();
    write_         .clear();
    read_          .clear();
    supervisory_   .clear();
    reserved_      .clear();
}

void
NSR::NovellRights::toISO( BYTE_PTR rbp )
{
    rbp += field_.start();

    accessControl_ .toISO( rbp );
    fileScan_      .toISO( rbp );
    modify_        .toISO( rbp );
    erase_         .toISO( rbp );
    create_        .toISO( rbp );
    write_         .toISO( rbp );
    read_          .toISO( rbp );
    supervisory_   .toISO( rbp );
    reserved_      .toISO( rbp );
}

void
NSR::NovellRights::fromISO( CONST_BYTE_PTR rbp )
{
    rbp += field_.start();

    accessControl_ .fromISO( rbp );
    fileScan_      .fromISO( rbp );
    modify_        .fromISO( rbp );
    erase_         .fromISO( rbp );
    create_        .fromISO( rbp );
    write_         .fromISO( rbp );
    read_          .fromISO( rbp );
    supervisory_   .fromISO( rbp );
    reserved_      .fromISO( rbp );
}

#ifdef NSR_VERIFY
NSR::Boolean
NSR::NovellRights::operator != ( const NovellRights  & obj ) const
{
    UINT16 bad = 0;

    bad += ( accessControl_ != obj.accessControl_ );
    bad += ( fileScan_      != obj.fileScan_      );
    bad += ( modify_        != obj.modify_        );
    bad += ( erase_         != obj.erase_         );
    bad += ( create_        != obj.create_        );
    bad += ( write_         != obj.write_         );
    bad += ( read_          != obj.read_          );
    bad += ( supervisory_   != obj.supervisory_   );
    bad += ( reserved_      != obj.reserved_      );

    return bad != 0 ? True : False;
}
#endif

// NovellRightsAssign

NSR::NovellRightsAssign::NovellRightsAssign( UINT16 o ) :
    field_ ( o, 8 ),
    user_   ( 0 ),
    rights_ ( 4 )
{
}

void
NSR::NovellRightsAssign::setAssignment( const
                                        NetwareTrusteeInfo::Assignment
                                        & nra )
{
    user_   = nra.user();
    rights_ .setRights(nra.rights());
}

NSR::NetwareTrusteeInfo::Assignment
NSR::NovellRightsAssign::getAssignment( ) const
{
    NetwareTrusteeInfo::Assignment a;

    a.user( user_ );
    a.rights( rights_.getRights() );

    return a;
}

void
NSR::NovellRightsAssign::clear( void )
{
    user_   .clear();
    rights_ .clear();
}

void
NSR::NovellRightsAssign::toISO( BYTE_PTR rbp )
{
    rbp += field_.start();

    user_   .toISO( rbp );
    rights_ .toISO( rbp );
}

void
NSR::NovellRightsAssign::fromISO( CONST_BYTE_PTR rbp )
{
    rbp += field_.start();

    user_   .fromISO( rbp );
    rights_ .fromISO( rbp );
}

#ifdef NSR_VERIFY
NSR::Boolean
NSR::NovellRightsAssign::operator != ( const NovellRightsAssign & obj ) const
{
    UINT16 bad = 0;

    bad += ( user_   != obj.user_   );
    bad += ( rights_ != obj.rights_ );

    return bad != 0 ? True : False;
}
#endif

// NovellRightsTable

void
NSR::NovellRightsTable::allocEnts( UINT32 ne )
{
    entry_ = new NovellRightsAssign[ne];
    numEnts_ = ne;
    if (entry_ != 0)
        field_.len( ne * entry_->field_.len() );
    else
        field_.len(0);
    clear();
}

NSR::NovellRightsTable::NovellRightsTable( UINT16 o, UINT32 ne ) :
    field_( o, 0 )               // len filled in by allocEnts.
{
    allocEnts( ne );
}

NSR::NovellRightsTable::~NovellRightsTable() { freeEnts(); }

NSR::NovellRightsAssign &
NSR::NovellRightsTable::operator[]( UINT32 i)
{
    if (i < numEnts_ && entry_ != 0)
        return entry_[i];
    else
        return nullEntry_;
}

const NSR::NovellRightsAssign &
NSR::NovellRightsTable::operator[]( UINT32 i) const
{
    if (i < numEnts_ && entry_ != 0)
        return entry_[i];
    else
        return nullEntry_;
}

#ifdef NSR_VERIFY
NSR::Boolean
NSR::NovellRightsTable::operator != ( const NovellRightsTable & obj ) const
{
    UINT32 bad = 0;

    bad += ( numEnts_ != obj.numEnts_ );
    if (entry_ == 0 || obj.entry_ == 0)
        bad += 1000;
    else {
        for ( UINT32 i = 0; i < numEnts_; i++ ) {
            bad += ( entry_[i] != obj.entry_[i] );
        }
    }
    return bad != 0 ? True : False;
}
#endif

NSR::Error
NSR::NovellRightsTable::error( void ) const
{
    if ( numEnts_ != 0 && entry_ == 0 ) {
        return Error(error_No_free_store);
    } else {
        return Error(error_None);
    }
}

// Cannot use const NTI, since it sets err on out of bounds.
void
NSR::NovellRightsTable::setRightsTable( const NetwareTrusteeInfo & t )
{
    fitEnts(t.getCount());
    for ( UINT32 i = 0; i < numEnts_; i++ )
        entry_[i].setAssignment(t[i]);
}


void
NSR::NovellRightsTable::getRightsTable( NetwareTrusteeInfo & t ) const
{
    t.resize(numEnts_);
    for ( UINT32 i = 0; i < numEnts_; i++ )
        t[i] = entry_[i].getAssignment();
}

void
NSR::NovellRightsTable::clear( void )
{
    if (entry_ != 0) {
        for ( UINT32 i = 0; i < numEnts_; i++ ) {
            entry_[i].clear();
        }
    }
}

void
NSR::NovellRightsTable::fitEnts( UINT32 ne )
{
    if ( ne != numEnts_ ) {
        freeEnts();
        allocEnts( ne );
    } else {
        clear();
    }
}

void
NSR::NovellRightsTable::toISO( BYTE_PTR rbp )
{
    rbp += field_.start();

    if (entry_ != 0) {
        for ( UINT32 i = 0; i < numEnts_; i++ ) {
            entry_[i].toISO( rbp );
            rbp += entry_->field_.len();
        }
    }
}

void
NSR::NovellRightsTable::fromISO( CONST_BYTE_PTR rbp )
{
    rbp += field_.start();

    if (entry_ != 0) {
        for ( UINT32 i = 0; i < numEnts_; i++ ) {
            entry_[i].fromISO( rbp );
            rbp += entry_->field_.len();
        }
    }
}

// NovellTrusteeEA

void
NSR::NovellTrusteeEA::init( void )
{
    prefix_ .id(HPNovellTrusteeID);
    prefix_ .implUseLen ( prefix_           .implUseLen() +
                          reserved_         .field.len() +
                          inhRightsMask_    .field_.len() +
                          rightsTableCount_ .field.len() +
                          rightsTable_      .field_.len() );
    prefix_ .attrLen ( minAttrLen() );
    rightsTableCount_  = rightsTable_.numEnts();
}

NSR::NovellTrusteeEA::NovellTrusteeEA( UINT32 n ) :
    prefix_           ( 0 ),
    reserved_         ( 50, 2 ),
    inhRightsMask_    ( 52 ),
    rightsTableCount_ ( 56 ),
    rightsTable_      ( 60, n )
{
    rightsTableCount_ = n;
    init();
}

#ifdef NSR_VERIFY
NSR::Boolean
NSR::NovellTrusteeEA::operator != ( const NovellTrusteeEA& obj ) const
{
    UINT16 bad = 0;

    bad += ( prefix_           != obj.prefix_           );
    bad += ( reserved_         != obj.reserved_         );
    bad += ( inhRightsMask_    != obj.inhRightsMask_    );
    bad += ( rightsTableCount_ != obj.rightsTableCount_ );
    bad += ( rightsTable_      != obj.rightsTable_      );

    return bad != 0 ? True : False;
}

NSR::Error
NSR::NovellTrusteeEA::verifyISO( CONST_BYTE_PTR rbp ) const
{
    NovellTrusteeEA tmp;
    tmp.fromISO(rbp);
    if (tmp != *this) {
        return Error(error_VerifyNovellTrusteeEA);
    } else {
        return Error(error_None);
    }
}
#endif // NSR_VERIFY

NSR::Error
NSR::NovellTrusteeEA::error( void ) const 
{
    Error err;

    if (( err = prefix_      .error()) != error_None ) return err;
    if (( err = rightsTable_ .error()) != error_None ) return err;
    return err;
}

NSR::UINT32
NSR::NovellTrusteeEA::minAttrLen(void) const
{
    return ((((UINT32)rightsTable_.field_.after() + 3) / 4) * 4); // round up
}

void
NSR::NovellTrusteeEA::attrLen( UINT32 len, Error & err )
{
    err = error_None;
    if ( len < minAttrLen() || (len % 4) != 0 ) {
        err = error_Invalid_EA_length ;
        return;
    }
    prefix_.attrLen(len);
    return;
}

// Cannot use const NTI, since it sets err on out of bounds.
void
NSR::NovellTrusteeEA::setTrusteeInfo( const NetwareTrusteeInfo & t )
{
    inhRightsMask_    .setInhRights(t.get_inh_rights());
    rightsTable_      .setRightsTable(t);
    rightsTableCount_ = rightsTable_.numEnts();
}

void
NSR::NovellTrusteeEA::getTrusteeInfo( NetwareTrusteeInfo & t ) const
{
    t.set_inh_rights(inhRightsMask_.getInhRights());
    rightsTable_.getRightsTable(t);
}

NSR::UINT32
NSR::NovellTrusteeEA::attrLen( void ) const
{
    return prefix_.attrLen();
}

void
NSR::NovellTrusteeEA::clear( void )
{
    prefix_            .clear();
    reserved_          .clear();
    inhRightsMask_     .clear();
    // rightsTableCount_ (not here)
    rightsTable_       .clear();

    init();
}

void
NSR::NovellTrusteeEA::toISO( BYTE_PTR rbp )
{
    prefix_           .toISO( rbp );
    reserved_         .toISO( rbp );
    inhRightsMask_    .toISO( rbp );
    rightsTableCount_ .toISO( rbp );
    rightsTable_      .toISO( rbp );
}

void
NSR::NovellTrusteeEA::fromISO( CONST_BYTE_PTR rbp )
{
    prefix_           .fromISO( rbp );
    reserved_         .fromISO( rbp );
    inhRightsMask_    .fromISO( rbp );
    rightsTableCount_ .fromISO( rbp );

    rightsTable_      .fitEnts( rightsTableCount_ );
    rightsTable_      .fromISO( rbp );
}
#endif //TRUSTEES
#endif // _INCL_NOVELL_EATTRS_

#ifdef _INCL_ICBTABLE_EATTR_
// ICBTableEA

void
NSR::ICBTableEA::init( void )
{
    prefix_ .implUseLen ( prefix_         .implUseLen() +
                          hpEAType_       .field.len() +
                          icbTableLength_ .field.len() +
                          icbTable_       .field.len() );
    prefix_ .attrLen ( minAttrLen() );
    hpEAType_       = hpea_ICBTable;
    icbTableLength_ = icbTable_.field.len();
}

NSR::ICBTableEA::ICBTableEA( UINT16 n = 1 ) :
    prefix_         (  0 ),
    hpEAType_       ( 48 ),
    icbTableLength_ ( 52 ),
    icbTable_       ( 56, n, ad_Long )
{
    init();
}

NSR::Error
NSR::ICBTableEA::error( void ) const 
{
    Error err;

    if (( err = prefix_   .error()) ) return err;
    if (( err = icbTable_ .error()) ) return err;
    return err;
}

NSR::UINT32
NSR::ICBTableEA::minAttrLen(void) const
{
    return ((((UINT32)icbTable_.field.after() + 3) / 4) * 4); // round up
}

void
NSR::ICBTableEA::attrLen( UINT32 len, Error & err )
{
    err = error_None;
    if ( len < minAttrLen() || (len % 4) != 0 ) {
        err = error_EA_Invalid_EA_length ;
        return;
    }
    prefix_.attrLen(len);
    return;
}

NSR::UINT32
NSR::ICBTableEA::attrLen( void ) const
{
    return prefix_.attrLen();
}

void
NSR::ICBTableEA::clear( void )
{
    prefix_         .clear();
    hpEAType_       .clear();
    // icbTableLength_ (not here)
    icbTable_       .clear();

    init();
}

void
NSR::ICBTableEA::toISO( BYTE_PTR rbp )
{
    prefix_         .toISO( rbp );
    hpEAType_       .toISO( rbp );
    icbTableLength_ .toISO( rbp );
    icbTable_       .toISO( rbp );
}

void
NSR::ICBTableEA::fromISO( CONST_BYTE_PTR rbp )
{
    prefix_         .fromISO( rbp );
    hpEAType_       .fromISO( rbp );
    icbTableLength_ .fromISO( rbp );

    icbTable_       .fitToLen( icbTableLength_ );
    icbTable_       .fromISO( rbp );
}

#ifdef NSR_VERIFY
NSR::Boolean
NSR::ICBTableEA::operator != ( const ICBTableEA& obj ) const
{
    UINT16 bad = 0;

    bad += ( prefix_         != obj.prefix_         );
    bad += ( hpEAType_       != obj.hpEAType_       );
    bad += ( icbTableLength_ != obj.icbTableLength_ );
    bad += ( icbTable_       != obj.icbTable_       );

    return bad != 0 ? True : False;
}

NSR::Error
NSR::ICBTableEA::verifyISO( CONST_BYTE_PTR rbp ) const
{
    ICBTableEA tmp(1);
    tmp.fromISO(rbp);
    if (tmp != *this) {
        return Error(error_VerifyICBTableEA);
    } else {
        return Error(error_None);
    }
}
#endif // NSR_VERIFY
#endif // _INCL_ICBTABLE_EATTR_

// EAInspector

void
NSR::EAInspector::clear( void )
{
    eaPrefix_   .clear();
    varyingLen_ .clear();
    attrID_     .clear();

    fixedLen_    = 0;
}

NSR::EAInspector::EAInspector(void) :
        eaPrefix_   (  0 ),
        varyingLen_ ( 12 ),
        attrID_     ( 16 ),

        fixedLen_ ( 0 )         // arg is value, not offset
{
}

//----------------------------------------------------------------------
// METHOD: EAInspector::error  --DVM
//      
//  Returns any errors found in the current EA.
//
//  This checks for construction problems as well as attrLen
//  consistency problems, and returns the appropriate error code.
//
//  Unless it is compiled with _PICKY_EA_INSPECTOR_ defined, it allows
//  unknown EA types and EA subtypes to be handled without generating
//  an error. Note that unknown EAs are treated as growable (for
//  padding purposes) but not shrinkable -- That is, their minAttrLen
//  is always set equal to their attrLen. This approach makes the
//  implementation tolerant to future extensions to the format, etc.
//
//  However, if the _PICKY_EA_INSPECTOR_ is defined, an error will be
//  returned if the type or subtype fields of the EA are not
//  recognized. Note that this is an ISO test, rather than a UDF
//  test. This means that only EAs not conforming to ISO/IEC 13346
//  will generate this error. All UDF-defined EAs are defined as ISO
//  implementation use EAs, so even future ones will not generate
//  these errors.
//
// RETURNS:
//  An Error object describing the problem.
// 
// PRE-CONDITIONS:
//  Performs meaningful checking if fromISO() has just been performed.
// 
// POST-CONDITIONS:
//  Nothing changes.
// 
// ERRORS:
//  error_None
//  error_Invalid_EA_length
//
// (If compiled with -D_PICKY_EA_INSPECTOR_, the following are also
//  possible:)
//  error_Invalid_EA_type
//  error_Invalid_EA_subtype
// 
// NOTES:
//  <Notes_go_here>
//
//----------------------------------------------------------------------
// Private comments go here - will not be extracted into HTML.
//----------------------------------------------------------------------
NSR::Error
NSR::EAInspector::error( void ) const
{
    Error err;
    
#ifdef _PICKY_EA_INSPECTOR_
    if ( err = eaPrefix_.checkValidity())
        return err;
#endif //_PICKY_EA_INSPECTOR_
    if ( err = attrID_.error() )
        return err;
    if ( minAttrLen() > attrLen() )
        err = error_EA_Invalid_EA_length;
    return err;
}

//----------------------------------------------------------------------
// METHOD: EAInspector::fromISO  --DVM
//      
//  Translates the on-disk structure at the supplied address into its
//  in-core data members.
//
//  
//
// ARGS:
//  CONST_BYTE_PTR   rbp   IN  Address where structure starts.
//
// RETURNS:
//  none.
// 
// PRE-CONDITIONS:
//  
// 
// POST-CONDITIONS:
//  List_postconditions (E.g., changes to class data members)
// 
// ERRORS:
//  error_
//  error_
//  error_
// 
// NOTES:
//  <Notes_go_here>
//
//----------------------------------------------------------------------
// Private comments go here - will not be extracted into HTML.
//----------------------------------------------------------------------
void
NSR::EAInspector::fromISO( CONST_BYTE_PTR rbp ) 
{
    // First, clear all data members. This makes sure that if it is
    // not a plain EA, the attrID() method will return an empty
    // string, and that the default varyingLen is 0.
    clear();

    // Now, perform fromISO() on all the fields known to be valid for
    // the EA. 

    // Then, read in the prefix, which is valid for all EAs.
    eaPrefix_.fromISO(rbp);

    // Only the AlternatePerms EA and unknown EAs do not have a length
    // field, so leave the varyingLen at zero, but read in the field
    // for all the others.
    if (( eaPrefix_.attrType() != ea_AlternatePerms ) &&
        ( eaPrefix_.attrType() != ea_Unknown )) {
        
        varyingLen_.fromISO(rbp);

        // If it is one of the implementation or application use EAs,
        // also grab its RegID. Otherwise, leave it blank.
        if (( eaPrefix_.attrType() == ea_ImplementUse ) ||
            ( eaPrefix_.attrType() == ea_ApplicationUse )) {

            attrID_.fromISO(rbp);
        }
    }

    // Now, do the switching to fill in the fixedLen_ data member from
    // the static functions associated with the appropriate EAs.
    switch (eaPrefix_.attrType() ) {
    case ea_AlternatePerms:
        fixedLen_ = AlternatePermsEA::fixedLen(); break;
    case ea_CharSetInfo:
        fixedLen_ =    CharSetInfoEA::fixedLen(); break;
    case ea_FileTimes:
        fixedLen_ =      FileTimesEA::fixedLen(); break;
    case ea_InfoTimes:
        fixedLen_ =      InfoTimesEA::fixedLen(); break;
    case ea_DeviceSpec:
        fixedLen_ =     DeviceSpecEA::fixedLen(); break;
    case ea_ImplementUse:
        fixedLen_ =   ImplementUseEA::fixedLen(); break;
    case ea_ApplicationUse:
        fixedLen_ = ApplicationUseEA::fixedLen(); break;
    case ea_Unknown:
    default:
        // If we cannot identify the EA, we make sure it is not shrunk
        // during padding by assuming that the entire attrLen IS the
        // minimum attrLen, with varyingLen = 0 and fixedLen =
        // attrLen.
        fixedLen_ = eaPrefix_.attrLen(); break;
    }
}


// SearchEA

NSR::SearchEA::SearchEA() :
        eaPrefix_     ( 0 ),    // These overlap -- read only
        impleaPrefix_ ( 0 ),    // These overlap -- read only
        udfeaPrefix_  ( 0 ),    // These overlap -- read only
        hpEAType_     ( 48 )    // Follows impleaPrefix_
{}    

void
NSR::SearchEA::fromISO( CONST_BYTE_PTR rbp )
{
    eaPrefix_     .fromISO( rbp );
    impleaPrefix_ .fromISO( rbp );
    udfeaPrefix_  .fromISO( rbp );
    hpEAType_     .fromISO( rbp );
}

NSR::Error
NSR::SearchEA::error( CONST_BYTE_PTR rbp ) const
{
    if ( eaPrefix_.attrType() != ea_ImplementUse &&
         eaPrefix_.attrType() != ea_ApplicationUse ) {
        // Not an impl or an appl EA. Only check eaPrefix.
        return eaPrefix_.checkValidity();
    }
    // impl or appl EA. So figure out which type it is.
    SupportedEAType eat = eaType();
    if ( eat == sea_ImplementUse   ||
         eat == sea_HPICBTable     ||
         eat == sea_HPOther        ||
         eat == sea_ApplicationUse ||
         eat == sea_Unknown          ) {
        // non UDF EA. Don't check udfeaPrefix.
        return impleaPrefix_.checkValidity();
    } else {
        // UDF EA. Check udfeaPrefix.
        Error err = udfeaPrefix_.error();
        if ( err )
            return err;
        else
            return udfeaPrefix_.checkValidity(rbp);
    }
}

NSR::SupportedEAType
NSR::SearchEA::eaType() const
{
    if ( eaPrefix_.checkValidity() )
        return sea_Unknown;
    switch (eaPrefix_.attrType()) {
    case ea_CharSetInfo    : return sea_CharSetInfo     ;
    case ea_AlternatePerms : return sea_AlternatePerms  ;
    case ea_FileTimes      : return sea_FileTimes       ;
    case ea_InfoTimes      : return sea_InfoTimes       ;
    case ea_DeviceSpec     : return sea_DeviceSpec      ;
    case ea_ImplementUse   : {
        String id(udfeaPrefix_.id());
        if ( id == HPNovellAttrID        ) return sea_HPNovellAttr       ;
        if ( id == HPNovellTrusteeID     ) return sea_HPNovellTrustee    ;
        if ( id == UDFFreeEASpaceID      ) return sea_UDFFreeEASpace      ;
        if ( id == UDFOS2ID              ) return sea_UDFOS2              ;
        if ( id == UDFOS2EALengthID      ) return sea_UDFOS2EALength      ;
        if ( id == UDFMacVolumeInfoID    ) return sea_UDFMacVolumeInfo    ;
        if ( id == UDFMacFinderInfoID    ) return sea_UDFMacFinderInfo    ;
        if ( id == UDFMacUniqueIDTableID ) return sea_UDFMacUniqueIDTable ;
        if ( id == UDFMacResourceForkID  ) return sea_UDFMacResourceFork  ;
        if ( id == ImplRegID::HPID       ) {
            if ( hpEAType_ == hpea_ICBTable ) {
                return sea_HPICBTable   ;
            } else {
                return sea_HPOther      ;
            }
        } else if ( id == HPEarlyICBTableID ) {
            return sea_HPICBTable ;
        } else {
            return sea_ImplementUse ;
        }
    }
    case ea_ApplicationUse : return sea_ApplicationUse  ;
    case ea_Unknown :
    default : return sea_Unknown ;
    }
}

// Returns empty String if no ID field.
NSR::String
NSR::SearchEA::id() const
{
    if ( eaPrefix_.attrType() == ea_ImplementUse ||
         eaPrefix_.attrType() == ea_ApplicationUse )
        return impleaPrefix_.id();
    return String("");
}
