Tại sao tôi có thể sửa đổi tệp chỉ đọc?


42

Câu hỏi ngắn:

Tại sao chúng ta có thể thao tác một tệp chỉ đọc trong Vim bằng cách sử dụng :+ w+ q+ !ngay cả khi không phải là quản trị viên?

Câu hỏi dài:

Tôi có một tệp văn bản (myFile.txt) chỉ đọc cho mọi người:

navid@navid-ThinkPad-T530:~/ubuntuTest$ ls -l myFile.txt 
-r--r--r-- 1 navid navid 26 Aug 22 21:21 myFile.txt

Tôi có thể mở nó bằng Vim mà không cần quyền quản trị viên:

navid@navid-ThinkPad-T530:~/ubuntuTest$ vi myFile.txt 

Tôi sửa đổi nó và nhấn: Esc+ :+ w+ q+ Entervà tôi thấy thông báo lỗi này:

E45: 'readonly' option is set (add ! to override)

Cho đến nay, mọi thứ đều có ý nghĩa. Nhưng khi tôi nhấn: Esc+ :+ w+ q+ !+ Enter, Vim lưu các thay đổi.

Tôi đang sử dụng Ubuntu 16.04 và VIM 7.4.


1
@Zanna Bạn có sở hữu thư mục chứa tập tin không?
Rob

Vâng, đây sẽ là một vấn đề HẤP DẪN :)
Rob

11
Sửa đổi một tập tin và thay thế một tập tin là hai điều khác nhau với các yêu cầu cấp phép khác nhau.
David Schwartz

1
Bạn có thể muốn có một cái nhìn về điều này . Về cơ bản, nó trả lời câu hỏi của bạn và như @DavidSchwartz đã chỉ ra một cách chính xác :Modifying a file and replacing a file are two different things
Panagiotis Tabakis

@PanagiotisTabakis Rất thoải mái tìm thấy điều này là rực rỡ .. chmod để làm cho các tập tin đọc-ghi và ngược lại nếu bạn sở hữu nó .. LOVE IT :)
Rob

Câu trả lời:


58

Như @Rob đã đề cập , bạn chỉ có thể làm điều này nếu bạn có quyền ghi vào thư mục chứa tệp. Ví dụ, cố gắng làm điều tương tự với một tệp trong đó /etcsẽ thất bại.

Đối với cách vim thực hiện việc này, nó xóa tệp và tạo lại nó. Để kiểm tra điều này, tôi đã tạo một tệp thuộc sở hữu của root:

echo foo | sudo tee fff

Và sau đó tiến hành chỉnh sửa tệp vimtheo cách bạn mô tả, nhưng đính kèm quy trình straceđể xem điều gì đang xảy ra:

strace vim fff 2> strace.out

Sau đó tôi đã kiểm tra strace.outvà tìm thấy:

unlink("fff")                           = 0
open("fff", O_WRONLY|O_CREAT|O_TRUNC, 0644) = 4
write(4, "foasdasdao\n", 11)            = 11

Vì vậy, lần đầu tiên tệp bị xóa ( unlink("fff")), sau đó một tệp mới cùng tên đã được tạo ( open("fff", O_WRONLY|O_CREAT|O_TRUNC, 0644)) và các sửa đổi tôi đã thực hiện được ghi vào nó ( write(4, "foasdasdao\n", 11)). Nếu bạn thử điều này ở nhà, bạn sẽ thấy rằng sau khi bạn chỉnh sửa nó vim, tập tin sẽ thuộc về bạn chứ không phải root.

Vì vậy, nói đúng ra, vimkhông chỉnh sửa một tập tin mà bạn không có quyền ghi. Đó là xóa một tệp từ một thư mục mà bạn có quyền truy cập ghi và sau đó tạo một tệp mới, một lần nữa, bạn có quyền truy cập ghi.



8
@CCJ đó là thao tác ghi trên thư mục nhưng không phải tệp, không. Thao tác ghi trên tệp là những thao tác thay đổi nội dung của tệp. Tương tự, việc tạo / xóa các tệp là các thao tác ghi trên thư mục do bạn đang thay đổi nội dung của nó.
terdon

2
Ngoài ra, đó là một thứ tự nguy hiểm của hoạt động. Sẽ an toàn hơn khi viết thay thế vào một tên tệp mới và sau đó sử dụng rename(2)để thay thế tệp cũ. Sau đó, không có cửa sổ thời gian mà dữ liệu của bạn không tồn tại trên đĩa.
Peter Cordes

