CernVM-FS  2.12.0
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
repository_util.cc
Go to the documentation of this file.
1 
5 #include "cvmfs_config.h"
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(tokens[0], tokens[2],
47  previous_branch);
48  return marker;
49 }
50 
51 void CheckoutMarker::SaveAs(const std::string &path) const {
52  std::string marker =
53  tag_ + " " + hash_.ToString(false /* with_suffix */) + " " + branch_;
54  if (!previous_branch_.empty())
55  marker += " " + previous_branch_;
56  marker += "\n";
57  SafeWriteToFile(marker, path, kDefaultFileMode);
58 }
59 
60 
61 //------------------------------------------------------------------------------
62 
63 
65  if (!TryLock()) {
66  throw EPublish("Could not acquire lock " + path_,
68  }
69 }
70 
71 
73  int new_fd = TryLockFile(path_);
74  if (new_fd >= 0) {
75  assert(fd_ < 0);
76  fd_ = new_fd;
77  return true;
78  } else if (new_fd == -1) {
79  throw EPublish("Error while attempting to acquire lock " + path_);
80  } else {
81  return false;
82  }
83 }
84 
85 
87  int old_fd = fd_;
88  assert(old_fd >= 0);
89  fd_ = -1;
90  unlink(path_.c_str());
91  close(old_fd);
92 }
93 
94 
95 //------------------------------------------------------------------------------
96 
97 
99  int fd = open(path_.c_str(), O_CREAT | O_RDWR, 0600);
100  if (fd < 0)
101  throw EPublish("cannot create flag file " + path_);
102  close(fd);
103 }
104 
105 
107  unlink(path_.c_str());
108 }
109 
110 
111 bool ServerFlagFile::IsSet() const {
112  return FileExists(path_);
113 }
114 
115 
116 //------------------------------------------------------------------------------
117 
118 
119 void RunSuidHelper(const std::string &verb, const std::string &fqrn) {
120  std::vector<std::string> cmd_line;
121  cmd_line.push_back("/usr/bin/cvmfs_suid_helper");
122  cmd_line.push_back(verb);
123  cmd_line.push_back(fqrn);
124  std::set<int> preserved_fds;
125  preserved_fds.insert(1);
126  preserved_fds.insert(2);
127  pid_t child_pid;
128  bool retval = ManagedExec(cmd_line, preserved_fds, std::map<int, int>(),
129  false /* drop_credentials */,
130  true /* clear_env */,
131  false /* double_fork */,
132  &child_pid);
133  if (!retval)
134  throw EPublish("cannot spawn suid helper");
135  int exit_code = WaitForChild(child_pid);
136  if (exit_code != 0)
137  throw EPublish("error calling suid helper: " + StringifyInt(exit_code));
138 }
139 
140 
141 void SetInConfig(const std::string &path,
142  const std::string &key, const std::string &value)
143 {
144  int fd = open(path.c_str(), O_RDWR | O_CREAT, kDefaultFileMode);
145  if (fd < 0)
146  throw EPublish("cannot modify configuration file " + path);
147 
148  std::string new_content;
149  std::string line;
150  bool key_exists = false;
151  while (GetLineFd(fd, &line)) {
152  std::string trimmed = Trim(line);
153  if (HasPrefix(trimmed, key + "=", false /* ignore_case */)) {
154  key_exists = true;
155  if (!value.empty())
156  new_content += key + "=" + value + "\n";
157  } else {
158  new_content += line + "\n";
159  }
160  }
161  if (!key_exists && !value.empty())
162  new_content += key + "=" + value + "\n";
163 
164  off_t off_zero = lseek(fd, 0, SEEK_SET);
165  if (off_zero != 0) {
166  close(fd);
167  throw EPublish("cannot rewind configuration file " + path);
168  }
169  int rvi = ftruncate(fd, 0);
170  if (rvi != 0) {
171  close(fd);
172  throw EPublish("cannot truncate configuration file " + path);
173  }
174  bool rvb = SafeWrite(fd, new_content.data(), new_content.length());
175  close(fd);
176  if (!rvb)
177  throw EPublish("cannot rewrite configuration file " + path);
178 }
179 
180 
181 std::string SendTalkCommand(const std::string &socket, const std::string &cmd) {
182  int fd = ConnectSocket(socket);
183  if (fd < 0) {
184  if (errno == ENOENT)
185  throw EPublish("Socket " + socket + " not found");
186  throw EPublish("Socket " + socket + " inaccessible");
187  }
188 
189  WritePipe(fd, cmd.data(), cmd.size());
190 
191  std::string result;
192  char buf;
193  int retval;
194  while ((retval = read(fd, &buf, 1)) == 1) {
195  result.push_back(buf);
196  }
197  close(fd);
198  if (retval != 0)
199  throw EPublish("Broken socket: " + socket);
200 
201  return result;
202 }
203 
204 } // namespace publish
const int kDefaultFileMode
Definition: posix.h:32
string Trim(const string &raw, bool trim_newline)
Definition: string.cc:428
std::string ToString(const bool with_suffix=false) const
Definition: hash.h:249
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:1846
bool SafeWrite(int fd, const void *buf, size_t nbyte)
Definition: posix.cc:1986
assert((mem||(size==0))&&"Out Of Memory")
bool SafeWriteToFile(const std::string &content, const std::string &path, int mode)
Definition: posix.cc:2084
int WaitForChild(pid_t pid, const std::vector< int > &sig_ok)
Definition: posix.cc:1602
bool FileExists(const std::string &path)
Definition: posix.cc:791
bool GetLineFile(FILE *f, std::string *line)
Definition: string.cc:386
vector< string > SplitString(const string &str, char delim)
Definition: string.cc:290
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:913
string StringifyInt(const int64_t value)
Definition: string.cc:78
bool HasPrefix(const string &str, const string &prefix, const bool ignore_case)
Definition: string.cc:267
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:404
void RunSuidHelper(const std::string &verb, const std::string &fqrn)
int ConnectSocket(const std::string &path)
Definition: posix.cc:427
Any MkFromHexPtr(const HexPtr hex, const char suffix)
Definition: hash.cc:83
void WritePipe(int fd, const void *buf, size_t nbyte)
Definition: posix.cc:501
static CheckoutMarker * CreateFrom(const std::string &path)