Author: Ronan Lamy <ronan.l...@gmail.com>
Branch: follow_symlinks
Changeset: r83372:d8c010696602
Date: 2016-03-25 20:42 +0000
http://bitbucket.org/pypy/pypy/changeset/d8c010696602/

Log:    Implement missing features in chmod()

diff --git a/pypy/module/posix/interp_posix.py 
b/pypy/module/posix/interp_posix.py
--- a/pypy/module/posix/interp_posix.py
+++ b/pypy/module/posix/interp_posix.py
@@ -1,6 +1,7 @@
 import os
 import sys
 from math import modf
+from errno import ENOTSUP, EOPNOTSUPP
 
 from rpython.rlib import rposix, rposix_stat
 from rpython.rlib import objectmodel, rurandom
@@ -113,19 +114,22 @@
     DEFAULT_DIR_FD = -100
 DIR_FD_AVAILABLE = False
 
-def _unwrap_fd(space, w_value):
+def unwrap_fd(space, w_value):
+    return space.c_int_w(w_value)
+
+def _unwrap_dirfd(space, w_value):
     if space.is_none(w_value):
         return DEFAULT_DIR_FD
     else:
-        return space.c_int_w(w_value)
+        return unwrap_fd(space, w_value)
 
 class _DirFD(Unwrapper):
     def unwrap(self, space, w_value):
-        return _unwrap_fd(space, w_value)
+        return _unwrap_dirfd(space, w_value)
 
 class _DirFD_Unavailable(Unwrapper):
     def unwrap(self, space, w_value):
-        dir_fd = _unwrap_fd(space, w_value)
+        dir_fd = unwrap_fd(space, w_value)
         if dir_fd == DEFAULT_DIR_FD:
             return dir_fd
         else:
@@ -140,7 +144,7 @@
 def argument_unavailable(space, funcname, arg):
     return oefmt(
             space.w_NotImplementedError,
-            "%s: %s unavailable on this platform" % (funcname, arg))
+            "%s: %s unavailable on this platform", funcname, arg)
 
 @unwrap_spec(flags=c_int, mode=c_int, dir_fd=DirFD(rposix.HAVE_OPENAT))
 def open(space, w_path, flags, mode=0777, dir_fd=DEFAULT_DIR_FD):
@@ -477,9 +481,9 @@
   of R_OK, W_OK, and X_OK."""
     if not rposix.HAVE_FACCESSAT:
         if not follow_symlinks:
-            raise argument_unavailable("access", "follow_symlinks")
+            raise argument_unavailable(space, "access", "follow_symlinks")
         if effective_ids:
-            raise argument_unavailable("access", "effective_ids")
+            raise argument_unavailable(space, "access", "effective_ids")
 
     try:
         if dir_fd == DEFAULT_DIR_FD and follow_symlinks and not effective_ids:
@@ -773,7 +777,7 @@
         raise wrap_oserror(space, e)
     return space.newtuple([space.wrap(fd1), space.wrap(fd2)])
 
-@unwrap_spec(mode=c_int, dir_fd=DirFD(available=False), 
follow_symlinks=kwonly(bool))
+@unwrap_spec(mode=c_int, dir_fd=DirFD(rposix.HAVE_FCHMODAT), 
follow_symlinks=kwonly(bool))
 def chmod(space, w_path, mode, dir_fd=DEFAULT_DIR_FD, follow_symlinks=True):
     """chmod(path, mode, *, dir_fd=None, follow_symlinks=True)
 
@@ -791,21 +795,55 @@
   an open file descriptor.
 dir_fd and follow_symlinks may not be implemented on your platform.
   If they are unavailable, using them will raise a NotImplementedError."""
+    if not rposix.HAVE_FCHMODAT:
+        if not follow_symlinks:
+            raise argument_unavailable(space, "chmod", "follow_symlinks")
+        else:
+            try:
+                dispatch_filename(rposix.chmod)(space, w_path, mode)
+                return
+            except OSError as e:
+                raise wrap_oserror2(space, e, w_path)
+
     try:
-        dispatch_filename(rposix.chmod)(space, w_path, mode)
-    except OSError, e:
-        raise wrap_oserror2(space, e, w_path)
+        path = space.fsencode_w(w_path)
+    except OperationError as operr:
+        if not space.isinstance_w(w_path, space.w_int):
+            raise oefmt(space.w_TypeError,
+                "argument should be string, bytes or integer, not %T", w_path)
+        fd = unwrap_fd(space, w_path)
+        _chmod_fd(space, fd, mode)
+    else:
+        try:
+            _chmod_path(path, mode, dir_fd, follow_symlinks)
+        except OSError as e:
+            if not follow_symlinks and e.errno in (ENOTSUP, EOPNOTSUPP):
+                # fchmodat() doesn't actually implement follow_symlinks=False
+                # so raise NotImplementedError in this case
+                raise argument_unavailable(space, "chmod", "follow_symlinks")
+            else:
+                raise wrap_oserror2(space, e, w_path)
 
-@unwrap_spec(mode=c_int)
-def fchmod(space, w_fd, mode):
-    """Change the access permissions of the file given by file
-descriptor fd."""
-    fd = space.c_filedescriptor_w(w_fd)
+def _chmod_path(path, mode, dir_fd, follow_symlinks):
+    if dir_fd != DEFAULT_DIR_FD or not follow_symlinks:
+        rposix.fchmodat(path, mode, dir_fd, follow_symlinks)
+    else:
+        rposix.chmod(path, mode)
+
+def _chmod_fd(space, fd, mode):
     try:
         os.fchmod(fd, mode)
-    except OSError, e:
+    except OSError as e:
         raise wrap_oserror(space, e)
 
+
+@unwrap_spec(fd=c_int, mode=c_int)
+def fchmod(space, fd, mode):
+    """\
+    Change the access permissions of the file given by file descriptor fd.
+    """
+    _chmod_fd(space, fd, mode)
+
 @unwrap_spec(src_dir_fd=DirFD(available=False), 
dst_dir_fd=DirFD(available=False))
 def rename(space, w_old, w_new,
         src_dir_fd=DEFAULT_DIR_FD, dst_dir_fd=DEFAULT_DIR_FD):
@@ -1197,7 +1235,7 @@
             raise wrap_oserror2(space, e, w_path)
 
     if not follow_symlinks:
-        raise argument_unavailable("utime", "follow_symlinks")
+        raise argument_unavailable(space, "utime", "follow_symlinks")
 
     if not space.is_w(w_ns, space.w_None):
         raise oefmt(space.w_NotImplementedError,
_______________________________________________
pypy-commit mailing list
pypy-commit@python.org
https://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to