• Skip to content
  • Skip to link menu
  • KDE API Reference
  • kdelibs-4.14.38 API Reference
  • KDE Home
  • Contact Us
 

KIO

  • kio
  • kio
chmodjob.cpp
Go to the documentation of this file.
1/* This file is part of the KDE libraries
2 Copyright (C) 2000 Stephan Kulow <coolo@kde.org>
3 David Faure <faure@kde.org>
4 Waldo Bastian <bastian@kde.org>
5
6 This library is free software; you can redistribute it and/or
7 modify it under the terms of the GNU Library General Public
8 License as published by the Free Software Foundation; either
9 version 2 of the License, or (at your option) any later version.
10
11 This library is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 Library General Public License for more details.
15
16 You should have received a copy of the GNU Library General Public License
17 along with this library; see the file COPYING.LIB. If not, write to
18 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
19 Boston, MA 02110-1301, USA.
20*/
21
22#include "chmodjob.h"
23
24#include "job.h"
25#include "jobuidelegate.h"
26
27#include <klocale.h>
28#include <kdebug.h>
29#include <kmessagebox.h>
30#include <QtCore/QFile>
31
32#include <config.h>
33
34#include <pwd.h>
35#include <grp.h>
36#include <sys/types.h>
37#include <unistd.h>
38#include <assert.h>
39
40#include "job_p.h"
41
42namespace KIO {
43
44 struct ChmodInfo
45 {
46 KUrl url;
47 int permissions;
48 };
49
50 enum ChmodJobState {
51 CHMODJOB_STATE_LISTING,
52 CHMODJOB_STATE_CHMODING
53 };
54
55 class ChmodJobPrivate: public KIO::JobPrivate
56 {
57 public:
58 ChmodJobPrivate(const KFileItemList& lstItems, int permissions, int mask,
59 int newOwner, int newGroup, bool recursive)
60 : state( CHMODJOB_STATE_LISTING )
61 , m_permissions( permissions )
62 , m_mask( mask )
63 , m_newOwner( newOwner )
64 , m_newGroup( newGroup )
65 , m_recursive( recursive )
66 , m_lstItems( lstItems )
67 {
68 }
69
70 ChmodJobState state;
71 int m_permissions;
72 int m_mask;
73 int m_newOwner;
74 int m_newGroup;
75 bool m_recursive;
76 KFileItemList m_lstItems;
77 QLinkedList<ChmodInfo> m_infos; // linkedlist since we keep removing the first item
78
79 void chmodNextFile();
80 void _k_slotEntries( KIO::Job * , const KIO::UDSEntryList & );
81 void _k_processList();
82
83 Q_DECLARE_PUBLIC(ChmodJob)
84
85 static inline ChmodJob *newJob(const KFileItemList& lstItems, int permissions, int mask,
86 int newOwner, int newGroup, bool recursive, JobFlags flags)
87 {
88 ChmodJob *job = new ChmodJob(*new ChmodJobPrivate(lstItems,permissions,mask,
89 newOwner,newGroup,recursive));
90 job->setUiDelegate(new JobUiDelegate());
91 if (!(flags & HideProgressInfo))
92 KIO::getJobTracker()->registerJob(job);
93 return job;
94 }
95 };
96
97} // namespace KIO
98
99using namespace KIO;
100
101ChmodJob::ChmodJob(ChmodJobPrivate &dd)
102 : KIO::Job(dd)
103{
104 QMetaObject::invokeMethod( this, "_k_processList", Qt::QueuedConnection );
105}
106
107ChmodJob::~ChmodJob()
108{
109}
110
111void ChmodJobPrivate::_k_processList()
112{
113 Q_Q(ChmodJob);
114 while ( !m_lstItems.isEmpty() )
115 {
116 const KFileItem item = m_lstItems.first();
117 if ( !item.isLink() ) // don't do anything with symlinks
118 {
119 // File or directory -> remember to chmod
120 ChmodInfo info;
121 info.url = item.url();
122 // This is a toplevel file, we apply changes directly (no +X emulation here)
123 const mode_t permissions = item.permissions() & 0777; // get rid of "set gid" and other special flags
124 info.permissions = ( m_permissions & m_mask ) | ( permissions & ~m_mask );
125 /*kDebug(7007) << "toplevel url:" << info.url << "\n current permissions=" << QString::number(permissions,8)
126 << "\n wanted permission=" << QString::number(m_permissions,8)
127 << "\n with mask=" << QString::number(m_mask,8)
128 << "\n with ~mask (mask bits we keep) =" << QString::number((uint)~m_mask,8)
129 << "\n bits we keep =" << QString::number(permissions & ~m_mask,8)
130 << "\n new permissions = " << QString::number(info.permissions,8);*/
131 m_infos.prepend( info );
132 //kDebug(7007) << "processList : Adding info for " << info.url;
133 // Directory and recursive -> list
134 if ( item.isDir() && m_recursive )
135 {
136 //kDebug(7007) << "ChmodJob::processList dir -> listing";
137 KIO::ListJob * listJob = KIO::listRecursive( item.url(), KIO::HideProgressInfo );
138 q->connect( listJob, SIGNAL(entries( KIO::Job *,
139 const KIO::UDSEntryList& )),
140 SLOT(_k_slotEntries(KIO::Job*,KIO::UDSEntryList)));
141 q->addSubjob( listJob );
142 return; // we'll come back later, when this one's finished
143 }
144 }
145 m_lstItems.removeFirst();
146 }
147 kDebug(7007) << "ChmodJob::processList -> going to STATE_CHMODING";
148 // We have finished, move on
149 state = CHMODJOB_STATE_CHMODING;
150 chmodNextFile();
151}
152
153void ChmodJobPrivate::_k_slotEntries( KIO::Job*, const KIO::UDSEntryList & list )
154{
155 KIO::UDSEntryList::ConstIterator it = list.begin();
156 KIO::UDSEntryList::ConstIterator end = list.end();
157 for (; it != end; ++it) {
158 const KIO::UDSEntry& entry = *it;
159 const bool isLink = !entry.stringValue( KIO::UDSEntry::UDS_LINK_DEST ).isEmpty();
160 const QString relativePath = entry.stringValue( KIO::UDSEntry::UDS_NAME );
161 if ( !isLink && relativePath != ".." )
162 {
163 const mode_t permissions = entry.numberValue( KIO::UDSEntry::UDS_ACCESS )
164 & 0777; // get rid of "set gid" and other special flags
165
166 ChmodInfo info;
167 info.url = m_lstItems.first().url(); // base directory
168 info.url.addPath( relativePath );
169 int mask = m_mask;
170 // Emulate -X: only give +x to files that had a +x bit already
171 // So the check is the opposite : if the file had no x bit, don't touch x bits
172 // For dirs this doesn't apply
173 if ( !entry.isDir() )
174 {
175 int newPerms = m_permissions & mask;
176 if ( (newPerms & 0111) && !(permissions & 0111) )
177 {
178 // don't interfere with mandatory file locking
179 if ( newPerms & 02000 )
180 mask = mask & ~0101;
181 else
182 mask = mask & ~0111;
183 }
184 }
185 info.permissions = ( m_permissions & mask ) | ( permissions & ~mask );
186 /*kDebug(7007) << info.url << "\n current permissions=" << QString::number(permissions,8)
187 << "\n wanted permission=" << QString::number(m_permissions,8)
188 << "\n with mask=" << QString::number(mask,8)
189 << "\n with ~mask (mask bits we keep) =" << QString::number((uint)~mask,8)
190 << "\n bits we keep =" << QString::number(permissions & ~mask,8)
191 << "\n new permissions = " << QString::number(info.permissions,8);*/
192 // Prepend this info in our todo list.
193 // This way, the toplevel dirs are done last.
194 m_infos.prepend( info );
195 }
196 }
197}
198
199void ChmodJobPrivate::chmodNextFile()
200{
201 Q_Q(ChmodJob);
202 if ( !m_infos.isEmpty() )
203 {
204 ChmodInfo info = m_infos.takeFirst();
205 // First update group / owner (if local file)
206 // (permissions have to set after, in case of suid and sgid)
207 if ( info.url.isLocalFile() && ( m_newOwner != -1 || m_newGroup != -1 ) )
208 {
209 QString path = info.url.toLocalFile();
210 if ( chown( QFile::encodeName(path), m_newOwner, m_newGroup ) != 0 )
211 {
212 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>" , path), QString(), KGuiItem(i18n("&Skip File")) );
213 if (answer == KMessageBox::Cancel)
214 {
215 q->setError( ERR_USER_CANCELED );
216 q->emitResult();
217 return;
218 }
219 }
220 }
221
222 kDebug(7007) << "chmod'ing" << info.url
223 << "to" << QString::number(info.permissions,8);
224 KIO::SimpleJob * job = KIO::chmod( info.url, info.permissions );
225 // copy the metadata for acl and default acl
226 const QString aclString = q->queryMetaData( QLatin1String("ACL_STRING") );
227 const QString defaultAclString = q->queryMetaData( QLatin1String("DEFAULT_ACL_STRING") );
228 if ( !aclString.isEmpty() )
229 job->addMetaData( QLatin1String("ACL_STRING"), aclString );
230 if ( !defaultAclString.isEmpty() )
231 job->addMetaData( QLatin1String("DEFAULT_ACL_STRING"), defaultAclString );
232 q->addSubjob(job);
233 }
234 else
235 // We have finished
236 q->emitResult();
237}
238
239void ChmodJob::slotResult( KJob * job )
240{
241 Q_D(ChmodJob);
242 removeSubjob(job);
243 if ( job->error() )
244 {
245 setError( job->error() );
246 setErrorText( job->errorText() );
247 emitResult();
248 return;
249 }
250 //kDebug(7007) << "d->m_lstItems:" << d->m_lstItems.count();
251 switch ( d->state )
252 {
253 case CHMODJOB_STATE_LISTING:
254 d->m_lstItems.removeFirst();
255 kDebug(7007) << "-> processList";
256 d->_k_processList();
257 return;
258 case CHMODJOB_STATE_CHMODING:
259 kDebug(7007) << "-> chmodNextFile";
260 d->chmodNextFile();
261 return;
262 default:
263 assert(0);
264 return;
265 }
266}
267
268ChmodJob *KIO::chmod( const KFileItemList& lstItems, int permissions, int mask,
269 const QString& owner, const QString& group,
270 bool recursive, JobFlags flags )
271{
272 uid_t newOwnerID = uid_t(-1); // chown(2) : -1 means no change
273 if ( !owner.isEmpty() )
274 {
275 struct passwd* pw = getpwnam(QFile::encodeName(owner));
276 if ( pw == 0L )
277 kError(250) << " ERROR: No user" << owner;
278 else
279 newOwnerID = pw->pw_uid;
280 }
281 gid_t newGroupID = gid_t(-1); // chown(2) : -1 means no change
282 if ( !group.isEmpty() )
283 {
284 struct group* g = getgrnam(QFile::encodeName(group));
285 if ( g == 0L )
286 kError(250) << " ERROR: No group" << group;
287 else
288 newGroupID = g->gr_gid;
289 }
290 return ChmodJobPrivate::newJob(lstItems, permissions, mask, newOwnerID,
291 newGroupID, recursive, flags);
292}
293
294#include "chmodjob.moc"
chmodjob.h
KFileItemList
List of KFileItems, which adds a few helper methods to QList<KFileItem>.
Definition: kfileitem.h:675
KFileItem
A KFileItem is a generic class to handle a file, local or remote.
Definition: kfileitem.h:46
KFileItem::isLink
bool isLink() const
Returns true if this item represents a link in the UNIX sense of a link.
Definition: kfileitem.cpp:1567
KFileItem::permissions
mode_t permissions() const
Returns the permissions of the file (stat.st_mode containing only permissions).
Definition: kfileitem.cpp:1551
KFileItem::isDir
bool isDir() const
Returns true if this item represents a directory.
Definition: kfileitem.cpp:1141
KFileItem::url
KUrl url() const
Returns the url of the file.
Definition: kfileitem.cpp:1543
KGuiItem
KIO::ChmodJob
This job changes permissions on a list of files or directories, optionally in a recursive manner.
Definition: chmodjob.h:40
KIO::ChmodJob::slotResult
virtual void slotResult(KJob *job)
Definition: chmodjob.cpp:239
KIO::ChmodJob::~ChmodJob
virtual ~ChmodJob()
Definition: chmodjob.cpp:107
KIO::ChmodJob::ChmodJob
ChmodJob(ChmodJobPrivate &dd)
Definition: chmodjob.cpp:101
KIO::JobPrivate
Definition: job_p.h:40
KIO::JobUiDelegate
A UI delegate tuned to be used with KIO Jobs.
Definition: jobuidelegate.h:40
KIO::Job
The base class for all jobs.
Definition: jobclasses.h:94
KIO::Job::removeSubjob
virtual bool removeSubjob(KJob *job)
Mark a sub job as being done.
Definition: job.cpp:118
KIO::Job::addMetaData
void addMetaData(const QString &key, const QString &value)
Add key/value pair to the meta data that is sent to the slave.
Definition: job.cpp:264
KIO::ListJob
A ListJob is allows you to get the get the content of a directory.
Definition: jobclasses.h:936
KIO::SimpleJob
A simple job (one url and one command).
Definition: jobclasses.h:322
KIO::UDSEntry
Universal Directory Service.
Definition: udsentry.h:59
KIO::UDSEntry::stringValue
QString stringValue(uint field) const
Definition: udsentry.cpp:73
KIO::UDSEntry::numberValue
long long numberValue(uint field, long long defaultValue=0) const
Definition: udsentry.cpp:78
KIO::UDSEntry::UDS_LINK_DEST
@ UDS_LINK_DEST
Name of the file where the link points to Allows to check for a symlink (don't use S_ISLNK !...
Definition: udsentry.h:184
KIO::UDSEntry::UDS_NAME
@ UDS_NAME
Filename - as displayed in directory listings etc.
Definition: udsentry.h:163
KIO::UDSEntry::UDS_ACCESS
@ UDS_ACCESS
Access permissions (part of the mode returned by stat)
Definition: udsentry.h:171
KIO::UDSEntry::isDir
bool isDir() const
Definition: udsentry.cpp:84
KJobTrackerInterface::registerJob
virtual void registerJob(KJob *job)
KJob
KJob::setErrorText
void setErrorText(const QString &errorText)
KJob::emitResult
void emitResult()
KJob::error
int error() const
KJob::setError
void setError(int errorCode)
KJob::errorText
QString errorText() const
KJob::setUiDelegate
void setUiDelegate(KJobUiDelegate *delegate)
KMessageBox::warningContinueCancel
static int warningContinueCancel(QWidget *parent, const QString &text, const QString &caption=QString(), const KGuiItem &buttonContinue=KStandardGuiItem::cont(), const KGuiItem &buttonCancel=KStandardGuiItem::cancel(), const QString &dontAskAgainName=QString(), Options options=Notify)
KMessageBox::Cancel
Cancel
KUrl
QList< UDSEntry >
kDebug
#define kDebug
job.h
job_p.h
jobuidelegate.h
mask
#define mask
kdebug.h
klocale.h
i18n
QString i18n(const char *text)
kmessagebox.h
KIO
A namespace for KIO globals.
Definition: kbookmarkmenu.h:55
KIO::chmod
ChmodJob * chmod(const KFileItemList &lstItems, int permissions, int mask, const QString &newOwner, const QString &newGroup, bool recursive, JobFlags flags=DefaultFlags)
Creates a job that changes permissions/ownership on several files or directories, optionally recursiv...
Definition: chmodjob.cpp:268
KIO::chown
SimpleJob * chown(const KUrl &url, const QString &owner, const QString &group)
Changes ownership and group of a file or directory.
Definition: job.cpp:718
KIO::listRecursive
ListJob * listRecursive(const KUrl &url, JobFlags flags=DefaultFlags, bool includeHidden=true)
The same as the previous method, but recurses subdirectories.
Definition: job.cpp:2740
KIO::ChmodJobState
ChmodJobState
Definition: chmodjob.cpp:50
KIO::CHMODJOB_STATE_LISTING
@ CHMODJOB_STATE_LISTING
Definition: chmodjob.cpp:51
KIO::CHMODJOB_STATE_CHMODING
@ CHMODJOB_STATE_CHMODING
Definition: chmodjob.cpp:52
KIO::HideProgressInfo
@ HideProgressInfo
Hide progress information dialog, i.e.
Definition: jobclasses.h:51
KIO::ERR_USER_CANCELED
@ ERR_USER_CANCELED
Definition: global.h:214
KIO::getJobTracker
KJobTrackerInterface * getJobTracker()
Definition: global.cpp:1246
group
group
KRecentDirs::list
QStringList list(const QString &fileClass)
Returns a list of directories associated with this file-class.
Definition: krecentdirs.cpp:60
end
const KShortcut & end()
This file is part of the KDE documentation.
Documentation copyright © 1996-2023 The KDE developers.
Generated on Mon Feb 20 2023 00:00:00 by doxygen 1.9.6 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.

KIO

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

kdelibs-4.14.38 API Reference

Skip menu "kdelibs-4.14.38 API Reference"
  • DNSSD
  • Interfaces
  •   KHexEdit
  •   KMediaPlayer
  •   KSpeech
  •   KTextEditor
  • kconf_update
  • KDE3Support
  •   KUnitTest
  • KDECore
  • KDED
  • KDEsu
  • KDEUI
  • KDEWebKit
  • KDocTools
  • KFile
  • KHTML
  • KImgIO
  • KInit
  • kio
  • KIOSlave
  • KJS
  •   KJS-API
  •   WTF
  • kjsembed
  • KNewStuff
  • KParts
  • KPty
  • Kross
  • KUnitConversion
  • KUtils
  • Nepomuk
  • Plasma
  • Solid
  • Sonnet
  • ThreadWeaver
Report problems with this website to our bug tracking system.
Contact the specific authors with questions and comments about the page contents.

KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal