Vim, sahip olduğu kök dosyaları nasıl çalar?


39

Aşağıdakilere şahit olun:

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

Her nasılsa, vim bu root'a ait dosyayı aldı ve bir kullanıcının sahip olduğu bir dosyaya dönüştürdü!

Bu, yalnızca kullanıcı dizinin sahibiyse çalışıyor gibi görünüyor - ancak yine de mümkün olmaması gerektiğini hissediyor Bunun nasıl yapıldığını açıklayan var mı?

Yanıtlar:


51

Siz,, dizininglen sahibisiniz ( listenizdeki dosyaya bakın ). Bir dizin sadece dosyaların bir listesidir ve bu listeyi değiştirme izniniz vardır (örneğin, dosya ekleme, dosyaları kaldırma, tekrar kendiniz yapmak için sahiplik değiştirme vb.). Sen değiştirmek mümkün olmayabilir içeriğini doğrudan dosyanın ama okuyabilir ve unlink (remove) bir bütün olarak dosya ve sonradan yeni dosyalar ekleyin. 1 Sadece önceki ve sonraki tanıklıklarda, bu dosya değiştirilmiş gibi görünebilir ..

O yüzden açıklıyor böylece Vim, etrafında su altında takas dosya ve hamle dosyalarını kullanır görünüyor size kabuğunda olduğu gibi aynı dosyaya yazma, ama aynı şey değil. 2

Öyleyse, Vim'in yaptığı şeye göre:

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

1 Bu, Windows ve Unices arasındaki dosya izin işlemlerinde önemli bir farktır. Windows'ta, genellikle yazma izniniz olmayan dosyaları kaldıramazsınız.

2 güncelleme: yorumlarda belirtildiği gibi, Vim, tempdosyadaki inode numarası değişmediği için ( ls -liönce ve sonra gelirken ) , sahipliği değiştirmek için bu şekilde yapmaz . Kullanarak stracetam olarak ne yaptığını görebiliriz vim. İlginç kısım burada:

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

Bu, yalnızca işaretin kaldırıldığını , ancak dosya tanımlayıcısının kapatılmadığını gösterir temp. Aksine, sadece tüm içeriğinin üzerine yazar ( more text bla\nbenim durumumda). Sanırım bu inode numarasının neden değişmediğini açıklıyor.


3
FWIW, bunun inode numarası değiştiyse, ls -ilönce ve sonra tempçalışarak olduğunu kontrol edebilirsiniz, aynı isimde farklı bir dosya olduğunu biliyorsunuz.
İşe yaramaz

3
Biri, rm'nin aslında dosyayı kaldırmadığını, ancak dosyanın bağlantısını kaldırdığını ve bağlantıların sayısı 0'a düşmeden önce dosyanın silinmediğini ekleyebilir. Kökün başka bir dizindeki dosyaya başka bir bağlantısı (sabit bağlantı) varsa, kullanıcı dosyayı kaldıramaz.
gerrit

1
@ Kullanılmaz denedim ve sahibi ve zaman damgası değişti rağmen sayı değişmedi!
amyassin

1
@amyassin Haklısın! Cevabımı, onu açıklayan kasvetli bir alıntı ile güncelledim.
gertvdijk

1
Windows ve Unix izinleriyle ilgili notunuza ek olarak, Unix'te Windows benzeri bir davranış istiyorsanız, root'a (veya evrensel kaldırma / yeniden adlandırma / etc izinlerine sahip olması gereken başka bir kullanıcıya) ait bir dizin oluşturabilir ve yapışkanı ayarlayabilirsiniz. dizindeki bit. O zaman kullanıcılar sadece kendi dosyalarını silebilecekler.
Matthew Crumley

16

önce:

-rw-r--r-- 1 root staff 0 19 Dec 12:38 temp

sonra:

-rw-r--r-- 1 glen staff 7 19 Dec 12:38 temp

Vim izin bariyerinden geçmez. Dikkatlice listelenen dosya bilgilerine bir göz atın, sonra vim'in orijinal dosyayı sildiğini öğrenebilirsiniz (çünkü içeriğini değiştiremezseniz de dosyayı kaldırma izniniz vardır), sonra kendinize ait yeni bir dosya oluşturdunuz ( Bakın sahibi artık 'root' değil.

Orijinal dosyayı vim biçiminde düzenlerken, salt okunur bir dosyayı değiştirdiğiniz konusunda uyarır. Bu nedenle komutu yazdığınızda :wq!(işlemi zorladığınızda), vim'in yapabileceği tek şey var olan dosyayı silmek ve aynı ada sahip yeni bir dosya oluşturmak.

Umarım yardımcı olur.


1

Bir dosyanın veya başka bir nesnenin benzersiz bir tanımlayıcısı olan (dosya sistemi içinde) inode numarasını görmek için -iseçeneğini kullanın ls.

Dosyanın farklı bir nesneyle değiştirildiğini göreceksiniz: inode numarası büyük olasılıkla değişecek.

Aynı inode numarasını görmek hiçbir şeyin kanıtı değildir: bir inode numarası geri dönüştürülebilir. Bir dosyadaki son bağlantıyı kaldırır ve sonra yeni bir dosya oluşturursak, aynı inode numarasına sahip bir tane bulabiliriz. Ancak eski dosya yenisi oluşturulduktan sonra kaldırılırsa bu olamaz. Örn mv file file.tmp; touch file; rm file.tmp. Vim'in aslında buna benzer bir şey yaptığını düşünüyorum echo new_content > tmpfile; mv tmpfile file. İşlem mvbir renamesistem çağrısına çevrilecektir , bu nedenle inode numaralarının atanması, dosya sisteminin bir varış yerini belirleyen bir yeniden adlandırmayı nasıl uyguladığına bağlıdır.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.