[Python-checkins] cpython (2.7): Issue #4591: Uid and gid values larger than 2**31 are supported now.

serhiy.storchaka python-checkins at python.org
Tue Feb 12 08:36:46 CET 2013


http://hg.python.org/cpython/rev/035cbc654889
changeset:   82173:035cbc654889
branch:      2.7
parent:      82170:7cb403f8a865
user:        Serhiy Storchaka <storchaka at gmail.com>
date:        Tue Feb 12 09:27:53 2013 +0200
summary:
  Issue #4591: Uid and gid values larger than 2**31 are supported now.

files:
  Lib/test/test_posix.py |   29 +-
  Lib/test/test_pwd.py   |    9 +
  Makefile.pre.in        |    5 +
  Misc/NEWS              |    2 +
  Modules/grpmodule.c    |   20 +-
  Modules/posixmodule.c  |  349 +++++++++++++++++-----------
  Modules/posixmodule.h  |   25 ++
  Modules/pwdmodule.c    |   22 +-
  8 files changed, 308 insertions(+), 153 deletions(-)


diff --git a/Lib/test/test_posix.py b/Lib/test/test_posix.py
--- a/Lib/test/test_posix.py
+++ b/Lib/test/test_posix.py
@@ -222,10 +222,20 @@
         if hasattr(posix, 'stat'):
             self.assertTrue(posix.stat(test_support.TESTFN))
 
-    def _test_all_chown_common(self, chown_func, first_param):
+    def _test_all_chown_common(self, chown_func, first_param, stat_func):
         """Common code for chown, fchown and lchown tests."""
+        def check_stat():
+            if stat_func is not None:
+                stat = stat_func(first_param)
+                self.assertEqual(stat.st_uid, os.getuid())
+                self.assertEqual(stat.st_gid, os.getgid())
         # test a successful chown call
         chown_func(first_param, os.getuid(), os.getgid())
+        check_stat()
+        chown_func(first_param, -1, os.getgid())
+        check_stat()
+        chown_func(first_param, os.getuid(), -1)
+        check_stat()
 
         if os.getuid() == 0:
             try:
@@ -245,8 +255,12 @@
                                     "behavior")
         else:
             # non-root cannot chown to root, raises OSError
-            self.assertRaises(OSError, chown_func,
-                              first_param, 0, 0)
+            self.assertRaises(OSError, chown_func, first_param, 0, 0)
+            check_stat()
+            self.assertRaises(OSError, chown_func, first_param, -1, 0)
+            check_stat()
+            self.assertRaises(OSError, chown_func, first_param, 0, -1)
+            check_stat()
 
     @unittest.skipUnless(hasattr(posix, 'chown'), "test needs os.chown()")
     def test_chown(self):
@@ -256,7 +270,8 @@
 
         # re-create the file
         open(test_support.TESTFN, 'w').close()
-        self._test_all_chown_common(posix.chown, test_support.TESTFN)
+        self._test_all_chown_common(posix.chown, test_support.TESTFN,
+                                    getattr(posix, 'stat', None))
 
     @unittest.skipUnless(hasattr(posix, 'fchown'), "test needs os.fchown()")
     def test_fchown(self):
@@ -266,7 +281,8 @@
         test_file = open(test_support.TESTFN, 'w')
         try:
             fd = test_file.fileno()
-            self._test_all_chown_common(posix.fchown, fd)
+            self._test_all_chown_common(posix.fchown, fd,
+                                        getattr(posix, 'fstat', None))
         finally:
             test_file.close()
 
@@ -275,7 +291,8 @@
         os.unlink(test_support.TESTFN)
         # create a symlink
         os.symlink(_DUMMY_SYMLINK, test_support.TESTFN)
-        self._test_all_chown_common(posix.lchown, test_support.TESTFN)
+        self._test_all_chown_common(posix.lchown, test_support.TESTFN,
+                                    getattr(posix, 'lstat', None))
 
     def test_chdir(self):
         if hasattr(posix, 'chdir'):
