/******************************************************************************/
/* */
/* X r d O s s R e n a m e . c c */
/* */
/* (c) 2003 by the Board of Trustees of the Leland Stanford, Jr., University */
/* All Rights Reserved */
/* Produced by Andrew Hanushevsky for Stanford University under contract */
/* DE-AC02-76-SFO0515 with the Department of Energy */
/* */
/* This file is part of the XRootD software suite. */
/* */
/* XRootD is free software: you can redistribute it and/or modify it under */
/* the terms of the GNU Lesser General Public License as published by the */
/* Free Software Foundation, either version 3 of the License, or (at your */
/* option) any later version. */
/* */
/* XRootD 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 Lesser General Public */
/* License for more details. */
/* */
/* You should have received a copy of the GNU Lesser General Public License */
/* along with XRootD in a file called COPYING.LESSER (LGPL license) and file */
/* COPYING (GPL license). If not, see . */
/* */
/* The copyright holder's institutional names and contributor's names may not */
/* be used to endorse or promote products derived from this software without */
/* specific prior written permission of the institution or contributor. */
/******************************************************************************/
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include "XrdSys/XrdSysHeaders.hh"
#include "XrdSys/XrdSysFAttr.hh"
#include "XrdOss/XrdOssApi.hh"
#include "XrdOss/XrdOssCache.hh"
#include "XrdOss/XrdOssError.hh"
#include "XrdOss/XrdOssPath.hh"
#include "XrdOss/XrdOssTrace.hh"
#include "XrdOuc/XrdOucExport.hh"
#include "XrdOuc/XrdOucUtils.hh"
#include "XrdFrc/XrdFrcXAttr.hh"
/******************************************************************************/
/* G l o b a l E r r o r R o u t i n g O b j e c t */
/******************************************************************************/
extern XrdSysError OssEroute;
extern XrdOucTrace OssTrace;
/******************************************************************************/
/* R e n a m e */
/******************************************************************************/
/*
Function: Renames a file with name 'old_name' to 'new_name'.
Input: old_name - Is the fully qualified name of the file to be renamed.
new_name - Is the fully qualified name that the file is to have.
old_env - Environmental information for old_name.
new_env - Environmental information for new_name.
Output: Returns XrdOssOK upon success and -errno upon failure.
*/
int XrdOssSys::Rename(const char *oldname, const char *newname,
XrdOucEnv *old_env, XrdOucEnv *new_env)
{
EPNAME("Rename")
static const mode_t pMode = S_IRWXU | S_IRWXG;
unsigned long long remotefs_Old, remotefs_New, remotefs, haslf;
unsigned long long old_popts, new_popts;
int i, retc2, retc = XrdOssOK;
struct stat statbuff;
char *slashPlus, sPChar;
char local_path_Old[MAXPATHLEN+8], *lpo;
char local_path_New[MAXPATHLEN+8], *lpn;
char remote_path_Old[MAXPATHLEN+1];
char remote_path_New[MAXPATHLEN+1];
// Determine whether we can actually rename a file on this server.
//
remotefs_Old = Check_RO(Rename, old_popts, oldname, "rename");
remotefs_New = Check_RO(Rename, new_popts, newname, "rename to");
// Make sure we are renaming within compatible file systems
//
if (remotefs_Old ^ remotefs_New
|| ((old_popts & XRDEXP_MIG) ^ (new_popts & XRDEXP_MIG)))
{char buff[MAXPATHLEN+128];
snprintf(buff, sizeof(buff), "rename %s to ", oldname);
return OssEroute.Emsg("Rename",-XRDOSS_E8011,buff,(char *)newname);
}
remotefs = remotefs_Old | remotefs_New;
haslf = (XRDEXP_MAKELF & (old_popts | new_popts));
// Construct the filename that we will be dealing with.
//
if ( (retc = GenLocalPath( oldname, local_path_Old))
|| (retc = GenLocalPath( newname, local_path_New)) ) return retc;
if (remotefs
&& (((retc = GenRemotePath(oldname, remote_path_Old))
|| (retc = GenRemotePath(newname, remote_path_New)))) ) return retc;
// If on a remote FS or symlink, make sure that the target path does not exist
//
if (!(retc2 = lstat(local_path_New, &statbuff)))
{ if (remotefs || (statbuff.st_mode & S_IFMT) == S_IFLNK) return -EEXIST;
}
// We need to create the directory path if it does not exist.
//
if (!(slashPlus = rindex(local_path_New, '/'))) return -EINVAL;
slashPlus++; sPChar = *slashPlus; *slashPlus = '\0';
retc2 = XrdOucUtils::makePath(local_path_New, pMode);
*slashPlus = sPChar;
if (retc2) return retc2;
// Check if this path is really a symbolic link elsewhere
//
if (lstat(local_path_Old, &statbuff)) retc = -errno;
else if ((statbuff.st_mode & S_IFMT) == S_IFLNK)
retc = RenameLink(local_path_Old, local_path_New);
else if (rename(local_path_Old, local_path_New)) retc = -errno;
DEBUG("lcl rc=" <Set(XrdFrcXAttrPfn::Name(), new_path,
strlen(new_path)+1, cPath))) return rc;
// Now merely rename the old to the new
//
if (!rename(old_path, new_path)) return 0;
// Rename failed, restore old attribute
//
rc = -errno;
XrdSysFAttr::Xat->Set(XrdFrcXAttrPfn::Name(),old_path,strlen(old_path)+1,cPath);
OssEroute.Emsg("RenameLink", rc, "rename", old_path);
return rc;
}