kio Library API Documentation

chmodjob.cpp

00001 /* This file is part of the KDE libraries 00002 Copyright (C) 2000 Stephan Kulow <coolo@kde.org> 00003 David Faure <faure@kde.org> 00004 Waldo Bastian <bastian@kde.org> 00005 00006 This library is free software; you can redistribute it and/or 00007 modify it under the terms of the GNU Library General Public 00008 License as published by the Free Software Foundation; either 00009 version 2 of the License, or (at your option) any later version. 00010 00011 This library is distributed in the hope that it will be useful, 00012 but WITHOUT ANY WARRANTY; without even the implied warranty of 00013 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00014 Library General Public License for more details. 00015 00016 You should have received a copy of the GNU Library General Public License 00017 along with this library; see the file COPYING.LIB. If not, write to 00018 the Free Software Foundation, Inc., 59 Temple Place - Suite 330, 00019 Boston, MA 02111-1307, USA. 00020 */ 00021 00022 #include <config.h> 00023 00024 #include <pwd.h> 00025 #include <grp.h> 00026 #include <sys/types.h> 00027 #include <unistd.h> 00028 #include <assert.h> 00029 00030 #include <qtimer.h> 00031 #include <qfile.h> 00032 #include <klocale.h> 00033 #include <kdebug.h> 00034 #include <kmessagebox.h> 00035 00036 #include "kio/job.h" 00037 #include "kio/chmodjob.h" 00038 00039 #include <kdirnotify_stub.h> 00040 00041 using namespace KIO; 00042 00043 ChmodJob::ChmodJob( const KFileItemList& lstItems, int permissions, int mask, 00044 int newOwner, int newGroup, 00045 bool recursive, bool showProgressInfo ) 00046 : KIO::Job( showProgressInfo ), state( STATE_LISTING ), 00047 m_permissions( permissions ), m_mask( mask ), 00048 m_newOwner( newOwner ), m_newGroup( newGroup ), 00049 m_recursive( recursive ), m_lstItems( lstItems ) 00050 { 00051 QTimer::singleShot( 0, this, SLOT(processList()) ); 00052 } 00053 00054 void ChmodJob::processList() 00055 { 00056 while ( !m_lstItems.isEmpty() ) 00057 { 00058 KFileItem * item = m_lstItems.first(); 00059 if ( !item->isLink() ) // don't do anything with symlinks 00060 { 00061 // File or directory -> remember to chmod 00062 ChmodInfo info; 00063 info.url = item->url(); 00064 // This is a toplevel file, we apply changes directly (no +X emulation here) 00065 info.permissions = ( m_permissions & m_mask ) | ( item->permissions() & ~m_mask ); 00066 /*kdDebug(7007) << "\n current permissions=" << QString::number(item->permissions(),8) 00067 << "\n wanted permission=" << QString::number(m_permissions,8) 00068 << "\n with mask=" << QString::number(m_mask,8) 00069 << "\n with ~mask (mask bits we keep) =" << QString::number((uint)~m_mask,8) 00070 << "\n bits we keep =" << QString::number(item->permissions() & ~m_mask,8) 00071 << "\n new permissions = " << QString::number(info.permissions,8) 00072 << endl;*/ 00073 m_infos.prepend( info ); 00074 //kdDebug(7007) << "processList : Adding info for " << info.url.prettyURL() << endl; 00075 // Directory and recursive -> list 00076 if ( item->isDir() && m_recursive ) 00077 { 00078 //kdDebug(7007) << "ChmodJob::processList dir -> listing" << endl; 00079 KIO::ListJob * listJob = KIO::listRecursive( item->url(), false /* no GUI */ ); 00080 connect( listJob, SIGNAL(entries( KIO::Job *, 00081 const KIO::UDSEntryList& )), 00082 SLOT( slotEntries( KIO::Job*, 00083 const KIO::UDSEntryList& ))); 00084 addSubjob( listJob ); 00085 return; // we'll come back later, when this one's finished 00086 } 00087 } 00088 m_lstItems.removeFirst(); 00089 } 00090 kdDebug(7007) << "ChmodJob::processList -> going to STATE_CHMODING" << endl; 00091 // We have finished, move on 00092 state = STATE_CHMODING; 00093 chmodNextFile(); 00094 } 00095 00096 void ChmodJob::slotEntries( KIO::Job*, const KIO::UDSEntryList & list ) 00097 { 00098 KIO::UDSEntryListConstIterator it = list.begin(); 00099 KIO::UDSEntryListConstIterator end = list.end(); 00100 for (; it != end; ++it) { 00101 KIO::UDSEntry::ConstIterator it2 = (*it).begin(); 00102 mode_t permissions = 0; 00103 bool isDir = false; 00104 bool isLink = false; 00105 QString relativePath; 00106 for( ; it2 != (*it).end(); it2++ ) { 00107 switch( (*it2).m_uds ) { 00108 case KIO::UDS_NAME: 00109 relativePath = (*it2).m_str; 00110 break; 00111 case KIO::UDS_FILE_TYPE: 00112 isDir = S_ISDIR((*it2).m_long); 00113 break; 00114 case KIO::UDS_LINK_DEST: 00115 isLink = !(*it2).m_str.isEmpty(); 00116 break; 00117 case KIO::UDS_ACCESS: 00118 permissions = (mode_t)((*it2).m_long); 00119 break; 00120 default: 00121 break; 00122 } 00123 } 00124 if ( !isLink && relativePath != QString::fromLatin1("..") ) 00125 { 00126 ChmodInfo info; 00127 info.url = m_lstItems.first()->url(); // base directory 00128 info.url.addPath( relativePath ); 00129 int mask = m_mask; 00130 // Emulate -X: only give +x to files that had a +x bit already 00131 // So the check is the opposite : if the file had no x bit, don't touch x bits 00132 // For dirs this doesn't apply 00133 if ( !isDir ) 00134 { 00135 int newPerms = m_permissions & mask; 00136 if ( (newPerms & 0111) && !(permissions & 0111) ) 00137 { 00138 // don't interfere with mandatory file locking 00139 if ( newPerms & 02000 ) 00140 mask = mask & ~0101; 00141 else 00142 mask = mask & ~0111; 00143 } 00144 } 00145 info.permissions = ( m_permissions & mask ) | ( permissions & ~mask ); 00146 /*kdDebug(7007) << "\n current permissions=" << QString::number(permissions,8) 00147 << "\n wanted permission=" << QString::number(m_permissions,8) 00148 << "\n with mask=" << QString::number(mask,8) 00149 << "\n with ~mask (mask bits we keep) =" << QString::number((uint)~mask,8) 00150 << "\n bits we keep =" << QString::number(permissions & ~mask,8) 00151 << "\n new permissions = " << QString::number(info.permissions,8) 00152 << endl;*/ 00153 // Prepend this info in our todo list. 00154 // This way, the toplevel dirs are done last. 00155 m_infos.prepend( info ); 00156 } 00157 } 00158 } 00159 00160 void ChmodJob::chmodNextFile() 00161 { 00162 if ( !m_infos.isEmpty() ) 00163 { 00164 ChmodInfo info = m_infos.first(); 00165 m_infos.remove( m_infos.begin() ); 00166 // First update group / owner (if local file) 00167 // (permissions have to set after, in case of suid and sgid) 00168 if ( info.url.isLocalFile() && ( m_newOwner != -1 || m_newGroup != -1 ) ) 00169 { 00170 QString path = info.url.path(); 00171 if ( chown( QFile::encodeName(path), m_newOwner, m_newGroup ) != 0 ) 00172 { 00173 int answer = KMessageBox::warningContinueCancel( 0, i18n( "<qt>Could not modify the ownership of file <b>%1</b>. You have insufficient access to the file to perform the change.</qt>" ).arg(path), QString::null, i18n("&Skip File") ); 00174 if (answer == KMessageBox::Cancel) 00175 { 00176 m_error = ERR_USER_CANCELED; 00177 emitResult(); 00178 return; 00179 } 00180 } 00181 } 00182 00183 kdDebug(7007) << "ChmodJob::chmodNextFile chmod'ing " << info.url.prettyURL() 00184 << " to " << QString::number(info.permissions,8) << endl; 00185 KIO::SimpleJob * job = KIO::chmod( info.url, info.permissions ); 00186 addSubjob(job); 00187 } 00188 else 00189 // We have finished 00190 emitResult(); 00191 } 00192 00193 void ChmodJob::slotResult( KIO::Job * job ) 00194 { 00195 if ( job->error() ) 00196 { 00197 m_error = job->error(); 00198 m_errorText = job->errorText(); 00199 emitResult(); 00200 return; 00201 } 00202 //kdDebug(7007) << " ChmodJob::slotResult( KIO::Job * job ) m_lstItems:" << m_lstItems.count() << endl; 00203 switch ( state ) 00204 { 00205 case STATE_LISTING: 00206 subjobs.remove(job); 00207 m_lstItems.removeFirst(); 00208 kdDebug(7007) << "ChmodJob::slotResult -> processList" << endl; 00209 processList(); 00210 return; 00211 case STATE_CHMODING: 00212 subjobs.remove(job); 00213 kdDebug(7007) << "ChmodJob::slotResult -> chmodNextFile" << endl; 00214 chmodNextFile(); 00215 return; 00216 default: 00217 assert(0); 00218 return; 00219 } 00220 } 00221 00222 // antlarr: KDE 4: Make owner and group be const QString & 00223 KIO_EXPORT ChmodJob *KIO::chmod( const KFileItemList& lstItems, int permissions, int mask, 00224 QString owner, QString group, 00225 bool recursive, bool showProgressInfo ) 00226 { 00227 uid_t newOwnerID = (uid_t)-1; // chown(2) : -1 means no change 00228 if ( !owner.isEmpty() ) 00229 { 00230 struct passwd* pw = getpwnam(QFile::encodeName(owner)); 00231 if ( pw == 0L ) 00232 kdError(250) << " ERROR: No user " << owner << endl; 00233 else 00234 newOwnerID = pw->pw_uid; 00235 } 00236 gid_t newGroupID = (gid_t)-1; // chown(2) : -1 means no change 00237 if ( !group.isEmpty() ) 00238 { 00239 struct group* g = getgrnam(QFile::encodeName(group)); 00240 if ( g == 0L ) 00241 kdError(250) << " ERROR: No group " << group << endl; 00242 else 00243 newGroupID = g->gr_gid; 00244 } 00245 return new ChmodJob( lstItems, permissions, mask, newOwnerID, newGroupID, recursive, showProgressInfo ); 00246 } 00247 00248 void ChmodJob::virtual_hook( int id, void* data ) 00249 { KIO::Job::virtual_hook( id, data ); } 00250 00251 #include "chmodjob.moc"
KDE Logo
This file is part of the documentation for kio Library Version 3.4.0.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Tue Apr 12 23:09:02 2005 by doxygen 1.3.7 written by Dimitri van Heesch, © 1997-2003