diff -Nru python-xattr-0.6.4/_build/_make_constants.py python-xattr-0.7.8/_build/_make_constants.py --- python-xattr-0.6.4/_build/_make_constants.py 2011-08-17 05:12:49.000000000 +0000 +++ python-xattr-0.7.8/_build/_make_constants.py 1970-01-01 00:00:00.000000000 +0000 @@ -1,20 +0,0 @@ -infile = '/usr/include/sys/xattr.h' -out = file('Lib/xattr/constants.py', 'w') -for line in file(infile): - line = line.rstrip() - if line.startswith('/*') and line.endswith('*/'): - print >>out, '' - print >>out, '# ' + line[2:-2].strip() - elif line.startswith('#define'): - if lastblank: - print >>out, '' - chunks = line.split(None, 3) - if len(chunks) == 3: - print >>out, '%s = %s' % (chunks[1], chunks[2]) - elif len(chunks) == 4: - comment = chunks[3].replace('/*', '').replace('*/', '').strip() - print >>out, '%s = %s # %s' % (chunks[1], chunks[2], comment) - if not line: - lastblank = True - else: - lastblank = False diff -Nru python-xattr-0.6.4/CHANGES.txt python-xattr-0.7.8/CHANGES.txt --- python-xattr-0.6.4/CHANGES.txt 2012-02-01 19:29:13.000000000 +0000 +++ python-xattr-0.7.8/CHANGES.txt 2015-06-25 17:25:42.000000000 +0000 @@ -1,3 +1,48 @@ +Version 0.7.8 released 2015-06-25 + +* Added MANIFEST.in to ensure that the .txt files are included + https://github.com/xattr/xattr/issues/40 + +Version 0.7.7 released 2015-06-19 + +* Fixed FreeBSD build + https://github.com/xattr/xattr/pull/32 + +Version 0.7.6 released 2014-03-27 + +* Fixed Solaris & Solaris Studio support and Python 2.6 compatibility + https://github.com/xattr/xattr/pull/29 + +Version 0.7.5 released 2014-03-23 + +* Improved error message when str/unicode is passed where bytes is + required + https://github.com/xattr/xattr/pull/24 + +Version 0.7.4 released 2014-03-03 + +* Improved Python 3 compatibility + https://github.com/xattr/xattr/pull/22 + +Version 0.7.3 released 2014-01-06 + +* Added some unicode-specific tests + +Version 0.7.2 released 2013-07-22 + +* Added Python 3 support. + https://github.com/xattr/xattr/commit/14795a47b1dc4bb994faf520888c51c5886b8187 + +Version 0.7.1 released 2013-07-19 + +* Fixed compilation on some platforms + https://github.com/xattr/xattr/issues/12 + +Version 0.7.0 released 2013-07-19 + +* Rewritten to use cffi + https://github.com/xattr/xattr/pull/11 + Version 0.6.4 released 2012-02-01 * Updated README.txt to match setup.py description diff -Nru python-xattr-0.6.4/debian/changelog python-xattr-0.7.8/debian/changelog --- python-xattr-0.6.4/debian/changelog 2014-07-07 23:00:09.000000000 +0000 +++ python-xattr-0.7.8/debian/changelog 2016-02-13 17:29:43.000000000 +0000 @@ -1,3 +1,15 @@ +python-xattr (0.7.8-3) unstable; urgency=medium + + * Add python-cffi runtime dependency + + -- Federico Ceratto Sat, 13 Feb 2016 17:29:14 +0000 + +python-xattr (0.7.8-2) unstable; urgency=low + + * New upstream release (Closes: #813075) + + -- Federico Ceratto Mon, 08 Feb 2016 09:39:26 +0000 + python-xattr (0.6.4-3) unstable; urgency=low * Add PSF to copyright (Closes: #689282) diff -Nru python-xattr-0.6.4/debian/control python-xattr-0.7.8/debian/control --- python-xattr-0.6.4/debian/control 2014-07-07 23:00:09.000000000 +0000 +++ python-xattr-0.7.8/debian/control 2016-02-13 17:29:43.000000000 +0000 @@ -1,19 +1,27 @@ Source: python-xattr Section: python Priority: optional -Maintainer: Federico Ceratto -Build-Depends: debhelper (>= 9~) - , python-all-dev (>= 2.6.6-3~) - , python-setuptools (>= 0.6.14-4) -Standards-Version: 3.9.5 +Maintainer: Federico Ceratto +Build-Depends: + debhelper (>= 9~), + dh-python, + python-all-dev (>= 2.6.6-3~), + python-cffi, + python-setuptools (>= 0.6.14-4) +Standards-Version: 3.9.6 X-Python-Version: >= 2.5 Homepage: http://www.undefined.org/python/ -Vcs-Git: git://anonscm.debian.org/collab-maint/python-xattr.git -Vcs-Browser: http://anonscm.debian.org/gitweb/?p=collab-maint/python-xattr.git;a=summary +Vcs-Git: https://anonscm.debian.org/git/collab-maint/python-xattr.git +Vcs-Browser: https://anonscm.debian.org/gitweb/?p=collab-maint/python-xattr.git;a=summary Package: python-xattr Architecture: any -Depends: ${python:Depends}, ${shlibs:Depends}, ${misc:Depends}, python-pkg-resources +Depends: + ${misc:Depends}, + ${python:Depends}, + ${shlibs:Depends}, + python-cffi, + python-pkg-resources Conflicts: python-pyxattr Provides: ${python:Provides} , python-pyxattr diff -Nru python-xattr-0.6.4/debian/rules python-xattr-0.7.8/debian/rules --- python-xattr-0.6.4/debian/rules 2014-07-07 23:00:09.000000000 +0000 +++ python-xattr-0.7.8/debian/rules 2016-02-13 17:29:43.000000000 +0000 @@ -1,3 +1,14 @@ #!/usr/bin/make -f + +export DH_VERBOSE=1 +export PYBUILD_NAME=xattr +export DEB_BUILD_MAINT_OPTIONS = hardening=+bindnow +export PYBUILD_DISABLE=test + %: - dh $@ --with python2 + dh $@ --with python2 --buildsystem=pybuild + +override_dh_auto_clean: + dh_auto_clean + rm -rf xattr.egg-info xattr/__pycache__ + find xattr -name '*.so' -delete diff -Nru python-xattr-0.6.4/debian/xattr.1 python-xattr-0.7.8/debian/xattr.1 --- python-xattr-0.6.4/debian/xattr.1 2014-07-07 23:00:09.000000000 +0000 +++ python-xattr-0.7.8/debian/xattr.1 2016-02-13 17:29:43.000000000 +0000 @@ -31,7 +31,13 @@ Print long format (attr_name: attr_value) when listing xattrs. .TP .B \-z -Compress or decompress (if compressed) attribute value in zip format). +Compress or decompress (if compressed) attribute value in zip format. +.SH EXAMPLES +.TP +.B "xattr -w user.mykey myvalue myfile" +.TP +.B "xattr -g user.mykey myfile" +.br .SH SEE ALSO The Python module "xattr" .br diff -Nru python-xattr-0.6.4/ez_setup.py python-xattr-0.7.8/ez_setup.py --- python-xattr-0.6.4/ez_setup.py 2011-08-17 05:22:51.000000000 +0000 +++ python-xattr-0.7.8/ez_setup.py 1970-01-01 00:00:00.000000000 +0000 @@ -1,284 +0,0 @@ -#!python -"""Bootstrap setuptools installation - -If you want to use setuptools in your package's setup.py, just include this -file in the same directory with it, and add this to the top of your setup.py:: - - from ez_setup import use_setuptools - use_setuptools() - -If you want to require a specific version of setuptools, set a download -mirror, or use an alternate download directory, you can do so by supplying -the appropriate options to ``use_setuptools()``. - -This file can also be run as a script to install or upgrade setuptools. -""" -import sys -DEFAULT_VERSION = "0.6c11" -DEFAULT_URL = "http://pypi.python.org/packages/%s/s/setuptools/" % sys.version[:3] - -md5_data = { - 'setuptools-0.6b1-py2.3.egg': '8822caf901250d848b996b7f25c6e6ca', - 'setuptools-0.6b1-py2.4.egg': 'b79a8a403e4502fbb85ee3f1941735cb', - 'setuptools-0.6b2-py2.3.egg': '5657759d8a6d8fc44070a9d07272d99b', - 'setuptools-0.6b2-py2.4.egg': '4996a8d169d2be661fa32a6e52e4f82a', - 'setuptools-0.6b3-py2.3.egg': 'bb31c0fc7399a63579975cad9f5a0618', - 'setuptools-0.6b3-py2.4.egg': '38a8c6b3d6ecd22247f179f7da669fac', - 'setuptools-0.6b4-py2.3.egg': '62045a24ed4e1ebc77fe039aa4e6f7e5', - 'setuptools-0.6b4-py2.4.egg': '4cb2a185d228dacffb2d17f103b3b1c4', - 'setuptools-0.6c1-py2.3.egg': 'b3f2b5539d65cb7f74ad79127f1a908c', - 'setuptools-0.6c1-py2.4.egg': 'b45adeda0667d2d2ffe14009364f2a4b', - 'setuptools-0.6c10-py2.3.egg': 'ce1e2ab5d3a0256456d9fc13800a7090', - 'setuptools-0.6c10-py2.4.egg': '57d6d9d6e9b80772c59a53a8433a5dd4', - 'setuptools-0.6c10-py2.5.egg': 'de46ac8b1c97c895572e5e8596aeb8c7', - 'setuptools-0.6c10-py2.6.egg': '58ea40aef06da02ce641495523a0b7f5', - 'setuptools-0.6c11-py2.3.egg': '2baeac6e13d414a9d28e7ba5b5a596de', - 'setuptools-0.6c11-py2.4.egg': 'bd639f9b0eac4c42497034dec2ec0c2b', - 'setuptools-0.6c11-py2.5.egg': '64c94f3bf7a72a13ec83e0b24f2749b2', - 'setuptools-0.6c11-py2.6.egg': 'bfa92100bd772d5a213eedd356d64086', - 'setuptools-0.6c2-py2.3.egg': 'f0064bf6aa2b7d0f3ba0b43f20817c27', - 'setuptools-0.6c2-py2.4.egg': '616192eec35f47e8ea16cd6a122b7277', - 'setuptools-0.6c3-py2.3.egg': 'f181fa125dfe85a259c9cd6f1d7b78fa', - 'setuptools-0.6c3-py2.4.egg': 'e0ed74682c998bfb73bf803a50e7b71e', - 'setuptools-0.6c3-py2.5.egg': 'abef16fdd61955514841c7c6bd98965e', - 'setuptools-0.6c4-py2.3.egg': 'b0b9131acab32022bfac7f44c5d7971f', - 'setuptools-0.6c4-py2.4.egg': '2a1f9656d4fbf3c97bf946c0a124e6e2', - 'setuptools-0.6c4-py2.5.egg': '8f5a052e32cdb9c72bcf4b5526f28afc', - 'setuptools-0.6c5-py2.3.egg': 'ee9fd80965da04f2f3e6b3576e9d8167', - 'setuptools-0.6c5-py2.4.egg': 'afe2adf1c01701ee841761f5bcd8aa64', - 'setuptools-0.6c5-py2.5.egg': 'a8d3f61494ccaa8714dfed37bccd3d5d', - 'setuptools-0.6c6-py2.3.egg': '35686b78116a668847237b69d549ec20', - 'setuptools-0.6c6-py2.4.egg': '3c56af57be3225019260a644430065ab', - 'setuptools-0.6c6-py2.5.egg': 'b2f8a7520709a5b34f80946de5f02f53', - 'setuptools-0.6c7-py2.3.egg': '209fdf9adc3a615e5115b725658e13e2', - 'setuptools-0.6c7-py2.4.egg': '5a8f954807d46a0fb67cf1f26c55a82e', - 'setuptools-0.6c7-py2.5.egg': '45d2ad28f9750e7434111fde831e8372', - 'setuptools-0.6c8-py2.3.egg': '50759d29b349db8cfd807ba8303f1902', - 'setuptools-0.6c8-py2.4.egg': 'cba38d74f7d483c06e9daa6070cce6de', - 'setuptools-0.6c8-py2.5.egg': '1721747ee329dc150590a58b3e1ac95b', - 'setuptools-0.6c9-py2.3.egg': 'a83c4020414807b496e4cfbe08507c03', - 'setuptools-0.6c9-py2.4.egg': '260a2be2e5388d66bdaee06abec6342a', - 'setuptools-0.6c9-py2.5.egg': 'fe67c3e5a17b12c0e7c541b7ea43a8e6', - 'setuptools-0.6c9-py2.6.egg': 'ca37b1ff16fa2ede6e19383e7b59245a', -} - -import sys, os -try: from hashlib import md5 -except ImportError: from md5 import md5 - -def _validate_md5(egg_name, data): - if egg_name in md5_data: - digest = md5(data).hexdigest() - if digest != md5_data[egg_name]: - print >>sys.stderr, ( - "md5 validation of %s failed! (Possible download problem?)" - % egg_name - ) - sys.exit(2) - return data - -def use_setuptools( - version=DEFAULT_VERSION, download_base=DEFAULT_URL, to_dir=os.curdir, - download_delay=15 -): - """Automatically find/download setuptools and make it available on sys.path - - `version` should be a valid setuptools version number that is available - as an egg for download under the `download_base` URL (which should end with - a '/'). `to_dir` is the directory where setuptools will be downloaded, if - it is not already available. If `download_delay` is specified, it should - be the number of seconds that will be paused before initiating a download, - should one be required. If an older version of setuptools is installed, - this routine will print a message to ``sys.stderr`` and raise SystemExit in - an attempt to abort the calling script. - """ - was_imported = 'pkg_resources' in sys.modules or 'setuptools' in sys.modules - def do_download(): - egg = download_setuptools(version, download_base, to_dir, download_delay) - sys.path.insert(0, egg) - import setuptools; setuptools.bootstrap_install_from = egg - try: - import pkg_resources - except ImportError: - return do_download() - try: - pkg_resources.require("setuptools>="+version); return - except pkg_resources.VersionConflict, e: - if was_imported: - print >>sys.stderr, ( - "The required version of setuptools (>=%s) is not available, and\n" - "can't be installed while this script is running. Please install\n" - " a more recent version first, using 'easy_install -U setuptools'." - "\n\n(Currently using %r)" - ) % (version, e.args[0]) - sys.exit(2) - except pkg_resources.DistributionNotFound: - pass - - del pkg_resources, sys.modules['pkg_resources'] # reload ok - return do_download() - -def download_setuptools( - version=DEFAULT_VERSION, download_base=DEFAULT_URL, to_dir=os.curdir, - delay = 15 -): - """Download setuptools from a specified location and return its filename - - `version` should be a valid setuptools version number that is available - as an egg for download under the `download_base` URL (which should end - with a '/'). `to_dir` is the directory where the egg will be downloaded. - `delay` is the number of seconds to pause before an actual download attempt. - """ - import urllib2, shutil - egg_name = "setuptools-%s-py%s.egg" % (version,sys.version[:3]) - url = download_base + egg_name - saveto = os.path.join(to_dir, egg_name) - src = dst = None - if not os.path.exists(saveto): # Avoid repeated downloads - try: - from distutils import log - if delay: - log.warn(""" ---------------------------------------------------------------------------- -This script requires setuptools version %s to run (even to display -help). I will attempt to download it for you (from -%s), but -you may need to enable firewall access for this script first. -I will start the download in %d seconds. - -(Note: if this machine does not have network access, please obtain the file - - %s - -and place it in this directory before rerunning this script.) ----------------------------------------------------------------------------""", - version, download_base, delay, url - ); from time import sleep; sleep(delay) - log.warn("Downloading %s", url) - src = urllib2.urlopen(url) - # Read/write all in one block, so we don't create a corrupt file - # if the download is interrupted. - data = _validate_md5(egg_name, src.read()) - dst = open(saveto,"wb"); dst.write(data) - finally: - if src: src.close() - if dst: dst.close() - return os.path.realpath(saveto) - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -def main(argv, version=DEFAULT_VERSION): - """Install or upgrade setuptools and EasyInstall""" - try: - import setuptools - except ImportError: - egg = None - try: - egg = download_setuptools(version, delay=0) - sys.path.insert(0,egg) - from setuptools.command.easy_install import main - return main(list(argv)+[egg]) # we're done here - finally: - if egg and os.path.exists(egg): - os.unlink(egg) - else: - if setuptools.__version__ == '0.0.1': - print >>sys.stderr, ( - "You have an obsolete version of setuptools installed. Please\n" - "remove it from your system entirely before rerunning this script." - ) - sys.exit(2) - - req = "setuptools>="+version - import pkg_resources - try: - pkg_resources.require(req) - except pkg_resources.VersionConflict: - try: - from setuptools.command.easy_install import main - except ImportError: - from easy_install import main - main(list(argv)+[download_setuptools(delay=0)]) - sys.exit(0) # try to force an exit - else: - if argv: - from setuptools.command.easy_install import main - main(argv) - else: - print "Setuptools version",version,"or greater has been installed." - print '(Run "ez_setup.py -U setuptools" to reinstall or upgrade.)' - -def update_md5(filenames): - """Update our built-in md5 registry""" - - import re - - for name in filenames: - base = os.path.basename(name) - f = open(name,'rb') - md5_data[base] = md5(f.read()).hexdigest() - f.close() - - data = [" %r: %r,\n" % it for it in md5_data.items()] - data.sort() - repl = "".join(data) - - import inspect - srcfile = inspect.getsourcefile(sys.modules[__name__]) - f = open(srcfile, 'rb'); src = f.read(); f.close() - - match = re.search("\nmd5_data = {\n([^}]+)}", src) - if not match: - print >>sys.stderr, "Internal error!" - sys.exit(2) - - src = src[:match.start(1)] + repl + src[match.end(1):] - f = open(srcfile,'w') - f.write(src) - f.close() - - -if __name__=='__main__': - if len(sys.argv)>2 and sys.argv[1]=='--md5update': - update_md5(sys.argv[2:]) - else: - main(sys.argv[1:]) - - - - - - diff -Nru python-xattr-0.6.4/.gitignore python-xattr-0.7.8/.gitignore --- python-xattr-0.6.4/.gitignore 2012-01-23 17:35:37.000000000 +0000 +++ python-xattr-0.7.8/.gitignore 2015-06-25 17:25:42.000000000 +0000 @@ -1,6 +1,8 @@ /xattr.egg-info /build /dist +/*.egg *.pyc *.so .\#* +__pycache__ diff -Nru python-xattr-0.6.4/MANIFEST.in python-xattr-0.7.8/MANIFEST.in --- python-xattr-0.6.4/MANIFEST.in 1970-01-01 00:00:00.000000000 +0000 +++ python-xattr-0.7.8/MANIFEST.in 2015-06-25 17:25:42.000000000 +0000 @@ -0,0 +1,3 @@ +include *.py +include *.txt +include MANIFEST.in diff -Nru python-xattr-0.6.4/PKG-INFO python-xattr-0.7.8/PKG-INFO --- python-xattr-0.6.4/PKG-INFO 2012-02-01 19:31:20.000000000 +0000 +++ python-xattr-0.7.8/PKG-INFO 1970-01-01 00:00:00.000000000 +0000 @@ -1,29 +0,0 @@ -Metadata-Version: 1.0 -Name: xattr -Version: 0.6.4 -Summary: Python wrapper for extended filesystem attributes -Home-page: http://github.com/xattr/xattr -Author: Bob Ippolito -Author-email: bob@redivi.com -License: MIT License -Description: - Extended attributes extend the basic attributes of files and directories - in the file system. They are stored as name:data pairs associated with - file system objects (files, directories, symlinks, etc). - - Extended attributes are currently only available on Darwin 8.0+ (Mac OS X 10.4) - and Linux 2.6+. Experimental support is included for Solaris and FreeBSD. - -Platform: MacOS X -Platform: Linux -Platform: FreeBSD -Platform: Solaris -Classifier: Environment :: Console -Classifier: Intended Audience :: Developers -Classifier: License :: OSI Approved :: MIT License -Classifier: Natural Language :: English -Classifier: Operating System :: MacOS :: MacOS X -Classifier: Operating System :: POSIX :: Linux -Classifier: Operating System :: POSIX :: BSD :: FreeBSD -Classifier: Programming Language :: Python -Classifier: Topic :: Software Development :: Libraries :: Python Modules diff -Nru python-xattr-0.6.4/requirements.txt python-xattr-0.7.8/requirements.txt --- python-xattr-0.6.4/requirements.txt 1970-01-01 00:00:00.000000000 +0000 +++ python-xattr-0.7.8/requirements.txt 2015-06-25 17:25:42.000000000 +0000 @@ -0,0 +1 @@ +cffi>=0.4 diff -Nru python-xattr-0.6.4/setup.cfg python-xattr-0.7.8/setup.cfg --- python-xattr-0.6.4/setup.cfg 2012-02-01 19:31:20.000000000 +0000 +++ python-xattr-0.7.8/setup.cfg 1970-01-01 00:00:00.000000000 +0000 @@ -1,5 +0,0 @@ -[egg_info] -tag_build = -tag_date = 0 -tag_svn_revision = 0 - diff -Nru python-xattr-0.6.4/setup.py python-xattr-0.7.8/setup.py --- python-xattr-0.6.4/setup.py 2012-02-01 19:29:52.000000000 +0000 +++ python-xattr-0.7.8/setup.py 2015-06-25 17:25:42.000000000 +0000 @@ -1,11 +1,22 @@ #!/usr/bin/env python -import ez_setup -ez_setup.use_setuptools() +import os +import sys -from setuptools import setup, Extension +from setuptools import setup +from distutils.command.build import build -VERSION = '0.6.4' +class cffi_build(build): + """This is a shameful hack to ensure that cffi is present when + we specify ext_modules. We can't do this eagerly because + setup_requires hasn't run yet. + """ + def finalize_options(self): + from xattr.lib import ffi + self.distribution.ext_modules = [ffi.verifier.get_extension()] + build.finalize_options(self) + +VERSION = '0.7.8' DESCRIPTION = "Python wrapper for extended filesystem attributes" LONG_DESCRIPTION = """ Extended attributes extend the basic attributes of files and directories @@ -16,7 +27,7 @@ and Linux 2.6+. Experimental support is included for Solaris and FreeBSD. """ -CLASSIFIERS = filter(None, map(str.strip, +CLASSIFIERS = filter(bool, map(str.strip, """ Environment :: Console Intended Audience :: Developers @@ -26,6 +37,8 @@ Operating System :: POSIX :: Linux Operating System :: POSIX :: BSD :: FreeBSD Programming Language :: Python +Programming Language :: Python :: 2 +Programming Language :: Python :: 3 Topic :: Software Development :: Libraries :: Python Modules """.splitlines())) @@ -40,15 +53,16 @@ url="http://github.com/xattr/xattr", license="MIT License", packages=['xattr'], + ext_package='xattr', platforms=['MacOS X', 'Linux', 'FreeBSD', 'Solaris'], - ext_modules=[ - Extension("xattr._xattr", ["xattr/_xattr.c"]), - ], entry_points={ 'console_scripts': [ "xattr = xattr.tool:main", ], }, + install_requires=["cffi>=0.4"], + setup_requires=["cffi>=0.4"], test_suite="xattr.tests.all_tests_suite", zip_safe=False, + cmdclass={'build': cffi_build}, ) diff -Nru python-xattr-0.6.4/.travis.yml python-xattr-0.7.8/.travis.yml --- python-xattr-0.6.4/.travis.yml 1970-01-01 00:00:00.000000000 +0000 +++ python-xattr-0.7.8/.travis.yml 2015-06-25 17:25:42.000000000 +0000 @@ -0,0 +1,5 @@ +language: objective-c +script: + - ARCHFLAGS="-Wno-error=unused-command-line-argument-hard-error-in-future" python setup.py build_ext -i + - python -m compileall -f xattr + - python setup.py test diff -Nru python-xattr-0.6.4/xattr/constants.py python-xattr-0.7.8/xattr/constants.py --- python-xattr-0.6.4/xattr/constants.py 2011-08-17 05:12:49.000000000 +0000 +++ python-xattr-0.7.8/xattr/constants.py 1970-01-01 00:00:00.000000000 +0000 @@ -1,16 +0,0 @@ - -# Options for pathname based xattr calls -XATTR_NOFOLLOW = 0x0001 # Don't follow symbolic links - -# Options for setxattr calls -XATTR_CREATE = 0x0002 # set the value, fail if attr already exists -XATTR_REPLACE = 0x0004 # set the value, fail if attr does not exist - -# Set this to bypass authorization checking (eg. if doing auth-related work) -XATTR_NOSECURITY = 0x0008 - -XATTR_MAXNAMELEN = 127 - -XATTR_FINDERINFO_NAME = "com.apple.FinderInfo" - -XATTR_RESOURCEFORK_NAME = "com.apple.ResourceFork" diff -Nru python-xattr-0.6.4/xattr/__init__.py python-xattr-0.7.8/xattr/__init__.py --- python-xattr-0.6.4/xattr/__init__.py 2012-02-01 19:29:36.000000000 +0000 +++ python-xattr-0.7.8/xattr/__init__.py 2015-06-25 17:25:42.000000000 +0000 @@ -7,26 +7,20 @@ that exposes these extended attributes. """ -__version__ = '0.6.4' -from constants import XATTR_NOFOLLOW, XATTR_CREATE, XATTR_REPLACE, \ - XATTR_NOSECURITY, XATTR_MAXNAMELEN, XATTR_FINDERINFO_NAME, \ - XATTR_RESOURCEFORK_NAME - -import _xattr - -def _pyflakes_api(): - # trick pyflakes into thinking these are used. - return [ - XATTR_NOFOLLOW, XATTR_CREATE, XATTR_REPLACE, - XATTR_NOSECURITY, XATTR_MAXNAMELEN, XATTR_FINDERINFO_NAME, - XATTR_RESOURCEFORK_NAME, - ] - - -def _boundfunc(func, first): - def _func(*args): - return func(first, *args) - return _func +__version__ = '0.7.8' + +from .lib import (XATTR_NOFOLLOW, XATTR_CREATE, XATTR_REPLACE, + XATTR_NOSECURITY, XATTR_MAXNAMELEN, XATTR_FINDERINFO_NAME, + XATTR_RESOURCEFORK_NAME, _getxattr, _fgetxattr, _setxattr, _fsetxattr, + _removexattr, _fremovexattr, _listxattr, _flistxattr) + + +__all__ = [ + "XATTR_NOFOLLOW", "XATTR_CREATE", "XATTR_REPLACE", "XATTR_NOSECURITY", + "XATTR_MAXNAMELEN", "XATTR_FINDERINFO_NAME", "XATTR_RESOURCEFORK_NAME", + "xattr", "listxattr", "getxattr", "setxattr", "removexattr" +] + class xattr(object): """ @@ -45,34 +39,24 @@ """ self.obj = obj self.options = options - self.flavor = None fileno = getattr(obj, 'fileno', None) if fileno is not None: - obj = fileno() - if isinstance(obj, int): - self.flavor = 'fd' - self._bind_any('f%sxattr', obj, options) + self.value = fileno() else: - self.flavor = 'file' - self._bind_any('%sxattr', obj, options) + self.value = obj def __repr__(self): - if self.flavor: - return '<%s %s=%r>' % (type(self).__name__, self.flavor, self.obj) + if isinstance(self.value, int): + flavor = "fd" else: - return object.__repr__(self) + flavor = "file" + return "<%s %s=%r>" % (type(self).__name__, flavor, self.value) - def _bind_any(self, fmt, obj, options): - options = self.options - for method in ("get", "set", "remove", "list"): - name = '_' + method - func = getattr(_xattr, fmt % (method,)) - meth = _boundfunc(func, obj) - try: - meth.__name__ = name - except TypeError: - pass - setattr(self, name, meth) + def _call(self, name_func, fd_func, *args): + if isinstance(self.value, int): + return fd_func(self.value, *args) + else: + return name_func(self.value, *args) def get(self, name, options=0): """ @@ -81,7 +65,7 @@ See x-man-page://2/getxattr for options and possible errors. """ - return self._get(name, 0, 0, options | self.options) + return self._call(_getxattr, _fgetxattr, name, 0, 0, options | self.options) def set(self, name, value, options=0): """ @@ -90,7 +74,7 @@ See x-man-page://2/setxattr for options and possible errors. """ - self._set(name, value, 0, options | self.options) + return self._call(_setxattr, _fsetxattr, name, value, 0, options | self.options) def remove(self, name, options=0): """ @@ -99,18 +83,19 @@ See x-man-page://2/removexattr for options and possible errors. """ + return self._call(_removexattr, _fremovexattr, name, options | self.options) self._remove(name, options | self.options) def list(self, options=0): """ Retrieves the extended attributes currently set as a list - of unicode strings. Raises ``IOError`` on failure. + of strings. Raises ``IOError`` on failure. See x-man-page://2/listxattr for options and possible errors. """ - res = self._list(options | self.options).split('\x00') + res = self._call(_listxattr, _flistxattr, options | self.options).split(b'\x00') res.pop() - return [unicode(s, 'utf-8') for s in res] + return [s.decode('utf-8') for s in res] # dict-like methods @@ -186,20 +171,19 @@ def listxattr(f, symlink=False): - __doc__ = xattr.list.__doc__ return tuple(xattr(f).list(options=symlink and XATTR_NOFOLLOW or 0)) + def getxattr(f, attr, symlink=False): - __doc__ = xattr.get.__doc__ return xattr(f).get(attr, options=symlink and XATTR_NOFOLLOW or 0) + def setxattr(f, attr, value, options=0, symlink=False): - __doc__ = xattr.set.__doc__ if symlink: options |= XATTR_NOFOLLOW return xattr(f).set(attr, value, options=options) + def removexattr(f, attr, symlink=False): - __doc__ = xattr.remove.__doc__ options = symlink and XATTR_NOFOLLOW or 0 return xattr(f).remove(attr, options=options) diff -Nru python-xattr-0.6.4/xattr/lib.py python-xattr-0.7.8/xattr/lib.py --- python-xattr-0.6.4/xattr/lib.py 1970-01-01 00:00:00.000000000 +0000 +++ python-xattr-0.7.8/xattr/lib.py 2015-06-25 17:25:42.000000000 +0000 @@ -0,0 +1,740 @@ +import os +import sys + +import cffi + +ffi = cffi.FFI() +ffi.cdef(""" +#define XATTR_NOFOLLOW ... +#define XATTR_CREATE ... +#define XATTR_REPLACE ... +#define XATTR_NOSECURITY ... +#define XATTR_MAXNAMELEN ... + +ssize_t xattr_getxattr(const char *, const char *, void *, ssize_t, uint32_t, int); +ssize_t xattr_fgetxattr(int, const char *, void *, ssize_t, uint32_t, int); + +ssize_t xattr_setxattr(const char *, const char *, void *, ssize_t, uint32_t, int); +ssize_t xattr_fsetxattr(int, const char *, void *, ssize_t, uint32_t, int); + +ssize_t xattr_removexattr(const char *, const char *, int); +ssize_t xattr_fremovexattr(int, const char *, int); + +ssize_t xattr_listxattr(const char *, char *, size_t, int); +ssize_t xattr_flistxattr(int, char *, size_t, int); + +""") + +lib = ffi.verify(""" +#include "Python.h" +#ifdef __FreeBSD__ +#include +#elif defined(__SUN__) || defined(__sun__) || defined(__sun) +#include +#include +#include +#include +#include +#include +#else +#include +#endif + +#ifdef __FreeBSD__ + +/* FreeBSD compatibility API */ +#define XATTR_XATTR_NOFOLLOW 0x0001 +#define XATTR_XATTR_CREATE 0x0002 +#define XATTR_XATTR_REPLACE 0x0004 +#define XATTR_XATTR_NOSECURITY 0x0008 + +#define XATTR_CREATE 0x1 +#define XATTR_REPLACE 0x2 + +/* Converts a freebsd format attribute list into a NULL terminated list. + * While the man page on extattr_list_file says it is NULL terminated, + * it is actually the first byte that is the length of the + * following attribute. + */ +static void convert_bsd_list(char *namebuf, size_t size) +{ + size_t offset = 0; + while(offset < size) { + int length = (int) namebuf[offset]; + memmove(namebuf+offset, namebuf+offset+1, length); + namebuf[offset+length] = '\\0'; + offset += length+1; + } +} + +static ssize_t xattr_getxattr(const char *path, const char *name, + void *value, ssize_t size, u_int32_t position, + int options) +{ + if (position != 0 || + !(options == 0 || options == XATTR_XATTR_NOFOLLOW)) { + return -1; + } + + if (options & XATTR_XATTR_NOFOLLOW) { + return extattr_get_link(path, EXTATTR_NAMESPACE_USER, + name, value, size); + } + else { + return extattr_get_file(path, EXTATTR_NAMESPACE_USER, + name, value, size); + } +} + +static ssize_t xattr_setxattr(const char *path, const char *name, + void *value, ssize_t size, u_int32_t position, + int options) +{ + int rv = 0; + int nofollow; + + if (position != 0) { + return -1; + } + + nofollow = options & XATTR_XATTR_NOFOLLOW; + options &= ~XATTR_XATTR_NOFOLLOW; + + if (options == XATTR_XATTR_CREATE || + options == XATTR_XATTR_REPLACE) { + + /* meh. FreeBSD doesn't really have this in its + * API... Oh well. + */ + } + else if (options != 0) { + return -1; + } + + if (nofollow) { + rv = extattr_set_link(path, EXTATTR_NAMESPACE_USER, + name, value, size); + } + else { + rv = extattr_set_file(path, EXTATTR_NAMESPACE_USER, + name, value, size); + } + + /* freebsd returns the written length on success, not zero. */ + if (rv >= 0) { + return 0; + } + else { + return rv; + } +} + +static ssize_t xattr_removexattr(const char *path, const char *name, + int options) +{ + if (!(options == 0 || + options == XATTR_XATTR_NOFOLLOW)) { + return -1; + } + + if (options & XATTR_XATTR_NOFOLLOW) { + return extattr_delete_link(path, EXTATTR_NAMESPACE_USER, name); + } + else { + return extattr_delete_file(path, EXTATTR_NAMESPACE_USER, name); + } +} + + +static ssize_t xattr_listxattr(const char *path, char *namebuf, + size_t size, int options) +{ + ssize_t rv = 0; + if (!(options == 0 || + options == XATTR_XATTR_NOFOLLOW)) { + return -1; + } + + if (options & XATTR_XATTR_NOFOLLOW) { + rv = extattr_list_link(path, EXTATTR_NAMESPACE_USER, namebuf, size); + } + else { + rv = extattr_list_file(path, EXTATTR_NAMESPACE_USER, namebuf, size); + } + + if (rv > 0 && namebuf) { + convert_bsd_list(namebuf, rv); + } + + return rv; +} + +static ssize_t xattr_fgetxattr(int fd, const char *name, void *value, + ssize_t size, u_int32_t position, int options) +{ + if (position != 0 || + !(options == 0 || options == XATTR_XATTR_NOFOLLOW)) { + return -1; + } + + if (options & XATTR_XATTR_NOFOLLOW) { + return -1; + } + else { + return extattr_get_fd(fd, EXTATTR_NAMESPACE_USER, name, value, size); + } +} + +static ssize_t xattr_fsetxattr(int fd, const char *name, void *value, + ssize_t size, u_int32_t position, int options) +{ + int rv = 0; + int nofollow; + + if (position != 0) { + return -1; + } + + nofollow = options & XATTR_XATTR_NOFOLLOW; + options &= ~XATTR_XATTR_NOFOLLOW; + + if (options == XATTR_XATTR_CREATE || + options == XATTR_XATTR_REPLACE) { + /* freebsd noop */ + } + else if (options != 0) { + return -1; + } + + if (nofollow) { + return -1; + } + else { + rv = extattr_set_fd(fd, EXTATTR_NAMESPACE_USER, + name, value, size); + } + + /* freebsd returns the written length on success, not zero. */ + if (rv >= 0) { + return 0; + } + else { + return rv; + } +} + +static ssize_t xattr_fremovexattr(int fd, const char *name, int options) +{ + + if (!(options == 0 || + options == XATTR_XATTR_NOFOLLOW)) { + return -1; + } + + if (options & XATTR_XATTR_NOFOLLOW) { + return -1; + } + else { + return extattr_delete_fd(fd, EXTATTR_NAMESPACE_USER, name); + } +} + + +static ssize_t xattr_flistxattr(int fd, char *namebuf, size_t size, int options) +{ + ssize_t rv = 0; + + if (!(options == 0 || + options == XATTR_XATTR_NOFOLLOW)) { + return -1; + } + + if (options & XATTR_XATTR_NOFOLLOW) { + return -1; + } + else { + rv = extattr_list_fd(fd, EXTATTR_NAMESPACE_USER, namebuf, size); + } + + if (rv > 0 && namebuf) { + convert_bsd_list(namebuf, rv); + } + + return rv; +} + +#elif defined(__SUN__) || defined(__sun__) || defined(__sun) + +/* Solaris 9 and later compatibility API */ +#define XATTR_XATTR_NOFOLLOW 0x0001 +#define XATTR_XATTR_CREATE 0x0002 +#define XATTR_XATTR_REPLACE 0x0004 +#define XATTR_XATTR_NOSECURITY 0x0008 + +#define XATTR_CREATE 0x1 +#define XATTR_REPLACE 0x2 + +#ifndef u_int32_t +#define u_int32_t uint32_t +#endif + +static ssize_t xattr_fgetxattr(int fd, const char *name, void *value, + ssize_t size, u_int32_t position, int options) +{ + int xfd; + ssize_t bytes; + struct stat statbuf; + + /* XXX should check that name does not have / characters in it */ + xfd = openat(fd, name, O_RDONLY | O_XATTR); + if (xfd == -1) { + return -1; + } + if (lseek(xfd, position, SEEK_SET) == -1) { + close(xfd); + return -1; + } + if (value == NULL) { + if (fstat(xfd, &statbuf) == -1) { + close(xfd); + return -1; + } + close(xfd); + return statbuf.st_size; + } + /* XXX should keep reading until the buffer is exhausted or EOF */ + bytes = read(xfd, value, size); + close(xfd); + return bytes; +} + +static ssize_t xattr_getxattr(const char *path, const char *name, + void *value, ssize_t size, u_int32_t position, + int options) +{ + int fd; + ssize_t bytes; + + if (position != 0 || + !(options == 0 || options == XATTR_XATTR_NOFOLLOW)) { + return -1; + } + + fd = open(path, + O_RDONLY | + ((options & XATTR_XATTR_NOFOLLOW) ? O_NOFOLLOW : 0)); + if (fd == -1) { + return -1; + } + bytes = xattr_fgetxattr(fd, name, value, size, position, options); + close(fd); + return bytes; +} + +static ssize_t xattr_fsetxattr(int fd, const char *name, void *value, + ssize_t size, u_int32_t position, int options) +{ + int xfd; + ssize_t bytes = 0; + + /* XXX should check that name does not have / characters in it */ + xfd = openat(fd, name, O_XATTR | O_TRUNC | + ((options & XATTR_XATTR_CREATE) ? O_EXCL : 0) | + ((options & XATTR_XATTR_NOFOLLOW) ? O_NOFOLLOW : 0) | + ((options & XATTR_XATTR_REPLACE) ? O_RDWR : O_WRONLY|O_CREAT), + 0644); + if (xfd == -1) { + return -1; + } + while (size > 0) { + bytes = write(xfd, value, size); + if (bytes == -1) { + close(xfd); + return -1; + } + size -= bytes; + value += bytes; + } + close(xfd); + return 0; +} + +static ssize_t xattr_setxattr(const char *path, const char *name, + void *value, ssize_t size, u_int32_t position, + int options) +{ + int fd; + ssize_t bytes; + + if (position != 0) { + return -1; + } + + fd = open(path, + O_RDONLY | (options & XATTR_XATTR_NOFOLLOW) ? O_NOFOLLOW : 0); + if (fd == -1) { + return -1; + } + bytes = xattr_fsetxattr(fd, name, value, size, position, options); + close(fd); + return bytes; +} + +static ssize_t xattr_fremovexattr(int fd, const char *name, int options) +{ + int xfd, status; + /* XXX should check that name does not have / characters in it */ + if (!(options == 0 || options == XATTR_XATTR_NOFOLLOW)) { + return -1; + } + if (options & XATTR_XATTR_NOFOLLOW) { + return -1; + } + xfd = openat(fd, ".", O_XATTR, 0644); + if (xfd == -1) { + return -1; + } + status = unlinkat(xfd, name, 0); + close(xfd); + return status; +} + +static ssize_t xattr_removexattr(const char *path, const char *name, + int options) +{ + int fd; + ssize_t status; + + fd = open(path, + O_RDONLY | ((options & XATTR_XATTR_NOFOLLOW) ? O_NOFOLLOW : 0)); + if (fd == -1) { + return -1; + } + status = xattr_fremovexattr(fd, name, options); + close(fd); + return status; +} + +static ssize_t xattr_xflistxattr(int xfd, char *namebuf, size_t size, int options) +{ + int esize; + DIR *dirp; + struct dirent *entry; + ssize_t nsize = 0; + + dirp = fdopendir(xfd); + if (dirp == NULL) { + return (-1); + } + while (entry = readdir(dirp)) { + if (strcmp(entry->d_name, ".") == 0 || + strcmp(entry->d_name, "..") == 0) + continue; + esize = strlen(entry->d_name); + if (nsize + esize + 1 <= size) { + snprintf((char *)(namebuf + nsize), esize + 1, + entry->d_name); + } + nsize += esize + 1; /* +1 for \\0 */ + } + closedir(dirp); + return nsize; +} +static ssize_t xattr_flistxattr(int fd, char *namebuf, size_t size, int options) +{ + int xfd; + + xfd = openat(fd, ".", O_RDONLY | O_XATTR); + return xattr_xflistxattr(xfd, namebuf, size, options); +} + +static ssize_t xattr_listxattr(const char *path, char *namebuf, + size_t size, int options) +{ + int xfd; + + xfd = attropen(path, ".", O_RDONLY); + return xattr_xflistxattr(xfd, namebuf, size, options); +} + +#elif !defined(XATTR_NOFOLLOW) +/* Linux compatibility API */ +#define XATTR_XATTR_NOFOLLOW 0x0001 +#define XATTR_XATTR_CREATE 0x0002 +#define XATTR_XATTR_REPLACE 0x0004 +#define XATTR_XATTR_NOSECURITY 0x0008 +static ssize_t xattr_getxattr(const char *path, const char *name, void *value, ssize_t size, u_int32_t position, int options) { + if (position != 0 || !(options == 0 || options == XATTR_XATTR_NOFOLLOW)) { + return -1; + } + if (options & XATTR_XATTR_NOFOLLOW) { + return lgetxattr(path, name, value, size); + } else { + return getxattr(path, name, value, size); + } +} + +static ssize_t xattr_setxattr(const char *path, const char *name, void *value, ssize_t size, u_int32_t position, int options) { + int nofollow; + if (position != 0) { + return -1; + } + nofollow = options & XATTR_XATTR_NOFOLLOW; + options &= ~XATTR_XATTR_NOFOLLOW; + if (options == XATTR_XATTR_CREATE) { + options = XATTR_CREATE; + } else if (options == XATTR_XATTR_REPLACE) { + options = XATTR_REPLACE; + } else if (options != 0) { + return -1; + } + if (nofollow) { + return lsetxattr(path, name, value, size, options); + } else { + return setxattr(path, name, value, size, options); + } +} + +static ssize_t xattr_removexattr(const char *path, const char *name, int options) { + if (!(options == 0 || options == XATTR_XATTR_NOFOLLOW)) { + return -1; + } + if (options & XATTR_XATTR_NOFOLLOW) { + return lremovexattr(path, name); + } else { + return removexattr(path, name); + } +} + + +static ssize_t xattr_listxattr(const char *path, char *namebuf, size_t size, int options) { + if (!(options == 0 || options == XATTR_XATTR_NOFOLLOW)) { + return -1; + } + if (options & XATTR_XATTR_NOFOLLOW) { + return llistxattr(path, namebuf, size); + } else { + return listxattr(path, namebuf, size); + } +} + +static ssize_t xattr_fgetxattr(int fd, const char *name, void *value, ssize_t size, u_int32_t position, int options) { + if (position != 0 || !(options == 0 || options == XATTR_XATTR_NOFOLLOW)) { + return -1; + } + if (options & XATTR_XATTR_NOFOLLOW) { + return -1; + } else { + return fgetxattr(fd, name, value, size); + } +} + +static ssize_t xattr_fsetxattr(int fd, const char *name, void *value, ssize_t size, u_int32_t position, int options) { + int nofollow; + if (position != 0) { + return -1; + } + nofollow = options & XATTR_XATTR_NOFOLLOW; + options &= ~XATTR_XATTR_NOFOLLOW; + if (options == XATTR_XATTR_CREATE) { + options = XATTR_CREATE; + } else if (options == XATTR_XATTR_REPLACE) { + options = XATTR_REPLACE; + } else if (options != 0) { + return -1; + } + if (options & XATTR_XATTR_NOFOLLOW) { + return -1; + } else { + return fsetxattr(fd, name, value, size, options); + } +} + +static ssize_t xattr_fremovexattr(int fd, const char *name, int options) { + if (!(options == 0 || options == XATTR_XATTR_NOFOLLOW)) { + return -1; + } + if (options & XATTR_XATTR_NOFOLLOW) { + return -1; + } else { + return fremovexattr(fd, name); + } +} + + +static ssize_t xattr_flistxattr(int fd, char *namebuf, size_t size, int options) { + if (!(options == 0 || options == XATTR_XATTR_NOFOLLOW)) { + return -1; + } + if (options & XATTR_XATTR_NOFOLLOW) { + return -1; + } else { + return flistxattr(fd, namebuf, size); + } +} + +#else /* Mac OS X assumed */ +#define xattr_getxattr getxattr +#define xattr_fgetxattr fgetxattr +#define xattr_removexattr removexattr +#define xattr_fremovexattr fremovexattr +#define xattr_setxattr setxattr +#define xattr_fsetxattr fsetxattr +#define xattr_listxattr listxattr +#define xattr_flistxattr flistxattr +#endif + +#ifndef XATTR_MAXNAMELEN +#define XATTR_MAXNAMELEN 127 +#endif + +#ifndef XATTR_NOFOLLOW +#define XATTR_NOFOLLOW 0x0001 +#endif + +#ifndef XATTR_NOSECURITY +#define XATTR_NOSECURITY 0x0008 +#endif +""", ext_package='xattr') + +XATTR_NOFOLLOW = lib.XATTR_NOFOLLOW +XATTR_CREATE = lib.XATTR_CREATE +XATTR_REPLACE = lib.XATTR_REPLACE +XATTR_NOSECURITY = lib.XATTR_NOSECURITY +XATTR_MAXNAMELEN = lib.XATTR_MAXNAMELEN + +XATTR_FINDERINFO_NAME = "com.apple.FinderInfo" +XATTR_RESOURCEFORK_NAME = "com.apple.ResourceFork" + + +def fs_encode(val): + if not isinstance(val, bytes): + return val.encode(sys.getfilesystemencoding()) + else: + return val + + +def _check_bytes(val): + if not isinstance(val, bytes): + raise TypeError( + "Value must be bytes, %s was passed." % type(val).__name__ + ) + + +def error(path=None): + errno = ffi.errno + strerror = os.strerror(ffi.errno) + if path: + raise IOError(errno, strerror, path) + else: + raise IOError(errno, strerror) + + +def _getxattr(path, name, size=0, position=0, options=0): + """ + getxattr(path, name, size=0, position=0, options=0) -> str + """ + path = fs_encode(path) + name = fs_encode(name) + if size == 0: + res = lib.xattr_getxattr(path, name, ffi.NULL, 0, position, options) + if res == -1: + raise error(path) + size = res + buf = ffi.new("char[]", size) + res = lib.xattr_getxattr(path, name, buf, size, position, options) + if res == -1: + raise error(path) + return ffi.buffer(buf)[:res] + + +def _fgetxattr(fd, name, size=0, position=0, options=0): + """ + fgetxattr(fd, name, size=0, position=0, options=0) -> str + """ + name = fs_encode(name) + if size == 0: + res = lib.xattr_fgetxattr(fd, name, ffi.NULL, 0, position, options) + if res == -1: + raise error() + size = res + buf = ffi.new("char[]", size) + res = lib.xattr_fgetxattr(fd, name, buf, size, position, options) + if res == -1: + raise error() + return ffi.buffer(buf)[:res] + + +def _setxattr(path, name, value, position=0, options=0): + """ + setxattr(path, name, value, position=0, options=0) -> None + """ + _check_bytes(value) + path = fs_encode(path) + name = fs_encode(name) + res = lib.xattr_setxattr(path, name, value, len(value), position, options) + if res: + raise error(path) + + +def _fsetxattr(fd, name, value, position=0, options=0): + """ + fsetxattr(fd, name, value, position=0, options=0) -> None + """ + _check_bytes(value) + name = fs_encode(name) + res = lib.xattr_fsetxattr(fd, name, value, len(value), position, options) + if res: + raise error() + + +def _removexattr(path, name, options=0): + """ + removexattr(path, name, options=0) -> None + """ + path = fs_encode(path) + name = fs_encode(name) + res = lib.xattr_removexattr(path, name, options) + if res: + raise error(path) + + +def _fremovexattr(fd, name, options=0): + """ + fremovexattr(fd, name, options=0) -> None + """ + name = fs_encode(name) + res = lib.xattr_fremovexattr(fd, name, options) + if res: + raise error() + + +def _listxattr(path, options=0): + """ + listxattr(path, options=0) -> str + """ + path = fs_encode(path) + res = lib.xattr_listxattr(path, ffi.NULL, 0, options) + if res == -1: + raise error(path) + elif res == 0: + return b"" + buf = ffi.new("char[]", res) + res = lib.xattr_listxattr(path, buf, res, options) + if res == -1: + raise error(path) + return ffi.buffer(buf)[:res] + + +def _flistxattr(fd, options=0): + """ + flistxattr(fd, options=0) -> str + """ + res = lib.xattr_flistxattr(fd, ffi.NULL, 0, options) + if res == -1: + raise error() + buf = ffi.new("char[]", res) + res = lib.xattr_flistxattr(fd, buf, res, options) + if res == -1: + raise error() + return ffi.buffer(buf)[:res] diff -Nru python-xattr-0.6.4/xattr/tests/__init__.py python-xattr-0.7.8/xattr/tests/__init__.py --- python-xattr-0.6.4/xattr/tests/__init__.py 2012-01-23 17:24:13.000000000 +0000 +++ python-xattr-0.7.8/xattr/tests/__init__.py 2015-06-25 17:25:42.000000000 +0000 @@ -1,3 +1,5 @@ +import os +import sys import unittest @@ -15,7 +17,5 @@ if __name__ == '__main__': - import os - import sys sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))) - main() \ No newline at end of file + main() diff -Nru python-xattr-0.6.4/xattr/tests/test_xattr.py python-xattr-0.7.8/xattr/tests/test_xattr.py --- python-xattr-0.6.4/xattr/tests/test_xattr.py 2012-01-23 17:28:45.000000000 +0000 +++ python-xattr-0.7.8/xattr/tests/test_xattr.py 2015-06-25 17:25:42.000000000 +0000 @@ -1,51 +1,95 @@ import os +import sys from unittest import TestCase from tempfile import mkdtemp, NamedTemporaryFile import xattr -class TestFile(TestCase): - def setUp(self): - self.tempfile = NamedTemporaryFile() - self.tempfilename = self.tempfile.name - def tearDown(self): - self.tempfile.close() - - def testAttr(self): +class BaseTestXattr(object): + def test_attr(self): x = xattr.xattr(self.tempfile) - self.assertEqual(x.keys(), []) - self.assertEqual(dict(x), {}) - x['user.sopal'] = 'foo' - x['user.sop.foo'] = 'bar' + # Solaris 11 and forward contain system attributes (file flags) in + # extended attributes present on all files, so cons them up into a + # comparison dict. + d = {} + if sys.platform == 'sunos5' and 'SUNWattr_ro' in x: + d['SUNWattr_ro'] = x['SUNWattr_ro'] + d['SUNWattr_rw'] = x['SUNWattr_rw'] + + self.assertEqual(list(x.keys()), list(d.keys())) + self.assertEqual(list(x.list()), list(d.keys())) + self.assertEqual(dict(x), d) + + x['user.sopal'] = b'foo' + x['user.sop.foo'] = b'bar' + x[u'user.\N{SNOWMAN}'] = b'not a snowman' del x x = xattr.xattr(self.tempfile) + attrs = set(x.list()) self.assertTrue('user.sopal' in x) - self.assertEqual(x['user.sopal'], 'foo') + self.assertTrue(u'user.sopal' in attrs) + self.assertEqual(x['user.sopal'], b'foo') self.assertTrue('user.sop.foo' in x) - self.assertEqual(x['user.sop.foo'], 'bar') + self.assertTrue(u'user.sop.foo' in attrs) + self.assertEqual(x['user.sop.foo'], b'bar') + self.assertTrue(u'user.\N{SNOWMAN}' in x) + self.assertTrue(u'user.\N{SNOWMAN}' in attrs) + self.assertEqual(x[u'user.\N{SNOWMAN}'], + b'not a snowman') + del x[u'user.\N{SNOWMAN}'] del x['user.sop.foo'] del x x = xattr.xattr(self.tempfile) self.assertTrue('user.sop.foo' not in x) - def testSymlinkAttrs(self): + def test_setxattr_unicode_error(self): + x = xattr.xattr(self.tempfile) + def assign(): + x['abc'] = u'abc' + self.assertRaises(TypeError, assign) + + if sys.version_info[0] >= 3: + msg = "Value must be bytes, str was passed." + else: + msg = "Value must be bytes, unicode was passed." + + try: + assign() + except TypeError: + e = sys.exc_info()[1] + self.assertEqual(str(e), msg) + + def test_symlink_attrs(self): + # Solaris doesn't support extended attributes on symlinks + if sys.platform == 'sunos5': + return symlinkPath = self.tempfilename + '.link' os.symlink(self.tempfilename, symlinkPath) try: symlink = xattr.xattr(symlinkPath, options=xattr.XATTR_NOFOLLOW) realfile = xattr.xattr(self.tempfilename) - symlink['user.islink'] = 'true' + symlink['user.islink'] = b'true' self.assertEqual(dict(realfile), {}) - self.assertEqual(symlink['user.islink'], 'true') + self.assertEqual(symlink['user.islink'], b'true') finally: os.remove(symlinkPath) -class TestDir(TestFile): + +class TestFile(TestCase, BaseTestXattr): + def setUp(self): + self.tempfile = NamedTemporaryFile() + self.tempfilename = self.tempfile.name + + def tearDown(self): + self.tempfile.close() + + +class TestDir(TestCase, BaseTestXattr): def setUp(self): self.tempfile = mkdtemp() self.tempfilename = self.tempfile diff -Nru python-xattr-0.6.4/xattr/tool.py python-xattr-0.7.8/xattr/tool.py --- python-xattr-0.6.4/xattr/tool.py 2011-08-17 05:12:49.000000000 +0000 +++ python-xattr-0.7.8/xattr/tool.py 2015-06-25 17:25:42.000000000 +0000 @@ -25,66 +25,74 @@ # IN THE SOFTWARE. ## +from __future__ import print_function + import sys import os import getopt -import xattr import zlib +import xattr + + def usage(e=None): if e: - print e - print "" + print(e) + print("") name = os.path.basename(sys.argv[0]) - print "usage: %s [-lz] file [file ...]" % (name,) - print " %s -p [-lz] attr_name file [file ...]" % (name,) - print " %s -w [-z] attr_name attr_value file [file ...]" % (name,) - print " %s -d attr_name file [file ...]" % (name,) - print "" - print "The first form lists the names of all xattrs on the given file(s)." - print "The second form (-p) prints the value of the xattr attr_name." - print "The third form (-w) sets the value of the xattr attr_name to attr_value." - print "The fourth form (-d) deletes the xattr attr_name." - print "" - print "options:" - print " -h: print this help" - print " -l: print long format (attr_name: attr_value)" - print " -z: compress or decompress (if compressed) attribute value in zip format" + print("usage: %s [-lz] file [file ...]" % (name,)) + print(" %s -p [-lz] attr_name file [file ...]" % (name,)) + print(" %s -w [-z] attr_name attr_value file [file ...]" % (name,)) + print(" %s -d attr_name file [file ...]" % (name,)) + print("") + print("The first form lists the names of all xattrs on the given file(s).") + print("The second form (-p) prints the value of the xattr attr_name.") + print("The third form (-w) sets the value of the xattr attr_name to attr_value.") + print("The fourth form (-d) deletes the xattr attr_name.") + print("") + print("options:") + print(" -h: print this help") + print(" -l: print long format (attr_name: attr_value)") + print(" -z: compress or decompress (if compressed) attribute value in zip format") if e: sys.exit(64) else: sys.exit(0) + class NullsInString(Exception): """Nulls in string.""" -_FILTER=''.join([(len(repr(chr(x)))==3) and chr(x) or '.' for x in range(256)]) + +_FILTER = ''.join([(len(repr(chr(x))) == 3) and chr(x) or '.' for x in range(256)]) + def _dump(src, length=16): - result=[] - for i in xrange(0, len(src), length): + result = [] + for i in range(0, len(src), length): s = src[i:i+length] - hexa = ' '.join(["%02X"%ord(x) for x in s]) + hexa = ' '.join(["%02X" % ord(x) for x in s]) printable = s.translate(_FILTER) result.append("%04X %-*s %s\n" % (i, length*3, hexa, printable)) return ''.join(result) + def main(): try: (optargs, args) = getopt.getopt(sys.argv[1:], "hlpwdz", ["help"]) - except getopt.GetoptError, e: + except getopt.GetoptError as e: usage(e) - attr_name = None + attr_name = None long_format = False - read = False - write = False - delete = False - compress = lambda x: x - decompress = compress - status = 0 + read = False + write = False + delete = False + compress = lambda x: x + decompress = compress + status = 0 for opt, arg in optargs: if opt in ("-h", "--help"): @@ -104,7 +112,7 @@ if read or write: usage("-d not allowed with -p or -w") elif opt == "-z": - compress = zlib.compress + compress = zlib.compress decompress = zlib.decompress if write or delete: @@ -132,25 +140,24 @@ sys.stderr.write("No such file: %s\n" % (filename,)) else: sys.stderr.write(str(e) + "\n") - status = 1 try: attrs = xattr.xattr(filename) - except (IOError, OSError), e: + except (IOError, OSError) as e: onError(e) continue if write: try: attrs[attr_name] = compress(attr_value) - except (IOError, OSError), e: + except (IOError, OSError) as e: onError(e) continue elif delete: try: del attrs[attr_name] - except (IOError, OSError), e: + except (IOError, OSError) as e: onError(e) continue except KeyError: @@ -163,7 +170,7 @@ attr_names = (attr_name,) else: attr_names = attrs.keys() - except (IOError, OSError), e: + except (IOError, OSError) as e: onError(e) continue @@ -185,16 +192,16 @@ if long_format: try: if attr_value.find('\0') >= 0: - raise NullsInString; - print "".join((file_prefix, "%s: " % (attr_name,), attr_value)) + raise NullsInString + print("".join((file_prefix, "%s: " % (attr_name,), attr_value))) except (UnicodeDecodeError, NullsInString): - print "".join((file_prefix, "%s:" % (attr_name,))) - print _dump(attr_value) + print("".join((file_prefix, "%s:" % (attr_name,)))) + print(_dump(attr_value)) else: if read: - print "".join((file_prefix, attr_value)) + print("".join((file_prefix, attr_value))) else: - print "".join((file_prefix, attr_name)) + print("".join((file_prefix, attr_name))) sys.exit(status) diff -Nru python-xattr-0.6.4/xattr/_xattr.c python-xattr-0.7.8/xattr/_xattr.c --- python-xattr-0.6.4/xattr/_xattr.c 2012-02-01 19:29:19.000000000 +0000 +++ python-xattr-0.7.8/xattr/_xattr.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,946 +0,0 @@ -#include "Python.h" -#ifdef __FreeBSD__ -#include -#elif defined(__SUN__) || defined(__sun__) -#include -#include -#include -#include -#include -#else -#include -#endif - -#ifdef __FreeBSD__ - -/* FreeBSD compatibility API */ -#define XATTR_XATTR_NOFOLLOW 0x0001 -#define XATTR_XATTR_CREATE 0x0002 -#define XATTR_XATTR_REPLACE 0x0004 -#define XATTR_XATTR_NOSECURITY 0x0008 - - -/* Converts a freebsd format attribute list into a NULL terminated list. - * While the man page on extattr_list_file says it is NULL terminated, - * it is actually the first byte that is the length of the - * following attribute. - */ -static void convert_bsd_list(char *namebuf, size_t size) -{ - size_t offset = 0; - while(offset < size) { - int length = (int) namebuf[offset]; - memmove(namebuf+offset, namebuf+offset+1, length); - namebuf[offset+length] = '\0'; - offset += length+1; - } -} - -static ssize_t xattr_getxattr(const char *path, const char *name, - void *value, ssize_t size, u_int32_t position, - int options) -{ - if (position != 0 || - !(options == 0 || options == XATTR_XATTR_NOFOLLOW)) { - return -1; - } - - if (options & XATTR_XATTR_NOFOLLOW) { - return extattr_get_link(path, EXTATTR_NAMESPACE_USER, - name, value, size); - } - else { - return extattr_get_file(path, EXTATTR_NAMESPACE_USER, - name, value, size); - } -} - -static ssize_t xattr_setxattr(const char *path, const char *name, - void *value, ssize_t size, u_int32_t position, - int options) -{ - int rv = 0; - int nofollow; - - if (position != 0) { - return -1; - } - - nofollow = options & XATTR_XATTR_NOFOLLOW; - options &= ~XATTR_XATTR_NOFOLLOW; - - if (options == XATTR_XATTR_CREATE || - options == XATTR_XATTR_REPLACE) { - - /* meh. FreeBSD doesn't really have this in it's - * API... Oh well. - */ - } - else if (options != 0) { - return -1; - } - - if (nofollow) { - rv = extattr_set_link(path, EXTATTR_NAMESPACE_USER, - name, value, size); - } - else { - rv = extattr_set_file(path, EXTATTR_NAMESPACE_USER, - name, value, size); - } - - /* freebsd returns the written length on success, not zero. */ - if (rv >= 0) { - return 0; - } - else { - return rv; - } -} - -static ssize_t xattr_removexattr(const char *path, const char *name, - int options) -{ - if (!(options == 0 || - options == XATTR_XATTR_NOFOLLOW)) { - return -1; - } - - if (options & XATTR_XATTR_NOFOLLOW) { - return extattr_delete_link(path, EXTATTR_NAMESPACE_USER, name); - } - else { - return extattr_delete_file(path, EXTATTR_NAMESPACE_USER, name); - } -} - - -static ssize_t xattr_listxattr(const char *path, char *namebuf, - size_t size, int options) -{ - ssize_t rv = 0; - if (!(options == 0 || - options == XATTR_XATTR_NOFOLLOW)) { - return -1; - } - - if (options & XATTR_XATTR_NOFOLLOW) { - rv = extattr_list_link(path, EXTATTR_NAMESPACE_USER, namebuf, size); - } - else { - rv = extattr_list_file(path, EXTATTR_NAMESPACE_USER, namebuf, size); - } - - if (rv > 0 && namebuf) { - convert_bsd_list(namebuf, rv); - } - - return rv; -} - -static ssize_t xattr_fgetxattr(int fd, const char *name, void *value, - ssize_t size, u_int32_t position, int options) -{ - if (position != 0 || - !(options == 0 || options == XATTR_XATTR_NOFOLLOW)) { - return -1; - } - - if (options & XATTR_XATTR_NOFOLLOW) { - return -1; - } - else { - return extattr_get_fd(fd, EXTATTR_NAMESPACE_USER, name, value, size); - } -} - -static ssize_t xattr_fsetxattr(int fd, const char *name, void *value, - ssize_t size, u_int32_t position, int options) -{ - int rv = 0; - int nofollow; - - if (position != 0) { - return -1; - } - - nofollow = options & XATTR_XATTR_NOFOLLOW; - options &= ~XATTR_XATTR_NOFOLLOW; - - if (options == XATTR_XATTR_CREATE || - options == XATTR_XATTR_REPLACE) { - /* freebsd noop */ - } - else if (options != 0) { - return -1; - } - - if (nofollow) { - return -1; - } - else { - rv = extattr_set_fd(fd, EXTATTR_NAMESPACE_USER, - name, value, size); - } - - /* freebsd returns the written length on success, not zero. */ - if (rv >= 0) { - return 0; - } - else { - return rv; - } -} - -static ssize_t xattr_fremovexattr(int fd, const char *name, int options) -{ - - if (!(options == 0 || - options == XATTR_XATTR_NOFOLLOW)) { - return -1; - } - - if (options & XATTR_XATTR_NOFOLLOW) { - return -1; - } - else { - return extattr_delete_fd(fd, EXTATTR_NAMESPACE_USER, name); - } -} - - -static ssize_t xattr_flistxattr(int fd, char *namebuf, size_t size, int options) -{ - ssize_t rv = 0; - - if (!(options == 0 || - options == XATTR_XATTR_NOFOLLOW)) { - return -1; - } - - if (options & XATTR_XATTR_NOFOLLOW) { - return -1; - } - else { - rv = extattr_list_fd(fd, EXTATTR_NAMESPACE_USER, namebuf, size); - } - - if (rv > 0 && namebuf) { - convert_bsd_list(namebuf, rv); - } - - return rv; -} - -#elif defined(__SUN__) || defined(__sun__) - -/* Solaris 9 and later compatibility API */ -#define XATTR_XATTR_NOFOLLOW 0x0001 -#define XATTR_XATTR_CREATE 0x0002 -#define XATTR_XATTR_REPLACE 0x0004 -#define XATTR_XATTR_NOSECURITY 0x0008 - -#define u_int32_t unsigned int - -static ssize_t xattr_fgetxattr(int fd, const char *name, void *value, - ssize_t size, u_int32_t position, int options) -{ - int xfd; - ssize_t bytes; - struct stat statbuf; - - /* XXX should check that name does not have / characters in it */ - xfd = openat(fd, name, O_RDONLY | O_XATTR); - if (xfd == -1) { - return -1; - } - if (lseek(xfd, position, SEEK_SET) == -1) { - close(xfd); - return -1; - } - if (value == NULL) { - if (fstat(xfd, &statbuf) == -1) { - close(xfd); - return -1; - } - close(xfd); - return statbuf.st_size; - } - /* XXX should keep reading until the buffer is exhausted or EOF */ - bytes = read(xfd, value, size); - close(xfd); - return bytes; -} - -static ssize_t xattr_getxattr(const char *path, const char *name, - void *value, ssize_t size, u_int32_t position, - int options) -{ - int fd; - ssize_t bytes; - - if (position != 0 || - !(options == 0 || options == XATTR_XATTR_NOFOLLOW)) { - return -1; - } - - fd = open(path, - O_RDONLY | - ((options & XATTR_XATTR_NOFOLLOW) ? O_NOFOLLOW : 0)); - if (fd == -1) { - return -1; - } - bytes = xattr_fgetxattr(fd, name, value, size, position, options); - close(fd); - return bytes; -} - -static ssize_t xattr_fsetxattr(int fd, const char *name, void *value, - ssize_t size, u_int32_t position, int options) -{ - int xfd; - ssize_t bytes = 0; - - /* XXX should check that name does not have / characters in it */ - xfd = openat(fd, name, O_XATTR | O_TRUNC | - ((options & XATTR_XATTR_CREATE) ? O_EXCL : 0) | - ((options & XATTR_XATTR_NOFOLLOW) ? O_NOFOLLOW : 0) | - ((options & XATTR_XATTR_REPLACE) ? O_RDWR : O_WRONLY|O_CREAT), - 0644); - if (xfd == -1) { - return -1; - } - while (size > 0) { - bytes = write(xfd, value, size); - if (bytes == -1) { - close(xfd); - return -1; - } - size -= bytes; - value += bytes; - } - close(xfd); - return 0; -} - -static ssize_t xattr_setxattr(const char *path, const char *name, - void *value, ssize_t size, u_int32_t position, - int options) -{ - int fd; - ssize_t bytes; - - if (position != 0) { - return -1; - } - - fd = open(path, - O_RDONLY | (options & XATTR_XATTR_NOFOLLOW) ? O_NOFOLLOW : 0); - if (fd == -1) { - return -1; - } - bytes = xattr_fsetxattr(fd, name, value, size, position, options); - close(fd); - return bytes; -} - -static ssize_t xattr_fremovexattr(int fd, const char *name, int options) -{ - int xfd, status; - /* XXX should check that name does not have / characters in it */ - if (!(options == 0 || options == XATTR_XATTR_NOFOLLOW)) { - return -1; - } - if (options & XATTR_XATTR_NOFOLLOW) { - return -1; - } - xfd = openat(fd, ".", O_XATTR, 0644); - if (xfd == -1) { - return -1; - } - status = unlinkat(xfd, name, 0); - close(xfd); - return status; -} - -static ssize_t xattr_removexattr(const char *path, const char *name, - int options) -{ - int fd; - ssize_t status; - - fd = open(path, - O_RDONLY | ((options & XATTR_XATTR_NOFOLLOW) ? O_NOFOLLOW : 0)); - if (fd == -1) { - return -1; - } - status = xattr_fremovexattr(fd, name, options); - close(fd); - return status; -} - -static ssize_t xattr_xflistxattr(int xfd, char *namebuf, size_t size, int options) -{ - int esize; - DIR *dirp; - struct dirent *entry; - ssize_t nsize = 0; - - dirp = fdopendir(xfd); - if (dirp == NULL) { - return (-1); - } - while (entry = readdir(dirp)) { - if (strcmp(entry->d_name, ".") == 0 || - strcmp(entry->d_name, "..") == 0) - continue; - esize = strlen(entry->d_name); - if (nsize + esize + 1 <= size) { - snprintf((char *)(namebuf + nsize), esize + 1, - entry->d_name); - } - nsize += esize + 1; /* +1 for \0 */ - } - closedir(dirp); - return nsize; -} -static ssize_t xattr_flistxattr(int fd, char *namebuf, size_t size, int options) -{ - int xfd; - - xfd = openat(fd, ".", O_RDONLY); - return xattr_xflistxattr(xfd, namebuf, size, options); -} - -static ssize_t xattr_listxattr(const char *path, char *namebuf, - size_t size, int options) -{ - int xfd; - - xfd = attropen(path, ".", O_RDONLY); - return xattr_xflistxattr(xfd, namebuf, size, options); -} - -#elif !defined(XATTR_NOFOLLOW) -/* Linux compatibility API */ -#define XATTR_XATTR_NOFOLLOW 0x0001 -#define XATTR_XATTR_CREATE 0x0002 -#define XATTR_XATTR_REPLACE 0x0004 -#define XATTR_XATTR_NOSECURITY 0x0008 -static ssize_t xattr_getxattr(const char *path, const char *name, void *value, ssize_t size, u_int32_t position, int options) { - if (position != 0 || !(options == 0 || options == XATTR_XATTR_NOFOLLOW)) { - return -1; - } - if (options & XATTR_XATTR_NOFOLLOW) { - return lgetxattr(path, name, value, size); - } else { - return getxattr(path, name, value, size); - } -} - -static ssize_t xattr_setxattr(const char *path, const char *name, void *value, ssize_t size, u_int32_t position, int options) { - int nofollow; - if (position != 0) { - return -1; - } - nofollow = options & XATTR_XATTR_NOFOLLOW; - options &= ~XATTR_XATTR_NOFOLLOW; - if (options == XATTR_XATTR_CREATE) { - options = XATTR_CREATE; - } else if (options == XATTR_XATTR_REPLACE) { - options = XATTR_REPLACE; - } else if (options != 0) { - return -1; - } - if (nofollow) { - return lsetxattr(path, name, value, size, options); - } else { - return setxattr(path, name, value, size, options); - } -} - -static ssize_t xattr_removexattr(const char *path, const char *name, int options) { - if (!(options == 0 || options == XATTR_XATTR_NOFOLLOW)) { - return -1; - } - if (options & XATTR_XATTR_NOFOLLOW) { - return lremovexattr(path, name); - } else { - return removexattr(path, name); - } -} - - -static ssize_t xattr_listxattr(const char *path, char *namebuf, size_t size, int options) { - if (!(options == 0 || options == XATTR_XATTR_NOFOLLOW)) { - return -1; - } - if (options & XATTR_XATTR_NOFOLLOW) { - return llistxattr(path, namebuf, size); - } else { - return listxattr(path, namebuf, size); - } -} - -static ssize_t xattr_fgetxattr(int fd, const char *name, void *value, ssize_t size, u_int32_t position, int options) { - if (position != 0 || !(options == 0 || options == XATTR_XATTR_NOFOLLOW)) { - return -1; - } - if (options & XATTR_XATTR_NOFOLLOW) { - return -1; - } else { - return fgetxattr(fd, name, value, size); - } -} - -static ssize_t xattr_fsetxattr(int fd, const char *name, void *value, ssize_t size, u_int32_t position, int options) { - int nofollow; - if (position != 0) { - return -1; - } - nofollow = options & XATTR_XATTR_NOFOLLOW; - options &= ~XATTR_XATTR_NOFOLLOW; - if (options == XATTR_XATTR_CREATE) { - options = XATTR_CREATE; - } else if (options == XATTR_XATTR_REPLACE) { - options = XATTR_REPLACE; - } else if (options != 0) { - return -1; - } - if (options & XATTR_XATTR_NOFOLLOW) { - return -1; - } else { - return fsetxattr(fd, name, value, size, options); - } -} - -static ssize_t xattr_fremovexattr(int fd, const char *name, int options) { - if (!(options == 0 || options == XATTR_XATTR_NOFOLLOW)) { - return -1; - } - if (options & XATTR_XATTR_NOFOLLOW) { - return -1; - } else { - return fremovexattr(fd, name); - } -} - - -static ssize_t xattr_flistxattr(int fd, char *namebuf, size_t size, int options) { - if (!(options == 0 || options == XATTR_XATTR_NOFOLLOW)) { - return -1; - } - if (options & XATTR_XATTR_NOFOLLOW) { - return -1; - } else { - return flistxattr(fd, namebuf, size); - } -} - -#else /* Mac OS X assumed */ -#define xattr_getxattr getxattr -#define xattr_fgetxattr fgetxattr -#define xattr_removexattr removexattr -#define xattr_fremovexattr fremovexattr -#define xattr_setxattr setxattr -#define xattr_fsetxattr fsetxattr -#define xattr_listxattr listxattr -#define xattr_flistxattr flistxattr -#endif - -static PyObject *xattr_error(void); -static PyObject *xattr_error_with_filename(char *name); - -static PyObject * -xattr_error(void) -{ - return PyErr_SetFromErrno(PyExc_IOError); -} - -static PyObject * -xattr_error_with_filename(char *name) -{ - return PyErr_SetFromErrnoWithFilename(PyExc_IOError, name); -} - -PyDoc_STRVAR(pydoc_getxattr, - "getxattr(path, name, size=0, position=0, options=0) -> str\n" - "\n" - "..." -); -static PyObject* -py_getxattr(PyObject* self __attribute__((__unused__)), PyObject *args) /* , PyObject *kwds) */ -{ - /* static char *keywords[] = { "path", "name", "size", "position", "options", NULL }; */ - char *path; - char *name; - PyObject *buffer; - int options = 0; - size_t size = 0; - u_int32_t position = 0; - ssize_t res; - if (!PyArg_ParseTuple(args, /* AndKeywords(args, kwds, */ - "etet|IIi:getxattr", /* keywords, */ - Py_FileSystemDefaultEncoding, &path, - Py_FileSystemDefaultEncoding, &name, - &size, - &position, - &options)) { - return NULL; - } - if (size == 0) { - Py_BEGIN_ALLOW_THREADS - res = xattr_getxattr((const char *)path, (const char *)name, NULL, 0, position, options); - Py_END_ALLOW_THREADS - if (res == -1) { - PyObject *tmp = xattr_error_with_filename(path); - PyMem_Free(path); - PyMem_Free(name); - return tmp; - } - size = res; - } - buffer = PyString_FromStringAndSize((char *)NULL, size); - if (buffer == NULL) { - PyMem_Free(path); - PyMem_Free(name); - return NULL; - } - Py_BEGIN_ALLOW_THREADS - res = xattr_getxattr((const char *)path, (const char *)name, (void *)PyString_AS_STRING(buffer), size, position, options); - Py_END_ALLOW_THREADS - if (res == -1) { - PyObject *tmp = xattr_error_with_filename(path); - Py_DECREF(buffer); - PyMem_Free(path); - PyMem_Free(name); - return tmp; - } - PyMem_Free(path); - PyMem_Free(name); - if (res != size) { - _PyString_Resize(&buffer, (int)res); - } - return buffer; -} - -PyDoc_STRVAR(pydoc_fgetxattr, - "fgetxattr(fd, name, size=0, position=0, options=0) -> str\n" - "\n" - "..." -); -static PyObject* -py_fgetxattr(PyObject* self __attribute__((__unused__)), PyObject *args) /* , PyObject *kwds) */ -{ - /* static char *keywords[] = { "fd", "name", "size", "position", "options", NULL }; */ - int fd; - char *name; - PyObject *buffer; - int options = 0; - size_t size = 0; - u_int32_t position = 0; - ssize_t res; - if (!PyArg_ParseTuple(args, /* AndKeywords(args, kwds, */ - "iet|IIi:fgetxattr", /* keywords, */ - &fd, - Py_FileSystemDefaultEncoding, &name, - &size, - &position, - &options)) { - return NULL; - } - if (size == 0) { - Py_BEGIN_ALLOW_THREADS - res = xattr_fgetxattr(fd, (const char *)name, NULL, 0, position, options); - Py_END_ALLOW_THREADS - if (res == -1) { - PyMem_Free(name); - return xattr_error(); - } - size = res; - } - buffer = PyString_FromStringAndSize((char *)NULL, size); - if (buffer == NULL) { - PyMem_Free(name); - return NULL; - } - Py_BEGIN_ALLOW_THREADS - res = xattr_fgetxattr(fd, (const char *)name, (void *)PyString_AS_STRING(buffer), size, position, options); - Py_END_ALLOW_THREADS - PyMem_Free(name); - if (res == -1) { - Py_DECREF(buffer); - return xattr_error(); - } - if (res != size) { - _PyString_Resize(&buffer, (int)res); - } - return buffer; -} - -PyDoc_STRVAR(pydoc_setxattr, - "setxattr(path, name, value, position=0, options=0) -> None\n" - "\n" - "..." -); -static PyObject* -py_setxattr(PyObject* self __attribute__((__unused__)), PyObject *args) /* , PyObject *kwds) */ -{ - /* static char *keywords[] = { "path", "name", "value", "position", "options", NULL }; */ - PyObject *result; - char *path; - char *name; - int options = 0; - char *value; - int size; - u_int32_t position = 0; - int res; - if (!PyArg_ParseTuple(args, /* AndKeywords(args, kwds, */ - "etets#|Ii:setxattr", /* keywords, */ - Py_FileSystemDefaultEncoding, &path, - Py_FileSystemDefaultEncoding, &name, - &value, &size, - &position, - &options)) { - return NULL; - } - Py_BEGIN_ALLOW_THREADS - res = xattr_setxattr((const char *)path, (const char *)name, (void *)value, size, position, options); - Py_END_ALLOW_THREADS - if (res) { - result = xattr_error_with_filename(path); - } else { - Py_INCREF(Py_None); - result = Py_None; - } - PyMem_Free(path); - PyMem_Free(name); - return result; -} - -PyDoc_STRVAR(pydoc_fsetxattr, - "fsetxattr(fd, name, value, position=0, options=0) -> None\n" - "\n" - "..." -); -static PyObject* -py_fsetxattr(PyObject* self __attribute__((__unused__)), PyObject *args) /* , PyObject *kwds) */ -{ - /* static char *keywords[] = { "fd", "name", "value", "position", "options", NULL }; */ - int fd; - char *name; - int options = 0; - char *value; - int size; - u_int32_t position = 0; - int res; - if (!PyArg_ParseTuple(args, /* AndKeywords(args, kwds, */ - "iets#|Ii:fsetxattr", /* keywords, */ - &fd, - Py_FileSystemDefaultEncoding, &name, - &value, &size, - &position, - &options)) { - return NULL; - } - Py_BEGIN_ALLOW_THREADS - res = xattr_fsetxattr(fd, (const char *)name, (void *)value, size, position, options); - Py_END_ALLOW_THREADS - PyMem_Free(name); - if (res) { - return xattr_error(); - } - Py_INCREF(Py_None); - return Py_None; -} - -PyDoc_STRVAR(pydoc_removexattr, - "removexattr(path, name, options=0) -> None\n" - "\n" - "..." -); -static PyObject* -py_removexattr(PyObject* self __attribute__((__unused__)), PyObject *args) /* , PyObject *kwds) */ -{ - /* static char *keywords[] = { "path", "name", "options", NULL }; */ - char *path; - char *name; - int options = 0; - int res; - PyObject *result; - if (!PyArg_ParseTuple(args, /* AndKeywords(args, kwds, */ - "etet|i:removexattr", /* keywords, */ - Py_FileSystemDefaultEncoding, &path, - Py_FileSystemDefaultEncoding, &name, - &options)) { - return NULL; - } - Py_BEGIN_ALLOW_THREADS - res = xattr_removexattr((const char *)path, (const char *)name, options); - Py_END_ALLOW_THREADS - if (res) { - result = xattr_error_with_filename(path); - } else { - Py_INCREF(Py_None); - result = Py_None; - } - PyMem_Free(path); - PyMem_Free(name); - return result; -} - -PyDoc_STRVAR(pydoc_fremovexattr, - "fremovexattr(fd, name, options=0) -> None\n" - "\n" - "..." -); -static PyObject* -py_fremovexattr(PyObject* self __attribute__((__unused__)), PyObject *args) /* , PyObject *kwds) */ -{ - /* static char *keywords[] = { "fd", "name", "options", NULL }; */ - int fd; - char *name; - int options = 0; - int res; - if (!PyArg_ParseTuple(args, /* AndKeywords(args, kwds, */ - "iet|i:fremovexattr", /* keywords, */ - &fd, - Py_FileSystemDefaultEncoding, &name, - &options)) { - return NULL; - } - Py_BEGIN_ALLOW_THREADS - res = xattr_fremovexattr(fd, (const char *)name, options); - Py_END_ALLOW_THREADS - PyMem_Free(name); - if (res) { - return xattr_error(); - } - Py_INCREF(Py_None); - return Py_None; -} - -PyDoc_STRVAR(pydoc_listxattr, - "listxattr(path, options=0) -> str\n" - "\n" - "..." -); -static PyObject* -py_listxattr(PyObject* self __attribute__((__unused__)), PyObject *args) /* , PyObject *kwds) */ -{ - /* static char *keywords[] = { "path", "options", NULL }; */ - PyObject *buffer; - char *path; - int options = 0; - ssize_t res; - if (!PyArg_ParseTuple(args, /* AndKeywords(args, kwds, */ - "et|i:listxattr", /* keywords, */ - Py_FileSystemDefaultEncoding, &path, - &options)) { - return NULL; - } - Py_BEGIN_ALLOW_THREADS - res = xattr_listxattr((const char *)path, NULL, 0, options); - Py_END_ALLOW_THREADS - if (res == -1) { - PyObject *tmp = xattr_error_with_filename(path); - PyMem_Free(path); - return tmp; - } - buffer = PyString_FromStringAndSize((char *)NULL, (int)res); - if (buffer == NULL) { - PyMem_Free(path); - return NULL; - } - /* avoid 2nd listxattr call if the first one returns 0 */ - if (res == 0) { - PyMem_Free(path); - return buffer; - } - Py_BEGIN_ALLOW_THREADS - res = xattr_listxattr((const char *)path, (void *)PyString_AS_STRING(buffer), (size_t)PyString_GET_SIZE(buffer), options); - Py_END_ALLOW_THREADS - if (res == -1) { - PyObject *tmp = xattr_error_with_filename(path); - Py_DECREF(buffer); - PyMem_Free(path); - return tmp; - } - PyMem_Free(path); - if (res != (ssize_t)PyString_GET_SIZE(buffer)) { - _PyString_Resize(&buffer, (int)res); - } - return buffer; -} - -PyDoc_STRVAR(pydoc_flistxattr, - "flistxattr(fd, options=0) -> str\n" - "\n" - "..." -); -static PyObject* -py_flistxattr(PyObject* self __attribute__((__unused__)), PyObject *args) /* , PyObject *kwds) */ -{ - /* static char *keywords[] = { "fd", "options", NULL }; */ - PyObject *buffer; - int fd; - int options = 0; - ssize_t res; - if (!PyArg_ParseTuple(args, /* AndKeywords(args, kwds, */ - "i|i:flistxattr", /* keywords, */ - &fd, - &options)) { - return NULL; - } - Py_BEGIN_ALLOW_THREADS - res = xattr_flistxattr(fd, NULL, 0, options); - Py_END_ALLOW_THREADS - if (res == -1) { - return xattr_error(); - } - buffer = PyString_FromStringAndSize((char *)NULL, (int)res); - if (buffer == NULL) { - return NULL; - } - Py_BEGIN_ALLOW_THREADS - res = xattr_flistxattr(fd, (void *)PyString_AS_STRING(buffer), (size_t)PyString_GET_SIZE(buffer), options); - Py_END_ALLOW_THREADS - if (res == -1) { - Py_DECREF(buffer); - return xattr_error(); - } - if (res != (ssize_t)PyString_GET_SIZE(buffer)) { - _PyString_Resize(&buffer, (int)res); - } - return buffer; -} - - -#define DEFN(n) \ - { \ - #n, \ - (PyCFunction)py_ ##n, \ - METH_VARARGS /* | METH_KEYWORDS */, \ - pydoc_ ##n \ - } -static PyMethodDef xattr_methods[] = { - DEFN(getxattr), - DEFN(fgetxattr), - DEFN(setxattr), - DEFN(fsetxattr), - DEFN(removexattr), - DEFN(fremovexattr), - DEFN(listxattr), - DEFN(flistxattr), - {} -}; -#undef DEFN - -void init_xattr(void); - -void -init_xattr(void) -{ - PyObject *m; - m = Py_InitModule4("_xattr", xattr_methods, NULL, NULL, PYTHON_API_VERSION); -} diff -Nru python-xattr-0.6.4/xattr.egg-info/dependency_links.txt python-xattr-0.7.8/xattr.egg-info/dependency_links.txt --- python-xattr-0.6.4/xattr.egg-info/dependency_links.txt 2012-02-01 19:31:17.000000000 +0000 +++ python-xattr-0.7.8/xattr.egg-info/dependency_links.txt 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ - diff -Nru python-xattr-0.6.4/xattr.egg-info/entry_points.txt python-xattr-0.7.8/xattr.egg-info/entry_points.txt --- python-xattr-0.6.4/xattr.egg-info/entry_points.txt 2012-02-01 19:31:17.000000000 +0000 +++ python-xattr-0.7.8/xattr.egg-info/entry_points.txt 1970-01-01 00:00:00.000000000 +0000 @@ -1,3 +0,0 @@ -[console_scripts] -xattr = xattr.tool:main - diff -Nru python-xattr-0.6.4/xattr.egg-info/not-zip-safe python-xattr-0.7.8/xattr.egg-info/not-zip-safe --- python-xattr-0.6.4/xattr.egg-info/not-zip-safe 2011-08-17 15:39:35.000000000 +0000 +++ python-xattr-0.7.8/xattr.egg-info/not-zip-safe 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ - diff -Nru python-xattr-0.6.4/xattr.egg-info/PKG-INFO python-xattr-0.7.8/xattr.egg-info/PKG-INFO --- python-xattr-0.6.4/xattr.egg-info/PKG-INFO 2012-02-01 19:31:17.000000000 +0000 +++ python-xattr-0.7.8/xattr.egg-info/PKG-INFO 1970-01-01 00:00:00.000000000 +0000 @@ -1,29 +0,0 @@ -Metadata-Version: 1.0 -Name: xattr -Version: 0.6.4 -Summary: Python wrapper for extended filesystem attributes -Home-page: http://github.com/xattr/xattr -Author: Bob Ippolito -Author-email: bob@redivi.com -License: MIT License -Description: - Extended attributes extend the basic attributes of files and directories - in the file system. They are stored as name:data pairs associated with - file system objects (files, directories, symlinks, etc). - - Extended attributes are currently only available on Darwin 8.0+ (Mac OS X 10.4) - and Linux 2.6+. Experimental support is included for Solaris and FreeBSD. - -Platform: MacOS X -Platform: Linux -Platform: FreeBSD -Platform: Solaris -Classifier: Environment :: Console -Classifier: Intended Audience :: Developers -Classifier: License :: OSI Approved :: MIT License -Classifier: Natural Language :: English -Classifier: Operating System :: MacOS :: MacOS X -Classifier: Operating System :: POSIX :: Linux -Classifier: Operating System :: POSIX :: BSD :: FreeBSD -Classifier: Programming Language :: Python -Classifier: Topic :: Software Development :: Libraries :: Python Modules diff -Nru python-xattr-0.6.4/xattr.egg-info/SOURCES.txt python-xattr-0.7.8/xattr.egg-info/SOURCES.txt --- python-xattr-0.6.4/xattr.egg-info/SOURCES.txt 2012-02-01 19:31:17.000000000 +0000 +++ python-xattr-0.7.8/xattr.egg-info/SOURCES.txt 1970-01-01 00:00:00.000000000 +0000 @@ -1,22 +0,0 @@ -.gitignore -CHANGES.txt -INSTALLING.txt -LICENSE.txt -README.txt -TODO.txt -ez_setup.py -setup.cfg -setup.py -_build/_make_constants.py -xattr/__init__.py -xattr/_xattr.c -xattr/constants.py -xattr/tool.py -xattr.egg-info/PKG-INFO -xattr.egg-info/SOURCES.txt -xattr.egg-info/dependency_links.txt -xattr.egg-info/entry_points.txt -xattr.egg-info/not-zip-safe -xattr.egg-info/top_level.txt -xattr/tests/__init__.py -xattr/tests/test_xattr.py \ No newline at end of file diff -Nru python-xattr-0.6.4/xattr.egg-info/top_level.txt python-xattr-0.7.8/xattr.egg-info/top_level.txt --- python-xattr-0.6.4/xattr.egg-info/top_level.txt 2012-02-01 19:31:17.000000000 +0000 +++ python-xattr-0.7.8/xattr.egg-info/top_level.txt 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -xattr