View Single Post
Old 12-24-2022, 02:43 PM   #18
lomkiri
Groupie
lomkiri ought to be getting tired of karma fortunes by now.lomkiri ought to be getting tired of karma fortunes by now.lomkiri ought to be getting tired of karma fortunes by now.lomkiri ought to be getting tired of karma fortunes by now.lomkiri ought to be getting tired of karma fortunes by now.lomkiri ought to be getting tired of karma fortunes by now.lomkiri ought to be getting tired of karma fortunes by now.lomkiri ought to be getting tired of karma fortunes by now.lomkiri ought to be getting tired of karma fortunes by now.lomkiri ought to be getting tired of karma fortunes by now.lomkiri ought to be getting tired of karma fortunes by now.
 
lomkiri's Avatar
 
Posts: 172
Karma: 1497966
Join Date: Jul 2021
Device: N/A
Quote:
Originally Posted by falsifier View Post
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)

Last edited by lomkiri; 12-24-2022 at 04:10 PM. Reason: Correction: I forgot to relat the change in def save_container
lomkiri is offline   Reply With Quote