CernVM-FS  2.12.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 #include "cvmfs_config.h"
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 {
41  struct cvmfs_attr *attr;
42  attr = reinterpret_cast<cvmfs_attr *>(calloc(1, sizeof(*attr)));
43  attr->version = 1;
44  attr->size = sizeof(*attr);
45  return attr;
46 }
47 
48 
53 void cvmfs_attr_free(struct cvmfs_attr *attr)
54 {
55  if (attr) {
56  free(attr->cvm_checksum);
57  free(attr->cvm_symlink);
58  free(attr->cvm_name);
59  free(attr->cvm_parent);
60  delete reinterpret_cast<XattrList *>(attr->cvm_xattrs);
61  }
62  free(attr);
63 }
64 
65 
67 {
68  struct cvmfs_nc_attr *attr;
69  attr = reinterpret_cast<cvmfs_nc_attr *>(calloc(1, sizeof(*attr)));
70  return attr;
71 }
72 
73 void cvmfs_nc_attr_free(struct cvmfs_nc_attr *nc_attr)
74 {
75  if (nc_attr) {
76  free(nc_attr->mountpoint);
77  free(nc_attr->hash);
78  }
79  free(nc_attr);
80 }
81 
82 
89 static int expand_path(
90  const int depth,
91  LibContext *ctx,
92  char const *path,
93  string *expanded_path)
94 {
95  string p_path = GetParentPath(path);
96  string fname = GetFileName(path);
97  int rc;
98 
99  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
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  string buf;
120  if (p_path != "") {
121  rc = expand_path(depth, ctx, p_path.c_str(), &buf);
122  if (rc != 0) {
123  return -1;
124  }
125 
126  if (fname == ".") {
127  *expanded_path = buf;
128  return 0;
129  }
130  }
131 
132  if (buf.length() == 0 || buf[buf.length()-1] != '/') {
133  buf += "/";
134  }
135  buf += fname;
136 
137  struct stat st;
138  rc = ctx->GetAttr(buf.c_str(), &st);
139  if (rc != 0) {
140  errno = -rc;
141  return -1;
142  }
143 
144  if (!S_ISLNK(st.st_mode)) {
145  *expanded_path = buf;
146  return 0;
147  }
148 
149  if (depth > 1000) {
150  // avoid unbounded recursion due to symlinks
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 {
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 }
199 
204  const char *path,
205  string *expanded_path)
206 {
207  string p_path = GetParentPath(path);
208  string fname = GetFileName(path);
209 
210  if (p_path == "") {
211  *expanded_path = path;
212  return 0;
213  }
214 
215  int rc = expand_path(0, ctx, p_path.c_str(), expanded_path);
216  if (rc != 0) {
217  return rc;
218  }
219 
220  (*expanded_path) += "/";
221  (*expanded_path) += fname;
222 
223  return 0;
224 }
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 
262 {
263  int rc = ctx->Close(fd);
264  if (rc < 0) {
265  errno = -rc;
266  return -1;
267  }
268  return 0;
269 }
270 
271 
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 int cvmfs_stat(LibContext *ctx, const char *path, struct stat *st) {
296  string lpath;
297  int rc;
298  rc = expand_path(0, 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 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 
332  LibContext *ctx,
333  const char *path,
334  struct cvmfs_attr *attr
335 ) {
336  string lpath;
337  int rc;
338  rc = expand_ppath(ctx, path, &lpath);
339  if (rc < 0) {
340  return -1;
341  }
342  path = lpath.c_str();
343 
344  rc = ctx->GetExtAttr(path, attr);
345  if (rc < 0) {
346  errno = -rc;
347  return -1;
348  }
349  return 0;
350 }
351 
352 
354  LibContext *ctx,
355  const char *path,
356  char ***buf,
357  size_t *buflen
358 ) {
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  size_t listsize = 0;
368  rc = ctx->ListDirectory(path, buf, &listsize, buflen, true);
369  if (rc < 0) {
370  errno = -rc;
371  return -1;
372  }
373  return 0;
374 }
375 
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 
400  LibContext *ctx,
401  const char *path,
402  struct cvmfs_stat_t **buf,
403  size_t *listlen,
404  size_t *buflen
405 ) {
406  string lpath;
407  int rc;
408  rc = expand_path(0, ctx, path, &lpath);
409  if (rc < 0) {
410  return -1;
411  }
412  path = lpath.c_str();
413 
414  rc = ctx->ListDirectoryStat(path, buf, listlen, buflen);
415  if (rc < 0) {
416  errno = -rc;
417  return -1;
418  }
419  return 0;
420 }
421 
422 
423 
425  LibContext *ctx,
426  const char *path,
427  struct cvmfs_nc_attr *nc_attr
428 ) {
429  string lpath;
430  int rc;
431  rc = expand_path(0, ctx, path, &lpath);
432  if (rc < 0) {
433  return -1;
434  }
435  path = lpath.c_str();
436 
437  rc = ctx->GetNestedCatalogAttr(path, nc_attr);
438  if (rc < 0) {
439  errno = -rc;
440  return -1;
441  }
442  return 0;
443 }
444 
445 
447  LibContext *ctx,
448  const char *path,
449  char ***buf,
450  size_t *buflen
451 ) {
452  string lpath;
453  int rc;
454  rc = expand_path(0, ctx, path, &lpath);
455  if (rc < 0) {
456  return -1;
457  }
458  path = lpath.c_str();
459 
460  rc = ctx->ListNestedCatalogs(path, buf, buflen);
461  if (rc < 0) {
462  errno = -rc;
463  return -1;
464  }
465  return 0;
466 }
467 
468 
469 void cvmfs_list_free(char **buf)
470 {
471  // Quick return if base pointer is NULL
472  if (!buf) return;
473  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  while (buf[pos]) {
477  free(buf[pos]);
478  pos++;
479  }
480  free(buf);
481 }
482 
484  LibContext *ctx
485 ) {
486  ctx->EnableMultiThreaded();
487 }
488 
490  const char *fqrn,
491  SimpleOptionsParser *opts,
492  LibContext **ctx)
493 {
494  assert(ctx != NULL);
496  *ctx = LibContext::Create(fqrn, opts);
497  assert(*ctx != NULL);
498  loader::Failures result = (*ctx)->mount_point()->boot_status();
499  if (result != loader::kFailOk) {
500  LogCvmfs(kLogCvmfs, kLogStderr, "Attaching %s failed: %s (%d)",
501  fqrn, (*ctx)->mount_point()->boot_error().c_str(), result);
502  delete *ctx;
503  *ctx = NULL;
504  }
505  return static_cast<cvmfs_errors>(result);
506 }
507 
508 
510  ctx->set_options_mgr(opts);
511 }
512 
513 
515  delete ctx;
516 }
517 
518 
520  int result = LibGlobals::Initialize(opts);
521  if (result != loader::kFailOk) {
522  LogCvmfs(kLogCvmfs, kLogStderr, "Initialization failed: %s (%d)",
523  LibGlobals::GetInstance()->file_system()->boot_error().c_str(),
524  result);
526  }
527  return static_cast<cvmfs_errors>(result);
528 }
529 
530 
531 void cvmfs_fini() {
533 }
534 
535 
536 static void (*ext_log_fn)(const char *msg) = NULL;
537 
538 
539 static void libcvmfs_log_fn(
540  const LogSource /*source*/,
541  const int /*mask*/,
542  const char *msg
543 ) {
544  if (ext_log_fn) {
545  (*ext_log_fn)(msg);
546  }
547 }
548 
549 
550 void cvmfs_set_log_fn(void (*log_fn)(const char *msg))
551 {
552  ext_log_fn = log_fn;
553  if (log_fn == NULL) {
554  SetAltLogFunc(NULL);
555  } else {
557  }
558 }
559 
560 
562  assert(ctx != NULL);
563  std::string stats = ctx->mount_point()->statistics()
565  return strdup(stats.c_str());
566 }
567 
568 
570  assert(ctx != NULL);
571  return ctx->Remount();
572 }
573 
574 
576  assert(ctx != NULL);
577  return ctx->GetRevision();
578 }
char * cvm_symlink
Definition: libcvmfs.h:172
int cvmfs_list_nc(LibContext *ctx, const char *path, char ***buf, size_t *buflen)
Definition: libcvmfs.cc:446
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:514
char * cvm_name
Definition: libcvmfs.h:174
char * mountpoint
Definition: libcvmfs.h:117
NameString GetFileName(const PathString &path)
Definition: shortstring.cc:29
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:376
void cvmfs_fini()
Definition: libcvmfs.cc:531
perf::Statistics * statistics()
Definition: mountpoint.h:534
void cvmfs_attr_free(struct cvmfs_attr *attr)
Definition: libcvmfs.cc:53
struct cvmfs_nc_attr * cvmfs_nc_attr_init()
Definition: libcvmfs.cc:66
std::string fqrn() const
Definition: mountpoint.h:512
cvmfs_errors cvmfs_init_v2(SimpleOptionsParser *opts)
Definition: libcvmfs.cc:519
int cvmfs_stat_attr(LibContext *ctx, const char *path, struct cvmfs_attr *attr)
Definition: libcvmfs.cc:331
int Close(int fd)
int cvmfs_stat_nc(LibContext *ctx, const char *path, struct cvmfs_nc_attr *nc_attr)
Definition: libcvmfs.cc:424
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:89
char * cvm_parent
Definition: libcvmfs.h:173
void SetAltLogFunc(void(*fn)(const LogSource source, const int mask, const char *msg))
Definition: logging.cc:408
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:561
uint64_t cvmfs_get_revision(LibContext *ctx)
Definition: libcvmfs.cc:575
void SwitchTemplateManager(OptionsTemplateManager *opt_templ_mgr_param)
Definition: options.cc:92
char * cvm_checksum
Definition: libcvmfs.h:171
char * hash
Definition: libcvmfs.h:118
void cvmfs_list_free(char **buf)
Definition: libcvmfs.cc:469
int cvmfs_listdir_stat(LibContext *ctx, const char *path, struct cvmfs_stat_t **buf, size_t *listlen, size_t *buflen)
Definition: libcvmfs.cc:399
void cvmfs_enable_threaded(LibContext *ctx)
Definition: libcvmfs.cc:483
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:94
int ListNestedCatalogs(const char *path, char ***buf, size_t *buflen)
int cvmfs_stat(LibContext *ctx, const char *path, struct stat *st)
Definition: libcvmfs.cc:295
static void(* ext_log_fn)(const char *msg)
Definition: libcvmfs.cc:536
cvmfs_errors cvmfs_attach_repo_v2(const char *fqrn, SimpleOptionsParser *opts, LibContext **ctx)
Definition: libcvmfs.cc:489
static void cvmfs_open(fuse_req_t req, fuse_ino_t ino, struct fuse_file_info *fi)
Definition: cvmfs.cc:1119
int cvmfs_lstat(LibContext *ctx, const char *path, struct stat *st)
Definition: libcvmfs.cc:313
LogSource
int cvmfs_listdir(LibContext *ctx, const char *path, char ***buf, size_t *buflen)
Definition: libcvmfs.cc:353
void cvmfs_nc_attr_free(struct cvmfs_nc_attr *nc_attr)
Definition: libcvmfs.cc:73
static void cvmfs_readlink(fuse_req_t req, fuse_ino_t ino)
Definition: cvmfs.cc:826
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:85
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:245
std::string PrintList(const PrintOptions print_options)
Definition: statistics.cc:79
PathString GetParentPath(const PathString &path)
Definition: shortstring.cc:15
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:261
int cvmfs_remount(LibContext *ctx)
Definition: libcvmfs.cc:569
static int expand_ppath(LibContext *ctx, const char *path, string *expanded_path)
Definition: libcvmfs.cc:203
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:550
void cvmfs_adopt_options(cvmfs_context *ctx, SimpleOptionsParser *opts)
Definition: libcvmfs.cc:509
static void libcvmfs_log_fn(const LogSource, const int, const char *msg)
Definition: libcvmfs.cc:539
cvmfs_errors
Definition: libcvmfs.h:78
CVMFS_EXPORT void LogCvmfs(const LogSource source, const int mask, const char *format,...)
Definition: logging.cc:528