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 <errno.h> 00025 #include <sys/stat.h> 00026 00027 #include <qptrlist.h> 00028 00029 class SortedEntryList : public QPtrList<acl_entry_t> 00030 { 00031 protected: 00032 int compareItems( QPtrCollection::Item i1, 00033 QPtrCollection::Item i2 ) 00034 { 00035 acl_entry_t *e1 = static_cast<acl_entry_t*>( i1 ); 00036 acl_entry_t *e2 = static_cast<acl_entry_t*>( i2 ); 00037 00038 acl_tag_t tag1, tag2; 00039 uid_t uid1 = 0, uid2 = 0; 00040 00041 acl_get_tag_type( *e1, &tag1 ); 00042 acl_get_tag_type( *e2, &tag2 ); 00043 00044 if ( tag1 == ACL_USER || tag1 == ACL_GROUP ) 00045 uid1 = *( (uid_t*) acl_get_qualifier( *e1 ) ); 00046 00047 if ( tag2 == ACL_USER || tag2 == ACL_GROUP ) 00048 uid2 = *( (uid_t*) acl_get_qualifier( *e2 ) ); 00049 00050 if ( tag1 < tag2 ) 00051 return -1; 00052 else if ( tag1 > tag2 ) 00053 return 1; 00054 00055 if ( uid1 < uid2 ) 00056 return -1; 00057 else if ( uid1 > uid2 ) 00058 return 1; 00059 00060 return 0; 00061 } 00062 }; 00063 00064 int acl_cmp(acl_t acl1, acl_t acl2) 00065 { 00066 if ( !acl1 || !acl2 ) 00067 return -1; 00068 00069 SortedEntryList entries1, entries2; 00070 entries1.setAutoDelete( true ); 00071 entries2.setAutoDelete( true ); 00072 00073 /* Add ACL entries to vectors */ 00074 acl_entry_t *entry = new acl_entry_t; 00075 int ret = acl_get_entry( acl1, ACL_FIRST_ENTRY, entry ); 00076 while( ret == 1 ) { 00077 entries1.append( entry ); 00078 entry = new acl_entry_t; 00079 ret = acl_get_entry( acl1, ACL_NEXT_ENTRY, entry ); 00080 } 00081 delete entry; 00082 00083 entry = new acl_entry_t; 00084 ret = acl_get_entry( acl2, ACL_FIRST_ENTRY, entry ); 00085 while ( ret == 1 ) { 00086 entries2.append( entry ); 00087 entry = new acl_entry_t; 00088 ret = acl_get_entry( acl2, ACL_NEXT_ENTRY, entry ); 00089 } 00090 delete entry; 00091 00092 /* If the entry count differs, we are done */ 00093 if ( entries1.count() != entries2.count() ) 00094 return 1; 00095 00096 /* Sort vectors */ 00097 entries1.sort(); 00098 entries2.sort(); 00099 00100 /* Compare all entries */ 00101 acl_permset_t permset1, permset2; 00102 acl_tag_t tag1, tag2; 00103 uid_t uid1, uid2; 00104 acl_entry_t *e1, *e2; 00105 00106 for ( e1 = entries1.first(), e2 = entries2.first(); e1; e1 = entries1.next(), e2 = entries2.next() ) { 00107 /* Compare tag */ 00108 if ( acl_get_tag_type( *e1, &tag1 ) != 0 ) return 1; 00109 if ( acl_get_tag_type( *e2, &tag2 ) != 0 ) return 1; 00110 if ( tag1 != tag2 ) return 1; 00111 00112 /* Compare permissions */ 00113 if ( acl_get_permset( *e1, &permset1 ) != 0 ) return 1; 00114 if ( acl_get_permset( *e2, &permset2 ) != 0 ) return 1; 00115 if ( *permset1 != *permset2) return 1; 00116 00117 /* Compare uid */ 00118 switch( tag1 ) { 00119 case ACL_USER: 00120 case ACL_GROUP: 00121 uid1 = *( (uid_t*) acl_get_qualifier( *e1 ) ); 00122 uid2 = *( (uid_t*) acl_get_qualifier( *e2 ) ); 00123 if ( uid1 != uid2 ) return 1; 00124 } 00125 } 00126 00127 return 0; 00128 } 00129 00130 acl_t acl_from_mode(mode_t mode) 00131 { 00132 acl_t newACL = acl_init( 3 ); 00133 acl_entry_t entry; 00134 acl_permset_t permset; 00135 int error = 0; 00136 00137 /* Add owner entry */ 00138 if ( ( error = acl_create_entry( &newACL, &entry ) ) == 0 ) { 00139 /* Set owner permissions */ 00140 acl_set_tag_type( entry, ACL_USER_OBJ ); 00141 acl_get_permset( entry, &permset ); 00142 acl_clear_perms( permset ); 00143 if ( mode & S_IRUSR ) acl_add_perm( permset, ACL_READ ); 00144 if ( mode & S_IWUSR ) acl_add_perm( permset, ACL_WRITE ); 00145 if ( mode & S_IXUSR ) acl_add_perm( permset, ACL_EXECUTE ); 00146 acl_set_permset( entry, permset ); 00147 00148 /* Add group entry */ 00149 if ( ( error = acl_create_entry( &newACL, &entry ) ) == 0 ) { 00150 /* Set group permissions */ 00151 acl_set_tag_type( entry, ACL_GROUP_OBJ ); 00152 acl_get_permset( entry, &permset ); 00153 acl_clear_perms( permset ); 00154 if ( mode & S_IRGRP ) acl_add_perm( permset, ACL_READ ); 00155 if ( mode & S_IWGRP ) acl_add_perm( permset, ACL_WRITE ); 00156 if ( mode & S_IXGRP ) acl_add_perm( permset, ACL_EXECUTE ); 00157 acl_set_permset( entry, permset ); 00158 00159 /* Add other entry */ 00160 if ( ( error = acl_create_entry( &newACL, &entry ) ) == 0) { 00161 /* Set other permissions */ 00162 acl_set_tag_type( entry, ACL_OTHER ); 00163 acl_get_permset( entry, &permset ); 00164 acl_clear_perms( permset ); 00165 if ( mode & S_IROTH ) acl_add_perm( permset, ACL_READ ); 00166 if ( mode & S_IWOTH ) acl_add_perm( permset, ACL_WRITE ); 00167 if ( mode & S_IXOTH ) acl_add_perm( permset, ACL_EXECUTE ); 00168 acl_set_permset( entry, permset ); 00169 } 00170 } 00171 } 00172 00173 if ( error ) { 00174 acl_free ( &newACL ); 00175 return NULL; 00176 } 00177 00178 return newACL; 00179 } 00180 00181 int acl_equiv_mode(acl_t acl, mode_t *mode_p) 00182 { 00183 acl_entry_t entry; 00184 acl_tag_t tag; 00185 acl_permset_t permset; 00186 mode_t mode = 0; 00187 int notEquiv = 0; 00188 00189 if ( !acl ) 00190 return -1; 00191 00192 int ret = acl_get_entry( acl, ACL_FIRST_ENTRY, &entry ); 00193 while ( ret == 1 ) { 00194 acl_get_tag_type( entry, &tag ); 00195 acl_get_permset( entry, &permset ); 00196 00197 switch( tag ) { 00198 case ACL_USER_OBJ: 00199 if ( acl_get_perm( permset, ACL_READ ) ) mode |= S_IRUSR; 00200 if ( acl_get_perm( permset, ACL_WRITE ) ) mode |= S_IWUSR; 00201 if ( acl_get_perm( permset, ACL_EXECUTE ) ) mode |= S_IXUSR; 00202 break; 00203 00204 case ACL_GROUP_OBJ: 00205 if ( acl_get_perm( permset, ACL_READ ) ) mode |= S_IRGRP; 00206 if ( acl_get_perm( permset, ACL_WRITE ) ) mode |= S_IWGRP; 00207 if ( acl_get_perm( permset, ACL_EXECUTE ) ) mode |= S_IXGRP; 00208 break; 00209 00210 case ACL_OTHER: 00211 if ( acl_get_perm( permset, ACL_READ ) ) mode |= S_IROTH; 00212 if ( acl_get_perm( permset, ACL_WRITE ) ) mode |= S_IWOTH; 00213 if ( acl_get_perm( permset, ACL_EXECUTE ) ) mode |= S_IXOTH; 00214 break; 00215 00216 case ACL_USER: 00217 case ACL_GROUP: 00218 case ACL_MASK: 00219 notEquiv = 1; 00220 break; 00221 00222 default: 00223 errno = EINVAL; 00224 return -1; 00225 } 00226 00227 ret = acl_get_entry( acl, ACL_NEXT_ENTRY, &entry ); 00228 } 00229 00230 if (mode_p) 00231 *mode_p = mode; 00232 00233 return notEquiv; 00234 } 00235 00236 #endif // USE_POSIX_ACL