summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorXavier Santolaria <xsa@cvs.openbsd.org>2007-01-05 07:13:50 +0000
committerXavier Santolaria <xsa@cvs.openbsd.org>2007-01-05 07:13:50 +0000
commit4217a63abf32c3e24936f413349723a96aa250af (patch)
treebeab42b1a66705e6cd64c648d7528d9f8993f07d
parentad5b22b647b348e50ba6b3257406c9e145c96467 (diff)
- introduce file comparison routine, cvs_file_cmp().
- compare the <file> in working dir and the one in CVS/Base/<file> for the unedit command. hints otto@, input and ok ray@ niallo@.
-rw-r--r--usr.bin/cvs/edit.c12
-rw-r--r--usr.bin/cvs/file.c66
-rw-r--r--usr.bin/cvs/file.h3
3 files changed, 77 insertions, 4 deletions
diff --git a/usr.bin/cvs/edit.c b/usr.bin/cvs/edit.c
index b745509e20d..189d688b70d 100644
--- a/usr.bin/cvs/edit.c
+++ b/usr.bin/cvs/edit.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: edit.c,v 1.16 2007/01/03 09:49:37 xsa Exp $ */
+/* $OpenBSD: edit.c,v 1.17 2007/01/05 07:13:49 xsa Exp $ */
/*
* Copyright (c) 2006, 2007 Xavier Santolaria <xsa@openbsd.org>
*
@@ -177,7 +177,15 @@ cvs_unedit_local(struct cvs_file *cf)
return;
}
- /* XXX: compare cf->file_path and bfpath */
+ if (cvs_file_cmp(cf->file_path, bfpath) != 0) {
+ cvs_printf("%s has been modified; revert changes? ",
+ cf->file_name);
+
+ if (cvs_yesno() == -1) {
+ xfree(bfpath);
+ return;
+ }
+ }
cvs_rename(bfpath, cf->file_path);
xfree(bfpath);
diff --git a/usr.bin/cvs/file.c b/usr.bin/cvs/file.c
index bf3f5c999fe..6e8f2773eb0 100644
--- a/usr.bin/cvs/file.c
+++ b/usr.bin/cvs/file.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: file.c,v 1.163 2006/10/25 20:52:34 moritz Exp $ */
+/* $OpenBSD: file.c,v 1.164 2007/01/05 07:13:49 xsa Exp $ */
/*
* Copyright (c) 2006 Joris Vink <joris@openbsd.org>
* Copyright (c) 2004 Jean-Francois Brousseau <jfb@openbsd.org>
@@ -27,6 +27,8 @@
#include "includes.h"
+#include <sys/mman.h>
+
#include "cvs.h"
#include "file.h"
#include "log.h"
@@ -847,3 +849,65 @@ cvs_file_cmpname(const char *name1, const char *name2)
return (cvs_nocase == 0) ? (strcmp(name1, name2)) :
(strcasecmp(name1, name2));
}
+
+int
+cvs_file_cmp(const char *file1, const char *file2)
+{
+ struct stat stb1, stb2;
+ int fd1, fd2, ret;
+
+ ret = 0;
+
+ if ((fd1 = open(file1, O_RDONLY|O_NOFOLLOW, 0)) == -1)
+ fatal("cvs_file_cmp: open: `%s': %s", file1, strerror(errno));
+ if ((fd2 = open(file2, O_RDONLY|O_NOFOLLOW, 0)) == -1)
+ fatal("cvs_file_cmp: open: `%s': %s", file2, strerror(errno));
+
+ if (fstat(fd1, &stb1) == -1)
+ fatal("cvs_file_cmp: `%s': %s", file1, strerror(errno));
+ if (fstat(fd2, &stb2) == -1)
+ fatal("cvs_file_cmp: `%s': %s", file2, strerror(errno));
+
+ if (stb1.st_size != stb2.st_size ||
+ (stb1.st_mode & S_IFMT) != (stb2.st_mode & S_IFMT)) {
+ ret = 1;
+ goto out;
+ }
+
+ if (S_ISBLK(stb1.st_mode) || S_ISCHR(stb1.st_mode)) {
+ if (stb1.st_rdev != stb2.st_rdev)
+ ret = 1;
+ goto out;
+ }
+
+ if (S_ISREG(stb1.st_mode)) {
+ void *p1, *p2;
+
+ if (stb1.st_size > SIZE_MAX) {
+ ret = 1;
+ goto out;
+ }
+
+ if ((p1 = mmap(NULL, stb1.st_size, PROT_READ,
+ MAP_FILE, fd1, (off_t)0)) == MAP_FAILED)
+ fatal("cvs_file_cmp: mmap failed");
+
+ if ((p2 = mmap(NULL, stb1.st_size, PROT_READ,
+ MAP_FILE, fd2, (off_t)0)) == MAP_FAILED)
+ fatal("cvs_file_cmp: mmap failed");
+
+ madvise(p1, stb1.st_size, MADV_SEQUENTIAL);
+ madvise(p2, stb1.st_size, MADV_SEQUENTIAL);
+
+ ret = memcmp(p1, p2, stb1.st_size);
+
+ (void)munmap(p1, stb1.st_size);
+ (void)munmap(p2, stb1.st_size);
+ }
+
+out:
+ (void)close(fd1);
+ (void)close(fd2);
+
+ return (ret);
+}
diff --git a/usr.bin/cvs/file.h b/usr.bin/cvs/file.h
index 00f5854de27..bb8de7b33dd 100644
--- a/usr.bin/cvs/file.h
+++ b/usr.bin/cvs/file.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: file.h,v 1.37 2006/05/30 21:32:52 joris Exp $ */
+/* $OpenBSD: file.h,v 1.38 2007/01/05 07:13:49 xsa Exp $ */
/*
* Copyright (c) 2006 Joris Vink <joris@openbsd.org>
* Copyright (c) 2004 Jean-Francois Brousseau <jfb@openbsd.org>
@@ -103,6 +103,7 @@ void cvs_file_freelist(struct cvs_flisthead *);
struct cvs_filelist *cvs_file_get(const char *, struct cvs_flisthead *);
int cvs_file_chkign(const char *);
+int cvs_file_cmp(const char *, const char *);
struct cvs_file *cvs_file_get_cf(const char *, const char *, int, int);