summaryrefslogtreecommitdiffstats
path: root/contrib/cvs/src/rcs.c
diff options
context:
space:
mode:
authorpeter <peter@FreeBSD.org>2002-09-02 05:57:14 +0000
committerpeter <peter@FreeBSD.org>2002-09-02 05:57:14 +0000
commita2b6a3a9b8cf8113c377699deba118c6b57d881e (patch)
tree32949f652e8da27bbd93bd53f3dc7bca126e7e9e /contrib/cvs/src/rcs.c
parent9977823bcf0469bcd2b9a4a936f590610431dc1e (diff)
downloadFreeBSD-src-a2b6a3a9b8cf8113c377699deba118c6b57d881e.zip
FreeBSD-src-a2b6a3a9b8cf8113c377699deba118c6b57d881e.tar.gz
Initial merge of 1.11.1p1 -> 1.11.2 changes onto mainline
Diffstat (limited to 'contrib/cvs/src/rcs.c')
-rw-r--r--contrib/cvs/src/rcs.c249
1 files changed, 197 insertions, 52 deletions
diff --git a/contrib/cvs/src/rcs.c b/contrib/cvs/src/rcs.c
index c7963b415..faa6ee7 100644
--- a/contrib/cvs/src/rcs.c
+++ b/contrib/cvs/src/rcs.c
@@ -15,6 +15,14 @@
#include "edit.h"
#include "hardlink.h"
+/* These need to be source after cvs.h or HAVE_MMAP won't be set... */
+#ifdef HAVE_MMAP
+# include <sys/mman.h>
+# ifndef HAVE_GETPAGESIZE
+# include "getpagesize.h"
+# endif
+#endif
+
int preserve_perms = 0;
/* The RCS -k options, and a set of enums that must match the array.
@@ -60,8 +68,10 @@ static void rcsbuf_close PROTO ((struct rcsbuffer *));
static int rcsbuf_getkey PROTO ((struct rcsbuffer *, char **keyp,
char **valp));
static int rcsbuf_getrevnum PROTO ((struct rcsbuffer *, char **revp));
+#ifndef HAVE_MMAP
static char *rcsbuf_fill PROTO ((struct rcsbuffer *, char *ptr, char **keyp,
char **valp));
+#endif
static int rcsbuf_valcmp PROTO ((struct rcsbuffer *));
static char *rcsbuf_valcopy PROTO ((struct rcsbuffer *, char *val, int polish,
size_t *lenp));
@@ -734,8 +744,8 @@ RCS_fully_parse (rcs)
vers = findnode (rcs->versions, key);
if (vers == NULL)
error (1, 0,
- "mismatch in rcs file %s between deltas and deltatexts",
- rcs->path);
+ "mismatch in rcs file %s between deltas and deltatexts (%s)",
+ rcs->path, key);
vnode = (RCSVers *) vers->data;
@@ -793,12 +803,12 @@ unrecognized operation '\\x%x' in %s",
op, rcs->path);
(void) strtoul (cp, (char **) &cp, 10);
if (*cp++ != ' ')
- error (1, 0, "space expected in %s",
- rcs->path);
+ error (1, 0, "space expected in %s revision %s",
+ rcs->path, vnode->version);
count = strtoul (cp, (char **) &cp, 10);
if (*cp++ != '\012')
- error (1, 0, "linefeed expected in %s",
- rcs->path);
+ error (1, 0, "linefeed expected in %s revision %s",
+ rcs->path, vnode->version);
if (op == 'd')
del += count;
@@ -813,8 +823,8 @@ unrecognized operation '\\x%x' in %s",
{
if (count != 1)
error (1, 0, "\
-invalid rcs file %s: premature end of value",
- rcs->path);
+premature end of value in %s revision %s",
+ rcs->path, vnode->version);
else
break;
}
@@ -991,14 +1001,45 @@ rcsbuf_open (rcsbuf, fp, filename, pos)
error (1, 0, "rcsbuf_open: internal error");
rcsbuf_inuse = 1;
+#ifdef HAVE_MMAP
+ {
+ /* When we have mmap, it is much more efficient to let the system do the
+ * buffering and caching for us
+ */
+ struct stat fs;
+ size_t mmap_off = 0;
+
+ if ( fstat (fileno(fp), &fs) < 0 )
+ error ( 1, errno, "Could not stat RCS archive %s for mapping", filename );
+
+ if (pos)
+ {
+ size_t ps = getpagesize ();
+ mmap_off = ( pos / ps ) * ps;
+ }
+
+ /* Map private here since this particular buffer is read only */
+ rcsbuf_buffer = mmap ( NULL, fs.st_size - mmap_off,
+ PROT_READ | PROT_WRITE,
+ MAP_PRIVATE, fileno(fp), mmap_off );
+ if ( rcsbuf_buffer == NULL || rcsbuf_buffer == MAP_FAILED )
+ error ( 1, errno, "Could not map memory to RCS archive %s", filename );
+
+ rcsbuf_buffer_size = fs.st_size - mmap_off;
+ rcsbuf->ptr = rcsbuf_buffer + pos - mmap_off;
+ rcsbuf->ptrend = rcsbuf_buffer + fs.st_size - mmap_off;
+ rcsbuf->pos = mmap_off;
+ }
+#else /* HAVE_MMAP */
if (rcsbuf_buffer_size < RCSBUF_BUFSIZE)
expand_string (&rcsbuf_buffer, &rcsbuf_buffer_size, RCSBUF_BUFSIZE);
rcsbuf->ptr = rcsbuf_buffer;
rcsbuf->ptrend = rcsbuf_buffer;
+ rcsbuf->pos = pos;
+#endif /* HAVE_MMAP */
rcsbuf->fp = fp;
rcsbuf->filename = filename;
- rcsbuf->pos = pos;
rcsbuf->vlen = 0;
rcsbuf->at_string = 0;
rcsbuf->embedded_at = 0;
@@ -1012,6 +1053,9 @@ rcsbuf_close (rcsbuf)
{
if (! rcsbuf_inuse)
error (1, 0, "rcsbuf_close: internal error");
+#ifdef HAVE_MMAP
+ munmap ( rcsbuf_buffer, rcsbuf_buffer_size );
+#endif
rcsbuf_inuse = 0;
}
@@ -1052,9 +1096,9 @@ rcsbuf_getkey (rcsbuf, keyp, valp)
ptrend = rcsbuf->ptrend;
/* Sanity check. */
- if (ptr < rcsbuf_buffer || ptr > rcsbuf_buffer + rcsbuf_buffer_size)
- abort ();
+ assert (ptr >= rcsbuf_buffer && ptr < rcsbuf_buffer + rcsbuf_buffer_size);
+#ifndef HAVE_MMAP
/* If the pointer is more than RCSBUF_BUFSIZE bytes into the
buffer, move back to the start of the buffer. This keeps the
buffer from growing indefinitely. */
@@ -1066,8 +1110,7 @@ rcsbuf_getkey (rcsbuf, keyp, valp)
/* Sanity check: we don't read more than RCSBUF_BUFSIZE bytes
at a time, so we can't have more bytes than that past PTR. */
- if (len > RCSBUF_BUFSIZE)
- abort ();
+ assert (len <= RCSBUF_BUFSIZE);
/* Update the POS field, which holds the file offset of the
first byte in the RCSBUF_BUFFER buffer. */
@@ -1078,18 +1121,23 @@ rcsbuf_getkey (rcsbuf, keyp, valp)
ptrend = ptr + len;
rcsbuf->ptrend = ptrend;
}
+#endif /* ndef HAVE_MMAP */
/* Skip leading whitespace. */
while (1)
{
if (ptr >= ptrend)
+#ifndef HAVE_MMAP
{
ptr = rcsbuf_fill (rcsbuf, ptr, (char **) NULL, (char **) NULL);
if (ptr == NULL)
+#endif
return 0;
+#ifndef HAVE_MMAP
ptrend = rcsbuf->ptrend;
}
+#endif
c = *ptr;
if (! my_whitespace (c))
@@ -1108,13 +1156,17 @@ rcsbuf_getkey (rcsbuf, keyp, valp)
{
++ptr;
if (ptr >= ptrend)
+#ifndef HAVE_MMAP
{
ptr = rcsbuf_fill (rcsbuf, ptr, keyp, (char **) NULL);
if (ptr == NULL)
+#endif
error (1, 0, "EOF in key in RCS file %s",
rcsbuf->filename);
+#ifndef HAVE_MMAP
ptrend = rcsbuf->ptrend;
}
+#endif
c = *ptr;
if (c == ';' || my_whitespace (c))
break;
@@ -1143,13 +1195,17 @@ rcsbuf_getkey (rcsbuf, keyp, valp)
while (1)
{
if (ptr >= ptrend)
+#ifndef HAVE_MMAP
{
ptr = rcsbuf_fill (rcsbuf, ptr, keyp, (char **) NULL);
if (ptr == NULL)
+#endif
error (1, 0, "EOF while looking for value in RCS file %s",
rcsbuf->filename);
+#ifndef HAVE_MMAP
ptrend = rcsbuf->ptrend;
}
+#endif
c = *ptr;
if (c == ';')
{
@@ -1184,6 +1240,7 @@ rcsbuf_getkey (rcsbuf, keyp, valp)
while (1)
{
while ((pat = memchr (ptr, '@', ptrend - ptr)) == NULL)
+#ifndef HAVE_MMAP
{
/* Note that we pass PTREND as the PTR value to
rcsbuf_fill, so that we will wind up setting PTR to
@@ -1191,25 +1248,31 @@ rcsbuf_getkey (rcsbuf, keyp, valp)
that we don't search the same bytes again. */
ptr = rcsbuf_fill (rcsbuf, ptrend, keyp, valp);
if (ptr == NULL)
+#endif
error (1, 0,
"EOF while looking for end of string in RCS file %s",
rcsbuf->filename);
+#ifndef HAVE_MMAP
ptrend = rcsbuf->ptrend;
}
+#endif
/* Handle the special case of an '@' right at the end of
the known bytes. */
if (pat + 1 >= ptrend)
+#ifndef HAVE_MMAP
{
/* Note that we pass PAT, not PTR, here. */
pat = rcsbuf_fill (rcsbuf, pat, keyp, valp);
if (pat == NULL)
{
+#endif
/* EOF here is OK; it just means that the last
character of the file was an '@' terminating a
value for a key type which does not require a
trailing ';'. */
pat = rcsbuf->ptrend - 1;
+#ifndef HAVE_MMAP
}
ptrend = rcsbuf->ptrend;
@@ -1217,6 +1280,7 @@ rcsbuf_getkey (rcsbuf, keyp, valp)
/* Note that the value of PTR is bogus here. This is
OK, because we don't use it. */
}
+#endif
if (pat + 1 >= ptrend || pat[1] != '@')
break;
@@ -1266,13 +1330,17 @@ rcsbuf_getkey (rcsbuf, keyp, valp)
char n;
if (ptr >= ptrend)
+#ifndef HAVE_MMAP
{
ptr = rcsbuf_fill (rcsbuf, ptr, keyp, valp);
if (ptr == NULL)
+#endif
error (1, 0, "EOF in value in RCS file %s",
rcsbuf->filename);
+#ifndef HAVE_MMAP
ptrend = rcsbuf->ptrend;
}
+#endif
n = *ptr;
if (n == ';')
{
@@ -1307,6 +1375,7 @@ rcsbuf_getkey (rcsbuf, keyp, valp)
/* Find the ';' which must end the value. */
start = ptr;
while ((psemi = memchr (ptr, ';', ptrend - ptr)) == NULL)
+#ifndef HAVE_MMAP
{
int slen;
@@ -1317,10 +1386,13 @@ rcsbuf_getkey (rcsbuf, keyp, valp)
slen = start - *valp;
ptr = rcsbuf_fill (rcsbuf, ptrend, keyp, valp);
if (ptr == NULL)
+#endif
error (1, 0, "EOF in value in RCS file %s", rcsbuf->filename);
+#ifndef HAVE_MMAP
start = *valp + slen;
ptrend = rcsbuf->ptrend;
}
+#endif
/* See if there are any '@' strings in the value. */
pat = memchr (start, '@', psemi - start);
@@ -1364,6 +1436,7 @@ rcsbuf_getkey (rcsbuf, keyp, valp)
while (1)
{
while ((pat = memchr (ptr, '@', ptrend - ptr)) == NULL)
+#ifndef HAVE_MMAP
{
/* Note that we pass PTREND as the PTR value to
rcsbuff_fill, so that we will wind up setting PTR
@@ -1371,22 +1444,29 @@ rcsbuf_getkey (rcsbuf, keyp, valp)
that we don't search the same bytes again. */
ptr = rcsbuf_fill (rcsbuf, ptrend, keyp, valp);
if (ptr == NULL)
+#endif
error (1, 0,
"EOF while looking for end of string in RCS file %s",
rcsbuf->filename);
+#ifndef HAVE_MMAP
ptrend = rcsbuf->ptrend;
}
+#endif
/* Handle the special case of an '@' right at the end of
the known bytes. */
if (pat + 1 >= ptrend)
+#ifndef HAVE_MMAP
{
ptr = rcsbuf_fill (rcsbuf, ptr, keyp, valp);
if (ptr == NULL)
+#endif
error (1, 0, "EOF in value in RCS file %s",
rcsbuf->filename);
+#ifndef HAVE_MMAP
ptrend = rcsbuf->ptrend;
}
+#endif
if (pat[1] != '@')
break;
@@ -1429,12 +1509,16 @@ rcsbuf_getrevnum (rcsbuf, revp)
while (1)
{
if (ptr >= ptrend)
+#ifndef HAVE_MMAP
{
ptr = rcsbuf_fill (rcsbuf, ptr, (char **) NULL, (char **) NULL);
if (ptr == NULL)
+#endif
return 0;
+#ifndef HAVE_MMAP
ptrend = rcsbuf->ptrend;
}
+#endif
c = *ptr;
if (! whitespace (c))
@@ -1455,14 +1539,18 @@ unexpected '\\x%x' reading revision number in RCS file %s",
{
++ptr;
if (ptr >= ptrend)
+#ifndef HAVE_MMAP
{
ptr = rcsbuf_fill (rcsbuf, ptr, revp, (char **) NULL);
if (ptr == NULL)
+#endif
error (1, 0,
"unexpected EOF reading revision number in RCS file %s",
rcsbuf->filename);
+#ifndef HAVE_MMAP
ptrend = rcsbuf->ptrend;
}
+#endif
c = *ptr;
}
@@ -1480,6 +1568,7 @@ unexpected '\\x%x' reading revision number in RCS file %s",
return 1;
}
+#ifndef HAVE_MMAP
/* Fill RCSBUF_BUFFER with bytes from the file associated with RCSBUF,
updating PTR and the PTREND field. If KEYP and *KEYP are not NULL,
then *KEYP points into the buffer, and must be adjusted if the
@@ -1531,6 +1620,7 @@ rcsbuf_fill (rcsbuf, ptr, keyp, valp)
return ptr;
}
+#endif /* HAVE_MMAP */
/* Test whether the last value returned by rcsbuf_getkey is a composite
value or not. */
@@ -1687,7 +1777,19 @@ rcsbuf_valpolish_internal (rcsbuf, to, from, lenp)
{
++from;
- /* Sanity check. */
+ /* Sanity check.
+ *
+ * FIXME: I restored this to an abort from an assert based on
+ * advice from Larry Jones that asserts should not be used to
+ * confirm the validity of an RCS file... This leaves two
+ * issues here: 1) I am uncertain that the fact that we will
+ * only find double '@'s hasn't already been confirmed; and:
+ * 2) If this is the proper place to spot the error in the RCS
+ * file, then we should print a much clearer error here for the
+ * user!!!!!!!
+ *
+ * - DRP
+ */
if (*from != '@' || clen == 0)
abort ();
@@ -1711,11 +1813,8 @@ rcsbuf_valpolish_internal (rcsbuf, to, from, lenp)
}
/* Sanity check. */
- if (from != orig_from + len
- || to != orig_to + (len - rcsbuf->embedded_at))
- {
- abort ();
- }
+ assert (from == orig_from + len
+ && to == orig_to + (len - rcsbuf->embedded_at));
*to = '\0';
}
@@ -1736,7 +1835,7 @@ rcsbuf_valword (rcsbuf, valp)
register char *ptr, *pat;
char c;
-#define my_whitespace(c) (my_spacetab[(unsigned char)c] != 0)
+# define my_whitespace(c) (my_spacetab[(unsigned char)c] != 0)
if (*valp == NULL)
return NULL;
@@ -1794,7 +1893,7 @@ rcsbuf_valword (rcsbuf, valp)
or an id. Make sure it is not another special character. */
if (c == '$' || c == '.' || c == ',')
{
- error (1, 0, "illegal special character in RCS field in %s",
+ error (1, 0, "invalid special character in RCS field in %s",
rcsbuf->filename);
}
@@ -1814,7 +1913,7 @@ rcsbuf_valword (rcsbuf, valp)
the character in its memory cell. Check to make sure that it
is a legitimate word delimiter -- whitespace or end. */
if (c != '\0' && !my_whitespace (c))
- error (1, 0, "illegal special character in RCS field in %s",
+ error (1, 0, "invalid special character in RCS field in %s",
rcsbuf->filename);
*pat = '\0';
@@ -1822,7 +1921,7 @@ rcsbuf_valword (rcsbuf, valp)
*valp = pat;
return xstrdup (ptr);
-#undef my_whitespace
+# undef my_whitespace
}
#endif
@@ -1833,7 +1932,7 @@ static unsigned long
rcsbuf_ftell (rcsbuf)
struct rcsbuffer *rcsbuf;
{
- return rcsbuf->pos + (rcsbuf->ptr - rcsbuf_buffer);
+ return rcsbuf->pos + rcsbuf->ptr - rcsbuf_buffer;
}
/* Return a pointer to any data buffered for RCSBUF, along with the
@@ -1880,9 +1979,9 @@ rcsbuf_cache_close ()
{
if (cached_rcs != NULL)
{
+ rcsbuf_close (&cached_rcsbuf);
if (fclose (cached_rcsbuf.fp) != 0)
error (0, errno, "cannot close %s", cached_rcsbuf.filename);
- rcsbuf_close (&cached_rcsbuf);
freercsnode (&cached_rcs);
cached_rcs = NULL;
}
@@ -1899,6 +1998,7 @@ rcsbuf_cache_open (rcs, pos, pfp, prcsbuf)
FILE **pfp;
struct rcsbuffer *prcsbuf;
{
+#ifndef HAVE_MMAP
if (cached_rcs == rcs)
{
if (rcsbuf_ftell (&cached_rcsbuf) != pos)
@@ -1929,19 +2029,32 @@ rcsbuf_cache_open (rcs, pos, pfp, prcsbuf)
}
else
{
+#endif /* ifndef HAVE_MMAP */
+ /* FIXME: If these routines can be rewritten to not write to the
+ * rcs file buffer, there would be a considerably larger memory savings
+ * from using mmap since the shared file would never need be copied to
+ * process memory.
+ *
+ * If this happens, cached mmapped buffers would be usable, but don't
+ * forget to make sure rcs->pos < pos here...
+ */
if (cached_rcs != NULL)
rcsbuf_cache_close ();
*pfp = CVS_FOPEN (rcs->path, FOPEN_BINARY_READ);
if (*pfp == NULL)
error (1, 0, "unable to reopen `%s'", rcs->path);
+#ifndef HAVE_MMAP
if (pos != 0)
{
if (fseek (*pfp, pos, SEEK_SET) != 0)
error (1, 0, "cannot fseek RCS file %s", rcs->path);
}
+#endif /* ifndef HAVE_MMAP */
rcsbuf_open (prcsbuf, *pfp, rcs->path, pos);
+#ifndef HAVE_MMAP
}
+#endif /* ifndef HAVE_MMAP */
}
@@ -2239,7 +2352,7 @@ RCS_gettag (rcs, symtag, force_tag_match, simple_tag)
RCS_reparsercsfile (rcs, (FILE **) NULL, (struct rcsbuffer *) NULL);
/* If tag is "HEAD", special case to get head RCS revision */
- if (tag && (STREQ (tag, TAG_HEAD) || *tag == '\0'))
+ if (tag && STREQ (tag, TAG_HEAD))
#if 0 /* This #if 0 is only in the Cygnus code. Why? Death support? */
if (force_tag_match && (rcs->flags & VALID) && (rcs->flags & INATTIC))
return ((char *) NULL); /* head request for removed file */
@@ -2848,16 +2961,21 @@ RCS_getdate (rcs, date, force_tag_match)
/* if the head is on a branch, try the branch first */
if (rcs->branch != NULL)
+ {
retval = RCS_getdatebranch (rcs, date, rcs->branch);
-
- /* if we found a match, we are done */
- if (retval != NULL)
- return (retval);
+ if (retval != NULL)
+ return (retval);
+ }
/* otherwise if we have a trunk, try it */
if (rcs->head)
{
p = findnode (rcs->versions, rcs->head);
+ if (p == NULL)
+ {
+ error (0, 0, "%s: head revision %s doesn't exist", rcs->path,
+ rcs->head);
+ }
while (p != NULL)
{
/* if the date of this one is before date, take it */
@@ -2875,10 +2993,13 @@ RCS_getdate (rcs, date, force_tag_match)
p = (Node *) NULL;
}
}
+ else
+ error (0, 0, "%s: no head revision", rcs->path);
/*
* at this point, either we have the revision we want, or we have the
- * first revision on the trunk (1.1?) in our hands
+ * first revision on the trunk (1.1?) in our hands, or we've come up
+ * completely empty
*/
/* if we found what we're looking for, and it's not 1.1 return it */
@@ -2913,7 +3034,8 @@ RCS_getdate (rcs, date, force_tag_match)
if (retval != NULL)
return (retval);
- if (!force_tag_match || RCS_datecmp (vers->date, date) <= 0)
+ if (!force_tag_match ||
+ (vers != NULL && RCS_datecmp (vers->date, date) <= 0))
return (xstrdup (vers->version));
else
return (NULL);
@@ -3186,6 +3308,8 @@ translate_symtag (rcs, tag)
while (! whitespace (*cp) && *cp != '\0')
++cp;
+ if (*cp == '\0')
+ break;
}
}
@@ -4267,7 +4391,7 @@ RCS_checkout (rcs, workfile, rev, nametag, options, sout, pfn, callerdat)
/* If the size of `devtype' changes, fix the sscanf call also */
char devtype[16];
- if (sscanf (info->data, "%16s %lu",
+ if (sscanf (info->data, "%15s %lu",
devtype, &devnum_long) < 2)
error (1, 0, "%s:%s has bad `special' newphrase %s",
workfile, vers->version, info->data);
@@ -4332,7 +4456,7 @@ RCS_checkout (rcs, workfile, rev, nametag, options, sout, pfn, callerdat)
#ifdef PRESERVE_PERMISSIONS_SUPPORT
else if (special_file)
{
-#ifdef HAVE_MKNOD
+# ifdef HAVE_MKNOD
char *dest;
/* Can send either to WORKFILE or to SOUT, as long as SOUT is
@@ -4353,11 +4477,11 @@ RCS_checkout (rcs, workfile, rev, nametag, options, sout, pfn, callerdat)
if (mknod (dest, special_file, devnum) < 0)
error (1, errno, "could not create special file %s",
dest);
-#else
+# else
error (1, 0,
"cannot create %s: unable to create special files on this system",
workfile);
-#endif
+# endif
}
#endif
else
@@ -4960,7 +5084,7 @@ RCS_checkin (rcs, workfile, message, rev, flags)
case S_IFREG: break;
case S_IFCHR:
case S_IFBLK:
-#ifdef HAVE_ST_RDEV
+# ifdef HAVE_ST_RDEV
np = getnode();
np->type = RCSFIELD;
np->key = xstrdup ("special");
@@ -4970,11 +5094,11 @@ RCS_checkin (rcs, workfile, message, rev, flags)
(unsigned long) sb.st_rdev);
np->data = xstrdup (buf);
addnode (delta->other_delta, np);
-#else
+# else
error (0, 0,
"can't preserve %s: unable to save device files on this system",
workfile);
-#endif
+# endif
break;
default:
@@ -5825,7 +5949,9 @@ RCS_unlock (rcs, rev, unlock_quiet)
if (rcs->flags & PARTIAL)
RCS_reparsercsfile (rcs, (FILE **) NULL, (struct rcsbuffer *) NULL);
- /* If rev is NULL, unlock the latest revision (first in
+ /* If rev is NULL, unlock the revision held by the caller; if more
+ than one, make the user specify the revision explicitly. This
+ differs from RCS which unlocks the latest revision (first in
rcs->locks) held by the caller. */
if (rev == NULL)
{
@@ -5850,17 +5976,24 @@ RCS_unlock (rcs, rev, unlock_quiet)
lock = NULL;
for (p = locks->list->next; p != locks->list; p = p->next)
{
- if (lock != NULL)
+ if (STREQ (p->data, user))
{
- if (!unlock_quiet)
- error (0, 0, "\
+ if (lock != NULL)
+ {
+ if (!unlock_quiet)
+ error (0, 0, "\
%s: multiple revisions locked by %s; please specify one", rcs->path, user);
- return 1;
+ return 1;
+ }
+ lock = p;
}
- lock = p;
}
if (lock == NULL)
+ {
+ if (!unlock_quiet)
+ error (0, 0, "No locks are set for %s.\n", user);
return 0; /* no lock found, ergo nothing to do */
+ }
xrev = xstrdup (lock->key);
}
else
@@ -5888,6 +6021,9 @@ RCS_unlock (rcs, rev, unlock_quiet)
is called with a NULL revision, since that means "whatever
revision is currently locked by the caller." */
char *repos, *workfile;
+ if (!unlock_quiet)
+ error (0, 0, "\
+%s: revision %s locked by %s; breaking lock", rcs->path, xrev, lock->data);
repos = xstrdup (rcs->path);
workfile = strrchr (repos, '/');
*workfile++ = '\0';
@@ -7109,8 +7245,8 @@ RCS_deltas (rcs, fp, rcsbuf, version, op, text, len, log, loglen)
node = findnode (rcs->versions, key);
if (node == NULL)
error (1, 0,
- "mismatch in rcs file %s between deltas and deltatexts",
- rcs->path);
+ "mismatch in rcs file %s between deltas and deltatexts (%s)",
+ rcs->path, key);
/* Stash the previous version. */
prev_vers = vers;
@@ -7602,8 +7738,8 @@ RCS_getdeltatext (rcs, fp, rcsbuf)
p = findnode (rcs->versions, num);
if (p == NULL)
- error (1, 0, "mismatch in rcs file %s between deltas and deltatexts",
- rcs->path);
+ error (1, 0, "mismatch in rcs file %s between deltas and deltatexts (%s)",
+ rcs->path, num);
d = (Deltatext *) xmalloc (sizeof (Deltatext));
d->version = xstrdup (num);
@@ -7963,8 +8099,10 @@ RCS_copydeltas (rcs, fin, rcsbufin, fout, newdtext, insertpt)
char *bufrest;
int nls;
size_t buflen;
+#ifndef HAVE_MMAP
char buf[8192];
int got;
+#endif
/* Count the number of versions for which we have to do some
special operation. */
@@ -8073,7 +8211,12 @@ RCS_copydeltas (rcs, fin, rcsbufin, fout, newdtext, insertpt)
fwrite (bufrest, 1, buflen, fout);
}
-
+#ifndef HAVE_MMAP
+ /* This bit isn't necessary when using mmap since the entire file
+ * will already be available via the RCS buffer. Besides, the
+ * mmap code doesn't always keep the file pointer up to date, so
+ * this adds some data twice.
+ */
while ((got = fread (buf, 1, sizeof buf, fin)) != 0)
{
if (nls > 0
@@ -8090,6 +8233,7 @@ RCS_copydeltas (rcs, fin, rcsbufin, fout, newdtext, insertpt)
nls = 0;
}
+#endif /* HAVE_MMAP */
}
/* A helper procedure for RCS_copydeltas. This is called via walklist
@@ -8351,7 +8495,8 @@ RCS_rewrite (rcs, newdtext, insertpt)
/* Update delta_pos to the current position in the output file.
Do NOT move these statements: they must be done after fin has
been positioned at the old delta_pos, but before any delta
- texts have been written to fout. */
+ texts have been written to fout.
+ */
rcs->delta_pos = ftell (fout);
if (rcs->delta_pos == -1)
error (1, errno, "cannot ftell in RCS file %s", rcs->path);
@@ -8368,7 +8513,7 @@ RCS_rewrite (rcs, newdtext, insertpt)
fragile even if it happens to sometimes be true. The real
solution is to make sure that all the code which reads
from fin checks for errors itself (some does, some doesn't). */
- error (0, 0, "warning: when closing RCS file `%s'", rcs->path);
+ error (0, 0, "warning: ferror set while rewriting RCS file `%s'", rcs->path);
if (fclose (fin) < 0)
error (0, errno, "warning: closing RCS file `%s'", rcs->path);
OpenPOWER on IntegriCloud