CernVM-FS  2.13.0
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
libcvmfs.cc
Go to the documentation of this file.
1 
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 
40  struct cvmfs_attr *attr;
41  attr = reinterpret_cast<cvmfs_attr *>(calloc(1, sizeof(*attr)));
42  attr->version = 1;
43  attr->size = sizeof(*attr);
44  return attr;
45 }
46 
47 
52 void cvmfs_attr_free(struct cvmfs_attr *attr) {
53  if (attr) {
54  free(attr->cvm_checksum);
55  free(attr->cvm_symlink);
56  free(attr->cvm_name);
57  free(attr->cvm_parent);
58  delete reinterpret_cast<XattrList *>(attr->cvm_xattrs);
59  }
60  free(attr);
61 }
62 
63 
65  struct cvmfs_nc_attr *attr;
66  attr = reinterpret_cast<cvmfs_nc_attr *>(calloc(1, sizeof(*attr)));
67  return attr;
68 }
69 
70 void cvmfs_nc_attr_free(struct cvmfs_nc_attr *nc_attr) {
71  if (nc_attr) {
72  free(nc_attr->mountpoint);
73  free(nc_attr->hash);
74  }
75  free(nc_attr);
76 }
77 
78 
85 static int expand_path(const int depth,
86  LibContext *ctx,
87  char const *path,
88  string *expanded_path) {
89  const string p_path = GetParentPath(path);
90  const string fname = GetFileName(path);
91  int rc;
92 
93  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
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  string buf;
115  if (p_path != "") {
116  rc = expand_path(depth, ctx, p_path.c_str(), &buf);
117  if (rc != 0) {
118  return -1;
119  }
120 
121  if (fname == ".") {
122  *expanded_path = buf;
123  return 0;
124  }
125  }
126 
127  if (buf.length() == 0 || buf[buf.length() - 1] != '/') {
128  buf += "/";
129  }
130  buf += fname;
131 
132  struct stat st;
133  rc = ctx->GetAttr(buf.c_str(), &st);
134  if (rc != 0) {
135  errno = -rc;
136  return -1;
137  }
138 
139  if (!S_ISLNK(st.st_mode)) {
140  *expanded_path = buf;
141  return 0;
142  }
143 
144  if (depth > 1000) {
145  // avoid unbounded recursion due to symlinks
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 {
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 }
193 
198  const char *path,
199  string *expanded_path) {
200  const string p_path = GetParentPath(path);
201  const string fname = GetFileName(path);
202 
203  if (p_path == "") {
204  *expanded_path = path;
205  return 0;
206  }
207 
208  const int rc = expand_path(0, ctx, p_path.c_str(), expanded_path);
209  if (rc != 0) {
210  return rc;
211  }
212 
213  (*expanded_path) += "/";
214  (*expanded_path) += fname;
215 
216  return 0;
217 }
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 int cvmfs_stat(LibContext *ctx, const char *path, struct stat *st) {
278  string lpath;
279  int rc;
280  rc = expand_path(0, ctx, path, &lpath);
281  if (rc < 0) {
282  return -1;
283  }
284  path = lpath.c_str();
285 
286  rc = ctx->GetAttr(path, st);
287  if (rc < 0) {
288  errno = -rc;
289  return -1;
290  }
291  return 0;
292 }
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 
314  const char *path,
315  struct cvmfs_attr *attr) {
316  string lpath;
317  int rc;
318  rc = expand_ppath(ctx, path, &lpath);
319  if (rc < 0) {
320  return -1;
321  }
322  path = lpath.c_str();
323 
324  rc = ctx->GetExtAttr(path, attr);
325  if (rc < 0) {
326  errno = -rc;
327  return -1;
328  }
329  return 0;
330 }
331 
332 
334  const char *path,
335  char ***buf,
336  size_t *buflen) {
337  string lpath;
338  int rc;
339  rc = expand_path(0, ctx, path, &lpath);
340  if (rc < 0) {
341  return -1;
342  }
343  path = lpath.c_str();
344 
345  size_t listsize = 0;
346  rc = ctx->ListDirectory(path, buf, &listsize, buflen, true);
347  if (rc < 0) {
348  errno = -rc;
349  return -1;
350  }
351  return 0;
352 }
353 
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 
376  const char *path,
377  struct cvmfs_stat_t **buf,
378  size_t *listlen,
379  size_t *buflen) {
380  string lpath;
381  int rc;
382  rc = expand_path(0, ctx, path, &lpath);
383  if (rc < 0) {
384  return -1;
385  }
386  path = lpath.c_str();
387 
388  rc = ctx->ListDirectoryStat(path, buf, listlen, buflen);
389  if (rc < 0) {
390  errno = -rc;
391  return -1;
392  }
393  return 0;
394 }
395 
396 
398  const char *path,
399  struct cvmfs_nc_attr *nc_attr) {
400  string lpath;
401  int rc;
402  rc = expand_path(0, ctx, path, &lpath);
403  if (rc < 0) {
404  return -1;
405  }
406  path = lpath.c_str();
407 
408  rc = ctx->GetNestedCatalogAttr(path, nc_attr);
409  if (rc < 0) {
410  errno = -rc;
411  return -1;
412  }
413  return 0;
414 }
415 
416 
418  const char *path,
419  char ***buf,
420  size_t *buflen) {
421  string lpath;
422  int rc;
423  rc = expand_path(0, ctx, path, &lpath);
424  if (rc < 0) {
425  return -1;
426  }
427  path = lpath.c_str();
428 
429  rc = ctx->ListNestedCatalogs(path, buf, buflen);
430  if (rc < 0) {
431  errno = -rc;
432  return -1;
433  }
434  return 0;
435 }
436 
437 
438 void cvmfs_list_free(char **buf) {
439  // Quick return if base pointer is NULL
440  if (!buf)
441  return;
442  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  while (buf[pos]) {
446  free(buf[pos]);
447  pos++;
448  }
449  free(buf);
450 }
451 
453 
455  SimpleOptionsParser *opts,
456  LibContext **ctx) {
457  assert(ctx != NULL);
459  *ctx = LibContext::Create(fqrn, opts);
460  assert(*ctx != NULL);
461  const loader::Failures result = (*ctx)->mount_point()->boot_status();
462  if (result != loader::kFailOk) {
463  LogCvmfs(kLogCvmfs, kLogStderr, "Attaching %s failed: %s (%d)", fqrn,
464  (*ctx)->mount_point()->boot_error().c_str(), result);
465  delete *ctx;
466  *ctx = NULL;
467  }
468  return static_cast<cvmfs_errors>(result);
469 }
470 
471 
473  ctx->set_options_mgr(opts);
474 }
475 
476 
478 
479 
481  const int result = LibGlobals::Initialize(opts);
482  if (result != loader::kFailOk) {
483  LogCvmfs(kLogCvmfs, kLogStderr, "Initialization failed: %s (%d)",
484  LibGlobals::GetInstance()->file_system()->boot_error().c_str(),
485  result);
487  }
488  return static_cast<cvmfs_errors>(result);
489 }
490 
491 
493 
494 
495 static void (*ext_log_fn)(const char *msg) = NULL;
496 
497 
498 static void libcvmfs_log_fn(const LogSource /*source*/,
499  const int /*mask*/,
500  const char *msg) {
501  if (ext_log_fn) {
502  (*ext_log_fn)(msg);
503  }
504 }
505 
506 
507 void cvmfs_set_log_fn(void (*log_fn)(const char *msg)) {
508  ext_log_fn = log_fn;
509  if (log_fn == NULL) {
510  SetAltLogFunc(NULL);
511  } else {
513  }
514 }
515 
516 
518  assert(ctx != NULL);
519  const std::string stats = ctx->mount_point()->statistics()->PrintList(
521  return strdup(stats.c_str());
522 }
523 
524 
526  assert(ctx != NULL);
527  return ctx->Remount();
528 }
529 
530 
532  assert(ctx != NULL);
533  return ctx->GetRevision();
534 }
char * cvm_symlink
Definition: libcvmfs.h:172
int cvmfs_list_nc(LibContext *ctx, const char *path, char ***buf, size_t *buflen)
Definition: libcvmfs.cc:417
uint64_t GetRevision()
struct cvmcache_context * ctx
static LibContext * Create(const std::string &fqrn, OptionsManager *options_mgr)
void EnableMultiThreaded()
void cvmfs_detach_repo(LibContext *ctx)
Definition: libcvmfs.cc:477
char * cvm_name
Definition: libcvmfs.h:174
char * mountpoint
Definition: libcvmfs.h:117
NameString GetFileName(const PathString &path)
Definition: shortstring.cc:28
int GetNestedCatalogAttr(const char *c_path, struct cvmfs_nc_attr *nc_attr)
int cvmfs_listdir_contents(LibContext *ctx, const char *path, char ***buf, size_t *listlen, size_t *buflen)
Definition: libcvmfs.cc:354
void cvmfs_fini()
Definition: libcvmfs.cc:492
perf::Statistics * statistics()
Definition: mountpoint.h:538
void cvmfs_attr_free(struct cvmfs_attr *attr)
Definition: libcvmfs.cc:52
struct cvmfs_nc_attr * cvmfs_nc_attr_init()
Definition: libcvmfs.cc:64
std::string fqrn() const
Definition: mountpoint.h:518
cvmfs_errors cvmfs_init_v2(SimpleOptionsParser *opts)
Definition: libcvmfs.cc:480
int cvmfs_stat_attr(LibContext *ctx, const char *path, struct cvmfs_attr *attr)
Definition: libcvmfs.cc:313
int Close(int fd)
int cvmfs_stat_nc(LibContext *ctx, const char *path, struct cvmfs_nc_attr *nc_attr)
Definition: libcvmfs.cc:397
assert((mem||(size==0))&&"Out Of Memory")
static int expand_path(const int depth, LibContext *ctx, char const *path, string *expanded_path)
Definition: libcvmfs.cc:85
char * cvm_parent
Definition: libcvmfs.h:173
void SetAltLogFunc(void(*fn)(const LogSource source, const int mask, const char *msg))
Definition: logging.cc:407
int GetAttr(const char *c_path, struct stat *info)
void set_options_mgr(OptionsManager *value)
Definition: libcvmfs_int.h:120
int GetExtAttr(const char *c_path, struct cvmfs_attr *info)
char * cvmfs_statistics_format(cvmfs_context *ctx)
Definition: libcvmfs.cc:517
uint64_t cvmfs_get_revision(LibContext *ctx)
Definition: libcvmfs.cc:531
void SwitchTemplateManager(OptionsTemplateManager *opt_templ_mgr_param)
Definition: options.cc:91
char * cvm_checksum
Definition: libcvmfs.h:171
char * hash
Definition: libcvmfs.h:118
void cvmfs_list_free(char **buf)
Definition: libcvmfs.cc:438
int cvmfs_listdir_stat(LibContext *ctx, const char *path, struct cvmfs_stat_t **buf, size_t *listlen, size_t *buflen)
Definition: libcvmfs.cc:375
void cvmfs_enable_threaded(LibContext *ctx)
Definition: libcvmfs.cc:452
void * cvm_xattrs
Definition: libcvmfs.h:175
int64_t Pread(int fd, void *buf, uint64_t size, uint64_t off)
static loader::Failures Initialize(OptionsManager *options_mgr)
Definition: libcvmfs_int.cc:96
int ListNestedCatalogs(const char *path, char ***buf, size_t *buflen)
int cvmfs_stat(LibContext *ctx, const char *path, struct stat *st)
Definition: libcvmfs.cc:277
static void(* ext_log_fn)(const char *msg)
Definition: libcvmfs.cc:495
cvmfs_errors cvmfs_attach_repo_v2(const char *fqrn, SimpleOptionsParser *opts, LibContext **ctx)
Definition: libcvmfs.cc:454
static void cvmfs_open(fuse_req_t req, fuse_ino_t ino, struct fuse_file_info *fi)
Definition: cvmfs.cc:1118
int cvmfs_lstat(LibContext *ctx, const char *path, struct stat *st)
Definition: libcvmfs.cc:295
LogSource
int cvmfs_listdir(LibContext *ctx, const char *path, char ***buf, size_t *buflen)
Definition: libcvmfs.cc:333
void cvmfs_nc_attr_free(struct cvmfs_nc_attr *nc_attr)
Definition: libcvmfs.cc:70
static void cvmfs_readlink(fuse_req_t req, fuse_ino_t ino)
Definition: cvmfs.cc:827
Failures
Definition: loader.h:27
int ListDirectoryStat(const char *c_path, cvmfs_stat_t **buf, size_t *listlen, size_t *buflen)
static LibGlobals * GetInstance()
Definition: libcvmfs_int.cc:87
int Open(const char *c_path)
MountPoint * mount_point()
Definition: libcvmfs_int.h:119
int ListDirectory(const char *path, char ***buf, size_t *listlen, size_t *buflen, bool self_reference)
ssize_t cvmfs_pread(LibContext *ctx, int fd, void *buf, size_t size, off_t off)
Definition: libcvmfs.cc:238
std::string PrintList(const PrintOptions print_options)
Definition: statistics.cc:80
PathString GetParentPath(const PathString &path)
Definition: shortstring.cc:14
unsigned version
Definition: libcvmfs.h:152
uint64_t size
Definition: libcvmfs.h:153
int Readlink(const char *path, char *buf, size_t size)
int cvmfs_close(LibContext *ctx, int fd)
Definition: libcvmfs.cc:249
int cvmfs_remount(LibContext *ctx)
Definition: libcvmfs.cc:525
static int expand_ppath(LibContext *ctx, const char *path, string *expanded_path)
Definition: libcvmfs.cc:197
static void size_t size
Definition: smalloc.h:54
struct cvmfs_attr * cvmfs_attr_init()
Definition: libcvmfs.cc:39
static void CleanupInstance()
void cvmfs_set_log_fn(void(*log_fn)(const char *msg))
Definition: libcvmfs.cc:507
void cvmfs_adopt_options(cvmfs_context *ctx, SimpleOptionsParser *opts)
Definition: libcvmfs.cc:472
static void libcvmfs_log_fn(const LogSource, const int, const char *msg)
Definition: libcvmfs.cc:498
cvmfs_errors
Definition: libcvmfs.h:78
CVMFS_EXPORT void LogCvmfs(const LogSource source, const int mask, const char *format,...)
Definition: logging.cc:545