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