File indexing completed on 2024-09-15 03:38:31
0001 /* 0002 This file is part of the KDE project 0003 SPDX-FileCopyrightText: 2004 Jan Schaefer <j_schaef@informatik.uni-kl.de> 0004 0005 SPDX-License-Identifier: LGPL-2.0-only 0006 */ 0007 0008 #include "knfsshare.h" 0009 0010 #include "../utils_p.h" 0011 0012 #include <QDebug> 0013 #include <QFile> 0014 #include <QFileInfo> 0015 #include <QSet> 0016 #include <QTextStream> 0017 0018 #include "kiocoredebug.h" 0019 #include <KConfig> 0020 #include <KConfigGroup> 0021 #include <KDirWatch> 0022 0023 class Q_DECL_HIDDEN KNFSShare::KNFSSharePrivate 0024 { 0025 public: 0026 explicit KNFSSharePrivate(KNFSShare *parent); 0027 0028 void slotFileChange(const QString &); 0029 0030 bool readExportsFile(); 0031 bool findExportsFile(); 0032 0033 KNFSShare *const q; 0034 QSet<QString> sharedPaths; 0035 QString exportsFile; 0036 }; 0037 0038 KNFSShare::KNFSSharePrivate::KNFSSharePrivate(KNFSShare *parent) 0039 : q(parent) 0040 { 0041 if (findExportsFile()) { 0042 readExportsFile(); 0043 } 0044 } 0045 0046 /** 0047 * Try to find the nfs config file path 0048 * First tries the kconfig, then checks 0049 * several well-known paths 0050 * @return whether an 'exports' file was found. 0051 **/ 0052 bool KNFSShare::KNFSSharePrivate::findExportsFile() 0053 { 0054 KConfig knfsshare(QStringLiteral("knfsshare")); 0055 KConfigGroup config(&knfsshare, QStringLiteral("General")); 0056 exportsFile = config.readPathEntry("exportsFile", QString()); 0057 0058 if (!exportsFile.isEmpty() && QFileInfo::exists(exportsFile)) { 0059 return true; 0060 } 0061 0062 if (QFile::exists(QStringLiteral("/etc/exports"))) { 0063 exportsFile = QStringLiteral("/etc/exports"); 0064 } else { 0065 // qDebug() << "Could not find exports file! /etc/exports doesn't exist. Configure it in share/config/knfsshare, [General], exportsFile=...."; 0066 return false; 0067 } 0068 0069 config.writeEntry("exportsFile", exportsFile); 0070 return true; 0071 } 0072 0073 /** 0074 * Reads all paths from the exports file 0075 * and fills the sharedPaths dict with the values 0076 */ 0077 bool KNFSShare::KNFSSharePrivate::readExportsFile() 0078 { 0079 QFile f(exportsFile); 0080 0081 // qDebug() << exportsFile; 0082 0083 if (!f.open(QIODevice::ReadOnly)) { 0084 qCWarning(KIO_CORE) << "KNFSShare: Could not open" << exportsFile; 0085 return false; 0086 } 0087 0088 sharedPaths.clear(); 0089 0090 QTextStream s(&f); 0091 0092 bool continuedLine = false; // is true if the line before ended with a backslash 0093 QString completeLine; 0094 0095 while (!s.atEnd()) { 0096 QString currentLine = s.readLine().trimmed(); 0097 0098 if (continuedLine) { 0099 completeLine += currentLine; 0100 continuedLine = false; 0101 } else { 0102 completeLine = currentLine; 0103 } 0104 0105 // is the line continued in the next line ? 0106 if (completeLine.endsWith(QLatin1Char('\\'))) { 0107 continuedLine = true; 0108 // remove the ending backslash 0109 completeLine.chop(1); 0110 continue; 0111 } 0112 0113 // comments or empty lines 0114 if (completeLine.startsWith(QLatin1Char('#')) || completeLine.isEmpty()) { 0115 continue; 0116 } 0117 0118 QString path; 0119 0120 // Handle quotation marks 0121 if (completeLine[0] == QLatin1Char('\"')) { 0122 int i = completeLine.indexOf(QLatin1Char('"'), 1); 0123 if (i == -1) { 0124 qCWarning(KIO_CORE) << "KNFSShare: Parse error: Missing quotation mark:" << completeLine; 0125 continue; 0126 } 0127 path = completeLine.mid(1, i - 1); 0128 0129 } else { // no quotation marks 0130 int i = completeLine.indexOf(QLatin1Char(' ')); 0131 if (i == -1) { 0132 i = completeLine.indexOf(QLatin1Char('\t')); 0133 } 0134 0135 if (i == -1) { 0136 path = completeLine; 0137 } else { 0138 path = completeLine.left(i); 0139 } 0140 } 0141 0142 // qDebug() << "KNFSShare: Found path: " << path; 0143 0144 if (!path.isEmpty()) { 0145 // Append a '/' to normalize path 0146 Utils::appendSlash(path); 0147 sharedPaths.insert(path); 0148 } 0149 } 0150 0151 return true; 0152 } 0153 0154 KNFSShare::KNFSShare() 0155 : d(new KNFSSharePrivate(this)) 0156 { 0157 if (!d->exportsFile.isEmpty() && QFileInfo::exists(d->exportsFile)) { 0158 KDirWatch::self()->addFile(d->exportsFile); 0159 connect(KDirWatch::self(), &KDirWatch::dirty, this, [this](const QString &path) { 0160 d->slotFileChange(path); 0161 }); 0162 } 0163 } 0164 0165 KNFSShare::~KNFSShare() = default; 0166 0167 bool KNFSShare::isDirectoryShared(const QString &path) const 0168 { 0169 if (path.isEmpty()) { 0170 return false; 0171 } 0172 0173 return d->sharedPaths.contains(Utils::slashAppended(path)); 0174 } 0175 0176 QStringList KNFSShare::sharedDirectories() const 0177 { 0178 return d->sharedPaths.values(); 0179 } 0180 0181 QString KNFSShare::exportsPath() const 0182 { 0183 return d->exportsFile; 0184 } 0185 0186 void KNFSShare::KNFSSharePrivate::slotFileChange(const QString &path) 0187 { 0188 if (path == exportsFile) { 0189 readExportsFile(); 0190 } 0191 0192 Q_EMIT q->changed(); 0193 } 0194 0195 class KNFSShareSingleton 0196 { 0197 public: 0198 KNFSShare instance; 0199 }; 0200 0201 Q_GLOBAL_STATIC(KNFSShareSingleton, _instance) 0202 0203 KNFSShare *KNFSShare::instance() 0204 { 0205 return &_instance()->instance; 0206 } 0207 0208 #include "moc_knfsshare.cpp"