00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #include "system.h"
00020
00021 #include "CopyShortId.H"
00022 #include "ShortIdBlock.H"
00023 #include "FdCache.H"
00024
00025 #define COPY_SIZE 8192
00026
00027 ShortId CopyShortId(ShortId oldsid, int &errno_out,
00028 Basics::uint64 n, Basics::uint64 *copied,
00029 bool writable)
00030 {
00031 FdCache::OFlag oldofl;
00032 int oldfd = FdCache::open(oldsid, FdCache::any, &oldofl);
00033 if (oldfd < 0) {
00034 errno_out = errno;
00035 return NullShortId;
00036 }
00037 if (lseek(oldfd, 0L, SEEK_SET) < 0) {
00038 errno_out = errno;
00039 FdCache::close(oldsid, oldfd, oldofl);
00040 return NullShortId;
00041 }
00042 ShortId newsid;
00043 int newfd = SourceOrDerived::fdcreate(newsid);
00044 if (newfd < 0) {
00045 errno_out = errno;
00046 FdCache::close(oldsid, oldfd, oldofl);
00047 return NullShortId;
00048 }
00049 struct stat st;
00050 if (fstat(oldfd, &st) < 0) {
00051 errno_out = errno;
00052 FdCache::close(oldsid, oldfd, oldofl);
00053 close(newfd);
00054 return NullShortId;
00055 }
00056 Basics::uint64 i = n;
00057 while (i > 0) {
00058 char buf[COPY_SIZE];
00059 int len = COPY_SIZE;
00060 if (len > i) len = i;
00061 len = read(oldfd, buf, len);
00062 if (len < 0) {
00063 errno_out = errno;
00064 FdCache::close(oldsid, oldfd, oldofl);
00065 close(newfd);
00066 return NullShortId;
00067 }
00068 if (len == 0) break;
00069 len = write(newfd, buf, len);
00070 if (len < 0) {
00071 errno_out = errno;
00072 FdCache::close(oldsid, oldfd, oldofl);
00073 close(newfd);
00074 return NullShortId;
00075 }
00076 i -= len;
00077 if (len < COPY_SIZE) break;
00078 }
00079 if(copied)
00080 *copied = (n - i);
00081
00082 if(writable)
00083 fchmod(newfd, st.st_mode | 0200);
00084 else
00085 fchmod(newfd, st.st_mode & ~0222);
00086 struct timeval tvp[2];
00087 tvp[0].tv_sec = st.st_atime;
00088 tvp[1].tv_sec = st.st_mtime;
00089 #if __digital__
00090 tvp[0].tv_usec = st.st_spare1;
00091 tvp[1].tv_usec = st.st_spare2;
00092 #else
00093 tvp[0].tv_usec = 0;
00094 tvp[1].tv_usec = 0;
00095 #endif
00096 char* path = ShortIdBlock::shortIdToName(newsid);
00097 if (utimes(path, tvp) < 0) {
00098 errno_out = errno;
00099 FdCache::close(oldsid, oldfd, oldofl);
00100 close(newfd);
00101 return NullShortId;
00102 }
00103 delete [] path;
00104 FdCache::close(oldsid, oldfd, oldofl);
00105 FdCache::close(newsid, newfd, FdCache::rw);
00106 return newsid;
00107
00108 }