Coverage Report

Created: 2026-01-13 06:59

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/clib/src/common/clib-cache.c
Line
Count
Source
1
//
2
// clib-cache.c
3
//
4
// Copyright (c) 2016-2020 clib authors
5
// MIT licensed
6
//
7
8
#include "clib-cache.h"
9
#include "copy/copy.h"
10
#include "fs/fs.h"
11
#include "rimraf/rimraf.h"
12
#include <limits.h>
13
#include <mkdirp/mkdirp.h>
14
#include <stdio.h>
15
#include <stdlib.h>
16
#include <unistd.h>
17
18
#define GET_PKG_CACHE(a, n, v)                                                 \
19
0
  char pkg_cache[BUFSIZ];                                                      \
20
0
  package_cache_path(pkg_cache, a, n, v);
21
22
#define GET_JSON_CACHE(a, n, v)                                                \
23
0
  char json_cache[BUFSIZ];                                                     \
24
0
  json_cache_path(json_cache, a, n, v);
25
26
#ifdef _WIN32
27
#define BASE_DIR getenv("AppData")
28
#else
29
0
#define BASE_DIR getenv("HOME")
30
#endif
31
32
0
#define BASE_CACHE_PATTERN "%s/.cache/clib"
33
0
#define PKG_CACHE_PATTERN "%s/%s_%s_%s"
34
0
#define JSON_CACHE_PATTERN "%s/%s_%s_%s.json"
35
36
/** Portable PATH_MAX ? */
37
static char package_cache_dir[BUFSIZ];
38
static char search_cache[BUFSIZ];
39
static char json_cache_dir[BUFSIZ];
40
static char meta_cache_dir[BUFSIZ];
41
static time_t expiration;
42
43
static void json_cache_path(char *pkg_cache, char *author, char *name,
44
0
                            char *version) {
45
0
  sprintf(pkg_cache, JSON_CACHE_PATTERN, json_cache_dir, author, name, version);
46
0
}
47
48
static void package_cache_path(char *json_cache, char *author, char *name,
49
0
                               char *version) {
50
0
  sprintf(json_cache, PKG_CACHE_PATTERN, package_cache_dir, author, name,
51
0
          version);
52
0
}
53
54
0
const char *clib_cache_dir(void) { return package_cache_dir; }
55
56
0
static int check_dir(char *dir) {
57
0
  if (0 != (fs_exists(dir))) {
58
0
    return mkdirp(dir, 0700);
59
0
  }
60
0
  return 0;
61
0
}
62
63
0
int clib_cache_meta_init(void) {
64
0
  sprintf(meta_cache_dir, BASE_CACHE_PATTERN "/meta", BASE_DIR);
65
66
0
  if (0 != check_dir(meta_cache_dir)) {
67
0
    return -1;
68
0
  }
69
70
0
  return 0;
71
0
}
72
73
0
const char *clib_cache_meta_dir(void) { return meta_cache_dir; }
74
75
0
int clib_cache_init(time_t exp) {
76
0
  expiration = exp;
77
78
0
  sprintf(package_cache_dir, BASE_CACHE_PATTERN "/packages", BASE_DIR);
79
0
  sprintf(json_cache_dir, BASE_CACHE_PATTERN "/json", BASE_DIR);
80
0
  sprintf(search_cache, BASE_CACHE_PATTERN "/search.html", BASE_DIR);
81
82
0
  if (0 != check_dir(package_cache_dir)) {
83
0
    return -1;
84
0
  }
85
0
  if (0 != check_dir(json_cache_dir)) {
86
0
    return -1;
87
0
  }
88
89
0
  return 0;
90
0
}
91
92
0
static int is_expired(char *cache) {
93
0
  fs_stats *stat = fs_stat(cache);
94
95
0
  if (!stat) {
96
0
    return -1;
97
0
  }
98
99
0
  time_t modified = stat->st_mtime;
100
0
  time_t now = time(NULL);
101
0
  free(stat);
102
103
0
  return now - modified >= expiration;
104
0
}
105
106
0
int clib_cache_has_json(char *author, char *name, char *version) {
107
0
  GET_JSON_CACHE(author, name, version);
108
109
0
  return 0 == fs_exists(json_cache) && !is_expired(json_cache);
110
0
}
111
112
0
char *clib_cache_read_json(char *author, char *name, char *version) {
113
0
  GET_JSON_CACHE(author, name, version);
114
115
0
  if (is_expired(json_cache)) {
116
0
    return NULL;
117
0
  }
118
119
0
  return fs_read(json_cache);
120
0
}
121
122
int clib_cache_save_json(char *author, char *name, char *version,
123
0
                         char *content) {
124
0
  GET_JSON_CACHE(author, name, version);
125
126
0
  return fs_write(json_cache, content);
127
0
}
128
129
0
int clib_cache_delete_json(char *author, char *name, char *version) {
130
0
  GET_JSON_CACHE(author, name, version);
131
132
0
  return unlink(json_cache);
133
0
}
134
135
0
int clib_cache_has_search(void) {
136
0
  return 0 == fs_exists(search_cache) && !is_expired(search_cache);
137
0
}
138
139
0
char *clib_cache_read_search(void) {
140
0
  if (!clib_cache_has_search()) {
141
0
    return NULL;
142
0
  }
143
0
  return fs_read(search_cache);
144
0
}
145
146
0
int clib_cache_save_search(char *content) {
147
0
  return fs_write(search_cache, content);
148
0
}
149
150
0
int clib_cache_delete_search(void) { return unlink(search_cache); }
151
152
0
int clib_cache_has_package(char *author, char *name, char *version) {
153
0
  GET_PKG_CACHE(author, name, version);
154
155
0
  return 0 == fs_exists(pkg_cache) && !is_expired(pkg_cache);
156
0
}
157
158
0
int clib_cache_is_expired_package(char *author, char *name, char *version) {
159
0
  GET_PKG_CACHE(author, name, version);
160
161
0
  return is_expired(pkg_cache);
162
0
}
163
164
int clib_cache_save_package(char *author, char *name, char *version,
165
0
                            char *pkg_dir) {
166
0
  GET_PKG_CACHE(author, name, version);
167
168
0
  if (0 == fs_exists(pkg_cache)) {
169
0
    rimraf(pkg_cache);
170
0
  }
171
172
0
  return copy_dir(pkg_dir, pkg_cache);
173
0
}
174
175
int clib_cache_load_package(char *author, char *name, char *version,
176
0
                            char *target_dir) {
177
0
  GET_PKG_CACHE(author, name, version);
178
179
0
  if (-1 == fs_exists(pkg_cache)) {
180
0
    return -1;
181
0
  }
182
183
0
  if (is_expired(pkg_cache)) {
184
0
    rimraf(pkg_cache);
185
186
0
    return -2;
187
0
  }
188
189
0
  return copy_dir(pkg_cache, target_dir);
190
0
}
191
192
0
int clib_cache_delete_package(char *author, char *name, char *version) {
193
0
  GET_PKG_CACHE(author, name, version);
194
195
0
  return rimraf(pkg_cache);
196
0
}