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 cap_value_t cap = CAP_SYS_ADMIN;
44 #ifdef CAP_IS_SUPPORTED
45 if (!CAP_IS_SUPPORTED(cap)) {
53 "Failed to obtain capability state "
54 "of current process (errno: %d)",
59 cap_flag_value_t cap_state;
60 if (cap_get_flag(caps, cap, CAP_EFFECTIVE, &cap_state) != 0) {
62 "Failed to check effective set for "
63 "CAP_SYS_ADMIN (errno: %d)",
68 if (cap_state == CAP_SET) {
73 if (cap_get_flag(caps, cap, CAP_PERMITTED, &cap_state) != 0) {
75 "Failed to check permitted set for "
76 "CAP_SYS_ADMIN (errno: %d)",
81 if (cap_state != CAP_SET) {
83 "CAP_SYS_ADMIN cannot be obtained. It's "
84 "not in the process's permitted-set.");
88 if (cap_set_flag(caps, CAP_EFFECTIVE, 1, &cap, CAP_SET) != 0) {
90 "Cannot set CAP_SYS_ADMIN as effective "
91 "for the current process (errno: %d)",
96 if (cap_set_proc(caps) != 0) {
98 "Cannot reset capabilities for current "
99 "process (errno: %d)",
109 cap_t caps = cap_get_proc();
117 if (entry->IsGraftMarker() || entry->IsWhiteout() || entry->IsDirectory()) {
127 if (!entry->IsNew() && !entry->WasDirectory()
128 && entry->GetRdOnlyLinkcount() > 1) {
130 "OverlayFS has copied-up a file (%s) "
131 "with existing hardlinks in lowerdir "
132 "(linkcount %d). OverlayFS cannot handle "
133 "hardlinks and would produce "
134 "inconsistencies. \n\n"
135 "Consider running this command: \n"
136 " cvmfs_server eliminate-hardlinks\n\n"
138 entry->GetUnionPath().c_str(), entry->GetRdOnlyLinkcount());
143 assert(entry->IsRegularFile() || entry->IsSymlink()
144 || entry->IsSpecialFile());
145 if (entry->GetUnionLinkcount() > 1) {
147 "Warning: Found file with linkcount > 1 "
148 "(%s). We will break up these hardlinks.",
149 entry->GetUnionPath().c_str());
150 entry->MaskHardlink();
171 "OverlayFS starting traversal "
172 "recursion for scratch_path=[%s]",
186 string const &compare_value) {
192 compare_len = compare_value.length() + 1;
195 buf =
static_cast<char *
>(alloca(compare_len + 1));
197 ssize_t len = ::readlink(path.c_str(), buf, compare_len);
201 return (std::string(buf) == compare_value);
205 "SyncUnionOverlayfs::ReadlinkEquals error reading link [%s]: %d\n",
206 path.c_str(), errno);
225 std::vector<std::string> attrs = xattrs->
ListKeys();
226 std::vector<std::string>::const_iterator i = attrs.begin();
227 std::vector<std::string>::const_iterator iend = attrs.end();
229 for (; i != iend; ++i) {
233 return xattrs.
IsValid() && xattrs->
Has(attr_name);
244 bool is_chardev_whiteout = entry->IsCharacterDevice()
245 && entry->GetRdevMajor() == 0
246 && entry->GetRdevMinor() == 0;
247 if (is_chardev_whiteout)
250 std::string whiteout_prefix_ =
".wh.";
251 bool has_wh_prefix =
HasPrefix(entry->filename().c_str(), whiteout_prefix_,
256 bool is_symlink_whiteout = entry->IsSymlink()
258 if (is_symlink_whiteout)
265 const bool is_whiteout =
ReadlinkEquals(path,
"(overlay-whiteout)");
280 const std::string path = directory->GetScratchPath();
285 bool is_opaque =
HasXattr(path.c_str(),
"trusted.overlay.opaque");
295 std::string whiteout_prefix_ =
".wh.";
297 if (
HasPrefix(entry->filename().c_str(), whiteout_prefix_,
true)) {
298 return entry->filename().substr(whiteout_prefix_.length());
300 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,...)