summaryrefslogtreecommitdiff
path: root/usr.bin/cvs/diff3.c
diff options
context:
space:
mode:
authorJoris Vink <joris@cvs.openbsd.org>2008-02-27 22:34:05 +0000
committerJoris Vink <joris@cvs.openbsd.org>2008-02-27 22:34:05 +0000
commitc8955619dd8db636823797d2bd41b68bc78af8c1 (patch)
tree0f1a922b9d1b4bb083ea6b7477f91aaa7333681d /usr.bin/cvs/diff3.c
parent3d3b75f61b57504b71451e352de59d6ff8ffd6a4 (diff)
prevent file races
ok tobias@
Diffstat (limited to 'usr.bin/cvs/diff3.c')
-rw-r--r--usr.bin/cvs/diff3.c68
1 files changed, 45 insertions, 23 deletions
diff --git a/usr.bin/cvs/diff3.c b/usr.bin/cvs/diff3.c
index 4bcfb654689..b551500fb41 100644
--- a/usr.bin/cvs/diff3.c
+++ b/usr.bin/cvs/diff3.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: diff3.c,v 1.41 2008/02/23 23:42:23 joris Exp $ */
+/* $OpenBSD: diff3.c,v 1.42 2008/02/27 22:34:04 joris Exp $ */
/*
* Copyright (C) Caldera International Inc. 2001-2002.
@@ -72,7 +72,7 @@ static const char copyright[] =
#ifndef lint
static const char rcsid[] =
- "$OpenBSD: diff3.c,v 1.41 2008/02/23 23:42:23 joris Exp $";
+ "$OpenBSD: diff3.c,v 1.42 2008/02/27 22:34:04 joris Exp $";
#endif /* not lint */
#include <ctype.h>
@@ -146,7 +146,7 @@ static int edit(struct diff *, int, int);
static char *getchange(FILE *);
static char *getline(FILE *, size_t *);
static int number(char **);
-static size_t readin(char *, struct diff **);
+static size_t readin(int, struct diff **);
static int skip(int, int, char *);
static int edscript(int);
static int merge(size_t, size_t);
@@ -160,10 +160,12 @@ static int diff3_internal(int, char **, const char *, const char *);
int diff3_conflicts = 0;
+static int fds[5];
+
void
cvs_merge_file(struct cvs_file *cf, int verbose)
{
- int argc;
+ int i, argc;
char *data, *patch;
char *argv[5], r1[CVS_REV_BUFSZ], r2[CVS_REV_BUFSZ];
char *dp13, *dp23, *path1, *path2, *path3;
@@ -182,34 +184,28 @@ cvs_merge_file(struct cvs_file *cf, int verbose)
d2 = cvs_buf_alloc(128);
diffb = cvs_buf_alloc(128);
- (void)close(cf->fd);
- cf->fd = open(cf->file_path, O_WRONLY | O_TRUNC);
- if (cf->fd == -1) {
- fatal("cvs_merge_file: failed to reopen fd for writing: %s",
- strerror(errno));
- }
-
(void)xasprintf(&path1, "%s/diff1.XXXXXXXXXX", cvs_tmpdir);
(void)xasprintf(&path2, "%s/diff2.XXXXXXXXXX", cvs_tmpdir);
(void)xasprintf(&path3, "%s/diff3.XXXXXXXXXX", cvs_tmpdir);
- cvs_buf_write_stmp(b1, path1, NULL);
+ fds[2] = cvs_buf_write_stmp(b1, path1, NULL);
if (verbose == 1)
cvs_printf("Retrieving revision %s\n", r1);
- rcs_rev_write_stmp(cf->file_rcs, cf->file_ent->ce_rev, path2, 0);
+ fds[3] = rcs_rev_write_stmp(cf->file_rcs, cf->file_ent->ce_rev,
+ path2, 0);
if (verbose == 1)
cvs_printf("Retrieving revision %s\n", r2);
- rcs_rev_write_stmp(cf->file_rcs, cf->file_rcsrev, path3, 0);
+ fds[4] = rcs_rev_write_stmp(cf->file_rcs, cf->file_rcsrev, path3, 0);
- cvs_diffreg(path1, path3, d1);
- cvs_diffreg(path2, path3, d2);
+ cvs_diffreg(path1, path3, fds[2], fds[4], d1);
+ cvs_diffreg(path2, path3, fds[3], fds[4], d2);
(void)xasprintf(&dp13, "%s/d13.XXXXXXXXXX", cvs_tmpdir);
- cvs_buf_write_stmp(d1, dp13, NULL);
+ fds[0] = cvs_buf_write_stmp(d1, dp13, NULL);
cvs_buf_free(d1);
(void)xasprintf(&dp23, "%s/d23.XXXXXXXXXX", cvs_tmpdir);
- cvs_buf_write_stmp(d2, dp23, NULL);
+ fds[1] = cvs_buf_write_stmp(d2, dp23, NULL);
cvs_buf_free(d2);
argc = 0;
@@ -220,6 +216,13 @@ cvs_merge_file(struct cvs_file *cf, int verbose)
argv[argc++] = path2;
argv[argc++] = path3;
+ if (lseek(fds[2], SEEK_SET, 0) < 0)
+ fatal("cvs_merge_file: lseek fds[2]: %s", strerror(errno));
+ if (lseek(fds[3], SEEK_SET, 0) < 0)
+ fatal("cvs_merge_file: lseek fds[3]: %s", strerror(errno));
+ if (lseek(fds[4], SEEK_SET, 0) < 0)
+ fatal("cvs_merge_file: lseek fds[4]: %s", strerror(errno));
+
diff3_conflicts = diff3_internal(argc, argv, cf->file_path, r2);
if (diff3_conflicts < 0)
fatal("cvs_merge_file: merging failed for an unknown reason");
@@ -243,6 +246,13 @@ cvs_merge_file(struct cvs_file *cf, int verbose)
(diff3_conflicts > 1) ? "s" : "");
}
+ (void)close(cf->fd);
+ cf->fd = open(cf->file_path, O_WRONLY | O_TRUNC);
+ if (cf->fd == -1) {
+ fatal("cvs_merge_file: failed to reopen fd for writing: %s",
+ strerror(errno));
+ }
+
TAILQ_FOREACH(lp, &(dlines->l_lines), l_list) {
if (lp->l_line == NULL)
continue;
@@ -258,6 +268,9 @@ cvs_merge_file(struct cvs_file *cf, int verbose)
xfree(data);
xfree(patch);
+ for (i = 0; i < 3; i++)
+ fclose(fp[i]);
+
(void)unlink(path1);
(void)unlink(path2);
(void)unlink(path3);
@@ -288,11 +301,16 @@ diff3_internal(int argc, char **argv, const char *fmark, const char *rmark)
(void)xsnprintf(f3mark, sizeof(f3mark), ">>>>>>> %s", rmark);
increase();
- m = readin(argv[0], &d13);
- n = readin(argv[1], &d23);
+
+ /* fds[0] and fds[1] are closed in readin() */
+ cvs_printf("calling readin with fds[0] (%s)\n", argv[0]);
+ m = readin(fds[0], &d13);
+ cvs_printf("calling readin with fds[1] (%s)\n", argv[1]);
+ n = readin(fds[1], &d23);
for (i = 0; i <= 2; i++) {
- if ((fp[i] = fopen(argv[i + 2], "r")) == NULL) {
+ cvs_printf("opening fds[%d] (%s)\n", i + 2, argv[i + 2]);
+ if ((fp[i] = fdopen(fds[i + 2], "r")) == NULL) {
cvs_log(LP_ERR, "%s", argv[i + 2]);
return (-1);
}
@@ -415,13 +433,16 @@ ed_patch_lines(struct cvs_lines *dlines, struct cvs_lines *plines)
* The vector could be optimized out of existence)
*/
static size_t
-readin(char *name, struct diff **dd)
+readin(int fd, struct diff **dd)
{
int a, b, c, d;
char kind, *p;
size_t i;
- fp[0] = fopen(name, "r");
+ fp[0] = fdopen(fd, "r");
+ if (fp[0] == NULL)
+ fatal("readin: fdopen: %s", strerror(errno));
+
for (i = 0; (p = getchange(fp[0])); i++) {
if (i >= szchanges - 1)
increase();
@@ -452,6 +473,7 @@ readin(char *name, struct diff **dd)
(*dd)[i].old.from = (*dd)[i-1].old.to;
(*dd)[i].new.from = (*dd)[i-1].new.to;
}
+
(void)fclose(fp[0]);
return (i);