Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

How to change and save a read-only file?

424 views
Skip to first unread message

Marius Hofert

unread,
Jun 29, 2013, 5:14:00 AM6/29/13
to Emacs help
Hi,

I often would like to edit files in emacs, which are write-protected
(owned by root, for example). With "C-x C-q" I can disable 'read-only
mode', which allows me to make changes in the file. But when I want to
save the file, I obtain "File ... is write-protected; try to save
anyway? (y or n)". Even if I choose 'y', it fails (*Messages* saying:
"basic-save-buffer-2: Doing chmod: operation not permitted").

What's the 'correct' approach to easily edit (change + save) such files?

Cheers,

Marius

Peter Dyballa

unread,
Jun 29, 2013, 5:20:46 AM6/29/13
to Marius Hofert, Emacs help

Am 29.06.2013 um 11:14 schrieb Marius Hofert:

> What's the 'correct' approach to easily edit (change + save) such files?

Save them in your home directory and then ask the super-user to move them to the appropriate place. (Or do your home work with elevated privileges! TRAMP for example.)

--
Mit friedvollen Grüßen

Pete

’Twas a woman who drove me to drink, and I never had the courtesy to thank her for it.
— W.C. Fields


Jude DaShiell

unread,
Jun 29, 2013, 7:16:06 AM6/29/13
to Thorsten Jolitz, help-gn...@gnu.org
On Sat, 29 Jun 2013, Thorsten Jolitz wrote:

> Marius Hofert <marius...@math.ethz.ch> writes:
>
> Hi,
>
> > What's the 'correct' approach to easily edit (change + save) such files?
>
> not sure whats the 'correct' approach, but there is tramp which allows
> you to do something like:
>
> 1. find-file as root
>
> ,---------------
> | C-x C-f /sudo:
> `---------------
>
> and then asks for a password
>
> ,-----------------------------------
> | Password for /sudo:root@localhost:
> `-----------------------------------
>
> to let you subsequently edit the file as root
>
> 2. or reopen dired buffer with sudo and thus open end edit files from
> that buffer as root
>
> ,-------------------------------------------------------------------------------
> | C-c C-s runs the command dired-toggle-sudo, which is an interactive autoloaded
> | compiled Lisp function in `dired-toggle-sudo.el'.
> |
> | It is bound to C-c C-s.
> |
> | (dired-toggle-sudo &optional SUDO-USER)
> |
> | Reopen current file or dired buffer with sudo.
> |
> | If SUDO-USER is nil assume root.
> |
> | If called with `universal-argument' (C-u), ask for username.
> `-------------------------------------------------------------------------------
>
> But I finally ended up to write a separate minimal init.el file and a
> small batch script that allow me to quickly open a root instance of
> emacs when I need it that warns me about being root while editing that I
> exit when I'm done with editing:
>
> ,---------------------------------------------
> | -rwxr-xr-x 1 me users 125 26. Apr 09:44 esu
> `---------------------------------------------
>
> with content:
>
> ,------------------------------------------------------
> | #!/bin/sh
> | # start emacs as root
> |
> | exec sudo emacs -Q -bg black -fg wheat --no-splash -l
> | /home/me/.emacs.d/emacs-ESU-script.el
> `------------------------------------------------------
>
> emacs-ESU-script.el:
>
> (it starts up pretty fast, but makes editing convenient, and has a nice
> red warning at the top of the buffer about editing as root)
>
With sudo, you enter your login password. You have to be mentioned in
/etc/sudoers though to do this and have it work. Of course if you have
root privileges, other things are possible.

>

---------------------------------------------------------------------------
jude <jdas...@shellworld.net> About to block another web browser version?
Ask yourself what Tim Berners-lee would do.


Emanuel Berg

unread,
Jun 29, 2013, 9:10:50 AM6/29/13
to
Marius Hofert <marius...@math.ethz.ch> writes:

> I often would like to edit files in emacs, which are
> write-protected (owned by root, for example). With "C-x C-q" I
> can disable 'read-only mode', which allows me to make changes in
> the file. But when I want to save the file, I obtain "File
> ... is write-protected; try to save anyway? (y or n)". Even if I
> choose 'y', it fails (*Messages* saying: "basic-save-buffer-2:
> Doing chmod: operation not permitted").

I want to do this on a file-to-file basis - and I don't want to
restart Emacs to do it.

When I open an out-of-line file - say /etc/rc.local - I want it to
be in read-only mode, as I don't want any sleepy fingers to jitter
it with unintended chars. However, sometimes I *do* want to tell
explicitly that I want to edit it, and then it need to be put
forward with superuser access. For this, a use `su-edit'.

It works like this:
1. Get the point position.
2. Kill the read-only buffer.
3. Open it as super user.
4. Move point and the window to make it look just the way it
looked.

(Point 4 - that is all that complicated stuff in the code. And,
sometimes, it doesn't work! If you feel like helping me with that,
please do. I'd like the window to be exactly the same
(seemingly). Only, it works for 1-3, so I never did that detail.)

Anyway:

(defun su-edit ()
"Edit the current buffer file as superuser -
in a new buffer, that should look the same."
(interactive)
(let ((start-point-pos (point)))
(recenter-top-bottom 0)
(let ((top-window-pos (point))
(buffer (buffer-file-name)) )
(kill-buffer)
(find-file (format "/sudo::%s" buffer))
(goto-char top-window-pos)
(recenter-top-bottom 0)
(goto-char start-point-pos) )))

