| 818 | } |
| 819 | |
| 820 | static bool delete_cached_project_db(const char *project_name) { |
| 821 | if (!cbm_validate_project_name(project_name)) { |
| 822 | return false; |
| 823 | } |
| 824 | |
| 825 | const char *cache_dir = cbm_resolve_cache_dir(); |
| 826 | if (!cache_dir) { |
| 827 | return false; |
| 828 | } |
| 829 | |
| 830 | size_t cache_length = strlen(cache_dir); |
| 831 | size_t project_length = strlen(project_name); |
| 832 | if (cache_length > SIZE_MAX - project_length - sizeof("/.db")) { |
| 833 | return false; |
| 834 | } |
| 835 | size_t path_capacity = cache_length + project_length + sizeof("/.db"); |
| 836 | char *path = malloc(path_capacity); |
| 837 | char *sidecar = malloc(path_capacity + sizeof("-wal")); |
| 838 | if (!path || !sidecar) { |
| 839 | free(path); |
| 840 | free(sidecar); |
| 841 | return false; |
| 842 | } |
| 843 | int written = snprintf(path, path_capacity, "%s/%s.db", cache_dir, project_name); |
| 844 | bool formatted = written > 0 && (size_t)written < path_capacity; |
| 845 | bool removed = formatted && watcher_unlink_cached_file(project_name, path, "database"); |
| 846 | /* If the main DB could not be removed, preserve WAL/SHM: together they |
| 847 | * may be the only recoverable committed generation. */ |
| 848 | if (removed) { |
| 849 | written = snprintf(sidecar, path_capacity + sizeof("-wal"), "%s-wal", path); |
| 850 | removed = written > 0 && (size_t)written < path_capacity + sizeof("-wal") && |
| 851 | watcher_unlink_cached_file(project_name, sidecar, "wal"); |
| 852 | } |
| 853 | if (removed) { |
| 854 | written = snprintf(sidecar, path_capacity + sizeof("-wal"), "%s-shm", path); |
| 855 | removed = written > 0 && (size_t)written < path_capacity + sizeof("-wal") && |
| 856 | watcher_unlink_cached_file(project_name, sidecar, "shm"); |
| 857 | } |
| 858 | free(path); |
| 859 | free(sidecar); |
| 860 | return removed; |
| 861 | } |
| 862 | |
| 863 | /* Hash table foreach callback to free state entries */ |
| 864 | static void free_state_entry(const char *key, void *val, void *ud) { |
no test coverage detected