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

Reply via email to