diff options
-rw-r--r-- | usr.bin/cvs/edit.c | 5 | ||||
-rw-r--r-- | usr.bin/cvs/file.c | 84 | ||||
-rw-r--r-- | usr.bin/cvs/file.h | 3 |
3 files changed, 88 insertions, 4 deletions
diff --git a/usr.bin/cvs/edit.c b/usr.bin/cvs/edit.c index f55f66cfbbb..1f428d6e408 100644 --- a/usr.bin/cvs/edit.c +++ b/usr.bin/cvs/edit.c @@ -1,4 +1,4 @@ -/* $OpenBSD: edit.c,v 1.25 2007/01/09 10:01:43 xsa Exp $ */ +/* $OpenBSD: edit.c,v 1.26 2007/01/10 21:32:19 xsa Exp $ */ /* * Copyright (c) 2006, 2007 Xavier Santolaria <xsa@openbsd.org> * @@ -303,7 +303,8 @@ cvs_edit_local(struct cvs_file *cf) fatal("cvs_edit_local: `%s': %s", CVS_PATH_BASEDIR, strerror(errno)); - /* XXX: copy cf->file_path to bfpath */ + if (cvs_file_copy(cf->file_path, bfpath) == -1) + fatal("cvs_edit_local: cvs_file_copy failed"); xfree(bfpath); diff --git a/usr.bin/cvs/file.c b/usr.bin/cvs/file.c index 35769f573ef..a370cf90362 100644 --- a/usr.bin/cvs/file.c +++ b/usr.bin/cvs/file.c @@ -1,4 +1,4 @@ -/* $OpenBSD: file.c,v 1.165 2007/01/06 17:09:08 xsa Exp $ */ +/* $OpenBSD: file.c,v 1.166 2007/01/10 21:32:19 xsa Exp $ */ /* * Copyright (c) 2006 Joris Vink <joris@openbsd.org> * Copyright (c) 2004 Jean-Francois Brousseau <jfb@openbsd.org> @@ -909,3 +909,85 @@ out: return (ret); } + +int +cvs_file_copy(const char *from, const char *to) +{ + struct stat st; + struct timeval tv[2]; + time_t atime, mtime; + int src, dst, ret; + + ret = 0; + + cvs_log(LP_TRACE, "cvs_file_copy(%s,%s)", from, to); + + if (cvs_noexec == 1) + return (0); + + if ((src = open(from, O_RDONLY, 0)) == -1) + fatal("cvs_file_copy: open: `%s': %s", from, strerror(errno)); + + if (fstat(src, &st) == -1) + fatal("cvs_file_copy: `%s': %s", from, strerror(errno)); + + atime = st.st_atimespec.tv_sec; + mtime = st.st_mtimespec.tv_sec; + + if (S_ISREG(st.st_mode)) { + size_t sz; + ssize_t nw; + char *p, *buf; + int saved_errno; + + if (st.st_size > SIZE_MAX) { + ret = -1; + goto out; + } + + if ((dst = open(to, O_CREAT|O_TRUNC|O_WRONLY, + st.st_mode & (S_IRWXU|S_IRWXG|S_IRWXO))) == -1) + fatal("cvs_file_copy: open `%s': %s", + to, strerror(errno)); + + if ((p = mmap(NULL, st.st_size, PROT_READ, + MAP_FILE, src, (off_t)0)) == MAP_FAILED) { + saved_errno = errno; + (void)unlink(to); + fatal("cvs_file_copy: mmap: %s", strerror(saved_errno)); + } + + madvise(p, st.st_size, MADV_SEQUENTIAL); + + sz = st.st_size; + buf = p; + + while (sz > 0) { + if ((nw = write(dst, p, sz)) == -1) { + saved_errno = errno; + (void)unlink(to); + fatal("cvs_file_copy: `%s': %s", + from, strerror(saved_errno)); + } + buf += nw; + sz -= nw; + } + + (void)munmap(p, st.st_size); + + tv[0].tv_sec = atime; + tv[1].tv_sec = mtime; + + if (futimes(dst, tv) == -1) { + saved_errno = errno; + (void)unlink(to); + fatal("cvs_file_copy: futimes: %s", + strerror(saved_errno)); + } + (void)close(dst); + } +out: + (void)close(src); + + return (ret); +} diff --git a/usr.bin/cvs/file.h b/usr.bin/cvs/file.h index 3fd5621d39d..c3c037fa54b 100644 --- a/usr.bin/cvs/file.h +++ b/usr.bin/cvs/file.h @@ -1,4 +1,4 @@ -/* $OpenBSD: file.h,v 1.39 2007/01/06 17:09:08 xsa Exp $ */ +/* $OpenBSD: file.h,v 1.40 2007/01/10 21:32:19 xsa Exp $ */ /* * Copyright (c) 2006 Joris Vink <joris@openbsd.org> * Copyright (c) 2004 Jean-Francois Brousseau <jfb@openbsd.org> @@ -105,6 +105,7 @@ struct cvs_filelist *cvs_file_get(const char *, struct cvs_flisthead *); int cvs_file_chkign(const char *); int cvs_file_cmpname(const char *, const char *); int cvs_file_cmp(const char *, const char *); +int cvs_file_copy(const char *, const char *); struct cvs_file *cvs_file_get_cf(const char *, const char *, int, int); |