OK, depois de pensar um pouco mais, acho que tenho uma solução clara.
O insight crítico é que, se cada link que faz parte de um caminho for resolvido para algo, o caminho inteiro será resolvido. Ou, ao contrário, se um caminho não for resolvido, deve haver um link simbólico específico que exija a travessia que não resolve.
Enquanto pensava sobre este problema anteriormente, eu estava usando um algoritmo que percorria elementos de um caminho a partir da raiz, e quando ele encontrou um symlink, ele substituiu o elemento path pelo conteúdo do symlink e continuou a travessia. Como essa abordagem não lembra qual link simbólico está resolvendo no momento, ela não pode detectar quando está em um loop não-resolvedor.
Se o algoritmo acompanhar qual link simbólico está resolvendo atualmente (ou quais links simbólicos no caso de links recursivos), ele pode detectar se está tentando resolver um link novamente de forma recursiva, o que ainda está ocupado resolvendo.
Algoritmo:
initialize 'location' to the current working directory
initialize 'link_contents' to the path we want to resolve
initialize 'active_symlinks' to the empty set
def resolve_symlink(location, link_contents, active_symlinks) :
loop forever:
next_location = location / [first element of link_contents]
see if next_location is a symlink.
if so:
if next_location in active_symlinks: abort, we have a loop
location = resolve_symlink(location, readlink(next_location), active_symlinks ∪ {next_location})
else:
location = next_location
strip first element of link_contents
if link_contents is empty:
return location
editar :
Eu tenho uma implementação funcional em Python no link .