CernVM-FS  2.9.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 "logging.h"
12 #include "publish/cmd_util.h"
13 #include "publish/except.h"
14 #include "publish/repository.h"
15 #include "publish/settings.h"
16 #include "util/pointer.h"
17 #include "util/posix.h"
18 #include "util/string.h"
19 #include "whitelist.h"
20 
21 namespace publish {
22 
23 int CmdAbort::Main(const Options &options) {
24  SettingsBuilder builder;
26  try {
27  settings = builder.CreateSettingsPublisher(
28  options.plain_args().empty() ? "" : options.plain_args()[0].value_str,
29  true /* needs_managed */);
30  } catch (const EPublish &e) {
33  {
34  LogCvmfs(kLogCvmfs, kLogStderr | kLogSyslogErr, "CernVM-FS error: %s",
35  e.msg().c_str());
36  return 1;
37  }
38  throw;
39  }
40 
41  if (settings->transaction().in_enter_session()) {
42  throw EPublish(
43  "aborting a transaction is unsupported within the ephemeral "
44  "writable shell",
46  }
47 
48  if (!SwitchCredentials(settings->owner_uid(), settings->owner_gid(),
49  false /* temporarily */))
50  {
51  throw EPublish("No write permission to repository",
53  }
54 
56  settings->transaction().spool_area().union_mnt() + "/",
57  false /* ignore_case */))
58  {
60  "Current working directory is in %s. Please release, "
61  "e.g. by 'cd $HOME'.",
62  settings->transaction().spool_area().union_mnt().c_str());
63  return 1;
64  }
65 
66  if (!options.Has("force")) {
68  "You are about to DISCARD ALL CHANGES OF THE CURRENT TRANSACTION "
69  "for %s! Are you sure (y/N)? ", settings->fqrn().c_str());
70  char answer[] = {0, 0, 0};
71  char *rv_charp = fgets(answer, 3, stdin);
72  if (rv_charp && (answer[0] != 'Y') && (answer[0] != 'y'))
73  return EINTR;
74  }
75 
76  std::vector<LsofEntry> lsof_entries =
77  Lsof(settings->transaction().spool_area().union_mnt());
78  if (!lsof_entries.empty()) {
79  if (options.Has("force")) {
81  "WARNING: Open file descriptors on %s (possible race!)"
82  "\nThe following lsof report might show the culprit:\n",
83  settings->transaction().spool_area().union_mnt().c_str());
84  } else {
86  "\nWARNING! There are open read-only file descriptors in %s\n"
87  " --> This is potentially harmful and might cause problems "
88  "later on.\n"
89  " We can anyway perform the requested operation, but this "
90  "will most likely\n"
91  " break other processes with open file descriptors on %s!\n"
92  "\n"
93  " The following lsof report might show the processes with "
94  "open file handles\n",
95  settings->transaction().spool_area().union_mnt().c_str(),
96  settings->transaction().spool_area().union_mnt().c_str());
97  }
98 
99  for (unsigned i = 0; i < lsof_entries.size(); ++i) {
100  std::string owner_name;
101  GetUserNameOf(lsof_entries[i].owner, &owner_name);
102  LogCvmfs(kLogCvmfs, kLogStdout, "%s %d %s %s",
103  lsof_entries[i].executable.c_str(),
104  lsof_entries[i].pid,
105  owner_name.c_str(),
106  lsof_entries[i].path.c_str());
107  }
108 
109  if (!options.Has("force")) {
111  "\n Do you want to proceed anyway? (y/N) ");
112  char answer[] = {0, 0, 0};
113  char *rv_charp = fgets(answer, 3, stdin);
114  if (rv_charp && (answer[0] != 'Y') && (answer[0] != 'y'))
115  return EINTR;
116  }
117  }
118 
119  UniquePtr<Publisher> publisher;
120  publisher = new Publisher(*settings);
121 
122  LogCvmfs(kLogCvmfs, kLogSyslog, "(%s) aborting transaction",
123  settings->fqrn().c_str());
124 
125  int rvi = CallServerHook("abort_before_hook", settings->fqrn());
126  if (rvi != 0) {
128  "abort hook failed, not aborting");
129  return rvi;
130  }
131 
132  try {
133  publisher->Abort();
134  } catch (const EPublish &e) {
136  LogCvmfs(kLogCvmfs, kLogStderr | kLogSyslogErr, "%s", e.msg().c_str());
137  return EINVAL;
138  }
139  }
140 
141  rvi = CallServerHook("abort_after_hook", settings->fqrn());
142  if (rvi != 0) {
144  "post abort hook failed");
145  return rvi;
146  }
147 
148  return 0;
149 }
150 
151 } // namespace publish
#define LogCvmfs(source, mask,...)
Definition: logging.h:20
SettingsPublisher * CreateSettingsPublisher(const std::string &ident, bool needs_managed=false)
Definition: settings.cc:500
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:1341
std::string msg() const
Definition: except.h:46
const SettingsPublisher & settings() const
Definition: repository.h:306
const std::vector< Argument > & plain_args() const
Definition: command.h:137
bool HasPrefix(const string &str, const string &prefix, const bool ignore_case)
Definition: string.cc:264
Publisher(const SettingsPublisher &settings)
Definition: repository.cc:620
EFailures failure() const
Definition: except.h:45
bool SwitchCredentials(const uid_t uid, const gid_t gid, const bool temporarily)
Definition: posix.cc:781
std::vector< LsofEntry > Lsof(const std::string &path)
Definition: posix.cc:1509
std::string GetCurrentWorkingDirectory()
Definition: posix.cc:1080
virtual int Main(const Options &options)
Definition: cmd_abort.cc:23