svn commit: r240538 - svnadmin/tools/checkacl

Bjoern A. Zeeb bz at FreeBSD.org
Sat Sep 15 19:17:20 UTC 2012


Author: bz
Date: Sat Sep 15 19:17:19 2012
New Revision: 240538
URL: http://svn.freebsd.org/changeset/base/240538

Log:
  Start synchronizing checkacl.c between various SVN repositories.
  
  Stop using CVS access files and use the SVN versions.
  Use a defined length for user named (not ideal but better than 32).
  Rather than using a variable per repo and karma, use two bitfields.
  Factor out repeated tasks, as checking an access file and adding
  the string for another foreign commit bit.
  Use #ifdef checks for all files, not just docs and ports. base is
  not special.
  Defer variable initialization to when needed.
  Accept a mandatory argument, the repo name, to allow code sharing
  between the repositories of all shared access files.
  Consistently use the 'username' and not pw_name after copy; close
  the password database to avoid further access.
  
  Inspired by:	ports version from beat

Modified:
  svnadmin/tools/checkacl/checkacl.c

Modified: svnadmin/tools/checkacl/checkacl.c
==============================================================================
--- svnadmin/tools/checkacl/checkacl.c	Sat Sep 15 18:53:00 2012	(r240537)
+++ svnadmin/tools/checkacl/checkacl.c	Sat Sep 15 19:17:19 2012	(r240538)
@@ -4,6 +4,8 @@
  * FreeBSD Subversion tree ACL check helper.  The program looks in
  * relevant access files to find out if the committer may commit.
  *
+ * !!! Please keep in sync between various SVN repositories. !!!
+ *
  * From: Id: cvssh.c,v 1.38 2008/05/31 02:54:58 peter Exp
  * $FreeBSD$
  */
@@ -24,13 +26,16 @@
 #include <stdarg.h>
 #include <fcntl.h>
 
-#define ACCESS		"/s/svn/base/conf/access"
-#define DOCACCESS	"/home/dcvs/CVSROOT/access"
-#define PORTSACCESS	"/home/pcvs/CVSROOT/access"
-
+#define	BASE		0x01
+#define	DOC		0x02
+#define	PORTS		0x04
+
+#define	SVNROOT		"/s/svn"
+#define	BASEACCESS	SVNROOT "/base/conf/access"
+#define	DOCACCESS	SVNROOT "/doc/conf/access"
+#define	PORTSACCESS	SVNROOT "/ports/conf/access"
 
-static char username[32];
-static char committag[256];
+static char username[_SC_LOGIN_NAME_MAX + 1];
 
 static void
 msg(const char *fmt, ...)
@@ -43,12 +48,12 @@ msg(const char *fmt, ...)
 	va_end(ap);
 }
 
