summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJoris Vink <joris@cvs.openbsd.org>2006-04-26 21:55:23 +0000
committerJoris Vink <joris@cvs.openbsd.org>2006-04-26 21:55:23 +0000
commitdf3a4e509cd581d1f7a20e485d02335219e83daf (patch)
tree624a5f81ee4938e5d6e948c5b9864f1921dcfcf4
parent3822e490767df6f6d16147268ba0f10c37a1e54c (diff)
prevent file races by obtaining an fd for the RCS file and
do our operations on that, this is safe and guarantees we can operate on the file until we close(2) it. a fix is coming for the remaining races in our diff code. okay niallo@ and ray@
-rw-r--r--usr.bin/rcs/ci.c26
-rw-r--r--usr.bin/rcs/co.c61
-rw-r--r--usr.bin/rcs/rcs.c42
-rw-r--r--usr.bin/rcs/rcs.h10
-rw-r--r--usr.bin/rcs/rcsclean.c13
-rw-r--r--usr.bin/rcs/rcsdiff.c21
-rw-r--r--usr.bin/rcs/rcsmerge.c9
-rw-r--r--usr.bin/rcs/rcsprog.c28
-rw-r--r--usr.bin/rcs/rcsutil.c103
-rw-r--r--usr.bin/rcs/rcsutil.h8
-rw-r--r--usr.bin/rcs/rlog.c10
11 files changed, 179 insertions, 152 deletions
diff --git a/usr.bin/rcs/ci.c b/usr.bin/rcs/ci.c
index b2d7c2d8869..088753a8698 100644
--- a/usr.bin/rcs/ci.c
+++ b/usr.bin/rcs/ci.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ci.c,v 1.162 2006/04/26 02:55:13 joris Exp $ */
+/* $OpenBSD: ci.c,v 1.163 2006/04/26 21:55:22 joris Exp $ */
/*
* Copyright (c) 2005, 2006 Niall O'Higgins <niallo@openbsd.org>
* All rights reserved.
@@ -100,6 +100,7 @@ checkin_usage(void)
int
checkin_main(int argc, char **argv)
{
+ int fd;
int i, ch, status;
char *rev_str;
struct checkin_params pb;
@@ -229,7 +230,6 @@ checkin_main(int argc, char **argv)
if ((pb.username = getlogin()) == NULL)
err(1, "getlogin");
-
for (i = 0; i < argc; i++) {
pb.filename = argv[i];
@@ -240,8 +240,10 @@ checkin_main(int argc, char **argv)
* Test for existence of ,v file. If we are expected to
* create one, set NEWFILE flag.
*/
- if (rcs_statfile(pb.filename, pb.fpath,
- sizeof(pb.fpath), pb.flags) < 0) {
+ fd = rcs_statfile(pb.filename, pb.fpath, sizeof(pb.fpath),
+ pb.flags);
+
+ if (fd < 0) {
if (pb.openflags & RCS_CREATE)
pb.flags |= NEWFILE;
else {
@@ -254,6 +256,7 @@ checkin_main(int argc, char **argv)
if (pb.flags & CI_INIT) {
warnx("%s already exists", pb.fpath);
status = 1;
+ (void)close(fd);
(void)close(workfile_fd);
continue;
}
@@ -264,18 +267,11 @@ checkin_main(int argc, char **argv)
* If we are to create a new ,v file, we must decide where it
* should go.
*/
- if (pb.flags & NEWFILE) {
- char *fpath = rcs_choosefile(pb.filename);
- if (fpath == NULL) {
- status = 1;
- (void)close(workfile_fd);
- continue;
- }
- strlcpy(pb.fpath, fpath, sizeof(pb.fpath));
- xfree(fpath);
- }
+ if (pb.flags & NEWFILE)
+ fd = rcs_choosefile(pb.filename,
+ pb.fpath, sizeof(pb.fpath));
- pb.file = rcs_open(pb.fpath, pb.openflags, pb.fmode);
+ pb.file = rcs_open(pb.fpath, fd, pb.openflags, pb.fmode);
if (pb.file == NULL)
errx(1, "failed to open rcsfile `%s'", pb.fpath);
diff --git a/usr.bin/rcs/co.c b/usr.bin/rcs/co.c
index 300076eb53d..80c68db241e 100644
--- a/usr.bin/rcs/co.c
+++ b/usr.bin/rcs/co.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: co.c,v 1.85 2006/04/26 02:55:13 joris Exp $ */
+/* $OpenBSD: co.c,v 1.86 2006/04/26 21:55:22 joris Exp $ */
/*
* Copyright (c) 2005 Joris Vink <joris@openbsd.org>
* All rights reserved.
@@ -36,7 +36,7 @@ static void checkout_err_nobranch(RCSFILE *, const char *, const char *,
int
checkout_main(int argc, char **argv)
{
- int i, ch, flags, kflag, status, warg;
+ int fd, i, ch, flags, kflag, status, warg;
RCSNUM *rev;
RCSFILE *file;
char fpath[MAXPATHLEN];
@@ -152,7 +152,8 @@ checkout_main(int argc, char **argv)
err(1, "getlogin");
for (i = 0; i < argc; i++) {
- if (rcs_statfile(argv[i], fpath, sizeof(fpath), flags) < 0)
+ fd = rcs_statfile(argv[i], fpath, sizeof(fpath), flags);
+ if (fd < 0)
continue;
if (!(flags & QUIET))
@@ -161,14 +162,16 @@ checkout_main(int argc, char **argv)
if ((flags & CO_LOCK) && (kflag & RCS_KWEXP_VAL)) {
warnx("%s: cannot combine -kv and -l", fpath);
+ (void)close(fd);
continue;
}
- if ((file = rcs_open(fpath, RCS_RDWR|RCS_PARSE_FULLY)) == NULL)
+ if ((file = rcs_open(fpath, fd,
+ RCS_RDWR|RCS_PARSE_FULLY)) == NULL)
continue;
if (flags & PRESERVETIME)
- rcs_mtime = rcs_get_mtime(file->rf_path);
+ rcs_mtime = rcs_get_mtime(file);
rcs_kwexp_set(file, kflag);
@@ -197,11 +200,12 @@ checkout_main(int argc, char **argv)
if (!(flags & QUIET))
printf("done\n");
- rcs_close(file);
rcsnum_free(rev);
+ rcs_write(file);
if (flags & PRESERVETIME)
- rcs_set_mtime(fpath, rcs_mtime);
+ rcs_set_mtime(file, rcs_mtime);
+ rcs_close(file);
}
if (author != NULL && warg)
@@ -240,7 +244,7 @@ checkout_rev(RCSFILE *file, RCSNUM *frev, const char *dst, int flags,
{
BUF *bp;
u_int i;
- int lcount;
+ int fd, lcount;
char buf[16];
mode_t mode = 0444;
struct stat st;
@@ -364,10 +368,11 @@ checkout_rev(RCSFILE *file, RCSNUM *frev, const char *dst, int flags,
/*
* File inherits permissions from its ,v file
*/
- if (stat(file->rf_path, &st) == -1)
- err(1, "%s", file->rf_path);
-
- mode = st.st_mode;
+ if (file->fd != -1) {
+ if (fstat(file->fd, &st) == -1)
+ err(1, "%s", file->rf_path);
+ mode = st.st_mode;
+ }
if (flags & CO_LOCK) {
if (file->rf_ndelta != 0) {
@@ -379,8 +384,11 @@ checkout_rev(RCSFILE *file, RCSNUM *frev, const char *dst, int flags,
}
/* Strip all write bits from mode */
- mode = st.st_mode &
- (S_IXUSR|S_IXGRP|S_IXOTH|S_IRUSR|S_IRGRP|S_IROTH);
+ if (file->fd != -1) {
+ mode = st.st_mode &
+ (S_IXUSR|S_IXGRP|S_IXOTH|S_IRUSR|S_IRGRP|S_IROTH);
+ }
+
mode |= S_IWUSR;
if (file->rf_ndelta != 0) {
@@ -397,8 +405,10 @@ checkout_rev(RCSFILE *file, RCSNUM *frev, const char *dst, int flags,
}
/* Strip all write bits from mode */
- mode = st.st_mode &
- (S_IXUSR|S_IXGRP|S_IXOTH|S_IRUSR|S_IRGRP|S_IROTH);
+ if (file->fd != -1) {
+ mode = st.st_mode &
+ (S_IXUSR|S_IXGRP|S_IXOTH|S_IRUSR|S_IRGRP|S_IROTH);
+ }
if (file->rf_ndelta != 0) {
if (!(flags & QUIET) && !(flags & NEWFILE) &&
@@ -424,7 +434,7 @@ checkout_rev(RCSFILE *file, RCSNUM *frev, const char *dst, int flags,
file->rf_path, lcount);
}
- if (!(flags & PIPEOUT) && stat(dst, &st) == 0 && !(flags & FORCE)) {
+ if (!(flags & PIPEOUT) && stat(dst, &st) != -1 && !(flags & FORCE)) {
/*
* XXX - Not sure what is "right". If we go according
* to GNU's behavior, an existing file with no writable
@@ -460,20 +470,33 @@ checkout_rev(RCSFILE *file, RCSNUM *frev, const char *dst, int flags,
printf("%s", content);
xfree(content);
} else {
- if (rcs_buf_write(bp, dst, mode) < 0) {
+ (void)unlink(dst);
+
+ if ((fd = open(dst, O_WRONLY|O_CREAT|O_TRUNC, mode)) < 0)
+ err(1, "%s", dst);
+
+ if (rcs_buf_write_fd(bp, fd) < 0) {
warnx("failed to write revision to file");
rcs_buf_free(bp);
+ (void)close(fd);
return (-1);
}
+
+ if (fchmod(fd, mode) == -1)
+ warn("%s", dst);
+
rcs_buf_free(bp);
+
if (flags & CO_REVDATE) {
struct timeval tv[2];
memset(&tv, 0, sizeof(tv));
tv[0].tv_sec = (long)rcs_rev_getdate(file, rev);
tv[1].tv_sec = tv[0].tv_sec;
- if (utimes(dst, (const struct timeval *)&tv) < 0)
+ if (futimes(fd, (const struct timeval *)&tv) < 0)
warn("utimes");
}
+
+ (void)close(fd);
}
return (0);
diff --git a/usr.bin/rcs/rcs.c b/usr.bin/rcs/rcs.c
index 4f24efce48b..28c98d197ed 100644
--- a/usr.bin/rcs/rcs.c
+++ b/usr.bin/rcs/rcs.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: rcs.c,v 1.2 2006/04/26 15:08:25 xsa Exp $ */
+/* $OpenBSD: rcs.c,v 1.3 2006/04/26 21:55:22 joris Exp $ */
/*
* Copyright (c) 2004 Jean-Francois Brousseau <jfb@openbsd.org>
* All rights reserved.
@@ -236,25 +236,12 @@ static void rcs_strprint(const u_char *, size_t, FILE *);
static char* rcs_expand_keywords(char *, struct rcs_delta *, char *,
size_t, int);
-/*
- * rcs_open()
- *
- * Open a file containing RCS-formatted information. The file's path is
- * given in <path>, and the opening flags are given in <flags>, which is either
- * RCS_READ, RCS_WRITE, or RCS_RDWR. If the open requests write access and
- * the file does not exist, the RCS_CREATE flag must also be given, in which
- * case it will be created with the mode specified in a third argument of
- * type mode_t. If the file exists and RCS_CREATE is passed, the open will
- * fail.
- * Returns a handle to the opened file on success, or NULL on failure.
- */
RCSFILE *
-rcs_open(const char *path, int flags, ...)
+rcs_open(const char *path, int fd, int flags, ...)
{
- int ret, mode;
+ int mode;
mode_t fmode;
RCSFILE *rfp;
- struct stat st;
va_list vap;
struct rcs_delta *rdp;
struct rcs_lock *lkr;
@@ -262,19 +249,11 @@ rcs_open(const char *path, int flags, ...)
fmode = S_IRUSR|S_IRGRP|S_IROTH;
flags &= 0xffff; /* ditch any internal flags */
- if (((ret = stat(path, &st)) == -1) && errno == ENOENT) {
- if (flags & RCS_CREATE) {
- va_start(vap, flags);
- mode = va_arg(vap, int);
- va_end(vap);
- fmode = (mode_t)mode;
- } else {
- rcs_errno = RCS_ERR_NOENT;
- return (NULL);
- }
- } else if (ret == 0 && (flags & RCS_CREATE)) {
- warnx("RCS file `%s' exists", path);
- return (NULL);
+ if (flags & RCS_CREATE) {
+ va_start(vap, flags);
+ mode = va_arg(vap, int);
+ va_end(vap);
+ fmode = (mode_t)mode;
}
rfp = xcalloc(1, sizeof(*rfp));
@@ -282,6 +261,7 @@ rcs_open(const char *path, int flags, ...)
rfp->rf_path = xstrdup(path);
rfp->rf_flags = flags | RCS_SLOCK | RCS_SYNCED;
rfp->rf_mode = fmode;
+ rfp->fd = fd;
TAILQ_INIT(&(rfp->rf_delta));
TAILQ_INIT(&(rfp->rf_access));
@@ -1731,8 +1711,8 @@ rcs_parse_init(RCSFILE *rfp)
pdp->rp_lines = 0;
pdp->rp_pttype = RCS_TOK_ERR;
- if ((pdp->rp_file = fopen(rfp->rf_path, "r")) == NULL)
- err(1, "%s", rfp->rf_path);
+ if ((pdp->rp_file = fdopen(rfp->fd, "r")) == NULL)
+ err(1, "fopen: `%s'", rfp->rf_path);
pdp->rp_buf = xmalloc((size_t)RCS_BUFSIZE);
pdp->rp_blen = RCS_BUFSIZE;
diff --git a/usr.bin/rcs/rcs.h b/usr.bin/rcs/rcs.h
index 4ae27d19e0b..adf7677bdc6 100644
--- a/usr.bin/rcs/rcs.h
+++ b/usr.bin/rcs/rcs.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: rcs.h,v 1.1 2006/04/26 02:55:13 joris Exp $ */
+/* $OpenBSD: rcs.h,v 1.2 2006/04/26 21:55:22 joris Exp $ */
/*
* Copyright (c) 2004 Jean-Francois Brousseau <jfb@openbsd.org>
* All rights reserved.
@@ -190,6 +190,7 @@ struct rcs_delta {
typedef struct rcs_file {
+ int fd;
char *rf_path;
mode_t rf_mode;
u_int rf_flags;
@@ -209,11 +210,9 @@ typedef struct rcs_file {
void *rf_pdata;
} RCSFILE;
-
extern int rcs_errno;
-
-RCSFILE *rcs_open(const char *, int, ...);
+RCSFILE *rcs_open(const char *, int, int, ...);
void rcs_close(RCSFILE *);
const RCSNUM *rcs_head_get(RCSFILE *);
int rcs_head_set(RCSFILE *, RCSNUM *);
@@ -253,7 +252,6 @@ RCSNUM *rcs_tag_resolve(RCSFILE *, const char *);
const char *rcs_errstr(int);
int rcs_write(RCSFILE *);
-
int rcs_kflag_get(const char *);
void rcs_kflag_usage(void);
int rcs_kw_expand(RCSFILE *, u_char *, size_t, size_t *);
@@ -272,9 +270,7 @@ int rcsnum_cmp(const RCSNUM *, const RCSNUM *, u_int);
/* rcstime.c */
void rcs_set_tz(char *, struct rcs_delta *, struct tm *);
-
extern char *timezone_flag;
-
extern int rcsnum_flags;
#endif /* RCS_H */
diff --git a/usr.bin/rcs/rcsclean.c b/usr.bin/rcs/rcsclean.c
index 9e20f1e55dc..6dc3b225110 100644
--- a/usr.bin/rcs/rcsclean.c
+++ b/usr.bin/rcs/rcsclean.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: rcsclean.c,v 1.44 2006/04/26 02:55:13 joris Exp $ */
+/* $OpenBSD: rcsclean.c,v 1.45 2006/04/26 21:55:22 joris Exp $ */
/*
* Copyright (c) 2005 Joris Vink <joris@openbsd.org>
* All rights reserved.
@@ -127,7 +127,7 @@ rcsclean_usage(void)
static void
rcsclean_file(char *fname, const char *rev_str)
{
- int match;
+ int fd, match;
RCSFILE *file;
char fpath[MAXPATHLEN], numb[64];
RCSNUM *rev;
@@ -138,14 +138,14 @@ rcsclean_file(char *fname, const char *rev_str)
file = NULL;
rev = NULL;
- if (rcs_statfile(fname, fpath, sizeof(fpath), flags) < 0)
+ if ((fd = rcs_statfile(fname, fpath, sizeof(fpath), flags)) < 0)
goto out;
- if ((file = rcs_open(fpath, RCS_RDWR)) == NULL)
+ if ((file = rcs_open(fpath, fd, RCS_RDWR)) == NULL)
goto out;
if (flags & PRESERVETIME)
- rcs_mtime = rcs_get_mtime(file->rf_path);
+ rcs_mtime = rcs_get_mtime(file);
rcs_kwexp_set(file, kflag);
@@ -200,8 +200,9 @@ rcsclean_file(char *fname, const char *rev_str)
}
}
+ rcs_write(file);
if (flags & PRESERVETIME)
- rcs_set_mtime(fpath, rcs_mtime);
+ rcs_set_mtime(file, rcs_mtime);
out:
if (b1 != NULL)
diff --git a/usr.bin/rcs/rcsdiff.c b/usr.bin/rcs/rcsdiff.c
index 034c4814848..a475d4a20cf 100644
--- a/usr.bin/rcs/rcsdiff.c
+++ b/usr.bin/rcs/rcsdiff.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: rcsdiff.c,v 1.57 2006/04/26 02:55:13 joris Exp $ */
+/* $OpenBSD: rcsdiff.c,v 1.58 2006/04/26 21:55:22 joris Exp $ */
/*
* Copyright (c) 2005 Joris Vink <joris@openbsd.org>
* All rights reserved.
@@ -38,7 +38,7 @@ static int kflag = RCS_KWEXP_ERR;
int
rcsdiff_main(int argc, char **argv)
{
- int i, ch, status;
+ int fd, i, ch, status;
RCSNUM *rev1, *rev2;
RCSFILE *file;
char fpath[MAXPATHLEN], *rev_str1, *rev_str2;
@@ -109,10 +109,12 @@ rcsdiff_main(int argc, char **argv)
}
for (i = 0; i < argc; i++) {
- if (rcs_statfile(argv[i], fpath, sizeof(fpath), flags) < 0)
+ fd = rcs_statfile(argv[i], fpath, sizeof(fpath), flags);
+ if (fd < 0)
continue;
- if ((file = rcs_open(fpath, RCS_READ|RCS_PARSE_FULLY)) == NULL)
+ if ((file = rcs_open(fpath, fd,
+ RCS_READ|RCS_PARSE_FULLY)) == NULL)
continue;
rcs_kwexp_set(file, kflag);
@@ -173,13 +175,13 @@ rcsdiff_usage(void)
static int
rcsdiff_file(RCSFILE *file, RCSNUM *rev, const char *filename)
{
- int ret;
+ int ret, fd;
time_t t;
+ struct stat st;
char path1[MAXPATHLEN], path2[MAXPATHLEN];
BUF *b1, *b2;
char rbuf[64];
struct tm *tb;
- struct stat st;
struct timeval tv[2], tv2[2];
memset(&tv, 0, sizeof(tv));
@@ -191,7 +193,7 @@ rcsdiff_file(RCSFILE *file, RCSNUM *rev, const char *filename)
diff_rev1 = rev;
diff_rev2 = NULL;
- if (stat(filename, &st) == -1) {
+ if ((fd = open(filename, O_RDONLY)) == -1) {
warn("%s", filename);
goto out;
}
@@ -217,6 +219,9 @@ rcsdiff_file(RCSFILE *file, RCSNUM *rev, const char *filename)
}
/* XXX - GNU uses GMT */
+ if (fstat(fd, &st) == -1)
+ err(1, "%s", filename);
+
tb = gmtime(&st.st_mtime);
t = mktime(tb);
@@ -247,6 +252,8 @@ rcsdiff_file(RCSFILE *file, RCSNUM *rev, const char *filename)
ret = 0;
out:
+ if (fd != -1)
+ (void)close(fd);
if (b1 != NULL)
rcs_buf_free(b1);
if (b2 != NULL)
diff --git a/usr.bin/rcs/rcsmerge.c b/usr.bin/rcs/rcsmerge.c
index 9335838e503..e4eadf8167b 100644
--- a/usr.bin/rcs/rcsmerge.c
+++ b/usr.bin/rcs/rcsmerge.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: rcsmerge.c,v 1.36 2006/04/26 02:55:13 joris Exp $ */
+/* $OpenBSD: rcsmerge.c,v 1.37 2006/04/26 21:55:22 joris Exp $ */
/*
* Copyright (c) 2005, 2006 Xavier Santolaria <xsa@openbsd.org>
* All rights reserved.
@@ -32,7 +32,7 @@
int
rcsmerge_main(int argc, char **argv)
{
- int i, ch, flags, kflag;
+ int fd, i, ch, flags, kflag;
char *fcont, fpath[MAXPATHLEN], r1[16], r2[16], *rev_str1, *rev_str2;
RCSFILE *file;
RCSNUM *rev1, *rev2;
@@ -105,10 +105,11 @@ rcsmerge_main(int argc, char **argv)
}
for (i = 0; i < argc; i++) {
- if (rcs_statfile(argv[i], fpath, sizeof(fpath), flags) < 0)
+ fd = rcs_statfile(argv[i], fpath, sizeof(fpath), flags);
+ if (fd < 0)
continue;
- if ((file = rcs_open(fpath, RCS_READ)) == NULL)
+ if ((file = rcs_open(fpath, fd, RCS_READ)) == NULL)
continue;
if (!(flags & QUIET))
diff --git a/usr.bin/rcs/rcsprog.c b/usr.bin/rcs/rcsprog.c
index 54592cfc129..e846f98d8d6 100644
--- a/usr.bin/rcs/rcsprog.c
+++ b/usr.bin/rcs/rcsprog.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: rcsprog.c,v 1.117 2006/04/26 02:55:13 joris Exp $ */
+/* $OpenBSD: rcsprog.c,v 1.118 2006/04/26 21:55:22 joris Exp $ */
/*
* Copyright (c) 2005 Jean-Francois Brousseau <jfb@openbsd.org>
* All rights reserved.
@@ -174,6 +174,7 @@ rcs_usage(void)
int
rcs_main(int argc, char **argv)
{
+ int fd, ofd;
int i, j, ch, flags, kflag, lkmode;
char fpath[MAXPATHLEN], ofpath[MAXPATHLEN];
char *logstr, *logmsg, *nflag, *descfile;
@@ -196,11 +197,13 @@ rcs_main(int argc, char **argv)
warnx("warning: No options were given; "
"this usage is obsolescent.");
+ ofd = -1;
while ((ch = rcs_getopt(argc, argv, RCSPROG_OPTSTRING)) != -1) {
switch (ch) {
case 'A':
- if (rcs_statfile(rcs_optarg, ofpath,
- sizeof(ofpath), flags) < 0)
+ ofd = rcs_statfile(rcs_optarg, ofpath,
+ sizeof(ofpath), flags);
+ if (ofd < 0)
exit(1);
rcsflags |= CO_ACLAPPEND;
break;
@@ -300,13 +303,14 @@ rcs_main(int argc, char **argv)
}
for (i = 0; i < argc; i++) {
- if (rcs_statfile(argv[i], fpath, sizeof(fpath), flags) < 0)
+ fd = rcs_statfile(argv[i], fpath, sizeof(fpath), flags);
+ if (fd < 0 && !(flags & RCS_CREATE))
continue;
if (!(rcsflags & QUIET))
printf("RCS file: %s\n", fpath);
- if ((file = rcs_open(fpath, flags, fmode)) == NULL)
+ if ((file = rcs_open(fpath, fd, flags, fmode)) == NULL)
continue;
if (rcsflags & DESCRIPTION)
@@ -315,7 +319,7 @@ rcs_main(int argc, char **argv)
rcs_set_description(file, NULL);
if (rcsflags & PRESERVETIME)
- rcs_mtime = rcs_get_mtime(file->rf_path);
+ rcs_mtime = rcs_get_mtime(file);
if (nflag != NULL)
rcs_attach_symbol(file, nflag);
@@ -348,13 +352,14 @@ rcs_main(int argc, char **argv)
/* entries to add from <oldfile> */
if (rcsflags & CO_ACLAPPEND) {
/* XXX */
- if ((oldfile = rcs_open(ofpath, RCS_READ)) == NULL)
+ if ((oldfile = rcs_open(ofpath, ofd, RCS_READ)) == NULL)
exit(1);
TAILQ_FOREACH(acp, &(oldfile->rf_access), ra_list)
rcs_access_add(file, acp->ra_name);
rcs_close(oldfile);
+ ofd = -1;
}
/* entries to add to the access list */
@@ -467,10 +472,12 @@ rcs_main(int argc, char **argv)
}
}
- rcs_close(file);
+ rcs_write(file);
if (rcsflags & PRESERVETIME)
- rcs_set_mtime(fpath, rcs_mtime);
+ rcs_set_mtime(file, rcs_mtime);
+
+ rcs_close(file);
if (!(rcsflags & QUIET))
printf("done\n");
@@ -485,6 +492,9 @@ rcs_main(int argc, char **argv)
if (orange != NULL)
xfree(orange);
+ if (ofd != -1)
+ (void)close(ofd);
+
return (0);
}
diff --git a/usr.bin/rcs/rcsutil.c b/usr.bin/rcs/rcsutil.c
index cd6c9ff086a..8c732a0e944 100644
--- a/usr.bin/rcs/rcsutil.c
+++ b/usr.bin/rcs/rcsutil.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: rcsutil.c,v 1.5 2006/04/26 02:55:13 joris Exp $ */
+/* $OpenBSD: rcsutil.c,v 1.6 2006/04/26 21:55:22 joris Exp $ */
/*
* Copyright (c) 2005, 2006 Joris Vink <joris@openbsd.org>
* Copyright (c) 2006 Xavier Santolaria <xsa@openbsd.org>
@@ -38,15 +38,16 @@
* Returns last modified time on success, or -1 on failure.
*/
time_t
-rcs_get_mtime(const char *filename)
+rcs_get_mtime(RCSFILE *file)
{
struct stat st;
time_t mtime;
- if (stat(filename, &st) == -1) {
- warn("%s", filename);
+ if (fstat(file->fd, &st) == -1) {
+ warn("%s", file->rf_path);
return (-1);
}
+
mtime = (time_t)st.st_mtimespec.tv_sec;
return (mtime);
@@ -58,7 +59,7 @@ rcs_get_mtime(const char *filename)
* Set <filename> last modified time to <mtime> if it's not set to -1.
*/
void
-rcs_set_mtime(const char *filename, time_t mtime)
+rcs_set_mtime(RCSFILE *file, time_t mtime)
{
static struct timeval tv[2];
@@ -68,7 +69,7 @@ rcs_set_mtime(const char *filename, time_t mtime)
tv[0].tv_sec = mtime;
tv[1].tv_sec = tv[0].tv_sec;
- if (utimes(filename, tv) == -1)
+ if (futimes(file->fd, tv) == -1)
err(1, "utimes");
}
@@ -137,9 +138,10 @@ rcs_getopt(int argc, char **argv, const char *optstr)
*
* Returns pointer to a char array on success, NULL on failure.
*/
-char *
-rcs_choosefile(const char *filename)
+int
+rcs_choosefile(const char *filename, char *out, size_t len)
{
+ int fd;
struct stat sb;
char *p, *ext, name[MAXPATHLEN], *next, *ptr, rcsdir[MAXPATHLEN],
*ret, *suffixes, rcspath[MAXPATHLEN];
@@ -148,13 +150,16 @@ rcs_choosefile(const char *filename)
if (rcs_suffixes == NULL)
rcs_suffixes = RCS_DEFAULT_SUFFIX;
+ fd = -1;
+
/*
* 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);
+ errx(1, "rcs_choosefile: truncation");
+
/* If `/' is found, end string after `/'. */
if ((ptr = strrchr(rcspath, '/')) != NULL)
*(++ptr) = '\0';
@@ -164,33 +169,36 @@ rcs_choosefile(const char *filename)
/* Append RCS/ to `rcspath' if it exists. */
if (strlcpy(rcsdir, rcspath, sizeof(rcsdir)) >= sizeof(rcsdir) ||
strlcat(rcsdir, RCSDIR, sizeof(rcsdir)) >= sizeof(rcsdir))
- return (NULL);
+ errx(1, "rcs_choosefile: truncation");
+
if (stat(rcsdir, &sb) == 0 && (sb.st_mode & S_IFDIR))
- if (strlcpy(rcspath, rcsdir, sizeof(rcspath)) >= sizeof(rcspath) ||
+ if (strlcpy(rcspath, rcsdir, sizeof(rcspath))
+ >= sizeof(rcspath) ||
strlcat(rcspath, "/", sizeof(rcspath)) >= sizeof(rcspath))
- return (NULL);
+ errx(1, "rcs_choosefile: truncation");
/* Name of file without path. */
if ((ptr = strrchr(filename, '/')) == NULL) {
if (strlcpy(name, filename, sizeof(name)) >= sizeof(name))
- return (NULL);
+ errx(1, "rcs_choosefile: truncation");
} else {
/* Skip `/'. */
if (strlcpy(name, ptr + 1, sizeof(name)) >= sizeof(name))
- return (NULL);
+ errx(1, "rcs_choosefile: truncation");
}
/* Name of RCS file without an extension. */
if (strlcat(rcspath, name, sizeof(rcspath)) >= sizeof(rcspath))
- return (NULL);
+ errx(1, "rcs_choosefile: truncation");
/*
* 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) {
- ret = xstrdup(rcspath);
- return (ret);
+ fd = open(rcspath, O_RDONLY);
+ strlcpy(out, rcspath, len);
+ return (fd);
}
/*
@@ -205,10 +213,16 @@ rcs_choosefile(const char *filename)
if ((p = strrchr(rcspath, ',')) != NULL) {
if (!strcmp(p, ext)) {
- if (stat(rcspath, &sb) == 0) {
- ret = xstrdup(rcspath);
- goto out;
- }
+ if ((fd = open(rcspath, O_RDONLY)) == -1)
+ continue;
+
+ if (fstat(fd, &sb) == -1)
+ err(1, "%s", rcspath);
+
+ if (strlcpy(out, rcspath, len) >= len)
+ errx(1, "rcs_choosefile; truncation");
+
+ return (fd);
}
continue;
@@ -217,16 +231,22 @@ rcs_choosefile(const char *filename)
/* Construct RCS file path. */
if (strlcpy(fpath, rcspath, sizeof(fpath)) >= sizeof(fpath) ||
strlcat(fpath, ext, sizeof(fpath)) >= sizeof(fpath))
- goto out;
+ errx(1, "rcs_choosefile: truncation");
/* Don't use `filename' as RCS file. */
if (strcmp(fpath, filename) == 0)
continue;
- if (stat(fpath, &sb) == 0) {
- ret = xstrdup(fpath);
- goto out;
- }
+ if ((fd = open(fpath, O_RDONLY)) == -1)
+ continue;
+
+ if (fstat(fd, &sb) == -1)
+ err(1, "%s", fpath);
+
+ if (strlcpy(out, fpath, len) >= len)
+ errx(1, "rcs_choosefile: truncation");
+
+ return (fd);
}
/*
@@ -238,13 +258,14 @@ rcs_choosefile(const char *filename)
*/
if (strlcat(rcspath, suffixes, sizeof(rcspath)) >=
sizeof(rcspath))
- goto out;
- ret = xstrdup(rcspath);
+ errx(1, "rcs_choosefile: truncation");
-out:
- /* `ret' may be NULL, which indicates an error. */
xfree(suffixes);
- return (ret);
+
+ fd = open(rcspath, O_RDONLY);
+ strlcpy(out, rcspath, len);
+
+ return (fd);
}
/*
@@ -255,27 +276,17 @@ out:
int
rcs_statfile(char *fname, char *out, size_t len, int flags)
{
- struct stat st;
- char *rcspath;
-
- if ((rcspath = rcs_choosefile(fname)) == NULL)
- errx(1, "rcs_statfile: path truncation");
+ int fd;
- /* Error out if file not found and we are not creating one. */
- if (stat(rcspath, &st) == -1 && !(flags & RCS_CREATE)) {
+ fd = rcs_choosefile(fname, out, len);
+ if (fd == -1 && !(flags & RCS_CREATE)) {
if (strcmp(__progname, "rcsclean") != 0 &&
strcmp(__progname, "ci") != 0)
- warn("%s", rcspath);
- xfree(rcspath);
+ warn("%s", out);
return (-1);
}
- if (strlcpy(out, rcspath, len) >= len)
- errx(1, "rcs_statfile: path truncation");
-
- xfree(rcspath);
-
- return (0);
+ return (fd);
}
/*
diff --git a/usr.bin/rcs/rcsutil.h b/usr.bin/rcs/rcsutil.h
index 69017e287b4..68dc5d655eb 100644
--- a/usr.bin/rcs/rcsutil.h
+++ b/usr.bin/rcs/rcsutil.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: rcsutil.h,v 1.2 2006/04/24 04:51:57 ray Exp $ */
+/* $OpenBSD: rcsutil.h,v 1.3 2006/04/26 21:55:22 joris Exp $ */
/*
* Copyright (c) 2006 Xavier Santolaria <xsa@openbsd.org>
* All rights reserved.
@@ -31,10 +31,10 @@
/* rcsutil.c */
int rcs_getopt(int, char **, const char *);
-void rcs_set_mtime(const char *, time_t);
-char *rcs_choosefile(const char *);
+void rcs_set_mtime(RCSFILE *, time_t);
+int rcs_choosefile(const char *, char *, size_t);
int rcs_statfile(char *, char *, size_t, int);
-time_t rcs_get_mtime(const char *);
+time_t rcs_get_mtime(RCSFILE *);
RCSNUM *rcs_getrevnum(const char *, RCSFILE *);
char *rcs_prompt(const char *);
u_int rcs_rev_select(RCSFILE *, char *);
diff --git a/usr.bin/rcs/rlog.c b/usr.bin/rcs/rlog.c
index 4fb1c917274..d19ccbd9cc7 100644
--- a/usr.bin/rcs/rlog.c
+++ b/usr.bin/rcs/rlog.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: rlog.c,v 1.51 2006/04/26 02:55:13 joris Exp $ */
+/* $OpenBSD: rlog.c,v 1.52 2006/04/26 21:55:22 joris Exp $ */
/*
* Copyright (c) 2005 Joris Vink <joris@openbsd.org>
* Copyright (c) 2005, 2006 Xavier Santolaria <xsa@openbsd.org>
@@ -58,7 +58,7 @@ rlog_main(int argc, char **argv)
{
RCSFILE *file;
int Rflag;
- int i, ch;
+ int i, ch, fd;
char fpath[MAXPATHLEN];
rcsnum_flags |= RCSNUM_NO_MAGIC;
@@ -137,10 +137,12 @@ rlog_main(int argc, char **argv)
}
for (i = 0; i < argc; i++) {
- if (rcs_statfile(argv[i], fpath, sizeof(fpath), 0) < 0)
+ fd = rcs_statfile(argv[i], fpath, sizeof(fpath), 0);
+ if (fd < 0)
continue;
- if ((file = rcs_open(fpath, RCS_READ|RCS_PARSE_FULLY)) == NULL)
+ if ((file = rcs_open(fpath, fd,
+ RCS_READ|RCS_PARSE_FULLY)) == NULL)
continue;
if (Lflag == 1 && TAILQ_EMPTY(&(file->rf_locks))) {