You, glen
, are the owner of the directory (see the .
file in your listing). A directory is just a list of files and you have the permission to alter this list (e.g. add files, remove files, change ownerships to make it yours again, etc.). You may not be able to alter the contents of the file directly, but you can read and unlink (remove) the file as a whole and add new files subsequently.1 Only witnessing the before and after, this may look like the file has been altered.
Vim uses swap files and moves files around under water, so that explains why it seems to write to the same file as you do in your shell, but it's not the same thing.2
So, what Vim does, comes down to this:
cat temp > .temp.swp # copy file by contents into a new glen-owned file
echo nope >> .temp.swp # or other command to alter the new file
rm temp && mv .temp.swp temp # move temporary swap file back
1This is an important difference in file permission handling between Windows and Unices. In Windows, one is usually not able to remove files you don't have write permission for.
2 update: as noted in the comments, Vim does not actually do it this way for changing the ownership, as the inode number on the temp
file does not change (comaring ls -li
before and after). Using strace
we can see exactly what vim
does. The interesting part is here:
open("temp", O_WRONLY|O_CREAT|O_TRUNC, 0664) = -1 EACCES (Permission denied)
unlink("temp") = 0
open("temp", O_WRONLY|O_CREAT|O_TRUNC, 0664) = 4
write(4, "more text bla\n", 14) = 14
close(4) = 0
chmod("temp", 0664) = 0
This shows that it only unlinks, but does not close the file descriptor to temp
. It rather just overwrites its whole contents (more text bla\n
in my case). I guess this explains why the inode number does not change.
I just discovered the reason, and it was a collection of circumstances:
First of all, I don't know exactly why, but sudo
was not grabbing the HOME
environment variable properly and used the one of the regular user, so it read the .vimrc
from /home/user/.vimrc.
In order to see this, I issued:
user@hostname:~$ sudo bash
[sudo] password for user:
root@hostname:/home/user# echo $HOME
/home/user
Second, I have folding persistence enabled in my user's vimrc file in order to store cursor position:
au BufWinLeave * mkview
au BufWinEnter * silent loadview
This makes that every time a file is edited, a properties file is created inside $HOME/.vim/view
folder.
In my case, it looks like I tried to edit the file without sudo
the first time, so the folding file was created as regular user's:
user@hostname:~$ ll .vim/view/ | grep thunderbird.sh
-rw-rw-r-- 1 user user 2650 Aug 20 15:56 =+usr=+lib=+thunderbird=+thunderbird.sh=
Since the root took /home/user
as $HOME
, the same folding file was (wrongly) used when I issued sudo vim
, and for some reason that I ignore, probable related to vim internals, if the folding file is not owned by the editing user, the edited file is opened in ReadOnly mode.
So, I realized that if I removed the file /home/user/.vim/view/=+usr=+lib=+thunderbird=+thunderbird.sh=
and then tried to edit using sudo vim,
I had no problems at all.
So, at the end of the story, in order to fix this situation I just edited /etc/sudoers
and added this line:
Defaults always_set_home
Now everything works as expected and I can use sudo
reliably again.
Best Answer
Since the file lives in a directory that is writable by the user, the user has permissions to delete and recreate the file. This is more or less what
vim
does when you force write to the file.As you can see in this example, the file has been recreated and has a new inode number. The user and group has been set to the user who wrote the file, and the permissions have been set according to the user's
umask
.