23 #include <config-acl.h>
25 #include <sys/types.h>
31 #include <acl/libacl.h>
41 class 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;
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 )
73 : d(
new KACLPrivate( acl_from_mode( basePermissions ) ) )
75 : d(
new KACLPrivate )
78 #ifndef HAVE_POSIX_ACL
79 Q_UNUSED( basePermissions );
84 : d( new KACLPrivate )
89 : d( new KACLPrivate )
107 #ifdef HAVE_POSIX_ACL
108 return ( acl_cmp( d->m_acl, rhs.d->m_acl ) == 0 );
123 #ifdef HAVE_POSIX_ACL
125 valid = ( acl_valid( d->m_acl ) == 0 );
133 #ifdef HAVE_POSIX_ACL
134 return ( acl_equiv_mode( d->m_acl, NULL ) != 0 );
140 #ifdef HAVE_POSIX_ACL
141 static 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 );
155 static 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 ) );
165 static 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 );
176 #ifdef HAVE_POSIX_ACL
178 static void printACL( acl_t acl,
const QString &comment )
180 const char* txt = acl_to_text(acl);
181 kDebug() << comment << txt;
187 static int getUidForName(
const QString& name )
189 struct passwd *user = getpwnam( name.toLocal8Bit() );
196 static int getGidForName(
const QString& name )
198 struct group *
group = getgrnam( name.toLocal8Bit() );
200 return group->gr_gid;
209 #ifdef HAVE_POSIX_ACL
210 return entryToPermissions( entryForTag( d->m_acl, ACL_USER_OBJ ) );
218 #ifdef HAVE_POSIX_ACL
219 permissionsToEntry( entryForTag( d->m_acl, ACL_USER_OBJ ), v );
228 #ifdef HAVE_POSIX_ACL
229 return entryToPermissions( entryForTag( d->m_acl, ACL_GROUP_OBJ ) );
237 #ifdef HAVE_POSIX_ACL
238 permissionsToEntry( entryForTag( d->m_acl, ACL_GROUP_OBJ ), v );
247 #ifdef HAVE_POSIX_ACL
248 return entryToPermissions( entryForTag( d->m_acl, ACL_OTHER ) );
256 #ifdef HAVE_POSIX_ACL
257 permissionsToEntry( entryForTag( d->m_acl, ACL_OTHER ), v );
267 #ifdef HAVE_POSIX_ACL
284 #ifdef HAVE_POSIX_ACL
285 acl_entry_t entry = entryForTag( d->m_acl, ACL_MASK );
290 return entryToPermissions( entry );
296 #ifdef HAVE_POSIX_ACL
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 );
311 #ifdef HAVE_POSIX_ACL
312 return d->setMaskPermissions( v );
324 #ifdef HAVE_POSIX_ACL
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 );
348 #ifdef HAVE_POSIX_ACL
349 bool 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 ) {
406 #ifdef HAVE_POSIX_ACL
407 return d->setNamedUserOrGroupPermissions( name, permissions, ACL_USER );
410 Q_UNUSED( permissions );
418 #ifdef HAVE_POSIX_ACL
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 );
438 #ifdef HAVE_POSIX_ACL
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 ) ) {
503 #ifdef HAVE_POSIX_ACL
504 return d->setAllUsersOrGroups( users, ACL_USER );
519 #ifdef HAVE_POSIX_ACL
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 );
543 #ifdef HAVE_POSIX_ACL
544 return d->setNamedUserOrGroupPermissions( name, permissions, ACL_GROUP );
547 Q_UNUSED( permissions );
556 #ifdef HAVE_POSIX_ACL
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 );
578 #ifdef HAVE_POSIX_ACL
579 return d->setAllUsersOrGroups( groups, ACL_GROUP );
593 #ifdef HAVE_POSIX_ACL
594 acl_t temp = acl_from_text( aclStr.toLatin1() );
595 if ( acl_valid( temp ) != 0 ) {
600 acl_free( d->m_acl );
612 #ifdef HAVE_POSIX_ACL
614 char* txt = acl_to_text(d->m_acl, &size);
615 const QString ret = QString::fromLatin1(txt, size);
626 #ifdef HAVE_POSIX_ACL
627 QString 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) );
637 return m_usercache[uid];
641 QString 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) );
651 return m_groupcache[gid];