• Skip to content
  • Skip to link menu
KDE 3.5 API Reference
  • KDE API Reference
  • API Reference
  • Sitemap
  • Contact Us
 

kio

chmodjob.cpp

Go to the documentation of this file.
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., 51 Franklin Street, Fifth Floor,
00019     Boston, MA 02110-1301, 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         // copy the metadata for acl and default acl
00187         const QString aclString = queryMetaData( "ACL_STRING" );
00188         const QString defaultAclString = queryMetaData( "DEFAULT_ACL_STRING" );
00189         if ( !aclString.isEmpty() )
00190             job->addMetaData( "ACL_STRING", aclString );
00191         if ( !defaultAclString.isEmpty() )
00192             job->addMetaData( "DEFAULT_ACL_STRING", defaultAclString );
00193         addSubjob(job);
00194     }
00195     else
00196         // We have finished
00197         emitResult();
00198 }
00199 
00200 void ChmodJob::slotResult( KIO::Job * job )
00201 {
00202     if ( job->error() )
00203     {
00204         m_error = job->error();
00205         m_errorText = job->errorText();
00206         emitResult();
00207         return;
00208     }
00209     //kdDebug(7007) << " ChmodJob::slotResult( KIO::Job * job ) m_lstItems:" << m_lstItems.count() << endl;
00210     switch ( state )
00211     {
00212         case STATE_LISTING:
00213             subjobs.remove(job);
00214             m_lstItems.removeFirst();
00215             kdDebug(7007) << "ChmodJob::slotResult -> processList" << endl;
00216             processList();
00217             return;
00218         case STATE_CHMODING:
00219             subjobs.remove(job);
00220             kdDebug(7007) << "ChmodJob::slotResult -> chmodNextFile" << endl;
00221             chmodNextFile();
00222             return;
00223         default:
00224             assert(0);
00225             return;
00226     }
00227 }
00228 
00229 // antlarr: KDE 4: Make owner and group be const QString &
00230 KIO_EXPORT ChmodJob *KIO::chmod( const KFileItemList& lstItems, int permissions, int mask,
00231                       QString owner, QString group,
00232                       bool recursive, bool showProgressInfo )
00233 {
00234     uid_t newOwnerID = (uid_t)-1; // chown(2) : -1 means no change
00235     if ( !owner.isEmpty() )
00236     {
00237         struct passwd* pw = getpwnam(QFile::encodeName(owner));
00238         if ( pw == 0L )
00239             kdError(250) << " ERROR: No user " << owner << endl;
00240         else
00241             newOwnerID = pw->pw_uid;
00242     }
00243     gid_t newGroupID = (gid_t)-1; // chown(2) : -1 means no change
00244     if ( !group.isEmpty() )
00245     {
00246         struct group* g = getgrnam(QFile::encodeName(group));
00247         if ( g == 0L )
00248             kdError(250) << " ERROR: No group " << group << endl;
00249         else
00250             newGroupID = g->gr_gid;
00251     }
00252     return new ChmodJob( lstItems, permissions, mask, newOwnerID, newGroupID, recursive, showProgressInfo );
00253 }
00254 
00255 void ChmodJob::virtual_hook( int id, void* data )
00256 { KIO::Job::virtual_hook( id, data ); }
00257 
00258 #include "chmodjob.moc"

kio

Skip menu "kio"
  • Main Page
  • Modules
  • Namespace List
  • Class Hierarchy
  • Alphabetical List
  • Class List
  • File List
  • Namespace Members
  • Class Members
  • Related Pages

API Reference

Skip menu "API Reference"
  • dcop
  • DNSSD
  • interfaces
  • Kate
  • kconf_update
  • KDECore
  • KDED
  • kdefx
  • KDEsu
  • kdeui
  • KDocTools
  • KHTML
  • KImgIO
  • KInit
  • kio
  • kioslave
  • KJS
  • KNewStuff
  • KParts
  • KUtils
Generated for API Reference by doxygen 1.5.9
This website is maintained by Adriaan de Groot and Allen Winter.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal