From 2a6158e05e38e8dd1d98d2562bfedce6a199f9e4 Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Wed, 4 Oct 2023 13:46:15 +0530 Subject: [PATCH] Save to disk: Do not limit the total path length to 240 characters on non-Windows platforms. Fixes #2038238 [file and folder names garbled if too long in "save to disk".](https://bugs.launchpad.net/calibre/+bug/2038238) --- src/calibre/db/backend.py | 4 ++-- src/calibre/library/save_to_disk.py | 11 ++++++----- src/calibre/utils/filenames.py | 1 + 3 files changed, 9 insertions(+), 7 deletions(-) diff --git a/src/calibre/db/backend.py b/src/calibre/db/backend.py index 34bdd469e8..35d08d7062 100644 --- a/src/calibre/db/backend.py +++ b/src/calibre/db/backend.py @@ -1707,7 +1707,7 @@ class DB: # Ensure that the file has the same case as dest try: os.rename(path, dest) - except: + except OSError: pass # Nothing too catastrophic happened, the cases mismatch, that's all else: if use_hardlink: @@ -1716,7 +1716,7 @@ class DB: return True except: pass - with open(path, 'rb') as f, open(dest, 'wb') as d: + with open(path, 'rb') as f, open(make_long_path_useable(dest), 'wb') as d: shutil.copyfileobj(f, d) return True diff --git a/src/calibre/library/save_to_disk.py b/src/calibre/library/save_to_disk.py index 8c6c67cf14..e844d23b74 100644 --- a/src/calibre/library/save_to_disk.py +++ b/src/calibre/library/save_to_disk.py @@ -10,7 +10,7 @@ import re import traceback from calibre import prints, sanitize_file_name, strftime -from calibre.constants import DEBUG, preferred_encoding +from calibre.constants import DEBUG, iswindows, preferred_encoding from calibre.db.errors import NoSuchFormat from calibre.db.lazy import FormatsList from calibre.ebooks.metadata import fmt_sidx, title_sort @@ -342,13 +342,13 @@ def do_save_book_to_disk(db, book_id, mi, plugboards, cdata = db.cover(book_id) if cdata: cpath = base_path + '.jpg' - with open(cpath, 'wb') as f: + with open(make_long_path_useable(cpath), 'wb') as f: f.write(cdata) mi.cover = base_name+'.jpg' if opts.write_opf: from calibre.ebooks.metadata.opf2 import metadata_to_opf opf = metadata_to_opf(mi) - with open(base_path+'.opf', 'wb') as f: + with open(make_long_path_useable(base_path+'.opf'), 'wb') as f: f.write(opf) finally: mi.cover, mi.pubdate, mi.timestamp = originals @@ -372,7 +372,7 @@ def do_save_book_to_disk(db, book_id, mi, plugboards, except NoSuchFormat: continue if opts.update_metadata: - with open(fmt_path, 'r+b') as stream: + with open(make_long_path_useable(fmt_path), 'r+b') as stream: update_metadata(mi, fmt, stream, plugboards, cdata) return not formats_written, book_id, mi.title @@ -384,7 +384,8 @@ def sanitize_args(root, opts): root = os.path.abspath(root) opts.template = preprocess_template(opts.template) - length = 240 + length = 255 if iswindows else 1024 + length -= 15 length -= len(root) if length < 5: raise ValueError('%r is too long.'%root) diff --git a/src/calibre/utils/filenames.py b/src/calibre/utils/filenames.py index e0f8c24ca2..f12855af24 100644 --- a/src/calibre/utils/filenames.py +++ b/src/calibre/utils/filenames.py @@ -442,6 +442,7 @@ class WindowsAtomicFolderMove: def hardlink_file(src, dest): + src, dest = make_long_path_useable(src), make_long_path_useable(dest) if iswindows: windows_hardlink(src, dest) return