Pith - whittle
whittle/src/core/Scanner.cpp [3.6 kb]
Modified: 19:51:43 130 026 (27 Jul 026)
0 Days Ago
#include "core/Scanner.h"
#include <QFile>
#include <dirent.h>
#include <sys/stat.h>
#include <fcntl.h>

namespace whittle {
namespace {

bool statxNoFollow(const QByteArray& path, struct statx& stx) {
    return ::statx(AT_FDCWD, path.constData(), AT_SYMLINK_NOFOLLOW,
                   STATX_TYPE | STATX_MODE | STATX_SIZE |
                   STATX_MTIME | STATX_NLINK, &stx) == 0;
}

std::int64_t mtimeNs(const struct statx& stx) {
    return std::int64_t(stx.stx_mtime.tv_sec) * 1'000'000'000LL
         + stx.stx_mtime.tv_nsec;
}

} 

QHash<QString, FileRecord> Scanner::run(const QStringList& roots,
                                        const QSet<QString>& excluded,
                                        bool isUsb, bool recursive,
                                        const std::atomic<bool>& cancel,
                                        const ProgressFn& onProgress) {
    QHash<QString, FileRecord> out;
    int folders = 0, files = 0;
    qint64 bytes = 0;
    for (const QString& root : roots) {
        if (cancel.load(std::memory_order_relaxed)) break;

        const QString base = isUsb ? root : QString();

        walk(root, base, recursive, excluded, out, folders, files, bytes,
             cancel, onProgress);
    }
    if (onProgress) onProgress(folders, files, bytes);
    return out;
}

void Scanner::walk(const QString& dirPath, const QString& base, bool recursive,
                   const QSet<QString>& excluded,
                   QHash<QString, FileRecord>& out,
                   int& folders, int& files, qint64& bytes,
                   const std::atomic<bool>& cancel, const ProgressFn& onProgress) {
    if (cancel.load(std::memory_order_relaxed)) return;

    const QByteArray dirEnc = QFile::encodeName(dirPath);
    DIR* d = ::opendir(dirEnc.constData());
    if (!d) return;

    if (dirPath != base) {
        struct statx stx;
        if (statxNoFollow(dirEnc, stx) && S_ISDIR(stx.stx_mode)) {
            FileRecord rec;
            rec.absPath = dirPath;
            rec.relPath = dirPath.mid(base.length() + 1);
            rec.isDir   = true;
            rec.mtimeNs = mtimeNs(stx);
            out.insert(rec.relPath, rec);
            if (++folders % 256 == 0 && onProgress) onProgress(folders, files, bytes);
        }
    }

    struct dirent* ent;
    while ((ent = ::readdir(d)) != nullptr) {
        if (cancel.load(std::memory_order_relaxed)) break;
        const char* n = ent->d_name;
        if (n[0] == '.' && (n[1] == '\0' || (n[1] == '.' && n[2] == '\0')))
            continue;

        const QString    childPath = dirPath + '/' + QFile::decodeName(n);
        const QByteArray childEnc  = QFile::encodeName(childPath);

        struct statx stx;
        if (!statxNoFollow(childEnc, stx)) continue;
        const auto mode = stx.stx_mode;

        if (S_ISLNK(mode) || S_ISFIFO(mode) || S_ISSOCK(mode) ||
            S_ISCHR(mode) || S_ISBLK(mode))
            continue;

        if (S_ISDIR(mode)) {
            if (recursive && !excluded.contains(childPath))
                walk(childPath, base, recursive, excluded, out,
                     folders, files, bytes, cancel, onProgress);
        } else if (S_ISREG(mode)) {
            if (stx.stx_nlink > 1) continue;
            FileRecord rec;
            rec.absPath = childPath;
            rec.relPath = childPath.mid(base.length() + 1);
            rec.size    = std::int64_t(stx.stx_size);
            rec.mtimeNs = mtimeNs(stx);
            out.insert(rec.relPath, rec);
            bytes += rec.size;
            if (++files % 256 == 0 && onProgress) onProgress(folders, files, bytes);
        }
    }
    ::closedir(d);
}

} 
Updates
Whittle - Linux 130.026
Wedge - Android 126.026
Wedge - Linux 124.026
Shim - Android 117.026
Miter - 114.026
Dev
TVShow (227) 'CSA'
TVShow (228) 'APT'
TVProgram (83) 'BXT'
Miter Update(s)
Peen (Messaging)

Menu
Calendar
Project Tin (024/029)
Miter
RSS Feed
User Avatar
@vgmlr
=SUM(parts)