[xattr] Rework
In particular, explicitly require NT before trying ADS, and do not try to parse process output that may be localized.
This commit is contained in:
		
							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…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user