diff options
| author | Yen Chi Hsuan <yan12125@gmail.com> | 2015-05-14 14:26:47 +0800 | 
|---|---|---|
| committer | Yen Chi Hsuan <yan12125@gmail.com> | 2015-05-14 14:28:41 +0800 | 
| commit | 86c7fdb17c0dcbff88a8daa131fddc57b6304b83 (patch) | |
| tree | 30b55bfc6383cc0273d45637ed71b87b092eb1e1 | |
| parent | 62bd6589c7f087ab81865993a87bdba6eb651293 (diff) | |
[xattr] Enhance error handling to catch ENOSPC
Fixes #5589
| -rw-r--r-- | youtube_dl/postprocessor/xattrpp.py | 61 | 
1 files changed, 50 insertions, 11 deletions
| diff --git a/youtube_dl/postprocessor/xattrpp.py b/youtube_dl/postprocessor/xattrpp.py index 93d0abcf6..16f2966e9 100644 --- a/youtube_dl/postprocessor/xattrpp.py +++ b/youtube_dl/postprocessor/xattrpp.py @@ -3,18 +3,32 @@ from __future__ import unicode_literals  import os  import subprocess  import sys +import errno  from .common import PostProcessor -from ..compat import ( -    subprocess_check_output -)  from ..utils import (      check_executable,      hyphenate_date,      version_tuple, +    PostProcessingError, +    encodeArgument, +    encodeFilename,  ) +class XAttrMetadataError(PostProcessingError): +    def __init__(self, code=None, msg='Unknown error'): +        super(XAttrMetadataError, self).__init__(msg) +        self.code = code + +        # Parsing code and msg +        if (self.code in (errno.ENOSPC, errno.EDQUOT) or +                'No space left' in self.msg or 'Disk quota excedded' in self.msg): +            self.reason = 'NO_SPACE' +        else: +            self.reason = 'NOT_SUPPORTED' + +  class XAttrMetadataPP(PostProcessor):      # @@ -51,7 +65,10 @@ class XAttrMetadataPP(PostProcessor):                  raise ImportError              def write_xattr(path, key, value): -                return xattr.setxattr(path, key, value) +                try: +                    xattr.set(path, key, value) +                except EnvironmentError as e: +                    raise XAttrMetadataError(e.errno, e.strerror)          except ImportError:              if os.name == 'nt': @@ -62,8 +79,11 @@ class XAttrMetadataPP(PostProcessor):                      assert os.path.exists(path)                      ads_fn = path + ":" + key -                    with open(ads_fn, "wb") as f: -                        f.write(value) +                    try: +                        with open(ads_fn, "wb") as f: +                            f.write(value) +                    except EnvironmentError as e: +                        raise XAttrMetadataError(e.errno, e.strerror)              else:                  user_has_setfattr = check_executable("setfattr", ['--version'])                  user_has_xattr = check_executable("xattr", ['-h']) @@ -71,12 +91,24 @@ class XAttrMetadataPP(PostProcessor):                  if user_has_setfattr or user_has_xattr:                      def write_xattr(path, key, value): +                        value = value.decode('utf-8')                          if user_has_setfattr: -                            cmd = ['setfattr', '-n', key, '-v', value, path] +                            executable = 'setfattr' +                            opts = ['-n', key, '-v', value]                          elif user_has_xattr: -                            cmd = ['xattr', '-w', key, value, path] +                            executable = 'xattr' +                            opts = ['-w', key, value] -                        subprocess_check_output(cmd) +                        cmd = ([encodeFilename(executable, True)] + +                               [encodeArgument(o) for o in opts] + +                               [encodeFilename(path, True)]) + +                        p = subprocess.Popen( +                            cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, stdin=subprocess.PIPE) +                        stdout, stderr = p.communicate() +                        stderr = stderr.decode('utf-8', 'replace') +                        if p.returncode != 0: +                            raise XAttrMetadataError(p.returncode, stderr)                  else:                      # On Unix, and can't find pyxattr, setfattr, or xattr. @@ -121,6 +153,13 @@ class XAttrMetadataPP(PostProcessor):              return [], info -        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)") +        except XAttrMetadataError as e: +            if e.reason == 'NO_SPACE': +                self._downloader.report_warning( +                    'There\'s no disk space left or disk quota exceeded. ' + +                    'Extended attributes are not written.') +            else: +                self._downloader.report_error( +                    'This filesystem doesn\'t support extended attributes. ' + +                    '(You may have to enable them in your /etc/fstab)')              return [], info | 