diff --git a/Lib/test/test_pwd.py b/Lib/test/test_pwd.py
--- a/Lib/test/test_pwd.py
+++ b/Lib/test/test_pwd.py
@@ -49,7 +49,9 @@
 
     def test_errors(self):
         self.assertRaises(TypeError, pwd.getpwuid)
+        self.assertRaises(TypeError, pwd.getpwuid, 3.14)
         self.assertRaises(TypeError, pwd.getpwnam)
+        self.assertRaises(TypeError, pwd.getpwnam, 42)
         self.assertRaises(TypeError, pwd.getpwall, 42)
 
         # try to get some errors
@@ -93,6 +95,13 @@
         self.assertNotIn(fakeuid, byuids)
         self.assertRaises(KeyError, pwd.getpwuid, fakeuid)
 
+        # -1 shouldn't be a valid uid because it has a special meaning in many
+        # uid-related functions
+        self.assertRaises(KeyError, pwd.getpwuid, -1)
+        # should be out of uid_t range
+        self.assertRaises(KeyError, pwd.getpwuid, 2**128)
+        self.assertRaises(KeyError, pwd.getpwuid, -2**128)
+
 def test_main():
     test_support.run_unittest(PwdTest)
 
diff --git a/Makefile.pre.in b/Makefile.pre.in
--- a/Makefile.pre.in
+++ b/Makefile.pre.in
@@ -579,6 +579,11 @@
 Modules/python.o: $(srcdir)/Modules/python.c
 	$(MAINCC) -c $(PY_CFLAGS) -o $@ $(srcdir)/Modules/python.c
 
+Modules/posixmodule.o: $(srcdir)/Modules/posixmodule.c $(srcdir)/Modules/posixmodule.h
+
+Modules/grpmodule.o: $(srcdir)/Modules/grpmodule.c $(srcdir)/Modules/posixmodule.h
+
+Modules/pwdmodule.o: $(srcdir)/Modules/pwdmodule.c $(srcdir)/Modules/posixmodule.h
 
 $(GRAMMAR_H): $(GRAMMAR_INPUT) $(PGENSRCS)
 		@$(MKDIR_P) Include
diff --git a/Misc/NEWS b/Misc/NEWS
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -204,6 +204,8 @@
 
 - Issue #17052: unittest discovery should use self.testLoader.
 
+- Issue #4591: Uid and gid values larger than 2**31 are supported now.
+
 - Issue #17141: random.vonmisesvariate() no more hangs for large kappas.
 
 - Issue #17149: Fix random.vonmisesvariate to always return results in
diff --git a/Modules/grpmodule.c b/Modules/grpmodule.c
--- a/Modules/grpmodule.c
+++ b/Modules/grpmodule.c
@@ -3,8 +3,8 @@
 
 #include "Python.h"
 #include "structseq.h"
+#include "posixmodule.h"
 
-#include <sys/types.h>
 #include <grp.h>
 
 static PyStructSequence_Field struct_group_type_fields[] = {
@@ -70,7 +70,7 @@
 	    Py_INCREF(Py_None);
     }
 #endif
-    SET(setIndex++, PyInt_FromLong((long) p->gr_gid));
+    SET(setIndex++, _PyInt_FromGid(p->gr_gid));
     SET(setIndex++, w);
 #undef SET
 
