Branko Čibej wrote:
> 
> Try getopt_tests.py.
Thanks, I'll take a look at it (probably not `til Wednesday).
>>+#if !( HAVE_UMASK && HAVE_SETUID && HAVE_SETGID )
>> 
>>
> 
> Urgh. We don't use spaces after open parens or before close parens.
Sorry!  I come from the "whitespace is free" school, so I have to rigorously 
supress my desire to lather everything in extra spaces... ;~)
> 
>>+       printf ("WARNING: --owner and --group unavailable under Win32");
> 
>    1. This warning isn't restricted to Win32 any more
Good point.  How does "...unavailable on this platform" sound?
>    2. Use svn_handle_warning instead of printf
I see lots of examples using "printf()" and "fprintf(stderr," in the commandline 
tools, and very few examples of using svn_handle_warning().  Since the error is 
not being thrown by one of the svn_* functions, it didn't seem appropriate to 
use that wrapper.  There is always a point where encapsulation becomes needless 
obfuscation; I'm not comfortable enough with svn code to know where that point is.
Thanks for taking the time to look over my code.  I learn, but slowly.  Having 
good clean code makes it easier, I must say.  New patch attached.
John
-- 
John Peacock
Director of Information Research and Technology
Rowman & Littlefield Publishing Group
4501 Forbes Boulevard
Suite H
Lanham, MD  20706
301-459-3366 x.5010
fax 301-429-5748
------------
LOG MESSAGE
------------
Implement two new options to the 'svnadmin create' command to explicitely 
create a new repository with rights appropriate for either
1) exclusive access by a single user/process
2) shared access by all members of an existing system group
This is likely to only be relevant to Unix-like operating systems,
where chmod(), setgid(), and setuid() are meaningful.
* configure.in
    Add tests to check for existance of chmod, setgid, and setuid
* subversion/svnadmin/main.c
    (#include) - need svn_private_config.h in order to get autoconf #define's
    (enum),(options_table),(cmd_table): add owner_id, group_id to option tables
    (subcommand_create): Add logic to get system UID and GID and switch
    current process to those values before calling svn_repos_create()
* doc/book/book/ch05.xml
    (svn-ch-5-sect-2): Add paragraph and link to discussion of --owner and
    --group options in svn-ch-5-sect-5.
    (svn-ch-5-sect-5): Document the use of --owner and --group to create
    the repository with specific rights for limited repository access.
Index: configure.in
===================================================================
--- configure.in	(revision 6915)
+++ configure.in	(working copy)
@@ -518,6 +518,12 @@
 esac
 AC_SUBST(INCLUDE_OUTPUTS)
 
+dnl
+dnl Check for support for umask, setuid, and setgid (needed by svnadmin)
+dnl
+
+AC_CHECK_FUNCS(umask setuid setgid)
+
 dnl Final step:  create the Makefile ----------------------------
 
 AC_CONFIG_FILES([Makefile])
Index: subversion/svnadmin/main.c
===================================================================
--- subversion/svnadmin/main.c	(revision 6915)
+++ subversion/svnadmin/main.c	(working copy)
@@ -25,7 +25,7 @@
 #include "svn_subst.h"
 #include "svn_path.h"
 #include "svn_config.h"
-
+#include "svn_private_config.h"
 #include "svnadmin.h"
 
 
@@ -79,7 +79,9 @@
     svnadmin__force_uuid,
     svnadmin__parent_dir,
     svnadmin__bdb_txn_nosync,
-    svnadmin__config_dir
+    svnadmin__config_dir,
+    svnadmin__owner_id,
+    svnadmin__group_id
   };
 
 /* Option codes and descriptions.
@@ -133,6 +135,12 @@
     {"config-dir", svnadmin__config_dir, 1,
      "read user configuration files from directory ARG"},
 
+    {"owner", svnadmin__owner_id, 1,
+     "create repository owned and usable by user ARG"},
+
+    {"group", svnadmin__group_id, 1,
+     "create repository owned and usable by group ARG"},
+
     {NULL}
   };
 
@@ -144,9 +152,13 @@
   {
     {"create", subcommand_create, {0},
      "usage: svnadmin create REPOS_PATH\n\n"
-     "Create a new, empty repository at REPOS_PATH.\n",
+     "Create a new, empty repository at REPOS_PATH.  The --owner and --group\n"
+     "options will create the repository with appropriate ownership and\n"
+     "permissions under most Unix-like O/S's (and do nothing on Win32), but\n"
+     "require that svnadmin be run as root.\n",
      {svnadmin__on_disk_template, svnadmin__in_repos_template,
-      svnadmin__bdb_txn_nosync, svnadmin__config_dir} },
+      svnadmin__bdb_txn_nosync, svnadmin__config_dir, 
+      svnadmin__owner_id, svnadmin__group_id} },
     
     {"createtxn", subcommand_createtxn, {0},
      "usage: svnadmin createtxn REPOS_PATH -r REVISION\n\n"
@@ -246,6 +258,8 @@
   const char *parent_dir;
 
   const char *config_dir;    /* Overriding Configuration Directory */
+  const char *owner_id;
+  const char *group_id;
 };
 
 /* This implements `svn_opt_subcommand_t'. */
@@ -264,6 +278,58 @@
                     APR_HASH_KEY_STRING, "1");
     }
 
