2010-02-23 15 views
8

En la falla del servidor, How to list symbolic link chains? (no es mi pregunta) se refiere a enumerar todos los enlaces simbólicos y seguirlos. Para hacer esto factible, consideremos un solo directorio al principio.¿Cómo puedo representar los enlaces simbólicos de un sistema de archivos en un hash Perl?

Quiero escribir un corto utilidad que hace esto. Parece fácil poner pares de enlaces simbólicos en un hash y luego procesar el hash.

Pero entonces yo podría tener algo como:

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 

donde es obvio que a->b->c es un bucle, y que los puntos trampa en un bucle, pero para saber x puntos en un bucle que necesita seguir una poco.

Una representación hash es:

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

Pero la representación inversa es mejor para el marcado de los bucles a los malos puntos de partida, una vez que sepa lo que los bucles son.

Así que aquí hay algunas preguntas:

  • es un hash de la mejor estructura para representar los enlaces simbólicos?
  • ¿Cuál es la mejor manera de separar el gráfico del sistema de archivos para contar los componentes con bucles de los componentes del árbol a la rama con un tipo de bucle?
  • ¿Hay un algoritmo mejor que la búsqueda manual de todos los bucles desde todos los puntos de partida?
  • Desde una perspectiva de teoría de gráficos, ¿ya está este tipo de cosas en el CPAN? Si no, ¿cuáles son algunos buenos módulos de ayuda?
+0

El envío del código de muestra para resolver el problema obviamente también se recomienda. – Paul

+0

Mostrarnos lo que has intentado hasta ahora también se recomienda. :) –

+0

@brian Doh! Vi esto principalmente como el problema claro de otra persona, y no intenté resolverlo más allá de reconocer algunas de las trampas. – Paul

Respuesta

7

Hay un módulo de Graph en CPAN que se pudiera utilizar como en el siguiente:

#! /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"; 
} 

Por ejemplo, en un directorio similar en estructura a la que en su pregunta, la salida es

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

Gracias por publicar esto. Tengo la intención de mirar Graph para otras necesidades que tengo, y repasar este tipo de cosas. – Paul

+0

@Paul ¡De nada! Me alegra que lo hayas encontrado beneficioso. –

2

Eche un vistazo al módulo CPAN File::Spec::Link. El método de resolución dice que atraviesa un enlace repetidamente para encontrar el destino vinculado.

El método de determinación del módulo tiene esto que decir:

determinación (enlace $)
    Devuelve el enlace en última instancia no vinculado a por $ enlace, por varias ocasiones llamando vinculado. Devuelve undef si el enlace no se puede resolver

Había utilizado este módulo para encontrar un objetivo de enlace simbólico cuyo objetivo era a su vez un enlace simbólico, etc. Pero no estoy seguro si esto detecta los enlaces simbólicos cíclicos.

-1

Necesita almacenar más que solo el nombre del enlace. O agarra el número de inodo (si tu FS lo admite) o algún otro aspecto único.Si no existe, considere crear la suya propia, tal vez mediante la suma de comprobación de la fecha del nombre/crear/última modificación. De cualquier manera, necesita alguna forma de identificar de manera única cada enlace. He visto algunas utilidades que simplemente limitan el número de enlaces (entre 8 y 255) y declaran que todo lo que exceda este límite es un bucle, pero siempre lo consideré como "tomar la salida más barata". :)

Cuestiones relacionadas