@@ -86,17 +86,25 @@
 grp_getgrgid(PyObject *self, PyObject *pyo_id)
 {
     PyObject *py_int_id;
-    unsigned int gid;
+    gid_t gid;
     struct group *p;
 
     py_int_id = PyNumber_Int(pyo_id);
     if (!py_int_id)
-	    return NULL;
-    gid = PyInt_AS_LONG(py_int_id);
+            return NULL;
+    if (!_Py_Gid_Converter(py_int_id, &gid)) {
+        Py_DECREF(py_int_id);
+        return NULL;
+    }
     Py_DECREF(py_int_id);
 
     if ((p = getgrgid(gid)) == NULL) {
-	PyErr_Format(PyExc_KeyError, "getgrgid(): gid not found: %d", gid);
+        if (gid < 0)
+            PyErr_Format(PyExc_KeyError,
+                         "getgrgid(): gid not found: %ld", (long)gid);
+        else
+            PyErr_Format(PyExc_KeyError,
+                         "getgrgid(): gid not found: %lu", (unsigned long)gid);
         return NULL;
     }
     return mkgrent(p);
diff --git a/Modules/posixmodule.c b/Modules/posixmodule.c
--- a/Modules/posixmodule.c
+++ b/Modules/posixmodule.c
@@ -27,6 +27,9 @@
 
 #include "Python.h"
 #include "structseq.h"
+#ifndef MS_WINDOWS
+#include "posixmodule.h"
+#endif
 
 #if defined(__VMS)
 #    include <unixio.h>
@@ -347,6 +350,134 @@
 #endif
 #endif
 
+
+#ifndef MS_WINDOWS
+PyObject *
+_PyInt_FromUid(uid_t uid)
+{
+    if (uid <= LONG_MAX)
+        return PyInt_FromLong(uid);
+    return PyLong_FromUnsignedLong(uid);
+}
+
+PyObject *
+_PyInt_FromGid(gid_t gid)
+{
+    if (gid <= LONG_MAX)
+        return PyInt_FromLong(gid);
+    return PyLong_FromUnsignedLong(gid);
+}
+
+int
+_Py_Uid_Converter(PyObject *obj, void *p)
+{
+    int overflow;
+    long result;
+    if (PyFloat_Check(obj)) {
+        PyErr_SetString(PyExc_TypeError,
+                        "integer argument expected, got float");
+        return 0;
+    }
+    result = PyLong_AsLongAndOverflow(obj, &overflow);
+    if (overflow < 0)
+        goto OverflowDown;
+    if (!overflow && result == -1) {
+        /* error or -1 */
+        if (PyErr_Occurred())
+            return 0;
+        *(uid_t *)p = (uid_t)-1;
+    }
+    else {
+        /* unsigned uid_t */
+        unsigned long uresult;
+        if (overflow > 0) {
+            uresult = PyLong_AsUnsignedLong(obj);
+            if (PyErr_Occurred()) {
+                if (PyErr_ExceptionMatches(PyExc_OverflowError))
+                    goto OverflowUp;
+                return 0;
+            }
+            if ((uid_t)uresult == (uid_t)-1)
+                goto OverflowUp;
+        } else {
+            if (result < 0)
+                goto OverflowDown;
+            uresult = result;
+        }
+        if (sizeof(uid_t) < sizeof(long) &&
+            (unsigned long)(uid_t)uresult != uresult)
+            goto OverflowUp;
+        *(uid_t *)p = (uid_t)uresult;
+    }
+    return 1;
+
+OverflowDown:
+    PyErr_SetString(PyExc_OverflowError,
+                    "user id is less than minimum");
+    return 0;
+
+OverflowUp:
+    PyErr_SetString(PyExc_OverflowError,
+                    "user id is greater than maximum");
+    return 0;
+}
+
+int
+_Py_Gid_Converter(PyObject *obj, void *p)
+{
+    int overflow;
+    long result;
+    if (PyFloat_Check(obj)) {
+        PyErr_SetString(PyExc_TypeError,
+                        "integer argument expected, got float");
+        return 0;
+    }
+    result = PyLong_AsLongAndOverflow(obj, &overflow);
+    if (overflow < 0)
+        goto OverflowDown;
+    if (!overflow && result == -1) {
+        /* error or -1 */
+        if (PyErr_Occurred())
+            return 0;
+        *(gid_t *)p = (gid_t)-1;
+    }
+    else {
+        /* unsigned gid_t */
+        unsigned long uresult;
+        if (overflow > 0) {
+            uresult = PyLong_AsUnsignedLong(obj);
+            if (PyErr_Occurred()) {
+                if (PyErr_ExceptionMatches(PyExc_OverflowError))
+                    goto OverflowUp;
+                return 0;
+            }
+            if ((gid_t)uresult == (gid_t)-1)
+                goto OverflowUp;
+        } else {
+            if (result < 0)
+                goto OverflowDown;
+            uresult = result;
+        }
+        if (sizeof(gid_t) < sizeof(long) &&
+            (unsigned long)(gid_t)uresult != uresult)
+            goto OverflowUp;
+        *(gid_t *)p = (gid_t)uresult;
+    }
+    return 1;
+
+OverflowDown:
+    PyErr_SetString(PyExc_OverflowError,
+                    "group id is less than minimum");
+    return 0;
+
+OverflowUp:
+    PyErr_SetString(PyExc_OverflowError,
+                    "group id is greater than maximum");
+    return 0;
+}
+#endif /* MS_WINDOWS */
+
+
 #if defined _MSC_VER && _MSC_VER >= 1400
 /* Microsoft CRT in VS2005 and higher will verify that a filehandle is
  * valid and raise an assertion if it isn't.
@@ -1306,8 +1437,13 @@
     PyStructSequence_SET_ITEM(v, 2, PyInt_FromLong((long)st->st_dev));
 #endif
     PyStructSequence_SET_ITEM(v, 3, PyInt_FromLong((long)st->st_nlink));
-    PyStructSequence_SET_ITEM(v, 4, PyInt_FromLong((long)st->st_uid));
-    PyStructSequence_SET_ITEM(v, 5, PyInt_FromLong((long)st->st_gid));
+#if defined(MS_WINDOWS)
+    PyStructSequence_SET_ITEM(v, 4, PyInt_FromLong(0));
+    PyStructSequence_SET_ITEM(v, 5, PyInt_FromLong(0));
+#else
+    PyStructSequence_SET_ITEM(v, 4, _PyInt_FromUid(st->st_uid));
+    PyStructSequence_SET_ITEM(v, 5, _PyInt_FromGid(st->st_gid));
+#endif
 #ifdef HAVE_LARGEFILE_SUPPORT
     PyStructSequence_SET_ITEM(v, 6,
                               PyLong_FromLongLong((PY_LONG_LONG)st->st_size));
@@ -1884,14 +2020,16 @@
 posix_chown(PyObject *self, PyObject *args)
 {
     char *path = NULL;
-    long uid, gid;
+    uid_t uid;
+    gid_t gid;
     int res;
-    if (!PyArg_ParseTuple(args, "etll:chown",
+    if (!PyArg_ParseTuple(args, "etO&O&:chown",
                           Py_FileSystemDefaultEncoding, &path,
-                          &uid, &gid))
+                          _Py_Uid_Converter, &uid,
+                          _Py_Gid_Converter, &gid))
         return NULL;
     Py_BEGIN_ALLOW_THREADS
-    res = chown(path, (uid_t) uid, (gid_t) gid);
+    res = chown(path, uid, gid);
     Py_END_ALLOW_THREADS
     if (res < 0)
         return posix_error_with_allocated_filename(path);
@@ -1911,12 +2049,15 @@
 posix_fchown(PyObject *self, PyObject *args)
 {
     int fd;
-    long uid, gid;
+    uid_t uid;
+    gid_t gid;
     int res;
-    if (!PyArg_ParseTuple(args, "ill:chown", &fd, &uid, &gid))
+    if (!PyArg_ParseTuple(args, "iO&O&:fchown", &fd,
+                          _Py_Uid_Converter, &uid,
+                          _Py_Gid_Converter, &gid))
         return NULL;
     Py_BEGIN_ALLOW_THREADS
-    res = fchown(fd, (uid_t) uid, (gid_t) gid);
+    res = fchown(fd, uid, gid);
     Py_END_ALLOW_THREADS
     if (res < 0)
         return posix_error();
@@ -1934,14 +2075,16 @@
 posix_lchown(PyObject *self, PyObject *args)
 {
     char *path = NULL;
-    long uid, gid;
+    uid_t uid;
+    gid_t gid;
     int res;
-    if (!PyArg_ParseTuple(args, "etll:lchown",
+    if (!PyArg_ParseTuple(args, "etO&O&:lchown",
                           Py_FileSystemDefaultEncoding, &path,
-                          &uid, &gid))
+                          _Py_Uid_Converter, &uid,
+                          _Py_Gid_Converter, &gid))
         return NULL;
     Py_BEGIN_ALLOW_THREADS
-    res = lchown(path, (uid_t) uid, (gid_t) gid);
+    res = lchown(path, uid, gid);
     Py_END_ALLOW_THREADS
     if (res < 0)
         return posix_error_with_allocated_filename(path);
@@ -3844,7 +3987,7 @@
 static PyObject *
 posix_getegid(PyObject *self, PyObject *noargs)
 {
-    return PyInt_FromLong((long)getegid());
+    return _PyInt_FromGid(getegid());
 }
 #endif
 
@@ -3857,7 +4000,7 @@
 static PyObject *
 posix_geteuid(PyObject *self, PyObject *noargs)
 {
-    return PyInt_FromLong((long)geteuid());
+    return _PyInt_FromUid(geteuid());
 }
 #endif
 
@@ -3870,7 +4013,7 @@
 static PyObject *
 posix_getgid(PyObject *self, PyObject *noargs)
 {
-    return PyInt_FromLong((long)getgid());
+    return _PyInt_FromGid(getgid());
 }
 #endif
 
@@ -3945,7 +4088,7 @@
     if (result != NULL) {
         int i;
         for (i = 0; i < n; ++i) {
-            PyObject *o = PyInt_FromLong((long)alt_grouplist[i]);
+            PyObject *o = _PyInt_FromGid(alt_grouplist[i]);
             if (o == NULL) {
                 Py_DECREF(result);
                 result = NULL;
@@ -3974,12 +4117,22 @@
 posix_initgroups(PyObject *self, PyObject *args)
 {
     char *username;
-    long gid;
-
-    if (!PyArg_ParseTuple(args, "sl:initgroups", &username, &gid))
-        return NULL;
-
-    if (initgroups(username, (gid_t) gid) == -1)
+#ifdef __APPLE__
+    int gid;
+#else
+    gid_t gid;
+#endif
+
+#ifdef __APPLE__
+    if (!PyArg_ParseTuple(args, "si:initgroups", &username,
+                          &gid))
+#else
+    if (!PyArg_ParseTuple(args, "sO&:initgroups", &username,
+                          _Py_Gid_Converter, &gid))
+#endif
+        return NULL;
+
+    if (initgroups(username, gid) == -1)
         return PyErr_SetFromErrno(PyExc_OSError);
 
     Py_INCREF(Py_None);
@@ -4093,7 +4246,7 @@
 static PyObject *
 posix_getuid(PyObject *self, PyObject *noargs)
 {
-    return PyInt_FromLong((long)getuid());
+    return _PyInt_FromUid(getuid());
 }
 #endif
 
@@ -5740,15 +5893,9 @@
 static PyObject *
 posix_setuid(PyObject *self, PyObject *args)
 {
-    long uid_arg;
     uid_t uid;
-    if (!PyArg_ParseTuple(args, "l:setuid", &uid_arg))
-        return NULL;
-    uid = uid_arg;
-    if (uid != uid_arg) {
-        PyErr_SetString(PyExc_OverflowError, "user id too big");
-        return NULL;
-    }
+    if (!PyArg_ParseTuple(args, "O&:setuid", _Py_Uid_Converter, &uid))
+        return NULL;
     if (setuid(uid) < 0)
         return posix_error();
     Py_INCREF(Py_None);
@@ -5765,15 +5912,9 @@
 static PyObject *
 posix_seteuid (PyObject *self, PyObject *args)
 {
-    long euid_arg;
     uid_t euid;
-    if (!PyArg_ParseTuple(args, "l", &euid_arg))
-        return NULL;
-    euid = euid_arg;
-    if (euid != euid_arg) {
-        PyErr_SetString(PyExc_OverflowError, "user id too big");
-        return NULL;
-    }
+    if (!PyArg_ParseTuple(args, "O&:seteuid", _Py_Uid_Converter, &euid))
+        return NULL;
     if (seteuid(euid) < 0) {
         return posix_error();
     } else {
@@ -5791,15 +5932,9 @@
 static PyObject *
 posix_setegid (PyObject *self, PyObject *args)
 {
-    long egid_arg;
     gid_t egid;
-    if (!PyArg_ParseTuple(args, "l", &egid_arg))
-        return NULL;
-    egid = egid_arg;
-    if (egid != egid_arg) {
-        PyErr_SetString(PyExc_OverflowError, "group id too big");
-        return NULL;
-    }
+    if (!PyArg_ParseTuple(args, "O&:setegid", _Py_Gid_Converter, &egid))
+        return NULL;
     if (setegid(egid) < 0) {
         return posix_error();
     } else {
@@ -5817,23 +5952,11 @@
 static PyObject *
 posix_setreuid (PyObject *self, PyObject *args)
 {
-    long ruid_arg, euid_arg;
     uid_t ruid, euid;
-    if (!PyArg_ParseTuple(args, "ll", &ruid_arg, &euid_arg))
-        return NULL;
-    if (ruid_arg == -1)
-        ruid = (uid_t)-1;  /* let the compiler choose how -1 fits */
-    else
-        ruid = ruid_arg;  /* otherwise, assign from our long */
-    if (euid_arg == -1)
-        euid = (uid_t)-1;
-    else
-        euid = euid_arg;
-    if ((euid_arg != -1 && euid != euid_arg) ||
-        (ruid_arg != -1 && ruid != ruid_arg)) {
-        PyErr_SetString(PyExc_OverflowError, "user id too big");
-        return NULL;
-    }
+    if (!PyArg_ParseTuple(args, "O&O&:setreuid",
+                          _Py_Uid_Converter, &ruid,
+                          _Py_Uid_Converter, &euid))
+        return NULL;
     if (setreuid(ruid, euid) < 0) {
         return posix_error();
     } else {
@@ -5851,23 +5974,11 @@
 static PyObject *
 posix_setregid (PyObject *self, PyObject *args)
 {
-    long rgid_arg, egid_arg;
     gid_t rgid, egid;
-    if (!PyArg_ParseTuple(args, "ll", &rgid_arg, &egid_arg))
-        return NULL;
-    if (rgid_arg == -1)
-        rgid = (gid_t)-1;  /* let the compiler choose how -1 fits */
-    else
-        rgid = rgid_arg;  /* otherwise, assign from our long */
-    if (egid_arg == -1)
-        egid = (gid_t)-1;
-    else
-        egid = egid_arg;
-    if ((egid_arg != -1 && egid != egid_arg) ||
-        (rgid_arg != -1 && rgid != rgid_arg)) {
-        PyErr_SetString(PyExc_OverflowError, "group id too big");
-        return NULL;
-    }
+    if (!PyArg_ParseTuple(args, "O&O&:setregid",
+                          _Py_Gid_Converter, &rgid,
+                          _Py_Gid_Converter, &egid))
+        return NULL;
     if (setregid(rgid, egid) < 0) {
         return posix_error();
     } else {
@@ -5885,15 +5996,9 @@
 static PyObject *
 posix_setgid(PyObject *self, PyObject *args)
 {
-    long gid_arg;
     gid_t gid;
-    if (!PyArg_ParseTuple(args, "l:setgid", &gid_arg))
-        return NULL;
-    gid = gid_arg;
-    if (gid != gid_arg) {
-        PyErr_SetString(PyExc_OverflowError, "group id too big");
-        return NULL;
-    }
+    if (!PyArg_ParseTuple(args, "O&:setgid", _Py_Gid_Converter, &gid))
+        return NULL;
     if (setgid(gid) < 0)
         return posix_error();
     Py_INCREF(Py_None);
@@ -5926,35 +6031,13 @@
         elem = PySequence_GetItem(groups, i);
         if (!elem)
             return NULL;
-        if (!PyInt_Check(elem)) {
-            if (!PyLong_Check(elem)) {
-                PyErr_SetString(PyExc_TypeError,
-                                "groups must be integers");
-                Py_DECREF(elem);
-                return NULL;
-            } else {
-                unsigned long x = PyLong_AsUnsignedLong(elem);
-                if (PyErr_Occurred()) {
-                    PyErr_SetString(PyExc_TypeError,
-                                    "group id too big");
-                    Py_DECREF(elem);
-                    return NULL;
-                }
-                grouplist[i] = x;
-                /* read back to see if it fits in gid_t */
-                if (grouplist[i] != x) {
-                    PyErr_SetString(PyExc_TypeError,
-                                    "group id too big");
-                    Py_DECREF(elem);
-                    return NULL;
-                }
-            }
+        if (!PyInt_Check(elem) && !PyLong_Check(elem)) {
+            PyErr_SetString(PyExc_TypeError,
+                            "groups must be integers");
+            Py_DECREF(elem);
+            return NULL;
         } else {
-            long x  = PyInt_AsLong(elem);
-            grouplist[i] = x;
-            if (grouplist[i] != x) {
-                PyErr_SetString(PyExc_TypeError,
-                                "group id too big");
+            if (!_Py_Gid_Converter(elem, &grouplist[i])) {
                 Py_DECREF(elem);
                 return NULL;
             }
@@ -8580,9 +8663,11 @@
 static PyObject*
 posix_setresuid (PyObject *self, PyObject *args)
 {
-    /* We assume uid_t is no larger than a long. */
-    long ruid, euid, suid;
-    if (!PyArg_ParseTuple(args, "lll", &ruid, &euid, &suid))
+    uid_t ruid, euid, suid;
+    if (!PyArg_ParseTuple(args, "O&O&O&:setresuid",
+                          _Py_Uid_Converter, &ruid,
+                          _Py_Uid_Converter, &euid,
+                          _Py_Uid_Converter, &suid))
         return NULL;
     if (setresuid(ruid, euid, suid) < 0)
         return posix_error();
@@ -8598,9 +8683,11 @@
 static PyObject*
 posix_setresgid (PyObject *self, PyObject *args)
 {
-    /* We assume uid_t is no larger than a long. */
-    long rgid, egid, sgid;
-    if (!PyArg_ParseTuple(args, "lll", &rgid, &egid, &sgid))
+    gid_t rgid, egid, sgid;
+    if (!PyArg_ParseTuple(args, "O&O&O&:setresgid",
+                          _Py_Gid_Converter, &rgid,
+                          _Py_Gid_Converter, &egid,
+                          _Py_Gid_Converter, &sgid))
         return NULL;
     if (setresgid(rgid, egid, sgid) < 0)
         return posix_error();
@@ -8617,14 +8704,11 @@
 posix_getresuid (PyObject *self, PyObject *noargs)
 {
     uid_t ruid, euid, suid;
-    long l_ruid, l_euid, l_suid;
     if (getresuid(&ruid, &euid, &suid) < 0)
         return posix_error();
-    /* Force the values into long's as we don't know the size of uid_t. */
-    l_ruid = ruid;
-    l_euid = euid;
-    l_suid = suid;
-    return Py_BuildValue("(lll)", l_ruid, l_euid, l_suid);
+    return Py_BuildValue("(NNN)", _PyInt_FromUid(ruid),
+                                  _PyInt_FromUid(euid),
+                                  _PyInt_FromUid(suid));
 }
 #endif
 
@@ -8637,14 +8721,11 @@
 posix_getresgid (PyObject *self, PyObject *noargs)
 {
     uid_t rgid, egid, sgid;
-    long l_rgid, l_egid, l_sgid;
     if (getresgid(&rgid, &egid, &sgid) < 0)
         return posix_error();
-    /* Force the values into long's as we don't know the size of uid_t. */
-    l_rgid = rgid;
-    l_egid = egid;
-    l_sgid = sgid;
-    return Py_BuildValue("(lll)", l_rgid, l_egid, l_sgid);
+    return Py_BuildValue("(NNN)", _PyInt_FromGid(rgid),
+                                  _PyInt_FromGid(egid),
+                                  _PyInt_FromGid(sgid));
 }
 #endif
 
diff --git a/Modules/posixmodule.h b/Modules/posixmodule.h
new file mode 100644
--- /dev/null
+++ b/Modules/posixmodule.h
@@ -0,0 +1,25 @@
+/* Declarations shared between the different POSIX-related modules */
+
+#ifndef Py_POSIXMODULE_H
+#define Py_POSIXMODULE_H
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+
+#ifndef Py_LIMITED_API
+#ifndef MS_WINDOWS
+PyAPI_FUNC(PyObject *) _PyInt_FromUid(uid_t);
+PyAPI_FUNC(PyObject *) _PyInt_FromGid(gid_t);
+PyAPI_FUNC(int) _Py_Uid_Converter(PyObject *, void *);
+PyAPI_FUNC(int) _Py_Gid_Converter(PyObject *, void *);
+#endif /* MS_WINDOWS */
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* !Py_POSIXMODULE_H */
diff --git a/Modules/pwdmodule.c b/Modules/pwdmodule.c
--- a/Modules/pwdmodule.c
+++ b/Modules/pwdmodule.c
@@ -3,8 +3,8 @@
 
 #include "Python.h"
 #include "structseq.h"
+#include "posixmodule.h"
 
-#include <sys/types.h>
 #include <pwd.h>
 
 static PyStructSequence_Field struct_pwd_type_fields[] = {
@@ -73,8 +73,8 @@
 #else
     SETS(setIndex++, p->pw_passwd);
 #endif
-    SETI(setIndex++, p->pw_uid);
-    SETI(setIndex++, p->pw_gid);
+    PyStructSequence_SET_ITEM(v, setIndex++, _PyInt_FromUid(p->pw_uid));
+    PyStructSequence_SET_ITEM(v, setIndex++, _PyInt_FromGid(p->pw_gid));
 #ifdef __VMS
     SETS(setIndex++, "");
 #else
@@ -103,13 +103,21 @@
 static PyObject *
 pwd_getpwuid(PyObject *self, PyObject *args)
 {
-    unsigned int uid;
+    uid_t uid;
     struct passwd *p;
-    if (!PyArg_ParseTuple(args, "I:getpwuid", &uid))
+    if (!PyArg_ParseTuple(args, "O&:getpwuid", _Py_Uid_Converter, &uid)) {
+        if (PyErr_ExceptionMatches(PyExc_OverflowError))
+            PyErr_Format(PyExc_KeyError,
+                         "getpwuid(): uid not found");
         return NULL;
+    }
     if ((p = getpwuid(uid)) == NULL) {
-        PyErr_Format(PyExc_KeyError,
-                     "getpwuid(): uid not found: %d", uid);
+        if (uid < 0)
+            PyErr_Format(PyExc_KeyError,
+                         "getpwuid(): uid not found: %ld", (long)uid);
+        else
+            PyErr_Format(PyExc_KeyError,
+                         "getpwuid(): uid not found: %lu", (unsigned long)uid);
         return NULL;
     }
     return mkpwent(p);

-- 
Repository URL: http://hg.python.org/cpython


More information about the Python-checkins mailing list