23#include <config-acl.h>
31#include <acl/libacl.h>
41class KACL::KACLPrivate {
43 KACLPrivate() : m_acl( 0 ) {}
45 KACLPrivate( acl_t acl )
47 ~KACLPrivate() {
if ( m_acl ) acl_free( m_acl ); }
52 QString getUserName( uid_t uid )
const;
53 QString getGroupName( gid_t gid )
const;
54 bool setAllUsersOrGroups(
const QList< QPair<QString, unsigned short> > &list, acl_tag_t type );
55 bool setNamedUserOrGroupPermissions(
const QString& name,
unsigned short permissions, acl_tag_t type );
61 mutable QHash<uid_t, QString> m_usercache;
62 mutable QHash<gid_t, QString> m_groupcache;
66 : d( new KACLPrivate )
75 : d(
new KACLPrivate )
84 : d( new KACLPrivate )
89 : d( new KACLPrivate )
108 return ( acl_cmp( d->m_acl, rhs.d->m_acl ) == 0 );
125 valid = ( acl_valid( d->m_acl ) == 0 );
134 return ( acl_equiv_mode( d->m_acl, NULL ) != 0 );
141static acl_entry_t entryForTag( acl_t acl, acl_tag_t tag )
144 int ret = acl_get_entry( acl, ACL_FIRST_ENTRY, &entry );
146 acl_tag_t currentTag;
147 acl_get_tag_type( entry, ¤tTag );
148 if ( currentTag == tag )
150 ret = acl_get_entry( acl, ACL_NEXT_ENTRY, &entry );
155static unsigned short entryToPermissions( acl_entry_t entry )
157 if ( entry == 0 )
return 0;
158 acl_permset_t permset;
159 if ( acl_get_permset( entry, &permset ) != 0 )
return 0;
160 return( acl_get_perm( permset, ACL_READ ) << 2 |
161 acl_get_perm( permset, ACL_WRITE ) << 1 |
162 acl_get_perm( permset, ACL_EXECUTE ) );
165static void permissionsToEntry( acl_entry_t entry,
unsigned short v )
167 if ( entry == 0 )
return;
168 acl_permset_t permset;
169 if ( acl_get_permset( entry, &permset ) != 0 )
return;
170 acl_clear_perms( permset );
171 if ( v & 4 ) acl_add_perm( permset, ACL_READ );
172 if ( v & 2 ) acl_add_perm( permset, ACL_WRITE );
173 if ( v & 1 ) acl_add_perm( permset, ACL_EXECUTE );
178static void printACL( acl_t acl,
const QString &comment )
180 const char* txt = acl_to_text(acl);
181 kDebug() << comment << txt;
187static int getUidForName(
const QString& name )
189 struct passwd *user = getpwnam(
name.toLocal8Bit() );
196static int getGidForName(
const QString& name )
198 struct group *group = getgrnam( name.toLocal8Bit() );
200 return group->gr_gid;
210 return entryToPermissions( entryForTag( d->m_acl, ACL_USER_OBJ ) );
219 permissionsToEntry( entryForTag( d->m_acl, ACL_USER_OBJ ), v );
229 return entryToPermissions( entryForTag( d->m_acl, ACL_GROUP_OBJ ) );
238 permissionsToEntry( entryForTag( d->m_acl, ACL_GROUP_OBJ ), v );
248 return entryToPermissions( entryForTag( d->m_acl, ACL_OTHER ) );
257 permissionsToEntry( entryForTag( d->m_acl, ACL_OTHER ), v );
285 acl_entry_t entry = entryForTag( d->m_acl, ACL_MASK );
290 return entryToPermissions( entry );
297bool KACL::KACLPrivate::setMaskPermissions(
unsigned short v )
299 acl_entry_t entry = entryForTag( m_acl, ACL_MASK );
301 acl_create_entry( &m_acl, &entry );
302 acl_set_tag_type( entry, ACL_MASK );
304 permissionsToEntry( entry, v );
312 return d->setMaskPermissions( v );
328 int ret = acl_get_entry( d->m_acl, ACL_FIRST_ENTRY, &entry );
330 acl_tag_t currentTag;
331 acl_get_tag_type( entry, ¤tTag );
332 if ( currentTag == ACL_USER ) {
333 id = *( (uid_t*) acl_get_qualifier( entry ) );
334 if ( d->getUserName(
id ) == name ) {
336 return entryToPermissions( entry );
339 ret = acl_get_entry( d->m_acl, ACL_NEXT_ENTRY, &entry );
349bool KACL::KACLPrivate::setNamedUserOrGroupPermissions(
const QString& name,
unsigned short permissions, acl_tag_t type )
351 bool allIsWell =
true;
352 acl_t newACL = acl_dup( m_acl );
354 bool createdNewEntry =
false;
356 int ret = acl_get_entry( newACL, ACL_FIRST_ENTRY, &entry );
358 acl_tag_t currentTag;
359 acl_get_tag_type( entry, ¤tTag );
360 if ( currentTag == type ) {
361 int id = * (
int*)acl_get_qualifier( entry );
362 const QString entryName = type == ACL_USER? getUserName(
id ): getGroupName( id );
363 if ( entryName == name ) {
365 permissionsToEntry( entry, permissions );
370 ret = acl_get_entry( newACL, ACL_NEXT_ENTRY, &entry );
373 acl_create_entry( &newACL, &entry );
374 acl_set_tag_type( entry, type );
375 int id = type == ACL_USER? getUidForName( name ): getGidForName(
name );
376 if (
id == -1 || acl_set_qualifier( entry, &
id ) != 0 ) {
377 acl_delete_entry( newACL, entry );
380 permissionsToEntry( entry, permissions );
381 createdNewEntry =
true;
384 if ( allIsWell && createdNewEntry ) {
388 if ( entryForTag( newACL, ACL_MASK ) == 0 ) {
389 acl_calc_mask( &newACL );
393 if ( !allIsWell || acl_valid( newACL ) != 0 ) {
407 return d->setNamedUserOrGroupPermissions( name, permissions, ACL_USER );
410 Q_UNUSED( permissions );
421 int ret = acl_get_entry( d->m_acl, ACL_FIRST_ENTRY, &entry );
423 acl_tag_t currentTag;
424 acl_get_tag_type( entry, ¤tTag );
425 if ( currentTag == ACL_USER ) {
426 id = *( (uid_t*) acl_get_qualifier( entry ) );
427 QString name = d->getUserName(
id );
428 unsigned short permissions = entryToPermissions( entry );
432 ret = acl_get_entry( d->m_acl, ACL_NEXT_ENTRY, &entry );
441 bool allIsWell =
true;
442 bool atLeastOneUserOrGroup =
false;
445 acl_t newACL = acl_dup( m_acl );
450 int ret = acl_get_entry( newACL, ACL_FIRST_ENTRY, &entry );
452 acl_tag_t currentTag;
453 acl_get_tag_type( entry, ¤tTag );
454 if ( currentTag == type ) {
455 acl_delete_entry( newACL, entry );
458 ret = acl_get_entry( newACL, ACL_FIRST_ENTRY, &entry );
460 ret = acl_get_entry( newACL, ACL_NEXT_ENTRY, &entry );
466 QList< QPair<QString, unsigned short> >::const_iterator it =
list.constBegin();
467 while ( it !=
list.constEnd() ) {
468 acl_create_entry( &newACL, &entry );
469 acl_set_tag_type( entry, type );
470 int id = type == ACL_USER? getUidForName( (*it).first):getGidForName( (*it).first );
471 if (
id == -1 || acl_set_qualifier( entry, &
id ) != 0 ) {
473 acl_delete_entry( newACL, entry );
477 permissionsToEntry( entry, (*it).second );
478 atLeastOneUserOrGroup =
true;
483 if ( allIsWell && atLeastOneUserOrGroup ) {
487 if ( entryForTag( newACL, ACL_MASK ) == 0 ) {
488 acl_calc_mask( &newACL );
491 if ( allIsWell && ( acl_valid( newACL ) == 0 ) ) {
504 return d->setAllUsersOrGroups( users, ACL_USER );
522 int ret = acl_get_entry( d->m_acl, ACL_FIRST_ENTRY, &entry );
524 acl_tag_t currentTag;
525 acl_get_tag_type( entry, ¤tTag );
526 if ( currentTag == ACL_GROUP ) {
527 id = *( (gid_t*) acl_get_qualifier( entry ) );
528 if ( d->getGroupName(
id ) == name ) {
530 return entryToPermissions( entry );
533 ret = acl_get_entry( d->m_acl, ACL_NEXT_ENTRY, &entry );
544 return d->setNamedUserOrGroupPermissions( name, permissions, ACL_GROUP );
547 Q_UNUSED( permissions );
559 int ret = acl_get_entry( d->m_acl, ACL_FIRST_ENTRY, &entry );
561 acl_tag_t currentTag;
562 acl_get_tag_type( entry, ¤tTag );
563 if ( currentTag == ACL_GROUP ) {
564 id = *( (gid_t*) acl_get_qualifier( entry ) );
565 QString name = d->getGroupName(
id );
566 unsigned short permissions = entryToPermissions( entry );
570 ret = acl_get_entry( d->m_acl, ACL_NEXT_ENTRY, &entry );
579 return d->setAllUsersOrGroups( groups, ACL_GROUP );
594 acl_t temp = acl_from_text( aclStr.toLatin1() );
595 if ( acl_valid( temp ) != 0 ) {
600 acl_free( d->m_acl );
614 char* txt = acl_to_text(d->m_acl, &size);
615 const QString ret = QString::fromLatin1(txt, size);
627QString KACL::KACLPrivate::getUserName( uid_t uid )
const
629 if ( !m_usercache.contains( uid ) ) {
630 struct passwd *user = getpwuid( uid );
632 m_usercache.insert( uid, QString::fromLatin1(user->pw_name) );
635 return QString::number( uid );
637 return m_usercache[uid];
641QString KACL::KACLPrivate::getGroupName( gid_t gid )
const
643 if ( !m_groupcache.contains( gid ) ) {
644 struct group *grp = getgrgid( gid );
646 m_groupcache.insert( gid, QString::fromLatin1(grp->gr_name) );
649 return QString::number( gid );
651 return m_groupcache[gid];
KACL()
Creates an empty KACL.
bool setNamedGroupPermissions(const QString &name, unsigned short)
Set the permissions for a group with the name name.
unsigned short maskPermissions(bool &exists) const
Return the entry for the permissions mask if there is one and sets exists to true.
unsigned short namedGroupPermissions(const QString &name, bool *exists) const
Access to the permissions entry for a named group, if such an entry exists.
unsigned short namedUserPermissions(const QString &name, bool *exists) const
Access to the permissions entry for a named user, if such an entry exists.
friend QDataStream & operator>>(QDataStream &s, KACL &a)
bool isExtended() const
The interface to the extended ACL.
bool setOthersPermissions(unsigned short)
Set the permissions entry for others.
bool setMaskPermissions(unsigned short)
Set the permissions mask for the ACL.
KACL & operator=(const KACL &rhs)
bool setACL(const QString &aclStr)
Sets the whole list from a string.
mode_t basePermissions() const
KACL(const QString &aclString)
Creates a new KACL from aclString.
bool isValid() const
Returns whether the KACL object represents a valid acl.
bool setOwningGroupPermissions(unsigned short)
Set the owning group's permissions entry.
virtual void virtual_hook(int id, void *data)
bool operator==(const KACL &rhs) const
ACLGroupPermissionsList allGroupPermissions() const
Returns the list of all group permission entries.
bool setOwnerPermissions(unsigned short)
Set the owner's permissions entry.
friend QDataStream & operator<<(QDataStream &s, const KACL &a)
unsigned short othersPermissions() const
bool setAllUserPermissions(const ACLUserPermissionsList &list)
Replace the list of all user permissions with list.
bool setNamedUserPermissions(const QString &name, unsigned short)
Set the permissions for a user with the name name.
ACLUserPermissionsList allUserPermissions() const
Returns the list of all group permission entries.
bool operator!=(const KACL &rhs) const
QString asString() const
Return a string representation of the ACL.
bool setAllGroupPermissions(const ACLGroupPermissionsList &)
Replace the list of all user permissions with list.
unsigned short ownerPermissions() const
The standard (non-extended) part of an ACL.
unsigned short owningGroupPermissions() const
static QDebug kDebug(bool cond, int area=KDE_DEFAULT_DEBUG_AREA)
QList< ACLGroupPermissions > ACLGroupPermissionsList
QPair< QString, unsigned short > ACLGroupPermissions
QList< ACLUserPermissions > ACLUserPermissionsList
QPair< QString, unsigned short > ACLUserPermissions
QStringList list(const QString &fileClass)
Returns a list of directories associated with this file-class.
const char * name(StandardAction id)