5
@PeterCordes um, OK. Bạn có thể muốn gửi khiếu nại của mình đến các nhà phát triển vim. Tôi thậm chí không sử dụng thứ đó, tôi đang ở trong trại emacs.
terdon

3
@CCJ Xóa một tệp là một thao tác ghi vào thư mục chứa nó, không phải cho chính tệp đó. Điều hoàn toàn trực quan là nếu bạn phụ trách một thư mục (nghĩa là có quyền truy cập ghi vào nó), bạn sẽ có thể kiểm soát những gì trong đó và chủ sở hữu của một tệp riêng lẻ không được phép ghi đè lên bạn.
fkraiem

16

Miễn là bạn sở hữu thư mục mẹ, bạn có thể xóa hoặc thay thế một tệp bất kể sự cho phép vì bạn có thể thay đổi nội dung của thư mục :).

Hãy thử nó với lệnh khác như rm, nó sẽ nhắc bạn nhưng bạn vẫn có thể làm được. Làm cho thư mục không thể ghi và nên dừng nó.

Thêm vào:

Chỉ cần thử nó, miễn là tôi sở hữu tập tin, tôi vẫn có thể sửa đổi nó, ngay cả với thư mục chỉ đọc. Tuy nhiên khi tôi thay đổi quyền sở hữu thành root: root thì không thể mở tệp để ghi. Vì vậy, giải quyết các tệp sửa đổi thuộc sở hữu của root (hoặc người khác)


7
Có vẻ như VIM chọn từ nhiều chiến lược, bao gồm viết lại tại chỗ hoặc hủy liên kết + viết một tệp mới.
Peter Cordes

3
@PeterCordes Có Rõ ràng sẽ rất cố gắng để làm những gì bạn nói với nó :) rất xảo quyệt. :)
Rob

16

Sử dụng w!bạn đang xóa tệp gốc ( mà bạn được phép làm ) và viết phiên bản của bạn thay vào đó.

Khi bạn có quyền ghi vào thư mục, bạn có thể: tạo, di chuyển hoặc xóa các tệp trong thư mục đó.

$ mkdir foo
$ echo hi > foo/file
$ chmod 777 foo
$ chmod 700 foo/file
$ ls -l foo/file 
-rwx------ 1 ravexina ravexina 7 Aug 31 03:19 foo/file

Bây giờ hãy để tôi chuyển người dùng của mình và thay đổi tập tin

$ sudo -u user2 -s
$ vi foo/a # save using w! (I wrote into the file bye)
$ ls -l foo/a
-rwx------ 1 user2 user2 7 Aug 31 03:20 foo/file

Bây giờ hãy xem những gì trong đó:

$ cat foo/file
bye

10

Xem :help write-readonly:

                                                        write-readonly
When the 'cpoptions' option contains 'W', Vim will refuse to overwrite a
readonly file.  When 'W' is not present, ":w!" will overwrite a readonly file,
if the system allows it (the directory must be writable).

Vì bạn có quyền ghi trên thư mục (có nghĩa là bạn có thể tạo, xóa hoặc đổi tên tệp trong đó), nên hệ thống cho phép.


Giá trị mặc định cpoptionskhông chứa W:

                                                'cpoptions' 'cpo' cpo
'cpoptions' 'cpo'       string  (Vim default: "aABceFs",
                                 Vi default:  all flags)
                        global

2

Đây là cảnh báo của VIM cho bạn rằng có thể tương đối quan trọng khi xem xét cách các quyền hoạt động trong UNIX. Sự không phù hợp rõ ràng của điều này là do các hệ thống tệp UNIX có quyền đối với tệp được lưu trữ trong nút i của tệp. Cấu trúc thư mục bằng cách nào đó riêng biệt và chỉ liên kết các nút i này. Các thư mục cũng có quyền cho biết liệu bạn có thể liên kết / hủy liên kết các tệp vào nó hay đọc nó hoặc duyệt qua các thư mục con. Thiết kế này cho phép cùng một tệp có thể xuất hiện ở một số vị trí khác nhau trong cấu trúc thư mục (thông qua các liên kết cứng). Bằng cách nói "thêm! Để ghi đè", VIM đang cố gắng cảnh báo bạn rằng tệp gốc sẽ bị hủy liên kết (vì vậy nó sẽ ở lại tất cả các vị trí khác không bị ảnh hưởng) và tệp mới sẽ được tạo và liên kết với vị trí ban đầu trong cấu trúc thư mục. Trong trường hợp số liên kết của tệp gốc giảm xuống 0, tệp gốc sẽ được giải phóng, nhưng nếu không, bạn đang sao chép tệp một cách hiệu quả. Mở tệp cũng được tính là liên kết, vì vậy nếu một số chương trình đã mở tệp và bạn đồng ý "thêm! Để ghi đè", chương trình sẽ không thấy các thay đổi do bạn thực hiện đối với tệp bằng VIM. Tệp chỉ được hủy liên kết khỏi thư mục bởi VIM và sau khi đóng tệp bằng chương trình khác, tệp sẽ được giải phóng, trừ khi được liên kết ở một nơi khác.

