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