From 5e88cee83489b06039848e5f91c63e4729d478bf Mon Sep 17 00:00:00 2001 From: JoeLametta Date: Thu, 18 Oct 2018 10:00:00 +0000 Subject: [PATCH 1/4] Limit length of filenames If whipper generated filenames are longer thant the maximum value supported by the filesystem, the I/O operations are going to fail. With this commit filenames which may be too long are truncated to the maximum allowable length. Fixes #197. --- whipper/common/common.py | 10 ++++++++++ whipper/common/program.py | 6 +++--- whipper/program/cdparanoia.py | 4 ++-- 3 files changed, 15 insertions(+), 5 deletions(-) diff --git a/whipper/common/common.py b/whipper/common/common.py index c8aefd4e..5a38407e 100644 --- a/whipper/common/common.py +++ b/whipper/common/common.py @@ -152,6 +152,16 @@ class MissingFrames(Exception): """ pass +def truncate_filename(path): + """ + Truncate filename to the max. len. allowed by the path's filesystem + Should handle unicode correctly too + """ + p, f = os.path.split(os.path.normpath(path)) + f, e = os.path.splitext(f) + fn_lim = os.pathconf(p, 'PC_NAME_MAX') + length = fn_lim - len(e) + return os.path.join(p, f[:length] + e) def shrinkPath(path): """ diff --git a/whipper/common/program.py b/whipper/common/program.py index 5a1daaac..78790b40 100644 --- a/whipper/common/program.py +++ b/whipper/common/program.py @@ -574,7 +574,7 @@ def verifyImage(self, runner, table): return accurip.verify_result(self.result, responses, checksums) def write_m3u(self, discname): - m3uPath = u'%s.m3u' % discname + m3uPath = common.truncate_filename(discname + '.m3u') with open(m3uPath, 'w') as f: f.write(u'#EXTM3U\n'.encode('utf-8')) for track in self.result.tracks: @@ -596,7 +596,7 @@ def write_m3u(self, discname): def writeCue(self, discName): assert self.result.table.canCue() - cuePath = '%s.cue' % discName + cuePath = common.truncate_filename(discName + '.cue') logger.debug('write .cue file to %s', cuePath) handle = open(cuePath, 'w') # FIXME: do we always want utf-8 ? @@ -608,7 +608,7 @@ def writeCue(self, discName): return cuePath def writeLog(self, discName, logger): - logPath = '%s.log' % discName + logPath = common.truncate_filename(discName + '.log') handle = open(logPath, 'w') log = logger.log(self.result) handle.write(log.encode('utf-8')) diff --git a/whipper/program/cdparanoia.py b/whipper/program/cdparanoia.py index 3163dc7d..07f2e699 100644 --- a/whipper/program/cdparanoia.py +++ b/whipper/program/cdparanoia.py @@ -481,8 +481,8 @@ def __init__(self, path, table, start, stop, overread, offset=0, except IOError as e: if errno.ENAMETOOLONG != e.errno: raise - path = common.shrinkPath(path) - tmpoutpath = path + u'.part' + path = common.truncate_filename(common.shrinkPath(path)) + tmpoutpath = common.truncate_filename(path + u'.part') open(tmpoutpath, 'wb').close() self._tmppath = tmpoutpath self.path = path From fd9296fc73730549179a76adee52a8cb0d7b44af Mon Sep 17 00:00:00 2001 From: JoeLametta Date: Thu, 18 Oct 2018 10:05:00 +0000 Subject: [PATCH 2/4] PEP-8 Fix --- whipper/common/common.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/whipper/common/common.py b/whipper/common/common.py index 5a38407e..2686dead 100644 --- a/whipper/common/common.py +++ b/whipper/common/common.py @@ -152,6 +152,7 @@ class MissingFrames(Exception): """ pass + def truncate_filename(path): """ Truncate filename to the max. len. allowed by the path's filesystem @@ -163,6 +164,7 @@ def truncate_filename(path): length = fn_lim - len(e) return os.path.join(p, f[:length] + e) + def shrinkPath(path): """ Shrink a full path to a shorter version. From ce212cba93dc4401d870cd5e30e19ed36612c379 Mon Sep 17 00:00:00 2001 From: JoeLametta Date: Mon, 22 Oct 2018 08:00:00 +0000 Subject: [PATCH 3/4] Fix Unicode strings processing --- whipper/common/common.py | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/whipper/common/common.py b/whipper/common/common.py index 2686dead..853204b3 100644 --- a/whipper/common/common.py +++ b/whipper/common/common.py @@ -23,6 +23,7 @@ import os.path import math import subprocess +import unicodedata from whipper.extern import asyncsub @@ -156,13 +157,15 @@ class MissingFrames(Exception): def truncate_filename(path): """ Truncate filename to the max. len. allowed by the path's filesystem - Should handle unicode correctly too + Hopefully it handles Unicode strings correctly """ p, f = os.path.split(os.path.normpath(path)) f, e = os.path.splitext(f) - fn_lim = os.pathconf(p, 'PC_NAME_MAX') - length = fn_lim - len(e) - return os.path.join(p, f[:length] + e) + fn_lim = os.pathconf(p, 'PC_NAME_MAX') # max filenmae length in bytes + max = fn_lim - len(e.encode('utf-8')) + f = unicodedata.normalize('NFC', f) + f_trunc = unicode(f.encode('utf-8')[:max], 'utf-8', errors='ignore') + return os.path.join(p, f_trunc + e) def shrinkPath(path): From bac4bba80d9ce7d45c68a5a17d5552810308be89 Mon Sep 17 00:00:00 2001 From: JoeLametta Date: Mon, 22 Oct 2018 08:05:00 +0000 Subject: [PATCH 4/4] Empty test commit