KIO

knfsshare.cpp
1 /*
2  This file is part of the KDE project
3  SPDX-FileCopyrightText: 2004 Jan Schaefer <[email protected]>
4 
5  SPDX-License-Identifier: LGPL-2.0-only
6 */
7 
8 #include "knfsshare.h"
9 
10 #include <QDebug>
11 #include <QFile>
12 #include <QFileInfo>
13 #include <QSet>
14 #include <QTextStream>
15 
16 #include "kiocoredebug.h"
17 #include <KConfig>
18 #include <KConfigGroup>
19 #include <KDirWatch>
20 
21 class Q_DECL_HIDDEN KNFSShare::KNFSSharePrivate
22 {
23 public:
24  explicit KNFSSharePrivate(KNFSShare *parent);
25 
26  void _k_slotFileChange(const QString &);
27 
28  bool readExportsFile();
29  bool findExportsFile();
30 
31  KNFSShare *const q;
32  QSet<QString> sharedPaths;
33  QString exportsFile;
34 };
35 
36 KNFSShare::KNFSSharePrivate::KNFSSharePrivate(KNFSShare *parent)
37  : q(parent)
38 {
39  if (findExportsFile()) {
40  readExportsFile();
41  }
42 }
43 
44 /**
45  * Try to find the nfs config file path
46  * First tries the kconfig, then checks
47  * several well-known paths
48  * @return whether an 'exports' file was found.
49  **/
50 bool KNFSShare::KNFSSharePrivate::findExportsFile()
51 {
52  KConfig knfsshare(QStringLiteral("knfsshare"));
53  KConfigGroup config(&knfsshare, "General");
54  exportsFile = config.readPathEntry("exportsFile", QString());
55 
56  if (!exportsFile.isEmpty() && QFileInfo::exists(exportsFile)) {
57  return true;
58  }
59 
60  if (QFile::exists(QStringLiteral("/etc/exports"))) {
61  exportsFile = QStringLiteral("/etc/exports");
62  } else {
63  // qDebug() << "Could not find exports file! /etc/exports doesn't exist. Configure it in share/config/knfsshare, [General], exportsFile=....";
64  return false;
65  }
66 
67  config.writeEntry("exportsFile", exportsFile);
68  return true;
69 }
70 
71 /**
72  * Reads all paths from the exports file
73  * and fills the sharedPaths dict with the values
74  */
75 bool KNFSShare::KNFSSharePrivate::readExportsFile()
76 {
77  QFile f(exportsFile);
78 
79  // qDebug() << exportsFile;
80 
81  if (!f.open(QIODevice::ReadOnly)) {
82  qCWarning(KIO_CORE) << "KNFSShare: Could not open" << exportsFile;
83  return false;
84  }
85 
86  sharedPaths.clear();
87 
88  QTextStream s(&f);
89 
90  bool continuedLine = false; // is true if the line before ended with a backslash
91  QString completeLine;
92 
93  while (!s.atEnd()) {
94  QString currentLine = s.readLine().trimmed();
95 
96  if (continuedLine) {
97  completeLine += currentLine;
98  continuedLine = false;
99  } else {
100  completeLine = currentLine;
101  }
102 
103  // is the line continued in the next line ?
104  if (completeLine.endsWith(QLatin1Char('\\'))) {
105  continuedLine = true;
106  // remove the ending backslash
107  completeLine.chop(1);
108  continue;
109  }
110 
111  // comments or empty lines
112  if (completeLine.startsWith(QLatin1Char('#')) || completeLine.isEmpty()) {
113  continue;
114  }
115 
116  QString path;
117 
118  // Handle quotation marks
119  if (completeLine[0] == QLatin1Char('\"')) {
120  int i = completeLine.indexOf(QLatin1Char('"'), 1);
121  if (i == -1) {
122  qCWarning(KIO_CORE) << "KNFSShare: Parse error: Missing quotation mark:" << completeLine;
123  continue;
124  }
125  path = completeLine.mid(1, i - 1);
126 
127  } else { // no quotation marks
128  int i = completeLine.indexOf(QLatin1Char(' '));
129  if (i == -1) {
130  i = completeLine.indexOf(QLatin1Char('\t'));
131  }
132 
133  if (i == -1) {
134  path = completeLine;
135  } else {
136  path = completeLine.left(i);
137  }
138  }
139 
140  // qDebug() << "KNFSShare: Found path: " << path;
141 
142  if (!path.isEmpty()) {
143  // normalize path
144  if (!path.endsWith(QLatin1Char('/'))) {
145  path += QLatin1Char('/');
146  }
147 
148  sharedPaths.insert(path);
149  }
150  }
151 
152  return true;
153 }
154 
155 KNFSShare::KNFSShare()
156  : d(new KNFSSharePrivate(this))
157 {
158  if (!d->exportsFile.isEmpty() && QFileInfo::exists(d->exportsFile)) {
159  KDirWatch::self()->addFile(d->exportsFile);
160  connect(KDirWatch::self(), &KDirWatch::dirty, this, [this](const QString &path) {
161  d->_k_slotFileChange(path);
162  });
163  }
164 }
165 
166 KNFSShare::~KNFSShare() = default;
167 
168 bool KNFSShare::isDirectoryShared(const QString &path) const
169 {
170  if (path.isEmpty()) {
171  return false;
172  }
173  QString fixedPath = path;
174  if (!fixedPath.endsWith(QLatin1Char('/'))) {
175  fixedPath += QLatin1Char('/');
176  }
177 
178  return d->sharedPaths.contains(fixedPath);
179 }
180 
182 {
183  return d->sharedPaths.values();
184 }
185 
187 {
188  return d->exportsFile;
189 }
190 
191 void KNFSShare::KNFSSharePrivate::_k_slotFileChange(const QString &path)
192 {
193  if (path == exportsFile) {
194  readExportsFile();
195  }
196 
197  Q_EMIT q->changed();
198 }
199 
200 class KNFSShareSingleton
201 {
202 public:
203  KNFSShare instance;
204 };
205 
206 Q_GLOBAL_STATIC(KNFSShareSingleton, _instance)
207 
208 KNFSShare *KNFSShare::instance()
209 {
210  return &_instance()->instance;
211 }
212 
213 #include "moc_knfsshare.cpp"
int indexOf(QChar ch, int from, Qt::CaseSensitivity cs) const const
static KDirWatch * self()
void addFile(const QString &file)
bool exists() const const
void chop(int n)
~KNFSShare() override
KNFSShare destructor.
KSharedConfigPtr config()
bool isEmpty() const const
QString trimmed() const const
bool startsWith(const QString &s, Qt::CaseSensitivity cs) const const
bool endsWith(const QString &s, Qt::CaseSensitivity cs) const const
bool exists() const const
QString mid(int position, int n) const const
bool isDirectoryShared(const QString &path) const
Whether or not the given path is shared by NFS.
Definition: knfsshare.cpp:168
QString left(int n) const const
void dirty(const QString &path)
static KNFSShare * instance()
Returns the one and only instance of KNFSShare.
Definition: knfsshare.cpp:208
QMetaObject::Connection connect(const QObject *sender, const char *signal, const QObject *receiver, const char *method, Qt::ConnectionType type)
Similar functionality like KFileShare, but works only for NFS and do not need any suid script...
Definition: knfsshare.h:26
QStringList sharedDirectories() const
Returns a list of all directories shared by NFS.
Definition: knfsshare.cpp:181
Q_EMITQ_EMIT
QString exportsPath() const
Returns the path to the used exports file, or null if no exports file was found.
Definition: knfsshare.cpp:186
This file is part of the KDE documentation.
Documentation copyright © 1996-2022 The KDE developers.
Generated on Tue Jan 18 2022 22:53:46 by doxygen 1.8.11 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.