Index: configure.in.in =================================================================== --- configure.in.in (revision 458545) +++ configure.in.in (working copy) @@ -50,13 +50,19 @@ USE_POSIX_ACL="yes" ACL_LIBS="" -KDE_CHECK_HEADER(sys/xattr.h, ,[USE_POSIX_ACL="no"]) KDE_CHECK_HEADER(sys/acl.h, ,[USE_POSIX_ACL="no"]) -KDE_CHECK_HEADER(acl/libacl.h, ,[USE_POSIX_ACL="no"]) -KDE_CHECK_LIB(acl,acl_init, ,[USE_POSIX_ACL="no"]) +case $host in + *-*-freebsd*) + KDE_CHECK_LIB(c,acl_init,[ACL_LIBS="-lc"],[USE_POSIX_ACL="no"]) + ;; + *) + KDE_CHECK_HEADER(sys/xattr.h, ,[USE_POSIX_ACL="no"]) + KDE_CHECK_HEADER(acl/libacl.h, ,[USE_POSIX_ACL="no"]) + KDE_CHECK_LIB(acl,acl_init,[ACL_LIBS="-lacl -lattr"],[USE_POSIX_ACL="no"]) + ;; +esac if test $USE_POSIX_ACL = "yes" ; then - ACL_LIBS="-lacl -lattr" AC_DEFINE([USE_POSIX_ACL], 1, [Define if system has POSIX ACL support.]) fi AC_SUBST(ACL_LIBS) Index: kio/kio/kacl.cpp =================================================================== --- kio/kio/kacl.cpp (revision 458549) +++ kio/kio/kacl.cpp (working copy) @@ -28,9 +28,12 @@ #include #ifdef USE_POSIX_ACL #include +#ifdef Q_OS_LINUX #include #endif +#endif #include +#include #include @@ -41,6 +44,37 @@ static void printACL( acl_t acl, const QString &comment ); #endif +class SortedEntryList : public QPtrList { +protected: + int compareItems( QPtrCollection::Item i1, + QPtrCollection::Item i2 ) + { + acl_entry_t e1 = static_cast( i1 ); + acl_entry_t e2 = static_cast( i2 ); + + acl_tag_t *e1Tag = 0, *e2Tag = 0; + uid_t e1ID, e2ID; + + acl_get_tag_type( e1, e1Tag ); + acl_get_tag_type( e2, e2Tag ); + + e1ID = *( (uid_t*) acl_get_qualifier( e1 ) ); + e2ID = *( (uid_t*) acl_get_qualifier( e2 ) ); + + if ( *e1Tag < *e2Tag ) + return -1; + else if ( *e1Tag > *e2Tag ) + return 1; + + if ( e1ID < e2ID ) + return -1; + else if ( e1ID > e2ID ) + return 1; + + return 0; + } +}; + class KACL::KACLPrivate { public: KACLPrivate() : m_acl( 0 ) { init(); } @@ -76,12 +110,59 @@ } KACL::KACL( mode_t basePermissions ) -#ifdef USE_POSIX_ACL +#if defined(USE_POSIX_ACL) && defined(Q_OS_LINUX) : d( new KACLPrivate( acl_from_mode( basePermissions ) ) ) #else : d( new KACLPrivate ) #endif { +#if defined(USE_POSIX_ACL) && !defined(Q_OS_LINUX) + acl_t newACL = acl_init( 3 ); + acl_entry_t entry; + acl_permset_t permset = 0; + + /* Add owner entry */ + if ( acl_create_entry( &newACL, &entry ) != 0 ) + goto fail; + + /* Set owner permissions */ + acl_set_tag_type( entry, ACL_USER_OBJ ); + acl_clear_perms( permset ); + if ( basePermissions & S_IRUSR ) acl_add_perm( permset, ACL_READ ); + if ( basePermissions & S_IWUSR ) acl_add_perm( permset, ACL_WRITE ); + if ( basePermissions & S_IXUSR ) acl_add_perm( permset, ACL_EXECUTE ); + acl_set_permset( entry, permset ); + + /* Add group entry */ + if ( acl_create_entry( &newACL, &entry ) != 0 ) + goto fail; + + /* Set group permissions */ + acl_set_tag_type( entry, ACL_GROUP_OBJ ); + acl_clear_perms( permset ); + if ( basePermissions & S_IRGRP ) acl_add_perm( permset, ACL_READ ); + if ( basePermissions & S_IWGRP ) acl_add_perm( permset, ACL_WRITE ); + if ( basePermissions & S_IXGRP ) acl_add_perm( permset, ACL_EXECUTE ); + acl_set_permset( entry, permset ); + + /* Add other entry */ + if ( acl_create_entry( &newACL, &entry ) != 0 ) + goto fail; + + /* Set other permissions */ + acl_set_tag_type( entry, ACL_OTHER ); + acl_clear_perms( permset ); + if ( basePermissions & S_IROTH ) acl_add_perm( permset, ACL_READ ); + if ( basePermissions & S_IWOTH ) acl_add_perm( permset, ACL_WRITE ); + if ( basePermissions & S_IXOTH ) acl_add_perm( permset, ACL_EXECUTE ); + acl_set_permset( entry, permset ); + + d->m_acl = newACL; + return; + +fail: + acl_free( &newACL ); +#endif } KACL::KACL() @@ -102,7 +183,64 @@ bool KACL::operator==( const KACL& rhs ) const { #ifdef USE_POSIX_ACL + #ifdef Q_OS_LINUX return ( acl_cmp( d->m_acl, rhs.d->m_acl ) == 0 ); + #else + /* Add ACL entries to vectors */ + SortedEntryList entries1, entries2; + entries1.setAutoDelete( true ); + entries2.setAutoDelete( true ); + acl_entry_t entry; + + int ret = acl_get_entry( d->m_acl, ACL_FIRST_ENTRY, &entry ); + while( ret == 1 ) { + entries1.append( &entry ); + ret = acl_get_entry( d->m_acl, ACL_NEXT_ENTRY, &entry ); + } + + ret = acl_get_entry( rhs.d->m_acl, ACL_FIRST_ENTRY, &entry ); + while ( ret == 1 ) { + entries2.append( &entry ); + ret = acl_get_entry( rhs.d->m_acl, ACL_NEXT_ENTRY, &entry ); + } + + /* If the entry count differs, we are done */ + if ( entries1.count() != entries2.count() ) + return false; + + /* Sort vectors */ + entries1.sort(); + entries2.sort(); + + /* Compare all entries */ + acl_permset_t permset1, permset2; + acl_tag_t tag1, tag2; + uid_t uid1, uid2; + acl_entry_t *e1, *e2; + + for ( e1 = entries1.first(), e2 = entries2.first(); e1; e1 = entries1.next(), e2 = entries2.next() ) { + /* Compare tag */ + if ( acl_get_tag_type( *e1, &tag1 ) != 0 ) return false; + if ( acl_get_tag_type( *e2, &tag2 ) != 0 ) return false; + if ( tag1 != tag2 ) return false; + + /* Compare permissions */ + if ( acl_get_permset( *e1, &permset1 ) != 0 ) return false; + if ( acl_get_permset( *e2, &permset2 ) != 0 ) return false; + if ( *permset1 != *permset2) return false; + + /* Compare uid */ + switch( tag1 ) { + case ACL_USER: + case ACL_GROUP: + uid1 = *( (uid_t*) acl_get_qualifier( *e1 ) ); + uid2 = *( (uid_t*) acl_get_qualifier( *e2 ) ); + if ( uid1 != uid2 ) return false; + } + } + + return true; + #endif #else return true; #endif @@ -122,7 +260,22 @@ bool KACL::isExtended() const { #ifdef USE_POSIX_ACL + #ifdef Q_OS_LINUX return ( acl_equiv_mode( d->m_acl, NULL ) != 0 ); + #else + acl_entry_t entry; + int ret = acl_get_entry( d->m_acl, ACL_FIRST_ENTRY, &entry ); + while ( ret == 1 ) { + acl_tag_t currentTag; + acl_get_tag_type( entry, ¤tTag ); + if ( currentTag != ACL_USER_OBJ && + currentTag != ACL_GROUP_OBJ && + currentTag != ACL_OTHER ) + return true; + ret = acl_get_entry( d->m_acl, ACL_NEXT_ENTRY, &entry ); + } + return false; + #endif #else return false; #endif @@ -148,9 +301,10 @@ if ( entry == 0 ) return 0; acl_permset_t permset; if ( acl_get_permset( entry, &permset ) != 0 ) return 0; - return( acl_get_perm( permset, ACL_READ ) << 2 | - acl_get_perm( permset, ACL_WRITE ) << 1 | - acl_get_perm( permset, ACL_EXECUTE ) ); + + return ( ( *permset & ACL_READ ? 1 : 0 ) << 2 | + ( *permset & ACL_WRITE ? 1 : 0 ) << 1 | + ( *permset & ACL_EXECUTE ? 1 : 0) ); } static void permissionsToEntry( acl_entry_t entry, unsigned short v )