// ----------------------------------------------------------------------
// File: Chksum.cc
// Author: Andreas-Joachim Peters - CERN
// ----------------------------------------------------------------------
/************************************************************************
* EOS - the CERN Disk Storage System *
* Copyright (C) 2011 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 .*
************************************************************************/
// -----------------------------------------------------------------------
// This file is included source code in XrdMgmOfs.cc to make the code more
// transparent without slowing down the compilation time.
// -----------------------------------------------------------------------
/*----------------------------------------------------------------------------*/
int
XrdMgmOfs::chksum(XrdSfsFileSystem::csFunc Func,
const char* csName,
const char* inpath,
XrdOucErrInfo& error,
const XrdSecEntity* client,
const char* ininfo)
/*----------------------------------------------------------------------------*/
/*
* @brief retrieve a checksum
*
* @param func function to be performed 'csCalc','csGet' or 'csSize'
* @param csName name of the checksum
* @param error error object
* @param client XRootD authentication object
* @param ininfo CGI
* @return SFS_OK on success otherwise SFS_ERROR
*
* We support only checksum type 'eos' which has the maximum length of 20 bytes
* and returns a checksum based on the defined directory policy (can be adler,
* md5,sha1 ...). The EOS directory based checksum configuration does not map
* 1:1 to the XRootD model where a storage system supports only one flavour.
*/
/*----------------------------------------------------------------------------*/
{
static const char* epname = "chksum";
const char* tident = error.getErrUser();
// use a thread private vid
eos::common::VirtualIdentity vid = eos::common::VirtualIdentity::Nobody();
char buff[MAXPATHLEN + 8];
int rc;
XrdOucString CheckSumName = csName;
// ---------------------------------------------------------------------------
// retrieve meta data for
// ---------------------------------------------------------------------------
// A csSize request is issued usually once to verify everything is working. We
// take this opportunity to also verify the checksum name.
// ---------------------------------------------------------------------------
rc = 0;
if (Func == XrdSfsFileSystem::csSize) {
if (1) {
// just return the length
error.setErrCode(20);
return SFS_OK;
} else {
eos_static_info("not supported");
strcpy(buff, csName);
strcat(buff, " checksum not supported.");
error.setErrInfo(ENOTSUP, buff);
return SFS_ERROR;
}
}
NAMESPACEMAP;
EXEC_TIMING_BEGIN("IdMap");
eos::common::Mapping::IdMap(client, ininfo, tident, vid, gOFS->mTokenAuthz,
AOP_Stat, inpath);
EXEC_TIMING_END("IdMap");
gOFS->MgmStats.Add("IdMap", vid.uid, vid.gid, 1);
gOFS->MgmStats.Add("Checksum", vid.uid, vid.gid, 1);
XrdOucEnv Open_Env(ininfo);
AUTHORIZE(client, &Open_Env, AOP_Stat, "stat", inpath, error);
BOUNCE_ILLEGAL_NAMES;
BOUNCE_NOT_ALLOWED;
ACCESSMODE_W;
MAYSTALL;
MAYREDIRECT;
eos_info("path=%s", inpath);
// ---------------------------------------------------------------------------
errno = 0;
std::shared_ptr fmd;
eos::common::Path cPath(path);
// ---------------------------------------------------------------------------
// Everything else requires a path
// ---------------------------------------------------------------------------
if (!path) {
strcpy(buff, csName);
strcat(buff, " checksum path not specified.");
error.setErrInfo(EINVAL, buff);
return SFS_ERROR;
}
// ---------------------------------------------------------------------------
eos::Prefetcher::prefetchFileMDAndWait(gOFS->eosView, cPath.GetPath());
eos::common::RWMutexReadLock lock(gOFS->eosViewRWMutex);
bool enonet = false;
try {
fmd = gOFS->eosView->getFile(cPath.GetPath());
enonet = !fmd->getNumLocation();
} catch (eos::MDException& e) {
errno = e.getErrno();
}
if (!fmd) {
// file does not exist
*buff = 0;
rc = ENOENT;
MAYREDIRECT_ENOENT;
MAYSTALL_ENOENT;
error.setErrInfo(rc, "no such file or directory");
return SFS_ERROR;
}
if (enonet) {
// File has no committed replicas, we might bounce to an alive remote master
if (!gOFS->mMaster->IsMaster() && gOFS->mMaster->IsRemoteMasterOk()) {
lock.Release();
// redirect ENONET to an alive remote master
int port {0};
std::string hostname;
std::string master_id = gOFS->mMaster->GetMasterId();
if (!eos::common::ParseHostNamePort(master_id, hostname, port)) {
eos_err("msg=\"failed parsing remote master info\", id=%s",
master_id.c_str());
return Emsg(epname, error, ENOENT, "get checksum - failed parsing "
"remote master info", path);
}
error.setErrInfo(port, hostname.c_str());
gOFS->MgmStats.Add("RedirectENONET", vid.uid, vid.gid, 1);
return SFS_REDIRECT;
}
}
// ---------------------------------------------------------------------------
// Now determine what to do
// ---------------------------------------------------------------------------
if ((Func == XrdSfsFileSystem::csCalc) ||
(Func == XrdSfsFileSystem::csGet)) {
} else {
error.setErrInfo(EINVAL, "Invalid checksum function.");
return SFS_ERROR;
}
// Set the checksum type
std::string cksum_type = eos::common::LayoutId::GetChecksumStringReal(
fmd->getLayoutId());
sprintf(buff, "!%s ", cksum_type.c_str());
// copy the checksum buffer
const char* hv = "0123456789abcdef";
size_t j = strlen(buff);
for (size_t i = 0;
i < eos::common::LayoutId::GetChecksumLen(fmd->getLayoutId()); i++) {
buff[j++] = hv[(fmd->getChecksum().getDataPadded(i) >> 4) & 0x0f];
buff[j++] = hv[ fmd->getChecksum().getDataPadded(i) & 0x0f];
}
if (j == 0) {
sprintf(buff, "NONE");
} else {
buff[j] = '\0';
}
eos_info("checksum=\"%s\"", buff);
error.setErrInfo(0, buff);
return SFS_OK;
}