[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