CernVM-FS  2.13.0
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
repository_util.cc
Go to the documentation of this file.
1 
6 #include "repository_util.h"
7 
8 #include <errno.h>
9 #include <fcntl.h>
10 #include <unistd.h>
11 
12 #include <cstdio>
13 #include <map>
14 #include <set>
15 #include <string>
16 #include <vector>
17 
18 #include "crypto/hash.h"
19 #include "publish/except.h"
20 #include "util/posix.h"
21 #include "util/string.h"
22 
23 namespace publish {
24 
25 CheckoutMarker *CheckoutMarker::CreateFrom(const std::string &path) {
26  if (!FileExists(path))
27  return NULL;
28 
29  FILE *f = fopen(path.c_str(), "r");
30  if (f == NULL)
31  throw publish::EPublish("cannot open checkout marker");
32  std::string line;
33  bool retval = GetLineFile(f, &line);
34  fclose(f);
35  if (!retval)
36  throw publish::EPublish("empty checkout marker");
37  line = Trim(line, true /* trim_newline */);
38  std::vector<std::string> tokens = SplitString(line, ' ');
39  std::string previous_branch;
40  if (tokens.size() == 4)
41  previous_branch = tokens[3];
42  if (tokens.size() < 3 || tokens.size() > 4)
43  throw publish::EPublish("checkout marker not parsable: " + line);
44 
45  CheckoutMarker *marker = new CheckoutMarker(
46  tokens[0], tokens[2],
48  previous_branch);
49  return marker;
50 }
51 
52 void CheckoutMarker::SaveAs(const std::string &path) const {
53  std::string marker = tag_ + " " + hash_.ToString(false /* with_suffix */)
54  + " " + branch_;
55  if (!previous_branch_.empty())
56  marker += " " + previous_branch_;
57  marker += "\n";
58  SafeWriteToFile(marker, path, kDefaultFileMode);
59 }
60 
61 
62 //------------------------------------------------------------------------------
63 
64 
66  if (!TryLock()) {
67  throw EPublish("Could not acquire lock " + path_,
69  }
70 }
71 
72 
74  int new_fd = TryLockFile(path_);
75  if (new_fd >= 0) {
76  assert(fd_ < 0);
77  fd_ = new_fd;
78  return true;
79  } else if (new_fd == -1) {
80  throw EPublish("Error while attempting to acquire lock " + path_);
81  } else {
82  return false;
83  }
84 }
85 
86 
88  int old_fd = fd_;
89  assert(old_fd >= 0);
90  fd_ = -1;
91  unlink(path_.c_str());
92  close(old_fd);
93 }
94 
95 
96 //------------------------------------------------------------------------------
97 
98 
100  int fd = open(path_.c_str(), O_CREAT | O_RDWR, 0600);
101  if (fd < 0)
102  throw EPublish("cannot create flag file " + path_);
103  close(fd);
104 }
105 
106 
107 void ServerFlagFile::Clear() { unlink(path_.c_str()); }
108 
109 
110 bool ServerFlagFile::IsSet() const { return FileExists(path_); }
111 
112 
113 //------------------------------------------------------------------------------
114 
115 
116 void RunSuidHelper(const std::string &verb, const std::string &fqrn) {
117  std::vector<std::string> cmd_line;
118  cmd_line.push_back("/usr/bin/cvmfs_suid_helper");
119  cmd_line.push_back(verb);
120  cmd_line.push_back(fqrn);
121  std::set<int> preserved_fds;
122  preserved_fds.insert(1);
123  preserved_fds.insert(2);
124  pid_t child_pid;
125  bool retval = ManagedExec(cmd_line, preserved_fds, std::map<int, int>(),
126  false /* drop_credentials */, true /* clear_env */,
127  false /* double_fork */, &child_pid);
128  if (!retval)
129  throw EPublish("cannot spawn suid helper");
130  int exit_code = WaitForChild(child_pid);
131  if (exit_code != 0)
132  throw EPublish("error calling suid helper: " + StringifyInt(exit_code));
133 }
134 
135 
136 void SetInConfig(const std::string &path, const std::string &key,
137  const std::string &value) {
138  int fd = open(path.c_str(), O_RDWR | O_CREAT, kDefaultFileMode);
139  if (fd < 0)
140  throw EPublish("cannot modify configuration file " + path);
141 
142  std::string new_content;
143  std::string line;
144  bool key_exists = false;
145  while (GetLineFd(fd, &line)) {
146  std::string trimmed = Trim(line);
147  if (HasPrefix(trimmed, key + "=", false /* ignore_case */)) {
148  key_exists = true;
149  if (!value.empty())
150  new_content += key + "=" + value + "\n";
151  } else {
152  new_content += line + "\n";
153  }
154  }
155  if (!key_exists && !value.empty())
156  new_content += key + "=" + value + "\n";
157 
158  off_t off_zero = lseek(fd, 0, SEEK_SET);
159  if (off_zero != 0) {
160  close(fd);
161  throw EPublish("cannot rewind configuration file " + path);
162  }
163  int rvi = ftruncate(fd, 0);
164  if (rvi != 0) {
165  close(fd);
166  throw EPublish("cannot truncate configuration file " + path);
167  }
168  bool rvb = SafeWrite(fd, new_content.data(), new_content.length());
169  close(fd);
170  if (!rvb)
171  throw EPublish("cannot rewrite configuration file " + path);
172 }
173 
174 
175 std::string SendTalkCommand(const std::string &socket, const std::string &cmd) {
176  int fd = ConnectSocket(socket);
177  if (fd < 0) {
178  if (errno == ENOENT)
179  throw EPublish("Socket " + socket + " not found");
180  throw EPublish("Socket " + socket + " inaccessible");
181  }
182 
183  WritePipe(fd, cmd.data(), cmd.size());
184 
185  std::string result;
186  char buf;
187  int retval;
188  while ((retval = read(fd, &buf, 1)) == 1) {
189  result.push_back(buf);
190  }
191  close(fd);
192  if (retval != 0)
193  throw EPublish("Broken socket: " + socket);
194 
195  return result;
196 }
197 
198 } // namespace publish
const int kDefaultFileMode
Definition: posix.h:32
string Trim(const string &raw, bool trim_newline)
Definition: string.cc:466
std::string ToString(const bool with_suffix=false) const
Definition: hash.h:241
bool ManagedExec(const std::vector< std::string > &command_line, const std::set< int > &preserve_fildes, const std::map< int, int > &map_fildes, const bool drop_credentials, const bool clear_env, const bool double_fork, pid_t *child_pid)
Definition: posix.cc:1895
bool SafeWrite(int fd, const void *buf, size_t nbyte)
Definition: posix.cc:2035
assert((mem||(size==0))&&"Out Of Memory")
bool SafeWriteToFile(const std::string &content, const std::string &path, int mode)
Definition: posix.cc:2136
int WaitForChild(pid_t pid, const std::vector< int > &sig_ok)
Definition: posix.cc:1600
bool FileExists(const std::string &path)
Definition: posix.cc:803
bool GetLineFile(FILE *f, std::string *line)
Definition: string.cc:422
vector< string > SplitString(const string &str, char delim)
Definition: string.cc:306
std::string previous_branch() const
CheckoutMarker(const std::string &t, const std::string &b, const shash::Any &h, const std::string &p)
const char kSuffixCatalog
Definition: hash.h:54
void SetInConfig(const std::string &path, const std::string &key, const std::string &value)
int TryLockFile(const std::string &path)
Definition: posix.cc:922
string StringifyInt(const int64_t value)
Definition: string.cc:77
bool HasPrefix(const string &str, const string &prefix, const bool ignore_case)
Definition: string.cc:279
void SaveAs(const std::string &path) const
std::string SendTalkCommand(const std::string &socket, const std::string &cmd)
bool GetLineFd(const int fd, std::string *line)
Definition: string.cc:441
void RunSuidHelper(const std::string &verb, const std::string &fqrn)
int ConnectSocket(const std::string &path)
Definition: posix.cc:422
Any MkFromHexPtr(const HexPtr hex, const char suffix)
Definition: hash.cc:82
void WritePipe(int fd, const void *buf, size_t nbyte)
Definition: posix.cc:496
static CheckoutMarker * CreateFrom(const std::string &path)