61 static const size_t segSize = 1024*1024;
65 ioFD(
int fd=-1) : FD(fd) {}
66 ~ioFD() {
if (FD >= 0)
close(FD);}
70 struct stat buf, bufO, bufSL;
72 off_t Offset=0, fileSize;
73 size_t ioSize, copySize;
79 if ((In.FD =
open(inFn, O_RDONLY)) < 0)
80 return -
OssEroute.Emsg(
"Copy", errno,
"open", inFn);
84 if (
fstat(In.FD, &buf))
return -
OssEroute.Emsg(
"Copy", errno,
"stat", inFn);
85 copySize = fileSize = buf.st_size;
91 if (
fstat(Out.FD, &bufO))
return -
OssEroute.Emsg(
"Copy",errno,
"stat",outFn);
92 if (buf.st_dev == bufO.st_dev)
93 {
char lnkBuff[1024+8];
const char *srcFn = inFn;
int n;
94 if (
lstat(inFn, &bufSL))
return -
OssEroute.Emsg(
"Copy",errno,
"lstat",inFn);
95 if ((bufSL.st_mode & S_IFMT) == S_IFLNK)
96 {
if ((n = readlink(inFn, lnkBuff,
sizeof(lnkBuff)-1)) < 0)
97 return -
OssEroute.Emsg(
"Copy", errno,
"readlink", inFn);
98 lnkBuff[n] =
'\0'; srcFn = lnkBuff;
101 if (link(srcFn,outFn))
return -
OssEroute.Emsg(
"Copy",errno,
"link",outFn);
107 ioSize = (fileSize < (off_t)segSize ? fileSize : segSize);
109 {
if ((inBuff = (
char *)mmap(0, ioSize, PROT_READ,
110#
if defined(__FreeBSD__)
111 MAP_RESERVED0040|MAP_PRIVATE, In.FD, Offset)) == MAP_FAILED)
112#elif defined(__GNU__)
113 MAP_PRIVATE, In.FD, Offset)) == MAP_FAILED)
115 MAP_NORESERVE|MAP_PRIVATE, In.FD, Offset)) == MAP_FAILED)
117 {
OssEroute.Emsg(
"Copy", errno,
"memory map", inFn);
break;}
118 if (Write(outFn, Out.FD, inBuff, ioSize, Offset) < 0)
break;
119 copySize -= ioSize; Offset += ioSize;
120 if (munmap(inBuff, ioSize) < 0)
121 {
OssEroute.Emsg(
"Copy", errno,
"unmap memory for", inFn);
break;}
122 if (copySize < segSize) ioSize = copySize;
128 {
if ((off_t)copySize != fileSize)
return -EIO;
130 OssEroute.Emsg(
"Copy",
"Trying traditional copy for", inFn,
"...");
131 char ioBuff[segSize];
132 off_t rdSize, wrSize = segSize, inOff=0;
134 {
if (copySize < segSize) rdSize = wrSize = copySize;
135 else rdSize = segSize;
138 {
do {rLen =
pread(In.FD, bP, rdSize, inOff);}
139 while(rLen < 0 && errno == EINTR);
140 if (rLen <= 0)
return -
OssEroute.Emsg(
"Copy",
141 rLen ? errno : ECANCELED,
"read", inFn);
142 bP += rLen; rdSize -= rLen; inOff += rLen;
144 if ((rc = Write(outFn, Out.FD, ioBuff, wrSize, Offset)) < 0)
return rc;
145 copySize -= wrSize; Offset += wrSize;
155 tBuff.actime = buf.st_atime;
156 tBuff.modtime= buf.st_mtime;
157 if (utime(outFn, &tBuff))
158 OssEroute.Emsg(
"Copy", errno,
"set mtime for", outFn);