kio Library: chmodjob.cpp Source File (kio Library)

| # kio Library API Documentation
Overview | Class Hierarchy | Classes | Classes (annotated) | Members | Namespaces | Source Files

# 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"

This file is part of the documentation for kio Library Version 3.4.1.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Sat Jun 11 20:23:52 2005 by doxygen 1.4.1 written by Dimitri van Heesch, © 1997-2003