| 1770 | } |
| 1771 | |
| 1772 | static int publish_writer_output(write_db_ctx_t *w) { |
| 1773 | if (sync_writer_output(w->fp) != 0) { |
| 1774 | return discard_writer_output(w, ERR_WRITE_FAILED); |
| 1775 | } |
| 1776 | if (fclose(w->fp) != 0) { |
| 1777 | w->fp = NULL; |
| 1778 | if (w->temp_path[0]) { |
| 1779 | (void)cbm_unlink(w->temp_path); |
| 1780 | } |
| 1781 | return ERR_WRITE_FAILED; |
| 1782 | } |
| 1783 | w->fp = NULL; |
| 1784 | if (!w->temp_path[0] || !w->final_path[0]) { |
| 1785 | return 0; |
| 1786 | } |
| 1787 | if (cbm_rename_replace(w->temp_path, w->final_path) != 0) { |
| 1788 | (void)cbm_unlink(w->temp_path); |
| 1789 | return ERR_WRITE_FAILED; |
| 1790 | } |
| 1791 | /* Sidecars are removed only after the replacement succeeds. On POSIX, |
| 1792 | * readers of the old generation retain their unlinked handles. On |
| 1793 | * Windows, an incompatible open handle makes MoveFileExW fail before |
| 1794 | * this cleanup, preserving the old DB and its sidecars. */ |
| 1795 | cbm_remove_db_sidecars(w->final_path); |
| 1796 | return 0; |
| 1797 | } |
| 1798 | |
| 1799 | /* Callback type for building a record from an item at index i. */ |
| 1800 | typedef uint8_t *(*build_record_fn)(const void *items, int i, int *out_len); |
no test coverage detected