Pourquoi les liens physiques vers des répertoires ne sont-ils pas autorisés sous UNIX / Linux?

130

J'ai lu dans des ouvrages que Unix / Linux n'autorisait pas les liens physiques vers des répertoires mais autorisait les liens souples. Est-ce parce que, lorsque nous avons des cycles et que nous créons des liens physiques, et après quelque temps, nous supprimons le fichier d'origine, il va pointer sur une valeur erronée?

Si les cycles étaient la seule raison derrière ne pas autoriser les liens physiques, alors pourquoi les liens symboliques vers des répertoires sont-ils autorisés?

utilisateur3539
la source
2
Où faut-il ..pointer? Surtout après avoir supprimé le lien physique vers ce répertoire, dans le répertoire désigné par ..? Il doit pointer quelque part.
Thorbjørn Ravn Andersen
2
..n'a pas besoin d'exister physiquement sur aucun lecteur. De toute façon, le travail du système d’exploitation est de garder une trace du répertoire de travail en cours. Il devrait donc être relativement simple de conserver également une liste des inodes associés à chaque cwd du processus et de s'y référer lorsqu’il voit une utilisation de ... Bien sûr, cela voudrait dire que les liens symboliques devraient être créés dans cet esprit, mais vous devez déjà faire attention à ne pas les rompre, et je ne pense pas que cette règle supplémentaire les rendrait inutiles.
Parthian Shot
J'aime cette explication . Concis et facile à lire et / ou à parcourir.
Trevor Boyd Smith

Réponses:

143

Ceci est juste une mauvaise idée, car il n'y a aucun moyen de faire la différence entre un lien dur et un nom original.

Autoriser des liens physiques vers des répertoires briserait la structure de graphes acyclique dirigée du système de fichiers, créant éventuellement des boucles de répertoires et des sous-arborescences de répertoires pendantes, ce qui rendrait fscktoute autre arborescence de fichiers sujette aux erreurs.

Tout d’abord, pour comprendre cela, parlons d’inodes. Les données du système de fichiers sont conservées dans des blocs sur le disque et ces blocs sont rassemblés par un inode. Vous pouvez considérer l'inode comme étant LE fichier. Les inodes manquent cependant de noms de fichiers. C'est là que les liens entrent en jeu.