+  /* If the user requested the repository be created as a specific
+   * owner and/or group, we need to lookup the system UID/GID and
+   * switch the current process to that user and group before 
+   * creating the repository.  In this case, svnadmin must be run
+   * as root, in order to be able to switch to an arbitrary user 
+   * and group.  This feature does not work (currently) under Win32.
+   */
+  if (opt_state->owner_id)
+    {
+#if !(HAVE_UMASK && HAVE_SETUID && HAVE_SETGID)
+       svn_handle_warning (stderr, svn_error_create
+           (SVN_ERR_INCORRECT_PARAMS, NULL,
+            "--owner and --group unavailable on this platform"));
+#else       
+       apr_uid_t retrieved_uid;
+       apr_gid_t retrieved_gid;
+       apr_status_t apr_err;
+
+       apr_err = apr_uid_get(&retrieved_uid, &retrieved_gid, 
+                             opt_state->owner_id, pool);
+
+       if (apr_err)
+         {
+           return svn_error_create
+             (apr_err, NULL, "failed to get owner's UID");
+         }
+
+       if (opt_state->group_id)
+         {
+           (void)umask(0007); /* permit group access */
+           apr_err = apr_gid_get(&retrieved_gid, 
+                                 opt_state->group_id, pool);
+           if (apr_err)
+             {
+               return svn_error_create
+                 (apr_err, NULL, "failed to get group's GID");
+             }
+	 }
+       else
+         {
+           (void)umask(0077); /* no group access */
+         }
+
+       if ( setgid(retrieved_gid) != 0 )
+         return svn_error_create (SVN_ERR_INCORRECT_PARAMS, NULL,
+                                   "problem setting gid (must be root)");
+       if ( setuid(retrieved_uid) != 0 )
+         return svn_error_createf (SVN_ERR_INCORRECT_PARAMS, NULL,
+                                   "problem setting uid (must be root)");
+#endif
+    }
+
   SVN_ERR (svn_config_get_config (&config, opt_state->config_dir, pool));
   SVN_ERR (svn_repos_create (&repos, opt_state->repository_path,
                              opt_state->on_disk, opt_state->in_repos, 
@@ -796,6 +862,12 @@
         opt_state.config_dir = apr_pstrdup (pool, svn_path_canonicalize(opt_arg,
                                                                        pool));
         break;
+      case svnadmin__group_id:
+        opt_state.group_id = apr_pstrdup (pool, opt_arg);
+        break;
+      case svnadmin__owner_id:
+        opt_state.owner_id = apr_pstrdup (pool, opt_arg);
+        break;
       default:
         {
           subcommand_help (NULL, NULL, pool);
Index: doc/book/book/ch05.xml
===================================================================
--- doc/book/book/ch05.xml	(revision 6915)
+++ doc/book/book/ch05.xml	(working copy)
@@ -170,6 +170,12 @@
       directory.  Initially, revision 0 also has a single revision
       property, <literal>svn:date</literal>, set to the time at which
       the repository was created.</para>
+
+    <para>If you need to limit the local file:// access to the repository
+      to a specific user or share it with a specific group, please see 
+      <xref linkend="svn-ch-5-sect-5"/>.  You should also consult that
+      section for one way to set the repository permissions for access 
+      via Apache or svnserver.</para>
           
     <para>You may have noticed that the path argument to
       <command>svnadmin</command> was just a regular filesystem path
@@ -2610,11 +2616,43 @@
       files?  Assuming you have a Unix-like operating system, a
       straightforward approach might be to place every potential
       repository user into a new <literal>svn</literal> group, and
-      make the repository wholly owned by that group.  But even that's
-      not enough, because a process may write to the database files
-      using an unfriendly umask—one which prevents access by
-      other users.</para>
+      make the repository wholly owned by that group.  Fortunately, 
+      <command>svnadmin create</command> has several options that
+      make this trivial under Unix-like operating systems.</para>
 
+    <para>If you want to initially create the repository so that it is
+      exclusively accessible by a single user (either because it is a 
+      private repository accessed via file:// or because you will only
+      access the repository via a specific non-priveledged account under
+      Apache or svnserver), you can use the following commands:</para>
+
+    <screen>
+$ su [enter root password]
+# svnadmin create --owner nobody /path/to/repository
+</screen>
+
+    <para>which will create a repository owned by the 'nobody' user, 
+      with exclusive (i.e. no group or other) rights.</para>
+
+    <para>On the other hand, if you want a group of local users to have
+      local file:// access (as well as possibly an Apache or svnserver
+      server), you can use something like the following commands:</para>
+
+    <screen>
+$ su [enter root password]
+# svnadmin create --group svn --owner admuser /path/to/repository
+</screen>
+
+    <para>which will create a repository owned by 'admuser' (typically
+      the user who will be managing the database, running recovery, etc).
+      The files will also have the group 'svn' (which needs to be created
+      and populated first), so that all users in that group will be able 
+      to use file:// access.</para>
+      
+    <para>But even that's not enough, because a process may write to the
+      database files using an unfriendly umask—one which prevents
+      access by other users.</para>
+
     <para>So the next step beyond setting up a common group for
       repository users is to force every repository-accessing process
       to use a sane umask.  For users accessing the repository
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@subversion.tigris.org
For additional commands, e-mail: dev-help@subversion.tigris.org
Received on Mon Sep 22 16:17:10 2003