GCC Code Coverage Report


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