emacs-bug-tracker
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

bug#66546: closed (30.0.50; save-buffer to write-protected file without


From: GNU bug Tracking System
Subject: bug#66546: closed (30.0.50; save-buffer to write-protected file without backup fails)
Date: Sat, 04 Nov 2023 13:01:01 +0000

Your message dated Sat, 04 Nov 2023 14:59:14 +0200
with message-id <83sf5l4qu5.fsf@gnu.org>
and subject line Re: bug#66546: 30.0.50; save-buffer to write-protected file 
without backup fails
has caused the debbugs.gnu.org bug report #66546,
regarding 30.0.50; save-buffer to write-protected file without backup fails
to be marked as done.

(If you believe you have received this mail in error, please contact
help-debbugs@gnu.org.)


-- 
66546: https://debbugs.gnu.org/cgi/bugreport.cgi?bug=66546
GNU Bug Tracking System
Contact help-debbugs@gnu.org with problems
--- Begin Message --- Subject: 30.0.50; save-buffer to write-protected file without backup fails Date: Sat, 14 Oct 2023 21:09:53 +0200 User-agent: Mozilla Thunderbird
X-Debbugs-Cc: Eli Zaretskii <eliz@gnu.org>
Severity: minor

Eli, sorry to disturb you with another edge-case bug, but the commit
that has introduced it was yours, I think ...

*** Issue A

In a shell execute:

echo foo > foo
chmod 0400 foo
./src/emacs -Q foo
C-x C-q
bar
C-0 C-x C-s
=> File foo is write-protected; try to save anyway?
yes RET
=> basic-save-buffer-2: Opening output file: Permission denied,
   /home/jschmidt/work/emacs-master/foo

When saving *with* backup, that is, without prefix C-0, everything works
as expected: The file temporarily gets write permissions, gets written
to, and write permissions get removed again.

The root cause is related to Eli's introduction of calls to
`set-file-extended-attributes' in ccad023bc3c7.  Here:

------------------------- files.el -------------------------
        ;; If file not writable, see if we can make it writable
        ;; temporarily while we write it.
        ;; But no need to do so if we have just backed it up
        ;; (setmodes is set) because that says we're superseding.
        (cond ((and tempsetmodes (not setmodes))
               ;; Change the mode back, after writing.
               (setq setmodes
                     (list (file-modes buffer-file-name)
                           (with-demoted-errors
                               "Error getting extended attributes: %s"
                             (file-extended-attributes buffer-file-name))
                           buffer-file-name))
               ;; If set-file-extended-attributes fails, fall back on
               ;; set-file-modes.
               (unless
                   (with-demoted-errors "Error setting attributes: %s"
                     (set-file-extended-attributes buffer-file-name
                                                   (nth 1 setmodes)))
                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ [1]
                 (set-file-modes buffer-file-name
                                 (logior (car setmodes) 128)))))
                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ [2]
------------------------- files.el -------------------------

The marked call [1] is a no-op, since it does not change the permissions
in any way when writing them back, while the call [2] to
`set-file-modes' actually changes the file mode.

Since an extended file attribute Elisp object cannot be modified yet (is
that so?) to mark it, for example, as writable, I propose to just drop
that call to `set-file-extended-attributes', like this:

------------------------- snip -------------------------
diff --git a/lisp/files.el b/lisp/files.el
index e1421b403bf..d4d556fa470 100644
--- a/lisp/files.el
+++ b/lisp/files.el
@@ -5944,14 +5944,8 @@ basic-save-buffer-2
                                "Error getting extended attributes: %s"
                             (file-extended-attributes buffer-file-name))
                           buffer-file-name))
-              ;; If set-file-extended-attributes fails, fall back on
-              ;; set-file-modes.
-              (unless
-                  (with-demoted-errors "Error setting attributes: %s"
-                    (set-file-extended-attributes buffer-file-name
-                                                  (nth 1 setmodes)))
-                (set-file-modes buffer-file-name
-                                (logior (car setmodes) 128)))))
+              (set-file-modes buffer-file-name
+                              (logior (car setmodes) 128))))
        (let (success)
          (unwind-protect
              (progn
------------------------- snip -------------------------

*** Issue B

But then there is another issue (?), probably even longer unnoticed.  To
notice it, apply above patch, make, then execute the following test
case:

rm -f foo
echo foo > foo
chmod 0400 foo
./src/emacs -Q

Define the following advice on `write-region' to simulate a write error:

------------------------- snip -------------------------
(advice-add 'write-region :override
            (lambda (&rest _) (error "No space left on device")))
------------------------- snip -------------------------

Then continue

C-x C-f foo RET
C-x C-q
bar
C-0 C-x C-s
=> File foo is write-protected; try to save anyway?
yes RET
=> No space left on device

Now check the permissions of file foo:

  [emacs-master]$ ls -al foo
  -rw------- 1 jschmidt jschmidt 7 Oct 14 20:33 foo

So the write permissions did not get removed again.

Here the root cause is that the `unwind-protect' around the
`write-region' in `basic-save-buffer-2' does not handle the no-backup
case separately.  I would extend the clean-up form of the
`unwind-protect' to distinguish these both cases and handle the
no-backup case appropriately, here by trying first to set back the
extended attributes, then the regular ones.

*** What to do and where?

I can provide patches for both issues.  Plus ERT tests.

I guess that would be in one changeset, since these are related.

Should I provide a separate patch fixing only issue A for emacs-29?  Or
is that issue not relevant for emacs-29, given that it went unnoticed
for 12 years?



--- End Message ---
--- Begin Message --- Subject: Re: bug#66546: 30.0.50; save-buffer to write-protected file without backup fails Date: Sat, 04 Nov 2023 14:59:14 +0200
> From: Jens Schmidt <jschmidt4gnu@vodafonemail.de>
> Cc: 66546@debbugs.gnu.org
> Date: Sat, 04 Nov 2023 13:30:37 +0100
> 
> Eli Zaretskii <eliz@gnu.org> writes:
> 
> > I think one nit is still missing:
> 
> Right you are.  Fixed in next version.

Thanks, installed on the master branch.

Can we close the bug now?


--- End Message ---

reply via email to

[Prev in Thread] Current Thread [Next in Thread]