diff options
author | Joris Vink <joris@cvs.openbsd.org> | 2008-02-27 22:34:05 +0000 |
---|---|---|
committer | Joris Vink <joris@cvs.openbsd.org> | 2008-02-27 22:34:05 +0000 |
commit | c8955619dd8db636823797d2bd41b68bc78af8c1 (patch) | |
tree | 0f1a922b9d1b4bb083ea6b7477f91aaa7333681d /usr.bin/cvs/diff3.c | |
parent | 3d3b75f61b57504b71451e352de59d6ff8ffd6a4 (diff) |
prevent file races
ok tobias@
Diffstat (limited to 'usr.bin/cvs/diff3.c')
-rw-r--r-- | usr.bin/cvs/diff3.c | 68 |
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); |