diff options
| author | frosty <gabriel@bwaaa.monster> | 2026-03-10 07:18:53 -0400 |
|---|---|---|
| committer | frosty <gabriel@bwaaa.monster> | 2026-03-10 07:18:53 -0400 |
| commit | ab7244b0f7c7dd5d268a9b5520d28770988f22e7 (patch) | |
| tree | 4c5cdda98d1bb35e89decf15c67079b745eb586b /src/Cache | |
| parent | e33310f26351e25fda718a353f8b8e9ece0007b5 (diff) | |
| download | omnisearch-indev.tar.gz | |
fix: didn't add cache folder in last commitindev
Diffstat (limited to 'src/Cache')
| -rw-r--r-- | src/Cache/Cache.c | 205 | ||||
| -rw-r--r-- | src/Cache/Cache.h | 23 |
2 files changed, 228 insertions, 0 deletions
diff --git a/src/Cache/Cache.c b/src/Cache/Cache.c new file mode 100644 index 0000000..59d0ed4 --- /dev/null +++ b/src/Cache/Cache.c @@ -0,0 +1,205 @@ +#include "Cache.h" +#include <dirent.h> +#include <openssl/evp.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <sys/stat.h> +#include <time.h> + +static char cache_dir[512] = {0}; +static int cache_ttl_search_val = 3600; +static int cache_ttl_infobox_val = 86400; + +void set_cache_ttl_search(int ttl) { cache_ttl_search_val = ttl; } + +void set_cache_ttl_infobox(int ttl) { cache_ttl_infobox_val = ttl; } + +int get_cache_ttl_search(void) { return cache_ttl_search_val; } + +int get_cache_ttl_infobox(void) { return cache_ttl_infobox_val; } + +static void md5_hash(const char *str, char *output) { + unsigned char hash[EVP_MAX_MD_SIZE]; + unsigned int hash_len; + EVP_MD_CTX *ctx = EVP_MD_CTX_new(); + if (!ctx) + return; + EVP_DigestInit_ex(ctx, EVP_md5(), NULL); + EVP_DigestUpdate(ctx, str, strlen(str)); + EVP_DigestFinal_ex(ctx, hash, &hash_len); + EVP_MD_CTX_free(ctx); + for (unsigned int i = 0; i < hash_len; i++) { + sprintf(output + (i * 2), "%02x", hash[i]); + } +} + +static time_t get_file_mtime(const char *filepath) { + struct stat st; + if (stat(filepath, &st) == 0) { + return st.st_mtime; + } + return 0; +} + +int cache_init(const char *dir) { + if (!dir || strlen(dir) == 0) { + strcpy(cache_dir, "/tmp/omnisearch_cache"); + } else { + strncpy(cache_dir, dir, sizeof(cache_dir) - 1); + cache_dir[sizeof(cache_dir) - 1] = '\0'; + } + + struct stat st; + if (stat(cache_dir, &st) != 0) { + if (mkdir(cache_dir, 0755) != 0) { + fprintf(stderr, "Failed to create cache directory: %s\n", cache_dir); + return -1; + } + } else if (!S_ISDIR(st.st_mode)) { + fprintf(stderr, "Cache path exists but is not a directory: %s\n", + cache_dir); + return -1; + } + + char subdirs[] = "0123456789abcdef"; + for (int i = 0; subdirs[i]; i++) { + char subdir_path[1024]; + snprintf(subdir_path, sizeof(subdir_path), "%s/%c", cache_dir, subdirs[i]); + if (stat(subdir_path, &st) != 0) { + mkdir(subdir_path, 0755); + } + } + + return 0; +} + +void cache_shutdown(void) { cache_dir[0] = '\0'; } + +char *cache_compute_key(const char *query, int page, const char *engine_name) { + char key_buffer[1024]; + snprintf(key_buffer, sizeof(key_buffer), "%s_%d_%s", query ? query : "", page, + engine_name ? engine_name : ""); + + char *hash = malloc(33); + if (!hash) { + return NULL; + } + md5_hash(key_buffer, hash); + return hash; +} + +int cache_get(const char *key, time_t max_age, char **out_data, + size_t *out_size) { + if (!key || !out_data || !out_size || cache_dir[0] == '\0') { + return -1; + } + + char filepath[1024]; + snprintf(filepath, sizeof(filepath), "%s/%c/%s.cache", cache_dir, key[0], + key); + + time_t file_mtime = get_file_mtime(filepath); + if (file_mtime == 0) { + return -1; + } + + time_t now = time(NULL); + if (max_age > 0 && (now - file_mtime) > max_age) { + remove(filepath); + return -1; + } + + FILE *fp = fopen(filepath, "rb"); + if (!fp) { + return -1; + } + + fseek(fp, 0, SEEK_END); + long size = ftell(fp); + fseek(fp, 0, SEEK_SET); + + if (size <= 0) { + fclose(fp); + return -1; + } + + char *data = malloc(size + 1); + if (!data) { + fclose(fp); + return -1; + } + + size_t read_size = fread(data, 1, size, fp); + fclose(fp); + + if (read_size != (size_t)size) { + free(data); + return -1; + } + + data[size] = '\0'; + *out_data = data; + *out_size = size; + return 0; +} + +int cache_set(const char *key, const char *data, size_t size) { + if (!key || !data || size == 0 || cache_dir[0] == '\0') { + return -1; + } + + char filepath[1024]; + snprintf(filepath, sizeof(filepath), "%s/%c/%s.cache", cache_dir, key[0], + key); + + FILE *fp = fopen(filepath, "wb"); + if (!fp) { + return -1; + } + + size_t written = fwrite(data, 1, size, fp); + fclose(fp); + + if (written != size) { + remove(filepath); + return -1; + } + + return 0; +} + +void cache_cleanup(time_t max_age) { + if (cache_dir[0] == '\0' || max_age <= 0) { + return; + } + + time_t now = time(NULL); + time_t cutoff = now - max_age; + char subdirs[] = "0123456789abcdef"; + + for (int d = 0; subdirs[d]; d++) { + char subdir_path[1024]; + snprintf(subdir_path, sizeof(subdir_path), "%s/%c", cache_dir, subdirs[d]); + + DIR *dir = opendir(subdir_path); + if (!dir) + continue; + + struct dirent *entry; + while ((entry = readdir(dir)) != NULL) { + size_t len = strlen(entry->d_name); + if (len > 7 && strcmp(entry->d_name + len - 7, ".cache") == 0) { + char filepath[2048]; + snprintf(filepath, sizeof(filepath), "%s/%s", subdir_path, + entry->d_name); + + struct stat st; + if (stat(filepath, &st) == 0 && st.st_mtime < cutoff) { + remove(filepath); + } + } + } + closedir(dir); + } +} diff --git a/src/Cache/Cache.h b/src/Cache/Cache.h new file mode 100644 index 0000000..0a84406 --- /dev/null +++ b/src/Cache/Cache.h @@ -0,0 +1,23 @@ +#ifndef CACHE_H +#define CACHE_H + +#include <stddef.h> +#include <time.h> + +int cache_init(const char *cache_dir); +void cache_shutdown(void); + +int cache_get(const char *key, time_t max_age, char **out_data, + size_t *out_size); +int cache_set(const char *key, const char *data, size_t size); + +void cache_cleanup(time_t max_age); + +char *cache_compute_key(const char *query, int page, const char *engine_name); + +void set_cache_ttl_search(int ttl); +void set_cache_ttl_infobox(int ttl); +int get_cache_ttl_search(void); +int get_cache_ttl_infobox(void); + +#endif |
