posixacladdons.cpp
00001 /*************************************************************************** 00002 * Copyright (C) 2005 by Markus Brueffer <markus@brueffer.de> * 00003 * * 00004 * This program is free software; you can redistribute it and/or modify * 00005 * it under the terms of the GNU Library General Public License as * 00006 * published by the Free Software Foundation; either version 2 of the * 00007 * License, or (at your option) any later version. * 00008 * * 00009 * This program is distributed in the hope that it will be useful, * 00010 * but WITHOUT ANY WARRANTY; without even the implied warranty of * 00011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * 00012 * GNU General Public License for more details. * 00013 * * 00014 * You should have received a copy of the GNU General Public License * 00015 * along with this program; if not, write to the * 00016 * Free Software Foundation, Inc., * 00017 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * 00018 ***************************************************************************/ 00019 00020 #include "posixacladdons.h" 00021 00022 #if defined(USE_POSIX_ACL) && !defined(HAVE_NON_POSIX_ACL_EXTENSIONS) 00023 00024 #include <kdemacros.h> 00025 00026 #include <errno.h> 00027 #include <sys/stat.h> 00028 00029 #include <tqptrlist.h> 00030 00031 class SortedEntryList : public TQPtrList<acl_entry_t> 00032 { 00033 protected: 00034 int compareItems( TQPtrCollection::Item i1, 00035 TQPtrCollection::Item i2 ) 00036 { 00037 acl_entry_t *e1 = static_cast<acl_entry_t*>( i1 ); 00038 acl_entry_t *e2 = static_cast<acl_entry_t*>( i2 ); 00039 00040 acl_tag_t tag1, tag2; 00041 uid_t uid1 = 0, uid2 = 0; 00042 00043 acl_get_tag_type( *e1, &tag1 ); 00044 acl_get_tag_type( *e2, &tag2 ); 00045 00046 if ( tag1 == ACL_USER || tag1 == ACL_GROUP ) 00047 uid1 = *( (uid_t*) acl_get_qualifier( *e1 ) ); 00048 00049 if ( tag2 == ACL_USER || tag2 == ACL_GROUP ) 00050 uid2 = *( (uid_t*) acl_get_qualifier( *e2 ) ); 00051 00052 if ( tag1 < tag2 ) 00053 return -1; 00054 else if ( tag1 > tag2 ) 00055 return 1; 00056 00057 if ( uid1 < uid2 ) 00058 return -1; 00059 else if ( uid1 > uid2 ) 00060 return 1; 00061 00062 return 0; 00063 } 00064 }; 00065 00066 KDE_EXPORT int acl_cmp(acl_t acl1, acl_t acl2) 00067 { 00068 if ( !acl1 || !acl2 ) 00069 return -1; 00070 00071 SortedEntryList entries1, entries2; 00072 entries1.setAutoDelete( true ); 00073 entries2.setAutoDelete( true ); 00074 00075 /* Add ACL entries to vectors */ 00076 acl_entry_t *entry = new acl_entry_t; 00077 int ret = acl_get_entry( acl1, ACL_FIRST_ENTRY, entry ); 00078 while( ret == 1 ) { 00079 entries1.append( entry ); 00080 entry = new acl_entry_t; 00081 ret = acl_get_entry( acl1, ACL_NEXT_ENTRY, entry ); 00082 } 00083 delete entry; 00084 00085 entry = new acl_entry_t; 00086 ret = acl_get_entry( acl2, ACL_FIRST_ENTRY, entry ); 00087 while ( ret == 1 ) { 00088 entries2.append( entry ); 00089 entry = new acl_entry_t; 00090 ret = acl_get_entry( acl2, ACL_NEXT_ENTRY, entry ); 00091 } 00092 delete entry; 00093 00094 /* If the entry count differs, we are done */ 00095 if ( entries1.count() != entries2.count() ) 00096 return 1; 00097 00098 /* Sort vectors */ 00099 entries1.sort(); 00100 entries2.sort(); 00101 00102 /* Compare all entries */ 00103 acl_permset_t permset1, permset2; 00104 acl_tag_t tag1, tag2; 00105 uid_t uid1, uid2; 00106 acl_entry_t *e1, *e2; 00107 00108 for ( e1 = entries1.first(), e2 = entries2.first(); e1; e1 = entries1.next(), e2 = entries2.next() ) { 00109 /* Compare tag */ 00110 if ( acl_get_tag_type( *e1, &tag1 ) != 0 ) return 1; 00111 if ( acl_get_tag_type( *e2, &tag2 ) != 0 ) return 1; 00112 if ( tag1 != tag2 ) return 1; 00113 00114 /* Compare permissions */ 00115 if ( acl_get_permset( *e1, &permset1 ) != 0 ) return 1; 00116 if ( acl_get_permset( *e2, &permset2 ) != 0 ) return 1; 00117 if ( *permset1 != *permset2) return 1; 00118 00119 /* Compare uid */ 00120 switch( tag1 ) { 00121 case ACL_USER: 00122 case ACL_GROUP: 00123 uid1 = *( (uid_t*) acl_get_qualifier( *e1 ) ); 00124 uid2 = *( (uid_t*) acl_get_qualifier( *e2 ) ); 00125 if ( uid1 != uid2 ) return 1; 00126 } 00127 } 00128 00129 return 0; 00130 } 00131 00132 KDE_EXPORT acl_t acl_from_mode(mode_t mode) 00133 { 00134 acl_t newACL = acl_init( 3 ); 00135 acl_entry_t entry; 00136 acl_permset_t permset; 00137 int error = 0; 00138 00139 /* Add owner entry */ 00140 if ( ( error = acl_create_entry( &newACL, &entry ) ) == 0 ) { 00141 /* Set owner permissions */ 00142 acl_set_tag_type( entry, ACL_USER_OBJ ); 00143 acl_get_permset( entry, &permset ); 00144 acl_clear_perms( permset ); 00145 if ( mode & S_IRUSR ) acl_add_perm( permset, ACL_READ ); 00146 if ( mode & S_IWUSR ) acl_add_perm( permset, ACL_WRITE ); 00147 if ( mode & S_IXUSR ) acl_add_perm( permset, ACL_EXECUTE ); 00148 acl_set_permset( entry, permset ); 00149 00150 /* Add group entry */ 00151 if ( ( error = acl_create_entry( &newACL, &entry ) ) == 0 ) { 00152 /* Set group permissions */ 00153 acl_set_tag_type( entry, ACL_GROUP_OBJ ); 00154 acl_get_permset( entry, &permset ); 00155 acl_clear_perms( permset ); 00156 if ( mode & S_IRGRP ) acl_add_perm( permset, ACL_READ ); 00157 if ( mode & S_IWGRP ) acl_add_perm( permset, ACL_WRITE ); 00158 if ( mode & S_IXGRP ) acl_add_perm( permset, ACL_EXECUTE ); 00159 acl_set_permset( entry, permset ); 00160 00161 /* Add other entry */ 00162 if ( ( error = acl_create_entry( &newACL, &entry ) ) == 0) { 00163 /* Set other permissions */ 00164 acl_set_tag_type( entry, ACL_OTHER ); 00165 acl_get_permset( entry, &permset ); 00166 acl_clear_perms( permset ); 00167 if ( mode & S_IROTH ) acl_add_perm( permset, ACL_READ ); 00168 if ( mode & S_IWOTH ) acl_add_perm( permset, ACL_WRITE ); 00169 if ( mode & S_IXOTH ) acl_add_perm( permset, ACL_EXECUTE ); 00170 acl_set_permset( entry, permset ); 00171 } 00172 } 00173 } 00174 00175 if ( error ) { 00176 acl_free ( &newACL ); 00177 return NULL; 00178 } 00179 00180 return newACL; 00181 } 00182 00183 KDE_EXPORT int acl_equiv_mode(acl_t acl, mode_t *mode_p) 00184 { 00185 acl_entry_t entry; 00186 acl_tag_t tag; 00187 acl_permset_t permset; 00188 mode_t mode = 0; 00189 int notEquiv = 0; 00190 00191 if ( !acl ) 00192 return -1; 00193 00194 int ret = acl_get_entry( acl, ACL_FIRST_ENTRY, &entry ); 00195 while ( ret == 1 ) { 00196 acl_get_tag_type( entry, &tag ); 00197 acl_get_permset( entry, &permset ); 00198 00199 switch( tag ) { 00200 case ACL_USER_OBJ: 00201 if ( acl_get_perm( permset, ACL_READ ) ) mode |= S_IRUSR; 00202 if ( acl_get_perm( permset, ACL_WRITE ) ) mode |= S_IWUSR; 00203 if ( acl_get_perm( permset, ACL_EXECUTE ) ) mode |= S_IXUSR; 00204 break; 00205 00206 case ACL_GROUP_OBJ: 00207 if ( acl_get_perm( permset, ACL_READ ) ) mode |= S_IRGRP; 00208 if ( acl_get_perm( permset, ACL_WRITE ) ) mode |= S_IWGRP; 00209 if ( acl_get_perm( permset, ACL_EXECUTE ) ) mode |= S_IXGRP; 00210 break; 00211 00212 case ACL_OTHER: 00213 if ( acl_get_perm( permset, ACL_READ ) ) mode |= S_IROTH; 00214 if ( acl_get_perm( permset, ACL_WRITE ) ) mode |= S_IWOTH; 00215 if ( acl_get_perm( permset, ACL_EXECUTE ) ) mode |= S_IXOTH; 00216 break; 00217 00218 case ACL_USER: 00219 case ACL_GROUP: 00220 case ACL_MASK: 00221 notEquiv = 1; 00222 break; 00223 00224 default: 00225 errno = EINVAL; 00226 return -1; 00227 } 00228 00229 ret = acl_get_entry( acl, ACL_NEXT_ENTRY, &entry ); 00230 } 00231 00232 if (mode_p) 00233 *mode_p = mode; 00234 00235 return notEquiv; 00236 } 00237 00238 #endif // USE_POSIX_ACL