35{
36 if (!rename(_oldpath, _newpath))
37 return 0;
38
39 if (errno != EXDEV)
40 return -1;
41
42
43
44 int oldfd = -1, newfd = -1;
45 struct stat oldstat, newstat;
46
47 if (lstat(_oldpath, &oldstat) || lstat(_newpath, &newstat))
48 return -1;
49#if 0
50 if (S_ISLNK(oldstat.st_mode)) {
51 char oldpath[1024 + 1];
52 int n = readlink(_oldpath, oldpath,
sizeof(oldpath) - 1);
54
55
57 if (symlink(oldpath, _newpath))
58 return -1;
59 unlink(_oldpath);
60 }
61 return -1;
62 }
63#endif
64 if (!S_ISREG(oldstat.st_mode)) {
65 errno = EINVAL;
66 return -1;
67 }
68
69 do {
70 oldfd = open(_oldpath, O_RDONLY);
71 newfd = open(_newpath, O_CREAT | O_WRONLY, oldstat.st_mode);
72 if (oldfd == -1 || newfd == -1)
73 break;
74#if __USE_SENDFILE
75 off_t offset = 0;
76 ssize_t
n = sendfile(newfd, oldfd, &offset, oldstat.st_size);
78 break;
79#else
80 char*
buf = (
char*)malloc(newstat.st_blksize);
82 errno = ENOMEM;
83 break;
84 }
86 while ((
n != -1) && (
n = read(oldfd,
buf, newstat.st_blksize)) > 0)
87 n = _write(newfd,
buf,
n);
90 break;
91#endif
92 close(oldfd);
93 close(newfd);
94
95 struct utimbuf ub;
96 ub.actime = oldstat.st_atime;
97 ub.modtime = oldstat.st_mtime;
98 utime(_newpath, &ub);
99 unlink(_oldpath);
100 return 0;
101 } while (true);
102
103 int save = errno;
104 if (oldfd != -1)
105 close(oldfd);
106 if (newfd != -1) {
107 close(newfd);
108 unlink(_newpath);
109 }
110
111 errno = save;
112 return -1;
113}
void CharsetConvertException *size_t n