9
votes

Réursion d'annuaire et symboles

Si vous traversez récursivement une arborescence de répertoire par la méthode évidente, vous rencontrez des problèmes avec une récursion infinie lorsqu'un lien symbolique pointe vers un répertoire parent.

Une solution évidente serait de vérifier simplement des liens symboliques et de ne pas les suivre du tout. Mais cela pourrait être une surprise désagréable pour un utilisateur qui ne s'attend pas à ce qui se comporte à d'autres fins, comme un répertoire parfaitement normal d'être ignoré silencieusement.

Une solution alternative peut être de garder une table de hachage de tous les annuaires visités jusqu'à présent et d'utiliser ceci pour vérifier les boucles. Mais cela nécessiterait qu'il y aurait une représentation canonique, d'une manière à obtenir l'identité, de l'annuaire que vous examinez actuellement (quel que soit le chemin que vous avez atteint).

Les utilisateurs UNIX seraient généralement généralement la deuxième solution comme moins surprenante?

Si tel est-ce, est-il un moyen d'obtenir une telle représentation / identité canonique d'un répertoire, qui est portable sur des systèmes UNIX? (J'aimerais que cela fonctionne à travers Linux, BSD, Mac OS, Solaris, etc. Je m'attends à avoir à écrire du code séparé pour Windows.)


0 commentaires

6 Réponses :


1
votes

Puisque vous n'avez pas spécifié quelle langue vous travaillez avec (le cas échéant), nous allons commencer avec le shell: si vous êtes sur un système GNU readlink , utilisez simplement le code < > readlink -f canoniser il.

Si vous êtes sur un Mac (qui a un non-gnu readlink qui se comporte différemment), voir Comment puis-je obtenir le comportement de GNU's Readlink -F sur un Mac? pour le chemin d'accomplissement même tâche.

L'autre option consiste à utiliser des ID d'inode pour suivre des fichiers uniques (via stat ou similaire), mais cela nécessitera d'abord tous les symboles de toute façon (puisque les symboles eux-mêmes ont leur propre unique. ID INODE), et le moyen le plus simple de suivre tous les symboles de symboles est, eh bien, readlink .


Alternativement, de nombreuses langues de programmation ont des liaisons à la fonction POSIX REALPATH , qui effectue essentiellement la même fonction que readlink -f (mais comme un appel de bibliothèque). Par exemple, Python a OS.PATH.REALPATH ( ) , C a comme fonction de stdlib.h , et cetera.

Si vous travaillez déjà dans une langue qui a une telle fonction, l'utilisation est fortement recommandée, car vous obtiendrez souvent une compatibilité multiplate-forme gratuitement (en supposant que votre langue est multiplate-forme).


0 commentaires

3
votes

Le chemin absolu de l'annuaire est une telle représentation. Vous pouvez l'obtenir avec la fonction realpath , qui est définie dans la norme POSIX, de sorte qu'il fonctionnera sur n'importe quel système compatible POSIX. Voir Man 3 RealPath .


0 commentaires

2
votes

Non seulement les symboles, mais aussi des liens matériels aussi. Pas très commun, mais pas interdit. (Seule les répertoires de la racine peuvent La seule chose qui est canonique est {Nombre de périphériques, inode_number}. Mais les systèmes de fichiers réseau peuvent mal se conduire mal.


0 commentaires

2
votes

Ce problème de fichiers identiques doit être résolu par de nombreuses applications, par exemple un vérificateur pour les doublées de fichier (contenus indiciels, noms différents) et utilitaires agissant sur des hiérarchies de l'ensemble du répertoire, telles que goudron

Une bonne implémentation ne voudrait pas donner de faux positifs pour des fichiers liés durs et des fichiers symboliques, soit par le biais de symboles aux répertoires parentes, soit à des fichiers.

L'approche la plus portable pour résoudre est d'identifier des fichiers en regardant les fonctions STAT / FSTAT POSIX et la statistique structure Ils remplissent avec st_dev et st_ino membres. Une mise en œuvre réelle mondiale d'un fichier de dape de fichier en C Utilisation de cette stratégie est Samefile (une implémentation différente de laquelle Était une entrée gagnante du 1998 IOCCC : -)


0 commentaires

3
votes

L'API la plus fréquemment ignorée dans ce champ serait

NFTW

NFTW a des options pour éviter de passer des symboles traversants. Il a des capacités beaucoup plus avancées que cela. Voici un échantillon simple de la page d'homme elle-même: xxx

Voir aussi


2 commentaires

La page d'homme pour NFTW dit d'utiliser les fonctions FTS à la place, qui sont également disponibles sur Linux et BSD (MacOS) et fonctionnent plus efficacement. Voir aussi ma réponse ci-dessous (qui ne fournit pas plus d'informations, cependant)


Merci @thomastempelmann pour avoir ajouté de la perspective. Je n'utilise jamais réellement cette fonction dans la pratique (je suppose que je pourrais dans un programme "rapide" qui devait être dans C. J'ai fait une fois une question d'entretien avec elle :)). Il est bon de relire les pages d'homme lors de la réutilisation des extraits après 10 ans!



2
votes

Il y a aussi la fonction Linux / BSD FTS_OPEN () .

Il vous donne un itérateur facile à utiliser pour parcourir tous les contenus de sous-répertoires tout en détectant de telles récursions symboliques.

En fait, la page man (sur MacOS) pour NFTW dit que c'est une ancienne fonction qui est maintenant remplacée par l'API FTS que je mentionne ici:

Ces fonctions sont fournies pour la compatibilité avec le code hérité. Le nouveau code doit utiliser les fonctions FTS (3).


0 commentaires