diff options
author | Niall O'Higgins <niallo@cvs.openbsd.org> | 2007-01-11 17:44:19 +0000 |
---|---|---|
committer | Niall O'Higgins <niallo@cvs.openbsd.org> | 2007-01-11 17:44:19 +0000 |
commit | d85c0dc058186c85cfed44b898af95f7d7ec453d (patch) | |
tree | a7da1e2066182857b36823351e715a72d4a32795 /usr.bin/cvs | |
parent | 97a8f0e03dbb1ac15c84940d8f111ff4fedfe002 (diff) |
rework opencvs so that we can deal with binary files. previously we assumed all files were ascii,
which broke things in real-world usage. now a checkout of src should work, albeit using lots of
memory and cpu. fixing this is the next step.
testing by many.
ok & some input joris@
Diffstat (limited to 'usr.bin/cvs')
-rw-r--r-- | usr.bin/cvs/annotate.c | 6 | ||||
-rw-r--r-- | usr.bin/cvs/diff3.c | 23 | ||||
-rw-r--r-- | usr.bin/cvs/rcs.c | 52 | ||||
-rw-r--r-- | usr.bin/cvs/update.c | 9 | ||||
-rw-r--r-- | usr.bin/cvs/util.c | 55 | ||||
-rw-r--r-- | usr.bin/cvs/util.h | 11 |
6 files changed, 87 insertions, 69 deletions
diff --git a/usr.bin/cvs/annotate.c b/usr.bin/cvs/annotate.c index 5e26f7a425f..50a2440fca4 100644 --- a/usr.bin/cvs/annotate.c +++ b/usr.bin/cvs/annotate.c @@ -1,4 +1,4 @@ -/* $OpenBSD: annotate.c,v 1.33 2007/01/11 02:35:55 joris Exp $ */ +/* $OpenBSD: annotate.c,v 1.34 2007/01/11 17:44:18 niallo Exp $ */ /* * Copyright (c) 2006 Xavier Santolaria <xsa@openbsd.org> * @@ -112,6 +112,7 @@ cvs_annotate_local(struct cvs_file *cf) BUF *b; RCSNUM *ann_rev; char *content; + size_t len; ann_rev = NULL; @@ -136,8 +137,9 @@ cvs_annotate_local(struct cvs_file *cf) b = rcs_getrev(cf->file_rcs, ann_rev); cvs_buf_putc(b, '\0'); + len = cvs_buf_len(b); content = cvs_buf_release(b); - if ((lines = cvs_splitlines(content)) == NULL) + if ((lines = cvs_splitlines(content, len)) == NULL) fatal("cvs_annotate_local: cvs_splitlines failed"); xfree(content); diff --git a/usr.bin/cvs/diff3.c b/usr.bin/cvs/diff3.c index e6df284e4ad..8dc97f1f011 100644 --- a/usr.bin/cvs/diff3.c +++ b/usr.bin/cvs/diff3.c @@ -1,4 +1,4 @@ -/* $OpenBSD: diff3.c,v 1.29 2006/11/10 08:32:37 xsa Exp $ */ +/* $OpenBSD: diff3.c,v 1.30 2007/01/11 17:44:18 niallo 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.29 2006/11/10 08:32:37 xsa Exp $"; + "$OpenBSD: diff3.c,v 1.30 2007/01/11 17:44:18 niallo Exp $"; #endif /* not lint */ #include "includes.h" @@ -163,6 +163,7 @@ cvs_diff3(RCSFILE *rf, char *workfile, int workfd, RCSNUM *rev1, char *argv[5], r1[16], r2[16]; char *dp13, *dp23, *path1, *path2, *path3; BUF *b1, *b2, *b3, *d1, *d2, *diffb; + size_t dlen, plen; b1 = b2 = b3 = d1 = d2 = diffb = NULL; @@ -230,11 +231,13 @@ cvs_diff3(RCSFILE *rf, char *workfile, int workfd, RCSNUM *rev1, cvs_buf_putc(diffb, '\0'); cvs_buf_putc(b1, '\0'); + plen = cvs_buf_len(diffb); patch = cvs_buf_release(diffb); + dlen = cvs_buf_len(b1); data = cvs_buf_release(b1); diffb = b1 = NULL; - if ((diffb = cvs_patchfile(data, patch, ed_patch_lines)) == NULL) + if ((diffb = cvs_patchfile(data, dlen, patch, plen, ed_patch_lines)) == NULL) goto out; if (verbose == 1 && diff3_conflicts != 0) { @@ -319,6 +322,7 @@ ed_patch_lines(struct cvs_lines *dlines, struct cvs_lines *plines) char op, *ep; struct cvs_line *sort, *lp, *dlp, *ndlp, *insert_after; int start, end, i, lineno; + u_char tmp; dlp = TAILQ_FIRST(&(dlines->l_lines)); lp = TAILQ_FIRST(&(plines->l_lines)); @@ -326,10 +330,17 @@ ed_patch_lines(struct cvs_lines *dlines, struct cvs_lines *plines) end = 0; for (lp = TAILQ_NEXT(lp, l_list); lp != NULL; lp = TAILQ_NEXT(lp, l_list)) { - if (lp->l_line[0] == '\0') - fatal("ed_patch_lines"); + /* Skip blank lines */ + if (lp->l_len < 2) + continue; + /* NUL-terminate line buffer for strtol() safety. */ + tmp = lp->l_line[lp->l_len - 1]; + lp->l_line[lp->l_len - 1] = '\0'; + /* len - 1 is NUL terminator so we use len - 2 for 'op' */ op = lp->l_line[strlen(lp->l_line) - 1]; start = (int)strtol(lp->l_line, &ep, 10); + /* Restore the last byte of the buffer */ + lp->l_line[lp->l_len - 1] = tmp; if (op == 'a') { if (start > dlines->l_nblines || start < 0 || *ep != 'a') @@ -386,7 +397,7 @@ ed_patch_lines(struct cvs_lines *dlines, struct cvs_lines *plines) if (lp == NULL) fatal("ed_patch_lines"); - if (!strcmp(lp->l_line, ".")) + if (!memcmp(lp->l_line, ".", 1)) break; TAILQ_REMOVE(&(plines->l_lines), lp, l_list); diff --git a/usr.bin/cvs/rcs.c b/usr.bin/cvs/rcs.c index 65a4a812c50..7084d97fd56 100644 --- a/usr.bin/cvs/rcs.c +++ b/usr.bin/cvs/rcs.c @@ -1,4 +1,4 @@ -/* $OpenBSD: rcs.c,v 1.192 2006/12/21 15:03:15 niallo Exp $ */ +/* $OpenBSD: rcs.c,v 1.193 2007/01/11 17:44:18 niallo Exp $ */ /* * Copyright (c) 2004 Jean-Francois Brousseau <jfb@openbsd.org> * All rights reserved. @@ -493,11 +493,6 @@ rcs_write(RCSFILE *rfp) fputs("@\ntext\n@", fp); if (rdp->rd_text != NULL) { rcs_strprint(rdp->rd_text, rdp->rd_tlen, fp); - - if (rdp->rd_tlen != 0) { - if (rdp->rd_text[rdp->rd_tlen-1] != '\n') - fputc('\n', fp); - } } fputs("@\n", fp); } @@ -1078,6 +1073,7 @@ rcs_patch_lines(struct cvs_lines *dlines, struct cvs_lines *plines) char op, *ep; struct cvs_line *lp, *dlp, *ndlp; int i, lineno, nbln; + u_char tmp; dlp = TAILQ_FIRST(&(dlines->l_lines)); lp = TAILQ_FIRST(&(plines->l_lines)); @@ -1085,15 +1081,21 @@ rcs_patch_lines(struct cvs_lines *dlines, struct cvs_lines *plines) /* skip first bogus line */ for (lp = TAILQ_NEXT(lp, l_list); lp != NULL; lp = TAILQ_NEXT(lp, l_list)) { + if (lp->l_len < 2) + fatal("line too short, RCS patch seems broken"); op = *(lp->l_line); + /* NUL-terminate line buffer for strtol() safety. */ + tmp = lp->l_line[lp->l_len - 1]; + lp->l_line[lp->l_len - 1] = '\0'; lineno = (int)strtol((lp->l_line + 1), &ep, 10); - if (lineno > dlines->l_nblines || lineno < 0 || - *ep != ' ') - fatal("invalid line specification in RCS patch: %s", - ep); + if (lineno - 1 > dlines->l_nblines || lineno < 0) { + fatal("invalid line specification in RCS patch"); + } ep++; nbln = (int)strtol(ep, &ep, 10); - if (nbln < 0 || *ep != '\0') + /* Restore the last byte of the buffer */ + lp->l_line[lp->l_len - 1] = tmp; + if (nbln < 0) fatal("invalid line number specification in RCS patch"); /* find the appropriate line */ @@ -1170,13 +1172,13 @@ rcs_patch_lines(struct cvs_lines *dlines, struct cvs_lines *plines) BUF* rcs_getrev(RCSFILE *rfp, RCSNUM *frev) { - size_t i; + size_t i, dlen, plen; int done, nextroot, found; BUF *rcsbuf; RCSNUM *tnum, *bnum; struct rcs_branch *brp; struct rcs_delta *hrdp, *trdp, *rdp; - char *data; + u_char *data, *patch; if ((hrdp = rcs_findrev(rfp, rfp->rf_head)) == NULL) fatal("rcs_getrev: no HEAD revision"); @@ -1223,13 +1225,15 @@ again: } } - cvs_buf_putc(rcsbuf, '\0'); + plen = rdp->rd_tlen; + dlen = cvs_buf_len(rcsbuf); + patch = rdp->rd_text; data = cvs_buf_release(rcsbuf); - - rcsbuf = cvs_patchfile(data, rdp->rd_text, rcs_patch_lines); + rcsbuf = cvs_patchfile(data, dlen, patch, plen, + rcs_patch_lines); + xfree(data); if (rcsbuf == NULL) fatal("rcs_getrev: failed to apply rcsdiff"); - xfree(data); if (!rcsnum_differ(rdp->rd_num, bnum)) break; @@ -2102,11 +2106,15 @@ rcs_parse_deltatext(RCSFILE *rfp) return (-1); } - rdp->rd_text = xmalloc(RCS_TOKLEN(rfp) + 1); - if (strlcpy(rdp->rd_text, RCS_TOKSTR(rfp), (RCS_TOKLEN(rfp) + 1)) >= - RCS_TOKLEN(rfp) + 1) - fatal("rcs_parse_deltatext: strlcpy"); - rdp->rd_tlen = RCS_TOKLEN(rfp); + if (RCS_TOKLEN(rfp) == 0) { + rdp->rd_text = xmalloc(1); + rdp->rd_text[0] = '\0'; + rdp->rd_tlen = 0; + } else { + rdp->rd_text = xmalloc(RCS_TOKLEN(rfp)); + memcpy(rdp->rd_text, RCS_TOKSTR(rfp), RCS_TOKLEN(rfp)); + rdp->rd_tlen = RCS_TOKLEN(rfp); + } return (1); } diff --git a/usr.bin/cvs/update.c b/usr.bin/cvs/update.c index afe1aae7124..19108f9f73d 100644 --- a/usr.bin/cvs/update.c +++ b/usr.bin/cvs/update.c @@ -1,4 +1,4 @@ -/* $OpenBSD: update.c,v 1.82 2007/01/11 02:35:55 joris Exp $ */ +/* $OpenBSD: update.c,v 1.83 2007/01/11 17:44:18 niallo Exp $ */ /* * Copyright (c) 2006 Joris Vink <joris@openbsd.org> * @@ -419,6 +419,7 @@ update_has_conflict_markers(struct cvs_file *cf) char *content; struct cvs_line *lp; struct cvs_lines *lines; + size_t len; cvs_log(LP_TRACE, "update_has_conflict_markers(%s)", cf->file_path); @@ -430,12 +431,11 @@ update_has_conflict_markers(struct cvs_file *cf) cf->file_path); cvs_buf_putc(bp, '\0'); + len = cvs_buf_len(bp); content = cvs_buf_release(bp); - if ((lines = cvs_splitlines(content)) == NULL) + if ((lines = cvs_splitlines(content, len)) == NULL) fatal("update_has_conflict_markers: failed to split lines"); - xfree(content); - conflict = 0; TAILQ_FOREACH(lp, &(lines->l_lines), l_list) { if (lp->l_line == NULL) @@ -453,5 +453,6 @@ update_has_conflict_markers(struct cvs_file *cf) } cvs_freelines(lines); + xfree(content); return (conflict); } diff --git a/usr.bin/cvs/util.c b/usr.bin/cvs/util.c index 11c21f59780..34e1de8d0ac 100644 --- a/usr.bin/cvs/util.c +++ b/usr.bin/cvs/util.c @@ -1,4 +1,4 @@ -/* $OpenBSD: util.c,v 1.96 2007/01/07 01:53:12 joris Exp $ */ +/* $OpenBSD: util.c,v 1.97 2007/01/11 17:44:18 niallo Exp $ */ /* * Copyright (c) 2004 Jean-Francois Brousseau <jfb@openbsd.org> * Copyright (c) 2005, 2006 Joris Vink <joris@openbsd.org> @@ -738,32 +738,33 @@ cvs_mkpath(const char *path) * Split the contents of a file into a list of lines. */ struct cvs_lines * -cvs_splitlines(const char *fcont) +cvs_splitlines(const u_char *data, size_t len) { - char *dcp; + u_char *p, *c; + size_t i, tlen; struct cvs_lines *lines; struct cvs_line *lp; lines = xmalloc(sizeof(*lines)); + memset(lines, 0, sizeof(*lines)); TAILQ_INIT(&(lines->l_lines)); - lines->l_nblines = 0; - lines->l_data = xstrdup(fcont); lp = xmalloc(sizeof(*lp)); - lp->l_line = NULL; - lp->l_lineno = 0; + memset(lp, 0, sizeof(*lp)); TAILQ_INSERT_TAIL(&(lines->l_lines), lp, l_list); - for (dcp = lines->l_data; *dcp != '\0';) { - lp = xmalloc(sizeof(*lp)); - lp->l_line = dcp; - lp->l_lineno = ++(lines->l_nblines); - TAILQ_INSERT_TAIL(&(lines->l_lines), lp, l_list); - - dcp = strchr(dcp, '\n'); - if (dcp == NULL) - break; - *(dcp++) = '\0'; + p = c = data; + for (i = 0; i < len; i++) { + if (*p == '\n' || (i == len - 1)) { + tlen = p - c + 1; + lp = xmalloc(sizeof(*lp)); + lp->l_line = c; + lp->l_len = tlen; + lp->l_lineno = ++(lines->l_nblines); + TAILQ_INSERT_TAIL(&(lines->l_lines), lp, l_list); + c = p + 1; + } + p++; } return (lines); @@ -779,26 +780,21 @@ cvs_freelines(struct cvs_lines *lines) xfree(lp); } - xfree(lines->l_data); xfree(lines); } BUF * -cvs_patchfile(const char *data, const char *patch, +cvs_patchfile(const u_char *data, size_t dlen, const u_char *patch, size_t plen, int (*p)(struct cvs_lines *, struct cvs_lines *)) { struct cvs_lines *dlines, *plines; struct cvs_line *lp; - size_t len; - int lineno; BUF *res; - len = strlen(data); - - if ((dlines = cvs_splitlines(data)) == NULL) + if ((dlines = cvs_splitlines(data, dlen)) == NULL) return (NULL); - if ((plines = cvs_splitlines(patch)) == NULL) + if ((plines = cvs_splitlines(patch, plen)) == NULL) return (NULL); if (p(dlines, plines) < 0) { @@ -807,12 +803,11 @@ cvs_patchfile(const char *data, const char *patch, return (NULL); } - lineno = 0; - res = cvs_buf_alloc(len, BUF_AUTOEXT); + res = cvs_buf_alloc(1024, BUF_AUTOEXT); TAILQ_FOREACH(lp, &dlines->l_lines, l_list) { - if (lineno != 0) - cvs_buf_fappend(res, "%s\n", lp->l_line); - lineno++; + if (lp->l_line == NULL) + continue; + cvs_buf_append(res, lp->l_line, lp->l_len); } cvs_freelines(dlines); diff --git a/usr.bin/cvs/util.h b/usr.bin/cvs/util.h index c7e89dd859e..1441e6fce2b 100644 --- a/usr.bin/cvs/util.h +++ b/usr.bin/cvs/util.h @@ -1,4 +1,4 @@ -/* $OpenBSD: util.h,v 1.12 2007/01/07 01:53:12 joris Exp $ */ +/* $OpenBSD: util.h,v 1.13 2007/01/11 17:44:18 niallo Exp $ */ /* * Copyright (c) 2006 Niall O'Higgins <niallo@openbsd.org> * All rights reserved. @@ -50,6 +50,7 @@ u_int cvs_revision_select(RCSFILE *, char *); struct cvs_line { char *l_line; + size_t l_len; int l_lineno; TAILQ_ENTRY(cvs_line) l_list; }; @@ -58,7 +59,6 @@ TAILQ_HEAD(cvs_tqh, cvs_line); struct cvs_lines { int l_nblines; - char *l_data; struct cvs_tqh l_lines; }; @@ -67,9 +67,10 @@ struct cvs_argvector { char **argv; }; -BUF *cvs_patchfile(const char *, const char *, - int (*p)(struct cvs_lines *, struct cvs_lines *)); -struct cvs_lines *cvs_splitlines(const char *); +BUF *cvs_patchfile(const u_char *, size_t, const u_char *, + size_t, int (*p)(struct cvs_lines *, + struct cvs_lines *)); +struct cvs_lines *cvs_splitlines(const u_char *, size_t); void cvs_freelines(struct cvs_lines *); struct cvs_argvector *cvs_strsplit(char *, const char *); void cvs_argv_destroy(struct cvs_argvector *); |