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 struct KIO::ChmodInfo 00044 { 00045 KURL url; 00046 int permissions; 00047 }; 00048 00049 /* 00050 00051 NOTE : This job is currently in ksycoca because kfileitem needs to know 00052 about mimetypes. For KDE 3.0, make a base class for KFileItem, that holds 00053 all the information except the mimetype, so that jobs can use it. 00054 00055 */ 00056 00057 ChmodJob::ChmodJob( const KFileItemList& lstItems, int permissions, int mask, 00058 int newOwner, int newGroup, 00059 bool recursive, bool showProgressInfo ) 00060 : KIO::Job( showProgressInfo ), state( STATE_LISTING ), 00061 m_permissions( permissions ), m_mask( mask ), 00062 m_newOwner( newOwner ), m_newGroup( newGroup ), 00063 m_recursive( recursive ), m_lstItems( lstItems ) 00064 { 00065 QTimer::singleShot( 0, this, SLOT(processList()) ); 00066 } 00067 00068 void ChmodJob::processList() 00069 { 00070 while ( !m_lstItems.isEmpty() ) 00071 { 00072 KFileItem * item = m_lstItems.first(); 00073 if ( !item->isLink() ) // don't do anything with symlinks 00074 { 00075 // File or directory -> remember to chmod 00076 ChmodInfo info; 00077 info.url = item->url(); 00078 // This is a toplevel file, we apply changes directly (no +X emulation here) 00079 info.permissions = ( m_permissions & m_mask ) | ( item->permissions() & ~m_mask ); 00080 /*kdDebug(7007) << "\n current permissions=" << QString::number(item->permissions(),8) 00081 << "\n wanted permission=" << QString::number(m_permissions,8) 00082 << "\n with mask=" << QString::number(m_mask,8) 00083 << "\n with ~mask (mask bits we keep) =" << QString::number((uint)~m_mask,8) 00084 << "\n bits we keep =" << QString::number(item->permissions() & ~m_mask,8) 00085 << "\n new permissions = " << QString::number(info.permissions,8) 00086 << endl;*/ 00087 m_infos.prepend( info ); 00088 //kdDebug(7007) << "processList : Adding info for " << info.url.prettyURL() << endl; 00089 // Directory and recursive -> list 00090 if ( item->isDir() && m_recursive ) 00091 { 00092 //kdDebug(7007) << "ChmodJob::processList dir -> listing" << endl; 00093 KIO::ListJob * listJob = KIO::listRecursive( item->url(), false /* no GUI */ ); 00094 connect( listJob, SIGNAL(entries( KIO::Job *, 00095 const KIO::UDSEntryList& )), 00096 SLOT( slotEntries( KIO::Job*, 00097 const KIO::UDSEntryList& ))); 00098 addSubjob( listJob ); 00099 return; // we'll come back later, when this one's finished 00100 } 00101 } 00102 m_lstItems.removeFirst(); 00103 } 00104 kdDebug(7007) << "ChmodJob::processList -> going to STATE_CHMODING" << endl; 00105 // We have finished, move on 00106 state = STATE_CHMODING; 00107 chmodNextFile(); 00108 } 00109 00110 void ChmodJob::slotEntries( KIO::Job*, const KIO::UDSEntryList & list ) 00111 { 00112 KIO::UDSEntryListConstIterator it = list.begin(); 00113 KIO::UDSEntryListConstIterator end = list.end(); 00114 for (; it != end; ++it) { 00115 KIO::UDSEntry::ConstIterator it2 = (*it).begin(); 00116 mode_t permissions = 0; 00117 bool isDir = false; 00118 bool isLink = false; 00119 QString relativePath; 00120 for( ; it2 != (*it).end(); it2++ ) { 00121 switch( (*it2).m_uds ) { 00122 case KIO::UDS_NAME: 00123 relativePath = (*it2).m_str; 00124 break; 00125 case KIO::UDS_FILE_TYPE: 00126 isDir = S_ISDIR((*it2).m_long); 00127 break; 00128 case KIO::UDS_LINK_DEST: 00129 isLink = !(*it2).m_str.isEmpty(); 00130 break; 00131 case KIO::UDS_ACCESS: 00132 permissions = (mode_t)((*it2).m_long); 00133 break; 00134 default: 00135 break; 00136 } 00137 } 00138 if ( !isLink && relativePath != QString::fromLatin1("..") ) 00139 { 00140 ChmodInfo info; 00141 info.url = m_lstItems.first()->url(); // base directory 00142 info.url.addPath( relativePath ); 00143 int mask = m_mask; 00144 // Emulate -X: only give +x to files that had a +x bit already 00145 // So the check is the opposite : if the file had no x bit, don't touch x bits 00146 // For dirs this doesn't apply 00147 if ( !isDir ) 00148 { 00149 int newPerms = m_permissions & mask; 00150 if ( (newPerms & 0111) && !(permissions & 0111) ) 00151 { 00152 // don't interfere with mandatory file locking 00153 if ( newPerms & 02000 ) 00154 mask = mask & ~0101; 00155 else 00156 mask = mask & ~0111; 00157 } 00158 } 00159 info.permissions = ( m_permissions & mask ) | ( permissions & ~mask ); 00160 /*kdDebug(7007) << "\n current permissions=" << QString::number(permissions,8) 00161 << "\n wanted permission=" << QString::number(m_permissions,8) 00162 << "\n with mask=" << QString::number(mask,8) 00163 << "\n with ~mask (mask bits we keep) =" << QString::number((uint)~mask,8) 00164 << "\n bits we keep =" << QString::number(permissions & ~mask,8) 00165 << "\n new permissions = " << QString::number(info.permissions,8) 00166 << endl;*/ 00167 // Prepend this info in our todo list. 00168 // This way, the toplevel dirs are done last. 00169 m_infos.prepend( info ); 00170 } 00171 } 00172 } 00173 00174 void ChmodJob::chmodNextFile() 00175 { 00176 if ( !m_infos.isEmpty() ) 00177 { 00178 ChmodInfo info = m_infos.first(); 00179 m_infos.remove( m_infos.begin() ); 00180 // First update group / owner (if local file) 00181 // (permissions have to set after, in case of suid and sgid) 00182 if ( info.url.isLocalFile() && ( m_newOwner != -1 || m_newGroup != -1 ) ) 00183 { 00184 QString path = info.url.path(); 00185 if ( chown( QFile::encodeName(path), m_newOwner, m_newGroup ) != 0 ) 00186 { 00187 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") ); 00188 if (answer == KMessageBox::Cancel) 00189 { 00190 m_error = ERR_USER_CANCELED; 00191 emitResult(); 00192 return; 00193 } 00194 } 00195 } 00196 00197 kdDebug(7007) << "ChmodJob::chmodNextFile chmod'ing " << info.url.prettyURL() 00198 << " to " << QString::number(info.permissions,8) << endl; 00199 KIO::SimpleJob * job = KIO::chmod( info.url, info.permissions ); 00200 addSubjob(job); 00201 } 00202 else 00203 // We have finished 00204 emitResult(); 00205 } 00206 00207 void ChmodJob::slotResult( KIO::Job * job ) 00208 { 00209 if ( job->error() ) 00210 { 00211 m_error = job->error(); 00212 m_errorText = job->errorText(); 00213 emitResult(); 00214 return; 00215 } 00216 //kdDebug(7007) << " ChmodJob::slotResult( KIO::Job * job ) m_lstItems:" << m_lstItems.count() << endl; 00217 switch ( state ) 00218 { 00219 case STATE_LISTING: 00220 subjobs.remove(job); 00221 m_lstItems.removeFirst(); 00222 kdDebug(7007) << "ChmodJob::slotResult -> processList" << endl; 00223 processList(); 00224 return; 00225 case STATE_CHMODING: 00226 subjobs.remove(job); 00227 kdDebug(7007) << "ChmodJob::slotResult -> chmodNextFile" << endl; 00228 chmodNextFile(); 00229 return; 00230 default: 00231 assert(0); 00232 return; 00233 } 00234 } 00235 00236 // antlarr: KDE 4: Make owner and group be const QString & 00237 ChmodJob *KIO::chmod( const KFileItemList& lstItems, int permissions, int mask, 00238 QString owner, QString group, 00239 bool recursive, bool showProgressInfo ) 00240 { 00241 uid_t newOwnerID = (uid_t)-1; // chown(2) : -1 means no change 00242 if ( !owner.isEmpty() ) 00243 { 00244 struct passwd* pw = getpwnam(QFile::encodeName(owner)); 00245 if ( pw == 0L ) 00246 kdError(250) << " ERROR: No user " << owner << endl; 00247 else 00248 newOwnerID = pw->pw_uid; 00249 } 00250 gid_t newGroupID = (gid_t)-1; // chown(2) : -1 means no change 00251 if ( !group.isEmpty() ) 00252 { 00253 struct group* g = getgrnam(QFile::encodeName(group)); 00254 if ( g == 0L ) 00255 kdError(250) << " ERROR: No group " << group << endl; 00256 else 00257 newGroupID = g->gr_gid; 00258 } 00259 return new ChmodJob( lstItems, permissions, mask, newOwnerID, newGroupID, recursive, showProgressInfo ); 00260 } 00261 00262 void ChmodJob::virtual_hook( int id, void* data ) 00263 { KIO::Job::virtual_hook( id, data ); } 00264 00265 #include "chmodjob.moc"
KDE Logo
This file is part of the documentation for kio Library Version 3.3.0.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Wed Sep 29 09:41:00 2004 by doxygen 1.3.8 written by Dimitri van Heesch, © 1997-2003