5 #define __STDC_FORMAT_MACROS
10 #include <sys/capability.h>
22 const string &rdonly_path,
23 const string &union_path,
24 const string &scratch_path)
25 :
SyncUnion(mediator, rdonly_path, union_path, scratch_path),
26 hardlink_lower_inode_(0) {}
35 cap_value_t cap = CAP_SYS_ADMIN;
43 #ifdef CAP_IS_SUPPORTED
44 if (!CAP_IS_SUPPORTED(cap)) {
52 "Failed to obtain capability state "
53 "of current process (errno: %d)",
58 cap_flag_value_t cap_state;
59 if (cap_get_flag(caps, cap, CAP_EFFECTIVE, &cap_state) != 0) {
61 "Failed to check effective set for "
62 "CAP_SYS_ADMIN (errno: %d)",
67 if (cap_state == CAP_SET) {
72 if (cap_get_flag(caps, cap, CAP_PERMITTED, &cap_state) != 0) {
74 "Failed to check permitted set for "
75 "CAP_SYS_ADMIN (errno: %d)",
80 if (cap_state != CAP_SET) {
82 "CAP_SYS_ADMIN cannot be obtained. It's "
83 "not in the process's permitted-set.");
87 if (cap_set_flag(caps, CAP_EFFECTIVE, 1, &cap, CAP_SET) != 0) {
89 "Cannot set CAP_SYS_ADMIN as effective "
90 "for the current process (errno: %d)",
95 if (cap_set_proc(caps) != 0) {
97 "Cannot reset capabilities for current "
98 "process (errno: %d)",
108 cap_t caps = cap_get_proc();
116 if (entry->IsGraftMarker() || entry->IsWhiteout() || entry->IsDirectory()) {
126 if (!entry->IsNew() && !entry->WasDirectory() &&
127 entry->GetRdOnlyLinkcount() > 1) {
129 "OverlayFS has copied-up a file (%s) "
130 "with existing hardlinks in lowerdir "
131 "(linkcount %d). OverlayFS cannot handle "
132 "hardlinks and would produce "
133 "inconsistencies. \n\n"
134 "Consider running this command: \n"
135 " cvmfs_server eliminate-hardlinks\n\n"
137 entry->GetUnionPath().c_str(), entry->GetRdOnlyLinkcount());
142 assert(entry->IsRegularFile() || entry->IsSymlink() ||
143 entry->IsSpecialFile());
144 if (entry->GetUnionLinkcount() > 1) {
146 "Warning: Found file with linkcount > 1 "
147 "(%s). We will break up these hardlinks.",
148 entry->GetUnionPath().c_str());
149 entry->MaskHardlink();
170 "OverlayFS starting traversal "
171 "recursion for scratch_path=[%s]",
185 string const &compare_value) {
191 compare_len = compare_value.length() + 1;
194 buf =
static_cast<char *
>(alloca(compare_len + 1));
196 ssize_t len = ::readlink(path.c_str(), buf, compare_len);
200 return (std::string(buf) == compare_value);
204 "SyncUnionOverlayfs::ReadlinkEquals error reading link [%s]: %d\n",
205 path.c_str(), errno);
224 std::vector<std::string> attrs = xattrs->
ListKeys();
225 std::vector<std::string>::const_iterator i = attrs.begin();
226 std::vector<std::string>::const_iterator iend = attrs.end();
228 for (; i != iend; ++i) {
232 return xattrs.
IsValid() && xattrs->
Has(attr_name);
243 bool is_chardev_whiteout = entry->IsCharacterDevice() &&
244 entry->GetRdevMajor() == 0 &&
245 entry->GetRdevMinor() == 0;
246 if (is_chardev_whiteout)
return true;
248 std::string whiteout_prefix_ =
".wh.";
250 HasPrefix(entry->filename().c_str(), whiteout_prefix_,
true);
251 if (has_wh_prefix)
return true;
253 bool is_symlink_whiteout =
255 if (is_symlink_whiteout)
return true;
261 const bool is_whiteout =
ReadlinkEquals(path,
"(overlay-whiteout)");
276 const std::string path = directory->GetScratchPath();
281 bool is_opaque =
HasXattr(path.c_str(),
"trusted.overlay.opaque");
291 std::string whiteout_prefix_ =
".wh.";
293 if (
HasPrefix(entry->filename().c_str(), whiteout_prefix_,
true)) {
294 return entry->filename().substr(whiteout_prefix_.length());
296 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,...)