00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013 const char *XrdOssRelocCVSID = "$Id: XrdOssReloc.cc 28902 2009-06-11 12:36:21Z ganis $";
00014
00015
00016
00017
00018
00019 #include <unistd.h>
00020 #include <errno.h>
00021 #include <fcntl.h>
00022 #include <strings.h>
00023 #include <stdio.h>
00024 #include <sys/stat.h>
00025 #include <sys/types.h>
00026 #include <sys/param.h>
00027
00028 #include "XrdOss/XrdOssApi.hh"
00029 #include "XrdOss/XrdOssCache.hh"
00030 #include "XrdOss/XrdOssConfig.hh"
00031 #include "XrdOss/XrdOssCopy.hh"
00032 #include "XrdOss/XrdOssError.hh"
00033 #include "XrdOss/XrdOssPath.hh"
00034 #include "XrdOss/XrdOssSpace.hh"
00035 #include "XrdOss/XrdOssTrace.hh"
00036 #include "XrdOuc/XrdOucUtils.hh"
00037 #include "XrdSys/XrdSysError.hh"
00038 #include "XrdSys/XrdSysHeaders.hh"
00039 #include "XrdSys/XrdSysPlatform.hh"
00040
00041
00042
00043
00044
00045 extern XrdSysError OssEroute;
00046
00047 extern XrdOucTrace OssTrace;
00048
00049 extern XrdOssSys *XrdOssSS;
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065 int XrdOssSys::Reloc(const char *tident, const char *path,
00066 const char *cgName, const char *anchor)
00067 {
00068 EPNAME("Reloc")
00069 const int AMode = S_IRWXU|S_IRWXG|S_IROTH|S_IXOTH;
00070 class pendFiles
00071 {public:
00072 char *pbuff;
00073 char *tbuff;
00074 int datfd;
00075 pendFiles(char *pb, char *tb) : datfd(-1)
00076 {pbuff = pb; *pb = '\0';
00077 tbuff = tb; *tb = '\0';
00078 }
00079 ~pendFiles() {if (datfd >= 0) close(datfd);
00080 if (pbuff && *pbuff) unlink(pbuff);
00081 if (tbuff && *tbuff) unlink(tbuff);
00082 }
00083 };
00084 char cgNow[XrdOssSpace::minSNbsz], cgbuff[XrdOssSpace::minSNbsz];
00085 char lbuff[MAXPATHLEN+8];
00086 char pbuff[MAXPATHLEN+8];
00087 char tbuff[MAXPATHLEN+8];
00088 char local_path[MAXPATHLEN+8];
00089 pendFiles PF(pbuff, tbuff);
00090 XrdOssCache::allocInfo aInfo(path, pbuff, sizeof(pbuff));
00091 int rc, lblen, datfd;
00092 struct stat buf;
00093
00094
00095
00096 if ((rc = GenLocalPath(path, local_path))) return rc;
00097
00098
00099
00100 if (stat(local_path, &buf)) return -errno;
00101 if ((buf.st_mode & S_IFMT) == S_IFDIR) return -EISDIR;
00102 if ((buf.st_mode & S_IFMT) != S_IFREG) return -ENOTBLK;
00103
00104
00105
00106 if ((aInfo.cgPath = XrdOssCache::Parse(cgName, cgbuff, sizeof(cgbuff))))
00107 aInfo.cgPlen = strlen(aInfo.cgPath);
00108
00109
00110
00111 lblen = XrdOssPath::getCname(local_path, cgNow, lbuff, sizeof(lbuff)-7);
00112 lbuff[lblen] = '\0';
00113 if (!strcmp(cgbuff, cgNow)
00114 && (!aInfo.cgPath || !strncmp(aInfo.cgPath, lbuff, aInfo.cgPlen)))
00115 return -EEXIST;
00116
00117
00118
00119 aInfo.aMode = buf.st_mode & S_IAMB;
00120 aInfo.cgSize = buf.st_size;
00121 aInfo.cgName = cgbuff;
00122 if ((PF.datfd = datfd = XrdOssCache::Alloc(aInfo)) < 0) return datfd;
00123 if (!aInfo.cgPsfx) return -ENOTSUP;
00124
00125
00126
00127 if (XrdOssCopy::Copy(path, pbuff, datfd) < 0) return -EIO;
00128 close(datfd); PF.datfd = -1;
00129
00130
00131
00132 if (!anchor) {strcpy(tbuff, local_path); strcat(tbuff, ".anew");}
00133 else {struct stat sbuf;
00134 char *Slash;
00135 if (strlen(anchor)+strlen(path) >= sizeof(local_path))
00136 return -ENAMETOOLONG;
00137 strcpy(local_path, anchor); strcat(local_path, path);
00138 if (!(Slash = rindex(local_path, '/'))) return -ENOTDIR;
00139 *Slash = '\0'; rc = stat(local_path, &sbuf); *Slash = '/';
00140 if (rc && (rc = XrdOucUtils::makePath(local_path, AMode)))
00141 return rc;
00142 strcpy(tbuff, local_path);
00143 }
00144
00145
00146
00147 if ((symlink(pbuff, tbuff) && errno != EEXIST)
00148 || unlink(tbuff) || symlink(pbuff, tbuff)) return -errno;
00149
00150
00151
00152 if (!anchor && rename(tbuff, local_path) < 0) return -errno;
00153 PF.tbuff = 0; PF.pbuff = 0;
00154
00155
00156
00157 strcpy(aInfo.cgPsfx, ".pfn"); rc = 0;
00158 if ((symlink(local_path, pbuff) && errno != EEXIST)
00159 || unlink(pbuff) || symlink(local_path, pbuff)) rc = errno;
00160
00161
00162
00163
00164 if (rc) OssEroute.Emsg("Reloc", rc, "create symlink", pbuff);
00165 *(aInfo.cgPsfx) = '\0';
00166
00167
00168
00169 DEBUG(cgNow <<':' <<local_path <<" -> " <<aInfo.cgName <<':' <<pbuff);
00170 if (anchor) return XrdOssOK;
00171
00172
00173
00174
00175 if (*lbuff)
00176 {if (unlink(lbuff)) OssEroute.Emsg("Reloc",errno,"removing",lbuff);
00177 if (XrdOssPath::isXA(lbuff))
00178 {strcat(lbuff, ".pfn");
00179 if (unlink(lbuff)) OssEroute.Emsg("Reloc",errno,"removing",lbuff);
00180 }
00181 XrdOssCache::Adjust(XrdOssCache::Find(lbuff, lblen), -buf.st_size);
00182 } else XrdOssCache::Adjust(buf.st_dev, -buf.st_size);
00183
00184
00185
00186 XrdOssCache::Adjust(aInfo.cgFSp, buf.st_size);
00187 return XrdOssOK;
00188 }