trace.c (46195B)
1 #include "trace.h" 2 3 #include <stdio.h> 4 #include <string.h> 5 6 static int set_err(char* err, size_t errcap, const char* msg) { 7 if (err && errcap) snprintf(err, errcap, "%s", msg); 8 return BUILD_ERR; 9 } 10 11 static int emit_bytes(KitWriter* out, const char* s) { 12 return kit_writer_write(out, s, strlen(s)) == KIT_OK ? BUILD_OK : BUILD_ERR; 13 } 14 15 static void hex_encode(char out[BUILD_HEX_LEN], 16 const uint8_t in[BUILD_HASH_LEN]) { 17 size_t i; 18 for (i = 0; i < BUILD_HASH_LEN; ++i) { 19 unsigned hi = (unsigned)(in[i] >> 4); 20 unsigned lo = (unsigned)(in[i] & 0x0fu); 21 out[2u * i] = (char)(hi < 10u ? '0' + hi : 'a' + (hi - 10u)); 22 out[2u * i + 1u] = (char)(lo < 10u ? '0' + lo : 'a' + (lo - 10u)); 23 } 24 out[2u * BUILD_HASH_LEN] = '\0'; 25 } 26 27 static int hex_val(char c, unsigned* out) { 28 if (c >= '0' && c <= '9') { 29 *out = (unsigned)(c - '0'); 30 return BUILD_OK; 31 } 32 if (c >= 'a' && c <= 'f') { 33 *out = (unsigned)(c - 'a') + 10u; 34 return BUILD_OK; 35 } 36 return BUILD_ERR; 37 } 38 39 static int hex_decode_strict(const char* s, uint8_t out[BUILD_HASH_LEN]) { 40 size_t i; 41 if (!s || strlen(s) != 2u * BUILD_HASH_LEN) return BUILD_ERR; 42 for (i = 0; i < BUILD_HASH_LEN; ++i) { 43 unsigned hi, lo; 44 if (hex_val(s[2u * i], &hi) != BUILD_OK) return BUILD_ERR; 45 if (hex_val(s[2u * i + 1u], &lo) != BUILD_OK) return BUILD_ERR; 46 out[i] = (uint8_t)((hi << 4) | lo); 47 } 48 return BUILD_OK; 49 } 50 51 static int is_token_char(unsigned char c) { 52 return c > 0x20u && c < 0x7fu; 53 } 54 55 static int valid_token(const char* s, size_t cap) { 56 size_t i; 57 if (!s || !s[0]) return 0; 58 for (i = 0; s[i]; ++i) { 59 if (i + 1u >= cap) return 0; 60 if (!is_token_char((unsigned char)s[i])) return 0; 61 } 62 return 1; 63 } 64 65 static int valid_target(const char* s) { return valid_token(s, BUILD_TARGET_MAX); } 66 67 static int valid_key(const char* s) { return valid_token(s, BUILD_KEY_MAX); } 68 69 static int valid_path(const char* s) { return valid_token(s, BUILD_PATH_MAX); } 70 71 static int valid_pattern(const char* s) { 72 return valid_token(s, BUILD_PATTERN_MAX); 73 } 74 75 static int copy_field(char* dst, size_t cap, const char* src, char* err, 76 size_t errcap) { 77 if (!valid_token(src, cap)) return set_err(err, errcap, "bad field value"); 78 snprintf(dst, cap, "%s", src); 79 return BUILD_OK; 80 } 81 82 static int emit_kv(KitWriter* out, const char* key, 83 const uint8_t h[BUILD_HASH_LEN]) { 84 char hex[BUILD_HEX_LEN]; 85 char line[96]; 86 hex_encode(hex, h); 87 snprintf(line, sizeof line, "%s %s\n", key, hex); 88 return emit_bytes(out, line); 89 } 90 91 static int emit_text_kv(KitWriter* out, const char* key, const char* val) { 92 char line[BUILD_TARGET_MAX + 32u]; 93 snprintf(line, sizeof line, "%s %s\n", key, val); 94 return emit_bytes(out, line); 95 } 96 97 static int id_cmp(const uint8_t a[BUILD_HASH_LEN], 98 const uint8_t b[BUILD_HASH_LEN]) { 99 return memcmp(a, b, BUILD_HASH_LEN); 100 } 101 102 static int source_cmp(const BuildSourceLeaf* a, const BuildSourceLeaf* b) { 103 return strcmp(a->path, b->path); 104 } 105 106 static int glob_cmp(const BuildGlobLeaf* a, const BuildGlobLeaf* b) { 107 return strcmp(a->pattern, b->pattern); 108 } 109 110 static int blob_cmp(const BuildBlobLeaf* a, const BuildBlobLeaf* b) { 111 return id_cmp(a->blob, b->blob); 112 } 113 114 static int config_cmp(const BuildConfigLeaf* a, const BuildConfigLeaf* b) { 115 int c = strcmp(a->key, b->key); 116 if (c != 0) return c; 117 if (a->present != b->present) return a->present < b->present ? -1 : 1; 118 if (a->has_default != b->has_default) 119 return a->has_default < b->has_default ? -1 : 1; 120 c = id_cmp(a->value_hash, b->value_hash); 121 if (c != 0) return c; 122 return id_cmp(a->default_hash, b->default_hash); 123 } 124 125 static int dep_cmp(const BuildDepEdge* a, const BuildDepEdge* b) { 126 int c = strcmp(a->name, b->name); 127 if (c != 0) return c; 128 c = id_cmp(a->overlay_id, b->overlay_id); 129 if (c != 0) return c; 130 return id_cmp(a->argv_id, b->argv_id); 131 } 132 133 static int emit_section(KitWriter* out, const char* name) { 134 char line[32]; 135 snprintf(line, sizeof line, "[%s]\n", name); 136 return emit_bytes(out, line); 137 } 138 139 static int emit_hash_or_dash(KitWriter* out, int has_hash, 140 const uint8_t h[BUILD_HASH_LEN]) { 141 char hex[BUILD_HEX_LEN]; 142 if (!has_hash) return emit_bytes(out, "-"); 143 hex_encode(hex, h); 144 return emit_bytes(out, hex); 145 } 146 147 static int emit_config_row(KitWriter* out, const BuildConfigLeaf* row) { 148 if (emit_bytes(out, row->key) != BUILD_OK) return BUILD_ERR; 149 if (emit_bytes(out, row->present ? " present " : " unset ") != BUILD_OK) 150 return BUILD_ERR; 151 if (emit_hash_or_dash(out, row->present || row->has_default, 152 row->value_hash) != BUILD_OK) 153 return BUILD_ERR; 154 if (emit_bytes(out, " ") != BUILD_OK) return BUILD_ERR; 155 if (emit_hash_or_dash(out, row->has_default, row->default_hash) != BUILD_OK) 156 return BUILD_ERR; 157 return emit_bytes(out, "\n"); 158 } 159 160 static int emit_sorted_configs(const BuildConfigLeaf* rows, size_t n, 161 KitWriter* out, char* err, size_t errcap) { 162 const BuildConfigLeaf* prev = NULL; 163 size_t emitted = 0; 164 if (n && !rows) return set_err(err, errcap, "missing config rows"); 165 if (emit_section(out, "config") != BUILD_OK) return BUILD_ERR; 166 while (emitted < n) { 167 const BuildConfigLeaf* best = NULL; 168 size_t i; 169 for (i = 0; i < n; ++i) { 170 const BuildConfigLeaf* cur = &rows[i]; 171 int after_prev; 172 if (!valid_key(cur->key)) 173 return set_err(err, errcap, "bad config key"); 174 if ((cur->present != 0 && cur->present != 1) || 175 (cur->has_default != 0 && cur->has_default != 1)) 176 return set_err(err, errcap, "bad config flags"); 177 after_prev = !prev || config_cmp(prev, cur) < 0; 178 if (after_prev && (!best || config_cmp(cur, best) < 0)) best = cur; 179 } 180 if (!best) return set_err(err, errcap, "duplicate config key"); 181 if (emit_config_row(out, best) != BUILD_OK) return BUILD_ERR; 182 prev = best; 183 ++emitted; 184 } 185 return BUILD_OK; 186 } 187 188 static int emit_source_row(KitWriter* out, const BuildSourceLeaf* row) { 189 char hex[BUILD_HEX_LEN]; 190 if (emit_bytes(out, row->path) != BUILD_OK) return BUILD_ERR; 191 if (emit_bytes(out, " ") != BUILD_OK) return BUILD_ERR; 192 if (row->absent) { 193 if (emit_bytes(out, "-") != BUILD_OK) return BUILD_ERR; 194 } else { 195 hex_encode(hex, row->blob); 196 if (emit_bytes(out, hex) != BUILD_OK) return BUILD_ERR; 197 } 198 return emit_bytes(out, "\n"); 199 } 200 201 static int emit_sorted_sources(const BuildSourceLeaf* rows, size_t n, 202 KitWriter* out, char* err, size_t errcap) { 203 const BuildSourceLeaf* prev = NULL; 204 size_t emitted = 0; 205 if (n && !rows) return set_err(err, errcap, "missing source rows"); 206 if (emit_section(out, "source") != BUILD_OK) return BUILD_ERR; 207 while (emitted < n) { 208 const BuildSourceLeaf* best = NULL; 209 size_t i; 210 for (i = 0; i < n; ++i) { 211 const BuildSourceLeaf* cur = &rows[i]; 212 int after_prev; 213 if (!valid_path(cur->path)) return set_err(err, errcap, "bad source path"); 214 if (cur->absent != 0 && cur->absent != 1) 215 return set_err(err, errcap, "bad source absent flag"); 216 after_prev = !prev || source_cmp(prev, cur) < 0; 217 if (after_prev && (!best || source_cmp(cur, best) < 0)) best = cur; 218 } 219 if (!best) return set_err(err, errcap, "duplicate source path"); 220 if (emit_source_row(out, best) != BUILD_OK) return BUILD_ERR; 221 prev = best; 222 ++emitted; 223 } 224 return BUILD_OK; 225 } 226 227 static int emit_glob_row(KitWriter* out, const BuildGlobLeaf* row) { 228 char hex[BUILD_HEX_LEN]; 229 hex_encode(hex, row->result_hash); 230 if (emit_bytes(out, row->pattern) != BUILD_OK) return BUILD_ERR; 231 if (emit_bytes(out, " ") != BUILD_OK) return BUILD_ERR; 232 if (emit_bytes(out, hex) != BUILD_OK) return BUILD_ERR; 233 return emit_bytes(out, "\n"); 234 } 235 236 static int emit_sorted_globs(const BuildGlobLeaf* rows, size_t n, KitWriter* out, 237 char* err, size_t errcap) { 238 const BuildGlobLeaf* prev = NULL; 239 size_t emitted = 0; 240 if (n && !rows) return set_err(err, errcap, "missing glob rows"); 241 if (emit_section(out, "glob") != BUILD_OK) return BUILD_ERR; 242 while (emitted < n) { 243 const BuildGlobLeaf* best = NULL; 244 size_t i; 245 for (i = 0; i < n; ++i) { 246 const BuildGlobLeaf* cur = &rows[i]; 247 int after_prev; 248 if (!valid_pattern(cur->pattern)) 249 return set_err(err, errcap, "bad glob pattern"); 250 after_prev = !prev || glob_cmp(prev, cur) < 0; 251 if (after_prev && (!best || glob_cmp(cur, best) < 0)) best = cur; 252 } 253 if (!best) return set_err(err, errcap, "duplicate glob pattern"); 254 if (emit_glob_row(out, best) != BUILD_OK) return BUILD_ERR; 255 prev = best; 256 ++emitted; 257 } 258 return BUILD_OK; 259 } 260 261 static int emit_blob_row(KitWriter* out, const BuildBlobLeaf* row) { 262 char hex[BUILD_HEX_LEN]; 263 hex_encode(hex, row->blob); 264 if (emit_bytes(out, hex) != BUILD_OK) return BUILD_ERR; 265 return emit_bytes(out, "\n"); 266 } 267 268 static int emit_sorted_blobs(const BuildBlobLeaf* rows, size_t n, 269 KitWriter* out, char* err, size_t errcap) { 270 const BuildBlobLeaf* prev = NULL; 271 size_t emitted = 0; 272 if (n && !rows) return set_err(err, errcap, "missing blob rows"); 273 if (emit_section(out, "blob") != BUILD_OK) return BUILD_ERR; 274 while (emitted < n) { 275 const BuildBlobLeaf* best = NULL; 276 size_t i; 277 for (i = 0; i < n; ++i) { 278 const BuildBlobLeaf* cur = &rows[i]; 279 int after_prev = !prev || blob_cmp(prev, cur) < 0; 280 if (after_prev && (!best || blob_cmp(cur, best) < 0)) best = cur; 281 } 282 if (!best) return set_err(err, errcap, "duplicate blob row"); 283 if (emit_blob_row(out, best) != BUILD_OK) return BUILD_ERR; 284 prev = best; 285 ++emitted; 286 } 287 return BUILD_OK; 288 } 289 290 static int emit_dep_row(KitWriter* out, const BuildDepEdge* row) { 291 char ovr[BUILD_HEX_LEN], argv[BUILD_HEX_LEN], tree[BUILD_HEX_LEN]; 292 hex_encode(ovr, row->overlay_id); 293 hex_encode(argv, row->argv_id); 294 hex_encode(tree, row->output_tree); 295 if (emit_bytes(out, row->name) != BUILD_OK) return BUILD_ERR; 296 if (emit_bytes(out, " ") != BUILD_OK) return BUILD_ERR; 297 if (emit_bytes(out, ovr) != BUILD_OK) return BUILD_ERR; 298 if (emit_bytes(out, " ") != BUILD_OK) return BUILD_ERR; 299 if (emit_bytes(out, argv) != BUILD_OK) return BUILD_ERR; 300 if (emit_bytes(out, " ") != BUILD_OK) return BUILD_ERR; 301 if (emit_bytes(out, tree) != BUILD_OK) return BUILD_ERR; 302 return emit_bytes(out, "\n"); 303 } 304 305 static int emit_sorted_deps(const BuildDepEdge* rows, size_t n, KitWriter* out, 306 char* err, size_t errcap) { 307 const BuildDepEdge* prev = NULL; 308 size_t emitted = 0; 309 if (n && !rows) return set_err(err, errcap, "missing dep rows"); 310 if (emit_section(out, "dep") != BUILD_OK) return BUILD_ERR; 311 while (emitted < n) { 312 const BuildDepEdge* best = NULL; 313 size_t i; 314 for (i = 0; i < n; ++i) { 315 const BuildDepEdge* cur = &rows[i]; 316 int after_prev; 317 if (!valid_target(cur->name)) return set_err(err, errcap, "bad dep name"); 318 after_prev = !prev || dep_cmp(prev, cur) < 0; 319 if (after_prev && (!best || dep_cmp(cur, best) < 0)) best = cur; 320 } 321 if (!best) return set_err(err, errcap, "duplicate dep row"); 322 if (emit_dep_row(out, best) != BUILD_OK) return BUILD_ERR; 323 prev = best; 324 ++emitted; 325 } 326 return BUILD_OK; 327 } 328 329 static int emit_child_row(KitWriter* out, const uint8_t id[BUILD_HASH_LEN]) { 330 char hex[BUILD_HEX_LEN]; 331 hex_encode(hex, id); 332 if (emit_bytes(out, hex) != BUILD_OK) return BUILD_ERR; 333 return emit_bytes(out, "\n"); 334 } 335 336 /* Use a flat byte view here: strict C11 cannot add const through a 337 * pointer-to-array conversion (that becomes well-defined only in C23). */ 338 static int emit_sorted_children(const uint8_t* rows, size_t n, KitWriter* out, 339 char* err, size_t errcap) { 340 const uint8_t* prev = NULL; 341 size_t emitted = 0; 342 if (n && !rows) return set_err(err, errcap, "missing child rows"); 343 if (emit_section(out, "child") != BUILD_OK) return BUILD_ERR; 344 while (emitted < n) { 345 const uint8_t* best = NULL; 346 size_t i; 347 for (i = 0; i < n; ++i) { 348 const uint8_t* cur = rows + i * BUILD_HASH_LEN; 349 int after_prev = !prev || id_cmp(prev, cur) < 0; 350 if (after_prev && (!best || id_cmp(cur, best) < 0)) best = cur; 351 } 352 if (!best) return set_err(err, errcap, "duplicate child row"); 353 if (emit_child_row(out, best) != BUILD_OK) return BUILD_ERR; 354 prev = best; 355 ++emitted; 356 } 357 return BUILD_OK; 358 } 359 360 static int check_record_kind(uint8_t kind) { 361 return kind == (uint8_t)BUILD_TRACE_DEEP || 362 kind == (uint8_t)BUILD_TRACE_SHALLOW; 363 } 364 365 static const char* record_kind_name(uint8_t kind) { 366 if (kind == (uint8_t)BUILD_TRACE_DEEP) return "deep"; 367 if (kind == (uint8_t)BUILD_TRACE_SHALLOW) return "shallow"; 368 return NULL; 369 } 370 371 static int record_kind_parse(const char* s, uint8_t* out) { 372 if (strcmp(s, "deep") == 0) { 373 *out = (uint8_t)BUILD_TRACE_DEEP; 374 return BUILD_OK; 375 } 376 if (strcmp(s, "shallow") == 0) { 377 *out = (uint8_t)BUILD_TRACE_SHALLOW; 378 return BUILD_OK; 379 } 380 return BUILD_ERR; 381 } 382 383 static int emit_record_rows(const BuildRecordRow* rows, size_t n, KitWriter* out, 384 char* err, size_t errcap) { 385 size_t i, j; 386 size_t deep = 0, shallow = 0; 387 if (n && !rows) return set_err(err, errcap, "missing record rows"); 388 for (i = 0; i < n; ++i) { 389 const char* kind = record_kind_name(rows[i].kind); 390 char hex[BUILD_HEX_LEN]; 391 if (!kind) return set_err(err, errcap, "bad record kind"); 392 if (rows[i].kind == (uint8_t)BUILD_TRACE_DEEP) { 393 if (++deep > KIT_BUILD_RECORD_CAP) 394 return set_err(err, errcap, "too many deep records"); 395 } else { 396 if (++shallow > KIT_BUILD_RECORD_CAP) 397 return set_err(err, errcap, "too many shallow records"); 398 } 399 for (j = 0; j < i; ++j) { 400 if (rows[j].kind == rows[i].kind && 401 build_id_eq(rows[j].trace_id, rows[i].trace_id)) 402 return set_err(err, errcap, "duplicate record row"); 403 } 404 hex_encode(hex, rows[i].trace_id); 405 if (emit_text_kv(out, kind, hex) != BUILD_OK) return BUILD_ERR; 406 } 407 return BUILD_OK; 408 } 409 410 static int shallow_emit_like(const BuildShallowTrace* t, KitWriter* out, 411 char* err, size_t errcap, const char* magic, 412 const char* result_key) { 413 if (!t || !out) return set_err(err, errcap, "missing shallow trace"); 414 if (!valid_target(t->target)) return set_err(err, errcap, "bad target"); 415 if (emit_bytes(out, magic) != BUILD_OK || emit_bytes(out, "\n") != BUILD_OK) 416 return BUILD_ERR; 417 if (emit_text_kv(out, "target", t->target) != BUILD_OK) return BUILD_ERR; 418 if (emit_kv(out, "recipe", t->recipe) != BUILD_OK) return BUILD_ERR; 419 if (emit_kv(out, result_key, t->output) != BUILD_OK) return BUILD_ERR; 420 if (emit_kv(out, "argv", t->argv) != BUILD_OK) return BUILD_ERR; 421 if (emit_sorted_configs(t->configs, t->n_configs, out, err, errcap) != 422 BUILD_OK) 423 return BUILD_ERR; 424 if (emit_sorted_sources(t->sources, t->n_sources, out, err, errcap) != 425 BUILD_OK) 426 return BUILD_ERR; 427 if (emit_sorted_globs(t->globs, t->n_globs, out, err, errcap) != BUILD_OK) 428 return BUILD_ERR; 429 if (emit_sorted_blobs(t->blobs, t->n_blobs, out, err, errcap) != 430 BUILD_OK) 431 return BUILD_ERR; 432 if (emit_sorted_deps(t->deps, t->n_deps, out, err, errcap) != BUILD_OK) 433 return BUILD_ERR; 434 return kit_writer_status(out) == KIT_OK ? BUILD_OK : BUILD_ERR; 435 } 436 437 int build_shallow_emit(const BuildShallowTrace* t, KitWriter* out, char* err, 438 size_t errcap) { 439 return shallow_emit_like(t, out, err, errcap, BUILD_SHALLOW_MAGIC, "output"); 440 } 441 442 int build_test_shallow_emit(const BuildShallowTrace* t, KitWriter* out, 443 char* err, size_t errcap) { 444 return shallow_emit_like(t, out, err, errcap, BUILD_TEST_SHALLOW_MAGIC, 445 "result"); 446 } 447 448 static int deep_emit_like(const BuildDeepTrace* t, KitWriter* out, char* err, 449 size_t errcap, const char* magic, 450 const char* result_key) { 451 if (!t || !out) return set_err(err, errcap, "missing deep trace"); 452 if (!valid_target(t->target)) return set_err(err, errcap, "bad target"); 453 if (emit_bytes(out, magic) != BUILD_OK || emit_bytes(out, "\n") != BUILD_OK) 454 return BUILD_ERR; 455 if (emit_text_kv(out, "target", t->target) != BUILD_OK) return BUILD_ERR; 456 if (emit_kv(out, "recipe", t->recipe) != BUILD_OK) return BUILD_ERR; 457 if (emit_kv(out, result_key, t->output) != BUILD_OK) return BUILD_ERR; 458 if (emit_kv(out, "argv", t->argv) != BUILD_OK) return BUILD_ERR; 459 if (emit_kv(out, "deepset", t->deepset) != BUILD_OK) return BUILD_ERR; 460 return kit_writer_status(out) == KIT_OK ? BUILD_OK : BUILD_ERR; 461 } 462 463 int build_deep_emit(const BuildDeepTrace* t, KitWriter* out, char* err, 464 size_t errcap) { 465 return deep_emit_like(t, out, err, errcap, BUILD_DEEP_MAGIC, "output"); 466 } 467 468 int build_test_deep_emit(const BuildDeepTrace* t, KitWriter* out, char* err, 469 size_t errcap) { 470 return deep_emit_like(t, out, err, errcap, BUILD_TEST_DEEP_MAGIC, "result"); 471 } 472 473 int build_deepset_emit(const BuildDeepSet* t, KitWriter* out, char* err, 474 size_t errcap) { 475 if (!t || !out) return set_err(err, errcap, "missing deepset"); 476 if (!valid_target(t->target)) return set_err(err, errcap, "bad target"); 477 if (emit_bytes(out, BUILD_DEEPSET_MAGIC "\n") != BUILD_OK) return BUILD_ERR; 478 if (emit_text_kv(out, "target", t->target) != BUILD_OK) return BUILD_ERR; 479 if (emit_kv(out, "recipe", t->recipe) != BUILD_OK) return BUILD_ERR; 480 if (emit_sorted_configs(t->configs, t->n_configs, out, err, errcap) != 481 BUILD_OK) 482 return BUILD_ERR; 483 if (emit_sorted_sources(t->sources, t->n_sources, out, err, errcap) != 484 BUILD_OK) 485 return BUILD_ERR; 486 if (emit_sorted_globs(t->globs, t->n_globs, out, err, errcap) != BUILD_OK) 487 return BUILD_ERR; 488 if (emit_sorted_blobs(t->blobs, t->n_blobs, out, err, errcap) != 489 BUILD_OK) 490 return BUILD_ERR; 491 if (emit_sorted_children(t->children ? t->children[0] : NULL, t->n_children, 492 out, err, errcap) != BUILD_OK) 493 return BUILD_ERR; 494 return kit_writer_status(out) == KIT_OK ? BUILD_OK : BUILD_ERR; 495 } 496 497 int build_record_emit(const BuildTargetRecord* t, KitWriter* out, char* err, 498 size_t errcap) { 499 if (!t || !out) return set_err(err, errcap, "missing target record"); 500 if (!valid_target(t->target)) return set_err(err, errcap, "bad target"); 501 if (emit_bytes(out, BUILD_RECORD_MAGIC "\n") != BUILD_OK) return BUILD_ERR; 502 if (emit_text_kv(out, "target", t->target) != BUILD_OK) return BUILD_ERR; 503 if (emit_record_rows(t->rows, t->n_rows, out, err, errcap) != BUILD_OK) 504 return BUILD_ERR; 505 return kit_writer_status(out) == KIT_OK ? BUILD_OK : BUILD_ERR; 506 } 507 508 typedef enum TraceSection { 509 TRACE_SEC_TOP = 0, 510 TRACE_SEC_CONFIG, 511 TRACE_SEC_SOURCE, 512 TRACE_SEC_GLOB, 513 TRACE_SEC_BLOB, 514 TRACE_SEC_DEP, 515 TRACE_SEC_CHILD, 516 TRACE_SEC_RECORD_ROWS 517 } TraceSection; 518 519 typedef struct TraceParser { 520 const uint8_t* data; 521 size_t len; 522 size_t pos; 523 int first; 524 char line[BUILD_PATH_MAX + 5u * BUILD_HEX_LEN + BUILD_TARGET_MAX + 16u]; 525 } TraceParser; 526 527 static int parser_next(TraceParser* p, char** line, char* err, size_t errcap) { 528 size_t end, n, i; 529 if (p->pos >= p->len) return 0; 530 end = p->pos; 531 while (end < p->len && p->data[end] != '\n') ++end; 532 if (end == p->len) { 533 set_err(err, errcap, "missing final newline"); 534 return -1; 535 } 536 n = end - p->pos; 537 if (n >= sizeof p->line) { 538 set_err(err, errcap, "line too long"); 539 return -1; 540 } 541 for (i = p->pos; i < end; ++i) { 542 if (p->data[i] == 0 || p->data[i] == '\r') { 543 set_err(err, errcap, "bad byte in trace"); 544 return -1; 545 } 546 } 547 memcpy(p->line, p->data + p->pos, n); 548 p->line[n] = '\0'; 549 p->pos = end + 1u; 550 *line = p->line; 551 return 1; 552 } 553 554 static int split_line(char* line, char** fields, size_t cap, size_t* nout) { 555 char* p = line; 556 size_t n = 0; 557 if (!line || !line[0]) return BUILD_ERR; 558 while (*p) { 559 if (*p == ' ') return BUILD_ERR; 560 if (n >= cap) return BUILD_ERR; 561 fields[n++] = p; 562 while (*p && *p != ' ') { 563 if (!is_token_char((unsigned char)*p)) return BUILD_ERR; 564 ++p; 565 } 566 if (*p == ' ') { 567 *p++ = '\0'; 568 if (!*p) return BUILD_ERR; 569 } 570 } 571 *nout = n; 572 return BUILD_OK; 573 } 574 575 static int expect_field_count(size_t got, size_t want, char* err, 576 size_t errcap) { 577 if (got != want) return set_err(err, errcap, "bad trace row"); 578 return BUILD_OK; 579 } 580 581 static int parse_top_text(char** fields, size_t n, const char* key, char* dst, 582 size_t cap, uint32_t* seen, uint32_t flag, char* err, 583 size_t errcap) { 584 if (expect_field_count(n, 2u, err, errcap) != BUILD_OK) return BUILD_ERR; 585 if (strcmp(fields[0], key) != 0) return set_err(err, errcap, "bad field order"); 586 if (*seen & flag) return set_err(err, errcap, "duplicate field"); 587 if (copy_field(dst, cap, fields[1], err, errcap) != BUILD_OK) return BUILD_ERR; 588 *seen |= flag; 589 return BUILD_OK; 590 } 591 592 static int parse_top_hash(char** fields, size_t n, const char* key, 593 uint8_t dst[BUILD_HASH_LEN], uint32_t* seen, 594 uint32_t flag, char* err, size_t errcap) { 595 if (expect_field_count(n, 2u, err, errcap) != BUILD_OK) return BUILD_ERR; 596 if (strcmp(fields[0], key) != 0) return set_err(err, errcap, "bad field order"); 597 if (*seen & flag) return set_err(err, errcap, "duplicate field"); 598 if (hex_decode_strict(fields[1], dst) != BUILD_OK) 599 return set_err(err, errcap, "bad hash"); 600 *seen |= flag; 601 return BUILD_OK; 602 } 603 604 static int parse_hash_or_dash(const char* s, int has_hash, 605 uint8_t out[BUILD_HASH_LEN], char* err, 606 size_t errcap) { 607 if (!has_hash) { 608 if (strcmp(s, "-") != 0) return set_err(err, errcap, "bad config hash"); 609 memset(out, 0, BUILD_HASH_LEN); 610 return BUILD_OK; 611 } 612 if (hex_decode_strict(s, out) != BUILD_OK) 613 return set_err(err, errcap, "bad config hash"); 614 return BUILD_OK; 615 } 616 617 static int parse_config_leaf(char** fields, size_t n, BuildConfigLeaf* row, 618 char* err, size_t errcap) { 619 if (expect_field_count(n, 4u, err, errcap) != BUILD_OK) return BUILD_ERR; 620 if (!valid_key(fields[0])) return set_err(err, errcap, "bad config key"); 621 snprintf(row->key, sizeof row->key, "%s", fields[0]); 622 if (strcmp(fields[1], "present") == 0) { 623 row->present = 1; 624 } else if (strcmp(fields[1], "unset") == 0) { 625 row->present = 0; 626 } else { 627 return set_err(err, errcap, "bad config presence"); 628 } 629 row->has_default = strcmp(fields[3], "-") != 0; 630 if (parse_hash_or_dash(fields[2], row->present || row->has_default, 631 row->value_hash, err, errcap) != BUILD_OK || 632 parse_hash_or_dash(fields[3], row->has_default, row->default_hash, err, 633 errcap) != BUILD_OK) 634 return BUILD_ERR; 635 if (!row->present && !row->has_default && strcmp(fields[2], "-") != 0) 636 return set_err(err, errcap, "bad unset config value"); 637 if (!row->present && row->has_default && 638 !build_id_eq(row->value_hash, row->default_hash)) 639 return set_err(err, errcap, "bad default config value"); 640 return BUILD_OK; 641 } 642 643 static int append_shallow_config(BuildShallowTrace* out, char** fields, 644 size_t n, char* err, size_t errcap) { 645 BuildConfigLeaf* row; 646 if (out->n_configs >= out->cap_configs) 647 return set_err(err, errcap, "too many config rows"); 648 row = &out->configs[out->n_configs]; 649 if (parse_config_leaf(fields, n, row, err, errcap) != BUILD_OK) 650 return BUILD_ERR; 651 if (out->n_configs && config_cmp(&out->configs[out->n_configs - 1u], row) >= 0) 652 return set_err(err, errcap, "non-canonical config rows"); 653 ++out->n_configs; 654 return BUILD_OK; 655 } 656 657 static int append_deepset_config(BuildDeepSet* out, char** fields, size_t n, 658 char* err, size_t errcap) { 659 BuildConfigLeaf* row; 660 if (out->n_configs >= out->cap_configs) 661 return set_err(err, errcap, "too many config rows"); 662 row = &out->configs[out->n_configs]; 663 if (parse_config_leaf(fields, n, row, err, errcap) != BUILD_OK) 664 return BUILD_ERR; 665 if (out->n_configs && config_cmp(&out->configs[out->n_configs - 1u], row) >= 0) 666 return set_err(err, errcap, "non-canonical config rows"); 667 ++out->n_configs; 668 return BUILD_OK; 669 } 670 671 static int parse_source_leaf(char** fields, size_t n, BuildSourceLeaf* row, 672 char* err, size_t errcap) { 673 if (expect_field_count(n, 2u, err, errcap) != BUILD_OK) return BUILD_ERR; 674 if (!valid_path(fields[0])) return set_err(err, errcap, "bad source path"); 675 snprintf(row->path, sizeof row->path, "%s", fields[0]); 676 if (strcmp(fields[1], "-") == 0) { 677 memset(row->blob, 0, sizeof row->blob); 678 row->absent = 1; 679 } else { 680 if (hex_decode_strict(fields[1], row->blob) != BUILD_OK) 681 return set_err(err, errcap, "bad source hash"); 682 row->absent = 0; 683 } 684 return BUILD_OK; 685 } 686 687 static int append_shallow_source(BuildShallowTrace* out, char** fields, size_t n, 688 char* err, size_t errcap) { 689 BuildSourceLeaf* row; 690 if (out->n_sources >= out->cap_sources) 691 return set_err(err, errcap, "too many source rows"); 692 row = &out->sources[out->n_sources]; 693 if (parse_source_leaf(fields, n, row, err, errcap) != BUILD_OK) 694 return BUILD_ERR; 695 if (out->n_sources && source_cmp(&out->sources[out->n_sources - 1u], row) >= 0) 696 return set_err(err, errcap, "non-canonical source rows"); 697 ++out->n_sources; 698 return BUILD_OK; 699 } 700 701 static int append_deepset_source(BuildDeepSet* out, char** fields, size_t n, 702 char* err, size_t errcap) { 703 BuildSourceLeaf* row; 704 if (out->n_sources >= out->cap_sources) 705 return set_err(err, errcap, "too many source rows"); 706 row = &out->sources[out->n_sources]; 707 if (parse_source_leaf(fields, n, row, err, errcap) != BUILD_OK) 708 return BUILD_ERR; 709 if (out->n_sources && source_cmp(&out->sources[out->n_sources - 1u], row) >= 0) 710 return set_err(err, errcap, "non-canonical source rows"); 711 ++out->n_sources; 712 return BUILD_OK; 713 } 714 715 static int parse_glob_leaf(char** fields, size_t n, BuildGlobLeaf* row, 716 char* err, size_t errcap) { 717 if (expect_field_count(n, 2u, err, errcap) != BUILD_OK) return BUILD_ERR; 718 if (!valid_pattern(fields[0])) return set_err(err, errcap, "bad glob pattern"); 719 snprintf(row->pattern, sizeof row->pattern, "%s", fields[0]); 720 if (hex_decode_strict(fields[1], row->result_hash) != BUILD_OK) 721 return set_err(err, errcap, "bad glob hash"); 722 return BUILD_OK; 723 } 724 725 static int append_shallow_glob(BuildShallowTrace* out, char** fields, size_t n, 726 char* err, size_t errcap) { 727 BuildGlobLeaf* row; 728 if (out->n_globs >= out->cap_globs) 729 return set_err(err, errcap, "too many glob rows"); 730 row = &out->globs[out->n_globs]; 731 if (parse_glob_leaf(fields, n, row, err, errcap) != BUILD_OK) 732 return BUILD_ERR; 733 if (out->n_globs && glob_cmp(&out->globs[out->n_globs - 1u], row) >= 0) 734 return set_err(err, errcap, "non-canonical glob rows"); 735 ++out->n_globs; 736 return BUILD_OK; 737 } 738 739 static int append_deepset_glob(BuildDeepSet* out, char** fields, size_t n, 740 char* err, size_t errcap) { 741 BuildGlobLeaf* row; 742 if (out->n_globs >= out->cap_globs) 743 return set_err(err, errcap, "too many glob rows"); 744 row = &out->globs[out->n_globs]; 745 if (parse_glob_leaf(fields, n, row, err, errcap) != BUILD_OK) 746 return BUILD_ERR; 747 if (out->n_globs && glob_cmp(&out->globs[out->n_globs - 1u], row) >= 0) 748 return set_err(err, errcap, "non-canonical glob rows"); 749 ++out->n_globs; 750 return BUILD_OK; 751 } 752 753 static int parse_blob_leaf(char** fields, size_t n, BuildBlobLeaf* row, 754 char* err, size_t errcap) { 755 if (expect_field_count(n, 1u, err, errcap) != BUILD_OK) return BUILD_ERR; 756 if (hex_decode_strict(fields[0], row->blob) != BUILD_OK) 757 return set_err(err, errcap, "bad blob hash"); 758 return BUILD_OK; 759 } 760 761 static int append_shallow_blob(BuildShallowTrace* out, char** fields, size_t n, 762 char* err, size_t errcap) { 763 BuildBlobLeaf* row; 764 if (out->n_blobs >= out->cap_blobs) 765 return set_err(err, errcap, "too many blob rows"); 766 row = &out->blobs[out->n_blobs]; 767 if (parse_blob_leaf(fields, n, row, err, errcap) != BUILD_OK) 768 return BUILD_ERR; 769 if (out->n_blobs && blob_cmp(&out->blobs[out->n_blobs - 1u], row) >= 0) 770 return set_err(err, errcap, "non-canonical blob rows"); 771 ++out->n_blobs; 772 return BUILD_OK; 773 } 774 775 static int append_deepset_blob(BuildDeepSet* out, char** fields, size_t n, 776 char* err, size_t errcap) { 777 BuildBlobLeaf* row; 778 if (out->n_blobs >= out->cap_blobs) 779 return set_err(err, errcap, "too many blob rows"); 780 row = &out->blobs[out->n_blobs]; 781 if (parse_blob_leaf(fields, n, row, err, errcap) != BUILD_OK) 782 return BUILD_ERR; 783 if (out->n_blobs && blob_cmp(&out->blobs[out->n_blobs - 1u], row) >= 0) 784 return set_err(err, errcap, "non-canonical blob rows"); 785 ++out->n_blobs; 786 return BUILD_OK; 787 } 788 789 static int append_dep(BuildShallowTrace* out, char** fields, size_t n, char* err, 790 size_t errcap) { 791 BuildDepEdge* row; 792 if (expect_field_count(n, 4u, err, errcap) != BUILD_OK) return BUILD_ERR; 793 if (out->n_deps >= out->cap_deps) 794 return set_err(err, errcap, "too many dep rows"); 795 if (!valid_target(fields[0])) return set_err(err, errcap, "bad dep target"); 796 row = &out->deps[out->n_deps]; 797 snprintf(row->name, sizeof row->name, "%s", fields[0]); 798 if (hex_decode_strict(fields[1], row->overlay_id) != BUILD_OK || 799 hex_decode_strict(fields[2], row->argv_id) != BUILD_OK || 800 hex_decode_strict(fields[3], row->output_tree) != BUILD_OK) 801 return set_err(err, errcap, "bad dep hash"); 802 if (out->n_deps && dep_cmp(&out->deps[out->n_deps - 1u], row) >= 0) 803 return set_err(err, errcap, "non-canonical dep rows"); 804 ++out->n_deps; 805 return BUILD_OK; 806 } 807 808 static int append_child(BuildDeepSet* out, char** fields, size_t n, char* err, 809 size_t errcap) { 810 uint8_t* row; 811 if (expect_field_count(n, 1u, err, errcap) != BUILD_OK) return BUILD_ERR; 812 if (out->n_children >= out->cap_children) 813 return set_err(err, errcap, "too many child rows"); 814 row = out->children[out->n_children]; 815 if (hex_decode_strict(fields[0], row) != BUILD_OK) 816 return set_err(err, errcap, "bad child hash"); 817 if (out->n_children && id_cmp(out->children[out->n_children - 1u], row) >= 0) 818 return set_err(err, errcap, "non-canonical child rows"); 819 ++out->n_children; 820 return BUILD_OK; 821 } 822 823 static int append_record_row(BuildTargetRecord* out, char** fields, size_t n, 824 char* err, size_t errcap) { 825 BuildRecordRow* row; 826 size_t i; 827 size_t same_kind = 0; 828 if (expect_field_count(n, 2u, err, errcap) != BUILD_OK) return BUILD_ERR; 829 if (out->n_rows >= out->cap_rows) 830 return set_err(err, errcap, "too many record rows"); 831 row = &out->rows[out->n_rows]; 832 if (record_kind_parse(fields[0], &row->kind) != BUILD_OK) 833 return set_err(err, errcap, "bad record kind"); 834 if (hex_decode_strict(fields[1], row->trace_id) != BUILD_OK) 835 return set_err(err, errcap, "bad record hash"); 836 for (i = 0; i < out->n_rows; ++i) { 837 if (out->rows[i].kind == row->kind) { 838 ++same_kind; 839 if (build_id_eq(out->rows[i].trace_id, row->trace_id)) 840 return set_err(err, errcap, "duplicate record row"); 841 } 842 } 843 if (same_kind >= KIT_BUILD_RECORD_CAP) 844 return set_err(err, errcap, "too many record rows for kind"); 845 ++out->n_rows; 846 return BUILD_OK; 847 } 848 849 #define F_TARGET 0x01u 850 #define F_RECIPE 0x02u 851 #define F_OUTPUT 0x04u 852 #define F_ARGV 0x08u 853 #define F_DEEPSET 0x10u 854 855 static int shallow_parse_like(const uint8_t* data, size_t len, 856 BuildShallowTrace* out, char* err, 857 size_t errcap, const char* magic, 858 const char* result_key) { 859 TraceParser p; 860 TraceSection sec = TRACE_SEC_TOP; 861 uint32_t seen = 0; 862 if (!data || !out) return set_err(err, errcap, "missing shallow trace"); 863 if ((out->cap_configs && !out->configs) || 864 (out->cap_sources && !out->sources) || (out->cap_globs && !out->globs) || 865 (out->cap_blobs && !out->blobs) || 866 (out->cap_deps && !out->deps)) 867 return set_err(err, errcap, "missing trace storage"); 868 memset(out->target, 0, sizeof out->target); 869 out->n_configs = 0; 870 out->n_sources = 0; 871 out->n_globs = 0; 872 out->n_blobs = 0; 873 out->n_deps = 0; 874 memset(&p, 0, sizeof p); 875 p.data = data; 876 p.len = len; 877 p.first = 1; 878 for (;;) { 879 char* line; 880 char* fields[4]; 881 size_t n = 0; 882 int r = parser_next(&p, &line, err, errcap); 883 if (r < 0) return BUILD_ERR; 884 if (r == 0) break; 885 if (p.first) { 886 p.first = 0; 887 if (strcmp(line, magic) != 0) 888 return set_err(err, errcap, "bad shallow magic/version"); 889 continue; 890 } 891 if (line[0] == '[') { 892 if (strcmp(line, "[config]") == 0 && sec == TRACE_SEC_TOP) { 893 if (seen != (F_TARGET | F_RECIPE | F_OUTPUT | F_ARGV)) 894 return set_err(err, errcap, "missing shallow field"); 895 sec = TRACE_SEC_CONFIG; 896 } else if (strcmp(line, "[source]") == 0 && sec == TRACE_SEC_CONFIG) { 897 sec = TRACE_SEC_SOURCE; 898 } else if (strcmp(line, "[glob]") == 0 && sec == TRACE_SEC_SOURCE) { 899 sec = TRACE_SEC_GLOB; 900 } else if (strcmp(line, "[blob]") == 0 && sec == TRACE_SEC_GLOB) { 901 sec = TRACE_SEC_BLOB; 902 } else if (strcmp(line, "[dep]") == 0 && 903 (sec == TRACE_SEC_GLOB || sec == TRACE_SEC_BLOB)) { 904 sec = TRACE_SEC_DEP; 905 } else { 906 return set_err(err, errcap, "bad shallow section"); 907 } 908 continue; 909 } 910 if (split_line(line, fields, sizeof fields / sizeof fields[0], &n) != 911 BUILD_OK) 912 return set_err(err, errcap, "bad shallow row"); 913 if (sec == TRACE_SEC_TOP) { 914 if (!(seen & F_TARGET)) { 915 if (parse_top_text(fields, n, "target", out->target, sizeof out->target, 916 &seen, F_TARGET, err, errcap) != BUILD_OK) 917 return BUILD_ERR; 918 } else if (!(seen & F_RECIPE)) { 919 if (parse_top_hash(fields, n, "recipe", out->recipe, &seen, F_RECIPE, 920 err, errcap) != BUILD_OK) 921 return BUILD_ERR; 922 } else if (!(seen & F_OUTPUT)) { 923 if (parse_top_hash(fields, n, result_key, out->output, &seen, 924 F_OUTPUT, err, errcap) != BUILD_OK) 925 return BUILD_ERR; 926 } else if (!(seen & F_ARGV)) { 927 if (parse_top_hash(fields, n, "argv", out->argv, &seen, F_ARGV, err, 928 errcap) != BUILD_OK) 929 return BUILD_ERR; 930 } else { 931 return set_err(err, errcap, "unexpected shallow field"); 932 } 933 } else if (sec == TRACE_SEC_CONFIG) { 934 if (append_shallow_config(out, fields, n, err, errcap) != BUILD_OK) 935 return BUILD_ERR; 936 } else if (sec == TRACE_SEC_SOURCE) { 937 if (append_shallow_source(out, fields, n, err, errcap) != BUILD_OK) 938 return BUILD_ERR; 939 } else if (sec == TRACE_SEC_GLOB) { 940 if (append_shallow_glob(out, fields, n, err, errcap) != BUILD_OK) 941 return BUILD_ERR; 942 } else if (sec == TRACE_SEC_BLOB) { 943 if (append_shallow_blob(out, fields, n, err, errcap) != BUILD_OK) 944 return BUILD_ERR; 945 } else if (sec == TRACE_SEC_DEP) { 946 if (append_dep(out, fields, n, err, errcap) != BUILD_OK) return BUILD_ERR; 947 } else { 948 return set_err(err, errcap, "bad shallow row"); 949 } 950 } 951 if (p.first) return set_err(err, errcap, "bad shallow magic/version"); 952 if (sec != TRACE_SEC_DEP) return set_err(err, errcap, "missing shallow section"); 953 return BUILD_OK; 954 } 955 956 int build_shallow_parse(const uint8_t* data, size_t len, BuildShallowTrace* out, 957 char* err, size_t errcap) { 958 return shallow_parse_like(data, len, out, err, errcap, BUILD_SHALLOW_MAGIC, 959 "output"); 960 } 961 962 int build_test_shallow_parse(const uint8_t* data, size_t len, 963 BuildShallowTrace* out, char* err, 964 size_t errcap) { 965 return shallow_parse_like(data, len, out, err, errcap, 966 BUILD_TEST_SHALLOW_MAGIC, "result"); 967 } 968 969 static int deep_parse_like(const uint8_t* data, size_t len, 970 BuildDeepTrace* out, char* err, size_t errcap, 971 const char* magic, const char* result_key) { 972 TraceParser p; 973 uint32_t seen = 0; 974 if (!data || !out) return set_err(err, errcap, "missing deep trace"); 975 memset(out->target, 0, sizeof out->target); 976 memset(&p, 0, sizeof p); 977 p.data = data; 978 p.len = len; 979 p.first = 1; 980 for (;;) { 981 char* line; 982 char* fields[2]; 983 size_t n = 0; 984 int r = parser_next(&p, &line, err, errcap); 985 if (r < 0) return BUILD_ERR; 986 if (r == 0) break; 987 if (p.first) { 988 p.first = 0; 989 if (strcmp(line, magic) != 0) 990 return set_err(err, errcap, "bad deep magic/version"); 991 continue; 992 } 993 if (line[0] == '[') return set_err(err, errcap, "bad deep section"); 994 if (split_line(line, fields, sizeof fields / sizeof fields[0], &n) != 995 BUILD_OK) 996 return set_err(err, errcap, "bad deep row"); 997 if (!(seen & F_TARGET)) { 998 if (parse_top_text(fields, n, "target", out->target, sizeof out->target, 999 &seen, F_TARGET, err, errcap) != BUILD_OK) 1000 return BUILD_ERR; 1001 } else if (!(seen & F_RECIPE)) { 1002 if (parse_top_hash(fields, n, "recipe", out->recipe, &seen, F_RECIPE, 1003 err, errcap) != BUILD_OK) 1004 return BUILD_ERR; 1005 } else if (!(seen & F_OUTPUT)) { 1006 if (parse_top_hash(fields, n, result_key, out->output, &seen, F_OUTPUT, 1007 err, errcap) != BUILD_OK) 1008 return BUILD_ERR; 1009 } else if (!(seen & F_ARGV)) { 1010 if (parse_top_hash(fields, n, "argv", out->argv, &seen, F_ARGV, err, 1011 errcap) != BUILD_OK) 1012 return BUILD_ERR; 1013 } else if (!(seen & F_DEEPSET)) { 1014 if (parse_top_hash(fields, n, "deepset", out->deepset, &seen, F_DEEPSET, 1015 err, errcap) != BUILD_OK) 1016 return BUILD_ERR; 1017 } else { 1018 return set_err(err, errcap, "unexpected deep field"); 1019 } 1020 } 1021 if (p.first) return set_err(err, errcap, "bad deep magic/version"); 1022 if (seen != (F_TARGET | F_RECIPE | F_OUTPUT | F_ARGV | F_DEEPSET)) 1023 return set_err(err, errcap, "missing deep field"); 1024 return BUILD_OK; 1025 } 1026 1027 int build_deep_parse(const uint8_t* data, size_t len, BuildDeepTrace* out, 1028 char* err, size_t errcap) { 1029 return deep_parse_like(data, len, out, err, errcap, BUILD_DEEP_MAGIC, 1030 "output"); 1031 } 1032 1033 int build_test_deep_parse(const uint8_t* data, size_t len, BuildDeepTrace* out, 1034 char* err, size_t errcap) { 1035 return deep_parse_like(data, len, out, err, errcap, BUILD_TEST_DEEP_MAGIC, 1036 "result"); 1037 } 1038 1039 int build_deepset_parse(const uint8_t* data, size_t len, BuildDeepSet* out, 1040 char* err, size_t errcap) { 1041 TraceParser p; 1042 TraceSection sec = TRACE_SEC_TOP; 1043 uint32_t seen = 0; 1044 if (!data || !out) return set_err(err, errcap, "missing deepset"); 1045 if ((out->cap_configs && !out->configs) || 1046 (out->cap_sources && !out->sources) || (out->cap_globs && !out->globs) || 1047 (out->cap_blobs && !out->blobs) || 1048 (out->cap_children && !out->children)) 1049 return set_err(err, errcap, "missing deepset storage"); 1050 memset(out->target, 0, sizeof out->target); 1051 out->n_configs = 0; 1052 out->n_sources = 0; 1053 out->n_globs = 0; 1054 out->n_blobs = 0; 1055 out->n_children = 0; 1056 memset(&p, 0, sizeof p); 1057 p.data = data; 1058 p.len = len; 1059 p.first = 1; 1060 for (;;) { 1061 char* line; 1062 char* fields[4]; 1063 size_t n = 0; 1064 int r = parser_next(&p, &line, err, errcap); 1065 if (r < 0) return BUILD_ERR; 1066 if (r == 0) break; 1067 if (p.first) { 1068 p.first = 0; 1069 if (strcmp(line, BUILD_DEEPSET_MAGIC) != 0) 1070 return set_err(err, errcap, "bad deepset magic/version"); 1071 continue; 1072 } 1073 if (line[0] == '[') { 1074 if (strcmp(line, "[config]") == 0 && sec == TRACE_SEC_TOP) { 1075 if (seen != (F_TARGET | F_RECIPE)) 1076 return set_err(err, errcap, "missing deepset field"); 1077 sec = TRACE_SEC_CONFIG; 1078 } else if (strcmp(line, "[source]") == 0 && sec == TRACE_SEC_CONFIG) { 1079 sec = TRACE_SEC_SOURCE; 1080 } else if (strcmp(line, "[glob]") == 0 && sec == TRACE_SEC_SOURCE) { 1081 sec = TRACE_SEC_GLOB; 1082 } else if (strcmp(line, "[blob]") == 0 && sec == TRACE_SEC_GLOB) { 1083 sec = TRACE_SEC_BLOB; 1084 } else if (strcmp(line, "[child]") == 0 && 1085 (sec == TRACE_SEC_GLOB || sec == TRACE_SEC_BLOB)) { 1086 sec = TRACE_SEC_CHILD; 1087 } else { 1088 return set_err(err, errcap, "bad deepset section"); 1089 } 1090 continue; 1091 } 1092 if (split_line(line, fields, sizeof fields / sizeof fields[0], &n) != 1093 BUILD_OK) 1094 return set_err(err, errcap, "bad deepset row"); 1095 if (sec == TRACE_SEC_TOP) { 1096 if (!(seen & F_TARGET)) { 1097 if (parse_top_text(fields, n, "target", out->target, sizeof out->target, 1098 &seen, F_TARGET, err, errcap) != BUILD_OK) 1099 return BUILD_ERR; 1100 } else if (!(seen & F_RECIPE)) { 1101 if (parse_top_hash(fields, n, "recipe", out->recipe, &seen, F_RECIPE, 1102 err, errcap) != BUILD_OK) 1103 return BUILD_ERR; 1104 } else { 1105 return set_err(err, errcap, "unexpected deepset field"); 1106 } 1107 } else if (sec == TRACE_SEC_CONFIG) { 1108 if (append_deepset_config(out, fields, n, err, errcap) != BUILD_OK) 1109 return BUILD_ERR; 1110 } else if (sec == TRACE_SEC_SOURCE) { 1111 if (append_deepset_source(out, fields, n, err, errcap) != BUILD_OK) 1112 return BUILD_ERR; 1113 } else if (sec == TRACE_SEC_GLOB) { 1114 if (append_deepset_glob(out, fields, n, err, errcap) != BUILD_OK) 1115 return BUILD_ERR; 1116 } else if (sec == TRACE_SEC_BLOB) { 1117 if (append_deepset_blob(out, fields, n, err, errcap) != BUILD_OK) 1118 return BUILD_ERR; 1119 } else if (sec == TRACE_SEC_CHILD) { 1120 if (append_child(out, fields, n, err, errcap) != BUILD_OK) 1121 return BUILD_ERR; 1122 } else { 1123 return set_err(err, errcap, "bad deepset row"); 1124 } 1125 } 1126 if (p.first) return set_err(err, errcap, "bad deepset magic/version"); 1127 if (sec != TRACE_SEC_CHILD) 1128 return set_err(err, errcap, "missing deepset section"); 1129 return BUILD_OK; 1130 } 1131 1132 int build_record_parse(const uint8_t* data, size_t len, BuildTargetRecord* out, 1133 char* err, size_t errcap) { 1134 TraceParser p; 1135 uint32_t seen = 0; 1136 if (!data || !out) return set_err(err, errcap, "missing target record"); 1137 if (out->cap_rows && !out->rows) 1138 return set_err(err, errcap, "missing record storage"); 1139 memset(out->target, 0, sizeof out->target); 1140 out->n_rows = 0; 1141 memset(&p, 0, sizeof p); 1142 p.data = data; 1143 p.len = len; 1144 p.first = 1; 1145 for (;;) { 1146 char* line; 1147 char* fields[2]; 1148 size_t n = 0; 1149 int r = parser_next(&p, &line, err, errcap); 1150 if (r < 0) return BUILD_ERR; 1151 if (r == 0) break; 1152 if (p.first) { 1153 p.first = 0; 1154 if (strcmp(line, BUILD_RECORD_MAGIC) != 0) 1155 return set_err(err, errcap, "bad record magic/version"); 1156 continue; 1157 } 1158 if (line[0] == '[') return set_err(err, errcap, "bad record section"); 1159 if (split_line(line, fields, sizeof fields / sizeof fields[0], &n) != 1160 BUILD_OK) 1161 return set_err(err, errcap, "bad record row"); 1162 if (!(seen & F_TARGET)) { 1163 if (parse_top_text(fields, n, "target", out->target, sizeof out->target, 1164 &seen, F_TARGET, err, errcap) != BUILD_OK) 1165 return BUILD_ERR; 1166 } else { 1167 if (append_record_row(out, fields, n, err, errcap) != BUILD_OK) 1168 return BUILD_ERR; 1169 } 1170 } 1171 if (p.first) return set_err(err, errcap, "bad record magic/version"); 1172 if (seen != F_TARGET) return set_err(err, errcap, "missing record target"); 1173 return BUILD_OK; 1174 } 1175 1176 void build_trace_id(const uint8_t* body, size_t len, 1177 uint8_t out[BUILD_HASH_LEN]) { 1178 KitBlobInfo bi; 1179 kit_blob_info(&bi, body, len); 1180 memcpy(out, bi.id, BUILD_HASH_LEN); 1181 } 1182 1183 void build_deepset_id(const uint8_t* body, size_t len, 1184 uint8_t out[BUILD_HASH_LEN]) { 1185 build_trace_id(body, len, out); 1186 } 1187 1188 int build_record_prepend(BuildTargetRecord* rec, const BuildRecordRow* row) { 1189 size_t read, write, count, i; 1190 if (!rec || !row) return BUILD_ERR; 1191 if (!check_record_kind(row->kind)) return BUILD_ERR; 1192 if (rec->cap_rows && !rec->rows) return BUILD_ERR; 1193 if (rec->n_rows > rec->cap_rows) return BUILD_ERR; 1194 write = 0; 1195 for (read = 0; read < rec->n_rows; ++read) { 1196 if (rec->rows[read].kind == row->kind && 1197 build_id_eq(rec->rows[read].trace_id, row->trace_id)) 1198 continue; 1199 if (write != read) rec->rows[write] = rec->rows[read]; 1200 ++write; 1201 } 1202 rec->n_rows = write; 1203 if (rec->n_rows >= rec->cap_rows) { 1204 size_t last_same = rec->n_rows; 1205 count = 0; 1206 for (i = 0; i < rec->n_rows; ++i) { 1207 if (rec->rows[i].kind == row->kind) { 1208 ++count; 1209 last_same = i; 1210 } 1211 } 1212 if (count < KIT_BUILD_RECORD_CAP || last_same == rec->n_rows) 1213 return BUILD_ERR; 1214 for (i = last_same + 1u; i < rec->n_rows; ++i) 1215 rec->rows[i - 1u] = rec->rows[i]; 1216 --rec->n_rows; 1217 } 1218 for (i = rec->n_rows; i > 0; --i) rec->rows[i] = rec->rows[i - 1u]; 1219 rec->rows[0] = *row; 1220 ++rec->n_rows; 1221 1222 count = 0; 1223 write = 0; 1224 for (read = 0; read < rec->n_rows; ++read) { 1225 if (rec->rows[read].kind == row->kind) { 1226 ++count; 1227 if (count > KIT_BUILD_RECORD_CAP) continue; 1228 } 1229 if (write != read) rec->rows[write] = rec->rows[read]; 1230 ++write; 1231 } 1232 rec->n_rows = write; 1233 return BUILD_OK; 1234 }