-static int
-karmacheck(FILE *fp, char *name)
+static u_int
+karmacheck(FILE *fp, const char *name, u_int k)
 {
 	char buf[1024];
 	char *p, *s;
-	int karma;
+	u_int karma;
 
 	karma = 0;
 	while ((p = fgets(buf, sizeof(buf) - 1, fp)) != NULL) {
@@ -58,11 +63,11 @@ karmacheck(FILE *fp, char *name)
 			if (*s == '#' || *s == '/' || *s == ';')
 				break;		/* comment */
 			if (strcmp(s, "*") == 0) {	/* all */
-				karma++;
+				karma |= k;
 				break;
 			}
 			if (strcmp(s, name) == 0) {
-				karma++;
+				karma |= k;
 				break;
 			}
 			break;	/* ignore further tokens on line */
@@ -71,34 +76,49 @@ karmacheck(FILE *fp, char *name)
 	return karma;
 }
 
+static u_int
+read_access(const char *accessf, const u_int repo, u_int k,
+    const char *name)
+{
+	FILE *fp;
+	u_int karma;
+
+	karma = 0;
+	fp = fopen(accessf, "r");
+	if (fp == NULL && (repo & k) == k) {
+		msg("Cannot open %s", accessf);
+		exit(1);
+	} else if (fp != NULL) {
+		karma |= karmacheck(fp, name, k);
+		fclose(fp);
+	}
+
+	return (karma);
+}
+
+static void
+catcommittag(char *committag, const char **comma, const u_int karma,
+    const u_int k, const char *s)
+{
+
+	if ((karma & k) == 0)
+		return;
+
+	strcat(committag, *comma);
+	strcat(committag, s);
+	*comma = ",";
+}
+
 int
 main(int argc, char *argv[])
 {
 	struct passwd *pw;
 	struct stat st;
-	FILE *fp;
-	int i;
 	gid_t repogid;
 	gid_t mygroups[NGROUPS_MAX];
-	int ngroups;
-	int writeable;
-	int karma;
-#ifdef PORTSACCESS
-	int portskarma;
-#endif
-#ifdef DOCACCESS
-	int dockarma;
-#endif
-	const char *comma;
+	int i, ngroups, writeable;
+	u_int karma, repo;
 
-#ifdef PORTSACCESS
-	portskarma = 0;
-#endif
-#ifdef DOCACCESS
-	dockarma = 0;
-#endif
-	karma = 0;
-	writeable = 0;
 	pw = getpwuid(getuid());
 	if (pw == NULL) {
 		msg("no user for uid %d", getuid());
@@ -109,11 +129,12 @@ main(int argc, char *argv[])
 		exit(1);
 	}
 
-	/* save in a static buffer */
+	/* Save in a static buffer. */
 	strlcpy(username, pw->pw_name, sizeof(username));
+	endpwent();
 
-	if (stat("/s/svn", &st) < 0) {
-		msg("Cannot stat %s", "/s/svn");
+	if (stat(SVNROOT, &st) < 0) {
+		msg("Cannot stat %s", SVNROOT);
 		exit(1);
 	}
 	repogid = st.st_gid;
@@ -121,6 +142,7 @@ main(int argc, char *argv[])
 		msg("unsafe repo gid %d\n", repogid);
 		exit(1);
 	}
+	writeable = 0;
 	ngroups = getgroups(NGROUPS_MAX, mygroups);
 	if (ngroups > 0) {
 		for (i = 0; i < ngroups; i++)
@@ -130,54 +152,48 @@ main(int argc, char *argv[])
 	if (!writeable)
 		printf("export SVN_READONLY=y\n");
 
-	fp = fopen(ACCESS, "r");
-	if (fp == NULL) {
-		msg("Cannot open %s", ACCESS);
+        if (argc != 2) {
+		msg("No repository given");
 		exit(1);
-	} else {
-		karma += karmacheck(fp, pw->pw_name);
-		fclose(fp);
 	}
-#ifdef DOCACCESS
-	if (karma == 0 && (fp = fopen(DOCACCESS, "r")) != NULL) {
-		dockarma += karmacheck(fp, pw->pw_name);
-		fclose(fp);
-	}
-#endif
-#ifdef PORTSACCESS
-	if (karma == 0 && (fp = fopen(PORTSACCESS, "r")) != NULL) {
-		portskarma += karmacheck(fp, pw->pw_name);
-		fclose(fp);
+	repo = 0;
+	/* Forward compat for base. */
+	if (strcmp(argv[1], "base") == 0 || strcmp(argv[1], "src") == 0)
+		 repo |= BASE;
+	else if (strcmp(argv[1], "doc") == 0)
+		repo |= DOC;
+	else if (strcmp(argv[1], "ports") == 0)
+		repo |= PORTS;
+	else {
+		msg("Invalid repository given: %s", argv[1]);
+		exit(1);
 	}
-#endif
 
-	if (karma == 0) {
-		strcpy(committag, "SVN_COMMIT_ATTRIB=");
-		comma = "";
+	karma = 0;
+#ifdef BASEACCESS
+	karma |= read_access(BASEACCESS, repo, BASE, username);
+#endif
 #ifdef DOCACCESS
-		if (dockarma > 0) {
-			strcat(committag, comma);
-			strcat(committag, "doc");
-			comma = ",";
-			karma += dockarma;
-		}
+	karma |= read_access(DOCACCESS, repo, DOC, username);
 #endif
 #ifdef PORTSACCESS
-		if (portskarma > 0) {
-			strcat(committag, comma);
-			strcat(committag, "ports");
-			comma = ",";
-			karma += portskarma;
-		}
+	karma |= read_access(PORTSACCESS, repo, PORTS, username);
 #endif
-		if (karma != 0) {
-			printf("export %s\n", committag);
-		}
-	}
-		
 	if (karma == 0) {
 		/* If still zero, its a readonly access */
 		printf("export SVN_READONLY=y\n");
+
+	} else if ((repo & karma) == 0) {
+		char committag[sizeof("src,doc,ports") + 1];
+		const char *comma;
+
+		committag[0] = '\0';
+		comma = "";
+		catcommittag(committag, &comma, karma, BASE, "src");
+		catcommittag(committag, &comma, karma, DOC, "doc");
+		catcommittag(committag, &comma, karma, PORTS, "ports");
+		printf("export SVN_COMMIT_ATTRIB=\"%s\"\n", committag);
 	}
+		
 	return (0);
 }


More information about the svn-src-svnadmin mailing list