CernVM-FS  2.11.0
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
mount.cvmfs.cc
Go to the documentation of this file.
1 
8 #include <errno.h>
9 #include <sys/select.h>
10 #include <sys/socket.h>
11 #include <sys/types.h>
12 #include <sys/uio.h>
13 #include <sys/wait.h>
14 #ifdef __APPLE__
15 #include <sys/sysctl.h>
16 #endif
17 #include <sys/un.h>
18 #include <unistd.h>
19 
20 #include <cstdio>
21 #include <cstdlib>
22 #include <string>
23 #include <vector>
24 
25 #include "options.h"
26 #include "sanitizer.h"
27 #include "util/logging.h"
28 #include "util/platform.h"
29 #include "util/posix.h"
30 #include "util/string.h"
31 
32 using namespace std; // NOLINT
33 
35 
36 static void Usage(int output_dest) {
37  LogCvmfs(kLogCvmfs, output_dest,
38  "Mount helper for CernVM-FS. Used by mount(8)\n"
39  "Mandatory arguments:\n"
40  " repository name: <repository>\n"
41  " mountpoint of the repository: <mountpoint>\n"
42  "Options:\n"
43  " -o <mount options>\n"
44  " -f dry run, just prints out the mount command\n"
45  " -h print this help");
46 }
47 
48 
49 static void AddMountOption(const string &option,
50  vector<string> *mount_options)
51 {
52  mount_options->push_back(option);
53 }
54 
55 
56 static string MkFqrn(const string &repository) {
57  const string::size_type idx = repository.find_last_of('.');
58  if (idx == string::npos) {
59  string domain;
60  bool retval = options_manager_.GetValue("CVMFS_DEFAULT_DOMAIN", &domain);
61  if (!retval) {
63  "CVMFS_DEFAULT_DOMAIN missing");
64  abort();
65  }
66  return repository + "." + domain;
67  }
68  return repository;
69 }
70 
71 
72 static bool CheckFuse() {
73  string fuse_device;
74  int retval;
75 #ifdef __APPLE__
76  retval = system("/Library/Filesystems/macfuse.fs/Contents/Resources/"
77  "load_macfuse");
78  if (retval != 0) {
79  LogCvmfs(kLogCvmfs, kLogStderr, "Failed loading macFUSE");
80  return false;
81  }
82  fuse_device = "/dev/macfuse0";
83 #else
84  fuse_device = "/dev/fuse";
85 #endif
86  platform_stat64 info;
87  retval = platform_stat(fuse_device.c_str(), &info);
88  if ((retval != 0) || !S_ISCHR(info.st_mode)) {
89  LogCvmfs(kLogCvmfs, kLogStderr, "Fuse not loaded");
90  return false;
91  }
92  return true;
93 }
94 
95 
96 static bool CheckStrictMount(const string &fqrn) {
97  string param_strict_mount;
98  if (options_manager_.GetValue("CVMFS_STRICT_MOUNT", &param_strict_mount) &&
99  options_manager_.IsOn(param_strict_mount))
100  {
101  string repository_list;
102  bool retval =
103  options_manager_.GetValue("CVMFS_REPOSITORIES", &repository_list);
104  if (!retval) {
105  LogCvmfs(kLogCvmfs, kLogStderr, "CVMFS_REPOSITORIES missing");
106  return false;
107  }
108  vector<string> repositories = SplitString(repository_list, ',');
109  for (unsigned i = 0; i < repositories.size(); ++i) {
110  if (MkFqrn(repositories[i]) == fqrn)
111  return true;
112  }
113  string config_repository;
114  retval =
115  options_manager_.GetValue("CVMFS_CONFIG_REPOSITORY", &config_repository);
116  if (retval && (config_repository == fqrn))
117  return true;
118  LogCvmfs(kLogCvmfs, kLogStderr, "Not allowed to mount %s, "
119  "add it to CVMFS_REPOSITORIES", fqrn.c_str());
120  return false;
121  }
122  return true;
123 }
124 
125 
126 static bool CheckProxy() {
127  string param;
128  int retval = options_manager_.GetValue("CVMFS_HTTP_PROXY", &param);
129  if (!retval || param.empty()) {
130  LogCvmfs(kLogCvmfs, kLogStderr, "CVMFS_HTTP_PROXY required");
131  return false;
132  }
133  return true;
134 }
135 
136 
137 static bool CheckConcurrentMount(const string &fqrn,
138  const string &workspace,
139  string *mountpointp) {
140  // Try connecting to cvmfs_io socket
141  int socket_fd = ConnectSocket(workspace + "/cvmfs_io." + fqrn);
142  if (socket_fd < 0)
143  return false;
144 
145  // There is a repository mounted, find out the mount point
146  SendMsg2Socket(socket_fd, "mountpoint");
147  string mountpoint;
148  char buf;
149  while (read(socket_fd, &buf, 1) == 1) {
150  if (buf != '\n')
151  mountpoint.push_back(buf);
152  }
153  *mountpointp = mountpoint;
154  close(socket_fd);
155  return true;
156 }
157 
158 static int GetExistingFuseFd(
159  const string &fqrn, const string &workspace, uid_t cvmfs_uid)
160 {
161  // Try connecting to cvmfs_io socket
162  int talk_fd = ConnectSocket(workspace + "/cvmfs_io." + fqrn);
163  if (talk_fd < 0)
164  return -1;
165 
166  // Create temporary socket
167  std::string recv_sock_dir = CreateTempDir(workspace + "/fusefd");
168  if (recv_sock_dir.empty() || (chmod(recv_sock_dir.c_str(), 0755) != 0)) {
169  close(talk_fd);
170  return -1;
171  }
172  std::string recv_sock_path = recv_sock_dir + "/sock";
173  int recv_sock_fd = MakeSocket(recv_sock_path, 0660);
174  if ((recv_sock_fd < 0) ||
175  (chown(recv_sock_path.c_str(), cvmfs_uid, getegid()) != 0))
176  {
177  if (recv_sock_fd >= 0)
178  close(recv_sock_fd);
179  close(talk_fd);
180  unlink(recv_sock_path.c_str());
181  rmdir(recv_sock_dir.c_str());
182  return -1;
183  }
184  listen(recv_sock_fd, 1);
185 
186  // Trigger fd transfer
187  SendMsg2Socket(talk_fd, "send mount fd " + recv_sock_path);
188  string result;
189  char buf;
190  while (read(talk_fd, &buf, 1) == 1) {
191  if (buf != '\n')
192  result.push_back(buf);
193  }
194  close(talk_fd);
195 
196  int fuse_fd = -1;
197  if (result == "OK") {
198  struct sockaddr_un addr;
199  unsigned int len = sizeof(addr);
200  int con_fd =
201  accept(recv_sock_fd, reinterpret_cast<struct sockaddr *>(&addr), &len);
202  fuse_fd = RecvFdFromSocket(con_fd);
203  close(con_fd);
204  }
205  close(recv_sock_fd);
206  unlink(recv_sock_path.c_str());
207  rmdir(recv_sock_dir.c_str());
208 
209  return fuse_fd;
210 }
211 
212 
213 static bool GetCacheDir(const string &fqrn, string *cachedir) {
214  string param;
215  bool retval = options_manager_.GetValue("CVMFS_CACHE_DIR", &param);
216  if (retval) {
217  *cachedir = MakeCanonicalPath(param);
218  return true;
219  }
220 
221  retval = options_manager_.GetValue("CVMFS_CACHE_BASE", &param);
222  if (!retval)
223  return false;
224 
225  *cachedir = MakeCanonicalPath(param);
226  if (options_manager_.GetValue("CVMFS_SHARED_CACHE", &param) &&
227  options_manager_.IsOn(param))
228  {
229  *cachedir = *cachedir + "/shared";
230  } else {
231  *cachedir = *cachedir + "/" + fqrn;
232  }
233  return true;
234 }
235 
236 
237 static bool GetWorkspace(const string &fqrn, string *workspace) {
238  string param;
239  bool retval = options_manager_.GetValue("CVMFS_WORKSPACE", &param);
240  if (retval) {
241  *workspace = MakeCanonicalPath(param);
242  return true;
243  }
244 
245  retval = GetCacheDir(fqrn, workspace);
246  if (!retval) {
248  "CVMFS_WORKSPACE or CVMFS_CACHE_[BASE|DIR] required");
249  return false;
250  }
251  return true;
252 }
253 
254 
255 static bool WaitForReload(const std::string &mountpoint) {
256  string param;
257  int retval = options_manager_.GetValue("CVMFS_RELOAD_SOCKETS", &param);
258  if (!retval) {
259  LogCvmfs(kLogCvmfs, kLogStderr, "CVMFS_RELOAD_SOCKETS required");
260  return false;
261  }
262  string reload_guard = param + "/cvmfs.pause";
263  // Deprecated, now a directory
264  if (FileExists(reload_guard)) {
265  LogCvmfs(kLogCvmfs, kLogStdout, "Waiting for CernVM-FS reload...");
266  while (FileExists(reload_guard))
267  SafeSleepMs(250);
268  }
269  if (DirectoryExists(reload_guard)) {
270  LogCvmfs(kLogCvmfs, kLogStdout, "Waiting for CernVM-FS reload...");
271  const string mountpoint_base64 = Base64(mountpoint);
272  while (DirectoryExists(reload_guard)) {
273  // We are in paused state but automounter unmounted the repo.
274  // We need to allow to mount just to reload.
275  if (FileExists(reload_guard + "/" + mountpoint_base64))
276  break;
277  SafeSleepMs(250);
278  }
279  }
280  return true;
281 }
282 
283 
284 static bool GetCvmfsUser(string *cvmfs_user) {
285  string param;
286  int retval = options_manager_.GetValue("CVMFS_USER", &param);
287  if (!retval) {
288  LogCvmfs(kLogCvmfs, kLogStderr, "CVMFS_USER required");
289  return false;
290  }
291  *cvmfs_user = param; // No sanitation; due to PAM, username can be anything
292  return true;
293 }
294 
295 
296 static std::string GetCvmfsBinary() {
297  std::string result;
298  vector<string> paths;
299  paths.push_back("/usr/bin");
300 
301 #ifdef __APPLE__
302  // OS X El Capitan came with SIP, forcing us to become relocatable. CVMFS
303  // 2.2.0+ installs into /usr/local always
304  paths.push_back("/usr/local/bin");
305 #endif
306 
307  // TODO(reneme): C++11 range based for loop
308  vector<string>::const_iterator i = paths.begin();
309  const vector<string>::const_iterator iend = paths.end();
310  for (; i != iend; ++i) {
311  const std::string cvmfs2 = *i + "/cvmfs2";
312  if (FileExists(cvmfs2) || SymlinkExists(cvmfs2)) {
313  result = cvmfs2;
314  break;
315  }
316  }
317 
318  return result;
319 }
320 
321 static int AttachMount(const std::string &mountpoint, const std::string &fqrn,
322  int fuse_fd)
323 {
324 #ifdef __APPLE__
325  (void) mountpoint;
326  (void) fqrn;
327  (void) fuse_fd;
328  return 1;
329 #else
330  platform_stat64 info;
331  int retval = platform_stat(mountpoint.c_str(), &info);
332  if (retval != 0)
333  return 1;
334 
335  char mntopt[100];
336  snprintf(mntopt, sizeof(mntopt),
337  "ro,fd=%i,rootmode=%o,user_id=%d,group_id=%d",
338  fuse_fd, info.st_mode & S_IFMT, geteuid(), getegid());
339  // TODO(jblomer): remove NOSUID according to options
340  retval = mount("cvmfs2", mountpoint.c_str(), "fuse",
341  MS_NODEV | MS_RDONLY | MS_NOSUID, mntopt);
342  if (retval != 0) {
344  "Cannot attach to existing fuse module (%d)", errno);
345  return 1;
346  }
348  "CernVM-FS: linking %s to repository %s (attaching)",
349  mountpoint.c_str(), fqrn.c_str());
350  return 0;
351 #endif
352 }
353 
354 
355 int main(int argc, char **argv) {
356  bool dry_run = false;
357  bool remount = false;
358  vector<string> mount_options;
359 
360  // Option parsing
361  vector<string> option_tokens;
362  int c;
363  while ((c = getopt(argc, argv, "vfnho:")) != -1) {
364  switch (c) {
365  case 'f':
366  dry_run = true;
367  break;
368  case 'n':
369  LogCvmfs(kLogCvmfs, kLogStdout, "Note: fusermount _does_ modify "
370  "/etc/mtab in case it is writable.");
371  // Fall through
372  case 'v':
373  break;
374  case 'h':
375  Usage(kLogStdout);
376  return 0;
377  case 'o':
378  AddMountOption(optarg, &mount_options);
379  option_tokens = SplitString(optarg, ',');
380  for (unsigned i = 0; i < option_tokens.size(); ++i) {
381  if (option_tokens[i] == string("remount"))
382  remount = true;
383  }
384  break;
385  default:
386  Usage(kLogStderr);
387  return 1;
388  }
389  }
390  if (optind+2 != argc) {
391  Usage(kLogStderr);
392  return 1;
393  }
394 
395  string device = argv[optind];
396  // Some mount versions expand the given device to a full path. Thus ignore
397  // everything before the last slash (/)/
398  if (HasPrefix(device, "/", false))
399  device = GetFileName(device);
400  sanitizer::RepositorySanitizer repository_sanitizer;
401  if (device.empty() || !repository_sanitizer.IsValid(device)) {
402  LogCvmfs(kLogCvmfs, kLogStderr, "Invalid repository: %s", device.c_str());
403  return 1;
404  }
405  string mountpoint = argv[optind+1];
406 
408  const string fqrn = MkFqrn(device);
412 
413  int retval;
414  int sysret;
415  bool dedicated_cachedir = false;
416  string cvmfs_user;
417  string cachedir;
418  string workspace;
419  // Environment checks
420  retval = WaitForReload(mountpoint);
421  if (!retval) return 1;
422  retval = GetWorkspace(fqrn, &workspace);
423  if (!retval) return 1;
424  retval = GetCacheDir(fqrn, &cachedir);
425  dedicated_cachedir = (retval && (cachedir != workspace));
426  retval = GetCvmfsUser(&cvmfs_user);
427  if (!retval) return 1;
428  retval = CheckFuse();
429  if (!retval) return 1;
430  retval = CheckStrictMount(fqrn);
431  if (!retval) return 1;
432  retval = CheckProxy();
433  if (!retval) return 1;
434 
435  // Retrieve cvmfs uid/gid and fuse gid if exists
436  uid_t uid_cvmfs;
437  gid_t gid_cvmfs;
438  gid_t gid_fuse;
439  bool has_fuse_group = false;
440  retval = GetUidOf(cvmfs_user, &uid_cvmfs, &gid_cvmfs);
441  if (!retval) {
442  LogCvmfs(kLogCvmfs, kLogStderr, "Failed to find user %s in passwd database",
443  cvmfs_user.c_str());
444  return 1;
445  }
446  has_fuse_group = GetGidOf("fuse", &gid_fuse);
447 
448  // This is not a sure thing. When the CVMFS_CACHE_BASE parameter is changed
449  // two repositories can get mounted concurrently (but that should not hurt).
450  // If the same repository is mounted multiple times at the same time, there
451  // is a race here. Eventually, only one repository will be mounted while the
452  // other cvmfs processes block on a file lock in the cache.
453  string prev_mountpoint;
454  retval = CheckConcurrentMount(fqrn, workspace, &prev_mountpoint);
455  if (retval) {
456  if (remount && (mountpoint == prev_mountpoint)) {
457  // Actually remounting is too hard, but pretend that it worked
458  return 0;
459  }
460  // Identify zombie fuse processes that are held open by other mount
461  // namespaces
462  if ((mountpoint == prev_mountpoint) && !IsMountPoint(mountpoint)) {
463  // Allow for group access to the socket receiving the fuse fd
464  umask(007);
465  int fuse_fd = GetExistingFuseFd(fqrn, workspace, uid_cvmfs);
466  if (fuse_fd < 0) {
468  "Cannot connect to existing fuse module");
469  return 1;
470  }
471  return AttachMount(mountpoint, fqrn, fuse_fd);
472  }
473  LogCvmfs(kLogCvmfs, kLogStderr, "Repository %s is already mounted on %s",
474  fqrn.c_str(), prev_mountpoint.c_str());
475  return 1;
476  } else {
477  // No double mount
478  if (remount) {
479  LogCvmfs(kLogCvmfs, kLogStderr, "Repository %s is not mounted on %s",
480  fqrn.c_str(), mountpoint.c_str());
481  return 1;
482  }
483  }
484 
485  // Prepare workspace and cache directory
486  retval = MkdirDeep(workspace, 0755, false);
487  if (!retval) {
488  LogCvmfs(kLogCvmfs, kLogStderr, "Failed to create workspace %s",
489  workspace.c_str());
490  return 1;
491  }
492  if (dedicated_cachedir) {
493  retval = MkdirDeep(cachedir, 0755, false);
494  if (!retval) {
495  LogCvmfs(kLogCvmfs, kLogStderr, "Failed to create cache directory %s",
496  cachedir.c_str());
497  return 1;
498  }
499  }
500  retval = MkdirDeep("/var/run/cvmfs", 0755);
501  if (!retval) {
502  LogCvmfs(kLogCvmfs, kLogStderr, "Failed to create socket directory");
503  return 1;
504  }
505  sysret = chown(workspace.c_str(), uid_cvmfs, getegid());
506  if (sysret != 0) {
507  LogCvmfs(kLogCvmfs, kLogStderr, "Failed to transfer ownership of %s to %s",
508  workspace.c_str(), cvmfs_user.c_str());
509  return 1;
510  }
511  if (dedicated_cachedir) {
512  sysret = chown(cachedir.c_str(), uid_cvmfs, getegid());
513  if (sysret != 0) {
515  "Failed to transfer ownership of %s to %s",
516  cachedir.c_str(), cvmfs_user.c_str());
517  return 1;
518  }
519  }
520  sysret = chown("/var/run/cvmfs", uid_cvmfs, getegid());
521  if (sysret != 0) {
522  LogCvmfs(kLogCvmfs, kLogStderr, "Failed to transfer ownership of %s to %s",
523  "/var/run/cvmfs", cvmfs_user.c_str());
524  return 1;
525  }
526 
527  // Set maximum number of files
528 #ifdef __APPLE__
529  string param;
530  if (options_manager_.GetValue("CVMFS_NFILES", &param)) {
531  sanitizer::IntegerSanitizer integer_sanitizer;
532  if (!integer_sanitizer.IsValid(param)) {
533  LogCvmfs(kLogCvmfs, kLogStderr, "Invalid CVMFS_NFILES: %s",
534  param.c_str());
535  return 1;
536  }
537  int nfiles = String2Uint64(param);
538  if ((nfiles < 128) || (nfiles > 524288)) {
539  LogCvmfs(kLogCvmfs, kLogStderr, "Invalid CVMFS_NFILES: %s",
540  param.c_str());
541  return 1;
542  }
543  int nfiles_all = nfiles + 512;
544  int sys_nfiles, sys_nfiles_all;
545  size_t len = sizeof(sys_nfiles);
546  int mib[2];
547  mib[0] = CTL_KERN;
548  mib[1] = KERN_MAXFILESPERPROC;
549  retval = sysctl(mib, 2, &sys_nfiles, &len, NULL, 0);
550  if ((retval != 0) || (sys_nfiles < 0)) {
551  LogCvmfs(kLogCvmfs, kLogStderr, "Failed to get KERN_MAXFILESPERPROC");
552  return 1;
553  }
554  if (sys_nfiles < nfiles) {
555  mib[1] = KERN_MAXFILES;
556  retval = sysctl(mib, 2, &sys_nfiles_all, &len, NULL, 0);
557  if ((retval != 0) || (sys_nfiles_all < 0)) {
558  LogCvmfs(kLogCvmfs, kLogStderr, "Failed to get KERN_MAXFILES");
559  return 1;
560  }
561  if (sys_nfiles_all < nfiles_all) {
562  retval = sysctl(mib, 2, NULL, NULL, &nfiles_all, sizeof(nfiles_all));
563  if (retval != 0) {
564  LogCvmfs(kLogCvmfs, kLogStderr, "Failed to set KERN_MAXFILES");
565  return 1;
566  }
567  }
568  mib[1] = KERN_MAXFILESPERPROC;
569  retval = sysctl(mib, 2, NULL, NULL, &nfiles_all, sizeof(nfiles_all));
570  if (retval != 0) {
571  LogCvmfs(kLogCvmfs, kLogStderr, "Failed to set KERN_MAXFILESPERPROC");
572  return 1;
573  }
574  }
575  }
576 #endif
577 
578  AddMountOption("system_mount", &mount_options);
579  AddMountOption("fsname=cvmfs2", &mount_options);
580  AddMountOption("allow_other", &mount_options);
581  AddMountOption("grab_mountpoint", &mount_options);
582  AddMountOption("uid=" + StringifyInt(uid_cvmfs), &mount_options);
583  AddMountOption("gid=" + StringifyInt(gid_cvmfs), &mount_options);
584  if (options_manager_.IsDefined("CVMFS_DEBUGLOG"))
585  AddMountOption("debug", &mount_options);
586 
587  const string cvmfs_binary = GetCvmfsBinary();
588  if (cvmfs_binary.empty()) {
589  LogCvmfs(kLogCvmfs, kLogStderr, "Failed to locate the cvmfs2 binary");
590  return 1;
591  }
592 
593  // Dry run early exit
594  if (dry_run) {
595  string cmd = cvmfs_binary + " -o " + JoinStrings(mount_options, ",") +
596  " " + fqrn + " " + mountpoint;
597  if (has_fuse_group) {
598  cmd = "sg fuse -c \"" + cmd + "\"";
599  }
600  LogCvmfs(kLogCvmfs, kLogStdout, "%s", cmd.c_str());
601  return 0;
602  }
603 
604  // Real mount, add supplementary fuse group
605  if (has_fuse_group) {
606  retval = AddGroup2Persona(gid_fuse);
607  if (!retval) {
608  LogCvmfs(kLogCvmfs, kLogStderr, "Failed to add fuse to "
609  " the list of supplementary groups");
610  return 1;
611  }
612  }
613 
614  // Exec cvmfs2, from here on errors return 32 (mount error)
615  int fd_stdin, fd_stdout, fd_stderr;
616  pid_t pid_cvmfs;
617  vector<string> cvmfs_args;
618  cvmfs_args.push_back("-o");
619  cvmfs_args.push_back(JoinStrings(mount_options, ","));
620  cvmfs_args.push_back(fqrn);
621  cvmfs_args.push_back(mountpoint);
622  retval = ExecuteBinary(&fd_stdin, &fd_stdout, &fd_stderr,
623  cvmfs_binary, cvmfs_args, false, &pid_cvmfs);
624  if (!retval) {
625  LogCvmfs(kLogCvmfs, kLogStderr, "Failed to launch %s",
626  cvmfs_binary.c_str());
627  return 32;
628  }
629  close(fd_stdin);
630 
631  // Print stdout / stderr and collect exit code
632  int nfds = fd_stdout > fd_stderr ? fd_stdout + 1 : fd_stderr + 1;
633  fd_set readfds;
634  bool stdout_open = true;
635  bool stderr_open = true;
636  int status = 0;
637  int ended = false;
638 
639  do {
640  FD_ZERO(&readfds);
641  if (stdout_open) FD_SET(fd_stdout, &readfds);
642  if (stderr_open) FD_SET(fd_stderr, &readfds);
643 
644  struct timeval timeout;
645  timeout.tv_sec = 0;
646  timeout.tv_usec = 100;
647  retval = select(nfds, &readfds, NULL, NULL, &timeout);
648  if ((retval == -1) && (errno != EINTR)) {
649  LogCvmfs(kLogCvmfs, kLogStderr, "Failed to pipe stdout/stderr");
650  return 32;
651  }
652 
653  char buf;
654  ssize_t num_bytes;
655  if (FD_ISSET(fd_stdout, &readfds)) {
656  num_bytes = read(fd_stdout, &buf, 1);
657  switch (num_bytes) {
658  case 0:
659  stdout_open = false;
660  break;
661  case 1:
663  break;
664  default:
665  LogCvmfs(kLogCvmfs, kLogStderr, "Failed reading stdout");
666  return 32;
667  }
668  }
669  if (FD_ISSET(fd_stderr, &readfds)) {
670  num_bytes = read(fd_stderr, &buf, 1);
671  switch (num_bytes) {
672  case 0:
673  stderr_open = false;
674  break;
675  case 1:
677  break;
678  default:
679  LogCvmfs(kLogCvmfs, kLogStderr, "Failed reading stderr");
680  return 32;
681  }
682  }
683  ended = (waitpid(pid_cvmfs, &status, WNOHANG) == pid_cvmfs);
684  } while ((stdout_open || stderr_open) && !ended);
685  close(fd_stdout);
686  close(fd_stderr);
687 
688  if (WIFEXITED(status) && (WEXITSTATUS(status) == 0))
689  return 0;
690 
691  return 32;
692 }
#define LogCvmfs(source, mask,...)
Definition: logging.h:25
int MakeSocket(const std::string &path, const int mode)
Definition: posix.cc:327
struct stat64 platform_stat64
static bool CheckFuse()
Definition: mount.cvmfs.cc:72
static bool CheckConcurrentMount(const string &fqrn, const string &workspace, string *mountpointp)
Definition: mount.cvmfs.cc:137
static bool GetCacheDir(const string &fqrn, string *cachedir)
Definition: mount.cvmfs.cc:213
NameString GetFileName(const PathString &path)
Definition: shortstring.cc:29
static void Usage(const char *progname)
static bool CheckProxy()
Definition: mount.cvmfs.cc:126
string JoinStrings(const vector< string > &strings, const string &joint)
Definition: string.cc:325
bool IsOn(const std::string &param_value) const
Definition: options.cc:409
static bool WaitForReload(const std::string &mountpoint)
Definition: mount.cvmfs.cc:255
static std::string GetCvmfsBinary()
Definition: mount.cvmfs.cc:296
void SendMsg2Socket(const int fd, const std::string &msg)
Definition: posix.cc:655
static bool CheckStrictMount(const string &fqrn)
Definition: mount.cvmfs.cc:96
int platform_stat(const char *path, platform_stat64 *buf)
void ParseDefault(const std::string &fqrn)
Definition: options.cc:282
bool AddGroup2Persona(const gid_t gid)
Definition: posix.cc:1397
void SwitchTemplateManager(OptionsTemplateManager *opt_templ_mgr_param)
Definition: options.cc:92
bool SymlinkExists(const std::string &path)
Definition: posix.cc:819
bool IsValid(const std::string &input) const
Definition: sanitizer.cc:114
static int AttachMount(const std::string &mountpoint, const std::string &fqrn, int fuse_fd)
Definition: mount.cvmfs.cc:321
int main()
Definition: helper_allow.cc:16
bool FileExists(const std::string &path)
Definition: posix.cc:787
static void AddMountOption(const string &option, vector< string > *mount_options)
Definition: mount.cvmfs.cc:49
vector< string > SplitString(const string &str, char delim)
Definition: string.cc:290
bool MkdirDeep(const std::string &path, const mode_t mode, bool verify_writable)
Definition: posix.cc:842
string StringifyInt(const int64_t value)
Definition: string.cc:78
bool GetGidOf(const std::string &groupname, gid_t *gid)
Definition: posix.cc:1363
static string MkFqrn(const string &repository)
Definition: mount.cvmfs.cc:56
std::string CreateTempDir(const std::string &path_prefix)
Definition: posix.cc:1043
bool HasPrefix(const string &str, const string &prefix, const bool ignore_case)
Definition: string.cc:267
bool GetValue(const std::string &key, std::string *value) const
Definition: options.cc:376
bool DirectoryExists(const std::string &path)
Definition: posix.cc:809
bool ExecuteBinary(int *fd_stdin, int *fd_stdout, int *fd_stderr, const std::string &binary_path, const std::vector< std::string > &argv, const bool double_fork, pid_t *child_pid)
Definition: posix.cc:1655
static int GetExistingFuseFd(const string &fqrn, const string &workspace, uid_t cvmfs_uid)
Definition: mount.cvmfs.cc:158
static bool GetCvmfsUser(string *cvmfs_user)
Definition: mount.cvmfs.cc:284
int ConnectSocket(const std::string &path)
Definition: posix.cc:423
string Base64(const string &data)
Definition: string.cc:504
BashOptionsManager options_manager_
Definition: mount.cvmfs.cc:34
uint64_t String2Uint64(const string &value)
Definition: string.cc:228
bool GetUidOf(const std::string &username, uid_t *uid, gid_t *main_gid)
Definition: posix.cc:1340
static bool GetWorkspace(const string &fqrn, string *workspace)
Definition: mount.cvmfs.cc:237
void SafeSleepMs(const unsigned ms)
Definition: posix.cc:1968
std::string MakeCanonicalPath(const std::string &path)
Definition: posix.cc:97
bool IsDefined(const std::string &key)
Definition: options.cc:370
bool IsMountPoint(const std::string &path)
Definition: posix.cc:262
int RecvFdFromSocket(int msg_fd)
Definition: posix.cc:704