Quote:
Originally Posted by falsifier
Here's a patch for the problem Lomkiri originally reported.
|
Or maybe something like this ?
Code:
== boss.py
(line 1331)
def do_save(c, path, tdir):
- save_container(c, path)
+ save_container(c, path, save_copy=True)
shutil.rmtree(tdir, ignore_errors=True)
== save.py
(line 28)
-def save_container(container, path):
+def save_container(container, path, save_copy=False):
if container.is_dir:
(line 35)
fno = temp.fileno()
- st = None
+ st = mode = None
try:
st = os.stat(path)
except OSError as err:
if err.errno != errno.ENOENT:
raise
# path may not exist if we are saving a copy, in which case we use
# the metadata from the original book
try:
st = os.stat(container.path_to_ebook)
except OSError as err:
if err.errno != errno.ENOENT:
raise
# Somebody deleted the original file
if st is not None:
try:
- os.fchmod(fno, st.st_mode | stat.S_IWUSR)
+ if save_copy:
+ # if the edited ebook is read-only, temporarily change its right to be able to save a copy
+ os.fchmod(fno, (mode := st.st_mode) | stat.S_IWUSR)
+ else:
+ os.fchmod(fno, st.st_mode)
except OSError as err:
if err.errno != errno.EPERM:
raise
raise OSError('Failed to change permissions of {} to {} ({}), with error: {}. Most likely the {} directory has a restrictive umask'.format(
temp.name, oct(st.st_mode), format_permissions(st.st_mode), errno.errorcode[err.errno], os.path.dirname(temp.name)))
try:
os.fchown(fno, st.st_uid, st.st_gid)
except OSError as err:
if err.errno not in (errno.EPERM, errno.EACCES):
# ignore chown failure as user could be editing file belonging
# to a different user, in which case we really can't do anything
# about it short of making the file update non-atomic
raise
- temp.close()
- temp = temp.name
try:
+ if save_copy and mode:
+ os.fchmod(fno, mode)
container.commit(temp)
atomic_rename(temp, path)
finally:
+ temp.close()
+ temp = temp.name
if os.path.exists(temp):
os.remove(temp)