From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.io!.POSTED.blaine.gmane.org!not-for-mail From: Eli Zaretskii Newsgroups: gmane.emacs.bugs Subject: bug#66546: 30.0.50; save-buffer to write-protected file without backup fails Date: Wed, 18 Oct 2023 14:32:40 +0300 Message-ID: <83cyxcnp2f.fsf@gnu.org> References: <83h6mtq9t7.fsf@gnu.org> <8734ydx7x3.fsf@sappc2.fritz.box> <83cyxgqwjm.fsf@gnu.org> <87lec4cjqe.fsf@sappc2.fritz.box> <83ttqsp5x1.fsf@gnu.org> <87il78cdyf.fsf@sappc2.fritz.box> <83pm1gozi6.fsf@gnu.org> <87edhvd84h.fsf@sappc2.fritz.box> <838r82q0gi.fsf@gnu.org> <87wmvmfi68.fsf@sappc2.fritz.box> <83o7gxo771.fsf@gnu.org> <87ttqpgg8l.fsf@sappc2.fritz.box> Injection-Info: ciao.gmane.io; posting-host="blaine.gmane.org:116.202.254.214"; logging-data="31574"; mail-complaints-to="usenet@ciao.gmane.io" Cc: 66546@debbugs.gnu.org To: Jens Schmidt Original-X-From: bug-gnu-emacs-bounces+geb-bug-gnu-emacs=m.gmane-mx.org@gnu.org Wed Oct 18 13:33:54 2023 Return-path: Envelope-to: geb-bug-gnu-emacs@m.gmane-mx.org Original-Received: from lists.gnu.org ([209.51.188.17]) by ciao.gmane.io with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from ) id 1qt4oD-0007yf-T0 for geb-bug-gnu-emacs@m.gmane-mx.org; Wed, 18 Oct 2023 13:33:54 +0200 Original-Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1qt4nx-0003Mi-C0; Wed, 18 Oct 2023 07:33:37 -0400 Original-Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1qt4nw-0003Fq-By for bug-gnu-emacs@gnu.org; Wed, 18 Oct 2023 07:33:36 -0400 Original-Received: from debbugs.gnu.org ([2001:470:142:5::43]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1qt4nw-0006Sa-2l for bug-gnu-emacs@gnu.org; Wed, 18 Oct 2023 07:33:36 -0400 Original-Received: from Debian-debbugs by debbugs.gnu.org with local (Exim 4.84_2) (envelope-from ) id 1qt4oL-0001t0-Id for bug-gnu-emacs@gnu.org; Wed, 18 Oct 2023 07:34:01 -0400 X-Loop: help-debbugs@gnu.org Resent-From: Eli Zaretskii Original-Sender: "Debbugs-submit" Resent-CC: bug-gnu-emacs@gnu.org Resent-Date: Wed, 18 Oct 2023 11:34:01 +0000 Resent-Message-ID: Resent-Sender: help-debbugs@gnu.org X-GNU-PR-Message: followup 66546 X-GNU-PR-Package: emacs Original-Received: via spool by 66546-submit@debbugs.gnu.org id=B66546.16976288087191 (code B ref 66546); Wed, 18 Oct 2023 11:34:01 +0000 Original-Received: (at 66546) by debbugs.gnu.org; 18 Oct 2023 11:33:28 +0000 Original-Received: from localhost ([127.0.0.1]:33360 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1qt4no-0001rs-7Y for submit@debbugs.gnu.org; Wed, 18 Oct 2023 07:33:28 -0400 Original-Received: from eggs.gnu.org ([2001:470:142:3::10]:60342) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1qt4nm-0001rd-4J for 66546@debbugs.gnu.org; Wed, 18 Oct 2023 07:33:27 -0400 Original-Received: from fencepost.gnu.org ([2001:470:142:3::e]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1qt4nF-0006DH-5t; Wed, 18 Oct 2023 07:32:54 -0400 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=gnu.org; s=fencepost-gnu-org; h=References:Subject:In-Reply-To:To:From:Date: mime-version; bh=IDOoW5gAAGHu+KRljGT2Gh8ZZHleOSIXyXFCQiasEKg=; b=Hc9FYEiVjzFt K4D6EcE2I9hTrcOfk9jLrm+lRYUIzmEnb2VMtVweb6rZRTgkuGP0tMHvYijawECyZDfBPtRIZAVHa kplSjADddwrjIbrbtHju3DjoKoJnItfMVacqTMhLzshMgLJwCVtsaz60MT52G1059i3gkFzLDA/DP /h1hzMhKKKnlxhW+0pVw3dJp4ILKf6ydWLSLdfuyzrl0FFVUGKMWvfLw8JAXsegZc3gFmQmLFijyN DB3JBXquJcGv8ZU2KHzOaOcLfv2NL0vOb548zOBNVRStoBiGxT8gsUAtmIAAxzOMwB/h1aBK9RcQS ZRwIzLc5R+iI/G0Yb/Jq/A==; In-Reply-To: <87ttqpgg8l.fsf@sappc2.fritz.box> (message from Jens Schmidt on Tue, 17 Oct 2023 22:12:58 +0200) X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list X-BeenThere: bug-gnu-emacs@gnu.org List-Id: "Bug reports for GNU Emacs, the Swiss army knife of text editors" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: bug-gnu-emacs-bounces+geb-bug-gnu-emacs=m.gmane-mx.org@gnu.org Original-Sender: bug-gnu-emacs-bounces+geb-bug-gnu-emacs=m.gmane-mx.org@gnu.org Xref: news.gmane.io gmane.emacs.bugs:272647 Archived-At: > From: Jens Schmidt > Cc: 66546@debbugs.gnu.org > Date: Tue, 17 Oct 2023 22:12:58 +0200 > > Eli Zaretskii writes: > > Do we agree that this bug is all about the "no-backup" case (*C-0* C-x > C-s)? The bug is, but basic-save-buffer-2 isn't. > For me that means: I want to save to file "foo", and I explicitly do not > want Emacs to create or touch a backup file "foo~" for that. While true, I'm not sure what does this have to do with the issue we are discussing. > As a consequence, during the whole operation, there is only _one_ file > being involved, and not some second one, both as far as Emacs and the > operating system are concerned. Only if this condition in basic-save-buffer-2 is NOT true: (let* ((dir (file-name-directory buffer-file-name)) (dir-writable (file-writable-p dir))) (if (or (and file-precious-flag dir-writable) (and break-hardlink-on-save (file-exists-p buffer-file-name) (> (file-nlinks buffer-file-name) 1) (or dir-writable (error (concat "Directory %s write-protected; " "cannot break hardlink when saving") dir)))) Again, I'm not sure why is this relevant. > If I were to write a function replacing `basic-save-buffer-2' just for > that special "no-backup" case, then this way: > > (defun basic-save-buffer-2-no-backup () > (interactive) > ;; ... user confirmation elided here ... > (setq setmodes (list (file-modes buffer-file-name) > (file-extended-attributes buffer-file-name) > buffer-file-name)) > ;; No need to call `set-file-extended-attributes' here, since > ;; we only have one file, and we just got the extended > ;; attributes from that file. > (set-file-modes buffer-file-name > (logior (car setmodes) 128)) > (let (success) > (unwind-protect > (progn > (write-region nil nil > buffer-file-name nil t buffer-file-truename) > (setq success t)) > (and setmodes (not success) > (progn > ;; No sense in calling `rename-file' here as done > ;; in `basic-save-buffer-2', since we only have > ;; one file. > (set-file-extended-attributes buffer-file-name > (nth 1 setmodes)) > (setq buffer-backed-up nil))))) > setmodes) > > > >> And wouldn't that be, in this context, just a no-op? > > > > Which part of the above would be a no-op? > > Exactly that: > > (set-file-extended-attributes > buffer-file-name > (file-extended-attributes buffer-file-name)) > > We set the extended file attributes on the same file > (`buffer-file-name') where we just got them from (`buffer-file-name'). I think you have an inaccurate mental model of what set-file-extended-attributes does. In particular, you seem to think that (set-file-extended-attributes buffer-file-name (file-extended-attributes buffer-file-name)) leaves the file with the same unchanged extended attributes, as if it were a set-file-modes call. But that is not true in general, especially if the original owner of the file was not the same user as the one who runs the Emacs session that makes these calls. Depending on the OS, the actual privileges of the user running Emacs, and the file-access setup of the underlying system, the user might not be allowed to set some of the attributes, or might become the owner of the file, or the OS could add some extended attributes to the original ones. So the above is not necessarily a no-op, although in simple cases it probably is. > >> I fully understand that the extended attributes stored in `setmodes' are > >> required later to restore the attributes of the file after it has been > >> written to. And in that context I understand why we call > >> `set-file-extended-attributes'. But here not really, yet. > > > > Well, then let me turn the table and ask you: why do you think we need > > to restore the extended attributes later? what is the purpose of doing > > that? > > To restore them after we (possibly) have made the file writable. Which > we need to do a) when the call to `write-region' has failed (then in > function `basic-save-buffer-2' itself), but also b) when the call has > succeeded (then further up the stack in `basic-save-buffer'). As I tried to explain above, this is not the case. We set the extended attributes so that the access rights to the file would be as close as possible to the original ones, as much as the underlying filesystem and the user privileges allow.