/************************************************************************
* EOS - the CERN Disk Storage System *
* Copyright (C) 2018 CERN/Switzerland *
* *
* This program is free software: you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation, either version 3 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program. If not, see .*
************************************************************************/
//------------------------------------------------------------------------------
//! @author Georgios Bitzes
//! @brief Helper function to check if it's safe to rename a directory into
//! another
//------------------------------------------------------------------------------
#ifndef EOS_NS_RENAME_SAFETY_CHECK_HH
#define EOS_NS_RENAME_SAFETY_CHECK_HH
#include
#include "namespace/interface/IContainerMD.hh"
#include "namespace/interface/IView.hh"
#include "namespace/Namespace.hh"
#include "common/Logging.hh"
EOSNSNAMESPACE_BEGIN
//------------------------------------------------------------------------------
// Is it safe to make "source" directory a subdirectory of "target"?
// Assumes source and target are at-least read-locked when calling this function OR
// assumes that the eosViewRWMutex is at-least read-locked when calling this function.
//------------------------------------------------------------------------------
bool isSafeToRename(IView *view, IContainerMD *source, IContainerMD *target) {
if(source == target) return false;
IContainerMDSvc *svc = view->getContainerMDSvc();
IContainerMDPtr current = svc->getContainerMD(target->getParentId());
size_t iterations = 0;
while(true) {
iterations++;
if(iterations > 1024) {
std::string msg = SSTR("potential loop when scanning parents of container "
<< target->getId() << " - serious namespace corruption");
eos_static_crit("%s", msg.c_str());
throw_mdexception(EFAULT, msg);
}
if(current.get() == source) {
return false; // Nope, sound alarm, this rename is not safe
}
if(current->getId() == source->getId()) {
// Should not happen.
eos_static_crit("%s", SSTR("Two containers with the same ID ended up with different objects in memory - " <<
current->getId() << " == " << source->getId() << " - " << current << " vs " << source).c_str());
return false;
}
if(current->getId() == 1) {
// We've reached root, this rename looks safe.
return true;
}
// Move up one step.
current = svc->getContainerMD(current->getParentId());
}
}
EOSNSNAMESPACE_END
#endif