Skip to content

Instantly share code, notes, and snippets.

@levaidaniel
Created April 30, 2020 18:58
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save levaidaniel/dfc71d782a6e023459c04a3f30ff5a6e to your computer and use it in GitHub Desktop.
Save levaidaniel/dfc71d782a6e023459c04a3f30ff5a6e to your computer and use it in GitHub Desktop.
Preserve ownership of files when RCSing!
diff --git a/usr.bin/rcs/ci.c b/usr.bin/rcs/ci.c
index 765b03a9388..d7212ad8365 100644
--- a/usr.bin/rcs/ci.c
+++ b/usr.bin/rcs/ci.c
@@ -565,6 +565,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 = st.st_uid;
+ pb->file->rf_gid = st.st_gid;
+
(void)close(workfile_fd);
(void)unlink(pb->filename);
@@ -685,6 +689,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 = st.st_uid;
+ pb->file->rf_gid = st.st_gid;
+
(void)close(workfile_fd);
(void)unlink(pb->filename);
diff --git a/usr.bin/rcs/co.c b/usr.bin/rcs/co.c
index 97baae78c44..4f5b0f41800 100644
--- a/usr.bin/rcs/co.c
+++ b/usr.bin/rcs/co.c
@@ -364,6 +364,9 @@ checkout_rev(RCSFILE *file, RCSNUM *frev, const char *dst, int flags,
if (fstat(fileno(file->rf_file), &st) == -1)
err(1, "%s", file->rf_path);
file->rf_mode = mode = st.st_mode;
+ /* Preserve the owner and group */
+ file->rf_uid = st.st_uid;
+ file->rf_gid = st.st_gid;
} else {
mode = file->rf_mode;
}
@@ -479,8 +482,13 @@ checkout_rev(RCSFILE *file, RCSNUM *frev, const char *dst, int flags,
return (-1);
}
- if (fchmod(fd, mode) == -1)
- warn("%s", dst);
+ if (fchmod(fd, mode) == -1) {
+ warn("chmod() %s", dst);
+ } else {
+ if (fchown(fd, file->rf_uid, file->rf_gid) == -1) {
+ warn("chown() %s", dst);
+ }
+ }
if (flags & CO_REVDATE) {
struct timeval tv[2];
diff --git a/usr.bin/rcs/rcs.c b/usr.bin/rcs/rcs.c
index 30415b9de17..13d41a526bd 100644
--- a/usr.bin/rcs/rcs.c
+++ b/usr.bin/rcs/rcs.c
@@ -72,7 +72,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_freedelta(struct rcs_delta *);
static void rcs_strprint(const u_char *, size_t, FILE *);
@@ -338,9 +338,12 @@ 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) {
+ if (rcs_movefile(fn, rfp->rf_path, rfp->rf_mode, -1, -1, rfp->rf_flags) == -1) {
+ (void)unlink(fn);
+ errx(1, "rcs_movefile failed");
+ }
(void)unlink(fn);
- errx(1, "rcs_movefile failed");
}
rfp->rf_flags |= RCS_SYNCED;
@@ -355,7 +358,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;
@@ -366,6 +369,10 @@ rcs_movefile(char *from, char *to, mode_t perm, u_int to_flags)
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");
@@ -393,6 +400,12 @@ rcs_movefile(char *from, char *to, mode_t perm, u_int to_flags)
(void)fclose(src);
(void)fclose(dst);
return (-1);
+ } else {
+ if (fchown(fileno(dst), owner, group) == -1) {
+ warn("%s", to);
+ (void)unlink(to);
+ return (-1);
+ }
}
buf = xmalloc(MAXBSIZE);
diff --git a/usr.bin/rcs/rcs.h b/usr.bin/rcs/rcs.h
index ec672a1306f..8a94d476dbd 100644
--- a/usr.bin/rcs/rcs.h
+++ b/usr.bin/rcs/rcs.h
@@ -198,6 +198,8 @@ typedef struct rcs_file {
FILE *rf_file;
char *rf_path;
mode_t rf_mode;
+ uid_t rf_uid;
+ gid_t rf_gid;
u_int rf_flags;
RCSNUM *rf_head;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment