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

KIO

  • sources
  • kde-4.14
  • kdelibs
  • 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 
42 namespace 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 
99 using namespace KIO;
100 
101 ChmodJob::ChmodJob(ChmodJobPrivate &dd)
102  : KIO::Job(dd)
103 {
104  QMetaObject::invokeMethod( this, "_k_processList", Qt::QueuedConnection );
105 }
106 
107 ChmodJob::~ChmodJob()
108 {
109 }
110 
111 void 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 
153 void 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 
199 void 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 
239 void 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 
268 ChmodJob *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"
i18n
QString i18n(const char *text)
KIO::CHMODJOB_STATE_LISTING
Definition: chmodjob.cpp:51
KIO::ChmodJob::slotResult
virtual void slotResult(KJob *job)
Definition: chmodjob.cpp:239
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
KFileItem::isDir
bool isDir() const
Returns true if this item represents a directory.
Definition: kfileitem.cpp:1141
kdebug.h
KCompositeJob::emitResult
void emitResult()
KCompositeJob::setUiDelegate
void setUiDelegate(KJobUiDelegate *delegate)
KIO::UDSEntry
Universal Directory Service.
Definition: udsentry.h:58
KIO::ListJob
A ListJob is allows you to get the get the content of a directory.
Definition: jobclasses.h:936
mask
#define mask
KIO::HideProgressInfo
Hide progress information dialog, i.e.
Definition: jobclasses.h:51
KIO::CHMODJOB_STATE_CHMODING
Definition: chmodjob.cpp:52
KCompositeJob::setError
void setError(int errorCode)
KIO::ERR_USER_CANCELED
Definition: global.h:214
KIO::UDSEntry::isDir
bool isDir() const
Definition: udsentry.cpp:84
kError
static QDebug kError(bool cond, int area=KDE_DEFAULT_DEBUG_AREA)
KFileItem::permissions
mode_t permissions() const
Returns the permissions of the file (stat.st_mode containing only permissions).
Definition: kfileitem.cpp:1551
KIO::Job::removeSubjob
virtual bool removeSubjob(KJob *job)
Mark a sub job as being done.
Definition: job.cpp:118
kDebug
static QDebug kDebug(bool cond, int area=KDE_DEFAULT_DEBUG_AREA)
klocale.h
KUrl
KMessageBox::Cancel
QLinkedList< ChmodInfo >
KCompositeJob::setErrorText
void setErrorText(const QString &errorText)
QString::number
QString number(int n, int base)
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::ChmodJob
This job changes permissions on a list of files or directories, optionally in a recursive manner...
Definition: chmodjob.h:39
KIO::UDSEntry::numberValue
long long numberValue(uint field, long long defaultValue=0) const
Definition: udsentry.cpp:78
KIO::JobUiDelegate
A UI delegate tuned to be used with KIO Jobs.
Definition: jobuidelegate.h:39
KGuiItem
QString::isEmpty
bool isEmpty() const
KIO::ChmodJobState
ChmodJobState
Definition: chmodjob.cpp:50
KFileItemList
List of KFileItems, which adds a few helper methods to QList.
Definition: kfileitem.h:674
KIO::UDSEntry::stringValue
QString stringValue(uint field) const
Definition: udsentry.cpp:73
KIO::getJobTracker
KJobTrackerInterface * getJobTracker()
Definition: global.cpp:1246
QString
QList< UDSEntry >
jobuidelegate.h
QList::end
iterator end()
KFileItem::isLink
bool isLink() const
Returns true if this item represents a link in the UNIX sense of a link.
Definition: kfileitem.cpp:1567
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::ChmodJob::ChmodJob
ChmodJob(ChmodJobPrivate &dd)
Definition: chmodjob.cpp:101
QMetaObject::invokeMethod
bool invokeMethod(QObject *obj, const char *member, Qt::ConnectionType type, QGenericReturnArgument ret, QGenericArgument val0, QGenericArgument val1, QGenericArgument val2, QGenericArgument val3, QGenericArgument val4, QGenericArgument val5, QGenericArgument val6, QGenericArgument val7, QGenericArgument val8, QGenericArgument val9)
job.h
job_p.h
QLatin1String
KIO::UDSEntry::UDS_ACCESS
Access permissions (part of the mode returned by stat)
Definition: udsentry.h:171
KIO::ChmodJob::~ChmodJob
virtual ~ChmodJob()
Definition: chmodjob.cpp:107
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::UDSEntry::UDS_NAME
Filename - as displayed in directory listings etc.
Definition: udsentry.h:163
KIO::UDSEntry::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
QList< UDSEntry >::ConstIterator
typedef ConstIterator
KIO::Job
The base class for all jobs.
Definition: jobclasses.h:94
KJobTrackerInterface::registerJob
virtual void registerJob(KJob *job)
kmessagebox.h
QObject::connect
bool connect(const QObject *sender, const char *signal, const QObject *receiver, const char *method, Qt::ConnectionType type)
KIO::JobPrivate
Definition: job_p.h:39
end
const KShortcut & end()
KJob
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)
QList::begin
iterator begin()
chmodjob.h
KFileItem::url
KUrl url() const
Returns the url of the file.
Definition: kfileitem.cpp:1543
QFile::encodeName
QByteArray encodeName(const QString &fileName)
KFileItem
A KFileItem is a generic class to handle a file, local or remote.
Definition: kfileitem.h:45
KRecentDirs::list
QStringList list(const QString &fileClass)
Returns a list of directories associated with this file-class.
Definition: krecentdirs.cpp:60
KIO::SimpleJob
A simple job (one url and one command).
Definition: jobclasses.h:322
This file is part of the KDE documentation.
Documentation copyright © 1996-2020 The KDE developers.
Generated on Mon Jun 22 2020 13:24:52 by doxygen 1.8.7 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 API Reference

Skip menu "kdelibs 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

Search



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