Xin lưu ý rằng trong Windows, các quyền đối với tệp được lưu trữ trong thư mục, do đó, từ quan điểm của mô hình quyền Windows, hành vi vim này thực sự có thể trông lạ. Để ghi vào tệp, Windows cũng có thể kiểm tra một số quyền của thư mục, thậm chí cả quyền siêu thư mục. Như đã nói ở trên, trong UNIX, các quyền của thư mục không liên quan đến thao tác với tệp theo như bạn có thể liệt kê và mở nó (tức là có x cho tất cả các siêu thư mục). Tệp đã mở trong UNIX có thể không còn có tên tệp nữa nếu nó bị hủy liên kết khỏi tất cả các thư mục sau khi mở.

Ví dụ: bạn có tệp / home / user1 / foo và đó là cùng một tệp với (tức là liên kết cứng đến) / home / user2 / foo và tệp này không thể ghi được bởi bất kỳ ai và hiện đang được mở bởi chương trình P (mở đọc-ghi bởi chương trình bắt đầu bằng root). Nếu user1 mở nó bằng vim và ghi đè, anh ta tạo bản sao của riêng mình và không còn thấy tệp gốc. Nếu sau đó user2 mở liên kết của mình với vim và ghi vào đó, nó sẽ được hủy liên kết lại và anh ta sẽ tạo một bản sao khác. Chương trình P vẫn sẽ thấy tệp gốc và có thể tự do đọc hoặc ghi vào nó. Ngay khi chương trình đóng tệp, tệp sẽ biến mất (được giải phóng bởi hệ thống tệp).


2

Cả quá trình biên tập vim và tệp của bạn đều mang

 getpwnam("navid")->pw_uid

quyền sở hữu để bạn cũng có thể bỏ ra

 :!chmod +w %

và bạn có thể đoán rằng ngày xưa còn đơn giản hơn

 :!rm %

.

Hãy thử ghi đè lên chị gái của bạn

 /home/whoopi/.profile

như chỉ là điều hướng và đặt cược là vim của bạn cung cấp cho bạn từ chối mong muốn của bạn.


Cảm ơn bạn @Zanna vì đã chỉnh sửa mã mặc dù nó làm tôi mất một chút tiếng tăm, dù xứng đáng.
Roman Czyborra

1

Đây không phải là một câu trả lời chính xác, nhưng nếu bạn thực sự muốn thiết lập một tệp để không ai có thể thay đổi hoặc xóa nó, bạn có thể làm cho nó không thay đổi.

Thông thường, ngay cả khi một tập tin được sở hữu bởi root, bạn vẫn có thể xóa tập tin nếu bạn có quyền ghi vào thư mục. Nhưng khi bạn tạo tập tin bất biến, ngay cả root cũng không thể sửa đổi hoặc xóa nó.

Để tạo một tập tin bất biến (bạn cần sudo):

sudo chattr +i myFile.txt

Bạn có thể thấy điều này với lsattr(chữ cái itrong kết quả):

$ lsattr myFile.txt
----i--------e-- myFile.txt

Để làm cho tập tin bình thường trở lại:

sudo chattr -i myFile.txt

Để làm rõ: Khi một tệp là bất biến, nó không thể bị xóa, đổi tên, sửa đổi hoặc thậm chí liên kết cứng.

Rất đáng để đọc man chattr, vì các tệp có thể có một số thuộc tính hữu ích.

Bạn cũng có thể thấy "xóa hạn chế" hữu ích. Nếu được đặt trên một thư mục (không phải tệp), điều này có nghĩa là bất cứ ai tạo tệp trong thư mục đều được phép sửa đổi hoặc xóa tệp đó, nhưng không ai khác (ngoại trừ root). Thư mục /tmpcó cờ này được đặt. Bạn có thể thấy điều này với tcờ trên /tmp:

$ ls -l --directory /tmp
drwxrwxrwt 10 root root 4096 Sep  6 09:00 /tmp

Để đặt hoặc xóa cờ xóa bị hạn chế trên một thư mục:

chmod +t myFolder      # Add the restricted deletion flag.
chmod -t myFolder      # Remove the restricted deletion flag.
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.