The standard library implements support for Linux's extended attribute
API with os.getxattr/setxattr/listxattr/removexattr. I'd like to
implement support for more platforms under the same API in the
standard library.

Proof of concept
================
I've implemented a native-Python library (using ctypes) that runs CI
tests against Linux, Mac OS X and FreeBSD. If accepted, this library
could also be used to backport support to Python 3.6+.

https://github.com/dgilman/xattr-compat

API discussion
==============
It is at least possible to do this on all three platforms as
demonstrated by my library.

Mutable mapping
---------------
I've also implemented a mutable mapping (inspired by os.environ) that
can be used for access to a file's extended attributes. Unlike
os.environ you have to instantiate the class with your path, but once
you have it, it's a straightforward API.

# class Xattrs(path: os.PathLike, follow_symlinks: bool = True)

import xattr_compat

xattrs = xattr_compat.Xattrs("./my_file")

xattrs["user.humanfund.xattr"] = b"hello\0world"

print("Extended attributes:", xattrs.items())


MacOS X
-------
Not listed in the manpage but defined in the xattr.h header file are a
few more bitflags: XATTR_NOSECURITY, XATTR_NODEFAULT and
XATTR_SHOWCOMPRESSION. Linux's setxattr takes a flags argument so
os.setxattr() has a flags argument, but on MacOS X all four functions
take a flags argument. It may be worth adding a flags= kwarg to all
four Python functions to support the MacOS X case.

MacOS X also has no restrictions on the name of the format key which
is nice. The manpages demand that you use UTF-8 for the encoding as
well.

Linux
-----
Linux requires the attribute name to start with "user.", "system.",
"trusted." or "security.". Luckily the current Python implementation
doesn't attempt to validate this, leaving it up to the kernel to set
errno when you don't do this. Because Linux was the most restrictive
of these platforms existing code will work correctly on the new
platforms.

FreeBSD/NetBSD
--------------
These systems added an argument attrnamespace to all of their xattr
system calls. There are only two namespaces: EXTATTR_NAMESPACE_SYSTEM
and EXTATTR_NAMESPACE_USER. There are no further restrictions on the
attribute name. Unfortunately, directly supporting attrnamespace in
the Python API is going to require breaking away a bit from the Linux
interface.

You can't rely on checking the attribute string to determine which
namespace a key should go into because there will be keys without
those prefixes on live systems. You also can't trim the string in
Python before handing it off to the kernel because it is valid to have
a key that starts with "user." and so on in the BSDs and I imagine
there are probably a lot of users who want compatibility with Linux
and are doing exactly that.

I have my library using the USER namespace by default which seems to
be the correct thing to do. However, it is still possible that someone
might want to read or write from a SYSTEM namespace xattr. I've
extended the function signature to optionally take a tuple in place of
the os.PathLike argument. The first member of the tuple is the
namespace constant, the second is the actual path or file descriptor
that you want to work on. I'm pretty happy with this API - it doesn't
break compatibility for the tiny user base of FreeBSD users who are
interested in reading SYSTEM-namespaced xattrs from Python but also
doesn't clutter things up too much. But maybe this is too tacky for
the standard library.

Windows
-------
If the Windows Subsystem for Linux implements xattr this code can
likely mimic what it does. I don't have a Windows machine so I can't
comment on if that is already there.


Bikeshedding
============
Should the mapping class be named os.xattrs or os.xattr or os.Xattrs
or os.Xattr?

Implementation
==============
If accepted, what sort of tests would be expected as part of the PR? I
already have a handful of unit tests in the xattr_compat repo.


-- 
David Gilman
:DG<
_______________________________________________
Python-ideas mailing list -- [email protected]
To unsubscribe send an email to [email protected]
https://mail.python.org/mailman3/lists/python-ideas.python.org/
Message archived at 
https://mail.python.org/archives/list/[email protected]/message/6GTEZ2UL3LXMQIGERR5SPRWVSSRVSKRG/
Code of Conduct: http://python.org/psf/codeofconduct/

Reply via email to