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

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

bug#66546: 30.0.50; save-buffer to write-protected file without backup f


From: Jens Schmidt
Subject: bug#66546: 30.0.50; save-buffer to write-protected file without backup fails
Date: Sat, 14 Oct 2023 22:31:36 +0200
User-agent: Gnus/5.13 (Gnus v5.13) Emacs/27.1 (gnu/linux)

Eli Zaretskii <eliz@gnu.org> writes:

>> Eli, sorry to disturb you with another edge-case bug, but the commit
>> that has introduced it was yours
>
> It wasn't.

Sorry, I misread the annotation.  Thanks for looking into this, anyway.

>> *** 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.
>
> Please explain what happens with "C-0 C-x C-s", and why.  I don't
> think I understand that, given what you wrote.

"C-0 C-x C-s" prompts me whether to write the modified buffer to the
write-protected file.  When I reply "yes", I expect Emacs to do the
following:

1. Get the mode bits/extended attributes of "foo".
2. Remove the write-potection on "foo".
3. Write the buffer to "foo", not creating a backup file.
4. Restore the mode bits/extended attributes on "foo" to their previous
   state taken in step 1.

What happens instead:

Emacs errors out that it cannot write to the file, even though it has
the permissions and means to temporarily remove the write-protection on
it.

>> 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.
>
> set-file-modes is supposed to be called only if
> set-file-extended-attributes fails, unless my reading of the code is
> incorrect.  So again, I don't follow.

Please ignore that bit, since my wording used there is indeed not quite
clear.  What I really wanted to express is explained below, hopefully
clearer now.

>> Since an extended file attribute Elisp object cannot be modified yet (is
>> that so?) to mark it, for example, as writable,
>
> What do you mean by that?

I mean that in an ideal world, my fix for this issue would have looked
like this:

------------------------- snip -------------------------
diff --git a/lisp/files.el b/lisp/files.el
index e1421b403bf..47245c43bd5 100644
--- a/lisp/files.el
+++ b/lisp/files.el
@@ -5948,8 +5948,9 @@ basic-save-buffer-2
               ;; set-file-modes.
               (unless
                   (with-demoted-errors "Error setting attributes: %s"
-                    (set-file-extended-attributes buffer-file-name
-                                                  (nth 1 setmodes)))
+                    (set-file-extended-attributes
+                      buffer-file-name
+                     (make-exattr-writable (nth 1 setmodes))))
                 (set-file-modes buffer-file-name
                                 (logior (car setmodes) 128)))))
        (let (success)
------------------------- snip -------------------------

where I invented a function `make-exattr-writable' that takes the
Elisp encapsulation of extended file attributes and modifies it such,
that when it is applied to a file again, the file is then writable.

Just as it happens with the traditional `set-file-modes' call through
the `(logior OLD-MODE 128)'.

>> I propose to just drop that call to `set-file-extended-attributes',
>> like this:
>
> Why does it make sense to ignore the extended attributes here, when we
> don't ignore them elsewhere in Emacs?

Because we do not have the equivalent to `(logior OLD-MODE 128)' for
extended attributes yet.  Or do we?





reply via email to

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