• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

llnl / dftracer-utils / 23531027933

25 Mar 2026 08:05AM UTC coverage: 48.592% (-1.5%) from 50.098%
23531027933

Pull #57

github

web-flow
Merge d1070e289 into 38f9f3616
Pull Request #57: feat(comparator): add pairwise traces comparator

18900 of 49456 branches covered (38.22%)

Branch coverage included in aggregate %.

1604 of 1954 new or added lines in 25 files covered. (82.09%)

3407 existing lines in 135 files now uncovered.

18487 of 27485 relevant lines covered (67.26%)

240991.5 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

15.48
/src/dftracer/utils/core/common/format_detector.cpp
1
#include <dftracer/utils/core/common/format_detector.h>
2
#include <dftracer/utils/core/common/logging.h>
3
#include <zlib.h>
4

5
#include <algorithm>
6
#include <cstring>
7

8
namespace dftracer::utils {
9

10
ArchiveFormat FormatDetector::detect(const std::string& file_path) {
2,110✔
11
    if (file_path.size() >= 7 &&
4,214✔
12
        file_path.substr(file_path.size() - 7) == ".tar.gz") {
2,104✔
13
        return ArchiveFormat::TAR_GZ;
22✔
14
    } else if (file_path.size() >= 4 &&
4,174!
15
               file_path.substr(file_path.size() - 4) == ".tgz") {
2,086✔
16
        return ArchiveFormat::TAR_GZ;
×
17
    } else if (file_path.size() >= 3 &&
4,174✔
18
               file_path.substr(file_path.size() - 3) == ".gz") {
2,086✔
19
        return ArchiveFormat::GZIP;
2,087✔
20
    } else if (file_path.size() >= 5 &&
1!
UNCOV
21
               file_path.substr(file_path.size() - 5) == ".gzip") {
×
22
        return ArchiveFormat::GZIP;
×
23
    }
24

25
    FILE* file = std::fopen(file_path.c_str(), "rb");
1✔
26
    if (!file) {
1!
27
        DFTRACER_UTILS_LOG_ERROR("Failed to open file for format detection: %s",
1!
28
                                 file_path.c_str());
29
        return ArchiveFormat::UNKNOWN;
1✔
30
    }
31

32
    ArchiveFormat format = detect_from_content(file);
×
33
    std::fclose(file);
×
34
    return format;
×
35
}
2,110✔
36

37
ArchiveFormat FormatDetector::detect_from_content(FILE* file) {
×
38
    if (!has_gzip_magic(file)) {
×
39
        return ArchiveFormat::UNKNOWN;
×
40
    }
41

42
    if (has_tar_header_after_gzip(file)) {
×
43
        return ArchiveFormat::TAR_GZ;
×
44
    }
45

46
    return ArchiveFormat::GZIP;
×
UNCOV
47
}
×
48

49
bool FormatDetector::is_tar_gz(FILE* file) {
×
50
    return detect_from_content(file) == ArchiveFormat::TAR_GZ;
×
51
}
52

53
bool FormatDetector::is_gzip(FILE* file) {
×
54
    return detect_from_content(file) == ArchiveFormat::GZIP;
×
55
}
56

57
bool FormatDetector::has_gzip_magic(FILE* file) {
×
58
    if (fseeko(file, 0, SEEK_SET) != 0) {
×
59
        return false;
×
60
    }
61

62
    unsigned char magic[2];
63
    if (fread(magic, 1, 2, file) != 2) {
×
64
        return false;
×
65
    }
66

67
    // GZIP magic: 0x1f 0x8b
68
    return magic[0] == 0x1f && magic[1] == 0x8b;
×
UNCOV
69
}
×
70

71
bool FormatDetector::has_tar_header_after_gzip(FILE* file) {
×
72
    // Seek to the beginning of the file
73
    if (fseeko(file, 0, SEEK_SET) != 0) {
×
74
        return false;
×
75
    }
76

77
    // Initialize zlib for GZIP decompression
78
    z_stream stream;
79
    memset(&stream, 0, sizeof(stream));
×
80

81
    if (inflateInit2(&stream, 31) != Z_OK) {  // 31 = 15 + 16 for GZIP format
×
82
        return false;
×
83
    }
84

85
    // Read input buffer
86
    const size_t buffer_size = 8192;
×
87
    unsigned char in_buffer[buffer_size];
88
    unsigned char out_buffer[buffer_size];
89

90
    bool found_tar_header = false;
×
91
    size_t total_out = 0;
×
92

93
    while (total_out < 512) {  // Need at least 512 bytes for TAR header
×
94
        // Read compressed data
95
        size_t bytes_read = fread(in_buffer, 1, buffer_size, file);
×
96
        if (bytes_read == 0) {
×
97
            if (ferror(file)) {
×
98
                DFTRACER_UTILS_LOG_DEBUG(
99
                    "%s", "Error reading file during TAR detection");
UNCOV
100
            }
×
101
            break;
×
102
        }
103

104
        stream.next_in = in_buffer;
×
105
        stream.avail_in = static_cast<uInt>(bytes_read);
×
106

107
        while (stream.avail_in > 0 && total_out < 512) {
×
108
            stream.next_out = out_buffer;
×
109
            stream.avail_out =
×
110
                static_cast<uInt>(std::min(buffer_size, 512 - total_out));
×
111

112
            int ret = inflate(&stream, Z_NO_FLUSH);
×
113
            if (ret != Z_OK && ret != Z_STREAM_END) {
×
114
                break;
×
115
            }
116

UNCOV
117
            size_t bytes_out =
×
118
                (std::min(buffer_size, 512 - total_out)) - stream.avail_out;
×
119

120
            // Check if we have enough bytes to validate TAR header
121
            if (total_out + bytes_out >= 512) {
×
122
                // We need to copy existing data if any and append new data
123
                unsigned char tar_header[512];
124
                memset(tar_header, 0, 512);
×
125

126
                if (total_out > 0) {
×
127
                    // This is more complex - we'd need to store previous output
128
                    // For simplicity, let's check if we got the header in one
129
                    // go
130
                    if (total_out == 0 && bytes_out >= 512) {
×
131
                        memcpy(tar_header, out_buffer, 512);
×
132
                        found_tar_header = is_valid_tar_header(tar_header);
×
UNCOV
133
                    }
×
134
                } else if (bytes_out >= 512) {
×
135
                    memcpy(tar_header, out_buffer, 512);
×
136
                    found_tar_header = is_valid_tar_header(tar_header);
×
UNCOV
137
                }
×
138
                break;
×
139
            }
140

141
            total_out += bytes_out;
×
142

143
            if (ret == Z_STREAM_END) {
×
144
                break;
×
145
            }
146
        }
147

148
        if (found_tar_header || total_out >= 512) {
×
UNCOV
149
            break;
×
150
        }
151
    }
152

153
    inflateEnd(&stream);
×
154
    return found_tar_header;
×
UNCOV
155
}
×
156

157
bool FormatDetector::is_valid_tar_header(const unsigned char* header) {
×
158
    // Check for POSIX TAR magic: "ustar\0"
159
    const char* ustar_magic = "ustar";
×
160
    if (memcmp(header + 257, ustar_magic, 5) == 0 && header[262] == 0) {
×
161
        // Validate checksum
162
        unsigned int stored_checksum = 0;
×
163

164
        // Read checksum field (bytes 148-155) as octal
165
        for (int i = 148; i < 156; i++) {
×
166
            char c = header[i];
×
167
            if (c >= '0' && c <= '7') {
×
168
                stored_checksum = stored_checksum * 8 + (c - '0');
×
169
            } else if (c == ' ' || c == '\0') {
×
UNCOV
170
                break;
×
171
            } else {
172
                return false;
×
173
            }
UNCOV
174
        }
×
175

176
        unsigned int calculated_checksum = calculate_tar_checksum(header);
×
177
        return stored_checksum == calculated_checksum;
×
178
    }
179

180
    // Check for old GNU tar format - look for reasonable filename
181
    // and verify that most of the header fields make sense
182
    bool has_filename = false;
×
183
    for (int i = 0; i < 100; i++) {
×
184
        if (header[i] == '\0') {
×
185
            has_filename = (i > 0);  // Non-empty filename
×
186
            break;
×
187
        }
188
        if (!isprint(header[i]) && header[i] != '/') {
×
189
            return false;
×
190
        }
UNCOV
191
    }
×
192

193
    if (!has_filename) {
×
194
        return false;
×
195
    }
196

197
    // Check file mode (should be reasonable octal value)
198
    bool mode_ok = true;
×
199
    for (int i = 100; i < 108; i++) {
×
200
        char c = header[i];
×
201
        if (c != ' ' && c != '\0' && (c < '0' || c > '7')) {
×
202
            mode_ok = false;
×
203
            break;
×
204
        }
UNCOV
205
    }
×
206

207
    return mode_ok;
×
UNCOV
208
}
×
209

210
unsigned int FormatDetector::calculate_tar_checksum(
×
211
    const unsigned char* header) {
212
    unsigned int checksum = 0;
×
213

214
    // Sum all bytes, treating checksum field (148-155) as spaces
215
    for (int i = 0; i < 512; i++) {
×
216
        if (i >= 148 && i < 156) {
×
217
            checksum += ' ';  // Checksum field treated as spaces
×
UNCOV
218
        } else {
×
219
            checksum += header[i];
×
220
        }
UNCOV
221
    }
×
222

223
    return checksum;
×
224
}
225
}  // namespace dftracer::utils
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc