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

0001 /*
0002     SPDX-License-Identifier: LGPL-2.0-or-later
0003     SPDX-FileCopyrightText: 2021 Harald Sitter <sitter@kde.org>
0004 */
0005 
0006 #ifndef KCRASH_METADATA_H
0007 #define KCRASH_METADATA_H
0008 
0009 #include <QtGlobal>
0010 
0011 #include <array>
0012 
0013 class QByteArray;
0014 
0015 namespace KCrash
0016 {
0017 // A metadata writer interface.
0018 class MetadataWriter
0019 {
0020 public:
0021     enum BoolValue { No = false, Yes = true };
0022 
0023     virtual void add(const char *key, const char *value, BoolValue boolValue) = 0;
0024     virtual void close() = 0;
0025 
0026 protected:
0027     MetadataWriter() = default;
0028     virtual ~MetadataWriter() = default;
0029 
0030 private:
0031     Q_DISABLE_COPY_MOVE(MetadataWriter)
0032 };
0033 
0034 #ifdef Q_OS_LINUX
0035 // This writes the metadata file. Only really useful on Linux for now as this needs
0036 // cleanup by a helper daemon later. Also, this is only ever useful when coredump is in use.
0037 class MetadataINIWriter : public MetadataWriter
0038 {
0039 public:
0040     explicit MetadataINIWriter(const QByteArray &path);
0041     ~MetadataINIWriter() override = default;
0042 
0043     void add(const char *key, const char *value, BoolValue boolValue) override;
0044     void close() override;
0045 
0046     // open or not, all functions are generally save to call without checking this
0047     [[nodiscard]] bool isWritable() const;
0048 
0049 private:
0050     bool writable = false;
0051     int fd = -1;
0052 
0053     Q_DISABLE_COPY_MOVE(MetadataINIWriter)
0054 };
0055 #endif
0056 
0057 // Compile the crash metadata. These are the primary ARGV metadata, but additional
0058 // metadata writers may be added behind it to (e.g.) write the data to a file as well.
0059 //   man 7 signal-safety
0060 class Metadata : public MetadataWriter
0061 {
0062 public:
0063     explicit Metadata(const char *cmd);
0064     ~Metadata() override = default;
0065 
0066     // Add an additional writer that should receive write calls as well. Do not call this after having called add.
0067     void setAdditionalWriter(MetadataWriter *writer);
0068 
0069     void add(const char *key, const char *value);
0070     void addBool(const char *key);
0071 
0072     // Also closes the backing writer.
0073     void close() override;
0074 
0075     // WARNING: DO NOT FORGET TO BUMP AND SHRINK THE CAPACITY
0076     // - boolean values increase the argv by 1 slot
0077     // - non-boolean values increase the argv by 2 slots
0078     // - this should always be the maximum of potentially used slots
0079     // - if you re-count slots, don't forget that the 'cmd' and terminal NULL take a slot each
0080     std::array<const char *, 34> argv{};
0081     std::size_t argc = 0;
0082 
0083 private:
0084     void add(const char *key, const char *value, BoolValue boolValue) override;
0085 
0086     // Obviously if we should ever need more writers, refactor to std::initializer_list or something similar.
0087     MetadataWriter *m_writer = nullptr;
0088 
0089     Q_DISABLE_COPY_MOVE(Metadata)
0090 };
0091 
0092 } // namespace KCrash
0093 
0094 #endif // KCRASH_METADATA_H