summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--usr.bin/cvs/edit.c5
-rw-r--r--usr.bin/cvs/file.c84
-rw-r--r--usr.bin/cvs/file.h3
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);