XRootD
XrdOssRename.cc
Go to the documentation of this file.
1 /******************************************************************************/
2 /* */
3 /* X r d O s s R e n a m e . c c */
4 /* */
5 /* (c) 2003 by the Board of Trustees of the Leland Stanford, Jr., University */
6 /* All Rights Reserved */
7 /* Produced by Andrew Hanushevsky for Stanford University under contract */
8 /* DE-AC02-76-SFO0515 with the Department of Energy */
9 /* */
10 /* This file is part of the XRootD software suite. */
11 /* */
12 /* XRootD is free software: you can redistribute it and/or modify it under */
13 /* the terms of the GNU Lesser General Public License as published by the */
14 /* Free Software Foundation, either version 3 of the License, or (at your */
15 /* option) any later version. */
16 /* */
17 /* XRootD is distributed in the hope that it will be useful, but WITHOUT */
18 /* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */
19 /* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public */
20 /* License for more details. */
21 /* */
22 /* You should have received a copy of the GNU Lesser General Public License */
23 /* along with XRootD in a file called COPYING.LESSER (LGPL license) and file */
24 /* COPYING (GPL license). If not, see <http://www.gnu.org/licenses/>. */
25 /* */
26 /* The copyright holder's institutional names and contributor's names may not */
27 /* be used to endorse or promote products derived from this software without */
28 /* specific prior written permission of the institution or contributor. */
29 /******************************************************************************/
30 
31 #include <unistd.h>
32 #include <cerrno>
33 #include <strings.h>
34 #include <limits.h>
35 #include <fcntl.h>
36 #include <cstdio>
37 #include <sys/param.h>
38 #include <sys/types.h>
39 #include <sys/stat.h>
40 
41 #include "XrdSys/XrdSysHeaders.hh"
42 #include "XrdSys/XrdSysFAttr.hh"
43 #include "XrdOss/XrdOssApi.hh"
44 #include "XrdOss/XrdOssCache.hh"
45 #include "XrdOss/XrdOssError.hh"
46 #include "XrdOss/XrdOssPath.hh"
47 #include "XrdOss/XrdOssTrace.hh"
48 #include "XrdOuc/XrdOucExport.hh"
49 #include "XrdOuc/XrdOucUtils.hh"
50 #include "XrdFrc/XrdFrcXAttr.hh"
51 
52 /******************************************************************************/
53 /* G l o b a l E r r o r R o u t i n g O b j e c t */
54 /******************************************************************************/
55 
56 extern XrdSysError OssEroute;
57 
58 extern XrdSysTrace OssTrace;
59 
60 /******************************************************************************/
61 /* R e n a m e */
62 /******************************************************************************/
63 
64 /*
65  Function: Renames a file with name 'old_name' to 'new_name'.
66 
67  Input: old_name - Is the fully qualified name of the file to be renamed.
68  new_name - Is the fully qualified name that the file is to have.
69  old_env - Environmental information for old_name.
70  new_env - Environmental information for new_name.
71 
72  Output: Returns XrdOssOK upon success and -errno upon failure.
73 */
74 int XrdOssSys::Rename(const char *oldname, const char *newname,
75  XrdOucEnv *old_env, XrdOucEnv *new_env)
76 {
77  EPNAME("Rename")
78  static const mode_t pMode = S_IRWXU | S_IRWXG;
79  unsigned long long remotefs_Old, remotefs_New, remotefs;
80  unsigned long long old_popts, new_popts;
81  int retc2, retc = XrdOssOK;
82  struct stat statbuff;
83  char *slashPlus, sPChar;
84  char local_path_Old[MAXPATHLEN+8];
85  char local_path_New[MAXPATHLEN+8];
86  char remote_path_Old[MAXPATHLEN+1];
87  char remote_path_New[MAXPATHLEN+1];
88 
89 // Determine whether we can actually rename a file on this server.
90 //
91  remotefs_Old = Check_RO(Rename, old_popts, oldname, "rename");
92  remotefs_New = Check_RO(Rename, new_popts, newname, "rename to");
93 
94 // Make sure we are renaming within compatible file systems
95 //
96  if (remotefs_Old ^ remotefs_New
97  || ((old_popts & XRDEXP_MIG) ^ (new_popts & XRDEXP_MIG)))
98  {char buff[MAXPATHLEN+128];
99  snprintf(buff, sizeof(buff), "rename %s to ", oldname);
100  return OssEroute.Emsg("Rename",-XRDOSS_E8011,buff,(char *)newname);
101  }
102  remotefs = remotefs_Old | remotefs_New;
103 
104 // Construct the filename that we will be dealing with.
105 //
106  if ( (retc = GenLocalPath( oldname, local_path_Old))
107  || (retc = GenLocalPath( newname, local_path_New)) ) return retc;
108  if (remotefs
109  && (((retc = GenRemotePath(oldname, remote_path_Old))
110  || (retc = GenRemotePath(newname, remote_path_New)))) ) return retc;
111 
112 // If on a remote FS or symlink, make sure that the target path does not exist
113 //
114  if (!(retc2 = lstat(local_path_New, &statbuff)))
115  { if (remotefs || (statbuff.st_mode & S_IFMT) == S_IFLNK) return -EEXIST;
116  }
117 
118 // We need to create the directory path if it does not exist.
119 //
120  if (!(slashPlus = rindex(local_path_New, '/'))) return -EINVAL;
121  slashPlus++; sPChar = *slashPlus; *slashPlus = '\0';
122  retc2 = XrdOucUtils::makePath(local_path_New, pMode);
123  *slashPlus = sPChar;
124  if (retc2) return retc2;
125 
126 // Check if this path is really a symbolic link elsewhere
127 //
128  if (lstat(local_path_Old, &statbuff)) retc = -errno;
129  else if ((statbuff.st_mode & S_IFMT) == S_IFLNK)
130  retc = RenameLink(local_path_Old, local_path_New);
131  else if (rename(local_path_Old, local_path_New)) retc = -errno;
132  DEBUG("lcl rc=" <<retc <<" op=" <<local_path_Old <<" np=" <<local_path_New);
133 
134 // Now rename the data file in the remote system if the local rename "worked".
135 // Do not do this if we really should not use the MSS.
136 //
137  if (remotefs)
138  {if (remotefs && (!retc || retc == -ENOENT) && RSSCmd)
139  {if ( (retc2 = MSS_Rename(remote_path_Old, remote_path_New))
140  != -ENOENT) retc = retc2;
141  DEBUG("rmt rc=" <<retc2 <<" op=" <<remote_path_Old <<" np=" <<remote_path_New);
142  }
143  }
144 
145 // All done.
146 //
147  return retc;
148 }
149 
150 /******************************************************************************/
151 /* p r i v a t e m e t h o d s */
152 /******************************************************************************/
153 /******************************************************************************/
154 /* R e n a m e L i n k */
155 /******************************************************************************/
156 
157 int XrdOssSys::RenameLink(char *old_path, char *new_path)
158 {
159  struct stat statbuff;
160  char oldlnk[MAXPATHLEN+32], newlnk[MAXPATHLEN+32];
161  int lnklen, n, rc = 0;
162 
163 // Read the contents of the link
164 //
165  if ((lnklen = readlink(old_path,oldlnk,sizeof(oldlnk)-1)) < 0) return -errno;
166  oldlnk[lnklen] = '\0';
167 
168 // Check if this is new or old style cache. Check if this is an offline rename
169 // and if so, add the space to the usage to account for stage-ins
170 //
171  if (oldlnk[lnklen-1] == XrdOssPath::xChar)
172  {rc = RenameLink3(oldlnk, old_path, new_path);
173  if (rc) return rc;
174  if (Solitary && UDir)
175  {n = strlen(old_path);
176  if (n < 6 || strcmp(old_path+n-5, ".anew")
177  || stat(new_path, &statbuff) || !statbuff.st_size) return 0;
178  XrdOssPath::Trim2Base(oldlnk+lnklen-1);
179  XrdOssCache::Adjust(oldlnk, statbuff.st_size);
180  }
181  return 0;
182  }
183 
184 // Convert old name to the new name
185 //
186  if ((rc = XrdOssPath::Convert(newlnk, sizeof(newlnk), oldlnk, new_path)))
187  {OssEroute.Emsg("RenameLink", rc, "convert", oldlnk);
188  return rc;
189  }
190 
191 // Make sure that the target name does not exist
192 //
193  if (!lstat(newlnk, &statbuff))
194  {OssEroute.Emsg("RenameLink",-EEXIST,"check new target", newlnk);
195  return -EEXIST;
196  }
197 
198 // Insert a new link in the target cache
199 //
200  if (symlink(newlnk, new_path))
201  {rc = errno;
202  OssEroute.Emsg("RenameLink", rc, "symlink to", newlnk);
203  return -rc;
204  }
205 
206 // Rename the actual target file
207 //
208  if (rename(oldlnk, newlnk))
209  {rc = errno;
210  OssEroute.Emsg("RenameLink", rc, "rename", oldlnk);
211  unlink(new_path);
212  return -rc;
213  }
214 
215 // Now, unlink the source path
216 //
217  if (unlink(old_path))
218  OssEroute.Emsg("RenameLink", rc, "unlink", old_path);
219 
220 // All done
221 //
222  return 0;
223 }
224 
225 /******************************************************************************/
226 /* R e n a m e L i n k 3 */
227 /******************************************************************************/
228 
229 int XrdOssSys::RenameLink3(char *cPath, char *old_path, char *new_path)
230 {
231  int rc;
232 
233 // First set the new extended attribute on this file
234 //
235  if ((rc = XrdSysFAttr::Xat->Set(XrdFrcXAttrPfn::Name(), new_path,
236  strlen(new_path)+1, cPath))) return rc;
237 
238 // Now merely rename the old to the new
239 //
240  if (!rename(old_path, new_path)) return 0;
241 
242 // Rename failed, restore old attribute
243 //
244  rc = -errno;
245  XrdSysFAttr::Xat->Set(XrdFrcXAttrPfn::Name(),old_path,strlen(old_path)+1,cPath);
246  OssEroute.Emsg("RenameLink", rc, "rename", old_path);
247  return rc;
248 }
#define DEBUG(x)
Definition: XrdBwmTrace.hh:54
#define EPNAME(x)
Definition: XrdBwmTrace.hh:56
#define Check_RO(act, flags, path, opname)
Definition: XrdOssApi.hh:387
#define XRDOSS_E8011
Definition: XrdOssError.hh:45
XrdSysTrace OssTrace
XrdSysError OssEroute
#define XrdOssOK
Definition: XrdOss.hh:50
#define XRDEXP_MIG
Definition: XrdOucExport.hh:54
int stat(const char *path, struct stat *buf)
int lstat(const char *path, struct stat *buf)
int unlink(const char *path)
int rename(const char *oldpath, const char *newpath)
static const char * Name()
Definition: XrdFrcXAttr.hh:184
static void Adjust(dev_t devid, off_t size)
Definition: XrdOssCache.cc:397
static int Convert(char *dst, int dln, const char *oldP, const char *newP)
Definition: XrdOssPath.cc:75
static void Trim2Base(char *eP)
Definition: XrdOssPath.cc:304
static const char xChar
Definition: XrdOssPath.hh:47
int GenRemotePath(const char *, char *)
Definition: XrdOssApi.cc:249
int MSS_Rename(const char *, const char *)
Definition: XrdOssMSS.cc:360
int RenameLink3(char *cPath, char *old_path, char *new_path)
char * UDir
Definition: XrdOssApi.hh:309
int Rename(const char *, const char *, XrdOucEnv *eP1=0, XrdOucEnv *eP2=0)
Definition: XrdOssRename.cc:74
int GenLocalPath(const char *, char *)
Definition: XrdOssApi.cc:232
int RenameLink(char *old_path, char *new_path)
int Solitary
Definition: XrdOssApi.hh:246
char * RSSCmd
Definition: XrdOssApi.hh:238
static int makePath(char *path, mode_t mode, bool reset=false)
Definition: XrdOucUtils.cc:917
int Emsg(const char *esfx, int ecode, const char *text1, const char *text2=0)
Definition: XrdSysError.cc:95
static XrdSysXAttr * Xat
Definition: XrdSysFAttr.hh:51
virtual int Set(const char *Aname, const void *Aval, int Avsz, const char *Path, int fd=-1, int isNew=0)=0