File indexing completed on 2024-04-21 03:51:40

0001 /*
0002     This file is part of the KDE Baloo Project
0003     SPDX-FileCopyrightText: 2015 Vishesh Handa <vhanda@kde.org>
0004 
0005     SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
0006 */
0007 
0008 #ifndef BALOO_ID_UTILS_
0009 #define BALOO_ID_UTILS_
0010 
0011 #include <qplatformdefs.h>
0012 #include <qglobal.h>
0013 
0014 #ifdef Q_OS_WIN
0015 # include <QFileInfo>
0016 #else
0017 # include <sys/statvfs.h>
0018 #endif
0019 
0020 namespace Baloo {
0021 
0022 inline quint64 devIdAndInodeToId(quint32 devId, quint32 inode)
0023 {
0024     quint64 res;
0025     quint32 arr[2];
0026     arr[0] = devId;
0027     arr[1] = inode;
0028 
0029     memcpy(&res, arr, sizeof(arr));
0030     return res;
0031 }
0032 
0033 /**
0034  * Convert the QT_STATBUF into a 64 bit unique identifier for the file.
0035  * This identifier is combination of the device id and inode number.
0036  */
0037 inline quint64 statBufToId(const QT_STATBUF& stBuf)
0038 {
0039     // We're losing 32 bits of info, so this could potentially break
0040     // on file systems with really large inode and device ids
0041     return devIdAndInodeToId(static_cast<quint32>(stBuf.st_dev),
0042                              static_cast<quint32>(stBuf.st_ino));
0043 }
0044 
0045 #ifndef Q_OS_WIN
0046 inline int statWithFsid(const char* path, QT_STATBUF* statBuf)
0047 {
0048     int ret = QT_LSTAT(path, statBuf);
0049     if (ret != 0) {
0050         return ret;
0051     }
0052 
0053     struct statvfs fsBuf;
0054     ret = statvfs(path, &fsBuf);
0055     if (ret == 0 && fsBuf.f_fsid != 0) {
0056         // Fold FSID into 32 bits, statBufToId would discard anything else
0057         statBuf->st_dev = static_cast<quint32>(fsBuf.f_fsid ^ (fsBuf.f_fsid >> 32));
0058     }
0059     return ret;
0060 }
0061 #endif
0062 
0063 inline int filePathToStat(const QByteArray& filePath, QT_STATBUF& statBuf)
0064 {
0065 #ifndef Q_OS_WIN
0066     return statWithFsid(filePath.constData(), &statBuf);
0067 #else
0068     const int ret = QT_STAT(filePath.constData(), &statBuf);
0069     const QString filePathStr = QString::fromUtf8(filePath);
0070     if (ret == 0 && QFileInfo(filePathStr).isSymLink()) {
0071         return QT_STAT(QFileInfo(filePathStr).symLinkTarget().toUtf8().constData(), &statBuf);
0072     } else {
0073         return ret;
0074     }
0075 #endif
0076 }
0077 
0078 inline quint64 filePathToId(const QByteArray& filePath)
0079 {
0080     QT_STATBUF statBuf;
0081     const int ret = filePathToStat(filePath, statBuf);
0082     return ret ? 0 : statBufToId(statBuf);
0083 }
0084 
0085 inline quint32 idToInode(quint64 id)
0086 {
0087     quint32* arr = reinterpret_cast<quint32*>(&id);
0088     return arr[1];
0089 }
0090 
0091 inline quint32 idToDeviceId(quint64 id)
0092 {
0093     quint32* arr = reinterpret_cast<quint32*>(&id);
0094     return arr[0];
0095 }
0096 
0097 template<typename T, typename V>
0098 inline void sortedIdInsert(T& vec, const V& id)
0099 {
0100     /**
0101      * search with normal <
0102      */
0103     const auto i(std::lower_bound(vec.begin(), vec.end(), id));
0104 
0105     /**
0106      * end reached or element found smaller?
0107      * => insert new element!
0108      */
0109     if (i == vec.end() || (id != *i))
0110         vec.insert(i, id);
0111 }
0112 
0113 template<typename T, typename V>
0114 inline void sortedIdRemove(T& vec, const V& id)
0115 {
0116     const int idx = vec.indexOf(id);
0117     if (idx >= 0) {
0118         vec.remove(idx);
0119     }
0120 }
0121 
0122 }
0123 
0124 #endif