Witness the following:
sh-3.2$ mkdir testcase
sh-3.2$ cd testcase
sh-3.2$ sudo touch temp
sh-3.2$ ls -al
total 0
drwxr-xr-x 3 glen staff 102 19 Dec 12:38 .
drwxr-xr-x 12 glen staff 408 19 Dec 12:38 ..
-rw-r--r-- 1 root staff 0 19 Dec 12:38 temp
sh-3.2$ echo nope > temp
sh: temp: Permission denied
sh-3.2$ vim temp
# inside vim
itheivery
# press [ESC]
:wq!
# vim exits
sh-3.2$ ls -al
total 8
drwxr-xr-x 3 glen staff 102 19 Dec 12:38 .
drwxr-xr-x 12 glen staff 408 19 Dec 12:38 ..
-rw-r--r-- 1 glen staff 7 19 Dec 12:38 temp
Somehow vim has taken this root-owned file, and changed it into a user owned file!
This only seems to work if the user owns the directory – but it still feels like it shouldn't be possible. Can anyone explain how this is done?
Best Answer
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:
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 (comaringls -li
before and after). Usingstrace
we can see exactly whatvim
does. The interesting part is here: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.