Pourquoi puis-je modifier un fichier en lecture seule?


42

Question courte:

Pourquoi pouvons-nous manipuler un fichier en lecture seule dans Vim avec :+ w+ q+ !même sans être administrateur?

Longue question:

J'ai un fichier texte (myFile.txt) qui est en lecture seule pour tout le monde:

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

Je peux l'ouvrir avec Vim sans avoir les privilèges d'administrateur:

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

Je le modifie et appuie sur: Esc+ :+ w+ q+ Enteret je vois ce message d'erreur:

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

Jusqu'à présent, tout est logique. Mais lorsque j'appuie sur: Esc+ :+ w+ q+ !+ Enter, Vim enregistre les modifications.

J'utilise Ubuntu 16.04 et VIM 7.4.


1
@Zanna Possédez-vous le répertoire dans lequel se trouve le fichier?
Rob

Ouais, ce serait un énorme problème sinon :)
Rob

11
La modification et le remplacement d’un fichier sont deux choses différentes avec des conditions d’autorisation différentes.
David Schwartz

1
Vous voudrez peut-être jeter un coup d'œil à cela . En gros, cela répond à votre question et comme @DavidSchwartz l'a bien souligné :Modifying a file and replacing a file are two different things
Panagiotis Tabakis

@PanagiotisTabakis Très belle trouvaille c'est génial .. chmod pour rendre le fichier en lecture-écriture et retour si vous le possédez .. LOVE IT :)
Rob

Réponses:


58

Comme @Rob déjà mentionné , vous ne pouvez le faire que si vous avez un accès en écriture au répertoire contenant le fichier. Tenter de faire la même chose avec un fichier, par exemple, /etcéchouera.

En ce qui concerne la façon dont vim fait cela, il supprime le fichier et recrée. Pour tester cela, j'ai créé un fichier appartenant à root:

echo foo | sudo tee fff

Et ensuite procédé à éditer le fichier avec vimla manière que vous décrivez, mais en joignant le processus stracepour voir ce qui se passe:

strace vim fff 2> strace.out

J'ai ensuite vérifié strace.outet trouvé:

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

Ainsi, le fichier a d'abord été supprimé ( unlink("fff")), puis un nouveau fichier du même nom a été créé ( open("fff", O_WRONLY|O_CREAT|O_TRUNC, 0644)) et les modifications que j'ai apportées y ont été écrites ( write(4, "foasdasdao\n", 11)). Si vous essayez ceci à la maison, vous verrez qu'après l'avoir modifié vim, le fichier vous appartiendra et non pas la racine.

Donc, à proprement parler, l' vimédition d'un fichier sur lequel vous n'avez pas d'accès en écriture n'est pas. Il s'agit de supprimer un fichier d'un répertoire auquel vous avez un accès en écriture, puis de créer un nouveau fichier auquel, encore une fois, vous avez un accès en écriture.



8
@CCJ c'est une opération d'écriture sur le répertoire mais pas le fichier, non. Les opérations d'écriture sur les fichiers sont celles qui modifient le contenu du fichier. De même, la création / suppression de fichiers est une opération d'écriture sur le répertoire puisque vous en modifiez le contenu.
terdon

2
En outre, c'est un ordre d'opérations dangereux. Il serait plus sûr d'écrire le remplacement dans un nouveau nom de fichier, puis rename(2)de remplacer l'ancien fichier. Ensuite, il n'y a aucune fenêtre temporelle où vos données n'existent pas sur le disque.
Peter Cordes

5
@PeterCordes euh, d'accord. Vous voudrez peut-être toutefois adresser vos plaintes aux développeurs de vim. Je n'utilise même pas la chose, je suis dans le camp d'emacs.
terdon

3
@CCJ La suppression d'un fichier est une opération d'écriture dans le répertoire qui le contient, pas dans le fichier lui-même. Il est parfaitement intuitif que si vous êtes en charge d’un répertoire (c’est-à-dire que vous y avez accès en écriture), vous devriez être en mesure de contrôler son contenu et le propriétaire d’un fichier ne doit pas être autorisé à vous remplacer.
fkraiem

16

Tant que vous possédez le répertoire parent, vous pouvez supprimer ou remplacer un fichier, quelle que soit l'autorisation, car vous pouvez modifier le contenu du répertoire :).

Essayez-le avec une autre commande comme rm, cela vous le demandera mais vous pouvez toujours le faire. Rendre le répertoire non accessible en écriture et cela devrait l'arrêter.

Une addition:

Juste essayé mais tant que je possède le fichier, je peux toujours le modifier, même avec le dossier en lecture seule. Cependant, lorsque je change de propriétaire en root: root, il ne peut pas ouvrir le fichier en écriture. Résout donc la modification des fichiers appartenant à root (ou à quelqu'un d'autre)


7
Il semble que VIM choisisse parmi plusieurs stratégies, y compris réécrire sur place ou dissocier + écrire un nouveau fichier.
Peter Cordes

3
@PeterCordes Oui Il va apparemment essayer de faire ce que vous lui dites :) très rusé. :)
Rob

16

En utilisant, w!vous supprimez le fichier d'origine ( ce que vous êtes autorisé à faire ) et écrivez votre version à la place.

Lorsque vous avez un accès en écriture à un répertoire, vous pouvez: créer, déplacer ou supprimer des fichiers de ce répertoire.

$ 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

Maintenant, permettez-moi de changer d'utilisateur et de changer le fichier

$ 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

Maintenant, voyez ce qu'il y a dedans:

$ cat foo/file
bye

10

Voir :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).

