XRootD
Loading...
Searching...
No Matches
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
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"
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
57
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*/
74int 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
157int 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
229int 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)
#define EPNAME(x)
XrdSysTrace OssTrace
XrdSysError OssEroute
#define Check_RO(act, flags, path, opname)
Definition XrdOssApi.hh:387
#define XRDOSS_E8011
#define XrdOssOK
Definition XrdOss.hh:50
#define XRDEXP_MIG
int lstat(const char *path, struct stat *buf)
#define unlink(a)
Definition XrdPosix.hh:108
#define stat(a, b)
Definition XrdPosix.hh:96
#define rename(a, b)
Definition XrdPosix.hh:87
static const char * Name()
static void Adjust(dev_t devid, off_t size)
static int Convert(char *dst, int dln, const char *oldP, const char *newP)
Definition XrdOssPath.cc:75
static void Trim2Base(char *eP)
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)
int GenLocalPath(const char *, char *)
Definition XrdOssApi.cc:232
int RenameLink(char *old_path, char *new_path)
char * RSSCmd
Definition XrdOssApi.hh:238
static int makePath(char *path, mode_t mode, bool reset=false)
static XrdSysXAttr * Xat