From 2be5867c5fd43e13dc8e2347308ed050e19a61b3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonas=20Borgstr=C3=B6m?= Date: Sun, 28 Jul 2013 14:55:48 +0200 Subject: [PATCH] Ported to FreeBSD --- CHANGES | 2 ++ attic/crypto.py | 2 ++ attic/xattr.py | 87 ++++++++++++++++++++++++++++++++++++++++++++++++- setup.py | 1 + 4 files changed, 91 insertions(+), 1 deletion(-) diff --git a/CHANGES b/CHANGES index f7cd65a45..ea8cb9ed3 100644 --- a/CHANGES +++ b/CHANGES @@ -9,7 +9,9 @@ Version 0.7 (feature release, released on X) +- Ported to FreeBSD - Experimental: Archives mountable as fuse filesystems. +- The "user." prefix is no longer stripped from xattrs on Linux Version 0.6.1 diff --git a/attic/crypto.py b/attic/crypto.py index 1235d1556..8d7b32040 100644 --- a/attic/crypto.py +++ b/attic/crypto.py @@ -7,6 +7,8 @@ libcrypto = cdll.LoadLibrary(find_library('crypto')) # Default libcrypto on OS X is too old, try the brew version if not hasattr(libcrypto, 'PKCS5_PBKDF2_HMAC') and sys.platform == 'darwin': libcrypto = cdll.LoadLibrary('/usr/local/opt/openssl/lib/libcrypto.dylib') +if not hasattr(libcrypto, 'PKCS5_PBKDF2_HMAC') and sys.platform.startswith('freebsd'): + libcrypto = cdll.LoadLibrary('/usr/local/lib/libcrypto.so') libcrypto.PKCS5_PBKDF2_HMAC.argtypes = (c_char_p, c_int, c_char_p, c_int, c_int, c_void_p, c_int, c_char_p) libcrypto.EVP_sha256.restype = c_void_p libcrypto.AES_set_encrypt_key.argtypes = (c_char_p, c_int, c_char_p) diff --git a/attic/xattr.py b/attic/xattr.py index ef3a8a08e..cc0d5a279 100644 --- a/attic/xattr.py +++ b/attic/xattr.py @@ -1,5 +1,6 @@ """A basic extended attributes (xattr) implementation for Linux and MacOS X """ +import errno import os import sys import tempfile @@ -8,7 +9,7 @@ import tempfile def is_enabled(): """Determine if xattr is enabled on the filesystem """ - with tempfile.TemporaryFile() as fd: + with tempfile.NamedTemporaryFile() as fd: try: setxattr(fd.fileno(), 'user.name', b'value') except OSError: @@ -164,5 +165,89 @@ except ImportError: flags = XATTR_NOFOLLOW _check(func(path, name, value, len(value), 0, flags), path) + elif sys.platform.startswith('freebsd'): + EXTATTR_NAMESPACE_USER = 0x0001 + libc.extattr_list_fd.argtypes = (c_int, c_int, c_char_p, c_size_t) + libc.extattr_list_fd.restype = c_ssize_t + libc.extattr_list_link.argtypes = (c_char_p, c_int, c_char_p, c_size_t) + libc.extattr_list_link.restype = c_ssize_t + libc.extattr_list_file.argtypes = (c_char_p, c_int, c_char_p, c_size_t) + libc.extattr_list_file.restype = c_ssize_t + libc.extattr_get_fd.argtypes = (c_int, c_int, c_char_p, c_char_p, c_size_t) + libc.extattr_get_fd.restype = c_ssize_t + libc.extattr_get_link.argtypes = (c_char_p, c_int, c_char_p, c_char_p, c_size_t) + libc.extattr_get_link.restype = c_ssize_t + libc.extattr_get_file.argtypes = (c_char_p, c_int, c_char_p, c_char_p, c_size_t) + libc.extattr_get_file.restype = c_ssize_t + libc.extattr_set_fd.argtypes = (c_int, c_int, c_char_p, c_char_p, c_size_t) + libc.extattr_set_fd.restype = c_int + libc.extattr_set_link.argtypes = (c_char_p, c_int, c_char_p, c_char_p, c_size_t) + libc.extattr_set_link.restype = c_int + libc.extattr_set_file.argtypes = (c_char_p, c_int, c_char_p, c_char_p, c_size_t) + libc.extattr_set_file.restype = c_int + + def listxattr(path, *, follow_symlinks=True): + ns = EXTATTR_NAMESPACE_USER + if isinstance(path, str): + path = os.fsencode(path) + if isinstance(path, int): + func = libc.extattr_list_fd + elif follow_symlinks: + func = libc.extattr_list_file + else: + func = libc.extattr_list_link + try: + n = _check(func(path, ns, None, 0), path) + except OSError as e: + if e.errno == errno.ENOTSUP: + return [] + raise + if n == 0: + return [] + namebuf = create_string_buffer(n) + n2 = _check(func(path, ns, namebuf, n), path) + if n2 != n: + raise Exception('listxattr failed') + names = [] + mv = memoryview(namebuf.raw) + while mv: + names.append(os.fsdecode(bytes(mv[1:1+mv[0]]))) + mv = mv[1+mv[0]:] + return names + + def getxattr(path, name, *, follow_symlinks=True): + name = os.fsencode(name) + if isinstance(path, str): + path = os.fsencode(path) + if isinstance(path, int): + func = libc.extattr_get_fd + elif follow_symlinks: + func = libc.extattr_get_file + else: + func = libc.extattr_get_link + n = _check(func(path, EXTATTR_NAMESPACE_USER, name, None, 0)) + if n == 0: + return + valuebuf = create_string_buffer(n) + n2 = _check(func(path, EXTATTR_NAMESPACE_USER, name, valuebuf, n), path) + if n2 != n: + raise Exception('getxattr failed') + return valuebuf.raw + + def setxattr(path, name, value, *, follow_symlinks=True): + name = os.fsencode(name) + value = os.fsencode(value) + if isinstance(path, str): + path = os.fsencode(path) + if isinstance(path, int): + func = libc.extattr_set_fd + elif follow_symlinks: + func = libc.extattr_set_file + else: + func = libc.extattr_set_link + _check(func(path, EXTATTR_NAMESPACE_USER, name, value, len(value)), path) + else: raise Exception('Unsupported platform: %s' % sys.platform) + + diff --git a/setup.py b/setup.py index c65e6e5be..430a17f5d 100644 --- a/setup.py +++ b/setup.py @@ -62,6 +62,7 @@ setup( 'Environment :: Console', 'Intended Audience :: System Administrators', 'License :: OSI Approved :: BSD License', + 'Operating System :: POSIX :: BSD :: FreeBSD', 'Operating System :: MacOS :: MacOS X', 'Operating System :: POSIX :: Linux', 'Programming Language :: Python',