GCC Code Coverage Report


Directory: cvmfs/
File: cvmfs/magic_xattr.cc
Date: 2025-06-22 02:36:02
Exec Total Coverage
Lines: 181 481 37.6%
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 1116 MagicXattrManager::MagicXattrManager(
20 MountPoint *mountpoint,
21 EVisibility visibility,
22 const std::set<std::string> &protected_xattrs,
23 1116 const std::set<gid_t> &priviledged_xattr_gids)
24 1116 : mount_point_(mountpoint)
25 1116 , visibility_(visibility)
26
1/2
✓ Branch 1 taken 1116 times.
✗ Branch 2 not taken.
1116 , protected_xattrs_(protected_xattrs)
27
1/2
✓ Branch 1 taken 1116 times.
✗ Branch 2 not taken.
1116 , privileged_xattr_gids_(priviledged_xattr_gids)
28 1116 , is_frozen_(false) {
29
4/8
✓ Branch 1 taken 1116 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1116 times.
✗ Branch 5 not taken.
✓ Branch 8 taken 1116 times.
✗ Branch 9 not taken.
✓ Branch 11 taken 1116 times.
✗ Branch 12 not taken.
1116 Register("user.catalog_counters", new CatalogCountersMagicXattr());
30
4/8
✓ Branch 1 taken 1116 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1116 times.
✗ Branch 5 not taken.
✓ Branch 8 taken 1116 times.
✗ Branch 9 not taken.
✓ Branch 11 taken 1116 times.
✗ Branch 12 not taken.
1116 Register("user.external_host", new ExternalHostMagicXattr());
31
4/8
✓ Branch 1 taken 1116 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1116 times.
✗ Branch 5 not taken.
✓ Branch 8 taken 1116 times.
✗ Branch 9 not taken.
✓ Branch 11 taken 1116 times.
✗ Branch 12 not taken.
1116 Register("user.external_timeout", new ExternalTimeoutMagicXattr());
32
4/8
✓ Branch 1 taken 1116 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1116 times.
✗ Branch 5 not taken.
✓ Branch 8 taken 1116 times.
✗ Branch 9 not taken.
✓ Branch 11 taken 1116 times.
✗ Branch 12 not taken.
1116 Register("user.fqrn", new FqrnMagicXattr());
33
4/8
✓ Branch 1 taken 1116 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1116 times.
✗ Branch 5 not taken.
✓ Branch 8 taken 1116 times.
✗ Branch 9 not taken.
✓ Branch 11 taken 1116 times.
✗ Branch 12 not taken.
1116 Register("user.host", new HostMagicXattr());
34
4/8
✓ Branch 1 taken 1116 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1116 times.
✗ Branch 5 not taken.
✓ Branch 8 taken 1116 times.
✗ Branch 9 not taken.
✓ Branch 11 taken 1116 times.
✗ Branch 12 not taken.
1116 Register("user.host_list", new HostListMagicXattr());
35
4/8
✓ Branch 1 taken 1116 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1116 times.
✗ Branch 5 not taken.
✓ Branch 8 taken 1116 times.
✗ Branch 9 not taken.
✓ Branch 11 taken 1116 times.
✗ Branch 12 not taken.
1116 Register("user.ncleanup24", new NCleanup24MagicXattr());
36
4/8
✓ Branch 1 taken 1116 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1116 times.
✗ Branch 5 not taken.
✓ Branch 8 taken 1116 times.
✗ Branch 9 not taken.
✓ Branch 11 taken 1116 times.
✗ Branch 12 not taken.
1116 Register("user.nclg", new NClgMagicXattr());
37
4/8
✓ Branch 1 taken 1116 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1116 times.
✗ Branch 5 not taken.
✓ Branch 8 taken 1116 times.
✗ Branch 9 not taken.
✓ Branch 11 taken 1116 times.
✗ Branch 12 not taken.
1116 Register("user.ndiropen", new NDirOpenMagicXattr());
38
4/8
✓ Branch 1 taken 1116 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1116 times.
✗ Branch 5 not taken.
✓ Branch 8 taken 1116 times.
✗ Branch 9 not taken.
✓ Branch 11 taken 1116 times.
✗ Branch 12 not taken.
1116 Register("user.ndownload", new NDownloadMagicXattr());
39
4/8
✓ Branch 1 taken 1116 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1116 times.
✗ Branch 5 not taken.
✓ Branch 8 taken 1116 times.
✗ Branch 9 not taken.
✓ Branch 11 taken 1116 times.
✗ Branch 12 not taken.
1116 Register("user.nioerr", new NIOErrMagicXattr());
40
4/8
✓ Branch 1 taken 1116 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1116 times.
✗ Branch 5 not taken.
✓ Branch 8 taken 1116 times.
✗ Branch 9 not taken.
✓ Branch 11 taken 1116 times.
✗ Branch 12 not taken.
1116 Register("user.nopen", new NOpenMagicXattr());
41
4/8
✓ Branch 1 taken 1116 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1116 times.
✗ Branch 5 not taken.
✓ Branch 8 taken 1116 times.
✗ Branch 9 not taken.
✓ Branch 11 taken 1116 times.
✗ Branch 12 not taken.
1116 Register("user.hitrate", new HitrateMagicXattr());
42
4/8
✓ Branch 1 taken 1116 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1116 times.
✗ Branch 5 not taken.
✓ Branch 8 taken 1116 times.
✗ Branch 9 not taken.
✓ Branch 11 taken 1116 times.
✗ Branch 12 not taken.
1116 Register("user.logbuffer", new LogBufferXattr());
43
4/8
✓ Branch 1 taken 1116 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1116 times.
✗ Branch 5 not taken.
✓ Branch 8 taken 1116 times.
✗ Branch 9 not taken.
✓ Branch 11 taken 1116 times.
✗ Branch 12 not taken.
1116 Register("user.proxy", new ProxyMagicXattr());
44
4/8
✓ Branch 1 taken 1116 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1116 times.
✗ Branch 5 not taken.
✓ Branch 8 taken 1116 times.
✗ Branch 9 not taken.
✓ Branch 11 taken 1116 times.
✗ Branch 12 not taken.
1116 Register("user.proxy_list", new ProxyListMagicXattr());
45
4/8
✓ Branch 1 taken 1116 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1116 times.
✗ Branch 5 not taken.
✓ Branch 8 taken 1116 times.
✗ Branch 9 not taken.
✓ Branch 11 taken 1116 times.
✗ Branch 12 not taken.
1116 Register("user.proxy_list_external", new ProxyListExternalMagicXattr());
46
4/8
✓ Branch 1 taken 1116 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1116 times.
✗ Branch 5 not taken.
✓ Branch 8 taken 1116 times.
✗ Branch 9 not taken.
✓ Branch 11 taken 1116 times.
✗ Branch 12 not taken.
1116 Register("user.pubkeys", new PubkeysMagicXattr());
47
4/8
✓ Branch 1 taken 1116 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1116 times.
✗ Branch 5 not taken.
✓ Branch 8 taken 1116 times.
✗ Branch 9 not taken.
✓ Branch 11 taken 1116 times.
✗ Branch 12 not taken.
1116 Register("user.repo_counters", new RepoCountersMagicXattr());
48
4/8
✓ Branch 1 taken 1116 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1116 times.
✗ Branch 5 not taken.
✓ Branch 8 taken 1116 times.
✗ Branch 9 not taken.
✓ Branch 11 taken 1116 times.
✗ Branch 12 not taken.
1116 Register("user.repo_metainfo", new RepoMetainfoMagicXattr());
49
4/8
✓ Branch 1 taken 1116 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1116 times.
✗ Branch 5 not taken.
✓ Branch 8 taken 1116 times.
✗ Branch 9 not taken.
✓ Branch 11 taken 1116 times.
✗ Branch 12 not taken.
1116 Register("user.revision", new RevisionMagicXattr());
50
4/8
✓ Branch 1 taken 1116 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1116 times.
✗ Branch 5 not taken.
✓ Branch 8 taken 1116 times.
✗ Branch 9 not taken.
✓ Branch 11 taken 1116 times.
✗ Branch 12 not taken.
1116 Register("user.root_hash", new RootHashMagicXattr());
51
4/8
✓ Branch 1 taken 1116 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1116 times.
✗ Branch 5 not taken.
✓ Branch 8 taken 1116 times.
✗ Branch 9 not taken.
✓ Branch 11 taken 1116 times.
✗ Branch 12 not taken.
1116 Register("user.rx", new RxMagicXattr());
52
4/8
✓ Branch 1 taken 1116 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1116 times.
✗ Branch 5 not taken.
✓ Branch 8 taken 1116 times.
✗ Branch 9 not taken.
✓ Branch 11 taken 1116 times.
✗ Branch 12 not taken.
1116 Register("user.speed", new SpeedMagicXattr());
53
4/8
✓ Branch 1 taken 1116 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1116 times.
✗ Branch 5 not taken.
✓ Branch 8 taken 1116 times.
✗ Branch 9 not taken.
✓ Branch 11 taken 1116 times.
✗ Branch 12 not taken.
1116 Register("user.tag", new TagMagicXattr());
54
4/8
✓ Branch 1 taken 1116 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1116 times.
✗ Branch 5 not taken.
✓ Branch 8 taken 1116 times.
✗ Branch 9 not taken.
✓ Branch 11 taken 1116 times.
✗ Branch 12 not taken.
1116 Register("user.timeout", new TimeoutMagicXattr());
55
4/8
✓ Branch 1 taken 1116 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1116 times.
✗ Branch 5 not taken.
✓ Branch 8 taken 1116 times.
✗ Branch 9 not taken.
✓ Branch 11 taken 1116 times.
✗ Branch 12 not taken.
1116 Register("user.timeout_direct", new TimeoutDirectMagicXattr());
56
4/8
✓ Branch 1 taken 1116 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1116 times.
✗ Branch 5 not taken.
✓ Branch 8 taken 1116 times.
✗ Branch 9 not taken.
✓ Branch 11 taken 1116 times.
✗ Branch 12 not taken.
1116 Register("user.timestamp_last_ioerr", new TimestampLastIOErrMagicXattr());
57
4/8
✓ Branch 1 taken 1116 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1116 times.
✗ Branch 5 not taken.
✓ Branch 8 taken 1116 times.
✗ Branch 9 not taken.
✓ Branch 11 taken 1116 times.
✗ Branch 12 not taken.
1116 Register("user.usedfd", new UsedFdMagicXattr());
58
4/8
✓ Branch 1 taken 1116 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1116 times.
✗ Branch 5 not taken.
✓ Branch 8 taken 1116 times.
✗ Branch 9 not taken.
✓ Branch 11 taken 1116 times.
✗ Branch 12 not taken.
1116 Register("user.useddirp", new UsedDirPMagicXattr());
59
4/8
✓ Branch 1 taken 1116 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1116 times.
✗ Branch 5 not taken.
✓ Branch 8 taken 1116 times.
✗ Branch 9 not taken.
✓ Branch 11 taken 1116 times.
✗ Branch 12 not taken.
1116 Register("user.version", new VersionMagicXattr());
60
61
4/8
✓ Branch 1 taken 1116 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1116 times.
✗ Branch 5 not taken.
✓ Branch 8 taken 1116 times.
✗ Branch 9 not taken.
✓ Branch 11 taken 1116 times.
✗ Branch 12 not taken.
1116 Register("user.hash", new HashMagicXattr());
62
4/8
✓ Branch 1 taken 1116 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1116 times.
✗ Branch 5 not taken.
✓ Branch 8 taken 1116 times.
✗ Branch 9 not taken.
✓ Branch 11 taken 1116 times.
✗ Branch 12 not taken.
1116 Register("user.lhash", new LHashMagicXattr());
63
64
4/8
✓ Branch 1 taken 1116 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1116 times.
✗ Branch 5 not taken.
✓ Branch 8 taken 1116 times.
✗ Branch 9 not taken.
✓ Branch 11 taken 1116 times.
✗ Branch 12 not taken.
1116 Register("user.chunk_list", new ChunkListMagicXattr());
65
4/8
✓ Branch 1 taken 1116 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1116 times.
✗ Branch 5 not taken.
✓ Branch 8 taken 1116 times.
✗ Branch 9 not taken.
✓ Branch 11 taken 1116 times.
✗ Branch 12 not taken.
1116 Register("user.chunks", new ChunksMagicXattr());
66
4/8
✓ Branch 1 taken 1116 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1116 times.
✗ Branch 5 not taken.
✓ Branch 8 taken 1116 times.
✗ Branch 9 not taken.
✓ Branch 11 taken 1116 times.
✗ Branch 12 not taken.
1116 Register("user.compression", new CompressionMagicXattr());
67
4/8
✓ Branch 1 taken 1116 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1116 times.
✗ Branch 5 not taken.
✓ Branch 8 taken 1116 times.
✗ Branch 9 not taken.
✓ Branch 11 taken 1116 times.
✗ Branch 12 not taken.
1116 Register("user.direct_io", new DirectIoMagicXattr());
68
4/8
✓ Branch 1 taken 1116 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1116 times.
✗ Branch 5 not taken.
✓ Branch 8 taken 1116 times.
✗ Branch 9 not taken.
✓ Branch 11 taken 1116 times.
✗ Branch 12 not taken.
1116 Register("user.external_file", new ExternalFileMagicXattr());
69
70
4/8
✓ Branch 1 taken 1116 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1116 times.
✗ Branch 5 not taken.
✓ Branch 8 taken 1116 times.
✗ Branch 9 not taken.
✓ Branch 11 taken 1116 times.
✗ Branch 12 not taken.
1116 Register("user.rawlink", new RawlinkMagicXattr());
71
4/8
✓ Branch 1 taken 1116 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1116 times.
✗ Branch 5 not taken.
✓ Branch 8 taken 1116 times.
✗ Branch 9 not taken.
✓ Branch 11 taken 1116 times.
✗ Branch 12 not taken.
1116 Register("xfsroot.rawlink", new RawlinkMagicXattr());
72
73
4/8
✓ Branch 1 taken 1116 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1116 times.
✗ Branch 5 not taken.
✓ Branch 8 taken 1116 times.
✗ Branch 9 not taken.
✓ Branch 11 taken 1116 times.
✗ Branch 12 not taken.
1116 Register("user.authz", new AuthzMagicXattr());
74
4/8
✓ Branch 1 taken 1116 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1116 times.
✗ Branch 5 not taken.
✓ Branch 8 taken 1116 times.
✗ Branch 9 not taken.
✓ Branch 11 taken 1116 times.
✗ Branch 12 not taken.
1116 Register("user.external_url", new ExternalURLMagicXattr());
75 1116 }
76
77 36 std::string MagicXattrManager::GetListString(catalog::DirectoryEntry *dirent) {
78
2/2
✓ Branch 1 taken 18 times.
✓ Branch 2 taken 18 times.
36 if (visibility() == kVisibilityNever) {
79
1/2
✓ Branch 2 taken 18 times.
✗ Branch 3 not taken.
18 return "";
80 }
81 // Only the root entry has an empty name
82
7/12
✓ Branch 1 taken 18 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 18 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 9 times.
✓ Branch 8 taken 9 times.
✓ Branch 9 taken 18 times.
✗ Branch 10 not taken.
✓ Branch 12 taken 9 times.
✓ Branch 13 taken 9 times.
✗ Branch 14 not taken.
✗ Branch 15 not taken.
18 if (visibility() == kVisibilityRootOnly && !dirent->name().IsEmpty()) {
83
1/2
✓ Branch 2 taken 9 times.
✗ Branch 3 not taken.
9 return "";
84 }
85
86 9 std::string result;
87 9 std::map<std::string, BaseMagicXattr *>::iterator it = xattr_list_.begin();
88
2/2
✓ Branch 3 taken 378 times.
✓ Branch 4 taken 9 times.
387 for (; it != xattr_list_.end(); ++it) {
89
1/2
✓ Branch 2 taken 378 times.
✗ Branch 3 not taken.
378 const MagicXattrFlavor flavor = (*it).second->GetXattrFlavor();
90 // Skip those which should not be displayed
91
6/7
✓ Branch 0 taken 279 times.
✓ Branch 1 taken 18 times.
✓ Branch 2 taken 45 times.
✓ Branch 3 taken 9 times.
✓ Branch 4 taken 18 times.
✓ Branch 5 taken 9 times.
✗ Branch 6 not taken.
378 switch (flavor) {
92 279 case kXattrBase:
93 279 break;
94 18 case kXattrWithHash:
95
1/2
✓ Branch 2 taken 18 times.
✗ Branch 3 not taken.
18 if (dirent->checksum().IsNull())
96 18 continue;
97 break;
98 45 case kXattrRegular:
99
1/2
✓ Branch 1 taken 45 times.
✗ Branch 2 not taken.
45 if (!dirent->IsRegular())
100 45 continue;
101 break;
102 9 case kXattrExternal:
103
2/6
✗ Branch 1 not taken.
✓ Branch 2 taken 9 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✓ Branch 6 taken 9 times.
✗ Branch 7 not taken.
9 if (!(dirent->IsRegular() && dirent->IsExternalFile()))
104 9 continue;
105 break;
106 18 case kXattrSymlink:
107
1/2
✓ Branch 1 taken 18 times.
✗ Branch 2 not taken.
18 if (!dirent->IsLink())
108 18 continue;
109 break;
110 9 case kXattrAuthz:
111
1/2
✓ Branch 1 taken 9 times.
✗ Branch 2 not taken.
9 if (!mount_point_->has_membership_req())
112 9 continue;
113 break;
114 default:
115 PANIC("unknown magic xattr flavor");
116 }
117
1/2
✓ Branch 2 taken 279 times.
✗ Branch 3 not taken.
279 result += (*it).first;
118
1/2
✓ Branch 1 taken 279 times.
✗ Branch 2 not taken.
279 result.push_back('\0');
119 }
120
121 9 return result;
122 9 }
123
124 36 BaseMagicXattr *MagicXattrManager::GetLocked(const std::string &name,
125 PathString path,
126 catalog::DirectoryEntry *d) {
127 BaseMagicXattr *result;
128
1/2
✓ Branch 1 taken 36 times.
✗ Branch 2 not taken.
36 if (xattr_list_.count(name) > 0) {
129 36 result = xattr_list_[name];
130 } else {
131 return NULL;
132 }
133
134
1/2
✓ Branch 2 taken 36 times.
✗ Branch 3 not taken.
36 result->Lock(path, d);
135
136 36 return result;
137 }
138
139 46872 void MagicXattrManager::Register(const std::string &name,
140 BaseMagicXattr *magic_xattr) {
141
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 46872 times.
46872 assert(!is_frozen_);
142
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 46872 times.
46872 if (xattr_list_.count(name) > 0) {
143 PANIC(kLogSyslogErr,
144 "Magic extended attribute with name %s already registered",
145 name.c_str());
146 }
147 46872 magic_xattr->xattr_mgr_ = this;
148 46872 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 9 times.
✓ Branch 2 taken 46863 times.
46872 if (protected_xattrs_.count(name) > 0) {
153 9 magic_xattr->MarkProtected();
154 }
155 46872 }
156
157 18 bool MagicXattrManager::IsPrivilegedGid(gid_t gid) {
158 18 return privileged_xattr_gids_.count(gid) > 0;
159 }
160
161 18 bool BaseMagicXattr::PrepareValueFencedProtected(gid_t gid) {
162
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 18 times.
18 assert(xattr_mgr_->is_frozen());
163
5/6
✓ Branch 0 taken 18 times.
✗ Branch 1 not taken.
✓ Branch 3 taken 9 times.
✓ Branch 4 taken 9 times.
✓ Branch 5 taken 9 times.
✓ Branch 6 taken 9 times.
18 if (is_protected_ && !xattr_mgr_->IsPrivilegedGid(gid)) {
164 9 return false;
165 }
166
167 9 return PrepareValueFenced();
168 }
169
170 9 void MagicXattrManager::SanityCheckProtectedXattrs() {
171 9 std::set<std::string>::const_iterator iter;
172 9 std::vector<string> tmp;
173
2/2
✓ Branch 3 taken 9 times.
✓ Branch 4 taken 9 times.
18 for (iter = protected_xattrs_.begin(); iter != protected_xattrs_.end();
174 9 iter++) {
175
2/4
✓ Branch 3 taken 9 times.
✗ Branch 4 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 9 times.
9 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 9 times.
9 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 9 tmp.clear();
189 9 std::set<gid_t>::const_iterator iter_gid;
190 9 for (iter_gid = privileged_xattr_gids_.begin();
191
2/2
✓ Branch 2 taken 9 times.
✓ Branch 3 taken 9 times.
18 iter_gid != privileged_xattr_gids_.end();
192 9 iter_gid++) {
193
2/4
✓ Branch 2 taken 9 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 9 times.
✗ Branch 6 not taken.
9 tmp.push_back(StringifyUint(*iter_gid));
194 }
195
196
1/2
✓ Branch 1 taken 9 times.
✗ Branch 2 not taken.
9 if (tmp.size() > 0) {
197
2/4
✓ Branch 2 taken 9 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 9 times.
✗ Branch 6 not taken.
18 const std::string msg = JoinStrings(tmp, ",");
198
1/2
✓ Branch 2 taken 9 times.
✗ Branch 3 not taken.
9 LogCvmfs(kLogCvmfs, kLogDebug | kLogSyslog,
199 "Following CVMFS_XATTR_PRIVILEGED_GIDS are set: %s", msg.c_str());
200 9 }
201 9 }
202
203 36 std::string BaseMagicXattr::HeaderMultipageHuman(uint32_t requested_page) {
204
3/6
✓ Branch 1 taken 36 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 36 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 36 times.
✗ Branch 8 not taken.
72 return "# Access page at idx: " + StringifyUint(requested_page) + ". "
205
2/4
✓ Branch 3 taken 36 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 36 times.
✗ Branch 7 not taken.
144 + "Total num pages: " + StringifyUint(result_pages_.size())
206
1/2
✓ Branch 1 taken 36 times.
✗ Branch 2 not taken.
72 + " (access other pages: xattr~<page_num>, starting "
207
1/2
✓ Branch 1 taken 36 times.
✗ Branch 2 not taken.
72 + " with 0; number of pages available: xattr~?)\n";
208 }
209
210 180 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 180 times.
180 assert(requested_page >= -1);
213 180 result_pages_.clear();
214
1/2
✓ Branch 1 taken 180 times.
✗ Branch 2 not taken.
180 FinalizeValue();
215
216
1/2
✓ Branch 2 taken 180 times.
✗ Branch 3 not taken.
180 std::string res = "";
217
2/2
✓ Branch 0 taken 126 times.
✓ Branch 1 taken 54 times.
180 if (mode == kXattrMachineMode) {
218
2/2
✓ Branch 1 taken 18 times.
✓ Branch 2 taken 108 times.
126 if (requested_page >= static_cast<int32_t>(result_pages_.size())) {
219
1/2
✓ Branch 1 taken 18 times.
✗ Branch 2 not taken.
18 return std::pair<bool, std::string>(false, "");
220 }
221
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 108 times.
108 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 54 times.
✗ Branch 1 not taken.
54 } else if (mode == kXattrHumanMode) {
226
2/2
✓ Branch 1 taken 18 times.
✓ Branch 2 taken 36 times.
54 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 18 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 18 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 18 times.
✗ Branch 9 not taken.
36 + StringifyUint(result_pages_.size()) + " pages available.\n"
231
1/2
✓ Branch 1 taken 18 times.
✗ Branch 2 not taken.
36 + "Access them with xattr~<page_num> (machine-readable mode) "
232
1/2
✓ Branch 1 taken 18 times.
✗ Branch 2 not taken.
36 + "or xattr@<page_num> (human-readable mode).\n"
233
1/2
✓ Branch 1 taken 18 times.
✗ Branch 2 not taken.
18 + "Use xattr@? or xattr~? to get extra info about the attribute");
234
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 36 times.
36 } 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 36 times.
✗ Branch 2 not taken.
36 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 144 times.
✗ Branch 3 not taken.
144 res += result_pages_[requested_page];
249
250
1/2
✓ Branch 1 taken 144 times.
✗ Branch 2 not taken.
144 return std::pair<bool, std::string>(true, res);
251 180 }
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 9 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 18 void FqrnMagicXattr::FinalizeValue() {
397
1/2
✓ Branch 3 taken 18 times.
✗ Branch 4 not taken.
18 result_pages_.push_back(xattr_mgr_->mount_point()->fqrn());
398 18 }
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 =
456 xattr_mgr_->mount_point()->file_system()->cache_mgr()->ChecksumFd(
457 fd, &hash);
458 if (retval_i != 0)
459 result = "I/O error (" + StringifyInt(retval_i) + ")";
460 else
461 result = hash.ToString();
462 xattr_mgr_->mount_point()->file_system()->cache_mgr()->Close(fd);
463 }
464 result_pages_.push_back(result);
465 }
466
467
1/2
✓ Branch 2 taken 1116 times.
✗ Branch 3 not taken.
1116 LogBufferXattr::LogBufferXattr() : BaseMagicXattr(), throttle_(1, 500, 2000) { }
468
469 18 void LogBufferXattr::FinalizeValue() {
470
1/2
✓ Branch 1 taken 18 times.
✗ Branch 2 not taken.
18 throttle_.Throttle();
471
1/2
✓ Branch 1 taken 18 times.
✗ Branch 2 not taken.
18 std::vector<LogBufferEntry> buffer = GetLogBuffer();
472 18 std::string result;
473 18 for (std::vector<LogBufferEntry>::reverse_iterator itr = buffer.rbegin();
474
3/4
✓ Branch 2 taken 198 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 180 times.
✓ Branch 5 taken 18 times.
198 itr != buffer.rend();
475 180 ++itr) {
476
3/4
✓ Branch 1 taken 180 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 9 times.
✓ Branch 5 taken 171 times.
180 if (itr->message.size() > kMaxLogLine) {
477
2/4
✓ Branch 1 taken 9 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 9 times.
✗ Branch 5 not taken.
9 itr->message.resize(kMaxLogLine);
478
2/4
✓ Branch 1 taken 9 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 9 times.
✗ Branch 5 not taken.
9 itr->message += " <snip>";
479 }
480
6/12
✓ Branch 1 taken 180 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 180 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 180 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 180 times.
✗ Branch 11 not taken.
✓ Branch 13 taken 180 times.
✗ Branch 14 not taken.
✓ Branch 16 taken 180 times.
✗ Branch 17 not taken.
360 result += "[" + StringifyLocalTime(itr->timestamp) + "] " + itr->message
481
2/4
✓ Branch 1 taken 180 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 180 times.
✗ Branch 5 not taken.
180 + "\n";
482 }
483
1/2
✓ Branch 1 taken 18 times.
✗ Branch 2 not taken.
18 result_pages_.push_back(result);
484 18 }
485
486 void NCleanup24MagicXattr::FinalizeValue() {
487 QuotaManager *quota_mgr = xattr_mgr_->mount_point()
488 ->file_system()
489 ->cache_mgr()
490 ->quota_mgr();
491 if (!quota_mgr->HasCapability(QuotaManager::kCapIntrospectCleanupRate)) {
492 result_pages_.push_back(StringifyInt(-1));
493 } else {
494 const uint64_t period_s = 24 * 60 * 60;
495 const uint64_t rate = quota_mgr->GetCleanupRate(period_s);
496 result_pages_.push_back(StringifyUint(rate));
497 }
498 }
499
500 bool NClgMagicXattr::PrepareValueFenced() {
501 n_catalogs_ = xattr_mgr_->mount_point()->catalog_mgr()->GetNumCatalogs();
502 return true;
503 }
504
505 void NClgMagicXattr::FinalizeValue() {
506 result_pages_.push_back(StringifyInt(n_catalogs_));
507 }
508
509 void NDirOpenMagicXattr::FinalizeValue() {
510 result_pages_.push_back(
511 xattr_mgr_->mount_point()->file_system()->n_fs_dir_open()->ToString());
512 }
513
514 void NDownloadMagicXattr::FinalizeValue() {
515 result_pages_.push_back(xattr_mgr_->mount_point()
516 ->statistics()
517 ->Lookup("fetch.n_downloads")
518 ->Print());
519 }
520
521 void NIOErrMagicXattr::FinalizeValue() {
522 result_pages_.push_back(StringifyInt(
523 xattr_mgr_->mount_point()->file_system()->io_error_info()->count()));
524 }
525
526 void NOpenMagicXattr::FinalizeValue() {
527 result_pages_.push_back(
528 xattr_mgr_->mount_point()->file_system()->n_fs_open()->ToString());
529 }
530
531 void HitrateMagicXattr::FinalizeValue() {
532 const int64_t n_invocations = xattr_mgr_->mount_point()
533 ->statistics()
534 ->Lookup("fetch.n_invocations")
535 ->Get();
536 if (n_invocations == 0) {
537 result_pages_.push_back("n/a");
538 return;
539 }
540
541 const int64_t n_downloads = xattr_mgr_->mount_point()
542 ->statistics()
543 ->Lookup("fetch.n_downloads")
544 ->Get();
545 const float hitrate = 100. * (1. - (static_cast<float>(n_downloads) /
546 static_cast<float>(n_invocations)));
547 result_pages_.push_back(StringifyDouble(hitrate));
548 }
549
550 void ProxyMagicXattr::FinalizeValue() {
551 vector<vector<download::DownloadManager::ProxyInfo> > proxy_chain;
552 unsigned current_group;
553 xattr_mgr_->mount_point()->download_mgr()->GetProxyInfo(&proxy_chain,
554 &current_group, NULL);
555 if (proxy_chain.size()) {
556 result_pages_.push_back(proxy_chain[current_group][0].url);
557 } else {
558 result_pages_.push_back("DIRECT");
559 }
560 }
561
562 static void ListProxy(download::DownloadManager *dm,
563 std::vector<std::string> *result_pages) {
564 vector<vector<download::DownloadManager::ProxyInfo> > proxy_chain;
565 unsigned current_group;
566 dm->GetProxyInfo(&proxy_chain, &current_group, NULL);
567 std::string buf = "";
568 for (unsigned int i = 0; i < proxy_chain.size(); i++) {
569 for (unsigned int j = 0; j < proxy_chain[i].size(); j++) {
570 buf += proxy_chain[i][j].url;
571 buf += "\n";
572 }
573
574 if (buf.size() > BaseMagicXattr::kMaxCharsPerPage) {
575 result_pages->push_back(buf);
576 buf = "";
577 }
578 }
579
580 if (buf.size() > 0 || result_pages->size() == 0) {
581 result_pages->push_back(buf);
582 }
583 }
584
585 void ProxyListMagicXattr::FinalizeValue() {
586 ListProxy(xattr_mgr_->mount_point()->download_mgr(), &result_pages_);
587 }
588
589 void ProxyListExternalMagicXattr::FinalizeValue() {
590 ListProxy(xattr_mgr_->mount_point()->external_download_mgr(), &result_pages_);
591 }
592
593 bool PubkeysMagicXattr::PrepareValueFenced() {
594 pubkeys_ = xattr_mgr_->mount_point()
595 ->signature_mgr()
596 ->GetActivePubkeysAsVector();
597 return true;
598 }
599
600 144 void PubkeysMagicXattr::FinalizeValue() {
601 144 size_t full_size = 0;
602
603
2/2
✓ Branch 1 taken 711 times.
✓ Branch 2 taken 144 times.
855 for (size_t i = 0; i < pubkeys_.size(); i++) {
604 711 full_size += pubkeys_[i].size();
605 }
606
607
2/2
✓ Branch 0 taken 18 times.
✓ Branch 1 taken 126 times.
144 if (full_size == 0) {
608 18 return;
609 }
610
611 126 size_t size_within_page = 0;
612
1/2
✓ Branch 2 taken 126 times.
✗ Branch 3 not taken.
126 std::string res = "";
613
614
2/2
✓ Branch 1 taken 711 times.
✓ Branch 2 taken 126 times.
837 for (size_t i = 0; i < pubkeys_.size(); i++) {
615
2/2
✓ Branch 2 taken 117 times.
✓ Branch 3 taken 594 times.
711 if (size_within_page + pubkeys_[i].size() >= kMaxCharsPerPage) {
616
1/2
✓ Branch 1 taken 117 times.
✗ Branch 2 not taken.
117 result_pages_.push_back(res);
617
1/2
✓ Branch 1 taken 117 times.
✗ Branch 2 not taken.
117 res = "";
618 117 size_within_page = 0;
619 }
620
621
1/2
✓ Branch 2 taken 711 times.
✗ Branch 3 not taken.
711 res += pubkeys_[i];
622 711 size_within_page += pubkeys_[i].size();
623 }
624
1/2
✓ Branch 1 taken 126 times.
✗ Branch 2 not taken.
126 if (res.size() > 0) {
625
1/2
✓ Branch 1 taken 126 times.
✗ Branch 2 not taken.
126 result_pages_.push_back(res);
626 }
627 126 }
628
629 bool RawlinkMagicXattr::PrepareValueFenced() { return dirent_->IsLink(); }
630
631 void RawlinkMagicXattr::FinalizeValue() {
632 result_pages_.push_back(dirent_->symlink().ToString());
633 }
634
635 bool RepoCountersMagicXattr::PrepareValueFenced() {
636 counters_ = xattr_mgr_->mount_point()
637 ->catalog_mgr()
638 ->GetRootCatalog()
639 ->GetCounters();
640 return true;
641 }
642
643 void RepoCountersMagicXattr::FinalizeValue() {
644 result_pages_.push_back(counters_.GetCsvMap());
645 }
646
647 uint64_t RepoMetainfoMagicXattr::kMaxMetainfoLength = 65536;
648
649 bool RepoMetainfoMagicXattr::PrepareValueFenced() {
650 if (!xattr_mgr_->mount_point()->catalog_mgr()->manifest()) {
651 error_reason_ = "manifest not available";
652 return true;
653 }
654
655 metainfo_hash_ = xattr_mgr_->mount_point()
656 ->catalog_mgr()
657 ->manifest()
658 ->meta_info();
659 if (metainfo_hash_.IsNull()) {
660 error_reason_ = "metainfo not available";
661 return true;
662 }
663 return true;
664 }
665
666 void RepoMetainfoMagicXattr::FinalizeValue() {
667 if (metainfo_hash_.IsNull()) {
668 result_pages_.push_back(error_reason_);
669 return;
670 }
671
672 CacheManager::Label label;
673 label.path = xattr_mgr_->mount_point()->fqrn() + "("
674 + metainfo_hash_.ToString() + ")";
675 label.flags = CacheManager::kLabelMetainfo;
676 const int fd = xattr_mgr_->mount_point()->fetcher()->Fetch(
677 CacheManager::LabeledObject(metainfo_hash_, label));
678 if (fd < 0) {
679 result_pages_.push_back("Failed to open metadata file");
680 return;
681 }
682 const uint64_t actual_size =
683 xattr_mgr_->mount_point()->file_system()->cache_mgr()->GetSize(fd);
684 if (actual_size > kMaxMetainfoLength) {
685 xattr_mgr_->mount_point()->file_system()->cache_mgr()->Close(fd);
686 result_pages_.push_back("Failed to open: metadata file is too big");
687 return;
688 }
689 char buffer[kMaxMetainfoLength];
690 const int64_t bytes_read =
691 xattr_mgr_->mount_point()->file_system()->cache_mgr()->Pread(
692 fd, buffer, actual_size, 0);
693 xattr_mgr_->mount_point()->file_system()->cache_mgr()->Close(fd);
694 if (bytes_read < 0) {
695 result_pages_.push_back("Failed to read metadata file");
696 return;
697 }
698 result_pages_.push_back(string(buffer, buffer + bytes_read));
699 }
700
701 bool RevisionMagicXattr::PrepareValueFenced() {
702 revision_ = xattr_mgr_->mount_point()->catalog_mgr()->GetRevision();
703 return true;
704 }
705
706 void RevisionMagicXattr::FinalizeValue() {
707 result_pages_.push_back(StringifyUint(revision_));
708 }
709
710 bool RootHashMagicXattr::PrepareValueFenced() {
711 root_hash_ = xattr_mgr_->mount_point()->catalog_mgr()->GetRootHash();
712 return true;
713 }
714
715 void RootHashMagicXattr::FinalizeValue() {
716 result_pages_.push_back(root_hash_.ToString());
717 }
718
719 void RxMagicXattr::FinalizeValue() {
720 perf::Statistics *statistics = xattr_mgr_->mount_point()->statistics();
721 const int64_t rx = statistics->Lookup("download.sz_transferred_bytes")->Get();
722 result_pages_.push_back(StringifyInt(rx / 1024));
723 }
724
725 void SpeedMagicXattr::FinalizeValue() {
726 perf::Statistics *statistics = xattr_mgr_->mount_point()->statistics();
727 const int64_t rx = statistics->Lookup("download.sz_transferred_bytes")->Get();
728 const int64_t time = statistics->Lookup("download.sz_transfer_time")->Get();
729 if (time == 0) {
730 result_pages_.push_back("n/a");
731 } else {
732 result_pages_.push_back(StringifyInt((1000 * (rx / 1024)) / time));
733 }
734 }
735
736 bool TagMagicXattr::PrepareValueFenced() {
737 tag_ = xattr_mgr_->mount_point()->repository_tag();
738 return true;
739 }
740
741 void TagMagicXattr::FinalizeValue() { result_pages_.push_back(tag_); }
742
743 void TimeoutMagicXattr::FinalizeValue() {
744 unsigned seconds, seconds_direct;
745 xattr_mgr_->mount_point()->download_mgr()->GetTimeout(&seconds,
746 &seconds_direct);
747 result_pages_.push_back(StringifyUint(seconds));
748 }
749
750 void TimeoutDirectMagicXattr::FinalizeValue() {
751 unsigned seconds, seconds_direct;
752 xattr_mgr_->mount_point()->download_mgr()->GetTimeout(&seconds,
753 &seconds_direct);
754 result_pages_.push_back(StringifyUint(seconds_direct));
755 }
756
757 void TimestampLastIOErrMagicXattr::FinalizeValue() {
758 result_pages_.push_back(StringifyInt(xattr_mgr_->mount_point()
759 ->file_system()
760 ->io_error_info()
761 ->timestamp_last()));
762 }
763
764 void UsedFdMagicXattr::FinalizeValue() {
765 result_pages_.push_back(
766 xattr_mgr_->mount_point()->file_system()->no_open_files()->ToString());
767 }
768
769 void UsedDirPMagicXattr::FinalizeValue() {
770 result_pages_.push_back(
771 xattr_mgr_->mount_point()->file_system()->no_open_dirs()->ToString());
772 }
773
774 void VersionMagicXattr::FinalizeValue() {
775 result_pages_.push_back(std::string(CVMFS_VERSION) + "."
776 + std::string(CVMFS_PATCH_LEVEL));
777 }
778
779 void ExternalURLMagicXattr::FinalizeValue() {
780 std::vector<std::string> host_chain;
781 std::vector<int> rtt;
782 unsigned current_host;
783 if (xattr_mgr_->mount_point()->external_download_mgr() != NULL) {
784 xattr_mgr_->mount_point()->external_download_mgr()->GetHostInfo(
785 &host_chain, &rtt, &current_host);
786 if (host_chain.size()) {
787 result_pages_.push_back(std::string(host_chain[current_host])
788 + std::string(path_.c_str()));
789 return;
790 }
791 }
792 result_pages_.push_back("");
793 }
794
795 bool ExternalURLMagicXattr::PrepareValueFenced() {
796 return dirent_->IsRegular() && dirent_->IsExternalFile();
797 }
798