Directory: | cvmfs/ |
---|---|
File: | cvmfs/libcvmfs.cc |
Date: | 2025-06-22 02:36:02 |
Exec | Total | Coverage | |
---|---|---|---|
Lines: | 155 | 278 | 55.8% |
Branches: | 84 | 258 | 32.6% |
Line | Branch | Exec | Source |
---|---|---|---|
1 | /** | ||
2 | * This file is part of the CernVM File System. | ||
3 | * | ||
4 | * libcvmfs provides an API for the CernVM-FS client. This is an | ||
5 | * alternative to FUSE for reading a remote CernVM-FS repository. | ||
6 | */ | ||
7 | |||
8 | #define _FILE_OFFSET_BITS 64 | ||
9 | |||
10 | #ifndef __STDC_FORMAT_MACROS | ||
11 | #define __STDC_FORMAT_MACROS | ||
12 | #endif | ||
13 | |||
14 | |||
15 | #include "libcvmfs.h" | ||
16 | |||
17 | #include <errno.h> | ||
18 | #include <inttypes.h> | ||
19 | #include <stddef.h> | ||
20 | #include <sys/stat.h> | ||
21 | |||
22 | #include <cassert> | ||
23 | #include <cstdlib> | ||
24 | #include <string> | ||
25 | |||
26 | #include "libcvmfs_int.h" | ||
27 | #include "statistics.h" | ||
28 | #include "util/logging.h" | ||
29 | #include "util/posix.h" | ||
30 | #include "util/smalloc.h" | ||
31 | #include "xattr.h" | ||
32 | |||
33 | using namespace std; // NOLINT | ||
34 | |||
35 | /** | ||
36 | * Create the cvmfs_attr struct which contains the same information | ||
37 | * as a stat, but also has pointers to the hash, symlink, and name. | ||
38 | */ | ||
39 | 144 | struct cvmfs_attr *cvmfs_attr_init() { | |
40 | struct cvmfs_attr *attr; | ||
41 | 144 | attr = reinterpret_cast<cvmfs_attr *>(calloc(1, sizeof(*attr))); | |
42 | 144 | attr->version = 1; | |
43 | 144 | attr->size = sizeof(*attr); | |
44 | 144 | return attr; | |
45 | } | ||
46 | |||
47 | |||
48 | /** | ||
49 | * Destroy the cvmfs_attr struct and frees the checksum, symlink, | ||
50 | * name, and xattrs. | ||
51 | */ | ||
52 | 144 | void cvmfs_attr_free(struct cvmfs_attr *attr) { | |
53 |
1/2✓ Branch 0 taken 144 times.
✗ Branch 1 not taken.
|
144 | if (attr) { |
54 | 144 | free(attr->cvm_checksum); | |
55 | 144 | free(attr->cvm_symlink); | |
56 | 144 | free(attr->cvm_name); | |
57 | 144 | free(attr->cvm_parent); | |
58 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 144 times.
|
144 | delete reinterpret_cast<XattrList *>(attr->cvm_xattrs); |
59 | } | ||
60 | 144 | free(attr); | |
61 | 144 | } | |
62 | |||
63 | |||
64 | 147 | struct cvmfs_nc_attr *cvmfs_nc_attr_init() { | |
65 | struct cvmfs_nc_attr *attr; | ||
66 | 147 | attr = reinterpret_cast<cvmfs_nc_attr *>(calloc(1, sizeof(*attr))); | |
67 | 147 | return attr; | |
68 | } | ||
69 | |||
70 | 147 | void cvmfs_nc_attr_free(struct cvmfs_nc_attr *nc_attr) { | |
71 |
1/2✓ Branch 0 taken 147 times.
✗ Branch 1 not taken.
|
147 | if (nc_attr) { |
72 | 147 | free(nc_attr->mountpoint); | |
73 | 147 | free(nc_attr->hash); | |
74 | } | ||
75 | 147 | free(nc_attr); | |
76 | 147 | } | |
77 | |||
78 | |||
79 | /** | ||
80 | * Expand symlinks in all levels of a path. Also, expand ".." and ".". This | ||
81 | * also has the side-effect of ensuring that cvmfs_getattr() is called on all | ||
82 | * parent paths, which is needed to ensure proper loading of nested catalogs | ||
83 | * before the child is accessed. | ||
84 | */ | ||
85 | 1063 | static int expand_path(const int depth, | |
86 | LibContext *ctx, | ||
87 | char const *path, | ||
88 | string *expanded_path) { | ||
89 |
2/4✓ Branch 2 taken 1063 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 1063 times.
✗ Branch 6 not taken.
|
2126 | const string p_path = GetParentPath(path); |
90 |
2/4✓ Branch 2 taken 1063 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 1063 times.
✗ Branch 6 not taken.
|
2126 | const string fname = GetFileName(path); |
91 | int rc; | ||
92 | |||
93 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 1063 times.
|
1063 | if (fname == "..") { |
94 | ✗ | rc = expand_path(depth, ctx, p_path.c_str(), expanded_path); | |
95 | ✗ | if (rc != 0) { | |
96 | ✗ | return -1; | |
97 | } | ||
98 | ✗ | if (*expanded_path == "/") { | |
99 | // attempt to access parent path of the root of the repository | ||
100 | ✗ | LogCvmfs(kLogCvmfs, kLogDebug, | |
101 | "libcvmfs cannot resolve symlinks to paths outside of the repo: " | ||
102 | "%s", | ||
103 | path); | ||
104 | ✗ | errno = ENOENT; | |
105 | ✗ | return -1; | |
106 | } | ||
107 | ✗ | *expanded_path = GetParentPath(*expanded_path); | |
108 | ✗ | if (*expanded_path == "") { | |
109 | ✗ | *expanded_path = "/"; | |
110 | } | ||
111 | ✗ | return 0; | |
112 | } | ||
113 | |||
114 | 1063 | string buf; | |
115 |
2/2✓ Branch 1 taken 436 times.
✓ Branch 2 taken 627 times.
|
1063 | if (p_path != "") { |
116 |
1/2✓ Branch 2 taken 436 times.
✗ Branch 3 not taken.
|
436 | rc = expand_path(depth, ctx, p_path.c_str(), &buf); |
117 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 436 times.
|
436 | if (rc != 0) { |
118 | ✗ | return -1; | |
119 | } | ||
120 | |||
121 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 436 times.
|
436 | if (fname == ".") { |
122 | ✗ | *expanded_path = buf; | |
123 | ✗ | return 0; | |
124 | } | ||
125 | } | ||
126 | |||
127 |
5/8✓ Branch 1 taken 436 times.
✓ Branch 2 taken 627 times.
✓ Branch 5 taken 436 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 436 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 1063 times.
✗ Branch 10 not taken.
|
1063 | if (buf.length() == 0 || buf[buf.length() - 1] != '/') { |
128 |
1/2✓ Branch 1 taken 1063 times.
✗ Branch 2 not taken.
|
1063 | buf += "/"; |
129 | } | ||
130 |
1/2✓ Branch 1 taken 1063 times.
✗ Branch 2 not taken.
|
1063 | buf += fname; |
131 | |||
132 | struct stat st; | ||
133 |
1/2✓ Branch 2 taken 1063 times.
✗ Branch 3 not taken.
|
1063 | rc = ctx->GetAttr(buf.c_str(), &st); |
134 |
2/2✓ Branch 0 taken 48 times.
✓ Branch 1 taken 1015 times.
|
1063 | if (rc != 0) { |
135 | 48 | errno = -rc; | |
136 | 48 | return -1; | |
137 | } | ||
138 | |||
139 |
1/2✓ Branch 0 taken 1015 times.
✗ Branch 1 not taken.
|
1015 | if (!S_ISLNK(st.st_mode)) { |
140 |
1/2✓ Branch 1 taken 1015 times.
✗ Branch 2 not taken.
|
1015 | *expanded_path = buf; |
141 | 1015 | return 0; | |
142 | } | ||
143 | |||
144 | ✗ | if (depth > 1000) { | |
145 | // avoid unbounded recursion due to symlinks | ||
146 | ✗ | LogCvmfs(kLogCvmfs, kLogDebug, | |
147 | "libcvmfs hit its symlink recursion limit: %s", path); | ||
148 | ✗ | errno = ELOOP; | |
149 | ✗ | return -1; | |
150 | } | ||
151 | |||
152 | // expand symbolic link | ||
153 | |||
154 | ✗ | char *ln_buf = reinterpret_cast<char *>(alloca(st.st_size + 2)); | |
155 | ✗ | if (!ln_buf) { | |
156 | ✗ | errno = ENOMEM; | |
157 | ✗ | return -1; | |
158 | } | ||
159 | ✗ | rc = ctx->Readlink(buf.c_str(), ln_buf, st.st_size + 2); | |
160 | ✗ | if (rc != 0) { | |
161 | ✗ | errno = -rc; | |
162 | ✗ | return -1; | |
163 | } | ||
164 | ✗ | if (ln_buf[0] == '/') { | |
165 | // symlink is absolute path, strip /cvmfs/$repo | ||
166 | ✗ | const unsigned len = ctx->mount_point()->fqrn().length(); | |
167 | ✗ | if (strncmp(ln_buf, ctx->mount_point()->fqrn().c_str(), len) == 0 | |
168 | ✗ | && (ln_buf[len] == '/' || ln_buf[len] == '\0')) { | |
169 | ✗ | buf = ln_buf + len; | |
170 | ✗ | if (ln_buf[len] == '\0') { | |
171 | ✗ | buf += "/"; | |
172 | } | ||
173 | } else { | ||
174 | ✗ | LogCvmfs(kLogCvmfs, kLogDebug, | |
175 | "libcvmfs can't resolve symlinks to paths outside of the repo: " | ||
176 | "%s --> %s (mountpoint=%s)", | ||
177 | ✗ | path, ln_buf, ctx->mount_point()->fqrn().c_str()); | |
178 | ✗ | errno = ENOENT; | |
179 | ✗ | return -1; | |
180 | } | ||
181 | } else { | ||
182 | // symlink is relative path | ||
183 | ✗ | buf = GetParentPath(buf); | |
184 | ✗ | buf += "/"; | |
185 | ✗ | buf += ln_buf; | |
186 | } | ||
187 | |||
188 | // In case the symlink references other symlinks or contains ".." | ||
189 | // or "." we must now call expand_path on the result. | ||
190 | |||
191 | ✗ | return expand_path(depth + 1, ctx, buf.c_str(), expanded_path); | |
192 | 1063 | } | |
193 | |||
194 | /** | ||
195 | * Like expand_path(), but do not expand the final element of the path. | ||
196 | */ | ||
197 | 144 | static int expand_ppath(LibContext *ctx, | |
198 | const char *path, | ||
199 | string *expanded_path) { | ||
200 |
2/4✓ Branch 2 taken 144 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 144 times.
✗ Branch 6 not taken.
|
288 | const string p_path = GetParentPath(path); |
201 |
2/4✓ Branch 2 taken 144 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 144 times.
✗ Branch 6 not taken.
|
288 | const string fname = GetFileName(path); |
202 | |||
203 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 144 times.
|
144 | if (p_path == "") { |
204 | ✗ | *expanded_path = path; | |
205 | ✗ | return 0; | |
206 | } | ||
207 | |||
208 |
1/2✓ Branch 2 taken 144 times.
✗ Branch 3 not taken.
|
144 | const int rc = expand_path(0, ctx, p_path.c_str(), expanded_path); |
209 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 144 times.
|
144 | if (rc != 0) { |
210 | ✗ | return rc; | |
211 | } | ||
212 | |||
213 |
1/2✓ Branch 1 taken 144 times.
✗ Branch 2 not taken.
|
144 | (*expanded_path) += "/"; |
214 |
1/2✓ Branch 1 taken 144 times.
✗ Branch 2 not taken.
|
144 | (*expanded_path) += fname; |
215 | |||
216 | 144 | return 0; | |
217 | 144 | } | |
218 | |||
219 | |||
220 | ✗ | int cvmfs_open(LibContext *ctx, const char *path) { | |
221 | ✗ | string lpath; | |
222 | int rc; | ||
223 | ✗ | rc = expand_path(0, ctx, path, &lpath); | |
224 | ✗ | if (rc < 0) { | |
225 | ✗ | return -1; | |
226 | } | ||
227 | ✗ | path = lpath.c_str(); | |
228 | |||
229 | ✗ | rc = ctx->Open(path); | |
230 | ✗ | if (rc < 0) { | |
231 | ✗ | errno = -rc; | |
232 | ✗ | return -1; | |
233 | } | ||
234 | ✗ | return rc; | |
235 | } | ||
236 | |||
237 | |||
238 | ✗ | ssize_t cvmfs_pread( | |
239 | LibContext *ctx, int fd, void *buf, size_t size, off_t off) { | ||
240 | ✗ | const ssize_t nbytes = ctx->Pread(fd, buf, size, off); | |
241 | ✗ | if (nbytes < 0) { | |
242 | ✗ | errno = -nbytes; | |
243 | ✗ | return -1; | |
244 | } | ||
245 | ✗ | return nbytes; | |
246 | } | ||
247 | |||
248 | |||
249 | ✗ | int cvmfs_close(LibContext *ctx, int fd) { | |
250 | ✗ | const int rc = ctx->Close(fd); | |
251 | ✗ | if (rc < 0) { | |
252 | ✗ | errno = -rc; | |
253 | ✗ | return -1; | |
254 | } | ||
255 | ✗ | return 0; | |
256 | } | ||
257 | |||
258 | |||
259 | ✗ | int cvmfs_readlink(LibContext *ctx, const char *path, char *buf, size_t size) { | |
260 | ✗ | string lpath; | |
261 | int rc; | ||
262 | ✗ | rc = expand_ppath(ctx, path, &lpath); | |
263 | ✗ | if (rc < 0) { | |
264 | ✗ | return -1; | |
265 | } | ||
266 | ✗ | path = lpath.c_str(); | |
267 | |||
268 | ✗ | rc = ctx->Readlink(path, buf, size); | |
269 | ✗ | if (rc < 0) { | |
270 | ✗ | errno = -rc; | |
271 | ✗ | return -1; | |
272 | } | ||
273 | ✗ | return 0; | |
274 | } | ||
275 | |||
276 | |||
277 | 144 | int cvmfs_stat(LibContext *ctx, const char *path, struct stat *st) { | |
278 | 144 | string lpath; | |
279 | int rc; | ||
280 |
1/2✓ Branch 1 taken 144 times.
✗ Branch 2 not taken.
|
144 | rc = expand_path(0, ctx, path, &lpath); |
281 |
2/2✓ Branch 0 taken 48 times.
✓ Branch 1 taken 96 times.
|
144 | if (rc < 0) { |
282 | 48 | return -1; | |
283 | } | ||
284 | 96 | path = lpath.c_str(); | |
285 | |||
286 |
1/2✓ Branch 1 taken 96 times.
✗ Branch 2 not taken.
|
96 | rc = ctx->GetAttr(path, st); |
287 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 96 times.
|
96 | if (rc < 0) { |
288 | ✗ | errno = -rc; | |
289 | ✗ | return -1; | |
290 | } | ||
291 | 96 | return 0; | |
292 | 144 | } | |
293 | |||
294 | |||
295 | ✗ | int cvmfs_lstat(LibContext *ctx, const char *path, struct stat *st) { | |
296 | ✗ | string lpath; | |
297 | int rc; | ||
298 | ✗ | rc = expand_ppath(ctx, path, &lpath); | |
299 | ✗ | if (rc < 0) { | |
300 | ✗ | return -1; | |
301 | } | ||
302 | ✗ | path = lpath.c_str(); | |
303 | |||
304 | ✗ | rc = ctx->GetAttr(path, st); | |
305 | ✗ | if (rc < 0) { | |
306 | ✗ | errno = -rc; | |
307 | ✗ | return -1; | |
308 | } | ||
309 | ✗ | return 0; | |
310 | } | ||
311 | |||
312 | |||
313 | 144 | int cvmfs_stat_attr(LibContext *ctx, | |
314 | const char *path, | ||
315 | struct cvmfs_attr *attr) { | ||
316 | 144 | string lpath; | |
317 | int rc; | ||
318 |
1/2✓ Branch 1 taken 144 times.
✗ Branch 2 not taken.
|
144 | rc = expand_ppath(ctx, path, &lpath); |
319 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 144 times.
|
144 | if (rc < 0) { |
320 | ✗ | return -1; | |
321 | } | ||
322 | 144 | path = lpath.c_str(); | |
323 | |||
324 |
1/2✓ Branch 1 taken 144 times.
✗ Branch 2 not taken.
|
144 | rc = ctx->GetExtAttr(path, attr); |
325 |
2/2✓ Branch 0 taken 48 times.
✓ Branch 1 taken 96 times.
|
144 | if (rc < 0) { |
326 | 48 | errno = -rc; | |
327 | 48 | return -1; | |
328 | } | ||
329 | 96 | return 0; | |
330 | 144 | } | |
331 | |||
332 | |||
333 | 48 | int cvmfs_listdir(LibContext *ctx, | |
334 | const char *path, | ||
335 | char ***buf, | ||
336 | size_t *buflen) { | ||
337 | 48 | string lpath; | |
338 | int rc; | ||
339 |
1/2✓ Branch 1 taken 48 times.
✗ Branch 2 not taken.
|
48 | rc = expand_path(0, ctx, path, &lpath); |
340 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 48 times.
|
48 | if (rc < 0) { |
341 | ✗ | return -1; | |
342 | } | ||
343 | 48 | path = lpath.c_str(); | |
344 | |||
345 | 48 | size_t listsize = 0; | |
346 |
1/2✓ Branch 1 taken 48 times.
✗ Branch 2 not taken.
|
48 | rc = ctx->ListDirectory(path, buf, &listsize, buflen, true); |
347 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 48 times.
|
48 | if (rc < 0) { |
348 | ✗ | errno = -rc; | |
349 | ✗ | return -1; | |
350 | } | ||
351 | 48 | return 0; | |
352 | 48 | } | |
353 | |||
354 | ✗ | int cvmfs_listdir_contents(LibContext *ctx, | |
355 | const char *path, | ||
356 | char ***buf, | ||
357 | size_t *listlen, | ||
358 | size_t *buflen) { | ||
359 | ✗ | string lpath; | |
360 | int rc; | ||
361 | ✗ | rc = expand_path(0, ctx, path, &lpath); | |
362 | ✗ | if (rc < 0) { | |
363 | ✗ | return -1; | |
364 | } | ||
365 | ✗ | path = lpath.c_str(); | |
366 | |||
367 | ✗ | rc = ctx->ListDirectory(path, buf, listlen, buflen, false); | |
368 | ✗ | if (rc < 0) { | |
369 | ✗ | errno = -rc; | |
370 | ✗ | return -1; | |
371 | } | ||
372 | ✗ | return 0; | |
373 | } | ||
374 | |||
375 | 48 | int cvmfs_listdir_stat(LibContext *ctx, | |
376 | const char *path, | ||
377 | struct cvmfs_stat_t **buf, | ||
378 | size_t *listlen, | ||
379 | size_t *buflen) { | ||
380 | 48 | string lpath; | |
381 | int rc; | ||
382 |
1/2✓ Branch 1 taken 48 times.
✗ Branch 2 not taken.
|
48 | rc = expand_path(0, ctx, path, &lpath); |
383 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 48 times.
|
48 | if (rc < 0) { |
384 | ✗ | return -1; | |
385 | } | ||
386 | 48 | path = lpath.c_str(); | |
387 | |||
388 |
1/2✓ Branch 1 taken 48 times.
✗ Branch 2 not taken.
|
48 | rc = ctx->ListDirectoryStat(path, buf, listlen, buflen); |
389 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 48 times.
|
48 | if (rc < 0) { |
390 | ✗ | errno = -rc; | |
391 | ✗ | return -1; | |
392 | } | ||
393 | 48 | return 0; | |
394 | 48 | } | |
395 | |||
396 | |||
397 | 147 | int cvmfs_stat_nc(LibContext *ctx, | |
398 | const char *path, | ||
399 | struct cvmfs_nc_attr *nc_attr) { | ||
400 | 147 | string lpath; | |
401 | int rc; | ||
402 |
1/2✓ Branch 1 taken 147 times.
✗ Branch 2 not taken.
|
147 | rc = expand_path(0, ctx, path, &lpath); |
403 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 147 times.
|
147 | if (rc < 0) { |
404 | ✗ | return -1; | |
405 | } | ||
406 | 147 | path = lpath.c_str(); | |
407 | |||
408 |
1/2✓ Branch 1 taken 147 times.
✗ Branch 2 not taken.
|
147 | rc = ctx->GetNestedCatalogAttr(path, nc_attr); |
409 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 147 times.
|
147 | if (rc < 0) { |
410 | ✗ | errno = -rc; | |
411 | ✗ | return -1; | |
412 | } | ||
413 | 147 | return 0; | |
414 | 147 | } | |
415 | |||
416 | |||
417 | 96 | int cvmfs_list_nc(LibContext *ctx, | |
418 | const char *path, | ||
419 | char ***buf, | ||
420 | size_t *buflen) { | ||
421 | 96 | string lpath; | |
422 | int rc; | ||
423 |
1/2✓ Branch 1 taken 96 times.
✗ Branch 2 not taken.
|
96 | rc = expand_path(0, ctx, path, &lpath); |
424 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 96 times.
|
96 | if (rc < 0) { |
425 | ✗ | return -1; | |
426 | } | ||
427 | 96 | path = lpath.c_str(); | |
428 | |||
429 |
1/2✓ Branch 1 taken 96 times.
✗ Branch 2 not taken.
|
96 | rc = ctx->ListNestedCatalogs(path, buf, buflen); |
430 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 96 times.
|
96 | if (rc < 0) { |
431 | ✗ | errno = -rc; | |
432 | ✗ | return -1; | |
433 | } | ||
434 | 96 | return 0; | |
435 | 96 | } | |
436 | |||
437 | |||
438 | 144 | void cvmfs_list_free(char **buf) { | |
439 | // Quick return if base pointer is NULL | ||
440 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 144 times.
|
144 | if (!buf) |
441 | ✗ | return; | |
442 | 144 | size_t pos = 0; | |
443 | // Iterate over each non-null entry and free | ||
444 | // This assumes no null entries, which don't currently exist | ||
445 |
2/2✓ Branch 0 taken 624 times.
✓ Branch 1 taken 144 times.
|
768 | while (buf[pos]) { |
446 | 624 | free(buf[pos]); | |
447 | 624 | pos++; | |
448 | } | ||
449 | 144 | free(buf); | |
450 | } | ||
451 | |||
452 | ✗ | void cvmfs_enable_threaded(LibContext *ctx) { ctx->EnableMultiThreaded(); } | |
453 | |||
454 | 386 | cvmfs_errors cvmfs_attach_repo_v2(const char *fqrn, | |
455 | SimpleOptionsParser *opts, | ||
456 | LibContext **ctx) { | ||
457 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 386 times.
|
386 | assert(ctx != NULL); |
458 |
4/8✓ Branch 2 taken 386 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 386 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 386 times.
✗ Branch 9 not taken.
✓ Branch 11 taken 386 times.
✗ Branch 12 not taken.
|
386 | opts->SwitchTemplateManager(new DefaultOptionsTemplateManager(fqrn)); |
459 |
2/4✓ Branch 2 taken 386 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 386 times.
✗ Branch 6 not taken.
|
386 | *ctx = LibContext::Create(fqrn, opts); |
460 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 386 times.
|
386 | assert(*ctx != NULL); |
461 | 386 | const loader::Failures result = (*ctx)->mount_point()->boot_status(); | |
462 |
2/2✓ Branch 0 taken 96 times.
✓ Branch 1 taken 290 times.
|
386 | if (result != loader::kFailOk) { |
463 |
1/4✓ Branch 2 taken 96 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
|
96 | LogCvmfs(kLogCvmfs, kLogStderr, "Attaching %s failed: %s (%d)", fqrn, |
464 | 192 | (*ctx)->mount_point()->boot_error().c_str(), result); | |
465 |
1/2✓ Branch 0 taken 96 times.
✗ Branch 1 not taken.
|
96 | delete *ctx; |
466 | 96 | *ctx = NULL; | |
467 | } | ||
468 | 386 | return static_cast<cvmfs_errors>(result); | |
469 | } | ||
470 | |||
471 | |||
472 | ✗ | void cvmfs_adopt_options(cvmfs_context *ctx, SimpleOptionsParser *opts) { | |
473 | ✗ | ctx->set_options_mgr(opts); | |
474 | } | ||
475 | |||
476 | |||
477 |
1/2✓ Branch 0 taken 290 times.
✗ Branch 1 not taken.
|
290 | void cvmfs_detach_repo(LibContext *ctx) { delete ctx; } |
478 | |||
479 | |||
480 | 484 | cvmfs_errors cvmfs_init_v2(SimpleOptionsParser *opts) { | |
481 | 484 | const int result = LibGlobals::Initialize(opts); | |
482 |
2/2✓ Branch 0 taken 49 times.
✓ Branch 1 taken 435 times.
|
484 | if (result != loader::kFailOk) { |
483 |
1/4✓ Branch 2 taken 49 times.
✗ Branch 3 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
|
49 | LogCvmfs(kLogCvmfs, kLogStderr, "Initialization failed: %s (%d)", |
484 | 98 | LibGlobals::GetInstance()->file_system()->boot_error().c_str(), | |
485 | result); | ||
486 | 49 | LibGlobals::CleanupInstance(); | |
487 | } | ||
488 | 484 | return static_cast<cvmfs_errors>(result); | |
489 | } | ||
490 | |||
491 | |||
492 | 628 | void cvmfs_fini() { LibGlobals::CleanupInstance(); } | |
493 | |||
494 | |||
495 | static void (*ext_log_fn)(const char *msg) = NULL; | ||
496 | |||
497 | |||
498 | 301992 | static void libcvmfs_log_fn(const LogSource /*source*/, | |
499 | const int /*mask*/, | ||
500 | const char *msg) { | ||
501 |
1/2✓ Branch 0 taken 301992 times.
✗ Branch 1 not taken.
|
301992 | if (ext_log_fn) { |
502 | 301992 | (*ext_log_fn)(msg); | |
503 | } | ||
504 | 301992 | } | |
505 | |||
506 | |||
507 | 1349 | void cvmfs_set_log_fn(void (*log_fn)(const char *msg)) { | |
508 | 1349 | ext_log_fn = log_fn; | |
509 |
2/2✓ Branch 0 taken 674 times.
✓ Branch 1 taken 675 times.
|
1349 | if (log_fn == NULL) { |
510 | 674 | SetAltLogFunc(NULL); | |
511 | } else { | ||
512 | 675 | SetAltLogFunc(libcvmfs_log_fn); | |
513 | } | ||
514 | 1349 | } | |
515 | |||
516 | |||
517 | ✗ | char *cvmfs_statistics_format(cvmfs_context *ctx) { | |
518 | ✗ | assert(ctx != NULL); | |
519 | const std::string stats = ctx->mount_point()->statistics()->PrintList( | ||
520 | ✗ | perf::Statistics::kPrintHeader); | |
521 | ✗ | return strdup(stats.c_str()); | |
522 | } | ||
523 | |||
524 | |||
525 | 2 | int cvmfs_remount(LibContext *ctx) { | |
526 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
|
2 | assert(ctx != NULL); |
527 | 2 | return ctx->Remount(); | |
528 | } | ||
529 | |||
530 | |||
531 | 3 | uint64_t cvmfs_get_revision(LibContext *ctx) { | |
532 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
|
3 | assert(ctx != NULL); |
533 | 3 | return ctx->GetRevision(); | |
534 | } | ||
535 |