Un lien est juste un pointeur sur un inode. Un répertoire est un inode qui contient des liens. Chaque nom de fichier dans un répertoire est simplement un lien vers un inode. Ouvrir un fichier sous Unix crée également un lien, mais il s'agit d'un type de lien différent (ce n'est pas un lien nommé).

Un lien physique est simplement une entrée de répertoire supplémentaire pointant vers cet inode. Lorsque vous ls -l, le nombre après les autorisations est le nombre de liens nommés. La plupart des fichiers normaux auront un lien. Créer un nouveau lien physique vers un fichier fera que les deux noms de fichiers pointent sur le même inode. Remarque:

% ls -l test
ls: test: No such file or directory
% touch test
% ls -l test
-rw-r--r--  1 danny  staff  0 Oct 13 17:58 test
% ln test test2
% ls -l test*
-rw-r--r--  2 danny  staff  0 Oct 13 17:58 test
-rw-r--r--  2 danny  staff  0 Oct 13 17:58 test2
% touch test3
% ls -l test*
-rw-r--r--  2 danny  staff  0 Oct 13 17:58 test
-rw-r--r--  2 danny  staff  0 Oct 13 17:58 test2
-rw-r--r--  1 danny  staff  0 Oct 13 17:59 test3
            ^
            ^ this is the link count

Maintenant, vous pouvez voir clairement qu’il n’existe pas de lien dur. Un lien dur est identique à un nom ordinaire. Dans l'exemple ci-dessus, testou test2, quel est le fichier d'origine et quel est le lien physique? À la fin, vous ne pouvez pas vraiment dire (même par horodatage) car les deux noms désignent le même contenu, le même inode:

% ls -li test*  
14445750 -rw-r--r--  2 danny  staff  0 Oct 13 17:58 test
14445750 -rw-r--r--  2 danny  staff  0 Oct 13 17:58 test2
14445892 -rw-r--r--  1 danny  staff  0 Oct 13 17:59 test3

Le -idrapeau à lsvous montre les numéros d’inode au début de la ligne. Notez comment testet test2avoir le même numéro d’inode, mais test3un numéro différent.

Maintenant, si vous étiez autorisé à le faire pour les répertoires, deux répertoires différents situés à des endroits différents du système de fichiers pourraient pointer vers la même chose. En fait, un sous-répertoire pourrait pointer vers son grand-parent, créant ainsi une boucle.

Pourquoi cette boucle est-elle une préoccupation? Parce que lorsque vous traversez, il n’ya aucun moyen de détecter que vous êtes en boucle (sans garder trace des numéros d’inodes pendant que vous traversez). Imaginez que vous écrivez la ducommande, qui doit être recurse à travers des sous-répertoires pour en savoir plus sur l'utilisation du disque. Comment pourrait dusavoir quand il a frappé une boucle? Il y a beaucoup d'erreurs dans la comptabilité et beaucoup de comptabilité duà faire, rien que pour réussir cette tâche simple.

Les liens symboliques sont une toute autre bête, en ce qu'ils constituent un type de "fichier" spécial que de nombreuses API de système de fichiers ont tendance à suivre automatiquement. Notez qu'un lien symbolique peut pointer vers une destination inexistante, car ils pointent par nom et non directement sur un inode. Ce concept n'a pas de sens avec les liens durs, car la simple existence d'un "lien dur" signifie que le fichier existe.

Alors, pourquoi peut dutraiter avec des liens symboliques facilement et non des liens durs? Nous avons pu voir ci-dessus que les liens physiques sont impossibles à distinguer des entrées de répertoire normales. Les liens symboliques, cependant, sont spéciaux, détectables et sautables!  duremarque que le lien symbolique est un lien symbolique et le saute complètement!

% ls -l 
total 4
drwxr-xr-x  3 danny  staff  102 Oct 13 18:14 test1/
lrwxr-xr-x  1 danny  staff    5 Oct 13 18:13 test2@ -> test1
% du -ah
242M    ./test1/bigfile
242M    ./test1
4.0K    ./test2
242M    .
Danny Dulai
la source
7
Allowing hard links to directories would break the directed acyclic graph structure of the filesystem. Pouvez-vous s'il vous plaît expliquer plus sur le problème avec les cycles en utilisant des liens durs? Pourquoi est-ce
acceptable
33
Ils semblent l'avoir autorisé sur les Mac en ajoutant la détection de cycle à l'appel système link () et en refusant de vous permettre de créer un lien physique de répertoire s'il créait un cycle. Semble être une solution raisonnable.
psusi
10
@psusi mkdir -pa / b; nocheckln ca; mv ca / ​​b; - le nocheckln il y a un ln théorique qui ne vérifie pas l'argument d'annuaire, et passe juste à lier, et comme aucun cycle n'est créé, nous sommes tous bons pour créer 'c'. alors nous passons 'c' dans 'a / b', et un cycle est créé à partir de / b / c -> a / - vérifier que le lien () n'est pas assez bon
Danny Dulai
3
Les cycles sont très mauvais. Windows a ce problème avec "jonctions" qui sont des répertoires de liens durs. Si vous appliquez accidentellement des autorisations à l'ensemble de votre profil, une série de jonctions créant un cycle infini est découverte. La récurrence dans les répertoires est récurrente jusqu'à ce que la longueur du chemin d'accès l'arrête.
Doug65536
4
@WhiteWinterWolf, selon ce lien, ils ont spécifiquement ajouté un support pour cela, mais seul root est autorisé à le faire: superuser.com/questions/360926/…
psusi
14

A l'exception des points de montage, chaque répertoire a un parent et que: ...

Une façon de faire pwdest de vérifier le périphérique: inode pour '.' et '..'. S'ils sont identiques, vous avez atteint la racine du système de fichiers. Sinon, trouvez le nom du répertoire en cours dans le parent, placez-le sur une pile et commencez à comparer '../.' avec '../ ..', puis '../../.' avec '../../ ..', etc. Une fois que vous avez frappé la racine, commencez à afficher et à imprimer les noms de la pile. Cet algorithme repose sur le fait que chaque répertoire a un et un seul parent.

Si les liens en dur vers les annuaires étaient autorisés, lequel des nombreux parents devrait ..pointer? C'est une des raisons impérieuses pour lesquelles les liens physiques en dur ne sont pas autorisés.

Les liens symboliques vers les répertoires ne posent pas ce problème. Si un programme le souhaite, il peut faire un lstat()sur chaque partie du chemin et détecter quand un lien symbolique est rencontré. L' pwdalgorithme renverra le vrai chemin absolu pour un répertoire cible. Le fait qu'il y ait un morceau de texte quelque part (le lien symbolique) qui pointe vers le répertoire cible est à peu près sans importance. L'existence d'un tel lien symbolique ne crée pas de boucle dans le graphique.

Joe Inwap
la source
3
Pas si sûr de ça. Si nous pensons ..qu’il s’agit d’une sorte de liaison virtuelle virtuelle avec le parent, il n’ya aucune raison technique pour que la cible du lien ne puisse avoir qu’un autre lien. pwddevrait simplement utiliser un algorithme différent pour résoudre le chemin.
Benubird
13

Vous pouvez utiliser bind mount pour simuler des répertoires de liens durs

sudo mount --bind /some/existing_real_contents /else/dummy_but_existing_directory
sudo umount /else/dummy_but_existing_directory
zainengineer
la source
7

J'aime ajouter quelques points supplémentaires à cette question. Les liens physiques pour les répertoires sont autorisés sous Linux, mais de manière restreinte.

Une façon de tester cela est lorsque nous listons le contenu d'un répertoire, nous trouvons deux répertoires spéciaux "." et "..". Comme nous le savons "." pointe vers le même répertoire et ".." pointe vers le répertoire parent.

Créons donc une arborescence de répertoires où "a" est le répertoire parent qui a pour répertoire "b".

 a
 `-- b

Notez l'inode du répertoire "a". Et quand nous faisons un ls -larépertoire "a", nous pouvons voir cela "." Le répertoire pointe également vers le même inode.

797358 drwxr-xr-x 3 mkannan mkannan 4096 Sep 17 19:13 a

Et ici nous pouvons trouver que le répertoire "a" a trois liens durs. En effet, l'inode 797358 a trois liens durs au nom de "." à l'intérieur du répertoire "a" et nommez-le sous la forme ".." dans le répertoire "b" et l'un portant le nom "a" itslef.

$ ls -ali a/
797358 drwxr-xr-x 3 mkannan mkannan 4096 Sep 17 19:13 .

$ ls -ali a/b/
797358 drwxr-xr-x 3 mkannan mkannan 4096 Sep 17 19:13 ..

Nous pouvons donc comprendre ici que les liens physiques ne sont là que pour que les répertoires se connectent avec leurs répertoires parent et enfant. Ainsi, un répertoire sans enfant n'aura que 2 liens durs, et le répertoire "b" n'aura que deux liens durs.

Une des raisons pour lesquelles la liaison en dur de répertoires a été librement empêchée serait d'éviter les boucles de référence infinies qui risqueraient de brouiller les programmes traversant le système de fichiers.

Comme le système de fichiers est organisé sous forme d'arborescence et que cette arborescence ne peut pas avoir de référence cyclique, cela aurait dû être évité.

Kannan Mohan
la source
1
Bon exemple. Cela a effacé mon doute. Donc, ces cas sont traités de manière spéciale pour éviter des boucles infinies. droite?
G Gill
1
Comme nous avons un moyen limité d’autoriser les liens durs pour les répertoires, c’est-à-dire ".." et "." nous n'atteindrons pas une boucle infinie et nous n'aurons donc pas besoin de moyens spéciaux pour les éviter car ils ne se produiront pas :)
Kannan Mohan
6

Aucune des raisons suivantes ne constitue la véritable raison pour interdire les liens physiques vers des répertoires; chaque problème est assez facile à résoudre:

  • les cycles dans l’arborescence rendent difficile la traversée
  • plusieurs parents, alors quel est le "vrai"?
  • système de fichiers garbage collection

La vraie raison (comme le suggère @ Thorbjørn Ravn Andersen) vient du fait que vous supprimez un répertoire comportant plusieurs parents, à partir du répertoire désigné par ..:

Que devrait ..maintenant indiquer?

Si le répertoire est supprimé de son parent mais que le nombre de liens est toujours supérieur à 0ce qu'il doit être, il doit y avoir quelque chose, quelque part qui le pointe toujours. Vous ne pouvez pas laisser ..pointant à rien; de nombreux programmes reposent sur .., de sorte que le système devrait parcourir tout le système de fichiers jusqu'à ce qu'il trouve la première chose qui pointe vers le répertoire supprimé, juste pour être mis à jour ... Soit cela, soit le système de fichiers devrait maintenir une liste de tous les répertoires pointant vers un répertoire lié en dur.

Dans les deux cas, il s'agirait d'un surcoût de performances et d'une complication supplémentaire pour les métadonnées et / ou le code du système de fichiers. Les concepteurs ont donc décidé de ne pas l'autoriser.

Lqueryvg
la source
3
C'est également facile à résoudre: conservez la liste des parents d'un répertoire enfant, que vous mettez à jour lorsque vous ajoutez ou supprimez un lien vers l'enfant. Lorsque vous supprimez le parent canonique (la cible de l'enfant ..), effectuez une mise ..à jour pour pointer sur l'un des autres parents de la liste.
Jathd
2
Je suis d'accord. Pas sorcier à résoudre. Néanmoins, il en résultait une surcharge de performances, qui prendrait un peu plus de place dans les métadonnées du système de fichiers et compliquerait davantage les choses. Les concepteurs ont donc opté pour une approche simple et rapide: n'autorisez pas les liens vers des répertoires en dur.
Lqueryvg
1
Les liens Sym vers dirs "violent la sémantique et les comportements établis", mais ils sont toujours autorisés. Certaines commandes ont donc besoin d'options pour contrôler si les liens sym sont suivis (par exemple -L dans find et cp). Lorsqu'un programme suit '..', il y a confusion supplémentaire, d'où la différence de sortie entre pwd et / bin / pwd après avoir traversé un lien sym. Il n'y a pas de "réponses Unix"; juste des décisions de conception. Celui-ci tourne autour de ce qu'il devient de ".." comme je l'ai dit dans ma réponse. Malheureusement, ".." n'est même pas mentionné dans la réponse pour laquelle tous les autres votent si timidement.
Lqueryvg
BTW, je ne dis pas que je suis en faveur de liens durs vers des dirs. Pas du tout. Je ne veux pas que mon travail de jour soit plus dur qu'il ne l'est déjà.
Lqueryvg
Ce n'est pas ce que POSIX dit, mais IMO '..' n'aurait jamais dû être un concept de système de fichiers, mais plutôt résolu syntaxiquement sur les chemins, ce qui a/..signifierait toujours .. Voici comment fonctionnent les URL, au fait. C'est le navigateur qui résout '..' avant même d'apparaître sur le serveur. Et ça marche très bien.
ybungalobill
3

La création de liens physiques sur des répertoires serait irréversible. Supposons que nous ayons:

/dir1
├──this.txt
├──directory
│  └──subfiles
└──etc

Je le lie au lien /dir2.

Alors /dir2maintenant contient également tous ces fichiers et répertoires

Et si je change d'idée? Je ne peux pas juste rmdir /dir2(parce que c'est non vide)

Et si je supprime récursivement dans /dir2... il sera également supprimé /dir1!

IMHO c'est une raison largement suffisante pour éviter cela!

Modifier :

Les commentaires suggèrent de supprimer le répertoire en le faisant rm. Mais rmsur un répertoire non vide échoue et ce comportement doit rester, que le répertoire soit lié durement ou non. Donc, vous ne pouvez pas simplement rmle dissocier. Il faudrait un nouvel argument rm, juste pour dire "si l'inode du répertoire a un nombre de références> 1, alors ne liez pas le répertoire".

Ce qui, à son tour, enfreint un autre principe de moindre surprise: cela signifie que la suppression d'un répertoire hardlink que je viens de créer n'est pas la même chose que la suppression d'un fichier normal, hardlink ...

Je vais reformuler ma phrase: sans développement supplémentaire, la création de liens physiques serait irréversible (aucune commande en cours ne pouvant gérer la suppression sans être incohérente avec le comportement actuel).

Si nous autorisons plus de développement à gérer le cas, le nombre de pièges et le risque de perte de données si vous ne connaissez pas suffisamment le fonctionnement du système, un tel développement implique, est à mon humble avis un motif suffisant pour restreindre la liaison en dur aux répertoires.

Pierre-Olivier Vares
la source
Cela ne devrait pas être un problème. Avec votre cas, lorsque nous créons un lien dur vers dir2, nous devons créer un lien dur vers tout le contenu de dir1. Ainsi, si nous renommons ou supprimons dir2, seul un lien supplémentaire vers l’inode est supprimé. Et cela ne devrait pas affecter dir1 et son contenu car il existe au moins un lien (dir1) vers l'inode.
Kannan Mohan
3
Votre argument est incorrect. Vous voudriez simplement le dissocier, pas faire rm -rf. Et si le nombre de liens atteint 0, le système saura qu'il peut également supprimer tout le contenu.
LtWorf
C'est plus ou moins tout ce rmqui est en dessous de toute façon (dissocier). Voir: unix.stackexchange.com/questions/151951/… Ce n’est vraiment pas un problème, pas plus qu’il ne l’est avec les fichiers à liens fixes . La suppression de la liaison supprime simplement la référence nommée et décrémente le nombre de liens. Le fait de rmdirne pas supprimer les répertoires non vides n'a aucune importance - cela ne le ferait pas non dir1 plus. Les liens physiques ne sont pas des copies de données, mais le même fichier. Par conséquent, le fait de "supprimer" le fichier dir2 effacerait la liste des répertoires de dir1. Vous auriez toujours besoin de dissocier.
BryKKan
Vous ne pouvez pas simplement le dissocier comme un fichier normal, car rmdans un répertoire , ne le dissociez pas s'il n'est pas vide. Voir Modifier.
Pierre-Olivier Vares le
1

C'est une bonne explication. En ce qui concerne "Lequel des parents multiples devrait .. pointer du doigt?" Une solution serait qu'un processus conserve son chemin wd complet, sous forme d'inodes ou de chaînes. les inodes seraient plus robustes puisque les noms peuvent être changés. Au moins dans les temps anciens, il y avait un inode en cœur pour chaque fichier ouvert qui était incrémenté chaque fois qu'un fichier était ouvert, décrémenté lors de sa fermeture. Quand il atteindra zéro, le stockage indiqué sera libéré. Lorsque le fichier n'est plus ouvert par personne, il est abandonné. Cela conserverait le chemin comme valide si un autre processus déplaçait un répertoire dans un autre répertoire alors que le sous-répertoire se trouvait dans le chemin d'un autre processus. Semblable à la façon dont vous pouvez supprimer un fichier ouvert mais il est simplement supprimé du répertoire,

Auparavant, les répertoires de liaison en dur étaient librement autorisés dans UNIX des Bell Labs, au moins V6 et V7, je ne sais pas pour Berkeley ou pour une version ultérieure. Aucun drapeau requis. Pourriez-vous faire des boucles? Oui, ne fais pas ça. Ce que vous faites si vous faites une boucle est très clair. Nether devrait vous entraîner à nouer autour de votre cou pendant que vous attendez votre tour pour sauter en parachute hors de l’avion si vous avez l’autre extrémité accrochée à un crochet sur votre tête.

Ce que j’espérais en faire aujourd’hui, c’était de lier durablement mon domicile à mon domicile pour que je puisse avoir / home / administ disponible, que / home soit masqué ou non par un automout sur mon domicile, ce dernier ayant un lien symbolique nommé administ to / lhome / administ. Cela me permet d’avoir un compte administratif qui fonctionne quel que soit l’état de mon système de fichiers hôte principal. C'EST une expérience pour Linux, mais je pense appris à la fois pour les SunOS à base UCB qui sont faites au automount niveau de chaîne de caractères ASCII. Il est difficile de voir comment ils pourraient être réalisés autrement en tant que couche au-dessus de tout service extérieur arbitraire.

Je lis ailleurs que. et .. ne sont plus des fichiers dans le répertoire non plus. Je suis convaincu que tout cela a de bonnes raisons et qu'une grande partie de ce que nous apprécions (par exemple, être capable de monter des NTFS) est possible grâce à de telles choses, mais une partie de l'élégance d'UNIX réside dans sa mise en œuvre. Ce sont les avantages tels que la généralité et la malléabilité fournis par cette élégance qui lui ont permis d’être si robustes et d’être durables pendant quatre décennies. Au fur et à mesure que nous perdons les élégantes implémentations, il deviendra éventuellement comme Windows (j'espère me tromper!). Quelqu'un créerait alors un nouveau système d'exploitation basé sur des principes élégants. Quelque chose à quoi penser. Peut-être que je me trompe, je ne suis pas (évidemment) au courant de la mise en œuvre actuelle. il est C'est incroyable de voir à quel point 30 ans de compréhension sont applicables à Linux ... la plupart du temps!

utilisateur57607
la source
Je pense que, si je peux me tromper, que .et ..ne sont pas dans le fichier-liens durs système, pour les systèmes de fichiers modernes. Cependant, le pilote du système de fichiers les imite. Ce sont ces systèmes de fichiers qui bloquent les répertoires de liens. Pour les anciens systèmes de fichiers, c'était possible (mais dangereux). Pour faire ce que vous essayez, regardez mount --bind, voyez mount --make…et peut-être aussi des conteneurs.
ctrl-alt-delor
0

D'après ce que je comprends, la raison principale est qu'il est utile de pouvoir modifier les noms de répertoire sans gâcher les programmes en cours d'exécution qui utilisent leur répertoire de travail pour référencer d'autres fichiers. Supposons que vous utilisiez Wine pour exécuter ~/.newwineprefix/drive_c/Program Files/Firefox/Firefox.exeet que vous vouliez déplacer le préfixe entier vers ~/.wine. Si pour une raison étrange, Firefox accédait drive_c/windowsen se référant à ../../windows, le changement de nom ~/.newwineprefixinterrompt les implémentations de ..cette trace du répertoire parent en tant que chaîne de texte au lieu d'un inode.

Stocker l'inode d'un seul répertoire parent doit être plus simple que d'essayer de garder trace de chaque chemin en tant que chaîne de texte et série d'inodes.

Une autre raison est que les applications défectueuses peuvent créer des boucles. Les applications comportantes doivent pouvoir vérifier si l'inode du répertoire qui est déplacé est le même que celui de l'un des répertoires imbriqués dans lesquels il est déplacé, tout comme vous ne pouvez pas déplacer un répertoire vers lui-même, mais cela pourrait ne pas être appliqué au niveau du système de fichiers.

Une autre raison encore pourrait être que si vous pouviez créer des liens physiques, vous voudriez éviter de créer des liens physiques qui ne pourraient pas être modifiés. finda des considérations de sécurité car il est utilisé pour effacer les fichiers créés par d'autres utilisateurs des répertoires temporaires, ce qui peut poser problème si un utilisateur bascule un répertoire réel pour un lien symbolique alors qu'il findappelle une autre commande. Pouvoir relier en dur des répertoires importants obligerait un administrateur à ajouter des tests supplémentaires findpour éviter de les affecter. (Ok, vous ne pouvez déjà pas faire cela pour les fichiers, donc cette raison est invalide.)

Une autre raison encore est que le stockage de l'inode du répertoire parent peut fournir une redondance supplémentaire en cas de corruption ou de dommage du système de fichiers. Si vous souhaitez ..répertorier tous les répertoires parents ayant un lien physique vers celui-ci, un parent différent et arbitraire pourrait donc être facilement trouvé si le répertoire actuel est dissocié. le système de fichiers stocke et utilise les inodes. Avoir des programmes traitant les chemins comme une série (unique pour chaque lien physique) d'inodes de répertoire éviterait cela, mais vous ne pourriez pas obtenir la redondance en cas de dommage du système de fichiers.

Misaki
la source