GCC Code Coverage Report


Directory: cvmfs/
File: cvmfs/magic_xattr.cc
Date: 2026-04-26 02:35:59
Exec Total Coverage
Lines: 184 518 35.5%
Branches: 301 1051 28.6%

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