summaryrefslogtreecommitdiff
path: root/usr.bin/rcs/ci.c
diff options
context:
space:
mode:
Diffstat (limited to 'usr.bin/rcs/ci.c')
-rw-r--r--usr.bin/rcs/ci.c148
1 files changed, 105 insertions, 43 deletions
diff --git a/usr.bin/rcs/ci.c b/usr.bin/rcs/ci.c
index d3028ba23fa..ad2e9f88323 100644
--- a/usr.bin/rcs/ci.c
+++ b/usr.bin/rcs/ci.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ci.c,v 1.115 2006/03/11 22:44:11 niallo Exp $ */
+/* $OpenBSD: ci.c,v 1.116 2006/03/14 03:33:30 ray Exp $ */
/*
* Copyright (c) 2005, 2006 Niall O'Higgins <niallo@openbsd.org>
* All rights reserved.
@@ -840,64 +840,126 @@ checkin_mtimedate(struct checkin_params *pb)
/*
* checkin_choose_rcsfile()
*
- * Given a relative filename, decide where the corresponding ,v file
- * should be.
+ * Given a relative filename, decide where the corresponding RCS file
+ * should be. Tries each extension until a file is found. If no file
+ * was found, returns a path with the first extension.
*
* Returns pointer to a char array on success, NULL on failure.
*/
static char *
checkin_choose_rcsfile(const char *filename)
{
- char name[MAXPATHLEN], *basepath;
- const char *ptr;
- size_t len;
struct stat sb;
+ char *ext, name[MAXPATHLEN], *next, *ptr, rcsdir[MAXPATHLEN],
+ *ret, *suffixes, rcspath[MAXPATHLEN];
- basepath = xmalloc(MAXPATHLEN);
- basepath[0] = '\0';
- if (strchr(filename, '/') == NULL) {
- strlcat(basepath, RCSDIR"/", MAXPATHLEN);
- if ((stat(basepath, &sb) == 0) && (sb.st_mode & S_IFDIR)) {
- /* <path>/RCS/<filename>,v */
- strlcat(basepath, filename, MAXPATHLEN);
- strlcat(basepath, RCS_FILE_EXT, MAXPATHLEN);
- } else {
- /* <path>/<filename>,v */
- strlcpy(basepath, filename, MAXPATHLEN);
- strlcat(basepath, RCS_FILE_EXT, MAXPATHLEN);
- }
+ /* If -x flag was not given, use default. */
+ if (rcs_suffixes == NULL)
+ rcs_suffixes = RCS_DEFAULT_SUFFIX;
+
+ /*
+ * If `filename' contains a directory, `rcspath' contains that
+ * directory, including a trailing slash. Otherwise `rcspath'
+ * contains an empty string.
+ */
+ if (strlcpy(rcspath, filename, sizeof(rcspath)) >= sizeof(rcspath))
+ return (NULL);
+ /* If `/' is found, end string after `/'. */
+ if ((ptr = strrchr(rcspath, '/')) != NULL)
+ *(++ptr) = '\0';
+ else
+ rcspath[0] = '\0';
+
+ /* Append RCS/ to `rcspath' if it exists. */
+ if (strlcpy(rcsdir, rcspath, sizeof(rcsdir)) >= sizeof(rcsdir) ||
+ strlcat(rcsdir, RCSDIR, sizeof(rcsdir)) >= sizeof(rcsdir))
+ return (NULL);
+ if ((stat(rcsdir, &sb) == 0) && (sb.st_mode & S_IFDIR))
+ if (strlcpy(rcspath, rcsdir, sizeof(rcspath)) >= sizeof(rcspath) ||
+ strlcat(rcspath, "/", sizeof(rcspath)) >= sizeof(rcspath))
+ return (NULL);
+
+ /* Name of file without path. */
+ if ((ptr = strrchr(filename, '/')) == NULL) {
+ if (strlcpy(name, filename, sizeof(name)) >= sizeof(name))
+ return (NULL);
} else {
- ptr = filename;
- /* Walk backwards till we find the base directory */
- len = strlen(filename);
- ptr += len + 1;
- while (filename[len] != '/') {
- len--;
- ptr--;
+ /* Skip `/'. */
+ if (strlcpy(name, ptr + 1, sizeof(name)) >= sizeof(name))
+ return (NULL);
+ }
+
+ /* Name of RCS file without an extension. */
+ if (strlcat(rcspath, name, sizeof(rcspath)) >= sizeof(rcspath))
+ return (NULL);
+
+ /*
+ * If only the empty suffix was given, use existing rcspath.
+ * This ensures that there is at least one suffix for strsep().
+ */
+ if (strcmp(rcs_suffixes, "") == 0) {
+ if ((ret = strdup(rcspath)) == NULL);
+ fatal("out of memory");
+ return (ret);
+ }
+
+ /*
+ * Cycle through slash-separated `rcs_suffixes', appending each
+ * extension to `rcspath' and testing if the file exists. If it
+ * does, return that string. Otherwise return path with first
+ * extension.
+ */
+ if ((suffixes = strdup(rcs_suffixes)) == NULL)
+ fatal("out of memory");
+ for (ret = NULL, next = suffixes; (ext = strsep(&next, "/")) != NULL;) {
+ char fpath[MAXPATHLEN];
+
+ /* Construct RCS file path. */
+ if (strlcpy(fpath, rcspath, sizeof(fpath)) >= sizeof(fpath) ||
+ strlcat(fpath, ext, sizeof(fpath)) >= sizeof(fpath)) {
+ xfree(suffixes);
+ return (NULL);
+ }
+
+ /* Don't use `filename' as RCS file. */
+ if (strcmp(fpath, filename) == 0)
+ continue;
+
+ if (stat(fpath, &sb) == 0) {
+ if ((ret = strdup(fpath)) == NULL)
+ fatal("out of memory");
+ break;
}
+ }
+ xfree(suffixes);
+
+ /*
+ * If `ret' is still NULL no RCS file with any extension exists
+ * so we use the first extension.
+ */
+ if (ret == NULL) {
/*
- * Need two bytes extra for trailing slash and
- * NUL-termination.
+ * XXX - We shouldn't need to do strsep again,
+ * suffixes should now be NUL separated.
*/
- len += 2;
- if (len > MAXPATHLEN) {
- xfree(basepath);
+ if ((suffixes = strdup(rcs_suffixes)) == NULL)
+ fatal("out of memory");
+ next = suffixes;
+ /* Get first extension again. */
+ if ((ext = strsep(&next, "/")) == NULL) {
+ xfree(suffixes);
return (NULL);
}
- strlcpy(basepath, filename, len);
- strlcpy(name, ptr, MAXPATHLEN);
- strlcat(basepath, RCSDIR"/", MAXPATHLEN);
- if ((stat(basepath, &sb) == 0) && (sb.st_mode & S_IFDIR)) {
- /* <path>/RCS/<filename>,v */
- strlcat(basepath, name, MAXPATHLEN);
- strlcat(basepath, RCS_FILE_EXT, MAXPATHLEN);
- } else {
- /* <path>/<filename>,v */
- strlcpy(basepath, filename, MAXPATHLEN);
- strlcat(basepath, RCS_FILE_EXT, MAXPATHLEN);
+ if (strlcat(rcspath, ext, sizeof(rcspath)) >= sizeof(rcspath)) {
+ xfree(suffixes);
+ return (NULL);
}
+ if ((ret = strdup(rcspath)) == NULL)
+ fatal("out of memory");
+ xfree(suffixes);
}
- return (basepath);
+
+ return (ret);
}
/*