5 #define __STDC_FORMAT_MACROS
9 #include <sys/capability.h>
23 const string &rdonly_path,
24 const string &union_path,
25 const string &scratch_path)
26 :
SyncUnion(mediator, rdonly_path, union_path, scratch_path)
27 , hardlink_lower_inode_(0) { }
36 const cap_value_t cap =
45 #ifdef CAP_IS_SUPPORTED
46 if (!CAP_IS_SUPPORTED(cap)) {
54 "Failed to obtain capability state "
55 "of current process (errno: %d)",
60 cap_flag_value_t cap_state;
61 if (cap_get_flag(caps, cap, CAP_EFFECTIVE, &cap_state) != 0) {
63 "Failed to check effective set for "
64 "CAP_SYS_ADMIN (errno: %d)",
69 if (cap_state == CAP_SET) {
74 if (cap_get_flag(caps, cap, CAP_PERMITTED, &cap_state) != 0) {
76 "Failed to check permitted set for "
77 "CAP_SYS_ADMIN (errno: %d)",
82 if (cap_state != CAP_SET) {
84 "CAP_SYS_ADMIN cannot be obtained. It's "
85 "not in the process's permitted-set.");
89 if (cap_set_flag(caps, CAP_EFFECTIVE, 1, &cap, CAP_SET) != 0) {
91 "Cannot set CAP_SYS_ADMIN as effective "
92 "for the current process (errno: %d)",
97 if (cap_set_proc(caps) != 0) {
99 "Cannot reset capabilities for current "
100 "process (errno: %d)",
110 cap_t caps = cap_get_proc();
118 if (entry->IsGraftMarker() || entry->IsWhiteout() || entry->IsDirectory()) {
128 if (!entry->IsNew() && !entry->WasDirectory()
129 && entry->GetRdOnlyLinkcount() > 1) {
131 "OverlayFS has copied-up a file (%s) "
132 "with existing hardlinks in lowerdir "
133 "(linkcount %d). OverlayFS cannot handle "
134 "hardlinks and would produce "
135 "inconsistencies. \n\n"
136 "Consider running this command: \n"
137 " cvmfs_server eliminate-hardlinks\n\n"
139 entry->GetUnionPath().c_str(), entry->GetRdOnlyLinkcount());
144 assert(entry->IsRegularFile() || entry->IsSymlink()
145 || entry->IsSpecialFile());
146 if (entry->GetUnionLinkcount() > 1) {
148 "Warning: Found file with linkcount > 1 "
149 "(%s). We will break up these hardlinks.",
150 entry->GetUnionPath().c_str());
151 entry->MaskHardlink();
172 "OverlayFS starting traversal "
173 "recursion for scratch_path=[%s]",
187 string const &compare_value) {
193 compare_len = compare_value.length() + 1;
196 buf =
static_cast<char *
>(alloca(compare_len + 1));
198 const ssize_t len = ::readlink(path.c_str(), buf, compare_len);
202 return (std::string(buf) == compare_value);
206 "SyncUnionOverlayfs::ReadlinkEquals error reading link [%s]: %d\n",
207 path.c_str(), errno);
226 std::vector<std::string> attrs = xattrs->
ListKeys();
227 std::vector<std::string>::const_iterator i = attrs.begin();
228 const std::vector<std::string>::const_iterator iend = attrs.end();
230 for (; i != iend; ++i) {
234 return xattrs.
IsValid() && xattrs->
Has(attr_name);
245 const bool is_chardev_whiteout = entry->IsCharacterDevice() &&
246 entry->GetRdevMajor() == 0 &&
247 entry->GetRdevMinor() == 0;
248 if (is_chardev_whiteout)
251 const std::string whiteout_prefix_ =
".wh.";
252 const bool has_wh_prefix =
253 HasPrefix(entry->filename().c_str(), whiteout_prefix_,
true);
257 const bool is_symlink_whiteout =
259 if (is_symlink_whiteout)
266 const bool is_whiteout =
ReadlinkEquals(path,
"(overlay-whiteout)");
281 const std::string path = directory->GetScratchPath();
286 const bool is_opaque =
HasXattr(path.c_str(),
"trusted.overlay.opaque");
296 const std::string whiteout_prefix_ =
".wh.";
298 if (
HasPrefix(entry->filename().c_str(), whiteout_prefix_,
true)) {
299 return entry->filename().substr(whiteout_prefix_.length());
301 return entry->filename();
virtual void LeaveDirectory(const std::string &parent_dir, const std::string &dir_name)
bool IsWhiteoutSymlinkPath(const std::string &path) const
void PreprocessSyncItem(SharedPtr< SyncItem > entry) const
VoidCallback fn_new_symlink
VoidCallback fn_new_character_dev
void Recurse(const std::string &dir_path) const
bool IsOpaqueDirectory(SharedPtr< SyncItem > directory) const
virtual bool Initialize()
virtual void PreprocessSyncItem(SharedPtr< SyncItem > entry) const
std::string scratch_path() const
static bool HasXattr(std::string const &path, std::string const &attr_name)
A simple recursion engine to abstract the recursion of directories. It provides several callback hook...
assert((mem||(size==0))&&"Out Of Memory")
VoidCallback fn_leave_dir
bool ObtainSysAdminCapabilityInternal(cap_t caps)
virtual void ProcessSymlink(const std::string &parent_dir, const std::string &link_name)
BoolCallback fn_ignore_file
std::string UnwindWhiteoutFilename(SharedPtr< SyncItem > entry) const
VoidCallback fn_enter_dir
bool IsInitialized() const
bool ObtainSysAdminCapability() const
void ProcessBlockDevice(const std::string &parent_dir, const std::string &filename)
virtual bool IgnoreFilePredicate(const std::string &parent_dir, const std::string &filename)
void ProcessSocket(const std::string &parent_dir, const std::string &filename)
bool IsOpaqueDirPath(const std::string &path) const
virtual void ProcessRegularFile(const std::string &parent_dir, const std::string &filename)
VoidCallback fn_new_block_dev
bool Has(const std::string &key) const
void MaskFileHardlinks(SharedPtr< SyncItem > entry) const
void CheckForBrokenHardlink(SharedPtr< SyncItem > entry) const
bool HasPrefix(const string &str, const string &prefix, const bool ignore_case)
bool DirectoryExists(const std::string &path)
SyncUnionOverlayfs(SyncMediator *mediator, const std::string &rdonly_path, const std::string &union_path, const std::string &scratch_path)
VoidCallback fn_new_socket
BoolCallback fn_new_dir_prefix
virtual bool ProcessDirectory(const std::string &parent_dir, const std::string &dir_name)
static bool ReadlinkEquals(std::string const &path, std::string const &compare_value)
static XattrList * CreateFromFile(const std::string &path)
virtual void EnterDirectory(const std::string &parent_dir, const std::string &dir_name)
std::vector< std::string > ListKeys() const
void ProcessFifo(const std::string &parent_dir, const std::string &filename)
void ProcessCharacterDevice(const std::string &parent_dir, const std::string &filename)
bool IsWhiteoutEntry(SharedPtr< SyncItem > entry) const
CVMFS_EXPORT void LogCvmfs(const LogSource source, const int mask, const char *format,...)