CernVM-FS  2.12.0
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
loader.cc
Go to the documentation of this file.
1 
12 #define ENOATTR ENODATA
13 #define _FILE_OFFSET_BITS 64
14 
15 #include "cvmfs_config.h"
16 #include "loader.h"
17 
18 #include <dlfcn.h>
19 #include <errno.h>
20 #include <fcntl.h>
21 #include <sched.h>
22 #include <signal.h>
23 #include <stddef.h>
24 #include <sys/resource.h>
25 #include <time.h>
26 #include <unistd.h>
27 // If valgrind headers are present on the build system, then we can detect
28 // valgrind at runtime.
29 #ifdef HAS_VALGRIND_HEADERS
30 #include <valgrind/valgrind.h>
31 #endif
32 
33 #include <cassert>
34 #include <cstdlib>
35 #include <cstring>
36 #include <string>
37 #include <vector>
38 
39 #include "duplex_fuse.h"
40 #include "fence.h"
41 #include "fuse_main.h"
42 #include "loader_talk.h"
43 #include "options.h"
44 #include "sanitizer.h"
45 #include "util/atomic.h"
46 #include "util/exception.h"
47 #include "util/logging.h"
48 #include "util/platform.h"
49 #include "util/posix.h"
50 #include "util/string.h"
51 
52 using namespace std; // NOLINT
53 
54 namespace loader {
55 
56 // Follow the fuse convention for option parsing
57 struct CvmfsOptions {
58  char *config;
59  int uid;
60  int gid;
68 
69  // Ignored options
71  int ign_user;
73  int ign_users;
74  int ign_auto;
77 };
78 
79 enum {
87 };
88 #define CVMFS_OPT(t, p, v) { t, offsetof(struct CvmfsOptions, p), v }
89 #define CVMFS_SWITCH(t, p) { t, offsetof(struct CvmfsOptions, p), 1 }
90 static struct fuse_opt cvmfs_array_opts[] = {
91  CVMFS_OPT("config=%s", config, 0),
92  CVMFS_OPT("uid=%d", uid, 0),
93  CVMFS_OPT("gid=%d", gid, 0),
94  CVMFS_SWITCH("system_mount", system_mount),
95  CVMFS_SWITCH("grab_mountpoint", grab_mountpoint),
96  CVMFS_SWITCH("cvmfs_suid", cvmfs_suid),
97  CVMFS_SWITCH("disable_watchdog", disable_watchdog),
98  CVMFS_SWITCH("simple_options_parsing", simple_options_parsing),
99  CVMFS_SWITCH("foreground", foreground),
100  CVMFS_SWITCH("fuse_debug", fuse_debug),
101 
102  // Ignore these options
103  CVMFS_SWITCH("_netdev", ign_netdev),
104  CVMFS_SWITCH("user", ign_user),
105  CVMFS_SWITCH("nouser", ign_nouser),
106  CVMFS_SWITCH("users", ign_users),
107  CVMFS_SWITCH("auto", ign_auto),
108  CVMFS_SWITCH("noauto", ign_noauto),
109  CVMFS_OPT("libfuse=%d", ign_libfuse, 0),
110 
111  FUSE_OPT_KEY("-V", KEY_VERSION),
112  FUSE_OPT_KEY("--version", KEY_VERSION),
113  FUSE_OPT_KEY("-h", KEY_HELP),
114  FUSE_OPT_KEY("--help", KEY_HELP),
115  FUSE_OPT_KEY("-f", KEY_FOREGROUND),
116  FUSE_OPT_KEY("-d", KEY_FUSE_DEBUG),
117  FUSE_OPT_KEY("debug", KEY_CVMFS_DEBUG),
118  FUSE_OPT_KEY("-s", KEY_SINGLETHREAD),
119  FUSE_OPT_KEY("parse", KEY_OPTIONS_PARSE),
120  FUSE_OPT_KEY("-k", KEY_OPTIONS_PARSE),
121  {0, 0, 0},
122 };
123 
124 
125 string *repository_name_ = NULL;
126 string *mount_point_ = NULL;
127 string *config_files_ = NULL;
128 string *socket_path_ = NULL;
129 string *usyslog_path_ = NULL;
132 uid_t uid_ = 0;
133 gid_t gid_ = 0;
134 bool single_threaded_ = false;
135 bool foreground_ = false;
136 bool debug_mode_ = false;
137 bool system_mount_ = false;
138 bool grab_mountpoint_ = false;
139 bool parse_options_only_ = false;
140 bool suid_mode_ = false;
141 bool premounted_ = false;
142 bool disable_watchdog_ = false;
148 
149 
150 static void Usage(const string &exename) {
152  "The CernVM File System\n"
153  "Version %s\n"
154  "Copyright (c) 2009- CERN, all rights reserved\n\n"
155  "Please visit http://cernvm.cern.ch for details.\n\n"
156  "Usage: %s [-h] [-V] [-s] [-f] [-d] [-k] [-o mount options] "
157  "<repository name> <mount point>\n\n"
158  "CernVM-FS general options:\n"
159  " --help|-h Print Help output (this)\n"
160  " --version|-V Print CernVM-FS version\n"
161  " -s Run singlethreaded\n"
162  " -f Run in foreground\n"
163  " -d Enable debugging\n"
164  " -k Parse options\n"
165  "CernVM-FS mount options:\n"
166  " -o config=FILES colon-separated path list of config files\n"
167  " -o uid=UID Drop credentials to another user\n"
168  " -o gid=GID Drop credentials to another group\n"
169  " -o system_mount Indicate that mount is system-wide\n"
170  " -o grab_mountpoint give ownership of the mountpoint to the user "
171  "before mounting (required for autofs)\n"
172  " -o parse Parse and print cvmfs parameters\n"
173  " -o cvmfs_suid Enable suid mode\n\n"
174  " -o disable_watchdog Do not spawn a post mortem crash handler\n"
175  " -o foreground Run in foreground\n"
176  " -o libfuse=[2,3] Enforce a certain libfuse version\n"
177  "Fuse mount options:\n"
178  " -o allow_other allow access to other users\n"
179  " -o allow_root allow access to root\n"
180  " -o nonempty allow mounts over non-empty directory\n",
181  PACKAGE_VERSION, exename.c_str());
182 }
183 
188 bool CheckPremounted(const std::string &mountpoint) {
189  int len;
190  unsigned fd;
191  bool retval = (sscanf(mountpoint.c_str(), "/dev/fd/%u%n", &fd, &len) == 1) &&
192  (len >= 0) &&
193  (static_cast<unsigned>(len) == mountpoint.length());
194  if (retval) {
196  "CernVM-FS: pre-mounted on file descriptor %d", fd);
197  return true;
198  }
199  return false;
200 }
201 
202 
203 static void stub_init(void *userdata, struct fuse_conn_info *conn) {
204  FenceGuard fence_guard(fence_reload_);
205  cvmfs_exports_->cvmfs_operations.init(userdata, conn);
206 }
207 
208 
209 static void stub_destroy(void *userdata) {
210  FenceGuard fence_guard(fence_reload_);
211  cvmfs_exports_->cvmfs_operations.destroy(userdata);
212 }
213 
214 
215 static void stub_lookup(fuse_req_t req, fuse_ino_t parent,
216  const char *name)
217 {
218  FenceGuard fence_guard(fence_reload_);
219  cvmfs_exports_->cvmfs_operations.lookup(req, parent, name);
220 }
221 
222 
223 static void stub_getattr(fuse_req_t req, fuse_ino_t ino,
224  struct fuse_file_info *fi)
225 {
226  FenceGuard fence_guard(fence_reload_);
227  cvmfs_exports_->cvmfs_operations.getattr(req, ino, fi);
228 }
229 
230 
231 static void stub_readlink(fuse_req_t req, fuse_ino_t ino) {
232  FenceGuard fence_guard(fence_reload_);
233  cvmfs_exports_->cvmfs_operations.readlink(req, ino);
234 }
235 
236 
237 static void stub_opendir(fuse_req_t req, fuse_ino_t ino,
238  struct fuse_file_info *fi)
239 {
240  FenceGuard fence_guard(fence_reload_);
241  cvmfs_exports_->cvmfs_operations.opendir(req, ino, fi);
242 }
243 
244 
245 static void stub_releasedir(fuse_req_t req, fuse_ino_t ino,
246  struct fuse_file_info *fi)
247 {
248  FenceGuard fence_guard(fence_reload_);
249  cvmfs_exports_->cvmfs_operations.releasedir(req, ino, fi);
250 }
251 
252 
253 static void stub_readdir(fuse_req_t req, fuse_ino_t ino, size_t size,
254  off_t off, struct fuse_file_info *fi)
255 {
256  FenceGuard fence_guard(fence_reload_);
257  cvmfs_exports_->cvmfs_operations.readdir(req, ino, size, off, fi);
258 }
259 
260 
261 static void stub_open(fuse_req_t req, fuse_ino_t ino,
262  struct fuse_file_info *fi)
263 {
264  FenceGuard fence_guard(fence_reload_);
265  cvmfs_exports_->cvmfs_operations.open(req, ino, fi);
266 }
267 
268 
269 static void stub_read(fuse_req_t req, fuse_ino_t ino, size_t size, off_t off,
270  struct fuse_file_info *fi)
271 {
272  FenceGuard fence_guard(fence_reload_);
273  cvmfs_exports_->cvmfs_operations.read(req, ino, size, off, fi);
274 }
275 
276 
277 static void stub_release(fuse_req_t req, fuse_ino_t ino,
278  struct fuse_file_info *fi)
279 {
280  FenceGuard fence_guard(fence_reload_);
281  cvmfs_exports_->cvmfs_operations.release(req, ino, fi);
282 }
283 
284 
285 static void stub_statfs(fuse_req_t req, fuse_ino_t ino) {
286  FenceGuard fence_guard(fence_reload_);
287  cvmfs_exports_->cvmfs_operations.statfs(req, ino);
288 }
289 
290 
291 #ifdef __APPLE__
292 static void stub_getxattr(fuse_req_t req, fuse_ino_t ino, const char *name,
293  size_t size, uint32_t position)
294 #else
295 static void stub_getxattr(fuse_req_t req, fuse_ino_t ino, const char *name,
296  size_t size)
297 #endif
298 {
299  FenceGuard fence_guard(fence_reload_);
300 #ifdef __APPLE__
301  cvmfs_exports_->cvmfs_operations.getxattr(req, ino, name, size, position);
302 #else
303  cvmfs_exports_->cvmfs_operations.getxattr(req, ino, name, size);
304 #endif
305 }
306 
307 
308 static void stub_listxattr(fuse_req_t req, fuse_ino_t ino, size_t size) {
309  FenceGuard fence_guard(fence_reload_);
310  cvmfs_exports_->cvmfs_operations.listxattr(req, ino, size);
311 }
312 
313 
314 static void stub_forget(
315  fuse_req_t req,
316  fuse_ino_t ino,
317 #if CVMFS_USE_LIBFUSE == 2
318  unsigned long nlookup // NOLINT
319 #else
320  uint64_t nlookup
321 #endif
322 ) {
323  FenceGuard fence_guard(fence_reload_);
324  cvmfs_exports_->cvmfs_operations.forget(req, ino, nlookup);
325 }
326 
327 
328 #if (FUSE_VERSION >= 29)
329 static void stub_forget_multi(
330  fuse_req_t req,
331  size_t count,
332  struct fuse_forget_data *forgets
333 ) {
334  FenceGuard fence_guard(fence_reload_);
335  cvmfs_exports_->cvmfs_operations.forget_multi(req, count, forgets);
336 }
337 #endif
338 
339 
346 static int ParseFuseOptions(void *data __attribute__((unused)), const char *arg,
347  int key, struct fuse_args *outargs)
348 {
349  unsigned arglen = 0;
350  if (arg)
351  arglen = strlen(arg);
352  switch (key) {
353  case FUSE_OPT_KEY_OPT:
354  // Check if it a cvmfs option
355  if ((arglen > 0) && (arg[0] != '-')) {
356  const char **o;
357  for (o = (const char**)cvmfs_array_opts; *o; o++) {
358  unsigned olen = strlen(*o);
359  if ((arglen > olen && arg[olen] == '=') &&
360  (strncasecmp(arg, *o, olen) == 0))
361  return 0;
362  }
363  }
364  return 1;
365 
366  case FUSE_OPT_KEY_NONOPT:
367  // first: repository name, second: mount point
368  assert(arg != NULL);
369  if (!repository_name_) {
370  repository_name_ = new string(arg);
371  } else {
372  if (mount_point_)
373  return 1;
374  mount_point_ = new string(arg);
376  }
377  return 0;
378 
379  case KEY_HELP:
380  Usage(outargs->argv[0]);
381  exit(0);
382  case KEY_VERSION:
383  LogCvmfs(kLogCvmfs, kLogStdout, "CernVM-FS version %s\n",
384  PACKAGE_VERSION);
385  exit(0);
386  case KEY_FOREGROUND:
387  foreground_ = true;
388  return 0;
389  case KEY_SINGLETHREAD:
390  single_threaded_ = true;
391  return 0;
392  case KEY_FUSE_DEBUG:
393  fuse_opt_add_arg(outargs, "-d");
394  case KEY_CVMFS_DEBUG:
395  debug_mode_ = true;
396  return 0;
397  case KEY_OPTIONS_PARSE:
398  parse_options_only_ = true;
399  return 0;
400  default:
401  PANIC(kLogStderr, "internal option parsing error");
402  }
403 }
404 
405 static fuse_args *ParseCmdLine(int argc, char *argv[]) {
406  struct fuse_args *mount_options = new fuse_args();
408  memset(&cvmfs_options, 0, sizeof(cvmfs_options));
409 
410  mount_options->argc = argc;
411  mount_options->argv = argv;
412  mount_options->allocated = 0;
413  if ((fuse_opt_parse(mount_options, &cvmfs_options, cvmfs_array_opts,
414  ParseFuseOptions) != 0) ||
416  {
417  delete mount_options;
418  return NULL;
419  }
420  if (cvmfs_options.config) {
421  config_files_ = new string(cvmfs_options.config);
422  free(cvmfs_options.config);
423  }
424  uid_ = cvmfs_options.uid;
425  gid_ = cvmfs_options.gid;
426  system_mount_ = cvmfs_options.system_mount;
427  grab_mountpoint_ = cvmfs_options.grab_mountpoint;
428  suid_mode_ = cvmfs_options.cvmfs_suid;
429  disable_watchdog_ = cvmfs_options.disable_watchdog;
431  if (cvmfs_options.foreground) {
432  foreground_ = true;
433  }
434  if (cvmfs_options.fuse_debug) {
435  fuse_opt_add_arg(mount_options, "-d");
436  }
437 
438  return mount_options;
439 }
440 
441 
442 static void SetFuseOperations(struct fuse_lowlevel_ops *loader_operations) {
443  memset(loader_operations, 0, sizeof(*loader_operations));
444 
445  loader_operations->init = stub_init;
446  loader_operations->destroy = stub_destroy;
447 
448  loader_operations->lookup = stub_lookup;
449  loader_operations->getattr = stub_getattr;
450  loader_operations->readlink = stub_readlink;
451  loader_operations->open = stub_open;
452  loader_operations->read = stub_read;
453  loader_operations->release = stub_release;
454  loader_operations->opendir = stub_opendir;
455  loader_operations->readdir = stub_readdir;
456  loader_operations->releasedir = stub_releasedir;
457  loader_operations->statfs = stub_statfs;
458  loader_operations->getxattr = stub_getxattr;
459  loader_operations->listxattr = stub_listxattr;
460  loader_operations->forget = stub_forget;
461 }
462 
463 
464 static void *OpenLibrary(const string &path) {
465  return dlopen(path.c_str(), RTLD_NOW | RTLD_LOCAL);
466 }
467 
468 
469 static void CloseLibrary() {
470 #ifdef HAS_VALGRIND_HEADERS
471  // If the libcvmfs_fuse library is unloaded, valgrind can't resolve the
472  // symbols anymore. We skip under valgrind.
473  if (!RUNNING_ON_VALGRIND) {
474 #endif
475  dlclose(library_handle_);
476  library_handle_ = NULL;
477 #ifdef HAS_VALGRIND_HEADERS
478  }
479 #endif
480 }
481 
482 
483 static CvmfsExports *LoadLibrary(const bool debug_mode,
484  LoaderExports *loader_exports)
485 {
486  std::string local_lib_path = "./";
487  if (getenv("CVMFS_LIBRARY_PATH") != NULL) {
488  local_lib_path = getenv("CVMFS_LIBRARY_PATH");
489  if (!local_lib_path.empty() && (*local_lib_path.rbegin() != '/'))
490  local_lib_path.push_back('/');
491  }
492 
493 #if CVMFS_USE_LIBFUSE == 2
494  string library_name = string("cvmfs_fuse") + ((debug_mode) ? "_debug" : "");
495 #else
496  string library_name = string("cvmfs_fuse3") + ((debug_mode) ? "_debug" : "");
497 #endif
498  library_name = platform_libname(library_name);
499  string error_messages;
500 
501  vector<string> library_paths; // TODO(rmeusel): C++11 initializer
502  if (library_paths.empty()) {
503  library_paths.push_back(local_lib_path + library_name);
504  library_paths.push_back("/usr/lib/" + library_name);
505  library_paths.push_back("/usr/lib64/" + library_name);
506 #ifdef __APPLE__
507  // Since OS X El Capitan (10.11) came with SIP, we needed to relocate our
508  // binaries from /usr/... to /usr/local/...
509  library_paths.push_back("/usr/local/lib/" + library_name);
510 #endif
511  }
512 
513  vector<string>::const_iterator i = library_paths.begin();
514  vector<string>::const_iterator iend = library_paths.end();
515  for (; i != iend; ++i) { // TODO(rmeusel): C++11 range based for
517  if (library_handle_ != NULL) {
518  break;
519  }
520 
521  error_messages += string(dlerror()) + "\n";
522  }
523 
524  if (!library_handle_) {
526  "failed to load cvmfs library, tried: '%s'\n%s",
527  JoinStrings(library_paths, "' '").c_str(), error_messages.c_str());
528  return NULL;
529  }
530 
531  CvmfsExports **exports_ptr = reinterpret_cast<CvmfsExports **>(
532  dlsym(library_handle_, "g_cvmfs_exports"));
533  if (!exports_ptr)
534  return NULL;
535 
536  if (loader_exports) {
537  LoadEvent *load_event = new LoadEvent();
538  load_event->timestamp = time(NULL);
539  load_event->so_version = (*exports_ptr)->so_version;
540  loader_exports->history.push_back(load_event);
541  }
542 
543  return *exports_ptr;
544 }
545 
546 Failures Reload(const int fd_progress, const bool stop_and_go,
547  const ReloadMode reload_mode) {
548  int retval;
549 
550  // for legacy call we take the current state of debug_mode_
551  if (reload_mode == kReloadDebug) {
552  debug_mode_ = true;
553  } else if (reload_mode == kReloadNoDebug) {
554  debug_mode_ = false;
555  }
556 
557  retval = cvmfs_exports_->fnMaintenanceMode(fd_progress);
558  if (!retval)
559  return kFailMaintenanceMode;
560 
561  SendMsg2Socket(fd_progress, "Blocking new file system calls\n");
562  fence_reload_->Close();
563 
564  SendMsg2Socket(fd_progress, "Waiting for active file system calls\n");
565  fence_reload_->Drain();
566 
567  retval = cvmfs_exports_->fnSaveState(fd_progress,
569  if (!retval)
570  return kFailSaveState;
571 
572  SendMsg2Socket(fd_progress, "Unloading Fuse module\n");
574  CloseLibrary();
575 
576  if (stop_and_go) {
577  CreateFile(*socket_path_ + ".paused", 0600);
578  SendMsg2Socket(fd_progress, "Waiting for the delivery of SIGUSR1...\n");
579  WaitForSignal(SIGUSR1);
580  unlink((*socket_path_ + ".paused").c_str());
581  }
582 
583  SendMsg2Socket(fd_progress, "Re-Loading Fuse module\n");
585  if (!cvmfs_exports_)
586  return kFailLoadLibrary;
588  if (retval != kFailOk) {
589  string msg_progress = cvmfs_exports_->fnGetErrorMsg() + " (" +
590  StringifyInt(retval) + ")\n";
591  LogCvmfs(kLogCvmfs, kLogSyslogErr, "%s", msg_progress.c_str());
592  SendMsg2Socket(fd_progress, msg_progress);
593  return (Failures)retval;
594  }
595 
596  retval = cvmfs_exports_->fnRestoreState(fd_progress,
598  if (!retval)
599  return kFailRestoreState;
601  for (unsigned i = 0, l = loader_exports_->saved_states.size(); i < l; ++i) {
602  delete loader_exports_->saved_states[i];
603  }
604  loader_exports_->saved_states.clear();
605 
606  SendMsg2Socket(fd_progress, "Activating Fuse module\n");
608 
609  fence_reload_->Open();
610  return kFailOk;
611 }
612 
613 } // namespace loader
614 
615 
616 using namespace loader; // NOLINT(build/namespaces)
617 
618 int FuseMain(int argc, char *argv[]) {
619  // Set a decent umask for new files (no write access to group/everyone).
620  // We want to allow group write access for the talk-socket.
621  umask(007);
622  // SIGUSR1 is used for the stop_and_go mode during reload
623  BlockSignal(SIGUSR1);
624 
625  int retval;
626 
627  // Jump into alternative process flavors (e.g. shared cache manager)
628  // We are here due to a fork+execve (ManagedExec in util.cc) or due to
629  // utility calls of cvmfs2
630  if ((argc > 1) && (strstr(argv[1], "__") == argv[1])) {
631  if (string(argv[1]) == string("__RELOAD__")) {
632  if (argc < 3)
633  return 1;
634  bool stop_and_go = false;
635  if ((argc > 3) && (string(argv[3]) == "stop_and_go"))
636  stop_and_go = true;
637 
638  // always last param of the cvmfs2 __RELOAD__ command
639  // check if debug mode is requested
640  // NOTE:
641  // debug mode is decided based on CVMFS_DEBUGLOG being set or not
642  // this means: reloading is now always based on CVMFS_DEBUGLOG, and
643  // reload ignores the current state
644  //
645  // if you mount with debug but do not set CVMFS_DEBUGLOG and reload,
646  // you will reload with
647  if (std::string(argv[argc - 1]) == std::string("--debug")) {
648  debug_mode_ = true;
649  } else {
650  debug_mode_ = false;
651  }
652  retval = loader_talk::MainReload(argv[2], stop_and_go, debug_mode_);
653 
654  if ((retval != 0) && (stop_and_go)) {
655  CreateFile(string(argv[2]) + ".paused.crashed", 0600);
656  }
657  return retval;
658  }
659 
660  if (string(argv[1]) == string("__MK_ALIEN_CACHE__")) {
661  if (argc < 5)
662  return 1;
663  string alien_cache_dir = argv[2];
665  if (!sanitizer.IsValid(argv[3]) || !sanitizer.IsValid(argv[4]))
666  return 1;
667  uid_t uid_owner = String2Uint64(argv[3]);
668  gid_t gid_owner = String2Uint64(argv[4]);
669 
670  int retval = MkdirDeep(alien_cache_dir, 0770);
671  if (!retval) {
672  LogCvmfs(kLogCvmfs, kLogStderr, "Failed to create %s",
673  alien_cache_dir.c_str());
674  return 1;
675  }
676  retval = chown(alien_cache_dir.c_str(), uid_owner, gid_owner);
677  if (retval != 0) {
678  LogCvmfs(kLogCvmfs, kLogStderr, "Failed to set owner of %s to %d:%d",
679  alien_cache_dir.c_str(), uid_owner, gid_owner);
680  return 1;
681  }
682  retval = SwitchCredentials(uid_owner, gid_owner, false);
683  if (!retval) {
684  LogCvmfs(kLogCvmfs, kLogStderr, "Failed to impersonate %d:%d",
685  uid_owner, gid_owner);
686  return 1;
687  }
688  // Allow access to user and group
689  retval = MakeCacheDirectories(alien_cache_dir, 0770);
690  if (!retval) {
691  LogCvmfs(kLogCvmfs, kLogStderr, "Failed to create cache skeleton");
692  return 1;
693  }
694  return 0;
695  }
696 
697  debug_mode_ = getenv("__CVMFS_DEBUG_MODE__") != NULL;
699  if (!cvmfs_exports_)
700  return kFailLoadLibrary;
701  return cvmfs_exports_->fnAltProcessFlavor(argc, argv);
702  }
703 
704  // Option parsing
705  struct fuse_args *mount_options;
706  mount_options = ParseCmdLine(argc, argv);
707  if (!mount_options) {
708  Usage(argv[0]);
709  return kFailOptions;
710  }
711 
712  string parameter;
713  OptionsManager *options_manager;
715  options_manager = new SimpleOptionsParser(
717  } else {
718  options_manager = new BashOptionsManager(
720  }
721  if (config_files_) {
722  vector<string> tokens = SplitString(*config_files_, ':');
723  for (unsigned i = 0, s = tokens.size(); i < s; ++i) {
724  options_manager->ParsePath(tokens[i], false);
725  }
726  } else {
727  options_manager->ParseDefault(*repository_name_);
728  }
729 
730 #ifdef __APPLE__
731  string volname = "-ovolname=" + *repository_name_;
732  fuse_opt_add_arg(mount_options, volname.c_str());
733  // Allow for up to 5 minute "hangs" before OS X may kill cvmfs
734  fuse_opt_add_arg(mount_options, "-odaemon_timeout=300");
735  fuse_opt_add_arg(mount_options, "-onoapplexattr");
736  // Should libfuse be single-threaded? See CVM-871, CVM-855
737  // single_threaded_ = true;
738 #endif
739  if (options_manager->GetValue("CVMFS_MOUNT_RW", &parameter) &&
740  options_manager->IsOn(parameter))
741  {
742  fuse_opt_add_arg(mount_options, "-orw");
743  } else {
744  fuse_opt_add_arg(mount_options, "-oro");
745  }
746  fuse_opt_add_arg(mount_options, "-onodev");
747  if (options_manager->GetValue("CVMFS_SUID", &parameter) &&
748  options_manager->IsOn(parameter))
749  {
750  suid_mode_ = true;
751  }
752  if (suid_mode_) {
753  if (getuid() != 0) {
755  "must be root to mount with suid option");
756  }
757  fuse_opt_add_arg(mount_options, "-osuid");
758  LogCvmfs(kLogCvmfs, kLogStdout, "CernVM-FS: running with suid support");
759  }
760 
761  if (options_manager->GetValue("CVMFS_CPU_AFFINITY", &parameter)) {
762 #ifndef __APPLE__
763  cpu_set_t mask;
764  vector<string> cpus = SplitString(parameter, ',');
765  CPU_ZERO(&mask);
766  for (vector<string>::iterator i = cpus.begin(); i != cpus.end(); i++) {
767  CPU_SET(String2Uint64(Trim(*i)), &mask);
768  }
770  "CernVM-FS: setting CPU Affinity to %s", parameter.c_str());
771  int err = sched_setaffinity(0, sizeof(mask), &mask);
772  if (err != 0) {
774  "Setting CPU Affinity failed with error %d", errno);
775  }
776 #else
778  "CPU affinity setting not supported on macOS");
779 #endif
780  }
782  loader_exports_->loader_version = PACKAGE_VERSION;
783  loader_exports_->boot_time = time(NULL);
784  loader_exports_->program_name = argv[0];
788  loader_exports_->device_id = "0:0"; // initially unknown, set after mount
791  if (config_files_)
793  else
795 
796  if (parse_options_only_) {
797  LogCvmfs(kLogCvmfs, kLogStdout, "# CernVM-FS parameters:\n%s",
798  options_manager->Dump().c_str());
799  return 0;
800  }
801 
802  // Logging
803  if (options_manager->GetValue("CVMFS_SYSLOG_LEVEL", &parameter))
804  SetLogSyslogLevel(String2Uint64(parameter));
805  else
807  if (options_manager->GetValue("CVMFS_SYSLOG_FACILITY", &parameter))
810  // Deferr setting usyslog until credentials are dropped
811 
812  // Permissions check
813  if (options_manager->GetValue("CVMFS_CHECK_PERMISSIONS", &parameter)) {
814  if (options_manager->IsOn(parameter)) {
815  fuse_opt_add_arg(mount_options, "-odefault_permissions");
816  }
817  }
818 
821  "Mount point %s does not exist", mount_point_->c_str());
822  return kFailPermission;
823  }
824 
825  // Number of file descriptors
826  if (options_manager->GetValue("CVMFS_NFILES", &parameter)) {
827  int retval = SetLimitNoFile(String2Uint64(parameter));
828  if (retval == -2) {
829  LogCvmfs(kLogCvmfs, kLogStdout, "CernVM-FS: running under valgrind");
830  } else if (retval == -1) {
831  if (system_mount_) {
833  "Failed to set maximum number of open files, "
834  "insufficient permissions");
835  return kFailPermission;
836  }
837  unsigned soft_limit, hard_limit;
838  GetLimitNoFile(&soft_limit, &hard_limit);
840  "Failed to set requested number of open files, "
841  "using maximum number %u", hard_limit);
842  if (hard_limit > soft_limit) {
843  (void) SetLimitNoFile(hard_limit);
844  }
845  }
846  }
847 
848  // Apply OOM score adjustment
849  if (options_manager->GetValue("CVMFS_OOM_SCORE_ADJ", &parameter)) {
850  string proc_path = "/proc/" + StringifyInt(getpid()) + "/oom_score_adj";
851  int fd_oom = open(proc_path.c_str(), O_WRONLY);
852  if (fd_oom < 0) {
854  "failed to open %s", proc_path.c_str());
855  } else {
856  bool retval = SafeWrite(fd_oom, parameter.data(), parameter.length());
857  if (!retval) {
859  "failed to set OOM score adjustment to %s", parameter.c_str());
860  }
861  close(fd_oom);
862  }
863  }
864 
865  // Protect the process from being killed by systemd
866  if (options_manager->GetValue("CVMFS_SYSTEMD_NOKILL", &parameter) &&
867  options_manager->IsOn(parameter))
868  {
869  argv[0][0] = '@';
870  }
871 
872  // Grab mountpoint
873  if (grab_mountpoint_) {
874  if ((chown(mount_point_->c_str(), uid_, gid_) != 0) ||
875  (chmod(mount_point_->c_str(), 0755) != 0))
876  {
878  "Failed to grab mountpoint %s (%d)",
879  mount_point_->c_str(), errno);
880  return kFailPermission;
881  }
882  }
883 
884  // Drop credentials
885  if ((uid_ != 0) || (gid_ != 0)) {
886  LogCvmfs(kLogCvmfs, kLogStdout, "CernVM-FS: running with credentials %d:%d",
887  uid_, gid_);
888  const bool retrievable = (suid_mode_ || !disable_watchdog_);
889  if (!SwitchCredentials(uid_, gid_, retrievable)) {
891  "Failed to drop credentials");
892  return kFailPermission;
893  }
894  }
895  if (disable_watchdog_) {
896  LogCvmfs(kLogCvmfs, kLogDebug, "No watchdog, enabling core files");
897  prctl(PR_SET_DUMPABLE, 1, 0, 0, 0);
898  }
899 
900  // Only set usyslog now, otherwise file permissions are wrong
901  usyslog_path_ = new string();
902  if (options_manager->GetValue("CVMFS_USYSLOG", &parameter))
903  *usyslog_path_ = parameter;
905 
906  if (single_threaded_) {
908  "CernVM-FS: running in single threaded mode");
909  }
910  if (debug_mode_) {
912  "CernVM-FS: running in debug mode");
913  }
914 
915 #ifndef FUSE_CAP_POSIX_ACL
916  if (options_manager->GetValue("CVMFS_ENFORCE_ACLS", &parameter) &&
917  options_manager->IsOn(parameter))
918  {
920  "CernVM-FS: ACL support requested but not available in this "
921  "version of libfuse");
922  return kFailPermission;
923  }
924 #endif
925 
926  // Initialize the loader socket, connections are not accepted until Spawn()
927  socket_path_ = new string("/var/run/cvmfs");
928  if (options_manager->GetValue("CVMFS_RELOAD_SOCKETS", &parameter))
929  *socket_path_ = MakeCanonicalPath(parameter);
930  *socket_path_ += "/cvmfs." + *repository_name_;
931  retval = loader_talk::Init(*socket_path_);
932  if (!retval) {
934  "Failed to initialize loader socket");
935  return kFailLoaderTalk;
936  }
937 
938  // TODO(jblomer): we probably want to apply a default setting related to the
939  // number of cores.
940  if (options_manager->GetValue("CVMFS_FUSE3_MAX_THREADS", &parameter)) {
941  fuse3_max_threads_ = String2Int64(parameter);
942  }
943  if (options_manager->GetValue("CVMFS_FUSE3_IDLE_THREADS", &parameter)) {
944  fuse3_idle_threads_ = String2Int64(parameter);
945  }
946 #ifdef CVMFS_ENABLE_FUSE3_LOOP_CONFIG
947  if (fuse3_max_threads_) {
949  "CernVM-FS: Fuse3 max_threads=%d", fuse3_max_threads_);
950  }
951  if (fuse3_idle_threads_) {
953  "CernVM-FS: Fuse3 min_idle_threads=%d", fuse3_idle_threads_);
954  }
955 #else
958  "CernVM-FS: ignoring fuse3 thread settings (libfuse too old)");
959  }
960 #endif
961 
962  // Options are not needed anymore
963  delete options_manager;
964  options_manager = NULL;
965 
966  struct fuse_session *session;
967 #if CVMFS_USE_LIBFUSE == 2
968  struct fuse_chan *channel;
969  loader_exports_->fuse_channel_or_session = reinterpret_cast<void **>(
970  &channel);
971 #else
972  loader_exports_->fuse_channel_or_session = reinterpret_cast<void **>(
973  &session);
974 #endif
975 
976  // Load and initialize cvmfs library
978  "CernVM-FS: loading Fuse module... ");
980  if (!cvmfs_exports_) {
981  return kFailLoadLibrary;
982  }
984  if (retval != kFailOk) {
985  if (retval == kFailDoubleMount) {
987  "\nCernVM-FS: repository %s already mounted on %s",
989  loader_exports_->mount_point.c_str());
990  return 0;
991  }
992  LogCvmfs(kLogCvmfs, kLogStderr | kLogSyslogErr, "%s (%d - %s)",
993  cvmfs_exports_->fnGetErrorMsg().c_str(),
994  retval, Code2Ascii((Failures)retval));
996  return retval;
997  }
998  LogCvmfs(kLogCvmfs, kLogStdout, "done");
999 
1000  // Mount
1001  fence_reload_ = new Fence();
1002 
1003  if (suid_mode_) {
1004  const bool retrievable = true;
1005  if (!SwitchCredentials(0, getgid(), retrievable)) {
1007  "failed to re-gain root permissions for mounting");
1009  return kFailPermission;
1010  }
1011  }
1012 
1013 
1014  struct fuse_lowlevel_ops loader_operations;
1015  SetFuseOperations(&loader_operations);
1016 #if (FUSE_VERSION >= 29)
1017  if (cvmfs_exports_->cvmfs_operations.forget_multi)
1018  loader_operations.forget_multi = stub_forget_multi;
1019 #endif
1020 
1021 #if CVMFS_USE_LIBFUSE == 2
1022  channel = fuse_mount(mount_point_->c_str(), mount_options);
1023  if (!channel) {
1025  "failed to create Fuse channel");
1027  return kFailMount;
1028  }
1029 
1030  session = fuse_lowlevel_new(mount_options, &loader_operations,
1031  sizeof(loader_operations), NULL);
1032  if (!session) {
1034  "failed to create Fuse session");
1035  fuse_unmount(mount_point_->c_str(), channel);
1037  return kFailMount;
1038  }
1039 #else
1040  // libfuse3
1041  session = fuse_session_new(mount_options, &loader_operations,
1042  sizeof(loader_operations), NULL);
1043  if (!session) {
1045  "failed to create Fuse session");
1047  return kFailMount;
1048  }
1049  retval = fuse_session_mount(session, mount_point_->c_str());
1050  if (retval != 0) {
1052  "failed to mount file system");
1054  return kFailMount;
1055  }
1056 #endif
1057 
1058  // drop credentials
1059  if (suid_mode_) {
1060  const bool retrievable = !disable_watchdog_;
1061  if (!SwitchCredentials(uid_, gid_, retrievable)) {
1063  "failed to drop permissions after mounting");
1065  return kFailPermission;
1066  }
1067  }
1068 
1069  // Determine device id
1070  int fd_mountinfo = open("/proc/self/mountinfo", O_RDONLY);
1071  if (fd_mountinfo > 0) {
1072  std::string line;
1073  while (GetLineFd(fd_mountinfo, &line)) {
1074  std::vector<std::string> tokens = SplitString(line, ' ');
1075  if (tokens.size() < 5) continue;
1076  if (tokens[4] != loader_exports_->mount_point) continue;
1077  unsigned i = 5;
1078  for (; i < tokens.size(); ++i) {
1079  if (tokens[i] == "-") break;
1080  }
1081  if (tokens.size() < i + 3) continue;
1082  if (tokens[i + 2] != "cvmfs2") continue;
1083  loader_exports_->device_id = tokens[2];
1084  break;
1085  }
1086  close(fd_mountinfo);
1087  }
1088 
1089  if (!premounted_) {
1090  LogCvmfs(kLogCvmfs, kLogStdout, "CernVM-FS: mounted cvmfs on %s",
1091  mount_point_->c_str());
1092  }
1094  "CernVM-FS: linking %s to repository %s",
1095  mount_point_->c_str(), repository_name_->c_str());
1096  if (!foreground_)
1097  Daemonize();
1098 
1101 
1102  SetLogMicroSyslog("");
1103  retval = fuse_set_signal_handlers(session);
1104  assert(retval == 0);
1105 #if CVMFS_USE_LIBFUSE == 2
1106  fuse_session_add_chan(session, channel);
1107 #endif
1108  if (single_threaded_) {
1109  retval = fuse_session_loop(session);
1110  } else {
1111 #if CVMFS_USE_LIBFUSE == 2
1112  retval = fuse_session_loop_mt(session);
1113 #else
1114 #ifdef CVMFS_ENABLE_FUSE3_LOOP_CONFIG
1115  struct fuse_loop_config *fuse_loop_cfg = fuse_loop_cfg_create();
1116 
1117  fuse_loop_cfg_set_clone_fd(fuse_loop_cfg, 1);
1118 
1119  if (fuse3_max_threads_ > 0) {
1120  fuse_loop_cfg_set_max_threads(fuse_loop_cfg, fuse3_max_threads_);
1121  }
1122  if (fuse3_idle_threads_ > 0) {
1123  fuse_loop_cfg_set_idle_threads(fuse_loop_cfg, fuse3_idle_threads_);
1124  }
1125 
1126  retval = fuse_session_loop_mt(session, fuse_loop_cfg);
1127  fuse_loop_cfg_destroy(fuse_loop_cfg);
1128 #else
1129  retval = fuse_session_loop_mt(session, 1 /* use fd per thread */);
1130 #endif // CVMFS_ENABLE_FUSE3_LOOP_CONFIG
1131 #endif // fuse2/3
1132  }
1134 
1137 
1138  // Unmount
1139 #if CVMFS_USE_LIBFUSE == 2
1140  fuse_remove_signal_handlers(session);
1141  fuse_session_remove_chan(channel);
1142  fuse_session_destroy(session);
1143  fuse_unmount(mount_point_->c_str(), channel);
1144  channel = NULL;
1145 #else
1146  // libfuse3
1147  fuse_remove_signal_handlers(session);
1148  fuse_session_unmount(session);
1149  fuse_session_destroy(session);
1150 #endif
1151  fuse_opt_free_args(mount_options);
1152  delete mount_options;
1153  session = NULL;
1154  mount_options = NULL;
1155 
1156  CloseLibrary();
1157 
1158  LogCvmfs(kLogCvmfs, kLogSyslog, "CernVM-FS: unmounted %s (%s)",
1159  mount_point_->c_str(), repository_name_->c_str());
1160 
1161  delete fence_reload_;
1162  delete loader_exports_;
1163  delete config_files_;
1164  delete repository_name_;
1165  delete mount_point_;
1166  delete socket_path_;
1167  fence_reload_ = NULL;
1168  loader_exports_ = NULL;
1169  config_files_ = NULL;
1170  repository_name_ = NULL;
1171  mount_point_ = NULL;
1172  socket_path_ = NULL;
1173 
1174  if (retval != 0)
1175  return kFailFuseLoop;
1176  return kFailOk;
1177 }
1178 
1179 
1180 __attribute__((visibility("default")))
1181 CvmfsStubExports *g_cvmfs_stub_exports = NULL;
1182 
1183 static void __attribute__((constructor)) LibraryMain() {
1184  g_cvmfs_stub_exports = new CvmfsStubExports();
1185  g_cvmfs_stub_exports->fn_main = FuseMain;
1186 }
1187 
1188 static void __attribute__((destructor)) LibraryExit() {
1189  delete g_cvmfs_stub_exports;
1190  g_cvmfs_stub_exports = NULL;
1191 }
bool MakeCacheDirectories(const std::string &path, const mode_t mode)
Definition: posix.cc:882
bool simple_options_parsing_
Definition: loader.cc:143
std::string repository_name
Definition: loader.h:178
bool debug_mode_
Definition: loader.cc:136
static void stub_opendir(fuse_req_t req, fuse_ino_t ino, struct fuse_file_info *fi)
Definition: loader.cc:237
void SetLogSyslogFacility(const int local_facility)
Definition: logging.cc:183
static void stub_destroy(void *userdata)
Definition: loader.cc:209
const char * Code2Ascii(const ObjectFetcherFailures::Failures error)
std::string mount_point
Definition: loader.h:179
void SetLogSyslogLevel(const int level)
Definition: logging.cc:151
static void stub_listxattr(fuse_req_t req, fuse_ino_t ino, size_t size)
Definition: loader.cc:308
time_t timestamp
Definition: loader.h:138
virtual void ParsePath(const std::string &config_file, const bool external)=0
Session * session() const
Definition: repository.h:320
static struct fuse_opt cvmfs_array_opts[]
Definition: loader.cc:90
EventList history
Definition: loader.h:182
bool grab_mountpoint_
Definition: loader.cc:138
Failures Reload(const int fd_progress, const bool stop_and_go, const ReloadMode reload_mode)
Definition: loader.cc:546
static CvmfsExports * LoadLibrary(const bool debug_mode, LoaderExports *loader_exports)
Definition: loader.cc:483
ReloadMode
Definition: loader.h:246
static void stub_read(fuse_req_t req, fuse_ino_t ino, size_t size, off_t off, struct fuse_file_info *fi)
Definition: loader.cc:269
int simple_options_parsing
Definition: loader.cc:65
int(* fnAltProcessFlavor)(int argc, char **argv)
Definition: loader.h:233
int FuseMain(int argc, char *argv[])
Definition: loader.cc:618
void CreateFile(const std::string &path, const int mode, const bool ignore_failure)
Definition: posix.cc:280
#define PANIC(...)
Definition: exception.h:29
string Trim(const string &raw, bool trim_newline)
Definition: string.cc:428
string JoinStrings(const vector< string > &strings, const string &joint)
Definition: string.cc:325
string * usyslog_path_
Definition: loader.cc:129
gid_t gid_
Definition: loader.cc:133
std::string so_version
Definition: loader.h:139
static void stub_getxattr(fuse_req_t req, fuse_ino_t ino, const char *name, size_t size)
Definition: loader.cc:295
bool foreground_
Definition: loader.cc:135
bool IsOn(const std::string &param_value) const
Definition: options.cc:409
void(* fnFini)()
Definition: loader.h:236
void Daemonize()
Definition: posix.cc:1628
string * config_files_
Definition: loader.cc:127
Fence * fence_reload_
Definition: loader.cc:145
bool SafeWrite(int fd, const void *buf, size_t nbyte)
Definition: posix.cc:1983
void SendMsg2Socket(const int fd, const std::string &msg)
Definition: posix.cc:659
assert((mem||(size==0))&&"Out Of Memory")
void ** fuse_channel_or_session
Definition: loader.h:196
MountPoint * mount_point_
Definition: cvmfs.cc:128
std::string program_name
Definition: loader.h:181
bool disable_watchdog_
Definition: loader.cc:142
std::string loader_version
Definition: loader.h:176
void SetLogMicroSyslog(const std::string &filename)
Definition: logging.cc:272
void ParseDefault(const std::string &fqrn)
Definition: options.cc:282
bool(* fnSaveState)(const int fd_progress, StateList *saved_states)
Definition: loader.h:239
bool parse_options_only_
Definition: loader.cc:139
struct cvmcache_object_info __attribute__
Definition: atomic.h:24
string * socket_path_
Definition: loader.cc:128
static void stub_readdir(fuse_req_t req, fuse_ino_t ino, size_t size, off_t off, struct fuse_file_info *fi)
Definition: loader.cc:253
int SetLimitNoFile(unsigned limit_nofile)
Definition: posix.cc:1458
bool IsValid(const std::string &input) const
Definition: sanitizer.cc:114
static void stub_statfs(fuse_req_t req, fuse_ino_t ino)
Definition: loader.cc:285
int64_t String2Int64(const string &value)
Definition: string.cc:222
void GetLimitNoFile(unsigned *soft_limit, unsigned *hard_limit)
Definition: posix.cc:1480
uid_t uid_
Definition: loader.cc:132
static void stub_open(fuse_req_t req, fuse_ino_t ino, struct fuse_file_info *fi)
Definition: loader.cc:261
static void stub_releasedir(fuse_req_t req, fuse_ino_t ino, struct fuse_file_info *fi)
Definition: loader.cc:245
static void stub_readlink(fuse_req_t req, fuse_ino_t ino)
Definition: loader.cc:231
static void stub_lookup(fuse_req_t req, fuse_ino_t parent, const char *name)
Definition: loader.cc:215
bool CheckPremounted(const std::string &mountpoint)
Definition: loader.cc:188
vector< string > SplitString(const string &str, char delim)
Definition: string.cc:290
std::string Dump()
Definition: options.cc:454
#define PR_SET_DUMPABLE
Definition: platform_osx.h:319
bool(* fnRestoreState)(const int fd_progress, const StateList &saved_states)
Definition: loader.h:240
#define CVMFS_OPT(t, p, v)
Definition: loader.cc:88
static fuse_args * ParseCmdLine(int argc, char *argv[])
Definition: loader.cc:405
const loader::LoaderExports * loader_exports_
Definition: cvmfs.cc:151
std::string config_files
Definition: loader.h:180
struct fuse_lowlevel_ops cvmfs_operations
Definition: loader.h:243
bool MkdirDeep(const std::string &path, const mode_t mode, bool verify_writable)
Definition: posix.cc:846
void Drain()
Definition: fence.h:52
void WaitForSignal(int signum)
Definition: posix.cc:1588
static void SetFuseOperations(struct fuse_lowlevel_ops *loader_operations)
Definition: loader.cc:442
void Usage()
int(* fnInit)(const LoaderExports *loader_exports)
Definition: loader.h:234
bool simple_options_parsing
Definition: loader.h:189
static int Init(const loader::LoaderExports *loader_exports)
Definition: cvmfs.cc:2275
static void stub_forget(fuse_req_t req, fuse_ino_t ino, uint64_t nlookup)
Definition: loader.cc:314
bool system_mount_
Definition: loader.cc:137
bool(* fnMaintenanceMode)(const int fd_progress)
Definition: loader.h:238
void(* fnFreeSavedState)(const int fd_progress, const StateList &saved_states)
Definition: loader.h:241
string StringifyInt(const int64_t value)
Definition: string.cc:78
Failures
Definition: loader.h:27
std::string device_id
Definition: loader.h:201
int MainReload(const std::string &socket_path, const bool stop_and_go, const bool debug)
Definition: loader_talk.cc:128
static int prctl(int option, uint64_t arg2, uint64_t arg3, uint64_t arg4, uint64_t arg5)
Definition: platform_osx.h:317
std::string platform_libname(const std::string &base_name)
bool GetValue(const std::string &key, std::string *value) const
Definition: options.cc:376
bool DirectoryExists(const std::string &path)
Definition: posix.cc:813
static void stub_getattr(fuse_req_t req, fuse_ino_t ino, struct fuse_file_info *fi)
Definition: loader.cc:223
void * library_handle_
Definition: loader.cc:144
void(* fnSpawn)()
Definition: loader.h:235
bool GetLineFd(const int fd, std::string *line)
Definition: string.cc:404
static void CloseLibrary()
Definition: loader.cc:469
int fuse3_idle_threads_
Definition: loader.cc:131
uint64_t String2Uint64(const string &value)
Definition: string.cc:228
std::string(* fnGetErrorMsg)()
Definition: loader.h:237
static void Fini()
Definition: cvmfs.cc:2498
static void Spawn()
Definition: cvmfs.cc:2406
bool SwitchCredentials(const uid_t uid, const gid_t gid, const bool temporarily)
Definition: posix.cc:761
static int ParseFuseOptions(void *data __attribute__((unused)), const char *arg, int key, struct fuse_args *outargs)
Definition: loader.cc:346
Definition: fence.h:25
bool premounted_
Definition: loader.cc:141
StateList saved_states
Definition: loader.h:183
bool suid_mode_
Definition: loader.cc:140
const int mask
Definition: logging.h:23
static void stub_release(fuse_req_t req, fuse_ino_t ino, struct fuse_file_info *fi)
Definition: loader.cc:277
void Close()
Definition: fence.h:45
#define CVMFS_SWITCH(t, p)
Definition: loader.cc:89
void SetLogSyslogPrefix(const std::string &prefix)
Definition: logging.cc:241
std::string MakeCanonicalPath(const std::string &path)
Definition: posix.cc:98
static void stub_init(void *userdata, struct fuse_conn_info *conn)
Definition: loader.cc:203
static void size_t size
Definition: smalloc.h:54
bool single_threaded_
Definition: loader.cc:134
int fuse3_max_threads_
Definition: loader.cc:130
CvmfsExports * cvmfs_exports_
Definition: loader.cc:146
static void * OpenLibrary(const string &path)
Definition: loader.cc:464
void BlockSignal(int signum)
Definition: posix.cc:1573
void Open()
Definition: fence.h:59
CVMFS_EXPORT void LogCvmfs(const LogSource source, const int mask, const char *format,...)
Definition: logging.cc:528
std::string * repository_name_
Definition: loader.cc:125