Warning, file /system/kjournald/lib/journaldexportreader.cpp was not indexed or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).

0001 /*
0002     SPDX-License-Identifier: LGPL-2.1-or-later OR MIT
0003     SPDX-FileCopyrightText: 2021 Andreas Cord-Landwehr <cordlandwehr@kde.org>
0004 */
0005 
0006 #include "journaldexportreader.h"
0007 #include "kjournaldlib_log_general.h"
0008 #include <QDebug>
0009 #include <QVector>
0010 #include <QIODevice>
0011 #include <climits>
0012 
0013 JournaldExportReader::JournaldExportReader(QIODevice *device)
0014     : mDevice(device)
0015 {
0016     if (!mDevice || !mDevice->open(QIODevice::ReadOnly)) {
0017         qCCritical(KJOURNALDLIB_GENERAL) << "Could not open device for reading";
0018         return;
0019     }
0020 }
0021 
0022 bool JournaldExportReader::atEnd() const
0023 {
0024     return mDevice->atEnd();
0025 }
0026 
0027 // Format description: <https://www.freedesktop.org/wiki/Software/systemd/export/>
0028 // - Two journal entries that follow each other are separated by a double newline.
0029 // - Journal fields consisting only of valid non-control UTF-8 codepoints are serialized as they are
0030 //   (i.e. the field name, followed by '=', followed by field data), followed by a newline as
0031 //   separator to the next field. Note that fields containing newlines cannot be formatted like
0032 //   this. Non-control UTF-8 codepoints are the codepoints with value at or above 32 (' '), or
0033 //   equal to 9 (TAB).
0034 // - Other journal fields are serialized in a special binary safe way: field name, followed by
0035 //   newline, followed by a binary 64bit little endian size value, followed by the binary field
0036 //   data, followed by a newline as separator to the next field.
0037 // - Entry metadata that is not actually a field is serialized like it was a field, but beginning
0038 //   with two underscores. More specifically, __CURSOR=, __REALTIME_TIMESTAMP=,
0039 //   __MONOTONIC_TIMESTAMP= are introduced this way. Note that these meta-fields are only generated
0040 //   when actual journal files are serialized. They are omitted for entries that do not originate
0041 //   from a journal file (for example because they are transferred for the first time to be stored
0042 //   in one). Or in other words: if you are generating this format you shouldn't care about these
0043 //   special double-underscore fields. But you might find them usable when you deserialize the
0044 //   format generated by us. Additional fields prefixed with two underscores might be added later
0045 //   on, your parser should skip over the fields it does not know.
0046 // - The order in which fields appear in an entry is undefined and might be different for each entry
0047 //   that is serialized.
0048 
0049 bool JournaldExportReader::readNext()
0050 {
0051     if (mDevice->atEnd()) {
0052         return false;
0053     }
0054 
0055     mCurrentEntry.clear();
0056     while (!mDevice->atEnd()) {
0057         QString line = QString::fromLocal8Bit(mDevice->readLine().trimmed());
0058         // empty line = beginning of new log entry
0059         if (line.isEmpty()) {
0060             break; // found break in log entry
0061         }
0062 
0063         // if line does not contain "=" then switch to binary reading mode
0064         int separatorIndex = line.indexOf(QLatin1Char('='));
0065         if (separatorIndex > 0) {
0066             mCurrentEntry[line.left(separatorIndex)] = line.right(line.length() - separatorIndex - 1).trimmed();
0067         } else {
0068             QString fieldId = line;
0069             union {
0070                 uint64_t uint64;
0071                 char chars[4];
0072             } size;
0073             qint64 bytes = mDevice->read(size.chars, 8);
0074             if (bytes != 8) {
0075                 qCWarning(KJOURNALDLIB_GENERAL) << "Journal entry read that has unexpected number of bytes (8 bytes expected)" << bytes;
0076             }
0077             mCurrentEntry[fieldId] = QString::fromLocal8Bit(mDevice->read(le64toh(size.uint64)));
0078             // read line break after binary content, such that reader points to next line
0079             mDevice->read(1);
0080         }
0081     }
0082 
0083     return true;
0084 }
0085 
0086 JournaldExportReader::LogEntry JournaldExportReader::entry() const
0087 {
0088     return mCurrentEntry;
0089 }