Hi!
Here is a diff, if someone is interested, which adds a new option to rcs'
ci(1) and co(1) to preserve owner and group information across
checkins/checkouts. I was really missing this feature with config files
which have to have uid/gid other than root/wheel and needed to manage the
files as root with rcs.
The man page addition probably could be more elaborate (or not),
and the option name (-O) is just from the top of my head.
Index: usr.bin/rcs/ci.1
===================================================================
RCS file: /cvs/src/usr.bin/rcs/ci.1,v
retrieving revision 1.35
diff -N -p -u usr.bin/rcs/ci.1
--- usr.bin/rcs/ci.1 26 Aug 2007 21:35:43 -0000 1.35
+++ usr.bin/rcs/ci.1 23 Jul 2009 08:32:16 -0000
@@ -23,7 +23,7 @@
.Sh SYNOPSIS
.Nm
.Bk -words
-.Op Fl qV
+.Op Fl qVO
.Op Fl d Ns Op Ar date
.Op Fl f Ns Op Ar rev
.Op Fl I Ns Op Ar rev
@@ -178,6 +178,8 @@ default time zone for
used in the
.Fl d
option.
+.It Fl O
+Preserve owner and group information of files.
.El
.Pp
.Ex -std ci
Index: usr.bin/rcs/ci.c
===================================================================
RCS file: /cvs/src/usr.bin/rcs/ci.c,v
retrieving revision 1.205
diff -N -p -u usr.bin/rcs/ci.c
--- usr.bin/rcs/ci.c 25 Feb 2009 23:16:20 -0000 1.205
+++ usr.bin/rcs/ci.c 23 Jul 2009 08:32:16 -0000
@@ -37,7 +37,7 @@
#include "rcsprog.h"
#include "diff.h"
-#define CI_OPTSTRING "d::f::I::i::j::k::l::M::m::N:n:qr::s:Tt::u::Vw:x::z::"
+#define CI_OPTSTRING
"d::f::I::i::j::k::l::M::m::N:n:Oqr::s:Tt::u::Vw:x::z::"
#define DATE_NOW -1
#define DATE_MTIME -2
@@ -98,7 +98,7 @@ void
checkin_usage(void)
{
fprintf(stderr,
- "usage: ci [-qV] [-d[date]] [-f[rev]] [-I[rev]] [-i[rev]]\n"
+ "usage: ci [-qVO] [-d[date]] [-f[rev]] [-I[rev]] [-i[rev]]\n"
" [-j[rev]] [-k[rev]] [-l[rev]] [-M[rev]] [-mmsg]\n"
" [-Nsymbol] [-nsymbol] [-r[rev]] [-sstate] [-tstr]\n"
" [-u[rev]] [-wusername] [-xsuffixes] [-ztz] file ...\n");
@@ -183,6 +183,9 @@ checkin_main(int argc, char **argv)
if (rcs_sym_check(pb.symbol) != 1)
errx(1, "invalid symbol `%s'", pb.symbol);
break;
+ case 'O':
+ base_flags |= PRESERVEOWNER;
+ break;
case 'q':
base_flags |= QUIET;
break;
@@ -585,6 +588,10 @@ checkin_update(struct checkin_params *pb)
/* Strip all the write bits */
pb->file->rf_mode = st.st_mode & ~(S_IWUSR|S_IWGRP|S_IWOTH);
+ /* Preserve the owner and group */
+ pb->file->rf_uid = (pb->flags & PRESERVEOWNER) ? st.st_uid : -1;
+ pb->file->rf_gid = (pb->flags & PRESERVEOWNER) ? st.st_gid : -1;
+
(void)close(workfile_fd);
(void)unlink(pb->filename);
@@ -705,6 +712,10 @@ skipdesc:
/* Strip all the write bits */
pb->file->rf_mode = st.st_mode & ~(S_IWUSR|S_IWGRP|S_IWOTH);
+ /* Preserve the owner and group */
+ pb->file->rf_uid = (pb->flags & PRESERVEOWNER) ? st.st_uid : -1;
+ pb->file->rf_gid = (pb->flags & PRESERVEOWNER) ? st.st_gid : -1;
+
(void)close(workfile_fd);
(void)unlink(pb->filename);
@@ -713,10 +724,9 @@ skipdesc:
/* Do checkout if -u or -l are specified. */
if (((pb->flags & CO_LOCK) || (pb->flags & CO_UNLOCK)) &&
- !(pb->flags & CI_DEFAULT)) {
+ !(pb->flags & CI_DEFAULT))
checkout_rev(pb->file, pb->newrev, pb->filename, pb->flags,
pb->username, pb->author, NULL, NULL);
- }
if (!(pb->flags & QUIET)) {
fprintf(stderr, "initial revision: %s\n",
Index: usr.bin/rcs/co.1
===================================================================
RCS file: /cvs/src/usr.bin/rcs/co.1,v
retrieving revision 1.28
diff -N -p -u usr.bin/rcs/co.1
--- usr.bin/rcs/co.1 31 May 2007 19:20:14 -0000 1.28
+++ usr.bin/rcs/co.1 23 Jul 2009 08:32:17 -0000
@@ -23,7 +23,7 @@
.Sh SYNOPSIS
.Nm
.Bk -words
-.Op Fl TV
+.Op Fl TVO
.Op Fl d Ns Ar date
.Op Fl f Ns Op Ar rev
.Op Fl I Ns Op Ar rev
@@ -132,6 +132,8 @@ default time zone for
used in the
.Fl d
option.
+.It Fl O
+Preserve owner and group information of files.
.El
.Pp
.Ex -std co
Index: usr.bin/rcs/co.c
===================================================================
RCS file: /cvs/src/usr.bin/rcs/co.c,v
retrieving revision 1.110
diff -N -p -u usr.bin/rcs/co.c
--- usr.bin/rcs/co.c 25 Feb 2009 23:16:20 -0000 1.110
+++ usr.bin/rcs/co.c 23 Jul 2009 08:32:18 -0000
@@ -36,7 +36,7 @@
#include "rcsprog.h"
#include "diff.h"
-#define CO_OPTSTRING "d:f::I::k:l::M::p::q::r::s:Tu::Vw::x::z::"
+#define CO_OPTSTRING "d:f::I::k:l::M::Op::q::r::s:Tu::Vw::x::z::"
static void checkout_err_nobranch(RCSFILE *, const char *, const char *,
const char *, int);
@@ -93,6 +93,9 @@ checkout_main(int argc, char **argv)
rcs_setrevstr(&rev_str, rcs_optarg);
flags |= CO_REVDATE;
break;
+ case 'O':
+ flags |= PRESERVEOWNER;
+ break;
case 'p':
rcs_setrevstr(&rev_str, rcs_optarg);
flags |= PIPEOUT;
@@ -229,7 +232,7 @@ void
checkout_usage(void)
{
fprintf(stderr,
- "usage: co [-TV] [-ddate] [-f[rev]] [-I[rev]] [-kmode] [-l[rev]]\n"
+ "usage: co [-TVO] [-ddate] [-f[rev]] [-I[rev]] [-kmode] [-l[rev]]\n"
" [-M[rev]] [-p[rev]] [-q[rev]] [-r[rev]] [-sstate]\n"
" [-u[rev]] [-w[user]] [-xsuffixes] [-ztz] file ...\n");
}
@@ -369,6 +372,9 @@ checkout_rev(RCSFILE *file, RCSNUM *frev, const char *
if (fstat(file->rf_fd, &st) == -1)
err(1, "%s", file->rf_path);
file->rf_mode = mode = st.st_mode;
+ /* Preserve the owner and group */
+ file->rf_uid = (flags & PRESERVEOWNER) ? st.st_uid : -1;
+ file->rf_gid = (flags & PRESERVEOWNER) ? st.st_gid : -1;
} else {
mode = file->rf_mode;
}
@@ -478,6 +484,9 @@ checkout_rev(RCSFILE *file, RCSNUM *frev, const char *
}
if (fchmod(fd, mode) == -1)
+ warn("%s", dst);
+
+ if (fchown(fd, file->rf_uid, file->rf_gid) == -1)
warn("%s", dst);
if (flags & CO_REVDATE) {
Index: usr.bin/rcs/rcs.c
===================================================================
RCS file: /cvs/src/usr.bin/rcs/rcs.c,v
retrieving revision 1.54
diff -N -p -u usr.bin/rcs/rcs.c
--- usr.bin/rcs/rcs.c 14 Apr 2009 21:16:40 -0000 1.54
+++ usr.bin/rcs/rcs.c 23 Jul 2009 08:32:21 -0000
@@ -228,7 +228,7 @@ int rcs_errno = RCS_ERR_NOERR;
char *timezone_flag = NULL;
int rcs_patch_lines(struct rcs_lines *, struct rcs_lines *);
-static int rcs_movefile(char *, char *, mode_t, u_int);
+static int rcs_movefile(char *, char *, mode_t, uid_t, gid_t, u_int);
static void rcs_parse_init(RCSFILE *);
static int rcs_parse_admin(RCSFILE *);
static int rcs_parse_delta(RCSFILE *);
@@ -507,7 +507,7 @@ rcs_write(RCSFILE *rfp)
}
(void)fclose(fp);
- if (rcs_movefile(fn, rfp->rf_path, rfp->rf_mode, rfp->rf_flags) == -1) {
+ if (rcs_movefile(fn, rfp->rf_path, rfp->rf_mode, rfp->rf_uid,
rfp->rf_gid,
rfp->rf_flags) == -1) {
(void)unlink(fn);
errx(1, "rcs_movefile failed");
}
@@ -525,7 +525,7 @@ rcs_write(RCSFILE *rfp)
* Returns 0 on success, -1 on failure.
*/
static int
-rcs_movefile(char *from, char *to, mode_t perm, u_int to_flags)
+rcs_movefile(char *from, char *to, mode_t perm, uid_t owner, gid_t group,
u_int
to_flags)
{
FILE *src, *dst;
size_t nread, nwritten;
@@ -539,6 +539,10 @@ rcs_movefile(char *from, char *to, mode_t perm, u_int
warn("%s", to);
return (-1);
}
+ if (chown(to, owner, group) == -1) {
+ warn("%s", to);
+ return (-1);
+ }
return (0);
} else if (errno != EXDEV) {
warn("failed to access temp RCS output file");
@@ -560,6 +564,11 @@ rcs_movefile(char *from, char *to, mode_t perm, u_int
return (-1);
}
if (fchmod(fileno(dst), perm)) {
+ warn("%s", to);
+ (void)unlink(to);
+ return (-1);
+ }
+ if (fchown(fileno(dst), owner, group) == -1) {
warn("%s", to);
(void)unlink(to);
return (-1);
Index: usr.bin/rcs/rcs.h
===================================================================
RCS file: /cvs/src/usr.bin/rcs/rcs.h,v
retrieving revision 1.8
diff -N -p -u usr.bin/rcs/rcs.h
--- usr.bin/rcs/rcs.h 2 Feb 2008 16:21:38 -0000 1.8
+++ usr.bin/rcs/rcs.h 23 Jul 2009 08:32:22 -0000
@@ -195,6 +195,8 @@ typedef struct rcs_file {
int rf_fd;
char *rf_path;
mode_t rf_mode;
+ uid_t rf_uid;
+ gid_t rf_gid;
u_int rf_flags;
RCSNUM *rf_head;
Index: usr.bin/rcs/rcsprog.h
===================================================================
RCS file: /cvs/src/usr.bin/rcs/rcsprog.h,v
retrieving revision 1.61
diff -N -p -u usr.bin/rcs/rcsprog.h
--- usr.bin/rcs/rcsprog.h 10 May 2008 19:54:58 -0000 1.61
+++ usr.bin/rcs/rcsprog.h 23 Jul 2009 08:32:22 -0000
@@ -72,6 +72,7 @@
#define PIPEOUT (1<<22)
#define PRESERVETIME (1<<23)
#define QUIET (1<<24)
+#define PRESERVEOWNER (1<<25)
extern char *__progname;
extern const char rcs_version[];
--
LIVAI Daniel
PGP key ID = 0x4AC0A4B1
Key fingerprint = D037 03B9 C12D D338 4412 2D83 1373 917A 4AC0 A4B1