CernVM-FS  2.11.0
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
cmd_abort.cc
Go to the documentation of this file.
1 
5 #include "cvmfs_config.h"
6 #include "cmd_abort.h"
7 
8 #include <cstdio>
9 #include <string>
10 
11 #include "publish/cmd_util.h"
12 #include "publish/except.h"
13 #include "publish/repository.h"
14 #include "publish/settings.h"
15 #include "util/logging.h"
16 #include "util/pointer.h"
17 #include "util/posix.h"
18 #include "util/string.h"
19 #include "whitelist.h"
20 
21 namespace {
22  std::string StripTrailingPath(const std::string& repo_and_path) {
23  if (!repo_and_path.empty()) {
24  std::vector<std::string> tokens = SplitString(repo_and_path, '/');
25  return tokens[0];
26  }
27 
28  return "";
29  }
30 }
31 
32 namespace publish {
33 
34 int CmdAbort::Main(const Options &options) {
35  SettingsBuilder builder;
36  std::string session_dir = Env::GetEnterSessionDir();
37 
38  if (!session_dir.empty()) {
39  builder.SetConfigPath(session_dir);
40  }
41 
43  try {
44  // Legacy behaviour is that trailing paths after the repository name should
45  // be ignored, e.g. cvmfs_server abort repo.cern.ch/some/path is equivalent
46  // to cvmfs_server abort repo.cern.ch
47  std::string repository_ident = StripTrailingPath(
48  options.plain_args().empty() ? "" : options.plain_args()[0].value_str);
49  settings = builder.CreateSettingsPublisher(
50  repository_ident, true /* needs_managed */);
51  } catch (const EPublish &e) {
54  {
55  LogCvmfs(kLogCvmfs, kLogStderr | kLogSyslogErr, "CernVM-FS error: %s",
56  e.msg().c_str());
57  return 1;
58  }
59  throw;
60  }
61 
62  if (!SwitchCredentials(settings->owner_uid(), settings->owner_gid(),
63  false /* temporarily */))
64  {
65  throw EPublish("No write permission to repository",
67  }
68 
70  settings->transaction().spool_area().union_mnt() + "/",
71  false /* ignore_case */))
72  {
74  "Current working directory is in %s. Please release, "
75  "e.g. by 'cd $HOME'.",
76  settings->transaction().spool_area().union_mnt().c_str());
77  return 1;
78  }
79 
80  if (!options.Has("force")) {
82  "You are about to DISCARD ALL CHANGES OF THE CURRENT TRANSACTION "
83  "for %s! Are you sure (y/N)? ", settings->fqrn().c_str());
84  char answer[] = {0, 0, 0};
85  char *rv_charp = fgets(answer, 3, stdin);
86  if (rv_charp && (answer[0] != 'Y') && (answer[0] != 'y'))
87  return EINTR;
88  }
89 
90  std::vector<LsofEntry> lsof_entries =
91  Lsof(settings->transaction().spool_area().union_mnt());
92  if (!lsof_entries.empty()) {
93  if (options.Has("force")) {
95  "WARNING: Open file descriptors on %s (possible race!)"
96  "\nThe following lsof report might show the culprit:\n",
97  settings->transaction().spool_area().union_mnt().c_str());
98  } else {
100  "\nWARNING! There are open read-only file descriptors in %s\n"
101  " --> This is potentially harmful and might cause problems "
102  "later on.\n"
103  " We can anyway perform the requested operation, but this "
104  "will most likely\n"
105  " break other processes with open file descriptors on %s!\n"
106  "\n"
107  " The following lsof report might show the processes with "
108  "open file handles\n",
109  settings->transaction().spool_area().union_mnt().c_str(),
110  settings->transaction().spool_area().union_mnt().c_str());
111  }
112 
113  for (unsigned i = 0; i < lsof_entries.size(); ++i) {
114  std::string owner_name;
115  GetUserNameOf(lsof_entries[i].owner, &owner_name);
116  LogCvmfs(kLogCvmfs, kLogStdout, "%s %d %s %s",
117  lsof_entries[i].executable.c_str(),
118  lsof_entries[i].pid,
119  owner_name.c_str(),
120  lsof_entries[i].path.c_str());
121  }
122 
123  if (!options.Has("force")) {
125  "\n Do you want to proceed anyway? (y/N) ");
126  char answer[] = {0, 0, 0};
127  char *rv_charp = fgets(answer, 3, stdin);
128  if (rv_charp && (answer[0] != 'Y') && (answer[0] != 'y'))
129  return EINTR;
130  }
131  }
132 
133  UniquePtr<Publisher> publisher;
134  publisher = new Publisher(*settings);
135 
136  LogCvmfs(kLogCvmfs, kLogSyslog, "(%s) aborting transaction",
137  settings->fqrn().c_str());
138 
139  int rvi = CallServerHook("abort_before_hook", settings->fqrn());
140  if (rvi != 0) {
142  "abort hook failed, not aborting");
143  return rvi;
144  }
145 
146  try {
147  publisher->Abort();
148  } catch (const EPublish &e) {
150  LogCvmfs(kLogCvmfs, kLogStderr | kLogSyslogErr, "%s", e.msg().c_str());
151  return EINVAL;
152  }
153  }
154 
155  rvi = CallServerHook("abort_after_hook", settings->fqrn());
156  if (rvi != 0) {
158  "post abort hook failed");
159  return rvi;
160  }
161 
162  if (settings->transaction().in_enter_session()) {
164  "Discarding changes and closing current transaction...");
165  SafeWriteToFile("abort", session_dir + "/shellaction.marker", 0600);
166  publisher->ExitShell();
167  }
168 
169  return 0;
170 }
171 
172 } // namespace publish
#define LogCvmfs(source, mask,...)
Definition: logging.h:22
std::string StripTrailingPath(const std::string &repo_and_path)
Definition: cmd_abort.cc:22
SettingsPublisher * CreateSettingsPublisher(const std::string &ident, bool needs_managed=false)
Definition: settings.cc:590
int CallServerHook(const std::string &func, const std::string &fqrn, const std::string &path_hooks="/etc/cvmfs/cvmfs_server_hooks.sh")
Definition: cmd_util.cc:18
bool Has(const std::string &key) const
Definition: command.h:114
bool GetUserNameOf(uid_t uid, std::string *username)
Definition: posix.cc:1308
std::string msg() const
Definition: except.h:46
const SettingsPublisher & settings() const
Definition: repository.h:316
bool SafeWriteToFile(const std::string &content, const std::string &path, int mode)
Definition: posix.cc:1988
void SetConfigPath(const std::string &config_path)
Definition: settings.h:526
const std::vector< Argument > & plain_args() const
Definition: command.h:137
vector< string > SplitString(const string &str, char delim)
Definition: string.cc:290
bool HasPrefix(const string &str, const string &prefix, const bool ignore_case)
Definition: string.cc:267
EFailures failure() const
Definition: except.h:45
bool SwitchCredentials(const uid_t uid, const gid_t gid, const bool temporarily)
Definition: posix.cc:748
std::vector< LsofEntry > Lsof(const std::string &path)
Definition: posix.cc:1476
Publisher(const SettingsPublisher &settings, const bool exists=true)
Definition: repository.cc:603
std::string GetCurrentWorkingDirectory()
Definition: posix.cc:1047
virtual int Main(const Options &options)
Definition: cmd_abort.cc:34