CernVM-FS  2.10.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;
25  std::string session_dir = Env::GetEnterSessionDir();
26 
27  if (!session_dir.empty()) {
28  builder.SetConfigPath(session_dir);
29  }
30 
32  try {
33  settings = builder.CreateSettingsPublisher(
34  options.plain_args().empty() ? "" : options.plain_args()[0].value_str,
35  true /* needs_managed */);
36  } catch (const EPublish &e) {
39  {
40  LogCvmfs(kLogCvmfs, kLogStderr | kLogSyslogErr, "CernVM-FS error: %s",
41  e.msg().c_str());
42  return 1;
43  }
44  throw;
45  }
46 
47  if (!SwitchCredentials(settings->owner_uid(), settings->owner_gid(),
48  false /* temporarily */))
49  {
50  throw EPublish("No write permission to repository",
52  }
53 
55  settings->transaction().spool_area().union_mnt() + "/",
56  false /* ignore_case */))
57  {
59  "Current working directory is in %s. Please release, "
60  "e.g. by 'cd $HOME'.",
61  settings->transaction().spool_area().union_mnt().c_str());
62  return 1;
63  }
64 
65  if (!options.Has("force")) {
67  "You are about to DISCARD ALL CHANGES OF THE CURRENT TRANSACTION "
68  "for %s! Are you sure (y/N)? ", settings->fqrn().c_str());
69  char answer[] = {0, 0, 0};
70  char *rv_charp = fgets(answer, 3, stdin);
71  if (rv_charp && (answer[0] != 'Y') && (answer[0] != 'y'))
72  return EINTR;
73  }
74 
75  std::vector<LsofEntry> lsof_entries =
76  Lsof(settings->transaction().spool_area().union_mnt());
77  if (!lsof_entries.empty()) {
78  if (options.Has("force")) {
80  "WARNING: Open file descriptors on %s (possible race!)"
81  "\nThe following lsof report might show the culprit:\n",
82  settings->transaction().spool_area().union_mnt().c_str());
83  } else {
85  "\nWARNING! There are open read-only file descriptors in %s\n"
86  " --> This is potentially harmful and might cause problems "
87  "later on.\n"
88  " We can anyway perform the requested operation, but this "
89  "will most likely\n"
90  " break other processes with open file descriptors on %s!\n"
91  "\n"
92  " The following lsof report might show the processes with "
93  "open file handles\n",
94  settings->transaction().spool_area().union_mnt().c_str(),
95  settings->transaction().spool_area().union_mnt().c_str());
96  }
97 
98  for (unsigned i = 0; i < lsof_entries.size(); ++i) {
99  std::string owner_name;
100  GetUserNameOf(lsof_entries[i].owner, &owner_name);
101  LogCvmfs(kLogCvmfs, kLogStdout, "%s %d %s %s",
102  lsof_entries[i].executable.c_str(),
103  lsof_entries[i].pid,
104  owner_name.c_str(),
105  lsof_entries[i].path.c_str());
106  }
107 
108  if (!options.Has("force")) {
110  "\n Do you want to proceed anyway? (y/N) ");
111  char answer[] = {0, 0, 0};
112  char *rv_charp = fgets(answer, 3, stdin);
113  if (rv_charp && (answer[0] != 'Y') && (answer[0] != 'y'))
114  return EINTR;
115  }
116  }
117 
118  UniquePtr<Publisher> publisher;
119  publisher = new Publisher(*settings);
120 
121  LogCvmfs(kLogCvmfs, kLogSyslog, "(%s) aborting transaction",
122  settings->fqrn().c_str());
123 
124  int rvi = CallServerHook("abort_before_hook", settings->fqrn());
125  if (rvi != 0) {
127  "abort hook failed, not aborting");
128  return rvi;
129  }
130 
131  try {
132  publisher->Abort();
133  } catch (const EPublish &e) {
135  LogCvmfs(kLogCvmfs, kLogStderr | kLogSyslogErr, "%s", e.msg().c_str());
136  return EINVAL;
137  }
138  }
139 
140  rvi = CallServerHook("abort_after_hook", settings->fqrn());
141  if (rvi != 0) {
143  "post abort hook failed");
144  return rvi;
145  }
146 
147  if (settings->transaction().in_enter_session()) {
149  "Discarding changes and closing current transaction...");
150  SafeWriteToFile("abort", session_dir + "/shellaction.marker", 0600);
151  publisher->ExitShell();
152  }
153 
154  return 0;
155 }
156 
157 } // namespace publish
#define LogCvmfs(source, mask,...)
Definition: logging.h:20
SettingsPublisher * CreateSettingsPublisher(const std::string &ident, bool needs_managed=false)
Definition: settings.cc:581
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:1346
std::string msg() const
Definition: except.h:46
const SettingsPublisher & settings() const
Definition: repository.h:314
bool SafeWriteToFile(const std::string &content, const std::string &path, int mode)
Definition: posix.cc:2027
void SetConfigPath(const std::string &config_path)
Definition: settings.h:521
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:265
Publisher(const SettingsPublisher &settings)
Definition: repository.cc:634
EFailures failure() const
Definition: except.h:45
bool SwitchCredentials(const uid_t uid, const gid_t gid, const bool temporarily)
Definition: posix.cc:786
std::vector< LsofEntry > Lsof(const std::string &path)
Definition: posix.cc:1514
std::string GetCurrentWorkingDirectory()
Definition: posix.cc:1085
virtual int Main(const Options &options)
Definition: cmd_abort.cc:23