diff options
author | 2006-03-14 03:33:30 +0000 | |
---|---|---|
committer | 2006-03-14 03:33:30 +0000 | |
commit | 103bc3068e39c562d8f90674b0e1b6475383953c (patch) | |
tree | be4540c07f362d356fdb00a8c5d7b23005f5495d /usr.bin/rcs | |
parent | sync (diff) | |
download | wireguard-openbsd-103bc3068e39c562d8f90674b0e1b6475383953c.tar.xz wireguard-openbsd-103bc3068e39c562d8f90674b0e1b6475383953c.zip |
ci currently doesn't parse the -x flag at all, defaulting to ",v/" every
time. I rewrote checkin_choose_rcsfile() to handle it using these rules:
- If a directory structure is given (ci -x,abcd dir/dir2/file) then all
RCS files are under dir/dir2.
- If the RCS/ directory exists, use it. Otherwise use current directory.
- If the -x flag is specified, use those slash-separated extensions.
Otherwise, use the default (",v/").
- Look in the rcs directory (RCS/ or current directory) for a file
with a matching extension, for each extension. Each extension is
tried in order. If a file exists, it is used. If no file exists
with any extension, the first one is used.
- The empty extension is treated as no extension, because I can't
figure out what its special meaning is.
It sounds complicated, and the code is kinda complicated as well, but it
makes sense if you think about it.
ok niallo
Diffstat (limited to 'usr.bin/rcs')
-rw-r--r-- | usr.bin/rcs/ci.c | 148 | ||||
-rw-r--r-- | usr.bin/rcs/rcsprog.c | 3 | ||||
-rw-r--r-- | usr.bin/rcs/rcsprog.h | 3 |
3 files changed, 108 insertions, 46 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); } /* diff --git a/usr.bin/rcs/rcsprog.c b/usr.bin/rcs/rcsprog.c index 295522d1d04..bea11281c5e 100644 --- a/usr.bin/rcs/rcsprog.c +++ b/usr.bin/rcs/rcsprog.c @@ -1,4 +1,4 @@ -/* $OpenBSD: rcsprog.c,v 1.71 2006/03/14 01:51:35 ray Exp $ */ +/* $OpenBSD: rcsprog.c,v 1.72 2006/03/14 03:33:30 ray Exp $ */ /* * Copyright (c) 2005 Jean-Francois Brousseau <jfb@openbsd.org> * All rights reserved. @@ -29,7 +29,6 @@ #include "rcsprog.h" #define RCS_CMD_MAXARG 128 -#define RCS_DEFAULT_SUFFIX ",v/" #define RCSPROG_OPTSTRING "A:a:b::c:e::hik:Lm:Mn:N:qt::TUVx:z:" #define DESC_PROMPT "enter description, terminated with single '.' " \ diff --git a/usr.bin/rcs/rcsprog.h b/usr.bin/rcs/rcsprog.h index 67da6bfa377..e7045e470fb 100644 --- a/usr.bin/rcs/rcsprog.h +++ b/usr.bin/rcs/rcsprog.h @@ -1,4 +1,4 @@ -/* $OpenBSD: rcsprog.h,v 1.36 2006/03/08 20:19:39 joris Exp $ */ +/* $OpenBSD: rcsprog.h,v 1.37 2006/03/14 03:33:30 ray Exp $ */ /* * Copyright (c) 2005 Joris Vink <joris@openbsd.org> * All rights reserved. @@ -32,6 +32,7 @@ #include "worklist.h" #include "xmalloc.h" +#define RCS_DEFAULT_SUFFIX ",v/" #define RCS_TMPDIR_DEFAULT "/tmp" /* flags specific to ci.c */ |