XrdOssRename.cc

Go to the documentation of this file.
00001 /******************************************************************************/
00002 /*                                                                            */
00003 /*                       X r d O s s R e n a m e . c c                        */
00004 /*                                                                            */
00005 /* (c) 2003 by the Board of Trustees of the Leland Stanford, Jr., University  */
00006 /*                            All Rights Reserved                             */
00007 /*   Produced by Andrew Hanushevsky for Stanford University under contract    */
00008 /*              DE-AC03-76-SFO0515 with the Department of Energy              */
00009 /******************************************************************************/
00010 
00011 //         $Id: XrdOssRename.cc 34000 2010-06-21 06:49:56Z ganis $
00012 
00013 const char *XrdOssRenameCVSID = "$Id: XrdOssRename.cc 34000 2010-06-21 06:49:56Z ganis $";
00014 
00015 #include <unistd.h>
00016 #include <errno.h>
00017 #include <strings.h>
00018 #include <limits.h>
00019 #include <fcntl.h>
00020 #include <stdio.h>
00021 #include <sys/param.h>
00022 #include <sys/types.h>
00023 #include <sys/stat.h>
00024 
00025 #include "XrdSys/XrdSysHeaders.hh"
00026 #include "XrdOss/XrdOssApi.hh"
00027 #include "XrdOss/XrdOssCache.hh"
00028 #include "XrdOss/XrdOssError.hh"
00029 #include "XrdOss/XrdOssLock.hh"
00030 #include "XrdOss/XrdOssPath.hh"
00031 #include "XrdOss/XrdOssTrace.hh"
00032 #include "XrdOuc/XrdOucExport.hh"
00033 #include "XrdOuc/XrdOucUtils.hh"
00034 
00035 /******************************************************************************/
00036 /*           G l o b a l   E r r o r   R o u t i n g   O b j e c t            */
00037 /******************************************************************************/
00038 
00039 extern XrdSysError OssEroute;
00040 
00041 extern XrdOucTrace OssTrace;
00042   
00043 /******************************************************************************/
00044 /*                                R e n a m e                                 */
00045 /******************************************************************************/
00046 
00047 /*
00048   Function: Renames a file with name 'old_name' to 'new_name'.
00049 
00050   Input:    old_name  - Is the fully qualified name of the file to be renamed.
00051             new_name  - Is the fully qualified name that the file is to have.
00052 
00053   Output:   Returns XrdOssOK upon success and -errno upon failure.
00054 */
00055 int XrdOssSys::Rename(const char *oldname, const char *newname)
00056 {
00057     EPNAME("Rename")
00058     static const mode_t pMode = S_IRWXU | S_IRWXG;
00059     unsigned long long remotefs_Old, remotefs_New, remotefs, haslf;
00060     unsigned long long old_popts, new_popts;
00061     int i, retc2, retc = XrdOssOK;
00062     XrdOssLock old_file, new_file;
00063     struct stat statbuff;
00064     char  *slashPlus, sPChar;
00065     char  local_path_Old[MAXPATHLEN+8], *lpo;
00066     char  local_path_New[MAXPATHLEN+8], *lpn;
00067     char remote_path_Old[MAXPATHLEN+1];
00068     char remote_path_New[MAXPATHLEN+1];
00069 
00070 // Determine whether we can actually rename a file on this server.
00071 //
00072    remotefs_Old = Check_RO(Rename, old_popts, oldname, "renaming ");
00073    remotefs_New = Check_RO(Rename, new_popts, newname, "renaming to ");
00074 
00075 // Make sure we are renaming within compatible file systems
00076 //
00077    if (remotefs_Old ^ remotefs_New
00078    || ((old_popts & XRDEXP_MIG) ^ (new_popts & XRDEXP_MIG)))
00079       {char buff[MAXPATHLEN+128];
00080        snprintf(buff, sizeof(buff), "rename %s to ", oldname);
00081        return OssEroute.Emsg("Rename",-XRDOSS_E8011,buff,(char *)newname);
00082       }
00083    remotefs = remotefs_Old | remotefs_New;
00084    haslf    = (XRDEXP_MAKELF & (old_popts | new_popts));
00085 
00086 // Construct the filename that we will be dealing with.
00087 //
00088    if ( (retc = GenLocalPath( oldname, local_path_Old))
00089      || (retc = GenLocalPath( newname, local_path_New)) ) return retc;
00090    if (remotefs
00091      && (((retc = GenRemotePath(oldname, remote_path_Old))
00092      ||   (retc = GenRemotePath(newname, remote_path_New)))) ) return retc;
00093 
00094 // Lock the target directory if this is a remote backed filesystem
00095 //
00096    if (remotefs &&
00097        (retc2 = new_file.Serialize(local_path_New, XrdOssDIR|XrdOssEXC)) < 0)
00098       return retc2;
00099 
00100 // Make sure that the target file does not exist
00101 //
00102    retc2 = lstat(local_path_New, &statbuff);
00103    if (remotefs) new_file.UnSerialize(0);
00104    if (!retc2) return -EEXIST;
00105 
00106 // We need to create the directory path if it does not exist.
00107 //
00108    if (!(slashPlus = rindex(local_path_New, '/'))) return -EINVAL;
00109    slashPlus++; sPChar = *slashPlus; *slashPlus = '\0';
00110    retc2 = XrdOucUtils::makePath(local_path_New, pMode);
00111    *slashPlus = sPChar;
00112    if (retc2) return retc2;
00113 
00114 // Serialize access to the source directory.
00115 //
00116      if (remotefs &&
00117          (retc = old_file.Serialize(local_path_Old, XrdOssDIR|XrdOssEXC)) < 0)
00118        return retc;
00119 
00120 // Check if this path is really a symbolic link elsewhere
00121 //
00122     if (lstat(local_path_Old, &statbuff)) retc = -errno;
00123        else if ((statbuff.st_mode & S_IFMT) == S_IFLNK)
00124                retc = RenameLink(local_path_Old, local_path_New);
00125                else if (rename(local_path_Old, local_path_New)) retc = -errno;
00126     DEBUG("lcl rc=" <<retc <<" op=" <<local_path_Old <<" np=" <<local_path_New);
00127 
00128 // For migratable space, rename all suffix variations of the base file
00129 //
00130    if (haslf)
00131       {if ((!retc || retc == -ENOENT))
00132           {i = strlen(local_path_Old); lpo = &local_path_Old[i];
00133            i = strlen(local_path_New); lpn = &local_path_New[i];
00134            for (i = 0;  i < XrdOssPath::sfxMigL; i++)
00135                {strcpy(lpo,XrdOssPath::Sfx[i]); strcpy(lpn,XrdOssPath::Sfx[i]);
00136                 if (rename(local_path_Old,local_path_New) && ENOENT != errno)
00137                    DEBUG("sfx retc=" <<errno <<" op=" <<local_path_Old);
00138                }
00139           }
00140       }
00141 
00142 // Now rename the data file in the remote system if the local rename "worked".
00143 // Do not do this if we really should not use the MSS (but unserialize!).
00144 //
00145    if (remotefs)
00146       {if (remotefs && (!retc || retc == -ENOENT) && RSSCmd)
00147           {if ( (retc2 = MSS_Rename(remote_path_Old, remote_path_New))
00148               != -ENOENT) retc = retc2;
00149            DEBUG("rmt rc=" <<retc2 <<" op=" <<remote_path_Old <<" np=" <<remote_path_New);
00150           }
00151 
00152       // All done.
00153       //
00154          old_file.UnSerialize(0);
00155       }
00156 
00157 // All done.
00158 //
00159    return retc;
00160 }
00161  
00162 /******************************************************************************/
00163 /*                       p r i v a t e   m e t h o d s                        */
00164 /******************************************************************************/
00165 /******************************************************************************/
00166 /*                            R e n a m e L i n k                             */
00167 /******************************************************************************/
00168 
00169 int XrdOssSys::RenameLink(char *old_path, char *new_path)
00170 {
00171    struct stat statbuff;
00172    char oldlnk[MAXPATHLEN+32], newlnk[MAXPATHLEN+32];
00173    int lnklen, n, rc = 0;
00174 
00175 // Read the contents of the link
00176 //
00177    if ((lnklen = readlink(old_path,oldlnk,sizeof(oldlnk)-1)) < 0) return -errno;
00178    oldlnk[lnklen] = '\0';
00179 
00180 // Check if this is new or old style cache. Check if this is an offline rename
00181 // and if so, add the space to the usage to account for stage-ins
00182 //
00183    if (oldlnk[lnklen-1] == XrdOssPath::xChar)
00184       {if ((rc=RenameLink2(lnklen,oldlnk,old_path,newlnk,new_path))) return rc;
00185        if (Solitary && UDir)
00186           {n = strlen(old_path);
00187            if (n < 6 || strcmp(old_path+n-5, ".anew")
00188            ||  stat(new_path, &statbuff) || !statbuff.st_size) return 0;
00189            XrdOssPath::Trim2Base(oldlnk+lnklen-1);
00190            XrdOssCache::Adjust(oldlnk, statbuff.st_size);
00191           }
00192        return 0;
00193       }
00194 
00195 // Convert old name to the new name
00196 //
00197    if ((rc = XrdOssPath::Convert(newlnk, sizeof(newlnk), oldlnk, new_path)))
00198       {OssEroute.Emsg("RenameLink", rc, "convert", oldlnk);
00199        return rc;
00200       }
00201 
00202 // Make sure that the target name does not exist
00203 //
00204    if (!lstat(newlnk, &statbuff))
00205       {OssEroute.Emsg("RenameLink",-EEXIST,"check new target", newlnk);
00206        return -EEXIST;
00207       }
00208 
00209 // Insert a new link in the target cache
00210 //
00211    if (symlink(newlnk, new_path))
00212       {rc = errno;
00213        OssEroute.Emsg("RenameLink", rc, "symlink to", newlnk);
00214        return -rc;
00215       }
00216 
00217 // Rename the actual target file
00218 //
00219    if (rename(oldlnk, newlnk))
00220       {rc = errno;
00221        OssEroute.Emsg("RenameLink", rc, "rename", oldlnk);
00222        unlink(new_path);
00223        return -rc;
00224       }
00225 
00226 // Now, unlink the source path
00227 //
00228    if (unlink(old_path))
00229       OssEroute.Emsg("RenameLink", rc, "unlink", old_path);
00230 
00231 // All done
00232 //
00233    return 0;
00234 }
00235 
00236 /******************************************************************************/
00237 /*                           R e n a m e L i n k 2                            */
00238 /******************************************************************************/
00239   
00240 int XrdOssSys::RenameLink2(int Llen, char *oLnk, char *old_path,
00241                                      char *nLnk, char *new_path)
00242 {
00243    int rc;
00244 
00245 // Setup to create new pfn file for this file
00246 //
00247    strcpy(nLnk, oLnk);
00248    strcpy(nLnk+Llen, ".pfn");
00249    unlink(nLnk);
00250 
00251 // Create the new pfn symlink
00252 //
00253    if (symlink(new_path, nLnk))
00254       {rc = errno;
00255        OssEroute.Emsg("RenameLink", rc, "create symlink", nLnk);
00256        return -rc;
00257       }
00258 
00259 // Create the new lfn symlink
00260 //
00261    if (symlink(oLnk, new_path))
00262       {rc = errno;
00263        OssEroute.Emsg("RenameLink", rc, "symlink to", oLnk);
00264        unlink(nLnk);
00265        return -rc;
00266       }
00267 
00268 // Now, unlink the old lfn path
00269 //
00270    if (unlink(old_path))
00271       OssEroute.Emsg("RenameLink", errno, "unlink", old_path);
00272 
00273 // All done (well, as well as it needs to be at this point)
00274 //
00275    return 0;
00276 }

Generated on Tue Jul 5 14:46:48 2011 for ROOT_528-00b_version by  doxygen 1.5.1