GCC Code Coverage Report


Directory: cvmfs/
File: cvmfs/fuse_main.cc
Date: 2024-04-28 02:33:07
Exec Total Coverage
Lines: 0 69 0.0%
Branches: 0 51 0.0%

Line Branch Exec Source
1 /**
2 * This file is part of the CernVM File System.
3 *
4 * The Fuse module entry point. Dynamically selects either the libfuse3
5 * cvmfs fuse module or the libfuse2 one, depending on the availability and on
6 * the mount options.
7 *
8 */
9
10 #include <dlfcn.h>
11 #include <unistd.h>
12
13 #include <cassert>
14 #include <cstdlib>
15 #include <cstring>
16 #include <string>
17 #include <vector>
18
19 #include "fuse_main.h"
20 #include "util/logging.h"
21 #include "util/platform.h"
22 #include "util/smalloc.h"
23 #include "util/string.h"
24
25 using namespace stub; // NOLINT
26
27
28 int main(int argc, char **argv) {
29 // Getopt option parsing modifies globals and the argv vector
30 int opterr_save = opterr;
31 int optc = argc;
32 assert(optc > 0);
33 char **optv = reinterpret_cast<char **>(smalloc(optc * sizeof(char *)));
34 for (int i = 0; i < optc; ++i) {
35 optv[i] = strdup(argv[i]);
36 }
37
38 bool debug = false;
39 unsigned enforce_libfuse = 0;
40 int c;
41 opterr = 0;
42 while ((c = getopt(optc, optv, "do:")) != -1) {
43 switch (c) {
44 case 'd':
45 debug = true;
46 break;
47 case 'o':
48 std::vector<std::string> mount_options = SplitString(optarg, ',');
49 for (unsigned i = 0; i < mount_options.size(); ++i) {
50 if (mount_options[i] == "debug") {
51 debug = true;
52 }
53
54 if (HasPrefix(mount_options[i], "libfuse=", false /*ign_case*/)) {
55 std::vector<std::string> t = SplitString(mount_options[i], '=');
56 enforce_libfuse = String2Uint64(t[1]);
57 if (debug) {
58 LogCvmfs(kLogCvmfs, kLogDebug | kLogStdout,
59 "Debug: enforcing libfuse version %u", enforce_libfuse);
60 }
61 }
62 }
63 break;
64 }
65 }
66 opterr = opterr_save;
67 optind = 1;
68 for (int i = 0; i < optc; ++i) {
69 free(optv[i]);
70 }
71 free(optv);
72
73 std::string libname_fuse2 = platform_libname("cvmfs_fuse_stub");
74 std::string libname_fuse3 = platform_libname("cvmfs_fuse3_stub");
75
76 std::string error_messages;
77
78 if (enforce_libfuse > 0) {
79 if ((enforce_libfuse < 2) || (enforce_libfuse > 3)) {
80 LogCvmfs(kLogCvmfs, kLogStderr | kLogSyslogErr,
81 "Error: invalid libfuse version '%u', valid values are 2 or 3.",
82 enforce_libfuse);
83 return 1;
84 }
85 }
86
87 std::string local_lib_path = "./";
88 if (getenv("CVMFS_LIBRARY_PATH") != NULL) {
89 local_lib_path = getenv("CVMFS_LIBRARY_PATH");
90 if (!local_lib_path.empty() && (*local_lib_path.rbegin() != '/'))
91 local_lib_path.push_back('/');
92 }
93
94 // Try loading libfuse3 module, else fallback to version 2
95 std::vector<std::string> library_paths;
96 if ((enforce_libfuse == 0) || (enforce_libfuse == 3)) {
97 library_paths.push_back(local_lib_path + libname_fuse3);
98 library_paths.push_back("/usr/lib/" + libname_fuse3);
99 library_paths.push_back("/usr/lib64/" + libname_fuse3);
100 #ifdef __APPLE__
101 library_paths.push_back("/usr/local/lib/" + libname_fuse3);
102 #endif
103 }
104 if ((enforce_libfuse == 0) || (enforce_libfuse == 2)) {
105 library_paths.push_back(local_lib_path + libname_fuse2);
106 library_paths.push_back("/usr/lib/" + libname_fuse2);
107 library_paths.push_back("/usr/lib64/" + libname_fuse2);
108 #ifdef __APPLE__
109 library_paths.push_back("/usr/local/lib/" + libname_fuse2);
110 #endif
111 }
112
113 void *library_handle;
114 std::vector<std::string>::const_iterator i = library_paths.begin();
115 std::vector<std::string>::const_iterator iend = library_paths.end();
116 for (; i != iend; ++i) {
117 library_handle = dlopen(i->c_str(), RTLD_NOW | RTLD_LOCAL);
118 if (library_handle != NULL) {
119 if (debug) {
120 LogCvmfs(kLogCvmfs, kLogDebug | kLogStdout, "Debug: using library %s",
121 i->c_str());
122 }
123 break;
124 }
125
126 error_messages += std::string(dlerror()) + "\n";
127 }
128
129 if (!library_handle) {
130 LogCvmfs(kLogCvmfs, kLogStderr | kLogSyslogErr,
131 "Error: failed to load cvmfs library, tried: '%s'\n%s",
132 JoinStrings(library_paths, "' '").c_str(), error_messages.c_str());
133 return 1;
134 }
135
136 CvmfsStubExports **exports_ptr = reinterpret_cast<CvmfsStubExports **>(
137 dlsym(library_handle, "g_cvmfs_stub_exports"));
138 if (exports_ptr == NULL) {
139 LogCvmfs(kLogCvmfs, kLogStderr | kLogSyslogErr,
140 "Error: symbol g_cvmfs_stub_exports not found");
141 return 1;
142 }
143
144 return (*exports_ptr)->fn_main(argc, argv);
145 }
146
147