00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013 const char *XrdOssCopyCVSID = "$Id: XrdOssCopy.cc 30949 2009-11-02 16:37:58Z ganis $";
00014
00015 #include <errno.h>
00016 #include <fcntl.h>
00017 #include <string.h>
00018 #include <time.h>
00019 #include <stdio.h>
00020 #include <unistd.h>
00021 #include <utime.h>
00022 #include <sys/mman.h>
00023 #include <sys/types.h>
00024 #include <sys/stat.h>
00025
00026 #include "XrdOss/XrdOssCopy.hh"
00027 #include "XrdOss/XrdOssTrace.hh"
00028 #include "XrdSys/XrdSysError.hh"
00029
00030
00031
00032
00033
00034 extern XrdSysError OssEroute;
00035
00036 extern XrdOucTrace OssTrace;
00037
00038
00039
00040
00041
00042 off_t XrdOssCopy::Copy(const char *inFn, const char *outFn, int outFD)
00043 {
00044 static const size_t segSize = 1024*1024;
00045 class ioFD
00046 {public:
00047 int FD;
00048 ioFD(int fd=-1) : FD(fd) {}
00049 ~ioFD() {if (FD >= 0) close(FD);}
00050 } In, Out(outFD);
00051
00052 struct utimbuf tBuff;
00053 struct stat buf;
00054 char *inBuff, *bP;
00055 off_t Offset=0, fileSize;
00056 size_t ioSize, copySize;
00057 ssize_t rLen;
00058
00059
00060
00061 if ((In.FD = open(inFn, O_RDONLY)) < 0)
00062 {OssEroute.Emsg("Copy", errno, "open", inFn); return -1;}
00063
00064
00065
00066 if (fstat(In.FD, &buf))
00067 {OssEroute.Emsg("Copy", errno, "stat", outFn); return -1;}
00068 copySize = fileSize = buf.st_size;
00069
00070
00071
00072 ioSize = (fileSize < (off_t)segSize ? fileSize : segSize);
00073 while(copySize)
00074 {if ((inBuff = (char *)mmap(0, ioSize, PROT_READ,
00075 MAP_NORESERVE|MAP_PRIVATE, In.FD, Offset)) == MAP_FAILED)
00076 {OssEroute.Emsg("Copy", errno, "memory map", inFn); break;}
00077 if (!Write(outFn, Out.FD, inBuff, ioSize, Offset)) break;
00078 copySize -= ioSize; Offset += ioSize;
00079 if (munmap(inBuff, ioSize) < 0)
00080 {OssEroute.Emsg("Copy", errno, "unmap memory for", inFn); break;}
00081 if (copySize < segSize) ioSize = copySize;
00082 }
00083
00084
00085
00086 if (!copySize) return fileSize;
00087 if ((off_t)copySize != fileSize) return -1;
00088 OssEroute.Emsg("Copy", "Trying traditional copy for", inFn, "...");
00089
00090
00091
00092 {char ioBuff[segSize];
00093 off_t rdSize, wrSize = segSize, inOff=0;
00094 while(copySize)
00095 {if (copySize < segSize) rdSize = wrSize = copySize;
00096 else rdSize = segSize;
00097 bP = ioBuff;
00098 while(rdSize)
00099 {do {rLen = pread(In.FD, bP, rdSize, inOff);}
00100 while(rLen < 0 && errno == EINTR);
00101 if (rLen <= 0)
00102 {OssEroute.Emsg("Copy",rLen ? errno : ECANCELED,"read",inFn);
00103 return -1;
00104 }
00105 bP += rLen; rdSize -= rLen; inOff += rLen;
00106 }
00107 if (!Write(outFn, Out.FD, ioBuff, wrSize, Offset)) return -1;
00108 copySize -= wrSize; Offset += wrSize;
00109 }
00110 }
00111
00112
00113
00114 tBuff.actime = buf.st_atime;
00115 tBuff.modtime= buf.st_mtime;
00116 if (utime(outFn, &tBuff))
00117 OssEroute.Emsg("Copy", errno, "set mtime for", outFn);
00118
00119
00120
00121 return fileSize;
00122 }
00123
00124
00125
00126
00127
00128 int XrdOssCopy::Write(const char *outFn,
00129 int oFD, char *Buff, size_t BLen, off_t BOff)
00130 {
00131 ssize_t wLen;
00132
00133
00134
00135 while(BLen)
00136 {if ((wLen = pwrite(oFD, Buff, BLen, BOff)) < 0)
00137 {if (errno == EINTR) continue;
00138 else break;
00139 }
00140 Buff += wLen; BLen -= wLen; BOff += wLen;
00141 }
00142
00143
00144
00145 if (!BLen) return 1;
00146 OssEroute.Emsg("Copy", errno, "write", outFn);
00147 return 0;
00148 }