summaryrefslogtreecommitdiffstats
path: root/contrib/cvs/src/subr.c
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/cvs/src/subr.c')
-rw-r--r--contrib/cvs/src/subr.c100
1 files changed, 80 insertions, 20 deletions
diff --git a/contrib/cvs/src/subr.c b/contrib/cvs/src/subr.c
index 07d516f..6a97f28 100644
--- a/contrib/cvs/src/subr.c
+++ b/contrib/cvs/src/subr.c
@@ -16,7 +16,7 @@ extern char *getlogin ();
/*
* malloc some data and die if it fails
*/
-char *
+void *
xmalloc (bytes)
size_t bytes;
{
@@ -30,8 +30,12 @@ xmalloc (bytes)
cp = malloc (bytes);
if (cp == NULL)
- error (1, 0, "out of memory; can not allocate %lu bytes",
- (unsigned long) bytes);
+ {
+ char buf[80];
+ sprintf (buf, "out of memory; can not allocate %lu bytes",
+ (unsigned long) bytes);
+ error (1, 0, buf);
+ }
return (cp);
}
@@ -53,7 +57,12 @@ xrealloc (ptr, bytes)
cp = realloc (ptr, bytes);
if (cp == NULL)
- error (1, 0, "can not reallocate %lu bytes", (unsigned long) bytes);
+ {
+ char buf[80];
+ sprintf (buf, "out of memory; can not reallocate %lu bytes",
+ (unsigned long) bytes);
+ error (1, 0, buf);
+ }
return (cp);
}
@@ -64,7 +73,11 @@ xrealloc (ptr, bytes)
memory which is likely to get as big as MAX_INCR shouldn't be doing
it in one block which must be contiguous, but since getrcskey does
so, we might as well limit the wasted memory to MAX_INCR or so
- bytes. */
+ bytes.
+
+ MIN_INCR and MAX_INCR should both be powers of two and we generally
+ try to keep our allocations to powers of two for the most part.
+ Most malloc implementations these days tend to like that. */
#define MIN_INCR 1024
#define MAX_INCR (2*1024*1024)
@@ -84,11 +97,15 @@ expand_string (strptr, n, newsize)
while (*n < newsize)
{
if (*n < MIN_INCR)
- *n += MIN_INCR;
- else if (*n > MAX_INCR)
+ *n = MIN_INCR;
+ else if (*n >= MAX_INCR)
*n += MAX_INCR;
else
+ {
*n *= 2;
+ if (*n > MAX_INCR)
+ *n = MAX_INCR;
+ }
}
*strptr = xrealloc (*strptr, *n);
}
@@ -487,7 +504,7 @@ check_numeric (rev, argc, argv)
int argc;
char **argv;
{
- if (rev == NULL || !isdigit (*rev))
+ if (rev == NULL || !isdigit ((unsigned char) *rev))
return;
/* Note that the check for whether we are processing more than one
@@ -534,7 +551,7 @@ make_message_rcslegal (message)
}
/* Backtrack to last non-space at end of string, and truncate. */
- while (dp > dst && isspace (dp[-1]))
+ while (dp > dst && isspace ((unsigned char) dp[-1]))
--dp;
*dp = '\0';
@@ -615,15 +632,14 @@ get_file (name, fullname, mode, buf, bufsize, len)
}
else
{
- if (CVS_LSTAT (name, &s) < 0)
- error (1, errno, "can't stat %s", fullname);
+ /* Although it would be cleaner in some ways to just read
+ until end of file, reallocating the buffer, this function
+ does get called on files in the working directory which can
+ be of arbitrary size, so I think we better do all that
+ extra allocation. */
- /* Don't attempt to read special files or symlinks. */
- if (!S_ISREG (s.st_mode))
- {
- *len = 0;
- return;
- }
+ if (CVS_STAT (name, &s) < 0)
+ error (1, errno, "can't stat %s", fullname);
/* Convert from signed to unsigned. */
filesize = s.st_size;
@@ -652,9 +668,7 @@ get_file (name, fullname, mode, buf, bufsize, len)
if (feof (e))
break;
- /* It's probably paranoid to think S.ST_SIZE might be
- too small to hold the entire file contents, but we
- handle it just in case. */
+ /* Allocate more space if needed. */
if (tobuf == *buf + *bufsize)
{
int c;
@@ -684,3 +698,49 @@ get_file (name, fullname, mode, buf, bufsize, len)
(*buf)[nread] = '\0';
}
}
+
+
+/* Follow a chain of symbolic links to its destination. FILENAME
+ should be a handle to a malloc'd block of memory which contains the
+ beginning of the chain. This routine will replace the contents of
+ FILENAME with the destination (a real file). */
+
+void
+resolve_symlink (filename)
+ char **filename;
+{
+ if ((! filename) || (! *filename))
+ return;
+
+ while (islink (*filename))
+ {
+ char *newname;
+#ifdef HAVE_READLINK
+ /* The clean thing to do is probably to have each filesubr.c
+ implement this (with an error if not supported by the
+ platform, in which case islink would presumably return 0).
+ But that would require editing each filesubr.c and so the
+ expedient hack seems to be looking at HAVE_READLINK. */
+ newname = xreadlink (*filename);
+#else
+ error (1, 0, "internal error: islink doesn't like readlink");
+#endif
+
+ if (isabsolute (newname))
+ {
+ free (*filename);
+ *filename = newname;
+ }
+ else
+ {
+ char *oldname = last_component (*filename);
+ int dirlen = oldname - *filename;
+ char *fullnewname = xmalloc (dirlen + strlen (newname) + 1);
+ strncpy (fullnewname, *filename, dirlen);
+ strcpy (fullnewname + dirlen, newname);
+ free (newname);
+ free (*filename);
+ *filename = fullnewname;
+ }
+ }
+}
OpenPOWER on IntegriCloud