00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
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() )
00060 {
00061
00062 ChmodInfo info;
00063 info.url = item->
url();
00064
00065 info.permissions = ( m_permissions & m_mask ) | ( item->
permissions() & ~m_mask );
00066
00067
00068
00069
00070
00071
00072
00073 m_infos.prepend( info );
00074
00075
00076
if ( item->
isDir() && m_recursive )
00077 {
00078
00079
KIO::ListJob * listJob =
KIO::listRecursive( item->
url(),
false );
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;
00086 }
00087 }
00088 m_lstItems.removeFirst();
00089 }
00090
kdDebug(7007) <<
"ChmodJob::processList -> going to STATE_CHMODING" <<
endl;
00091
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();
00128 info.url.addPath( relativePath );
00129
int mask = m_mask;
00130
00131
00132
00133
if ( !isDir )
00134 {
00135
int newPerms = m_permissions & mask;
00136
if ( (newPerms & 0111) && !(permissions & 0111) )
00137 {
00138
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
00147
00148
00149
00150
00151
00152
00153
00154
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
00167
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
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
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
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;
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;
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"