2010-02-23 16 views
8

Sur Server Fault, How to list symbolic link chains? (pas ma question) parle de lister tous les liens symboliques et de les suivre. Pour rendre cela faisable, considérons un seul répertoire au début.Comment représenter les liens symboliques d'un système de fichiers dans un hachage Perl?

Je veux écrire un utilitaire court qui fait cela. Il semble facile de mettre des paires de liens symboliques dans un hachage, puis de traiter le hachage.

Mais alors je pourrais avoir quelque chose comme:

ls -l 
total 0 
lrwxrwxrwx 1 pjb pjb 1 2010-02-23 08:48 a -> b 
lrwxrwxrwx 1 pjb pjb 1 2010-02-23 08:48 b -> c 
lrwxrwxrwx 1 pjb pjb 1 2010-02-23 09:03 c -> a 
lrwxrwxrwx 1 pjb pjb 1 2010-02-23 09:17 trap -> b 
lrwxrwxrwx 1 pjb pjb 1 2010-02-23 09:17 x -> y 
lrwxrwxrwx 1 pjb pjb 1 2010-02-23 09:17 y -> b 

où il est évident que a->b->c est une boucle, et que les points de piège dans une boucle, mais de savoir x des points dans une boucle je suivre un bit.

Une représentation de hachage est:

a => b 
b => c 
c => a 
trap => b 
x => y 
y => b 

Mais la représentation inverse est mieux pour marquer des boucles de mauvais points de départ, une fois que je sais ce que les boucles sont.

Alors, voici quelques questions:

  • est un hachage de la meilleure structure pour représenter les liens symboliques? Quelle est la meilleure façon de séparer le graphe du système de fichiers pour indiquer les composants bouclés des composants de l'arbre à la brindille avec une pièce de type boucle?
  • Existe-t-il un meilleur algorithme que la recherche manuelle de toutes les boucles à partir de tous les points de départ?
  • D'un point de vue de la théorie des graphes - est ce genre de chose dans le CPAN déjà? Si non, quels sont les bons modules d'aide?
+0

La soumission de l'exemple de code pour résoudre le problème est évidemment également encouragée. – Paul

+0

La présentation de ce que vous avez essayé jusqu'ici est également encouragée. :) –

+0

@brian Doh! J'ai vu cela surtout comme le problème de quelqu'un d'autre, et je n'ai pas essayé de le résoudre au-delà de reconnaître certains des pièges. – Paul

Répondre

7

Il y a un module Graph sur CPAN que vous pouvez utiliser comme dans les domaines suivants:

#! /usr/bin/perl 

use warnings; 
use strict; 

use Graph; 

my $g = Graph->new; 
my $dir = @ARGV ? shift : "."; 

opendir my $dh, $dir or die "$0: opendir $dir: $!"; 
while (defined(my $name = readdir $dh)) { 
    my $path = $dir . "/" . $name; 

    if (-l $path) { 
    my $dest = readlink $path; 
    die "$0: readlink $path: $!" unless defined $dest; 

    $g->add_edge($name => $dest); 
    } 
    else { 
    $g->add_vertex($name); 
    } 
} 

my @cycle = $g->find_a_cycle; 
if (@cycle) { 
    $" = ' -> '; #" # highlighting error 
    print "$0: $dir: at least one cycle: @cycle\n"; 
} 
else { 
    print "$0: $dir: no cycles\n"; 
} 

Par exemple, dans un répertoire structure similaire à celle de votre question, la sortie est

$ ../has-cycle 
../has-cycle: .: at least one cycle: c -> a -> b
+0

Merci d'avoir posté ce message. J'ai l'intention de regarder Graph pour d'autres besoins que j'ai, et pour rafraîchir ce genre de choses. – Paul

+0

@Paul De rien! Je suis content que vous l'ayez trouvé bénéfique. –

2

Regardez le module CPAN File::Spec::Link. La méthode de résolution indique qu'elle parcourt plusieurs fois un lien pour trouver la cible liée.

La méthode de détermination du module a ceci à dire:

détermination ($ link)
    Renvoie la non-lien en fin de compte lié par lien $, par chaque appel successif lié. Renvoie undef si le lien ne peut pas être résolu

J'avais utilisé ce module pour trouver une cible de lien symbolique dont la cible était à son tour un lien symbolique et ainsi de suite. Mais je ne suis pas sûr si cela détecte les liens symboliques cycliques.

-1

Vous devez stocker plus que le nom du lien. Saisissez le numéro d'inode (si votre FS le prend en charge) ou un autre aspect unique.Si tel n'est pas le cas, envisagez de créer le vôtre, peut-être en cochant le nom/create/last-modified date. De toute façon, vous avez besoin d'un moyen d'identifier de manière unique chaque lien. J'ai vu des utilitaires qui limitent simplement le nombre de liens (entre 8 et 255) et déclarent que tout ce qui dépasse cette limite est une boucle, mais j'ai toujours considéré cela comme une «sortie à bas prix». :)