Returns bytes transferred, or 0 on error */
| 311 | |
| 312 | /* Returns bytes transferred, or 0 on error */ |
| 313 | static size_t transfer_store_msg(int from_fd, size_t from_off, |
| 314 | int to_fd, size_t to_off, |
| 315 | int *type) |
| 316 | { |
| 317 | struct gossip_hdr hdr; |
| 318 | u32 msglen; |
| 319 | u8 *msg; |
| 320 | const u8 *p; |
| 321 | size_t tmplen; |
| 322 | |
| 323 | *type = -1; |
| 324 | if (pread(from_fd, &hdr, sizeof(hdr), from_off) != sizeof(hdr)) { |
| 325 | status_broken("Failed reading header from to gossip store @%zu" |
| 326 | ": %s", |
| 327 | from_off, strerror(errno)); |
| 328 | return 0; |
| 329 | } |
| 330 | |
| 331 | msglen = be32_to_cpu(hdr.len); |
| 332 | if (msglen & GOSSIP_STORE_LEN_DELETED_BIT) { |
| 333 | status_broken("Can't transfer deleted msg from gossip store @%zu", |
| 334 | from_off); |
| 335 | return 0; |
| 336 | } |
| 337 | |
| 338 | /* Ignore any non-length bits (e.g. push) */ |
| 339 | msglen &= GOSSIP_STORE_LEN_MASK; |
| 340 | |
| 341 | /* FIXME: Reuse buffer? */ |
| 342 | msg = tal_arr(tmpctx, u8, sizeof(hdr) + msglen); |
| 343 | memcpy(msg, &hdr, sizeof(hdr)); |
| 344 | if (pread(from_fd, msg + sizeof(hdr), msglen, from_off + sizeof(hdr)) |
| 345 | != msglen) { |
| 346 | status_broken("Failed reading %u from to gossip store @%zu" |
| 347 | ": %s", |
| 348 | msglen, from_off, strerror(errno)); |
| 349 | return 0; |
| 350 | } |
| 351 | |
| 352 | if (pwrite(to_fd, msg, msglen + sizeof(hdr), to_off) |
| 353 | != msglen + sizeof(hdr)) { |
| 354 | status_broken("Failed writing to gossip store: %s", |
| 355 | strerror(errno)); |
| 356 | return 0; |
| 357 | } |
| 358 | |
| 359 | /* Can't use peektype here, since we have header on front */ |
| 360 | p = msg + sizeof(hdr); |
| 361 | tmplen = msglen; |
| 362 | *type = fromwire_u16(&p, &tmplen); |
| 363 | if (!p) |
| 364 | *type = -1; |
| 365 | tal_free(msg); |
| 366 | return sizeof(hdr) + msglen; |
| 367 | } |
| 368 | |
| 369 | /* We keep a htable map of old gossip_store offsets to new ones. */ |
| 370 | struct offset_map { |
no test coverage detected