GCC Code Coverage Report


Directory: cvmfs/
File: cvmfs/magic_xattr.cc
Date: 2024-04-28 02:33:07
Exec Total Coverage
Lines: 174 482 36.1%
Branches: 289 983 29.4%

Line Branch Exec Source
1 /**
2 * This file is part of the CernVM File System.
3 */
4
5 #include "magic_xattr.h"
6
7 #include <cassert>
8 #include <string>
9 #include <vector>
10
11 #include "catalog_mgr_client.h"
12 #include "crypto/signature.h"
13 #include "fetch.h"
14 #include "mountpoint.h"
15 #include "quota.h"
16 #include "util/logging.h"
17 #include "util/string.h"
18
19 28 MagicXattrManager::MagicXattrManager(MountPoint *mountpoint,
20 EVisibility visibility,
21 const std::set<std::string> &protected_xattrs,
22 28 const std::set<gid_t> &priviledged_xattr_gids)
23 28 : mount_point_(mountpoint),
24 28 visibility_(visibility),
25
1/2
✓ Branch 1 taken 28 times.
✗ Branch 2 not taken.
28 protected_xattrs_(protected_xattrs),
26
1/2
✓ Branch 1 taken 28 times.
✗ Branch 2 not taken.
28 privileged_xattr_gids_(priviledged_xattr_gids),
27 28 is_frozen_(false)
28 {
29
4/8
✓ Branch 1 taken 28 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 28 times.
✗ Branch 5 not taken.
✓ Branch 8 taken 28 times.
✗ Branch 9 not taken.
✓ Branch 11 taken 28 times.
✗ Branch 12 not taken.
28 Register("user.catalog_counters", new CatalogCountersMagicXattr());
30
4/8
✓ Branch 1 taken 28 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 28 times.
✗ Branch 5 not taken.
✓ Branch 8 taken 28 times.
✗ Branch 9 not taken.
✓ Branch 11 taken 28 times.
✗ Branch 12 not taken.
28 Register("user.external_host", new ExternalHostMagicXattr());
31
4/8
✓ Branch 1 taken 28 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 28 times.
✗ Branch 5 not taken.
✓ Branch 8 taken 28 times.
✗ Branch 9 not taken.
✓ Branch 11 taken 28 times.
✗ Branch 12 not taken.
28 Register("user.external_timeout", new ExternalTimeoutMagicXattr());
32
4/8
✓ Branch 1 taken 28 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 28 times.
✗ Branch 5 not taken.
✓ Branch 8 taken 28 times.
✗ Branch 9 not taken.
✓ Branch 11 taken 28 times.
✗ Branch 12 not taken.
28 Register("user.fqrn", new FqrnMagicXattr());
33
4/8
✓ Branch 1 taken 28 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 28 times.
✗ Branch 5 not taken.
✓ Branch 8 taken 28 times.
✗ Branch 9 not taken.
✓ Branch 11 taken 28 times.
✗ Branch 12 not taken.
28 Register("user.host", new HostMagicXattr());
34
4/8
✓ Branch 1 taken 28 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 28 times.
✗ Branch 5 not taken.
✓ Branch 8 taken 28 times.
✗ Branch 9 not taken.
✓ Branch 11 taken 28 times.
✗ Branch 12 not taken.
28 Register("user.host_list", new HostListMagicXattr());
35
4/8
✓ Branch 1 taken 28 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 28 times.
✗ Branch 5 not taken.
✓ Branch 8 taken 28 times.
✗ Branch 9 not taken.
✓ Branch 11 taken 28 times.
✗ Branch 12 not taken.
28 Register("user.ncleanup24", new NCleanup24MagicXattr());
36
4/8
✓ Branch 1 taken 28 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 28 times.
✗ Branch 5 not taken.
✓ Branch 8 taken 28 times.
✗ Branch 9 not taken.
✓ Branch 11 taken 28 times.
✗ Branch 12 not taken.
28 Register("user.nclg", new NClgMagicXattr());
37
4/8
✓ Branch 1 taken 28 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 28 times.
✗ Branch 5 not taken.
✓ Branch 8 taken 28 times.
✗ Branch 9 not taken.
✓ Branch 11 taken 28 times.
✗ Branch 12 not taken.
28 Register("user.ndiropen", new NDirOpenMagicXattr());
38
4/8
✓ Branch 1 taken 28 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 28 times.
✗ Branch 5 not taken.
✓ Branch 8 taken 28 times.
✗ Branch 9 not taken.
✓ Branch 11 taken 28 times.
✗ Branch 12 not taken.
28 Register("user.ndownload", new NDownloadMagicXattr());
39
4/8
✓ Branch 1 taken 28 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 28 times.
✗ Branch 5 not taken.
✓ Branch 8 taken 28 times.
✗ Branch 9 not taken.
✓ Branch 11 taken 28 times.
✗ Branch 12 not taken.
28 Register("user.nioerr", new NIOErrMagicXattr());
40
4/8
✓ Branch 1 taken 28 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 28 times.
✗ Branch 5 not taken.
✓ Branch 8 taken 28 times.
✗ Branch 9 not taken.
✓ Branch 11 taken 28 times.
✗ Branch 12 not taken.
28 Register("user.nopen", new NOpenMagicXattr());
41
4/8
✓ Branch 1 taken 28 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 28 times.
✗ Branch 5 not taken.
✓ Branch 8 taken 28 times.
✗ Branch 9 not taken.
✓ Branch 11 taken 28 times.
✗ Branch 12 not taken.
28 Register("user.hitrate", new HitrateMagicXattr());
42
4/8
✓ Branch 1 taken 28 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 28 times.
✗ Branch 5 not taken.
✓ Branch 8 taken 28 times.
✗ Branch 9 not taken.
✓ Branch 11 taken 28 times.
✗ Branch 12 not taken.
28 Register("user.logbuffer", new LogBufferXattr());
43
4/8
✓ Branch 1 taken 28 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 28 times.
✗ Branch 5 not taken.
✓ Branch 8 taken 28 times.
✗ Branch 9 not taken.
✓ Branch 11 taken 28 times.
✗ Branch 12 not taken.
28 Register("user.proxy", new ProxyMagicXattr());
44
4/8
✓ Branch 1 taken 28 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 28 times.
✗ Branch 5 not taken.
✓ Branch 8 taken 28 times.
✗ Branch 9 not taken.
✓ Branch 11 taken 28 times.
✗ Branch 12 not taken.
28 Register("user.proxy_list", new ProxyListMagicXattr());
45
4/8
✓ Branch 1 taken 28 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 28 times.
✗ Branch 5 not taken.
✓ Branch 8 taken 28 times.
✗ Branch 9 not taken.
✓ Branch 11 taken 28 times.
✗ Branch 12 not taken.
28 Register("user.proxy_list_external", new ProxyListExternalMagicXattr());
46
4/8
✓ Branch 1 taken 28 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 28 times.
✗ Branch 5 not taken.
✓ Branch 8 taken 28 times.
✗ Branch 9 not taken.
✓ Branch 11 taken 28 times.
✗ Branch 12 not taken.
28 Register("user.pubkeys", new PubkeysMagicXattr());
47
4/8
✓ Branch 1 taken 28 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 28 times.
✗ Branch 5 not taken.
✓ Branch 8 taken 28 times.
✗ Branch 9 not taken.
✓ Branch 11 taken 28 times.
✗ Branch 12 not taken.
28 Register("user.repo_counters", new RepoCountersMagicXattr());
48
4/8
✓ Branch 1 taken 28 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 28 times.
✗ Branch 5 not taken.
✓ Branch 8 taken 28 times.
✗ Branch 9 not taken.
✓ Branch 11 taken 28 times.
✗ Branch 12 not taken.
28 Register("user.repo_metainfo", new RepoMetainfoMagicXattr());
49
4/8
✓ Branch 1 taken 28 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 28 times.
✗ Branch 5 not taken.
✓ Branch 8 taken 28 times.
✗ Branch 9 not taken.
✓ Branch 11 taken 28 times.
✗ Branch 12 not taken.
28 Register("user.revision", new RevisionMagicXattr());
50
4/8
✓ Branch 1 taken 28 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 28 times.
✗ Branch 5 not taken.
✓ Branch 8 taken 28 times.
✗ Branch 9 not taken.
✓ Branch 11 taken 28 times.
✗ Branch 12 not taken.
28 Register("user.root_hash", new RootHashMagicXattr());
51
4/8
✓ Branch 1 taken 28 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 28 times.
✗ Branch 5 not taken.
✓ Branch 8 taken 28 times.
✗ Branch 9 not taken.
✓ Branch 11 taken 28 times.
✗ Branch 12 not taken.
28 Register("user.rx", new RxMagicXattr());
52
4/8
✓ Branch 1 taken 28 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 28 times.
✗ Branch 5 not taken.
✓ Branch 8 taken 28 times.
✗ Branch 9 not taken.
✓ Branch 11 taken 28 times.
✗ Branch 12 not taken.
28 Register("user.speed", new SpeedMagicXattr());
53
4/8
✓ Branch 1 taken 28 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 28 times.
✗ Branch 5 not taken.
✓ Branch 8 taken 28 times.
✗ Branch 9 not taken.
✓ Branch 11 taken 28 times.
✗ Branch 12 not taken.
28 Register("user.tag", new TagMagicXattr());
54
4/8
✓ Branch 1 taken 28 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 28 times.
✗ Branch 5 not taken.
✓ Branch 8 taken 28 times.
✗ Branch 9 not taken.
✓ Branch 11 taken 28 times.
✗ Branch 12 not taken.
28 Register("user.timeout", new TimeoutMagicXattr());
55
4/8
✓ Branch 1 taken 28 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 28 times.
✗ Branch 5 not taken.
✓ Branch 8 taken 28 times.
✗ Branch 9 not taken.
✓ Branch 11 taken 28 times.
✗ Branch 12 not taken.
28 Register("user.timeout_direct", new TimeoutDirectMagicXattr());
56
4/8
✓ Branch 1 taken 28 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 28 times.
✗ Branch 5 not taken.
✓ Branch 8 taken 28 times.
✗ Branch 9 not taken.
✓ Branch 11 taken 28 times.
✗ Branch 12 not taken.
28 Register("user.timestamp_last_ioerr", new TimestampLastIOErrMagicXattr());
57
4/8
✓ Branch 1 taken 28 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 28 times.
✗ Branch 5 not taken.
✓ Branch 8 taken 28 times.
✗ Branch 9 not taken.
✓ Branch 11 taken 28 times.
✗ Branch 12 not taken.
28 Register("user.usedfd", new UsedFdMagicXattr());
58
4/8
✓ Branch 1 taken 28 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 28 times.
✗ Branch 5 not taken.
✓ Branch 8 taken 28 times.
✗ Branch 9 not taken.
✓ Branch 11 taken 28 times.
✗ Branch 12 not taken.
28 Register("user.useddirp", new UsedDirPMagicXattr());
59
4/8
✓ Branch 1 taken 28 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 28 times.
✗ Branch 5 not taken.
✓ Branch 8 taken 28 times.
✗ Branch 9 not taken.
✓ Branch 11 taken 28 times.
✗ Branch 12 not taken.
28 Register("user.version", new VersionMagicXattr());
60
61
4/8
✓ Branch 1 taken 28 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 28 times.
✗ Branch 5 not taken.
✓ Branch 8 taken 28 times.
✗ Branch 9 not taken.
✓ Branch 11 taken 28 times.
✗ Branch 12 not taken.
28 Register("user.hash", new HashMagicXattr());
62
4/8
✓ Branch 1 taken 28 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 28 times.
✗ Branch 5 not taken.
✓ Branch 8 taken 28 times.
✗ Branch 9 not taken.
✓ Branch 11 taken 28 times.
✗ Branch 12 not taken.
28 Register("user.lhash", new LHashMagicXattr());
63
64
4/8
✓ Branch 1 taken 28 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 28 times.
✗ Branch 5 not taken.
✓ Branch 8 taken 28 times.
✗ Branch 9 not taken.
✓ Branch 11 taken 28 times.
✗ Branch 12 not taken.
28 Register("user.chunk_list", new ChunkListMagicXattr());
65
4/8
✓ Branch 1 taken 28 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 28 times.
✗ Branch 5 not taken.
✓ Branch 8 taken 28 times.
✗ Branch 9 not taken.
✓ Branch 11 taken 28 times.
✗ Branch 12 not taken.
28 Register("user.chunks", new ChunksMagicXattr());
66
4/8
✓ Branch 1 taken 28 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 28 times.
✗ Branch 5 not taken.
✓ Branch 8 taken 28 times.
✗ Branch 9 not taken.
✓ Branch 11 taken 28 times.
✗ Branch 12 not taken.
28 Register("user.compression", new CompressionMagicXattr());
67
4/8
✓ Branch 1 taken 28 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 28 times.
✗ Branch 5 not taken.
✓ Branch 8 taken 28 times.
✗ Branch 9 not taken.
✓ Branch 11 taken 28 times.
✗ Branch 12 not taken.
28 Register("user.direct_io", new DirectIoMagicXattr());
68
4/8
✓ Branch 1 taken 28 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 28 times.
✗ Branch 5 not taken.
✓ Branch 8 taken 28 times.
✗ Branch 9 not taken.
✓ Branch 11 taken 28 times.
✗ Branch 12 not taken.
28 Register("user.external_file", new ExternalFileMagicXattr());
69
70
4/8
✓ Branch 1 taken 28 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 28 times.
✗ Branch 5 not taken.
✓ Branch 8 taken 28 times.
✗ Branch 9 not taken.
✓ Branch 11 taken 28 times.
✗ Branch 12 not taken.
28 Register("user.rawlink", new RawlinkMagicXattr());
71
4/8
✓ Branch 1 taken 28 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 28 times.
✗ Branch 5 not taken.
✓ Branch 8 taken 28 times.
✗ Branch 9 not taken.
✓ Branch 11 taken 28 times.
✗ Branch 12 not taken.
28 Register("xfsroot.rawlink", new RawlinkMagicXattr());
72
73
4/8
✓ Branch 1 taken 28 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 28 times.
✗ Branch 5 not taken.
✓ Branch 8 taken 28 times.
✗ Branch 9 not taken.
✓ Branch 11 taken 28 times.
✗ Branch 12 not taken.
28 Register("user.authz", new AuthzMagicXattr());
74
4/8
✓ Branch 1 taken 28 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 28 times.
✗ Branch 5 not taken.
✓ Branch 8 taken 28 times.
✗ Branch 9 not taken.
✓ Branch 11 taken 28 times.
✗ Branch 12 not taken.
28 Register("user.external_url", new ExternalURLMagicXattr());
75 28 }
76
77 4 std::string MagicXattrManager::GetListString(catalog::DirectoryEntry *dirent) {
78
2/2
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 2 times.
4 if (visibility() == kVisibilityNever) {
79
1/2
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
2 return "";
80 }
81 // Only the root entry has an empty name
82
7/12
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 1 times.
✓ Branch 8 taken 1 times.
✓ Branch 9 taken 2 times.
✗ Branch 10 not taken.
✓ Branch 12 taken 1 times.
✓ Branch 13 taken 1 times.
✗ Branch 14 not taken.
✗ Branch 15 not taken.
2 if (visibility() == kVisibilityRootOnly && !dirent->name().IsEmpty()) {
83
1/2
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
1 return "";
84 }
85
86 1 std::string result;
87 1 std::map<std::string, BaseMagicXattr *>::iterator it = xattr_list_.begin();
88
2/2
✓ Branch 3 taken 42 times.
✓ Branch 4 taken 1 times.
43 for (; it != xattr_list_.end(); ++it) {
89
1/2
✓ Branch 2 taken 42 times.
✗ Branch 3 not taken.
42 MagicXattrFlavor flavor = (*it).second->GetXattrFlavor();
90 // Skip those which should not be displayed
91
6/7
✓ Branch 0 taken 31 times.
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 5 times.
✓ Branch 3 taken 1 times.
✓ Branch 4 taken 2 times.
✓ Branch 5 taken 1 times.
✗ Branch 6 not taken.
42 switch (flavor) {
92 31 case kXattrBase:
93 31 break;
94 2 case kXattrWithHash:
95
1/2
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
2 if (dirent->checksum().IsNull()) continue;
96 break;
97 5 case kXattrRegular:
98
1/2
✓ Branch 1 taken 5 times.
✗ Branch 2 not taken.
5 if (!dirent->IsRegular()) continue;
99 break;
100 1 case kXattrExternal:
101
2/6
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✓ Branch 6 taken 1 times.
✗ Branch 7 not taken.
1 if (!(dirent->IsRegular() && dirent->IsExternalFile())) continue;
102 break;
103 2 case kXattrSymlink:
104
1/2
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
2 if (!dirent->IsLink()) continue;
105 break;
106 1 case kXattrAuthz:
107
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 if (!mount_point_->has_membership_req()) continue;
108 break;
109 default:
110 PANIC("unknown magic xattr flavor");
111 }
112
1/2
✓ Branch 2 taken 31 times.
✗ Branch 3 not taken.
31 result += (*it).first;
113
1/2
✓ Branch 1 taken 31 times.
✗ Branch 2 not taken.
31 result.push_back('\0');
114 }
115
116 1 return result;
117 1 }
118
119 4 BaseMagicXattr* MagicXattrManager::GetLocked(const std::string &name,
120 PathString path,
121 catalog::DirectoryEntry *d)
122 {
123 BaseMagicXattr *result;
124
1/2
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
4 if (xattr_list_.count(name) > 0) {
125 4 result = xattr_list_[name];
126 } else {
127 return NULL;
128 }
129
130
1/2
✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
4 result->Lock(path, d);
131
132 4 return result;
133 }
134
135 1176 void MagicXattrManager::Register(const std::string &name,
136 BaseMagicXattr *magic_xattr)
137 {
138
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1176 times.
1176 assert(!is_frozen_);
139
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1176 times.
1176 if (xattr_list_.count(name) > 0) {
140 PANIC(kLogSyslogErr,
141 "Magic extended attribute with name %s already registered",
142 name.c_str());
143 }
144 1176 magic_xattr->xattr_mgr_ = this;
145 1176 xattr_list_[name] = magic_xattr;
146
147 // Mark Xattr protected so that only certain fuse_gids' can access it.
148 // If Xattr with registered "name" is part of *protected_xattrs
149
2/2
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 1175 times.
1176 if (protected_xattrs_.count(name) > 0) {
150 1 magic_xattr->MarkProtected();
151 }
152 1176 }
153
154 2 bool MagicXattrManager::IsPrivilegedGid(gid_t gid) {
155 2 return privileged_xattr_gids_.count(gid) > 0;
156 }
157
158 2 bool BaseMagicXattr::PrepareValueFencedProtected(gid_t gid) {
159
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
2 assert(xattr_mgr_->is_frozen());
160
5/6
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✓ Branch 3 taken 1 times.
✓ Branch 4 taken 1 times.
✓ Branch 5 taken 1 times.
✓ Branch 6 taken 1 times.
2 if (is_protected_ && !xattr_mgr_->IsPrivilegedGid(gid)) {
161 1 return false;
162 }
163
164 1 return PrepareValueFenced();
165 }
166
167 1 void MagicXattrManager::SanityCheckProtectedXattrs() {
168 1 std::set<std::string>::const_iterator iter;
169 1 std::vector<string> tmp;
170 1 for (iter = protected_xattrs_.begin();
171
2/2
✓ Branch 3 taken 1 times.
✓ Branch 4 taken 1 times.
2 iter != protected_xattrs_.end(); iter++) {
172
2/4
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 1 times.
1 if (xattr_list_.find(*iter) == xattr_list_.end()) {
173 tmp.push_back(*iter);
174 }
175 }
176
177
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
1 if (tmp.size() > 0) {
178 std::string msg = JoinStrings(tmp, ",");
179 LogCvmfs(kLogCvmfs, kLogDebug | kLogSyslogWarn,
180 "Following CVMFS_XATTR_PROTECTED_XATTRS are "
181 "set but not recognized: %s", msg.c_str());
182 }
183
184 1 tmp.clear();
185 1 std::set<gid_t>::const_iterator iter_gid;
186 1 for (iter_gid = privileged_xattr_gids_.begin();
187
2/2
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 1 times.
2 iter_gid != privileged_xattr_gids_.end(); iter_gid++) {
188
2/4
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 1 times.
✗ Branch 6 not taken.
1 tmp.push_back(StringifyUint(*iter_gid));
189 }
190
191
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 if (tmp.size() > 0) {
192
2/4
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 1 times.
✗ Branch 6 not taken.
2 std::string msg = JoinStrings(tmp, ",");
193
1/2
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
1 LogCvmfs(kLogCvmfs, kLogDebug | kLogSyslog,
194 "Following CVMFS_XATTR_PRIVILEGED_GIDS are set: %s", msg.c_str());
195 1 }
196 1 }
197
198 4 std::string BaseMagicXattr::HeaderMultipageHuman(uint32_t requested_page) {
199
4/8
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 4 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 4 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 4 times.
✗ Branch 11 not taken.
8 return "# Access page at idx: " + StringifyUint(requested_page) + ". " +
200
2/4
✓ Branch 3 taken 4 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 4 times.
✗ Branch 7 not taken.
16 "Total num pages: " + StringifyUint(result_pages_.size()) +
201 " (access other pages: xattr~<page_num>, starting " +
202
1/2
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
8 " with 0; number of pages available: xattr~?)\n";
203 }
204
205 20 std::pair<bool, std::string> BaseMagicXattr::GetValue(int32_t requested_page,
206 const MagicXattrMode mode) {
207
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 20 times.
20 assert(requested_page >= -1);
208 20 result_pages_.clear();
209
1/2
✓ Branch 1 taken 20 times.
✗ Branch 2 not taken.
20 FinalizeValue();
210
211
1/2
✓ Branch 2 taken 20 times.
✗ Branch 3 not taken.
20 std::string res = "";
212
2/2
✓ Branch 0 taken 14 times.
✓ Branch 1 taken 6 times.
20 if (mode == kXattrMachineMode) {
213
2/2
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 12 times.
14 if (requested_page >= static_cast<int32_t>(result_pages_.size())) {
214
1/2
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
2 return std::pair<bool, std::string> (false, "");
215 }
216
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 if (requested_page == -1) {
217 return std::pair<bool, std::string> (true,
218 "num_pages, " + StringifyUint(result_pages_.size()));
219 }
220
1/2
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
6 } else if (mode == kXattrHumanMode) {
221
2/2
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 4 times.
6 if (requested_page >= static_cast<int32_t>(result_pages_.size())) {
222 return std::pair<bool, std::string> (true,
223 "Page requested does not exists. There are "
224
3/6
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 2 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 2 times.
✗ Branch 9 not taken.
4 + StringifyUint(result_pages_.size()) + " pages available.\n"
225
1/2
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
4 + "Access them with xattr~<page_num> (machine-readable mode) "
226
1/2
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
4 + "or xattr@<page_num> (human-readable mode).\n"
227
1/2
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
2 + "Use xattr@? or xattr~? to get extra info about the attribute");
228
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 } else if (requested_page == -1) {
229 return std::pair<bool, std::string> (true,
230 "Access xattr with xattr~<page_num> (machine-readable mode) or "
231 + std::string(" xattr@<page_num> (human-readable mode).\n")
232 + "Pages available: " + StringifyUint(result_pages_.size()));
233 } else {
234
1/2
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
4 res = HeaderMultipageHuman(requested_page);
235 }
236 } else {
237 PANIC(kLogStderr | kLogSyslogErr,
238 "Unknown mode of magic xattr requested: %d", mode);
239 }
240
241
1/2
✓ Branch 2 taken 16 times.
✗ Branch 3 not taken.
16 res += result_pages_[requested_page];
242
243
1/2
✓ Branch 1 taken 16 times.
✗ Branch 2 not taken.
16 return std::pair<bool, std::string> (true, res);
244 20 }
245
246 bool AuthzMagicXattr::PrepareValueFenced() {
247 return xattr_mgr_->mount_point()->has_membership_req();
248 }
249
250 void AuthzMagicXattr::FinalizeValue() {
251 result_pages_.push_back(xattr_mgr_->mount_point()->membership_req());
252 }
253
254 1 MagicXattrFlavor AuthzMagicXattr::GetXattrFlavor() {
255 1 return kXattrAuthz;
256 }
257
258 bool CatalogCountersMagicXattr::PrepareValueFenced() {
259 counters_ =
260 xattr_mgr_->mount_point()->catalog_mgr()->
261 LookupCounters(path_, &subcatalog_path_, &hash_);
262 return true;
263 }
264
265 void CatalogCountersMagicXattr::FinalizeValue() {
266 std::string res;
267 res = "catalog_hash: " + hash_.ToString() + "\n";
268 res += "catalog_mountpoint: " + subcatalog_path_ + "\n";
269 res += counters_.GetCsvMap();
270
271 result_pages_.push_back(res);
272 }
273
274 bool ChunkListMagicXattr::PrepareValueFenced() {
275 chunk_list_.clear();
276
277 const std::string header = "hash,offset,size\n";
278 std::string chunk_list_page_(header);
279 if (!dirent_->IsRegular()) {
280 chunk_list_.push_back(chunk_list_page_);
281 return false;
282 }
283 if (dirent_->IsChunkedFile()) {
284 FileChunkList chunks;
285 if (!xattr_mgr_->mount_point()->catalog_mgr()
286 ->ListFileChunks(path_, dirent_->hash_algorithm(), &chunks)
287 || chunks.IsEmpty())
288 {
289 LogCvmfs(kLogCvmfs, kLogDebug | kLogSyslogErr, "file %s is marked as "
290 "'chunked', but no chunks found.", path_.c_str());
291 return false;
292 } else {
293 for (size_t i = 0; i < chunks.size(); ++i) {
294 chunk_list_page_ += chunks.At(i).content_hash().ToString() + ",";
295 chunk_list_page_ += StringifyInt(chunks.At(i).offset()) + ",";
296 chunk_list_page_ += StringifyUint(chunks.At(i).size()) + "\n";
297
298 if (chunk_list_page_.size() > kMaxCharsPerPage) {
299 chunk_list_.push_back(chunk_list_page_);
300 chunk_list_page_ = header;
301 }
302 }
303 }
304 } else {
305 chunk_list_page_ += dirent_->checksum().ToString() + ",";
306 chunk_list_page_ += "0,";
307 chunk_list_page_ += StringifyUint(dirent_->size()) + "\n";
308 }
309
310 // add the last page
311 if (chunk_list_page_.size() > header.size()) {
312 chunk_list_.push_back(chunk_list_page_);
313 }
314
315 return true;
316 }
317
318 void ChunkListMagicXattr::FinalizeValue() {
319 result_pages_ = chunk_list_;
320 }
321
322 bool ChunksMagicXattr::PrepareValueFenced() {
323 if (!dirent_->IsRegular()) {
324 return false;
325 }
326 if (dirent_->IsChunkedFile()) {
327 FileChunkList chunks;
328 if (!xattr_mgr_->mount_point()->catalog_mgr()
329 ->ListFileChunks(path_, dirent_->hash_algorithm(), &chunks)
330 || chunks.IsEmpty())
331 {
332 LogCvmfs(kLogCvmfs, kLogDebug | kLogSyslogErr, "file %s is marked as "
333 "'chunked', but no chunks found.", path_.c_str());
334 return false;
335 } else {
336 n_chunks_ = chunks.size();
337 }
338 } else {
339 n_chunks_ = 1;
340 }
341
342 return true;
343 }
344
345 void ChunksMagicXattr::FinalizeValue() {
346 result_pages_.push_back(StringifyUint(n_chunks_));
347 }
348
349 bool CompressionMagicXattr::PrepareValueFenced() {
350 return dirent_->IsRegular();
351 }
352
353 void CompressionMagicXattr::FinalizeValue() {
354 result_pages_.push_back(zlib::AlgorithmName(
355 dirent_->compression_algorithm()));
356 }
357
358 bool DirectIoMagicXattr::PrepareValueFenced() {
359 return dirent_->IsRegular();
360 }
361
362 void DirectIoMagicXattr::FinalizeValue() {
363 result_pages_.push_back(dirent_->IsDirectIo() ? "1" : "0");
364 }
365
366 bool ExternalFileMagicXattr::PrepareValueFenced() {
367 return dirent_->IsRegular();
368 }
369
370 void ExternalFileMagicXattr::FinalizeValue() {
371 result_pages_.push_back(dirent_->IsExternalFile() ? "1" : "0");
372 }
373
374 void ExternalHostMagicXattr::FinalizeValue() {
375 std::vector<string> host_chain;
376 std::vector<int> rtt;
377 unsigned current_host;
378 xattr_mgr_->mount_point()->external_download_mgr()->GetHostInfo(
379 &host_chain, &rtt, &current_host);
380 if (host_chain.size()) {
381 result_pages_.push_back(std::string(host_chain[current_host]));
382 } else {
383 result_pages_.push_back("internal error: no hosts defined");
384 }
385 }
386
387 void ExternalTimeoutMagicXattr::FinalizeValue() {
388 unsigned seconds, seconds_direct;
389 xattr_mgr_->mount_point()->external_download_mgr()->
390 GetTimeout(&seconds, &seconds_direct);
391 result_pages_.push_back(StringifyUint(seconds_direct));
392 }
393
394 2 void FqrnMagicXattr::FinalizeValue() {
395
1/2
✓ Branch 3 taken 2 times.
✗ Branch 4 not taken.
2 result_pages_.push_back(xattr_mgr_->mount_point()->fqrn());
396 2 }
397
398 bool HashMagicXattr::PrepareValueFenced() {
399 return !dirent_->checksum().IsNull();
400 }
401
402 void HashMagicXattr::FinalizeValue() {
403 result_pages_.push_back(dirent_->checksum().ToString());
404 }
405
406 void HostMagicXattr::FinalizeValue() {
407 std::vector<std::string> host_chain;
408 std::vector<int> rtt;
409 unsigned current_host;
410 xattr_mgr_->mount_point()->download_mgr()->
411 GetHostInfo(&host_chain, &rtt, &current_host);
412 if (host_chain.size()) {
413 result_pages_.push_back(std::string(host_chain[current_host]));
414 } else {
415 result_pages_.push_back("internal error: no hosts defined");
416 }
417 }
418
419 void HostListMagicXattr::FinalizeValue() {
420 std::string result;
421 std::vector<std::string> host_chain;
422 std::vector<int> rtt;
423 unsigned current_host;
424 xattr_mgr_->mount_point()->download_mgr()->
425 GetHostInfo(&host_chain, &rtt, &current_host);
426 if (host_chain.size()) {
427 result = host_chain[current_host];
428 for (unsigned i = 1; i < host_chain.size(); ++i) {
429 result +=
430 ";" + host_chain[(i+current_host) % host_chain.size()];
431 }
432 } else {
433 result = "internal error: no hosts defined";
434 }
435 result_pages_.push_back(result);
436 }
437
438 bool LHashMagicXattr::PrepareValueFenced() {
439 return !dirent_->checksum().IsNull();
440 }
441
442 void LHashMagicXattr::FinalizeValue() {
443 string result;
444 CacheManager::Label label;
445 label.path = path_.ToString();
446 if (xattr_mgr_->mount_point()->catalog_mgr()->volatile_flag())
447 label.flags = CacheManager::kLabelVolatile;
448 int fd = xattr_mgr_->mount_point()->file_system()->cache_mgr()->Open(
449 CacheManager::LabeledObject(dirent_->checksum(), label));
450 if (fd < 0) {
451 result = "Not in cache";
452 } else {
453 shash::Any hash(dirent_->checksum().algorithm);
454 int retval_i =
455 xattr_mgr_->mount_point()->file_system()->cache_mgr()
456 ->ChecksumFd(fd, &hash);
457 if (retval_i != 0)
458 result = "I/O error (" + StringifyInt(retval_i) + ")";
459 else
460 result = hash.ToString();
461 xattr_mgr_->mount_point()->file_system()->cache_mgr()->Close(fd);
462 }
463 result_pages_.push_back(result);
464 }
465
466
1/2
✓ Branch 2 taken 28 times.
✗ Branch 3 not taken.
28 LogBufferXattr::LogBufferXattr() : BaseMagicXattr(), throttle_(1, 500, 2000) { }
467
468 2 void LogBufferXattr::FinalizeValue() {
469
1/2
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
2 throttle_.Throttle();
470
1/2
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
2 std::vector<LogBufferEntry> buffer = GetLogBuffer();
471 2 std::string result;
472 2 for (std::vector<LogBufferEntry>::reverse_iterator itr = buffer.rbegin();
473
3/4
✓ Branch 2 taken 22 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 20 times.
✓ Branch 5 taken 2 times.
22 itr != buffer.rend(); ++itr)
474 {
475
3/4
✓ Branch 1 taken 20 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✓ Branch 5 taken 19 times.
20 if (itr->message.size() > kMaxLogLine) {
476
2/4
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
1 itr->message.resize(kMaxLogLine);
477
2/4
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
1 itr->message += " <snip>";
478 }
479
4/8
✓ Branch 1 taken 20 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 20 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 20 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 20 times.
✗ Branch 11 not taken.
40 result += "[" + StringifyTime(itr->timestamp, true /* UTC */) + " UTC] " +
480
4/8
✓ Branch 1 taken 20 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 20 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 20 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 20 times.
✗ Branch 11 not taken.
40 itr->message + "\n";
481 }
482
1/2
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
2 result_pages_.push_back(result);
483 2 }
484
485 void NCleanup24MagicXattr::FinalizeValue() {
486 QuotaManager *quota_mgr =
487 xattr_mgr_->mount_point()->file_system()->cache_mgr()->quota_mgr();
488 if (!quota_mgr->HasCapability(QuotaManager::kCapIntrospectCleanupRate)) {
489 result_pages_.push_back(StringifyInt(-1));
490 } else {
491 const uint64_t period_s = 24 * 60 * 60;
492 const uint64_t rate = quota_mgr->GetCleanupRate(period_s);
493 result_pages_.push_back(StringifyUint(rate));
494 }
495 }
496
497 bool NClgMagicXattr::PrepareValueFenced() {
498 n_catalogs_ = xattr_mgr_->mount_point()->catalog_mgr()->GetNumCatalogs();
499 return true;
500 }
501
502 void NClgMagicXattr::FinalizeValue() {
503 result_pages_.push_back(StringifyInt(n_catalogs_));
504 }
505
506 void NDirOpenMagicXattr::FinalizeValue() {
507 result_pages_.push_back(xattr_mgr_->mount_point()->
508 file_system()->n_fs_dir_open()->ToString());
509 }
510
511 void NDownloadMagicXattr::FinalizeValue() {
512 result_pages_.push_back(xattr_mgr_->mount_point()->statistics()
513 ->Lookup("fetch.n_downloads")->Print());
514 }
515
516 void NIOErrMagicXattr::FinalizeValue() {
517 result_pages_.push_back(StringifyInt(xattr_mgr_->mount_point()->file_system()
518 ->io_error_info()->count()));
519 }
520
521 void NOpenMagicXattr::FinalizeValue() {
522 result_pages_.push_back(xattr_mgr_->mount_point()->file_system()->n_fs_open()
523 ->ToString());
524 }
525
526 void HitrateMagicXattr::FinalizeValue() {
527 int64_t n_invocations =
528 xattr_mgr_->mount_point()->statistics()->Lookup("fetch.n_invocations")
529 ->Get();
530 if (n_invocations == 0) {
531 result_pages_.push_back("n/a");
532 return;
533 }
534
535 int64_t n_downloads =
536 xattr_mgr_->mount_point()->statistics()->Lookup("fetch.n_downloads")->Get();
537 float hitrate = 100. * (1. -
538 (static_cast<float>(n_downloads) / static_cast<float>(n_invocations)));
539 result_pages_.push_back(StringifyDouble(hitrate));
540 }
541
542 void ProxyMagicXattr::FinalizeValue() {
543 vector< vector<download::DownloadManager::ProxyInfo> > proxy_chain;
544 unsigned current_group;
545 xattr_mgr_->mount_point()->download_mgr()->GetProxyInfo(
546 &proxy_chain, &current_group, NULL);
547 if (proxy_chain.size()) {
548 result_pages_.push_back(proxy_chain[current_group][0].url);
549 } else {
550 result_pages_.push_back("DIRECT");
551 }
552 }
553
554 static void ListProxy(download::DownloadManager *dm,
555 std::vector<std::string> *result_pages) {
556 vector< vector<download::DownloadManager::ProxyInfo> > proxy_chain;
557 unsigned current_group;
558 dm->GetProxyInfo(&proxy_chain, &current_group, NULL);
559 std::string buf = "";
560 for (unsigned int i = 0; i < proxy_chain.size(); i++) {
561 for (unsigned int j = 0; j < proxy_chain[i].size(); j++) {
562 buf += proxy_chain[i][j].url;
563 buf += "\n";
564 }
565
566 if (buf.size() > BaseMagicXattr::kMaxCharsPerPage) {
567 result_pages->push_back(buf);
568 buf = "";
569 }
570 }
571
572 if (buf.size() > 0 || result_pages->size() == 0) {
573 result_pages->push_back(buf);
574 }
575 }
576
577 void ProxyListMagicXattr::FinalizeValue() {
578 ListProxy(xattr_mgr_->mount_point()->download_mgr(), &result_pages_);
579 }
580
581 void ProxyListExternalMagicXattr::FinalizeValue() {
582 ListProxy(xattr_mgr_->mount_point()->external_download_mgr(), &result_pages_);
583 }
584
585 bool PubkeysMagicXattr::PrepareValueFenced() {
586 pubkeys_ = xattr_mgr_->mount_point()->signature_mgr()
587 ->GetActivePubkeysAsVector();
588 return true;
589 }
590
591 16 void PubkeysMagicXattr::FinalizeValue() {
592 16 size_t full_size = 0;
593
594
2/2
✓ Branch 1 taken 79 times.
✓ Branch 2 taken 16 times.
95 for (size_t i = 0; i < pubkeys_.size(); i++) {
595 79 full_size += pubkeys_[i].size();
596 }
597
598
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 14 times.
16 if (full_size == 0) {
599 2 return;
600 }
601
602 14 size_t size_within_page = 0;
603
1/2
✓ Branch 2 taken 14 times.
✗ Branch 3 not taken.
14 std::string res = "";
604
605
2/2
✓ Branch 1 taken 79 times.
✓ Branch 2 taken 14 times.
93 for (size_t i = 0; i < pubkeys_.size(); i++) {
606
2/2
✓ Branch 2 taken 13 times.
✓ Branch 3 taken 66 times.
79 if (size_within_page + pubkeys_[i].size() >= kMaxCharsPerPage) {
607
1/2
✓ Branch 1 taken 13 times.
✗ Branch 2 not taken.
13 result_pages_.push_back(res);
608
1/2
✓ Branch 1 taken 13 times.
✗ Branch 2 not taken.
13 res = "";
609 13 size_within_page = 0;
610 }
611
612
1/2
✓ Branch 2 taken 79 times.
✗ Branch 3 not taken.
79 res += pubkeys_[i];
613 79 size_within_page += pubkeys_[i].size();
614 }
615
1/2
✓ Branch 1 taken 14 times.
✗ Branch 2 not taken.
14 if (res.size() > 0) {
616
1/2
✓ Branch 1 taken 14 times.
✗ Branch 2 not taken.
14 result_pages_.push_back(res);
617 }
618 14 }
619
620 bool RawlinkMagicXattr::PrepareValueFenced() {
621 return dirent_->IsLink();
622 }
623
624 void RawlinkMagicXattr::FinalizeValue() {
625 result_pages_.push_back(dirent_->symlink().ToString());
626 }
627
628 bool RepoCountersMagicXattr::PrepareValueFenced() {
629 counters_ = xattr_mgr_->mount_point()->catalog_mgr()->GetRootCatalog()
630 ->GetCounters();
631 return true;
632 }
633
634 void RepoCountersMagicXattr::FinalizeValue() {
635 result_pages_.push_back(counters_.GetCsvMap());
636 }
637
638 uint64_t RepoMetainfoMagicXattr::kMaxMetainfoLength = 65536;
639
640 bool RepoMetainfoMagicXattr::PrepareValueFenced() {
641 if (!xattr_mgr_->mount_point()->catalog_mgr()->manifest()) {
642 error_reason_ = "manifest not available";
643 return true;
644 }
645
646 metainfo_hash_ = xattr_mgr_->mount_point()->catalog_mgr()->manifest()
647 ->meta_info();
648 if (metainfo_hash_.IsNull()) {
649 error_reason_ = "metainfo not available";
650 return true;
651 }
652 return true;
653 }
654
655 void RepoMetainfoMagicXattr::FinalizeValue() {
656 if (metainfo_hash_.IsNull()) {
657 result_pages_.push_back(error_reason_);
658 return;
659 }
660
661 CacheManager::Label label;
662 label.path = xattr_mgr_->mount_point()->fqrn() +
663 "(" + metainfo_hash_.ToString() + ")";
664 label.flags = CacheManager::kLabelMetainfo;
665 int fd = xattr_mgr_->mount_point()->fetcher()->Fetch(
666 CacheManager::LabeledObject(metainfo_hash_, label));
667 if (fd < 0) {
668 result_pages_.push_back("Failed to open metadata file");
669 return;
670 }
671 uint64_t actual_size = xattr_mgr_->mount_point()->file_system()->cache_mgr()
672 ->GetSize(fd);
673 if (actual_size > kMaxMetainfoLength) {
674 xattr_mgr_->mount_point()->file_system()->cache_mgr()->Close(fd);
675 result_pages_.push_back("Failed to open: metadata file is too big");
676 return;
677 }
678 char buffer[kMaxMetainfoLength];
679 int64_t bytes_read =
680 xattr_mgr_->mount_point()->file_system()->cache_mgr()
681 ->Pread(fd, buffer, actual_size, 0);
682 xattr_mgr_->mount_point()->file_system()->cache_mgr()->Close(fd);
683 if (bytes_read < 0) {
684 result_pages_.push_back("Failed to read metadata file");
685 return;
686 }
687 result_pages_.push_back(string(buffer, buffer + bytes_read));
688 }
689
690 bool RevisionMagicXattr::PrepareValueFenced() {
691 revision_ = xattr_mgr_->mount_point()->catalog_mgr()->GetRevision();
692 return true;
693 }
694
695 void RevisionMagicXattr::FinalizeValue() {
696 result_pages_.push_back(StringifyUint(revision_));
697 }
698
699 bool RootHashMagicXattr::PrepareValueFenced() {
700 root_hash_ = xattr_mgr_->mount_point()->catalog_mgr()->GetRootHash();
701 return true;
702 }
703
704 void RootHashMagicXattr::FinalizeValue() {
705 result_pages_.push_back(root_hash_.ToString());
706 }
707
708 void RxMagicXattr::FinalizeValue() {
709 perf::Statistics *statistics = xattr_mgr_->mount_point()->statistics();
710 int64_t rx = statistics->Lookup("download.sz_transferred_bytes")->Get();
711 result_pages_.push_back(StringifyInt(rx/1024));
712 }
713
714 void SpeedMagicXattr::FinalizeValue() {
715 perf::Statistics *statistics = xattr_mgr_->mount_point()->statistics();
716 int64_t rx = statistics->Lookup("download.sz_transferred_bytes")->Get();
717 int64_t time = statistics->Lookup("download.sz_transfer_time")->Get();
718 if (time == 0) {
719 result_pages_.push_back("n/a");
720 } else {
721 result_pages_.push_back(StringifyInt((1000 * (rx/1024))/time));
722 }
723 }
724
725 bool TagMagicXattr::PrepareValueFenced() {
726 tag_ = xattr_mgr_->mount_point()->repository_tag();
727 return true;
728 }
729
730 void TagMagicXattr::FinalizeValue() {
731 result_pages_.push_back(tag_);
732 }
733
734 void TimeoutMagicXattr::FinalizeValue() {
735 unsigned seconds, seconds_direct;
736 xattr_mgr_->mount_point()->download_mgr()
737 ->GetTimeout(&seconds, &seconds_direct);
738 result_pages_.push_back(StringifyUint(seconds));
739 }
740
741 void TimeoutDirectMagicXattr::FinalizeValue() {
742 unsigned seconds, seconds_direct;
743 xattr_mgr_->mount_point()->download_mgr()
744 ->GetTimeout(&seconds, &seconds_direct);
745 result_pages_.push_back(StringifyUint(seconds_direct));
746 }
747
748 void TimestampLastIOErrMagicXattr::FinalizeValue() {
749 result_pages_.push_back(StringifyInt(xattr_mgr_->mount_point()->
750 file_system()->io_error_info()->timestamp_last()));
751 }
752
753 void UsedFdMagicXattr::FinalizeValue() {
754 result_pages_.push_back(xattr_mgr_->mount_point()->file_system()->
755 no_open_files()->ToString());
756 }
757
758 void UsedDirPMagicXattr::FinalizeValue() {
759 result_pages_.push_back(xattr_mgr_->mount_point()->file_system()->
760 no_open_dirs()->ToString());
761 }
762
763 void VersionMagicXattr::FinalizeValue() {
764 result_pages_.push_back(std::string(VERSION) + "."
765 + std::string(CVMFS_PATCH_LEVEL));
766 }
767
768 void ExternalURLMagicXattr::FinalizeValue() {
769 std::vector<std::string> host_chain;
770 std::vector<int> rtt;
771 unsigned current_host;
772 if (xattr_mgr_->mount_point()->external_download_mgr() != NULL) {
773 xattr_mgr_->mount_point()->external_download_mgr()->GetHostInfo(
774 &host_chain, &rtt, &current_host);
775 if (host_chain.size()) {
776 result_pages_.push_back(std::string(host_chain[current_host])
777 + std::string(path_.c_str()));
778 return;
779 }
780 }
781 result_pages_.push_back("");
782 }
783
784 bool ExternalURLMagicXattr::PrepareValueFenced() {
785 return dirent_->IsRegular() && dirent_->IsExternalFile();
786 }
787