[xattr] Rework

In particular, explicitly require NT before trying ADS, and do not try to parse process output that may be localized.
totalwebcasting
Philipp Hagemeister 11 years ago
parent d70ad093af
commit 168da92b9a

@ -4,6 +4,7 @@ import sys
from .common import PostProcessor from .common import PostProcessor
from ..utils import ( from ..utils import (
check_executable,
hyphenate_date, hyphenate_date,
preferredencoding, preferredencoding,
) )
@ -30,48 +31,35 @@ class XAttrMetadataPP(PostProcessor):
try: try:
# try the pyxattr module... # try the pyxattr module...
import xattr import xattr
def write_xattr(path, key, value): def write_xattr(path, key, value):
return xattr.setxattr(path, key, value) return xattr.setxattr(path, key, value)
except ImportError: except ImportError:
if os.name == 'nt':
# Write xattrs to NTFS Alternate Data Streams:
# http://en.wikipedia.org/wiki/NTFS#Alternate_data_streams_.28ADS.29
def write_xattr(path, key, value):
assert(key.find(":") < 0)
assert(path.find(":") < 0)
assert(os.path.exists(path))
if os.name == 'posix': ads_fn = path + ":" + key
def which(bin): with open(ads_fn, "w") as f:
for dir in os.environ["PATH"].split(":"): f.write(value)
path = os.path.join(dir, bin) else:
if os.path.exists(path): user_has_setfattr = check_executable("setfattr", ['--version'])
return path user_has_xattr = check_executable("xattr", ['-h'])
user_has_setfattr = which("setfattr")
user_has_xattr = which("xattr")
if user_has_setfattr or user_has_xattr: if user_has_setfattr or user_has_xattr:
def write_xattr(path, key, value): def write_xattr(path, key, value):
import errno
potential_errors = {
# setfattr: /tmp/blah: Operation not supported
"Operation not supported": errno.EOPNOTSUPP,
# setfattr: ~/blah: No such file or directory
# xattr: No such file: ~/blah
"No such file": errno.ENOENT,
}
if user_has_setfattr: if user_has_setfattr:
cmd = ['setfattr', '-n', key, '-v', value, path] cmd = ['setfattr', '-n', key, '-v', value, path]
elif user_has_xattr: elif user_has_xattr:
cmd = ['xattr', '-w', key, value, path] cmd = ['xattr', '-w', key, value, path]
try: subprocess.check_output(cmd)
subprocess.check_output(cmd, stderr=subprocess.STDOUT)
except subprocess.CalledProcessError as e:
errorstr = e.output.strip().decode()
for potential_errorstr, potential_errno in potential_errors.items():
if errorstr.find(potential_errorstr) > -1:
e = OSError(potential_errno, potential_errorstr)
e.__cause__ = None
raise e
raise # Reraise unhandled error
else: else:
# On Unix, and can't find pyxattr, setfattr, or xattr. # On Unix, and can't find pyxattr, setfattr, or xattr.
@ -86,19 +74,9 @@ class XAttrMetadataPP(PostProcessor):
"Couldn't find a tool to set the xattrs. " "Couldn't find a tool to set the xattrs. "
"Install either the python 'xattr' module, " "Install either the python 'xattr' module, "
"or the 'xattr' binary.") "or the 'xattr' binary.")
else:
# Write xattrs to NTFS Alternate Data Streams: http://en.wikipedia.org/wiki/NTFS#Alternate_data_streams_.28ADS.29
def write_xattr(path, key, value):
assert(key.find(":") < 0)
assert(path.find(":") < 0)
assert(os.path.exists(path))
ads_fn = path + ":" + key
with open(ads_fn, "w") as f:
f.write(value)
# Write the metadata to the file's xattrs # Write the metadata to the file's xattrs
self._downloader.to_screen('[metadata] Writing metadata to file\'s xattrs...') self._downloader.to_screen('[metadata] Writing metadata to file\'s xattrs')
filename = info['filepath'] filename = info['filepath']
@ -126,7 +104,7 @@ class XAttrMetadataPP(PostProcessor):
return True, info return True, info
except OSError: except (subprocess.CalledProcessError, OSError):
self._downloader.report_error("This filesystem doesn't support extended attributes. (You may have to enable them in your /etc/fstab)") self._downloader.report_error("This filesystem doesn't support extended attributes. (You may have to enable them in your /etc/fstab)")
return False, info return False, info

Loading…
Cancel
Save