| 403 | } |
| 404 | |
| 405 | static void update_scb(struct plugin *p, struct modern_scb_chan **channels) |
| 406 | { |
| 407 | |
| 408 | /* If the temp file existed before, remove it */ |
| 409 | unlink_noerr("scb.tmp"); |
| 410 | |
| 411 | int fd = open("scb.tmp", O_CREAT|O_EXCL|O_WRONLY, 0400); |
| 412 | if (fd<0) |
| 413 | plugin_err(p, "Opening: %s", strerror(errno)); |
| 414 | |
| 415 | plugin_log(p, LOG_DBG, "Updating the SCB file..."); |
| 416 | |
| 417 | write_scb(p, fd, channels); |
| 418 | |
| 419 | /* fsync (mostly!) ensures that the file has reached the disk. */ |
| 420 | if (fsync(fd) != 0) { |
| 421 | unlink_noerr("scb.tmp"); |
| 422 | } |
| 423 | |
| 424 | /* This should never fail if fsync succeeded. But paranoia good, and |
| 425 | * bugs exist. */ |
| 426 | if (close(fd) != 0) { |
| 427 | unlink_noerr("scb.tmp"); |
| 428 | } |
| 429 | /* We actually need to sync the *directory itself* to make sure the |
| 430 | * file exists! You're only allowed to open directories read-only in |
| 431 | * modern Unix though. */ |
| 432 | fd = open(".", O_RDONLY); |
| 433 | if (fd < 0) { |
| 434 | plugin_log(p, LOG_DBG, "Opening: %s", strerror(errno)); |
| 435 | } |
| 436 | if (fsync(fd) != 0) { |
| 437 | unlink_noerr("scb.tmp"); |
| 438 | } |
| 439 | close(fd); |
| 440 | |
| 441 | /* This will atomically replace the main file */ |
| 442 | rename("scb.tmp", FILENAME); |
| 443 | } |
| 444 | |
| 445 | |
| 446 | static struct command_result |
no test coverage detected