[pypy-commit] pypy py3.5-xattr: Add rposix.(f)listxattr

rlamy pypy.commits at gmail.com
Tue Dec 19 11:50:33 EST 2017


Author: Ronan Lamy <ronan.lamy at gmail.com>
Branch: py3.5-xattr
Changeset: r93495:05c458bd2a65
Date: 2017-12-19 16:49 +0000
http://bitbucket.org/pypy/pypy/changeset/05c458bd2a65/

Log:	Add rposix.(f)listxattr

diff --git a/rpython/rlib/rposix.py b/rpython/rlib/rposix.py
--- a/rpython/rlib/rposix.py
+++ b/rpython/rlib/rposix.py
@@ -2603,29 +2603,41 @@
         save_err=rffi.RFFI_SAVE_ERRNO)
     c_fsetxattr = external('fsetxattr',
         [rffi.INT, rffi.CCHARP, rffi.CCHARP, rffi.SIZE_T, rffi.INT],
-        rffi.SSIZE_T,
+        rffi.INT,
         compilation_info=CConfig._compilation_info_,
         save_err=rffi.RFFI_SAVE_ERRNO)
     c_setxattr = external('setxattr',
         [rffi.CCHARP, rffi.CCHARP, rffi.CCHARP, rffi.SIZE_T, rffi.INT],
-        rffi.SSIZE_T,
+        rffi.INT,
         compilation_info=CConfig._compilation_info_,
         save_err=rffi.RFFI_SAVE_ERRNO)
     c_lsetxattr = external('lsetxattr',
         [rffi.CCHARP, rffi.CCHARP, rffi.CCHARP, rffi.SIZE_T, rffi.INT],
-        rffi.SSIZE_T,
+        rffi.INT,
         compilation_info=CConfig._compilation_info_,
         save_err=rffi.RFFI_SAVE_ERRNO)
     c_fremovexattr = external('fremovexattr',
-        [rffi.INT, rffi.CCHARP], rffi.SSIZE_T,
+        [rffi.INT, rffi.CCHARP], rffi.INT,
         compilation_info=CConfig._compilation_info_,
         save_err=rffi.RFFI_SAVE_ERRNO)
     c_removexattr = external('removexattr',
-        [rffi.CCHARP, rffi.CCHARP], rffi.SSIZE_T,
+        [rffi.CCHARP, rffi.CCHARP], rffi.INT,
         compilation_info=CConfig._compilation_info_,
         save_err=rffi.RFFI_SAVE_ERRNO)
     c_lremovexattr = external('lremovexattr',
-        [rffi.CCHARP, rffi.CCHARP], rffi.SSIZE_T,
+        [rffi.CCHARP, rffi.CCHARP], rffi.INT,
+        compilation_info=CConfig._compilation_info_,
+        save_err=rffi.RFFI_SAVE_ERRNO)
+    c_flistxattr = external('flistxattr',
+        [rffi.INT, rffi.CCHARP, rffi.SIZE_T], rffi.SSIZE_T,
+        compilation_info=CConfig._compilation_info_,
+        save_err=rffi.RFFI_SAVE_ERRNO)
+    c_listxattr = external('listxattr',
+        [rffi.CCHARP, rffi.CCHARP, rffi.SIZE_T], rffi.SSIZE_T,
+        compilation_info=CConfig._compilation_info_,
+        save_err=rffi.RFFI_SAVE_ERRNO)
+    c_llistxattr = external('llistxattr',
+        [rffi.CCHARP, rffi.CCHARP, rffi.SIZE_T], rffi.SSIZE_T,
         compilation_info=CConfig._compilation_info_,
         save_err=rffi.RFFI_SAVE_ERRNO)
     buf_sizes = [256, XATTR_SIZE_MAX]
@@ -2683,3 +2695,39 @@
             return handle_posix_error('removexattr', c_removexattr(path, name))
         else:
             return handle_posix_error('lremovexattr', c_lremovexattr(path, name))
+
+    def _unpack_attrs(attr_string):
+        result = attr_string.split('\0')
+        del result[-1]
+        return result
+
+    def flistxattr(fd):
+        for size in buf_sizes:
+            with rffi.scoped_alloc_buffer(size) as buf:
+                res = c_flistxattr(fd, buf.raw, size)
+                if res < 0:
+                    err = get_saved_errno()
+                    if err != errno.ERANGE:
+                        raise OSError(err, 'flistxattr failed')
+                else:
+                    return _unpack_attrs(buf.str(res))
+        else:
+            raise OSError(errno.ERANGE, 'flistxattr failed')
+
+    def listxattr(path, follow_symlinks=True):
+        for size in buf_sizes:
+            with rffi.scoped_alloc_buffer(size) as buf:
+                if follow_symlinks:
+                    res = c_listxattr(path, buf.raw, size)
+                else:
+                    res = c_llistxattr(path, buf.raw, size)
+                if res < 0:
+                    err = get_saved_errno()
+                    if err != errno.ERANGE:
+                        c_name = 'listxattr' if follow_symlinks else 'llistxattr'
+                        raise OSError(err, c_name + 'failed')
+                else:
+                    return _unpack_attrs(buf.str(res))
+        else:
+            c_name = 'listxattr' if follow_symlinks else 'llistxattr'
+            raise OSError(errno.ERANGE, c_name + 'failed')
diff --git a/rpython/rlib/test/test_rposix.py b/rpython/rlib/test/test_rposix.py
--- a/rpython/rlib/test/test_rposix.py
+++ b/rpython/rlib/test/test_rposix.py
@@ -853,27 +853,38 @@
     assume(follow_symlinks or not use_fd)
     name = 'user.' + name.encode('utf-8')
     fname = str(udir.join('xattr_test.txt'))
+    try:
+        os.unlink(fname)
+    except OSError:
+        pass
     with open(fname, 'wb'):
         pass
     if use_fd:
         file_id = os.open(fname, os.O_CREAT, 0777)
         read, write, delete = rposix.fgetxattr, rposix.fsetxattr, rposix.fremovexattr
+        all_names = rposix.flistxattr
     else:
         file_id = fname
         if follow_symlinks:
             read, write, delete = rposix.getxattr, rposix.setxattr, rposix.removexattr
+            all_names = rposix.listxattr
         else:
             read = lambda *args, **kwargs: rposix.getxattr(*args, follow_symlinks=False, **kwargs)
             write = lambda *args, **kwargs: rposix.setxattr(*args, follow_symlinks=False, **kwargs)
             delete = lambda *args, **kwargs: rposix.removexattr(*args, follow_symlinks=False, **kwargs)
+            all_names = lambda *args, **kwargs: rposix.listxattr(*args, follow_symlinks=False, **kwargs)
     try:
+        init_names = all_names(file_id)
         with pytest.raises(OSError):
             read(file_id, name)
         write(file_id, name, value)
         assert read(file_id, name) == value
+        assert set(all_names(file_id)) == set(init_names + [name])
+        assert '' not in all_names(file_id)
         delete(file_id, name)
         with pytest.raises(OSError):
             read(file_id, name)
+        assert set(all_names(file_id)) == set(init_names)
     finally:
         if use_fd:
             os.close(file_id)


More information about the pypy-commit mailing list