CernVM-FS  2.13.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 
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  CVMFS_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  CVMFS_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 bool MatchFuseOption(const fuse_args *mount_options, const char *opt) {
443  for (int i = 0; i < mount_options->argc; i++) {
444  char *arg = mount_options->argv[i];
445  char *p = strstr(arg, opt);
446  if (p != NULL) {
447  if (p == arg)
448  return true;
449  char c = *(p-1);
450  if ((c == ',') || (c == ' '))
451  return true;
452  if ((c == 'o') && (p >= arg+2) && (*(p-2) == '-'))
453  return true;
454  }
455  }
456  return false;
457 }
458 
459 
460 static void SetFuseOperations(struct fuse_lowlevel_ops *loader_operations) {
461  memset(loader_operations, 0, sizeof(*loader_operations));
462 
463  loader_operations->init = stub_init;
464  loader_operations->destroy = stub_destroy;
465 
466  loader_operations->lookup = stub_lookup;
467  loader_operations->getattr = stub_getattr;
468  loader_operations->readlink = stub_readlink;
469  loader_operations->open = stub_open;
470  loader_operations->read = stub_read;
471  loader_operations->release = stub_release;
472  loader_operations->opendir = stub_opendir;
473  loader_operations->readdir = stub_readdir;
474  loader_operations->releasedir = stub_releasedir;
475  loader_operations->statfs = stub_statfs;
476  loader_operations->getxattr = stub_getxattr;
477  loader_operations->listxattr = stub_listxattr;
478  loader_operations->forget = stub_forget;
479 }
480 
481 
482 static void *OpenLibrary(const string &path) {
483  return dlopen(path.c_str(), RTLD_NOW | RTLD_LOCAL);
484 }
485 
486 
487 static void CloseLibrary() {
488 #ifdef HAS_VALGRIND_HEADERS
489  // If the libcvmfs_fuse library is unloaded, valgrind can't resolve the
490  // symbols anymore. We skip under valgrind.
491  if (!RUNNING_ON_VALGRIND) {
492 #endif
493  dlclose(library_handle_);
494  library_handle_ = NULL;
495 #ifdef HAS_VALGRIND_HEADERS
496  }
497 #endif
498 }
499 
500 
501 static CvmfsExports *LoadLibrary(const bool debug_mode,
502  LoaderExports *loader_exports)
503 {
504  std::string local_lib_path = "./";
505  if (getenv("CVMFS_LIBRARY_PATH") != NULL) {
506  local_lib_path = getenv("CVMFS_LIBRARY_PATH");
507  if (!local_lib_path.empty() && (*local_lib_path.rbegin() != '/'))
508  local_lib_path.push_back('/');
509  }
510 
511 #if CVMFS_USE_LIBFUSE == 2
512  string library_name = string("cvmfs_fuse") + ((debug_mode) ? "_debug" : "");
513 #else
514  string library_name = string("cvmfs_fuse3") + ((debug_mode) ? "_debug" : "");
515 #endif
516  library_name = platform_libname(library_name);
517  string error_messages;
518 
519  vector<string> library_paths; // TODO(rmeusel): C++11 initializer
520  if (library_paths.empty()) {
521  library_paths.push_back(local_lib_path + library_name);
522  library_paths.push_back("/usr/lib/" + library_name);
523  library_paths.push_back("/usr/lib64/" + library_name);
524 #ifdef __APPLE__
525  // Since OS X El Capitan (10.11) came with SIP, we needed to relocate our
526  // binaries from /usr/... to /usr/local/...
527  library_paths.push_back("/usr/local/lib/" + library_name);
528 #endif
529  }
530 
531  vector<string>::const_iterator i = library_paths.begin();
532  vector<string>::const_iterator iend = library_paths.end();
533  for (; i != iend; ++i) { // TODO(rmeusel): C++11 range based for
535  if (library_handle_ != NULL) {
536  break;
537  }
538 
539  error_messages += string(dlerror()) + "\n";
540  }
541 
542  if (!library_handle_) {
544  "failed to load cvmfs library, tried: '%s'\n%s",
545  JoinStrings(library_paths, "' '").c_str(), error_messages.c_str());
546  return NULL;
547  }
548 
549  CvmfsExports **exports_ptr = reinterpret_cast<CvmfsExports **>(
550  dlsym(library_handle_, "g_cvmfs_exports"));
551  if (!exports_ptr)
552  return NULL;
553 
554  if (loader_exports) {
555  LoadEvent *load_event = new LoadEvent();
556  load_event->timestamp = time(NULL);
557  load_event->so_version = (*exports_ptr)->so_version;
558  loader_exports->history.push_back(load_event);
559  }
560 
561  return *exports_ptr;
562 }
563 
564 Failures Reload(const int fd_progress, const bool stop_and_go,
565  const ReloadMode reload_mode) {
566  int retval;
567 
568  // for legacy call we take the current state of debug_mode_
569  if (reload_mode == kReloadDebug) {
570  debug_mode_ = true;
571  } else if (reload_mode == kReloadNoDebug) {
572  debug_mode_ = false;
573  }
574 
575  retval = cvmfs_exports_->fnMaintenanceMode(fd_progress);
576  if (!retval)
577  return kFailMaintenanceMode;
578 
579  SendMsg2Socket(fd_progress, "Blocking new file system calls\n");
580  fence_reload_->Close();
581 
582  SendMsg2Socket(fd_progress, "Waiting for active file system calls\n");
583  fence_reload_->Drain();
584 
585  retval = cvmfs_exports_->fnSaveState(fd_progress,
587  if (!retval)
588  return kFailSaveState;
589 
590  SendMsg2Socket(fd_progress, "Unloading Fuse module\n");
592  CloseLibrary();
593 
594  if (stop_and_go) {
595  CreateFile(*socket_path_ + ".paused", 0600);
596  SendMsg2Socket(fd_progress, "Waiting for the delivery of SIGUSR1...\n");
597  WaitForSignal(SIGUSR1);
598  unlink((*socket_path_ + ".paused").c_str());
599  }
600 
601  SendMsg2Socket(fd_progress, "Re-Loading Fuse module\n");
603  if (!cvmfs_exports_)
604  return kFailLoadLibrary;
606  if (retval != kFailOk) {
607  string msg_progress = cvmfs_exports_->fnGetErrorMsg() + " (" +
608  StringifyInt(retval) + ")\n";
609  LogCvmfs(kLogCvmfs, kLogSyslogErr, "%s", msg_progress.c_str());
610  SendMsg2Socket(fd_progress, msg_progress);
611  return (Failures)retval;
612  }
613 
614  retval = cvmfs_exports_->fnRestoreState(fd_progress,
616  if (!retval)
617  return kFailRestoreState;
619  for (unsigned i = 0, l = loader_exports_->saved_states.size(); i < l; ++i) {
620  delete loader_exports_->saved_states[i];
621  }
622  loader_exports_->saved_states.clear();
623 
624  SendMsg2Socket(fd_progress, "Activating Fuse module\n");
626 
627  fence_reload_->Open();
628  return kFailOk;
629 }
630 
631 } // namespace loader
632 
633 
634 using namespace loader; // NOLINT(build/namespaces)
635 
636 int FuseMain(int argc, char *argv[]) {
637  // Set a decent umask for new files (no write access to group/everyone).
638  // We want to allow group write access for the talk-socket.
639  umask(007);
640  // SIGUSR1 is used for the stop_and_go mode during reload
641  BlockSignal(SIGUSR1);
642 
643  int retval;
644 
645  // Jump into alternative process flavors (e.g. shared cache manager)
646  // We are here due to a fork+execve (ManagedExec in util.cc) or due to
647  // utility calls of cvmfs2
648  if ((argc > 1) && (strstr(argv[1], "__") == argv[1])) {
649  if (string(argv[1]) == string("__RELOAD__")) {
650  if (argc < 3)
651  return 1;
652  bool stop_and_go = false;
653  if ((argc > 3) && (string(argv[3]) == "stop_and_go"))
654  stop_and_go = true;
655 
656  // always last param of the cvmfs2 __RELOAD__ command
657  // check if debug mode is requested
658  // NOTE:
659  // debug mode is decided based on CVMFS_DEBUGLOG being set or not
660  // this means: reloading is now always based on CVMFS_DEBUGLOG, and
661  // reload ignores the current state
662  //
663  // if you mount with debug but do not set CVMFS_DEBUGLOG and reload,
664  // you will reload with
665  if (std::string(argv[argc - 1]) == std::string("--debug")) {
666  debug_mode_ = true;
667  } else {
668  debug_mode_ = false;
669  }
670  retval = loader_talk::MainReload(argv[2], stop_and_go, debug_mode_);
671 
672  if ((retval != 0) && (stop_and_go)) {
673  CreateFile(string(argv[2]) + ".paused.crashed", 0600);
674  }
675  return retval;
676  }
677 
678  if (string(argv[1]) == string("__MK_ALIEN_CACHE__")) {
679  if (argc < 5)
680  return 1;
681  string alien_cache_dir = argv[2];
683  if (!sanitizer.IsValid(argv[3]) || !sanitizer.IsValid(argv[4]))
684  return 1;
685  uid_t uid_owner = String2Uint64(argv[3]);
686  gid_t gid_owner = String2Uint64(argv[4]);
687 
688  int retval = MkdirDeep(alien_cache_dir, 0770);
689  if (!retval) {
690  LogCvmfs(kLogCvmfs, kLogStderr, "Failed to create %s",
691  alien_cache_dir.c_str());
692  return 1;
693  }
694  retval = chown(alien_cache_dir.c_str(), uid_owner, gid_owner);
695  if (retval != 0) {
696  LogCvmfs(kLogCvmfs, kLogStderr, "Failed to set owner of %s to %d:%d",
697  alien_cache_dir.c_str(), uid_owner, gid_owner);
698  return 1;
699  }
700  retval = SwitchCredentials(uid_owner, gid_owner, false);
701  if (!retval) {
702  LogCvmfs(kLogCvmfs, kLogStderr, "Failed to impersonate %d:%d",
703  uid_owner, gid_owner);
704  return 1;
705  }
706  // Allow access to user and group
707  retval = MakeCacheDirectories(alien_cache_dir, 0770);
708  if (!retval) {
709  LogCvmfs(kLogCvmfs, kLogStderr, "Failed to create cache skeleton");
710  return 1;
711  }
712  return 0;
713  }
714 
715  debug_mode_ = getenv("__CVMFS_DEBUG_MODE__") != NULL;
717  if (!cvmfs_exports_)
718  return kFailLoadLibrary;
719  return cvmfs_exports_->fnAltProcessFlavor(argc, argv);
720  }
721 
722  // Option parsing
723  struct fuse_args *mount_options;
724  mount_options = ParseCmdLine(argc, argv);
725  if (!mount_options) {
726  Usage(argv[0]);
727  return kFailOptions;
728  }
729 
730  string parameter;
731  OptionsManager *options_manager;
733  options_manager = new SimpleOptionsParser(
735  } else {
736  options_manager = new BashOptionsManager(
738  }
739  if (config_files_) {
740  vector<string> tokens = SplitString(*config_files_, ':');
741  for (unsigned i = 0, s = tokens.size(); i < s; ++i) {
742  options_manager->ParsePath(tokens[i], false);
743  }
744  } else {
745  options_manager->ParseDefault(*repository_name_);
746  }
747 
748 #ifdef __APPLE__
749  string volname = "-ovolname=" + *repository_name_;
750  fuse_opt_add_arg(mount_options, volname.c_str());
751  // Allow for up to 5 minute "hangs" before OS X may kill cvmfs
752  fuse_opt_add_arg(mount_options, "-odaemon_timeout=300");
753  fuse_opt_add_arg(mount_options, "-onoapplexattr");
754  // Should libfuse be single-threaded? See CVM-871, CVM-855
755  // single_threaded_ = true;
756 #endif
757  if (options_manager->GetValue("CVMFS_MOUNT_RW", &parameter) &&
758  options_manager->IsOn(parameter))
759  {
760  fuse_opt_add_arg(mount_options, "-orw");
761  } else {
762  fuse_opt_add_arg(mount_options, "-oro");
763  }
764  fuse_opt_add_arg(mount_options, "-onodev");
765  if (options_manager->GetValue("CVMFS_SUID", &parameter) &&
766  options_manager->IsOn(parameter))
767  {
768  suid_mode_ = true;
769  }
770  if (suid_mode_) {
771  if (getuid() != 0) {
773  "must be root to mount with suid option");
774  }
775  fuse_opt_add_arg(mount_options, "-osuid");
776  LogCvmfs(kLogCvmfs, kLogStdout, "CernVM-FS: running with suid support");
777  }
778 
779  if (options_manager->GetValue("CVMFS_CPU_AFFINITY", &parameter)) {
780 #ifndef __APPLE__
781  cpu_set_t mask;
782  vector<string> cpus = SplitString(parameter, ',');
783  CPU_ZERO(&mask);
784  for (vector<string>::iterator i = cpus.begin(); i != cpus.end(); i++) {
785  CPU_SET(String2Uint64(Trim(*i)), &mask);
786  }
788  "CernVM-FS: setting CPU Affinity to %s", parameter.c_str());
789  int err = sched_setaffinity(0, sizeof(mask), &mask);
790  if (err != 0) {
792  "Setting CPU Affinity failed with error %d", errno);
793  }
794 #else
796  "CPU affinity setting not supported on macOS");
797 #endif
798  }
800  loader_exports_->loader_version = CVMFS_VERSION;
801  loader_exports_->boot_time = time(NULL);
802  loader_exports_->program_name = argv[0];
806  loader_exports_->device_id = "0:0"; // initially unknown, set after mount
809  if (config_files_)
811  else
813 
814  if (parse_options_only_) {
815  LogCvmfs(kLogCvmfs, kLogStdout, "# CernVM-FS parameters:\n%s",
816  options_manager->Dump().c_str());
817  return 0;
818  }
819 
820  // Logging
821  if (options_manager->GetValue("CVMFS_SYSLOG_LEVEL", &parameter))
822  SetLogSyslogLevel(String2Uint64(parameter));
823  else
825  if (options_manager->GetValue("CVMFS_SYSLOG_FACILITY", &parameter))
828  // Deferr setting usyslog until credentials are dropped
829 
830  // Permissions check
831  if (options_manager->GetValue("CVMFS_CHECK_PERMISSIONS", &parameter)) {
832  if (options_manager->IsOn(parameter)) {
833  fuse_opt_add_arg(mount_options, "-odefault_permissions");
834  }
835  }
836 
839  "Mount point %s does not exist", mount_point_->c_str());
840  return kFailPermission;
841  }
842 
843  // Number of file descriptors
844  if (options_manager->GetValue("CVMFS_NFILES", &parameter)) {
845  int retval = SetLimitNoFile(String2Uint64(parameter));
846  if (retval == -2) {
847  LogCvmfs(kLogCvmfs, kLogStdout, "CernVM-FS: running under valgrind");
848  } else if (retval == -1) {
849  if (system_mount_) {
851  "Failed to set maximum number of open files, "
852  "insufficient permissions");
853  return kFailPermission;
854  }
855  unsigned soft_limit, hard_limit;
856  GetLimitNoFile(&soft_limit, &hard_limit);
858  "Failed to set requested number of open files, "
859  "using maximum number %u", hard_limit);
860  if (hard_limit > soft_limit) {
861  (void) SetLimitNoFile(hard_limit);
862  }
863  }
864  }
865 
866  // Apply OOM score adjustment
867  if (options_manager->GetValue("CVMFS_OOM_SCORE_ADJ", &parameter)) {
868  string proc_path = "/proc/" + StringifyInt(getpid()) + "/oom_score_adj";
869  int fd_oom = open(proc_path.c_str(), O_WRONLY);
870  if (fd_oom < 0) {
872  "failed to open %s", proc_path.c_str());
873  } else {
874  bool retval = SafeWrite(fd_oom, parameter.data(), parameter.length());
875  if (!retval) {
877  "failed to set OOM score adjustment to %s", parameter.c_str());
878  }
879  close(fd_oom);
880  }
881  }
882 
883  // Protect the process from being killed by systemd
884  if (options_manager->GetValue("CVMFS_SYSTEMD_NOKILL", &parameter) &&
885  options_manager->IsOn(parameter))
886  {
887  argv[0][0] = '@';
888  }
889 
890  // Grab mountpoint
891  if (grab_mountpoint_) {
892  if ((chown(mount_point_->c_str(), uid_, gid_) != 0) ||
893  (chmod(mount_point_->c_str(), 0755) != 0))
894  {
896  "Failed to grab mountpoint %s (%d)",
897  mount_point_->c_str(), errno);
898  return kFailPermission;
899  }
900  }
901 
902 #if CVMFS_USE_LIBFUSE != 2
903  int premount_fd = -1;
904  if (!premounted_ && !suid_mode_ && getuid() == 0) {
905  // If not already premounted or using suid mode, premount the fuse
906  // mountpoint before dropping privileges to avoid the need for fusermount.
907  // Requires libfuse >= 3.3.0.
908  platform_stat64 info;
909  // Need to know if it is a directory or not
910  if (platform_stat(mount_point_->c_str(), &info) != 0) { LogCvmfs(kLogCvmfs, kLogStderr | kLogSyslogErr,
911  "Failed to stat mountpoint %s (%d)",
912  mount_point_->c_str(), errno);
913  return kFailPermission;
914  }
915  premount_fd = open("/dev/fuse", O_RDWR);
916  if (premount_fd == -1) {
918  "Failed to open /dev/fuse (%d)", errno);
919  return kFailPermission;
920  }
921  char opts[128];
922  snprintf(opts, sizeof(opts),
923  "fd=%i,rootmode=%o,user_id=0,group_id=0%s%s",
924  premount_fd, info.st_mode & S_IFMT,
925  MatchFuseOption(mount_options, "default_permissions") ?
926  ",default_permissions" : "",
927  MatchFuseOption(mount_options, "allow_other") ? ",allow_other" : "");
928  unsigned long flags = MS_NOSUID | MS_NODEV | MS_RELATIME;
929  if (!MatchFuseOption(mount_options, "rw")) {
930  flags |= MS_RDONLY;
931  }
932  if (mount("cvmfs2", mount_point_->c_str(), "fuse", flags, opts) == -1) {
934  "Failed to mount -t fuse -o %s cvmfs2 %s (%d)",
935  opts, mount_point_->c_str(), errno);
936  return kFailPermission;
937  }
938  }
939 #endif
940 
941  int fd_mountinfo = -1; // needs to be declared before start using goto
942 
943  // Drop credentials
944  if ((uid_ != 0) || (gid_ != 0)) {
945  LogCvmfs(kLogCvmfs, kLogStdout, "CernVM-FS: running with credentials %d:%d",
946  uid_, gid_);
947  const bool retrievable = (suid_mode_ || !disable_watchdog_);
948  if (!SwitchCredentials(uid_, gid_, retrievable)) {
950  "Failed to drop credentials");
951  retval = kFailPermission;
952  goto cleanup;
953  }
954  }
955  if (disable_watchdog_) {
956  LogCvmfs(kLogCvmfs, kLogDebug, "No watchdog, enabling core files");
957  prctl(PR_SET_DUMPABLE, 1, 0, 0, 0);
958  }
959 
960  // Only set usyslog now, otherwise file permissions are wrong
961  usyslog_path_ = new string();
962  if (options_manager->GetValue("CVMFS_USYSLOG", &parameter))
963  *usyslog_path_ = parameter;
965 
966  if (single_threaded_) {
968  "CernVM-FS: running in single threaded mode");
969  }
970  if (debug_mode_) {
972  "CernVM-FS: running in debug mode");
973  }
974 
975 #ifndef FUSE_CAP_POSIX_ACL
976  if (options_manager->GetValue("CVMFS_ENFORCE_ACLS", &parameter) &&
977  options_manager->IsOn(parameter))
978  {
980  "CernVM-FS: ACL support requested but not available in this "
981  "version of libfuse");
982  retval = kFailPermission;
983  goto cleanup;
984  }
985 #endif
986 
987  // Initialize the loader socket, connections are not accepted until Spawn()
988  socket_path_ = new string("/var/run/cvmfs");
989  if (options_manager->GetValue("CVMFS_RELOAD_SOCKETS", &parameter))
990  *socket_path_ = MakeCanonicalPath(parameter);
991  *socket_path_ += "/cvmfs." + *repository_name_;
992  retval = loader_talk::Init(*socket_path_);
993  if (!retval) {
995  "Failed to initialize loader socket");
996  retval = kFailLoaderTalk;
997  goto cleanup;
998  }
999 
1000  // TODO(jblomer): we probably want to apply a default setting related to the
1001  // number of cores.
1002  if (options_manager->GetValue("CVMFS_FUSE3_MAX_THREADS", &parameter)) {
1003  fuse3_max_threads_ = String2Int64(parameter);
1004  }
1005  if (options_manager->GetValue("CVMFS_FUSE3_IDLE_THREADS", &parameter)) {
1006  fuse3_idle_threads_ = String2Int64(parameter);
1007  }
1008 #ifdef CVMFS_ENABLE_FUSE3_LOOP_CONFIG
1009  if (fuse3_max_threads_) {
1011  "CernVM-FS: Fuse3 max_threads=%d", fuse3_max_threads_);
1012  }
1013  if (fuse3_idle_threads_) {
1015  "CernVM-FS: Fuse3 min_idle_threads=%d", fuse3_idle_threads_);
1016  }
1017 #else
1020  "CernVM-FS: ignoring fuse3 thread settings (libfuse too old)");
1021  }
1022 #endif
1023 
1024  // Options are not needed anymore
1025  delete options_manager;
1026  options_manager = NULL;
1027 
1028  struct fuse_session *session;
1029 #if CVMFS_USE_LIBFUSE == 2
1030  struct fuse_chan *channel;
1031  loader_exports_->fuse_channel_or_session = reinterpret_cast<void **>(
1032  &channel);
1033 #else
1034  loader_exports_->fuse_channel_or_session = reinterpret_cast<void **>(
1035  &session);
1036 #endif
1037 
1038  // Load and initialize cvmfs library
1040  "CernVM-FS: loading Fuse module... ");
1042  if (!cvmfs_exports_) {
1043  retval = kFailLoadLibrary;
1044  goto cleanup;
1045  }
1047  if (retval != kFailOk) {
1048  if (retval == kFailDoubleMount) {
1050  "\nCernVM-FS: repository %s already mounted on %s",
1052  loader_exports_->mount_point.c_str());
1053  return 0;
1054  }
1055  LogCvmfs(kLogCvmfs, kLogStderr | kLogSyslogErr, "%s (%d - %s)",
1056  cvmfs_exports_->fnGetErrorMsg().c_str(),
1057  retval, Code2Ascii((Failures)retval));
1059  goto cleanup;
1060  }
1061  LogCvmfs(kLogCvmfs, kLogStdout, "done");
1062 
1063  // Mount
1064  fence_reload_ = new Fence();
1065 
1066  if (suid_mode_) {
1067  const bool retrievable = true;
1068  if (!SwitchCredentials(0, getgid(), retrievable)) {
1070  "failed to re-gain root permissions for mounting");
1072  retval = kFailPermission;
1073  goto cleanup;
1074  }
1075  }
1076 
1077 
1078  struct fuse_lowlevel_ops loader_operations;
1079  SetFuseOperations(&loader_operations);
1080 #if (FUSE_VERSION >= 29)
1081  if (cvmfs_exports_->cvmfs_operations.forget_multi)
1082  loader_operations.forget_multi = stub_forget_multi;
1083 #endif
1084 
1085 #if CVMFS_USE_LIBFUSE == 2
1086  channel = fuse_mount(mount_point_->c_str(), mount_options);
1087  if (!channel) {
1089  "failed to create Fuse channel");
1091  retval = kFailMount;
1092  goto cleanup;
1093  }
1094 
1095  session = fuse_lowlevel_new(mount_options, &loader_operations,
1096  sizeof(loader_operations), NULL);
1097  if (!session) {
1099  "failed to create Fuse session");
1100  fuse_unmount(mount_point_->c_str(), channel);
1102  retval = kFailMount;
1103  goto cleanup;
1104  }
1105 #else
1106  // libfuse3
1107  session = fuse_session_new(mount_options, &loader_operations,
1108  sizeof(loader_operations), NULL);
1109  if (!session) {
1111  "failed to create Fuse session");
1113  retval = kFailMount;
1114  goto cleanup;
1115  }
1116  if (premount_fd >= 0) {
1117  char premount_str[64];
1118  snprintf(premount_str, sizeof(premount_str), "/dev/fd/%d", premount_fd);
1119  retval = fuse_session_mount(session, premount_str);
1120  } else {
1121  retval = fuse_session_mount(session, mount_point_->c_str());
1122  }
1123  if (retval != 0) {
1125  "failed to mount file system");
1127  retval = kFailMount;
1128  goto cleanup;
1129  }
1130 #endif
1131 
1132  // drop credentials
1133  if (suid_mode_) {
1134  const bool retrievable = !disable_watchdog_;
1135  if (!SwitchCredentials(uid_, gid_, retrievable)) {
1137  "failed to drop permissions after mounting");
1139  retval = kFailPermission;
1140  goto cleanup;
1141  }
1142  }
1143 
1144  // Determine device id
1145  fd_mountinfo = open("/proc/self/mountinfo", O_RDONLY);
1146  if (fd_mountinfo > 0) {
1147  std::string line;
1148  while (GetLineFd(fd_mountinfo, &line)) {
1149  std::vector<std::string> tokens = SplitString(line, ' ');
1150  if (tokens.size() < 5) continue;
1151  if (tokens[4] != loader_exports_->mount_point) continue;
1152  unsigned i = 5;
1153  for (; i < tokens.size(); ++i) {
1154  if (tokens[i] == "-") break;
1155  }
1156  if (tokens.size() < i + 3) continue;
1157  if (tokens[i + 2] != "cvmfs2") continue;
1158  loader_exports_->device_id = tokens[2];
1159  break;
1160  }
1161  close(fd_mountinfo);
1162  }
1163 
1164  if (!premounted_) {
1165  LogCvmfs(kLogCvmfs, kLogStdout, "CernVM-FS: mounted cvmfs on %s",
1166  mount_point_->c_str());
1167  }
1169  "CernVM-FS: linking %s to repository %s",
1170  mount_point_->c_str(), repository_name_->c_str());
1171  if (!foreground_)
1172  Daemonize();
1173 
1176 
1177  SetLogMicroSyslog("");
1178  retval = fuse_set_signal_handlers(session);
1179  assert(retval == 0);
1180 #if CVMFS_USE_LIBFUSE == 2
1181  fuse_session_add_chan(session, channel);
1182 #endif
1183  if (single_threaded_) {
1184  retval = fuse_session_loop(session);
1185  } else {
1186 #if CVMFS_USE_LIBFUSE == 2
1187  retval = fuse_session_loop_mt(session);
1188 #else
1189 #ifdef CVMFS_ENABLE_FUSE3_LOOP_CONFIG
1190  struct fuse_loop_config *fuse_loop_cfg = fuse_loop_cfg_create();
1191 
1192  fuse_loop_cfg_set_clone_fd(fuse_loop_cfg, 1);
1193 
1194  if (fuse3_max_threads_ > 0) {
1195  fuse_loop_cfg_set_max_threads(fuse_loop_cfg, fuse3_max_threads_);
1196  }
1197  if (fuse3_idle_threads_ > 0) {
1198  fuse_loop_cfg_set_idle_threads(fuse_loop_cfg, fuse3_idle_threads_);
1199  }
1200 
1201  retval = fuse_session_loop_mt(session, fuse_loop_cfg);
1202  fuse_loop_cfg_destroy(fuse_loop_cfg);
1203 #else
1204  retval = fuse_session_loop_mt(session, 1 /* use fd per thread */);
1205 #endif // CVMFS_ENABLE_FUSE3_LOOP_CONFIG
1206 #endif // fuse2/3
1207  }
1209 
1212 
1213  // Unmount
1214 #if CVMFS_USE_LIBFUSE == 2
1215  fuse_remove_signal_handlers(session);
1216  fuse_session_remove_chan(channel);
1217  fuse_session_destroy(session);
1218  fuse_unmount(mount_point_->c_str(), channel);
1219  channel = NULL;
1220 #else
1221  // libfuse3
1222  fuse_remove_signal_handlers(session);
1223  fuse_session_unmount(session);
1224  fuse_session_destroy(session);
1225 #endif
1226  fuse_opt_free_args(mount_options);
1227  delete mount_options;
1228  session = NULL;
1229  mount_options = NULL;
1230 
1231  CloseLibrary();
1232 
1233  delete fence_reload_;
1234  delete loader_exports_;
1235  delete config_files_;
1236  delete repository_name_;
1237  delete mount_point_;
1238  delete socket_path_;
1239  fence_reload_ = NULL;
1240  loader_exports_ = NULL;
1241  config_files_ = NULL;
1242  socket_path_ = NULL;
1243 
1244  if (retval != 0)
1245  retval = kFailFuseLoop;
1246  else
1247  retval = kFailOk;
1248 
1249 #if CVMFS_USE_LIBFUSE != 2
1250  if (premount_fd >= 0) {
1251  goto cleanup;
1252  }
1253 #endif
1254 
1255  LogCvmfs(kLogCvmfs, kLogSyslog, "CernVM-FS: unmounted %s (%s)",
1256  mount_point_->c_str(), repository_name_->c_str());
1257 
1258  repository_name_ = NULL;
1259  mount_point_ = NULL;
1260 
1261  return retval;
1262 
1263 cleanup:
1264 #if CVMFS_USE_LIBFUSE != 2
1265  if (premount_fd >= 0) {
1266  if (!SwitchCredentials(0, getgid(), true)) {
1268  "failed to re-gain root permissions for umounting");
1269  retval = kFailPermission;
1270  } else if (umount(mount_point_->c_str()) < 0) {
1272  "failed to umount %s (%d)", mount_point_->c_str(), errno);
1273  retval = kFailPermission;
1274  } else {
1275  LogCvmfs(kLogCvmfs, kLogSyslog, "CernVM-FS: unmounted %s (%s)",
1276  mount_point_->c_str(), repository_name_->c_str());
1277  }
1278  close(premount_fd);
1279  }
1280 #endif
1281 
1282  repository_name_ = NULL;
1283  mount_point_ = NULL;
1284 
1285  return retval;
1286 }
1287 
1288 
1289 __attribute__((visibility("default")))
1290 CvmfsStubExports *g_cvmfs_stub_exports = NULL;
1291 
1292 static void __attribute__((constructor)) LibraryMain() {
1293  g_cvmfs_stub_exports = new CvmfsStubExports();
1294  g_cvmfs_stub_exports->fn_main = FuseMain;
1295 }
1296 
1297 static void __attribute__((destructor)) LibraryExit() {
1298  delete g_cvmfs_stub_exports;
1299  g_cvmfs_stub_exports = NULL;
1300 }
bool MakeCacheDirectories(const std::string &path, const mode_t mode)
Definition: posix.cc:893
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
struct stat64 platform_stat64
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:564
static CvmfsExports * LoadLibrary(const bool debug_mode, LoaderExports *loader_exports)
Definition: loader.cc:501
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:636
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:462
string JoinStrings(const vector< string > &strings, const string &joint)
Definition: string.cc:359
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:1702
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:2060
void SendMsg2Socket(const int fd, const std::string &msg)
Definition: posix.cc:670
assert((mem||(size==0))&&"Out Of Memory")
void ** fuse_channel_or_session
Definition: loader.h:196
MountPoint * mount_point_
Definition: cvmfs.cc:129
std::string program_name
Definition: loader.h:181
bool disable_watchdog_
Definition: loader.cc:142
std::string loader_version
Definition: loader.h:176
int platform_stat(const char *path, platform_stat64 *buf)
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:1469
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
int prctl(int, uint64_t, uint64_t, uint64_t, uint64_t)
Definition: platform_osx.h:317
int64_t String2Int64(const string &value)
Definition: string.cc:240
void GetLimitNoFile(unsigned *soft_limit, unsigned *hard_limit)
Definition: posix.cc:1491
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:308
std::string Dump()
Definition: options.cc:454
#define PR_SET_DUMPABLE
Definition: platform_osx.h:318
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:152
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:857
void Drain()
Definition: fence.h:52
void WaitForSignal(int signum)
Definition: posix.cc:1599
static void SetFuseOperations(struct fuse_lowlevel_ops *loader_operations)
Definition: loader.cc:460
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:2316
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
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:824
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:438
static void CloseLibrary()
Definition: loader.cc:487
int fuse3_idle_threads_
Definition: loader.cc:131
uint64_t String2Uint64(const string &value)
Definition: string.cc:246
std::string(* fnGetErrorMsg)()
Definition: loader.h:237
static void Fini()
Definition: cvmfs.cc:2539
static void Spawn()
Definition: cvmfs.cc:2447
bool SwitchCredentials(const uid_t uid, const gid_t gid, const bool temporarily)
Definition: posix.cc:772
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
static bool MatchFuseOption(const fuse_args *mount_options, const char *opt)
Definition: loader.cc:442
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:482
void BlockSignal(int signum)
Definition: posix.cc:1584
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