diff --git a/CHANGES.md b/CHANGES.md index 485d3daf..e92a1e23 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -78,6 +78,7 @@ * Change make indexer lookup optional in NameParser, and deactivate during searches * Change improve newnab autoselect categories * Change add nzb.org BoxSD and BoxHD categories +* Change post processor, ignore symlinks found in process_dir [develop changelog] diff --git a/sickbeard/helpers.py b/sickbeard/helpers.py index 219e0b6c..699a2eeb 100644 --- a/sickbeard/helpers.py +++ b/sickbeard/helpers.py @@ -34,6 +34,7 @@ import traceback import urlparse import uuid import subprocess +import sys import adba import requests @@ -1558,4 +1559,25 @@ def should_delete_episode(status): if s not in (SNATCHED, SNATCHED_PROPER, SNATCHED_BEST, DOWNLOADED, ARCHIVED, IGNORED): return True logger.log('not safe to delete episode from db because of status: %s' % statusStrings[s], logger.DEBUG) - return False \ No newline at end of file + return False + + +def is_link(filepath): + """ + Check if given file/pathname is symbolic link + + :param filepath: file or path to check + :return: True or False + """ + if 'win32' == sys.platform: + if not ek.ek(os.path.exists, filepath): + return False + + import ctypes + invalid_file_attributes = 0xFFFFFFFF + file_attribute_reparse_point = 0x0400 + + attr = ctypes.windll.kernel32.GetFileAttributesW(unicode(filepath)) + return invalid_file_attributes != attr and 0 != attr & file_attribute_reparse_point + + return ek.ek(os.path.islink, filepath) diff --git a/sickbeard/processTV.py b/sickbeard/processTV.py index f4e498cf..bde3adc2 100644 --- a/sickbeard/processTV.py +++ b/sickbeard/processTV.py @@ -276,7 +276,9 @@ class ProcessTVShow(object): if self.fail_detected: self._process_failed(dir_name, nzb_name, showObj=showObj) return self.result + rar_content = [x for x in rar_content if not helpers.is_link(ek.ek(os.path.join, path, x))] path, dirs, files = self._get_path_dir_files(dir_name, nzb_name, pp_type) + files = [x for x in files if not helpers.is_link(ek.ek(os.path.join, path, x))] video_files = filter(helpers.has_media_ext, files) video_in_rar = filter(helpers.has_media_ext, rar_content) work_files += [ek.ek(os.path.join, path, item) for item in rar_content] @@ -343,6 +345,9 @@ class ProcessTVShow(object): self._log_helper(u'Found temporary sync files, skipping post process', logger.ERROR) return self.result + # Ignore any symlinks at this stage to avoid the potential for unraring a symlinked archive + files = [x for x in files if not helpers.is_link(ek.ek(os.path.join, walk_path, x))] + rar_files, rarfile_history = self.unused_archives( walk_path, filter(helpers.is_first_rar_volume, files), pp_type, process_method, rarfile_history) rar_content = self._unrar(walk_path, rar_files, force) @@ -350,6 +355,7 @@ class ProcessTVShow(object): if self.fail_detected: self._process_failed(dir_name, nzb_name, showObj=self.showObj_helper(showObj, directory)) continue + rar_content = [x for x in rar_content if not helpers.is_link(ek.ek(os.path.join, walk_path, x))] files = list(set(files + rar_content)) video_files = filter(helpers.has_media_ext, files) video_in_rar = filter(helpers.has_media_ext, rar_content) @@ -886,6 +892,7 @@ class ProcessTVShow(object): # Scheduled Post Processing Active # Get at first all the subdir in the dir_name for path, dirs, files in ek.ek(os.walk, dir_name): + files = [x for x in files if not helpers.is_link(ek.ek(os.path.join, path, x))] break else: path, dirs = ek.ek(os.path.split, dir_name) # Script Post Processing