/******************************************************************************/ /* */ /* 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; }