File indexing completed on 2024-04-28 15:20:27
0001 /* 0002 SPDX-License-Identifier: LGPL-2.0-or-later 0003 SPDX-FileCopyrightText: 2021 Harald Sitter <sitter@kde.org> 0004 */ 0005 0006 #include "metadata_p.h" 0007 0008 #include <QByteArray> 0009 #include <cerrno> 0010 0011 #ifdef Q_OS_LINUX 0012 #include <cstring> 0013 #include <fcntl.h> 0014 #include <sys/stat.h> 0015 #include <sys/types.h> 0016 #include <unistd.h> 0017 #endif 0018 0019 namespace KCrash 0020 { 0021 #ifdef Q_OS_LINUX 0022 MetadataINIWriter::MetadataINIWriter(const QByteArray &path) 0023 : MetadataWriter() 0024 { 0025 if (path.isEmpty()) { 0026 return; 0027 } 0028 0029 fd = ::open(path.constData(), O_WRONLY | O_CREAT | O_NONBLOCK | O_TRUNC | O_CLOEXEC, S_IRUSR | S_IWUSR); 0030 if (fd == -1) { 0031 fprintf(stderr, "Failed to open metadata file: %s\n", strerror(errno)); 0032 } else if (fd >= 0) { 0033 writable = true; 0034 const char *header = "[KCrash]\n"; 0035 write(fd, header, strlen(header)); 0036 } else { 0037 fprintf(stderr, "MetadataINIWriter: Unexpected fd %d\n", fd); 0038 Q_UNREACHABLE(); 0039 } 0040 } 0041 0042 void MetadataINIWriter::close() 0043 { 0044 if (fd >= 0 && ::close(fd) == -1) { 0045 fprintf(stderr, "Failed to close metadata file: %s\n", strerror(errno)); 0046 } 0047 writable = false; 0048 } 0049 0050 void MetadataINIWriter::add(const char *key, const char *value, BoolValue boolValue) 0051 { 0052 Q_ASSERT(key); 0053 Q_ASSERT(value); 0054 Q_ASSERT(key[0] == '-' && key[1] == '-'); // well-formed '--' prefix. This is important. MetadataWriter presume this 0055 Q_UNUSED(boolValue); // value is a bool string but we don't care, we always write the value anyway 0056 0057 if (fd < 0) { 0058 return; 0059 } 0060 const int ret = snprintf(iniLine.data(), iniLine.max_size(), "%s=%s\n", key + 2 /** skip the leading -- */, value); 0061 if (ret < 0) { 0062 fprintf(stderr, "Failed to generate metadata line for '%s', '%s'\n", key, value); 0063 return; 0064 } 0065 // Cannot be negative anymore. 0066 const std::make_unsigned<decltype(ret)>::type lineLength = ret; 0067 fprintf(stderr, "%d -- %s", lineLength, iniLine.data()); 0068 Q_ASSERT(lineLength <= iniLine.max_size()); // is not truncated41 0069 write(fd, iniLine.data(), lineLength); 0070 } 0071 0072 bool MetadataINIWriter::isWritable() const 0073 { 0074 return writable; 0075 } 0076 #endif 0077 0078 Metadata::Metadata(const char *cmd) 0079 { 0080 // NB: cmd may be null! Just because we create metadata doesn't mean we'll execute drkonqi (we may only need the 0081 // backing writers) 0082 Q_ASSERT(argc == 0); 0083 argv.at(argc++) = cmd; 0084 } 0085 0086 void Metadata::setAdditionalWriter(MetadataWriter *writer) 0087 { 0088 // Once set the writer oughtn't be reset as we have no use case for this and should we get one in the future 0089 // it'll need at least review of the existing code to handle writer switching correctly. 0090 Q_ASSERT(m_writer == nullptr); 0091 Q_ASSERT(writer != nullptr); 0092 m_writer = writer; 0093 } 0094 0095 void Metadata::add(const char *key, const char *value) 0096 { 0097 add(key, value, BoolValue::No); 0098 } 0099 0100 void Metadata::addBool(const char *key) 0101 { 0102 add(key, "true", BoolValue::Yes); 0103 } 0104 0105 void Metadata::close() 0106 { 0107 // NULL terminated list 0108 argv.at(argc) = nullptr; 0109 0110 if (m_writer) { 0111 m_writer->close(); 0112 } 0113 } 0114 0115 void Metadata::add(const char *key, const char *value, BoolValue boolValue) 0116 { 0117 Q_ASSERT(key); 0118 Q_ASSERT(value); 0119 Q_ASSERT(key[0] == '-' && key[1] == '-'); // well-formed '--' prefix. This is important. MetadataWriter presume this 0120 Q_ASSERT(argc < argv.max_size()); // argv has a static max size. guard against exhaustion 0121 0122 argv.at(argc++) = key; 0123 if (!boolValue) { 0124 argv.at(argc++) = value; 0125 } 0126 0127 if (m_writer) { 0128 m_writer->add(key, value, boolValue); 0129 } 0130 } 0131 0132 } // namespace KCrash