Download raw body.
rcs(1): fix comparisons between selected revision and HEAD
Hi,
In some cases rcs(1) fails to check whether a revision number is greater
than the current HEAD. Due to this rcsdiff(1) and co(1) fail in cases
where they should run fine.
The check fails when any of the HEAD revision numbers are lesser than
the number at the same depth on the revision it is comparing against.
E.g. r1.3 is detected to be greater than HEAD if HEAD is r2.1.
Diff applies the fix mentioned in the XXX comments and provides
regression tests for the cases detected. None of the tests failed.
ok?
Index: usr.bin/rcs/co.c
===================================================================
RCS file: /cvs/src/usr.bin/rcs/co.c,v
diff -u -p -u -p -r1.127 co.c
--- usr.bin/rcs/co.c 11 Aug 2023 05:02:21 -0000 1.127
+++ usr.bin/rcs/co.c 8 Jan 2026 04:03:17 -0000
@@ -243,7 +243,6 @@ checkout_rev(RCSFILE *file, RCSNUM *frev
const char *date)
{
BUF *bp;
- u_int i;
int fd, lcount;
char buf[RCS_REV_BUFSZ];
mode_t mode = DEFFILEMODE;
@@ -265,15 +264,10 @@ checkout_rev(RCSFILE *file, RCSNUM *frev
(void)fprintf(stderr,
"no revisions present; generating empty revision 0.0\n");
- /* XXX rcsnum_cmp()
- * Check out the latest revision if <frev> is greater than HEAD
- */
+ /* Check out the latest revision if <frev> is greater than HEAD */
if (file->rf_ndelta != 0) {
- for (i = 0; i < file->rf_head->rn_len; i++) {
- if (file->rf_head->rn_id[i] < frev->rn_id[i]) {
- frev = file->rf_head;
- break;
- }
+ if (rcsnum_cmp(file->rf_head, frev, 0) == 1) {
+ frev = file->rf_head;
}
}
Index: usr.bin/rcs/rcs.c
===================================================================
RCS file: /cvs/src/usr.bin/rcs/rcs.c,v
diff -u -p -u -p -r1.89 rcs.c
--- usr.bin/rcs/rcs.c 28 Nov 2021 19:28:42 -0000 1.89
+++ usr.bin/rcs/rcs.c 8 Jan 2026 04:03:17 -0000
@@ -921,12 +921,9 @@ rcs_getrev(RCSFILE *rfp, RCSNUM *frev)
else
rev = frev;
- /* XXX rcsnum_cmp() */
- for (i = 0; i < rfp->rf_head->rn_len; i++) {
- if (rfp->rf_head->rn_id[i] < rev->rn_id[i]) {
- rcs_errno = RCS_ERR_NOENT;
- return (NULL);
- }
+ if (rcsnum_cmp(rfp->rf_head, rev, 0) == 1) {
+ rcs_errno = RCS_ERR_NOENT;
+ return (NULL);
}
/* No matter what, we'll need everything parsed up until the description
Index: regress/usr.bin/rcs/Makefile
===================================================================
RCS file: /cvs/src/regress/usr.bin/rcs/Makefile,v
diff -u -p -u -p -r1.46 Makefile
--- regress/usr.bin/rcs/Makefile 1 Mar 2022 06:13:17 -0000 1.46
+++ regress/usr.bin/rcs/Makefile 8 Jan 2026 04:03:23 -0000
@@ -76,6 +76,8 @@ LTESTS= ci-initial \
ci-parse-keywords2 \
co-parse-truncated \
ci-2files \
+ rcsdiff-revnum-inequality \
+ co-picks-correct-rev \
.for t in ${LTESTS}
REGRESS_TARGETS+=test-${t}
@@ -632,6 +634,26 @@ test-ci-2files: clean
@test -f foo,v -a ! -f bar,v
@${CI} -q -t-second -l foo bar
@test -f foo,v -a -f bar,v
+
+# Test rcsdiff does not fail after a major revnum jump
+test-rcsdiff-revnum-inequality: clean
+ @echo '1.1' > test
+ @echo '.' | ${CI} -q -l test
+ @echo '1.2' > test
+ @echo '.' | ${CI} -q -l test
+ @echo '2.1' > test
+ @echo '.' | ${CI} -q -r2.1 test
+ @${RCSDIFF} -q -r1.1 -r1.2 test,v >/dev/null || \
+ case "$$?" in 1) exit 0;; esac && exit 1
+
+test-co-picks-correct-rev: clean
+ @echo '1.1' > test
+ @echo '.' | ${CI} -q -l test
+ @echo '1.2' > test
+ @echo '.' | ${CI} -q -l test
+ @echo '2.1' > test
+ @echo '.' | ${CI} -q -r2.1 test
+ @${CO} -q -p1.2 test,v | fgrep -q '1.2'
clean:
@rm -rf ${CLEANFILES}
rcs(1): fix comparisons between selected revision and HEAD