35 #include <sys/param.h>
36 #include <sys/types.h>
52 #define ENODATA ENOATTR
61 #define XATTR XrdSysXAttrNative
73 ~cUp() {
if (fd >= 0)
close(fd);}
93 static const unsigned int crcSZ =
sizeof(uint32_t);
94 static const unsigned int hdrSZ =
sizeof(cpHdr);
95 static const unsigned int segSZ =
sizeof(cpSeg);
96 static const char *attrName =
"xrdckp_srclfn";
106 uint32_t InitSeq(
char *buff,
int n)
108 uint32_t tod =
static_cast<uint32_t
>(time(0));
109 snprintf(buff, n,
"%08x", tod);
114 uint32_t ckpSeq = InitSeq(ckpHdr,
sizeof(ckpHdr));
122 DataVec(0), DataNum(0), DataLen(0), rBuff(0) {}
125 {
if (DataVec)
delete [] DataVec;
126 if (rBuff) free(rBuff);
137 : ckpFN(ckpfn ? strdup(ckpfn) : 0), ckpFD(-1),
138 ckpDLen(0), ckpSize(0) {}
149 if (ckpFD >= 0)
close(ckpFD);
150 if (ckpFN) free(ckpFN);
166 ckpSize += dlen + segSZ;
170 theSeg.dataOfs = offset;
171 theSeg.dataLen = dlen;
180 ioV[0].iov_base = &theSeg;
181 ioV[0].iov_len = segSZ;
182 ioV[1].iov_base = (
void *)data;
183 ioV[1].iov_len = dlen;
187 retval =
writev(ckpFD, ioV, 2);
188 if (retval != (
int)(dlen+segSZ))
return (retval < 0 ? -errno : -EIO);
201 static const int oFlag = O_CREAT | O_EXCL | O_WRONLY;
202 static const int oMode = S_IRUSR | S_IWUSR | S_IRGRP;
209 if (ckpFD >= 0 || ckpFN)
return -EEXIST;
213 ckpFN = genCkpPath();
217 if ((ckpFD = XrdSysFD_Open(ckpFN, oFlag, oMode)) < 0
218 ||
XATTR.Set(attrName, srcFN, strlen(srcFN)+1, ckpFN, ckpFD) < 0)
220 if (ckpFD >= 0) {
close(ckpFD); ckpFD = -1;}
228 theHdr.lfnLen = strlen(srcFN) + 1;
229 theHdr.hdrLen = hdrSZ + theHdr.lfnLen;
230 theHdr.fSize =
Stat.st_size;
231 theHdr.mTime =
Stat.st_mtime;
232 memcpy(theHdr.srcUrl,
" file://",
sizeof(theHdr.srcUrl));
233 memset(theHdr.rsvd, 0,
sizeof(theHdr.rsvd));
242 ioV[0].iov_base = &theHdr;
243 ioV[0].iov_len =
sizeof(theHdr);
244 ioV[1].iov_base = (
void *)srcFN;
245 ioV[1].iov_len = theHdr.lfnLen;
246 ckpSize =
sizeof(theHdr) + theHdr.lfnLen;
250 retval =
writev(ckpFD, ioV, 2);
251 if (retval != ckpSize) rc = (retval < 0 ? -errno : -EIO);
252 else if (
fsync(ckpFD)) rc = -errno;
270 if (ckpFN &&
unlink(ckpFN))
286 char buff[MAXPATHLEN+8];
292 snprintf(buff,
sizeof(buff),
"%serr", ckpFN);
293 return (
rename(ckpFN, buff) ? -errno : 0);
304 {
char *slash = rindex(ckpFN,
'/');
305 if (slash)
return slash+1;
316 char *XrdOfsCPFile::genCkpPath()
319 char ckpPath[MAXPATHLEN];
324 snprintf(ckpPath,
sizeof(ckpPath),
"%s%s-%u.ckp",
326 return strdup(ckpPath);
336 char srcfn[MAXPATHLEN+80];
340 if ((n =
XATTR.Get(attrName, srcfn,
sizeof(srcfn)-1, cFN, fd)) > 0)
342 if (rinfo.rBuff) free(rinfo.rBuff);
343 rinfo.rBuff = strdup(srcfn);
344 rinfo.
srcLFN = (
const char *)rinfo.rBuff;
357 if (dlen < 0 || nseg < 0 || ckpFD < 0)
return false;
366 fstore_t Store = {F_ALLOCATEALL, F_PEOFPOSMODE, ckpSize, dlen};
367 if (
fcntl(ckpFD, F_PREALLOCATE, &Store) == -1
368 &&
ftruncate(ckpFD, ckpSize + dlen) == -1)
return false;
370 if (posix_fallocate(ckpFD, ckpSize, dlen))
387 std::vector<XrdOucIOVec> vecIO;
390 char *ckpRec, *ckpEnd;
398 if ((cup.fd = XrdSysFD_Open(ckpFN, O_RDONLY)) < 0)
399 {
if (errno == ENOENT)
return -ENOENT;
400 eWhy =
"open failed";
401 return getSrcLfn(ckpFN, rinfo, cup.fd, errno);
407 {eWhy =
"stat failed";
408 return getSrcLfn(ckpFN, rinfo, cup.fd, errno);
413 if (
Stat.st_size == 0)
return getSrcLfn(ckpFN, rinfo, cup.fd,
ENODATA);
417 if (
Stat.st_size < hdrSZ+1)
418 {eWhy =
"truncated header";
419 return getSrcLfn(ckpFN, rinfo, cup.fd, EDOM);
424 if (!(ckpRec = (
char *)malloc(
Stat.st_size)))
425 return getSrcLfn(ckpFN, rinfo, cup.fd, ENOMEM);
426 rinfo.rBuff = ckpRec;
430 if ((retval =
read(cup.fd, ckpRec,
Stat.st_size)) !=
Stat.st_size)
431 {eWhy =
"read failed";
432 return getSrcLfn(ckpFN, rinfo, cup.fd, (retval < 0 ? errno : EIO));
439 cpHdr &theHdr = *((cpHdr *)ckpRec);
440 if (theHdr.hdrLen >
Stat.st_size
441 || (theHdr.hdrLen - theHdr.lfnLen) != (int)hdrSZ)
442 {eWhy =
"corrupted header";
443 return getSrcLfn(ckpFN, rinfo, cup.fd, EDOM);
449 {eWhy =
"header checksum mismatch";
450 return getSrcLfn(ckpFN, rinfo, cup.fd, EDOM);
455 rinfo.
srcLFN = ckpRec+hdrSZ;
456 rinfo.
fSize = theHdr.fSize;
457 rinfo.
mTime = theHdr.mTime;
461 ckpEnd = ckpRec +
Stat.st_size;
462 ckpRec = ckpRec + theHdr.hdrLen;
468 aOK =
false; eWhy = 0;
469 while(ckpRec+
sizeof(cpSeg) < ckpEnd)
470 {memcpy(&theSeg, ckpRec, segSZ);
471 if (!theSeg.dataLen && !theSeg.dataOfs && !theSeg.crc32C)
475 char *ckpData = ckpRec + segSZ;
476 if (theSeg.dataLen <= 0 || ckpData + theSeg.dataLen > ckpEnd)
break;
477 int cLen = theSeg.dataLen+
sizeof(cpSeg)-crcSZ;
479 {eWhy =
"data checksum mismatch";
482 ioItem.offset = theSeg.dataOfs;
483 ioItem.size = theSeg.dataLen;
484 ioItem.data = ckpRec + segSZ;
485 rinfo.
DataLen += theSeg.dataLen;
486 vecIO.push_back(ioItem);
487 ckpRec += (segSZ + theSeg.dataLen);
493 if (!aOK && ckpRec != ckpEnd)
494 {
if (!eWhy) eWhy =
"truncated file";
501 if (!vecIO.size())
return 0;
506 int j = vecIO.
size() - 1;
507 for (
int i = 0; i < (int)vecIO.size(); i++) ioV[j--] = vecIO[i];
522 if (
fsync(ckpFD))
return -errno;
532 struct {cpHdr hdr;
char srcfn[MAXPATHLEN+8];} ckpRec;
534 const char *
eMsg =
"Target unknown; corrupt checkpoint file";
539 if ((n =
XATTR.Get(attrName,ckpRec.srcfn,
sizeof(ckpRec.srcfn)-1,ckpfn)) > 0)
540 {ckpRec.srcfn[n] = 0;
541 return strdup(ckpRec.srcfn);
546 if ((cup.fd = XrdSysFD_Open(ckpfn, O_RDONLY)) < 0)
548 snprintf(buff,
sizeof(buff),
"Target unknown; %s",
XrdSysE2T(errno));
554 if ((n =
read(cup.fd, &ckpRec,
sizeof(ckpRec))) <= (
int)
sizeof(cpHdr))
559 if (ckpRec.hdr.lfnLen <= 1 || ckpRec.hdr.lfnLen > (
int)MAXPATHLEN)
564 ckpRec.srcfn[ckpRec.hdr.lfnLen-1] = 0;
565 return strdup(ckpRec.srcfn);
void trim(std::string &str)
XrdSysXAttr & XrdSysXAttrNative
int truncate(const char *path, off_t offset)
int stat(const char *path, struct stat *buf)
int ftruncate(int fildes, off_t offset)
int fstat(int fildes, struct stat *buf)
int fcntl(int fd, int cmd,...)
int unlink(const char *path)
int rename(const char *oldpath, const char *newpath)
ssize_t writev(int fildes, const struct iovec *iov, int iovcnt)
ssize_t read(int fildes, void *buf, size_t nbyte)
const char * XrdSysE2T(int errcode)
int64_t fSize
Original size of the source file.
const char * srcLFN
Pointer to the source filename.
XrdOucIOVec * DataVec
A vector of data that must be written back.
int DataLen
Number of bytes to write back (may be 0)
int DataNum
Number of elements in DataVec (may be 0)
time_t mTime
Original modification time of the source.
bool Reserve(int dlen, int nseg)
static char * Target(const char *ckpfn)
int Append(const char *data, off_t offset, int dlen)
XrdOfsCPFile(const char *cfn=0)
int RestoreInfo(rInfo &rinfo, const char *&ewhy)
~XrdOfsCPFile()
Destructor.
int Create(const char *lfn, struct stat &Stat)
const char * FName(bool trim=false)
static uint32_t Calc32C(const void *data, size_t count, uint32_t prevcs=0)
static bool Ver32C(const void *data, size_t count, const uint32_t csval, uint32_t *csbad=0)