[CalendarServer-changes] [4116] CalendarServer/trunk/lib-patches/Twisted/twisted.python.util.patch

source_changes at macosforge.org source_changes at macosforge.org
Thu Apr 30 11:02:04 PDT 2009


Revision: 4116
          http://trac.macosforge.org/projects/calendarserver/changeset/4116
Author:   sagen at apple.com
Date:     2009-04-30 11:02:03 -0700 (Thu, 30 Apr 2009)
Log Message:
-----------
Use the libc implementation of initgroups if possible, since the python implementation doesn't scale to large numbers of groups

Added Paths:
-----------
    CalendarServer/trunk/lib-patches/Twisted/twisted.python.util.patch

Added: CalendarServer/trunk/lib-patches/Twisted/twisted.python.util.patch
===================================================================
--- CalendarServer/trunk/lib-patches/Twisted/twisted.python.util.patch	                        (rev 0)
+++ CalendarServer/trunk/lib-patches/Twisted/twisted.python.util.patch	2009-04-30 18:02:03 UTC (rev 4116)
@@ -0,0 +1,180 @@
+Index: twisted/python/util.py
+===================================================================
+--- twisted/python/util.py	(revision 19773)
++++ twisted/python/util.py	(working copy)
+@@ -561,83 +561,107 @@
+     L2.sort()
+     return [e[2] for e in L2]
+ 
++
++# The python implementation of initgroups below, which iterates all groups,
++# doesn't scale, so use the libc version if available:
++
+ try:
+-    import pwd, grp
+-    from os import setgroups, getgroups
+-    
+-    def _setgroups_until_success(l):
+-        while(1):
+-            # NASTY NASTY HACK (but glibc does it so it must be okay):
+-            # In case sysconfig didn't give the right answer, find the limit
+-            # on max groups by just looping, trying to set fewer and fewer
+-            # groups each time until it succeeds.
++    from ctypes import *
++    import ctypes.util
++    hasCtypes = True
++except ImportError:
++    hasCtypes = False
++
++if sys.platform == "darwin" and hasCtypes:
++    import pwd
++
++    libc = cdll.LoadLibrary(ctypes.util.find_library("libc"))
++
++    def initgroups(uid, primaryGid):
++        c_gid = c_int(primaryGid)
++        username = pwd.getpwuid(uid)[0]
++        c_username = c_char_p(username)
++        return libc.initgroups(c_username, c_gid)
++
++else:
++    # Original twisted implementation
++    try:
++        import pwd, grp
++        from os import setgroups, getgroups
++        
++        def _setgroups_until_success(l):
++            while(1):
++                # NASTY NASTY HACK (but glibc does it so it must be okay):
++                # In case sysconfig didn't give the right answer, find the limit
++                # on max groups by just looping, trying to set fewer and fewer
++                # groups each time until it succeeds.
++                try:
++                    setgroups(l)
++                except ValueError:
++                    # This exception comes from python itself restricting
++                    # number of groups allowed.
++                    if len(l) > 1:
++                        del l[-1]
++                    else:
++                        raise
++                except OSError, e:
++                    if e.errno == errno.EINVAL and len(l) > 1:
++                        # This comes from the OS saying too many groups
++                        del l[-1]
++                    else:
++                        raise
++                else:
++                    # Success, yay!
++                    return
++                
++        def initgroups(uid, primaryGid):
++            """Initializes the group access list.
++
++            This is done by reading the group database /etc/group and using all
++            groups of which C{uid} is a member.  The additional group
++            C{primaryGid} is also added to the list.
++
++            If the given user is a member of more than C{NGROUPS}, arbitrary
++            groups will be silently discarded to bring the number below that
++            limit.
++            """       
+             try:
+-                setgroups(l)
+-            except ValueError:
+-                # This exception comes from python itself restricting
+-                # number of groups allowed.
+-                if len(l) > 1:
+-                    del l[-1]
+-                else:
+-                    raise
++                # Try to get the maximum number of groups
++                max_groups = os.sysconf("SC_NGROUPS_MAX")
++            except:
++                # No predefined limit
++                max_groups = 0
++            
++            username = pwd.getpwuid(uid)[0]
++            l = []
++            if primaryGid is not None:
++                l.append(primaryGid)
++            for groupname, password, gid, userlist in grp.getgrall():
++                if username in userlist:
++                    l.append(gid)
++                    if len(l) == max_groups:
++                        break # No more groups, ignore any more
++            try:
++                _setgroups_until_success(l)
+             except OSError, e:
+-                if e.errno == errno.EINVAL and len(l) > 1:
+-                    # This comes from the OS saying too many groups
+-                    del l[-1]
++                # We might be able to remove this code now that we
++                # don't try to setgid/setuid even when not asked to.
++                if e.errno == errno.EPERM:
++                    for g in getgroups():
++                        if g not in l:
++                            raise
+                 else:
+                     raise
+-            else:
+-                # Success, yay!
+-                return
+-            
+-    def initgroups(uid, primaryGid):
+-        """Initializes the group access list.
++                                        
+ 
+-        This is done by reading the group database /etc/group and using all
+-        groups of which C{uid} is a member.  The additional group
+-        C{primaryGid} is also added to the list.
++    except:
++        def initgroups(uid, primaryGid):
++            """Do nothing.
+ 
+-        If the given user is a member of more than C{NGROUPS}, arbitrary
+-        groups will be silently discarded to bring the number below that
+-        limit.
+-        """       
+-        try:
+-            # Try to get the maximum number of groups
+-            max_groups = os.sysconf("SC_NGROUPS_MAX")
+-        except:
+-            # No predefined limit
+-            max_groups = 0
+-        
+-        username = pwd.getpwuid(uid)[0]
+-        l = []
+-        if primaryGid is not None:
+-            l.append(primaryGid)
+-        for groupname, password, gid, userlist in grp.getgrall():
+-            if username in userlist:
+-                l.append(gid)
+-                if len(l) == max_groups:
+-                    break # No more groups, ignore any more
+-        try:
+-            _setgroups_until_success(l)
+-        except OSError, e:
+-            # We might be able to remove this code now that we
+-            # don't try to setgid/setuid even when not asked to.
+-            if e.errno == errno.EPERM:
+-                for g in getgroups():
+-                    if g not in l:
+-                        raise
+-            else:
+-                raise
+-                                    
++            Underlying platform support require to manipulate groups is missing.
++            """
+ 
+-except:
+-    def initgroups(uid, primaryGid):
+-        """Do nothing.
+ 
+-        Underlying platform support require to manipulate groups is missing.
+-        """
+-
+-
+ def switchUID(uid, gid, euid=False):
+     if euid:
+         setuid = os.seteuid
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.macosforge.org/pipermail/calendarserver-changes/attachments/20090430/6e74290f/attachment.html>


More information about the calendarserver-changes mailing list