Étant donné que vous disposez d'autorisations en écriture sur le répertoire (ce qui signifie que vous pouvez créer, supprimer ou renommer des fichiers dans ce répertoire), le système l'autorise.


La valeur par défaut de cpoptionsne contient pas W:

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

2

Ceci est un avertissement de VIM qui pourrait vous être relativement important compte tenu du fonctionnement des autorisations dans UNIX. Cela semble peu intuitif, car les systèmes de fichiers UNIX disposent d'autorisations pour les fichiers stockés dans i-node du fichier. La structure des répertoires est en quelque sorte séparée et ne lie que ces i-nœuds. Les répertoires ont également leurs autorisations qui indiquent si vous pouvez lier / dissocier des fichiers, ou le lire ou le parcourir dans des sous-répertoires. Cette conception permet qu'un même fichier puisse apparaître à plusieurs endroits différents de la structure de répertoires (via des liens physiques). En disant "ajouter! Pour remplacer", VIM essaie de vous avertir que le fichier d'origine sera dissocié (de sorte qu'il restera inchangé) et que le nouveau fichier sera créé et lié à l'emplacement d'origine dans la structure de répertoires. Si le nombre de liens du fichier d'origine est réduit à zéro, le fichier d'origine sera libéré, mais dans le cas contraire, vous clonez effectivement le fichier. L’ouverture du fichier est également considérée comme un lien. Par conséquent, si un programme a ouvert le fichier et que vous acceptez d’ajouter «au remplacement», le programme ne verra pas les modifications apportées au fichier par VIM. Le fichier est uniquement dissocié du répertoire par VIM et, après fermeture du fichier par un autre programme, le fichier sera libéré, sauf s'il était lié ailleurs.

Veuillez noter que dans Windows, les autorisations pour les fichiers sont stockées dans un répertoire. Par conséquent, du point de vue du paradigme des autorisations Windows, ce comportement de vim peut en effet paraître étrange. Logiquement, pour écrire dans le fichier, il peut également vérifier certaines autorisations de répertoire, même les autorisations de super-répertoire. Comme indiqué ci-dessus, sous UNIX, les autorisations de répertoire ne sont pas pertinentes pour la manipulation du fichier, dans la mesure où vous avez pu le répertorier et l'ouvrir (c'est-à-dire qu'il y avait x pour tous les super-répertoires). Le fichier ouvert sous UNIX peut même ne plus avoir de nom de fichier s'il est dissocié de tous les répertoires après son ouverture.

Par exemple, vous avez le fichier / home / user1 / foo et c’est le même fichier que (c.-à-d. Un lien fixe) / home / user2 / foo et le fichier n’est pas accessible en écriture pour personne et est actuellement ouvert par le programme P (ouvert en lecture-écriture par programme lancé par root). Si l'utilisateur1 l'ouvre avec vim et remplace, il crée sa propre copie et ne voit plus le fichier d'origine. Si, par la suite, l'utilisateur2 ouvre son lien avec vim et y écrit, le lien sera de nouveau dissocié et il en créera une autre copie. Le programme P verra toujours le fichier original et pourra y lire ou écrire librement. Dès que le programme ferme le fichier, le fichier disparaîtra (sera libéré par le système de fichiers).


2

Le processus de votre éditeur vim et votre fichier portent tous deux votre

 getpwnam("navid")->pw_uid

la propriété afin que vous puissiez aussi débourser

 :!chmod +w %

et vous pourriez deviner qu'il était une fois encore plus simple

 :!rm %

(ne nécessitant que + w, ut dissocier l’autorisation sur. et même pas la propriété) est devenu trop fréquent pour que quelqu'un puisse taper, de sorte que vim a été reprogrammé pour offrir automatiquement et sur demande effectuer automatiquement une telle opération.

Essayez de remplacer votre grande soeur

 /home/whoopi/.profile

comme simple navid et paris sont votre vim vous donne votre refus souhaité.


Merci @Zanna pour l'édition du code, même si cela m'a coûté un petit peu de réputation au novice, à juste titre.
Roman Czyborra

1

Ce n'est pas exactement une réponse, mais si vous voulez vraiment définir un fichier afin que personne ne puisse le modifier ou le supprimer, vous pouvez le rendre immuable.

Normalement, même si un fichier appartient à root, vous pouvez toujours le supprimer si vous disposez des autorisations d'écriture sur le dossier. Mais lorsque vous rendez le fichier immuable, même root ne peut ni le modifier ni le supprimer.

Pour rendre un fichier immuable (il vous faut sudo):

sudo chattr +i myFile.txt

Vous pouvez voir ceci avec lsattr(la lettre idans le résultat):

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

Pour que le fichier redevienne normal:

sudo chattr -i myFile.txt

Pour clarifier: lorsqu'un fichier est immuable, il ne peut pas être supprimé, renommé, modifié ou même lié en dur.

Cela vaut la peine d'être lu man chattr, car les fichiers peuvent avoir un certain nombre d'attributs utiles.

Vous pourriez également trouver utile "suppression restreinte". S'il est placé dans un dossier (pas un fichier), cela signifie que quiconque crée un fichier dans le dossier est autorisé à modifier ou supprimer ce fichier, mais personne d'autre ne l'est (à l'exception de la racine). Le dossier /tmpa cet indicateur défini. Vous pouvez voir cela avec le tdrapeau sur /tmp:

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

Pour définir ou supprimer l'indicateur de suppression restreinte sur un dossier:

chmod +t myFolder      # Add the restricted deletion flag.
chmod -t myFolder      # Remove the restricted deletion flag.
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.