CernVM-FS  2.9.0
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
libcvmfs_legacy.cc
Go to the documentation of this file.
1 
8 #include "cvmfs_config.h"
9 #include "libcvmfs.h"
10 
11 #include <cstdio>
12 #include <cstring>
13 #include <string>
14 
15 #include "libcvmfs_int.h"
16 #include "loader.h"
17 #include "options.h"
18 #include "util/string.h"
19 
20 using namespace std; // NOLINT
21 
22 static int set_option(char const *name, char const *value, bool *var) {
23  if (*value != '\0') {
24  fprintf(stderr, "Option %s=%s contains a value when none was expected.\n",
25  name, value);
26  return -1;
27  }
28  *var = true;
29  return 0;
30 }
31 
32 
33 static int set_option(char const *name, char const *value, unsigned *var) {
34  unsigned v = 0;
35  int end = 0;
36  int rc = sscanf(value, "%u%n", &v, &end);
37  if (rc != 1 || value[end] != '\0') {
38  fprintf(stderr, "Invalid unsigned integer value for %s=%s\n", name, value);
39  return -1;
40  }
41  *var = v;
42  return 0;
43 }
44 
45 
46 static int set_option(char const *name, char const *value, int *var) {
47  int v = 0;
48  int end = 0;
49  int rc = sscanf(value, "%d%n", &v, &end);
50  if (rc != 1 || value[end] != '\0') {
51  fprintf(stderr, "Invalid integer value for %s=%s\n", name, value);
52  return -1;
53  }
54  *var = v;
55  return 0;
56 }
57 
58 
59 static int set_option(char const *name, char const *value, string *var) {
60  *var = value;
61  return 0;
62 }
63 
64 
65 #define CVMFS_OPT(var) if (strcmp(name, #var) == 0) \
66  return ::set_option(name, value, &var)
67 
68 
70  int set_option(char const *name, char const *value) {
71  CVMFS_OPT(allow_unsigned);
72  CVMFS_OPT(blacklist);
73  CVMFS_OPT(deep_mount); // deprecated
74  CVMFS_OPT(fallback_proxies);
75  CVMFS_OPT(mountpoint);
76  CVMFS_OPT(proxies);
77  CVMFS_OPT(pubkey);
78  CVMFS_OPT(repo_name);
79  CVMFS_OPT(timeout);
80  CVMFS_OPT(timeout_direct);
81  CVMFS_OPT(tracefile);
82  CVMFS_OPT(url);
83 
84  fprintf(stderr, "Unknown repo option: %s\n", name);
85  return -1;
86  }
87 
88  int verify_sanity() {
89  if (mountpoint.empty() && !repo_name.empty()) {
90  mountpoint = "/cvmfs/";
91  mountpoint += repo_name;
92  }
93  while (mountpoint.length() > 0 && mountpoint[mountpoint.length()-1] == '/')
94  {
95  mountpoint.resize(mountpoint.length()-1);
96  }
97 
98  return LIBCVMFS_FAIL_OK;
99  }
100 
102  timeout(2),
103  timeout_direct(2),
104  pubkey("/etc/cvmfs/keys/cern.ch.pub"),
105  blacklist(""),
106  allow_unsigned(false) {}
107 
108  unsigned timeout;
109  unsigned timeout_direct;
110  std::string url;
111  std::string external_url;
112  std::string proxies;
113  std::string fallback_proxies;
114  std::string tracefile; // unused
115  std::string pubkey;
116  std::string deep_mount;
117  std::string blacklist;
118  std::string repo_name;
119  std::string root_hash;
120  std::string mountpoint;
122 };
123 
124 
126  int set_option(char const *name, char const *value) {
127  CVMFS_OPT(alien_cache);
128  CVMFS_OPT(alien_cachedir);
129  CVMFS_OPT(cache_directory);
130  CVMFS_OPT(cachedir);
131  CVMFS_OPT(lock_directory);
132  CVMFS_OPT(change_to_cache_directory);
133  CVMFS_OPT(logfile);
134  CVMFS_OPT(log_file);
135  CVMFS_OPT(log_prefix);
136  CVMFS_OPT(log_syslog_level);
138  CVMFS_OPT(max_open_files);
139  CVMFS_OPT(nofiles);
140  CVMFS_OPT(quota_limit);
141  CVMFS_OPT(quota_threshold);
142  CVMFS_OPT(rebuild_cachedb);
143 
144  fprintf(stderr, "Unknown global option: %s\n", name);
145  return LIBCVMFS_FAIL_BADOPT;
146  }
147 
149  // Alias handling
150  if ((nofiles >= 0) && (max_open_files != 0) && (nofiles != max_open_files))
151  return LIBCVMFS_FAIL_BADOPT;
152  if (nofiles >= 0)
153  max_open_files = nofiles;
154 
155  if ((syslog_level >= 0) && (log_syslog_level != 0) &&
156  (syslog_level != log_syslog_level))
157  {
158  return LIBCVMFS_FAIL_BADOPT;
159  }
160  if (syslog_level >= 0)
161  log_syslog_level = syslog_level;
162  if (log_syslog_level < 0)
163  log_syslog_level = 3;
164 
165  if ((logfile != "") && (log_file != "") && (log_file != logfile))
166  return LIBCVMFS_FAIL_BADOPT;
167  if (logfile != "")
168  log_file = logfile;
169 
170  if ((cachedir != "") && (cache_directory != "") &&
171  (cache_directory != cachedir))
172  {
173  return LIBCVMFS_FAIL_BADOPT;
174  }
175  if (cachedir != "")
176  cache_directory = cachedir;
177 
178  return LIBCVMFS_FAIL_OK;
179  }
180 
182  : change_to_cache_directory(false)
183  , alien_cache(false)
184  , syslog_level(-1)
185  , log_syslog_level(-1)
186  , nofiles(-1)
187  , max_open_files(0)
188  , quota_limit(0)
189  , quota_threshold(0)
190  , rebuild_cachedb(0)
191  { }
192 
193  std::string cache_directory;
194  std::string cachedir; // Alias of cache_directory
195  std::string alien_cachedir;
196  std::string lock_directory;
199 
202  std::string log_prefix;
203  std::string logfile;
204  std::string log_file;
205 
206  int nofiles;
207  int max_open_files; // Alias of nofiles
208 
209  // Currently ignored
210  unsigned quota_limit;
211  unsigned quota_threshold;
213 };
214 
215 
219 template <class DerivedT>
220 struct cvmfs_options : public DerivedT {
221  int set_option(char const *name, char const *value) {
222  return DerivedT::set_option(name, value);
223  }
224 
225  int parse_options(char const *options)
226  {
227  while (*options) {
228  char const *next = options;
229  string name;
230  string value;
231 
232  // get the option name
233  for (next=options; *next && *next != ',' && *next != '='; next++) {
234  if (*next == '\\') {
235  next++;
236  if (*next == '\0') break;
237  }
238  name += *next;
239  }
240 
241  if (*next == '=') {
242  next++;
243  }
244 
245  // get the option value
246  for (; *next && *next != ','; next++) {
247  if (*next == '\\') {
248  next++;
249  if (*next == '\0') break;
250  }
251  value += *next;
252  }
253 
254  if (!name.empty() || !value.empty()) {
255  int result = set_option(name.c_str(), value.c_str());
256  if (result != 0) {
257  return result;
258  }
259  }
260 
261  if (*next == ',') next++;
262  options = next;
263  }
264 
265  return DerivedT::verify_sanity();
266  }
267 };
268 
271 
275 static void usage() {
276  struct cvmfs_repo_options defaults;
277  fprintf(stderr,
278  "CernVM-FS version %s\n"
279  "Copyright (c) 2009- CERN\n"
280  "All rights reserved\n\n"
281  "Please visit http://cernvm.cern.ch/project/info for license details "
282  "and author list.\n\n"
283 
284  "libcvmfs options are expected in the form: option1,option2,option3,...\n"
285  "Within an option, the characters , and \\ must be preceded by \\.\n\n"
286 
287  "There are two types of options (global and repository specifics)\n"
288  " cvmfs_init() expects global options\n"
289  " cvmfs_attach_repo() expects repository specific options\n"
290 
291  "global options are:\n"
292  " cache_directory/cachedir=DIR Where to store disk cache\n"
293  " change_to_cache_directory Performs a cd to the cache directory "
294  "(performance tweak)\n"
295  " alien_cache Treat cache directory as alien cache\n"
296  " alien_cachedir=DIR Explicitly set an alien cache directory\n"
297  " lock_directory=DIR Directory for per instance lock files.\n"
298  " Needs to be on a file system with POSIX locks.\n"
299  " Should be different from alien cache directory."
300  " \nDefaults to cache_directory.\n"
301  " (log_)syslog_level=LEVEL Sets the level used for syslog to "
302  "DEBUG (1), INFO (2), or NOTICE (3).\n"
303  " Default is NOTICE.\n"
304  " log_prefix String to use as a log prefix in syslog\n"
305  " log_file/logfile Logs all messages to FILE instead of "
306  "stderr and daemonizes.\n"
307  " Makes only sense for the debug version\n"
308  " nofiles/max_open_files Set the maximum number of open files "
309  "for CernVM-FS process (soft limit)\n\n"
310 
311  "repository specific options are:"
312  " repo_name=REPO_NAME Unique name of the mounted repository, "
313  "e.g. atlas.cern.ch\n"
314  " url=REPOSITORY_URL The URL of the CernVM-FS server(s): "
315  "'url1;url2;...'\n"
316  " timeout=SECONDS Timeout for network operations (default is %d)\n"
317  " timeout_direct=SECONDS Timeout for network operations without proxy "
318  "(default is %d)\n"
319  " proxies=HTTP_PROXIES Set the HTTP proxy list, such as "
320  "'proxy1|proxy2;DIRECT'\n"
321  " fallback_proxies=PROXIES Set the fallback proxy list, such as "
322  "'proxy1;proxy2'\n"
323  " tracefile=FILE Trace FUSE opaerations into FILE\n"
324  " pubkey=PEMFILE Public RSA key that is used to verify the "
325  "whitelist signature.\n"
326  " allow_unsigned Accept unsigned catalogs "
327  "(allows man-in-the-middle attacks)\n"
328  " deep_mount=PREFIX Path prefix if a repository is mounted on a "
329  "nested catalog,\n"
330  " i.e. deep_mount=/software/15.0.1\n"
331  " mountpoint=PATH Path to root of repository, "
332  "e.g. /cvmfs/atlas.cern.ch\n"
333  " blacklist=FILE Local blacklist for invalid certificates. "
334  "Has precedence over the whitelist.\n",
335  PACKAGE_VERSION, defaults.timeout, defaults.timeout_direct);
336 }
337 
338 
343  const int unknown = -10;
344 
345  switch (code) {
346  case loader::kFailOk:
347  return LIBCVMFS_FAIL_OK;
349  return unknown; // missing constant
351  return LIBCVMFS_FAIL_BADOPT;
353  return LIBCVMFS_FAIL_NOFILES;
354  case loader::kFailMount:
359  return unknown;
361  return LIBCVMFS_FAIL_MKCACHE;
362  case loader::kFailPeers:
364  return unknown;
365  case loader::kFailQuota:
368  case loader::kFailTalk:
369  return unknown;
380  return unknown;
381  case loader::kFailWpad:
384  return LIBCVMFS_FAIL_LOCKFILE;
385  default:
386  return unknown;
387  }
388 }
389 
390 
391 SimpleOptionsParser *cvmfs_options_init_legacy(char const *legacy_options) {
392  global_options global_opts;
393  int parse_result = global_opts.parse_options(legacy_options);
394  if (parse_result != 0) {
395  fprintf(stderr, "Invalid CVMFS global options: %s.\n", legacy_options);
396  usage();
397  return NULL;
398  }
399 
400  SimpleOptionsParser *options_mgr = cvmfs_options_init();
401  options_mgr->SetValue("CVMFS_CACHE_DIR", global_opts.cache_directory);
402  if (!global_opts.lock_directory.empty()) {
403  options_mgr->SetValue("CVMFS_WORKSPACE", global_opts.lock_directory);
404  }
405  if (global_opts.alien_cache) {
406  options_mgr->SetValue("CVMFS_ALIEN_CACHE", global_opts.cache_directory);
407  }
408  if (!global_opts.alien_cachedir.empty()) {
409  options_mgr->SetValue("CVMFS_ALIEN_CACHE", global_opts.alien_cachedir);
410  }
411  // Note: as of version 2.4 CVMFS_CWD_CACHE support was dropped due to
412  // disproportional large complexity in the FileSystem class
413  // if (global_opts.change_to_cache_directory) {
414  // options_mgr->SetValue("CVMFS_CWD_CACHE", "on");
415  // }
416  options_mgr->SetValue("CVMFS_SYSLOG_LEVEL",
417  StringifyInt(global_opts.log_syslog_level));
418  if (!global_opts.log_prefix.empty()) {
419  options_mgr->SetValue("CVMFS_SYSLOG_PREFIX", global_opts.log_prefix);
420  }
421  if (!global_opts.log_file.empty()) {
422  options_mgr->SetValue("CVMFS_DEBUGLOG", global_opts.log_file);
423  }
424  if (global_opts.max_open_files > 0) {
425  options_mgr->SetValue("CVMFS_NFILES",
426  StringifyInt(global_opts.max_open_files));
427  }
428 
429  return options_mgr;
430 }
431 
432 
433 int cvmfs_init(char const *options) {
434  SimpleOptionsParser *options_mgr = cvmfs_options_init_legacy(options);
435  if (options_mgr == NULL) {
436  fprintf(stderr, "Invalid CVMFS global options: %s.\n", options);
437  usage();
438  return LIBCVMFS_FAIL_BADOPT;
439  }
440 
441  loader::Failures result = LibGlobals::Initialize(options_mgr);
443  if (result != loader::kFailOk)
445  return TranslateReturnValue(result);
446 }
447 
448 
450  SimpleOptionsParser *opts,
451  const char *legacy_options)
452 {
453  // Parse options
454  repo_options repo_opts;
455  int parse_result = repo_opts.parse_options(legacy_options);
456  if ((parse_result != 0) || repo_opts.url.empty()) {
457  return NULL;
458  }
459 
460  SimpleOptionsParser *options_mgr = cvmfs_options_clone(opts);
461  options_mgr->SwitchTemplateManager(
462  new DefaultOptionsTemplateManager(repo_opts.repo_name));
463  options_mgr->SetValue("CVMFS_FQRN", repo_opts.repo_name);
464  options_mgr->SetValue("CVMFS_TIMEOUT", StringifyInt(repo_opts.timeout));
465  options_mgr->SetValue("CVMFS_TIMEOUT_DIRECT",
466  StringifyInt(repo_opts.timeout_direct));
467  options_mgr->SetValue("CVMFS_SERVER_URL", repo_opts.url);
468  if (!repo_opts.external_url.empty()) {
469  options_mgr->SetValue("CVMFS_EXTERNAL_URL", repo_opts.external_url);
470  }
471  if (repo_opts.proxies.empty()) {
472  if (!options_mgr->IsDefined("CVMFS_HTTP_PROXY"))
473  options_mgr->SetValue("CVMFS_HTTP_PROXY", "DIRECT");
474  } else {
475  options_mgr->SetValue("CVMFS_HTTP_PROXY", repo_opts.proxies);
476  }
477  options_mgr->SetValue("CVMFS_FALLBACK_PROXY", repo_opts.fallback_proxies);
478  options_mgr->SetValue("CVMFS_PUBLIC_KEY", repo_opts.pubkey);
479  if (!repo_opts.blacklist.empty()) {
480  options_mgr->SetValue("CVMFS_BLACKLIST", repo_opts.blacklist);
481  }
482  if (!repo_opts.root_hash.empty()) {
483  options_mgr->SetValue("CVMFS_ROOT_HASH", repo_opts.root_hash);
484  }
485 
486  return options_mgr;
487 }
488 
489 
490 LibContext* cvmfs_attach_repo(char const *options)
491 {
492  SimpleOptionsParser *options_mgr_base = cvmfs_options_init();
493  SimpleOptionsParser *options_mgr =
494  cvmfs_options_clone_legacy(options_mgr_base, options);
495  cvmfs_options_fini(options_mgr_base);
496  if (options_mgr == NULL) {
497  fprintf(stderr, "Invalid CVMFS options: %s.\n", options);
498  usage();
499  return NULL;
500  }
501 
502  string repo_name;
503  bool retval = options_mgr->GetValue("CVMFS_FQRN", &repo_name);
504  assert(retval);
505  LibContext *ctx = LibContext::Create(repo_name, options_mgr);
506  assert(ctx != NULL);
507  if (ctx->mount_point()->boot_status() != loader::kFailOk) {
508  LogCvmfs(kLogCvmfs, kLogDebug, "failed attaching %s, %s (%d)",
509  repo_name.c_str(), ctx->mount_point()->boot_error().c_str(),
510  ctx->mount_point()->boot_status());
511  delete ctx;
512  return NULL;
513  }
514  ctx->set_options_mgr(options_mgr);
515  return ctx;
516 }
static void usage()
#define LogCvmfs(source, mask,...)
Definition: logging.h:20
struct cvmcache_context * ctx
static LibContext * Create(const std::string &fqrn, OptionsManager *options_mgr)
bool GetValue(const std::string &key, std::string *value)
Definition: options.cc:376
#define LIBCVMFS_FAIL_MKCACHE
Definition: libcvmfs.h:54
loader::Failures boot_status()
Definition: mountpoint.h:74
cvmfs_context * cvmfs_attach_repo(char const *options)
std::string external_url
cvmfs_option_map * cvmfs_options_clone(cvmfs_option_map *opts)
cvmfs_option_map * cvmfs_options_init()
assert((mem||(size==0))&&"Out Of Memory")
#define CVMFS_OPT(var)
void set_options_mgr(OptionsManager *value)
Definition: libcvmfs_int.h:126
cvmfs_options< cvmfs_global_options > global_options
static void cvmfs_init(void *userdata, struct fuse_conn_info *conn)
Definition: cvmfs.cc:1536
void SwitchTemplateManager(OptionsTemplateManager *opt_templ_mgr_param)
Definition: options.cc:92
#define LIBCVMFS_FAIL_NOFILES
Definition: libcvmfs.h:53
void SetValue(const std::string &key, const std::string &value)
Definition: options.cc:466
int set_option(char const *name, char const *value)
void cvmfs_options_fini(cvmfs_option_map *opts)
static loader::Failures Initialize(OptionsManager *options_mgr)
Definition: libcvmfs_int.cc:94
#define LIBCVMFS_FAIL_OK
Definition: libcvmfs.h:52
int set_option(char const *name, char const *value)
int parse_options(char const *options)
std::string boot_error()
Definition: mountpoint.h:75
#define LIBCVMFS_FAIL_BADOPT
Definition: libcvmfs.h:59
string StringifyInt(const int64_t value)
Definition: string.cc:78
cvmfs_option_map * cvmfs_options_init_legacy(const char *legacy_options)
#define LIBCVMFS_FAIL_INITCACHE
Definition: libcvmfs.h:57
Failures
Definition: loader.h:27
std::string fallback_proxies
static LibGlobals * GetInstance()
Definition: libcvmfs_int.cc:85
cvmfs_options< cvmfs_repo_options > repo_options
MountPoint * mount_point()
Definition: libcvmfs_int.h:125
#define LIBCVMFS_FAIL_LOCKFILE
Definition: libcvmfs.h:56
cvmfs_option_map * cvmfs_options_clone_legacy(cvmfs_option_map *opts, const char *legacy_options)
static int set_option(char const *name, char const *value, bool *var)
#define LIBCVMFS_FAIL_INITQUOTA
Definition: libcvmfs.h:58
bool IsDefined(const std::string &key)
Definition: options.cc:370
int set_option(char const *name, char const *value)
void set_options_mgr(OptionsManager *value)
Definition: libcvmfs_int.h:67
static void CleanupInstance()
static int TranslateReturnValue(loader::Failures code)