But, there is a much *better* way, as the files you have to edit
as superuser are many, but not *that* many:

(global-set-key (kbd "C-j") 'jump-to-register)

(set-register ?a (cons 'file "/sudo::/etc/apt/sources.list"))
(set-register ?c (cons 'file "~/.irssi/config"))
(set-register ?C (cons 'file "/sudo::/etc/default/console-setup"))
(set-register ?e (cons 'file "~/.emacs"))
;; etc.

Note: 1) How to use it for superuser, *and* ordinary files, 2)
that it is case sensitive ('c' and 'C'), and 3) the mnemonic use
of letters (I use zsh, otherwise there would have been a 'b' for
.bashrc - you get it).

Before I started with this system, I lost a lot of time typing
file paths, iterating the buffer list, etc. Now I just (for
example) [C-j e] to bring up .emacs - and if there is such a
buffer already, I get to the correct place (where I had point on
my last visit).

Only for some rare cases do I bump into a file I have to edit,
which I haven't added to the list - that's when I use the
(imperfect) `su-edit', all the while contemplating if I should add
that file to a register...

--
Emanuel Berg - programmer (hire me! CV below)
computer projects: http://user.it.uu.se/~embe8573
internet activity: http://home.student.uu.se/embe8573

Emanuel Berg

unread,
Jun 29, 2013, 9:30:08 AM6/29/13
to
Emanuel Berg <embe...@student.uu.se> writes:

> (defun su-edit ()
> "Edit the current buffer file as superuser -
> in a new buffer, that should look the same."
> (interactive)
> (let ((start-point-pos (point)))
> (recenter-top-bottom 0)
> (let ((top-window-pos (point))
> (buffer (buffer-file-name)) )
> (kill-buffer)
> (find-file (format "/sudo::%s" buffer))
> (goto-char top-window-pos)
> (recenter-top-bottom 0)
> (goto-char start-point-pos) )))

Aha, now I see, `recenter-top-bottom' doesn't change the point!
Silly. Still, even though with this realization I could fix it, I
leave it open to you foxes as you more than once have provided me
with standard solutions (for which I am grateful, because they
work better - and not without pride I add that last word :) )

Richard Copley

unread,
Jul 1, 2013, 6:35:45 PM7/1/13
to Emanuel Berg, help-gn...@gnu.org
On 29 June 2013 14:30, Emanuel Berg <embe...@student.uu.se> wrote:
> Emanuel Berg <embe...@student.uu.se> writes:
>
>> (defun su-edit ()
>> "Edit the current buffer file as superuser -
>> in a new buffer, that should look the same."
>> (interactive)
>> (let ((start-point-pos (point)))
>> (recenter-top-bottom 0)
>> (let ((top-window-pos (point))
>> (buffer (buffer-file-name)) )
>> (kill-buffer)
>> (find-file (format "/sudo::%s" buffer))
>> (goto-char top-window-pos)
>> (recenter-top-bottom 0)
>> (goto-char start-point-pos) )))
>
> Aha, now I see, `recenter-top-bottom' doesn't change the point!
> Silly. Still, even though with this realization I could fix it, I
> leave it open to you foxes as you more than once have provided me
> with standard solutions (for which I am grateful, because they
> work better - and not without pride I add that last word :) )

Not sure about "standard solution" (or "fox") but I would do it like this:

(let ((window-start (window-start))
(point (point)))
(find-alternate-file (format "%s~" (buffer-file-name)))
(goto-char point)
(set-window-start nil window-start)))

Emanuel Berg

unread,
Jul 1, 2013, 7:42:48 PM7/1/13
to
Richard Copley <rco...@gmail.com> writes:

> Not sure about "standard solution" (or "fox") but I would do it
> like this:
>
> (let ((window-start (window-start))
> (point (point)))
> (find-alternate-file (format "%s~" (buffer-file-name)))
> (goto-char point)
> (set-window-start nil window-start)))

That looks pretty standard to me. But more important, it works
great!

I take it the temporary file~ is what you used for testing?

Anyway, it boiled down to this - awesome stuff:

(defun su-edit ()
"Edit the current buffer file as superuser."
(interactive)
(let ((window-start (window-start))
(point (point)) )
(find-alternate-file (format "/sudo::%s" (buffer-file-name)))
(goto-char point)
(set-window-start nil window-start) )) ; nil - selected window

Emanuel Berg

unread,
Jul 19, 2013, 8:36:04 AM7/19/13
to
Emanuel Berg <embe...@student.uu.se> writes:

> That looks pretty standard to me. But more important, it works
> great!

I tried to improve the function even more, because I noticed, when
there was a region in the original buffer, and I wanted to do
something on that region, when I stroke the `su-edit', the region
disapeared. So, I made changes to the function (code last). It
works, but with one detail missing: I get the region as desired in
the new buffer, but for some reason, *the region doesn't
show*. The highlight isn't there. But if I strike `write-region'
or whatever, I can confirm that the region is there as it
should. Any ideas?

I tried both with set-mark, and set-mark-command, with the same
result.

(defun su-edit ()
"Edit the current buffer file as superuser."
(interactive)
(let((window-start (window-start))
(point (point))
(pres-reg-beg (if (use-region-p) (region-beginning) nil)))
(find-alternate-file (format "/sudo::%s" (buffer-file-name)))
(message (format "The variable is %d." pres-reg-beg))
(if pres-reg-beg (set-mark pres-reg-beg)) ; same: set-mark-command
(goto-char point)
(set-window-start nil window-start) )) ; nil - the selected window
0 new messages