1 /*
2 * Copyright (C) the libgit2 contributors. All rights reserved.
3 *
4 * This file is part of libgit2, distributed under the GNU GPL v2 with
5 * a Linking Exception. For full terms see the included COPYING file.
6 */
7
8 #include "libgit2.h"
9
10 #include <git2.h>
11 #include "alloc.h"
12 #include "cache.h"
13 #include "common.h"
14 #include "filter.h"
15 #include "hash.h"
16 #include "index.h"
17 #include "merge_driver.h"
18 #include "pool.h"
19 #include "mwindow.h"
20 #include "object.h"
21 #include "odb.h"
22 #include "refs.h"
23 #include "runtime.h"
24 #include "sysdir.h"
25 #include "thread.h"
26 #include "threadstate.h"
27 #include "git2/global.h"
28 #include "streams/registry.h"
29 #include "streams/mbedtls.h"
30 #include "streams/openssl.h"
31 #include "transports/smart.h"
32 #include "transports/http.h"
33 #include "transports/ssh.h"
34
35 #ifdef GIT_WIN32
36 # include "win32/w32_leakcheck.h"
37 #endif
38
39 #ifdef GIT_OPENSSL
40 # include <openssl/err.h>
41 #endif
42
43 #ifdef GIT_MBEDTLS
44 # include <mbedtls/error.h>
45 #endif
46
47 /* Declarations for tuneable settings */
48 extern size_t git_mwindow__window_size;
49 extern size_t git_mwindow__mapped_limit;
50 extern size_t git_mwindow__file_limit;
51 extern size_t git_indexer__max_objects;
52 extern bool git_disable_pack_keep_file_checks;
53
54 char *git__user_agent;
55 char *git__ssl_ciphers;
56
libgit2_settings_global_shutdown(void)57 static void libgit2_settings_global_shutdown(void)
58 {
59 git__free(git__user_agent);
60 git__free(git__ssl_ciphers);
61 }
62
git_libgit2_settings_global_init(void)63 static int git_libgit2_settings_global_init(void)
64 {
65 return git_runtime_shutdown_register(libgit2_settings_global_shutdown);
66 }
67
git_libgit2_init(void)68 int git_libgit2_init(void)
69 {
70 static git_runtime_init_fn init_fns[] = {
71 #ifdef GIT_WIN32
72 git_win32_leakcheck_global_init,
73 #endif
74 git_allocator_global_init,
75 git_threadstate_global_init,
76 git_threads_global_init,
77 git_hash_global_init,
78 git_sysdir_global_init,
79 git_filter_global_init,
80 git_merge_driver_global_init,
81 git_transport_ssh_global_init,
82 git_stream_registry_global_init,
83 git_openssl_stream_global_init,
84 git_mbedtls_stream_global_init,
85 git_mwindow_global_init,
86 git_pool_global_init,
87 git_libgit2_settings_global_init
88 };
89
90 return git_runtime_init(init_fns, ARRAY_SIZE(init_fns));
91 }
92
git_libgit2_init_count(void)93 int git_libgit2_init_count(void)
94 {
95 return git_runtime_init_count();
96 }
97
git_libgit2_shutdown(void)98 int git_libgit2_shutdown(void)
99 {
100 return git_runtime_shutdown();
101 }
102
git_libgit2_version(int * major,int * minor,int * rev)103 int git_libgit2_version(int *major, int *minor, int *rev)
104 {
105 *major = LIBGIT2_VER_MAJOR;
106 *minor = LIBGIT2_VER_MINOR;
107 *rev = LIBGIT2_VER_REVISION;
108
109 return 0;
110 }
111
git_libgit2_features(void)112 int git_libgit2_features(void)
113 {
114 return 0
115 #ifdef GIT_THREADS
116 | GIT_FEATURE_THREADS
117 #endif
118 #ifdef GIT_HTTPS
119 | GIT_FEATURE_HTTPS
120 #endif
121 #if defined(GIT_SSH)
122 | GIT_FEATURE_SSH
123 #endif
124 #if defined(GIT_USE_NSEC)
125 | GIT_FEATURE_NSEC
126 #endif
127 ;
128 }
129
config_level_to_sysdir(int * out,int config_level)130 static int config_level_to_sysdir(int *out, int config_level)
131 {
132 switch (config_level) {
133 case GIT_CONFIG_LEVEL_SYSTEM:
134 *out = GIT_SYSDIR_SYSTEM;
135 return 0;
136 case GIT_CONFIG_LEVEL_XDG:
137 *out = GIT_SYSDIR_XDG;
138 return 0;
139 case GIT_CONFIG_LEVEL_GLOBAL:
140 *out = GIT_SYSDIR_GLOBAL;
141 return 0;
142 case GIT_CONFIG_LEVEL_PROGRAMDATA:
143 *out = GIT_SYSDIR_PROGRAMDATA;
144 return 0;
145 default:
146 break;
147 }
148
149 git_error_set(
150 GIT_ERROR_INVALID, "invalid config path selector %d", config_level);
151 return -1;
152 }
153
git_libgit2__user_agent(void)154 const char *git_libgit2__user_agent(void)
155 {
156 return git__user_agent;
157 }
158
git_libgit2__ssl_ciphers(void)159 const char *git_libgit2__ssl_ciphers(void)
160 {
161 return git__ssl_ciphers;
162 }
163
git_libgit2_opts(int key,...)164 int git_libgit2_opts(int key, ...)
165 {
166 int error = 0;
167 va_list ap;
168
169 va_start(ap, key);
170
171 switch (key) {
172 case GIT_OPT_SET_MWINDOW_SIZE:
173 git_mwindow__window_size = va_arg(ap, size_t);
174 break;
175
176 case GIT_OPT_GET_MWINDOW_SIZE:
177 *(va_arg(ap, size_t *)) = git_mwindow__window_size;
178 break;
179
180 case GIT_OPT_SET_MWINDOW_MAPPED_LIMIT:
181 git_mwindow__mapped_limit = va_arg(ap, size_t);
182 break;
183
184 case GIT_OPT_GET_MWINDOW_MAPPED_LIMIT:
185 *(va_arg(ap, size_t *)) = git_mwindow__mapped_limit;
186 break;
187
188 case GIT_OPT_SET_MWINDOW_FILE_LIMIT:
189 git_mwindow__file_limit = va_arg(ap, size_t);
190 break;
191
192 case GIT_OPT_GET_MWINDOW_FILE_LIMIT:
193 *(va_arg(ap, size_t *)) = git_mwindow__file_limit;
194 break;
195
196 case GIT_OPT_GET_SEARCH_PATH:
197 {
198 int sysdir = va_arg(ap, int);
199 git_buf *out = va_arg(ap, git_buf *);
200 const git_buf *tmp;
201 int level;
202
203 if ((error = config_level_to_sysdir(&level, sysdir)) < 0 ||
204 (error = git_buf_sanitize(out)) < 0 ||
205 (error = git_sysdir_get(&tmp, level)) < 0)
206 break;
207
208 error = git_buf_sets(out, tmp->ptr);
209 }
210 break;
211
212 case GIT_OPT_SET_SEARCH_PATH:
213 {
214 int level;
215
216 if ((error = config_level_to_sysdir(&level, va_arg(ap, int))) >= 0)
217 error = git_sysdir_set(level, va_arg(ap, const char *));
218 }
219 break;
220
221 case GIT_OPT_SET_CACHE_OBJECT_LIMIT:
222 {
223 git_object_t type = (git_object_t)va_arg(ap, int);
224 size_t size = va_arg(ap, size_t);
225 error = git_cache_set_max_object_size(type, size);
226 break;
227 }
228
229 case GIT_OPT_SET_CACHE_MAX_SIZE:
230 git_cache__max_storage = va_arg(ap, ssize_t);
231 break;
232
233 case GIT_OPT_ENABLE_CACHING:
234 git_cache__enabled = (va_arg(ap, int) != 0);
235 break;
236
237 case GIT_OPT_GET_CACHED_MEMORY:
238 *(va_arg(ap, ssize_t *)) = git_cache__current_storage.val;
239 *(va_arg(ap, ssize_t *)) = git_cache__max_storage;
240 break;
241
242 case GIT_OPT_GET_TEMPLATE_PATH:
243 {
244 git_buf *out = va_arg(ap, git_buf *);
245 const git_buf *tmp;
246
247 if ((error = git_buf_sanitize(out)) < 0 ||
248 (error = git_sysdir_get(&tmp, GIT_SYSDIR_TEMPLATE)) < 0)
249 break;
250
251 error = git_buf_sets(out, tmp->ptr);
252 }
253 break;
254
255 case GIT_OPT_SET_TEMPLATE_PATH:
256 error = git_sysdir_set(GIT_SYSDIR_TEMPLATE, va_arg(ap, const char *));
257 break;
258
259 case GIT_OPT_SET_SSL_CERT_LOCATIONS:
260 #ifdef GIT_OPENSSL
261 {
262 const char *file = va_arg(ap, const char *);
263 const char *path = va_arg(ap, const char *);
264 error = git_openssl__set_cert_location(file, path);
265 }
266 #elif defined(GIT_MBEDTLS)
267 {
268 const char *file = va_arg(ap, const char *);
269 const char *path = va_arg(ap, const char *);
270 if (file)
271 error = git_mbedtls__set_cert_location(file, 0);
272 if (error && path)
273 error = git_mbedtls__set_cert_location(path, 1);
274 }
275 #else
276 git_error_set(GIT_ERROR_SSL, "TLS backend doesn't support certificate locations");
277 error = -1;
278 #endif
279 break;
280 case GIT_OPT_SET_USER_AGENT:
281 git__free(git__user_agent);
282 git__user_agent = git__strdup(va_arg(ap, const char *));
283 if (!git__user_agent) {
284 git_error_set_oom();
285 error = -1;
286 }
287
288 break;
289
290 case GIT_OPT_ENABLE_STRICT_OBJECT_CREATION:
291 git_object__strict_input_validation = (va_arg(ap, int) != 0);
292 break;
293
294 case GIT_OPT_ENABLE_STRICT_SYMBOLIC_REF_CREATION:
295 git_reference__enable_symbolic_ref_target_validation = (va_arg(ap, int) != 0);
296 break;
297
298 case GIT_OPT_SET_SSL_CIPHERS:
299 #if (GIT_OPENSSL || GIT_MBEDTLS)
300 {
301 git__free(git__ssl_ciphers);
302 git__ssl_ciphers = git__strdup(va_arg(ap, const char *));
303 if (!git__ssl_ciphers) {
304 git_error_set_oom();
305 error = -1;
306 }
307 }
308 #else
309 git_error_set(GIT_ERROR_SSL, "TLS backend doesn't support custom ciphers");
310 error = -1;
311 #endif
312 break;
313
314 case GIT_OPT_GET_USER_AGENT:
315 {
316 git_buf *out = va_arg(ap, git_buf *);
317 if ((error = git_buf_sanitize(out)) < 0)
318 break;
319 error = git_buf_sets(out, git__user_agent);
320 }
321 break;
322
323 case GIT_OPT_ENABLE_OFS_DELTA:
324 git_smart__ofs_delta_enabled = (va_arg(ap, int) != 0);
325 break;
326
327 case GIT_OPT_ENABLE_FSYNC_GITDIR:
328 git_repository__fsync_gitdir = (va_arg(ap, int) != 0);
329 break;
330
331 case GIT_OPT_GET_WINDOWS_SHAREMODE:
332 #ifdef GIT_WIN32
333 *(va_arg(ap, unsigned long *)) = git_win32__createfile_sharemode;
334 #endif
335 break;
336
337 case GIT_OPT_SET_WINDOWS_SHAREMODE:
338 #ifdef GIT_WIN32
339 git_win32__createfile_sharemode = va_arg(ap, unsigned long);
340 #endif
341 break;
342
343 case GIT_OPT_ENABLE_STRICT_HASH_VERIFICATION:
344 git_odb__strict_hash_verification = (va_arg(ap, int) != 0);
345 break;
346
347 case GIT_OPT_SET_ALLOCATOR:
348 error = git_allocator_setup(va_arg(ap, git_allocator *));
349 break;
350
351 case GIT_OPT_ENABLE_UNSAVED_INDEX_SAFETY:
352 git_index__enforce_unsaved_safety = (va_arg(ap, int) != 0);
353 break;
354
355 case GIT_OPT_SET_PACK_MAX_OBJECTS:
356 git_indexer__max_objects = va_arg(ap, size_t);
357 break;
358
359 case GIT_OPT_GET_PACK_MAX_OBJECTS:
360 *(va_arg(ap, size_t *)) = git_indexer__max_objects;
361 break;
362
363 case GIT_OPT_DISABLE_PACK_KEEP_FILE_CHECKS:
364 git_disable_pack_keep_file_checks = (va_arg(ap, int) != 0);
365 break;
366
367 case GIT_OPT_ENABLE_HTTP_EXPECT_CONTINUE:
368 git_http__expect_continue = (va_arg(ap, int) != 0);
369 break;
370
371 default:
372 git_error_set(GIT_ERROR_INVALID, "invalid option key");
373 error = -1;
374 }
375
376 va_end(ap);
377
378 return error;
379 }
380