KIO

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

KDE's Doxygen guidelines are available online.