| 338 | } |
| 339 | |
| 340 | static size_t append_to_file(struct lightningd *ld, |
| 341 | const char *fname, |
| 342 | const char *str, |
| 343 | bool must_exist) |
| 344 | { |
| 345 | int fd; |
| 346 | const char *buffer; |
| 347 | |
| 348 | fd = open(fname, O_RDWR|O_APPEND); |
| 349 | if (fd < 0) { |
| 350 | if (errno != ENOENT || must_exist) |
| 351 | fatal("Could not write to config %s: %s", |
| 352 | fname, strerror(errno)); |
| 353 | fd = open(fname, O_RDWR|O_APPEND|O_CREAT, 0644); |
| 354 | if (fd < 0) |
| 355 | fatal("Could not create config file %s: %s", |
| 356 | fname, strerror(errno)); |
| 357 | } |
| 358 | |
| 359 | /* Note: always nul terminates */ |
| 360 | buffer = grab_fd_str(tmpctx, fd); |
| 361 | if (!buffer) |
| 362 | fatal("Error reading %s: %s", fname, strerror(errno)); |
| 363 | |
| 364 | /* If there's a last character and it's not \n, add one */ |
| 365 | if (tal_bytelen(buffer) > 1 |
| 366 | && buffer[tal_bytelen(buffer)-2] != '\n') |
| 367 | str = tal_strcat(tmpctx, "\n", str); |
| 368 | |
| 369 | /* Always append a \n ourselves */ |
| 370 | str = tal_strcat(tmpctx, str, "\n"); |
| 371 | if (write(fd, str, strlen(str)) != strlen(str)) |
| 372 | fatal("Could not write to config file %s: %s", |
| 373 | fname, strerror(errno)); |
| 374 | if (fsync(fd) != 0) |
| 375 | fatal("Syncing %s: %s", fname, strerror(errno)); |
| 376 | close(fd); |
| 377 | |
| 378 | /* 1-based counter of where new stuff appeared */ |
| 379 | return strcount(buffer, "\n") + 1; |
| 380 | } |
| 381 | |
| 382 | static const char *grab_and_check(const tal_t *ctx, |
| 383 | const char *fname, |
no test coverage detected