GCC Code Coverage Report


Directory: cvmfs/
File: cvmfs/publish/repository_util.cc
Date: 2024-04-28 02:33:07
Exec Total Coverage
Lines: 0 112 0.0%
Branches: 0 228 0.0%

Line Branch Exec Source
1 /**
2 * This file is part of the CernVM File System.
3 */
4
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],
46 shash::MkFromHexPtr(shash::HexPtr(tokens[1]), shash::kSuffixCatalog),
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
64 void ServerLockFile::Lock() {
65 if (!TryLock()) {
66 throw EPublish("Could not acquire lock " + path_,
67 EPublish::kFailTransactionState);
68 }
69 }
70
71
72 bool ServerLockFile::TryLock() {
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
86 void ServerLockFile::Unlock() {
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
98 void ServerFlagFile::Set() {
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
106 void ServerFlagFile::Clear() {
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
205