Como os programas idiomáticos do Unix detectam em qual prefixo eles estão instalados?

5

Se eu instalar um binário com prefixo não padrão, por exemplo /opt/bin/foo , que precisa de alguns arquivos estáticos de /opt/share/foo , como eles são encontrados? Usando referências anteriores em relação ao executável ( ../share/foo )? Codificado em tempo de compilação?

Qual é a maneira idiomática para um aplicativo manipular o prefixo de instalação de variáveis? Todos os diretórios devem ser prefixados? (e quanto a /var ?)

    
por Alex B 19.01.2011 / 00:11

5 respostas

7

É comum codificar essas referências em tempo de compilação e, talvez, fornecer uma opção de linha de comando ou variável de ambiente para substituir o padrão de tempo de compilação. Muitas vezes o programa apenas lembra a localização de um arquivo de configuração (normalmente sob /etc ) onde qualquer padrão de tempo de compilação pode ser substituído. Esta abordagem faz mais sentido para o software de código aberto que é compilado pelas mesmas pessoas que fazem o sistema operacional, como parte de uma distribuição Linux ou portas BSD.

Para aplicativos distribuídos em uma forma binária, a abordagem usual é localizar o binário do aplicativo a partir de seu argumento zero. Por convenção, o argumento zeroth para execve (ou seja, argv[0] ) é o caminho para o binário (cabe ao chamador, geralmente um shell, respeitar a convenção). Se argv[0] não contiver / , o aplicativo deverá realizar $PATH de pesquisa.

    
por 19.01.2011 / 01:14
3

Eu diria que o mais comum é detectar o caminho fornecido por --prefix . Caminhos diferentes podem ser fornecidos por prefixos diferentes e há separado para configuração do sistema (" /etc "), diretório da biblioteca (" /usr/lib ") etc. em autotools

    
por 19.01.2011 / 00:31
3

As ferramentas usadas para compilar o programa, como o GNU Autotools, podem pegar o valor da opção --prefix e colocá-lo em um arquivo de cabeçalho como definição.

#define PREFIX "/usr/local/"

E no seu código, você usaria apenas PREFIX como parte dos nomes dos seus caminhos.

    
por 19.01.2011 / 15:15
2

Há também a função dladdr() na libc, que retorna o caminho para o binário no qual o dado ponteiro de função existe, mas:

  • Ele existe apenas no Linux e no SunOS, de acordo com a página do manual.
  • Você precisa compilar os executáveis com -rdynamic para que ele funcione. Eu não acho que as bibliotecas precisem disso.

Para uma biblioteca, suas opções são muito mais limitadas: não há argv[0] , portanto, suas opções são dladdr() ou o obscuro hack da análise manual do /proc/self/maps somente para Linux e procurando o intervalo de endereço de memória que contém o endereço de memória de algum símbolo interno da biblioteca (por exemplo, um ponteiro de função ou uma variável estática).

Outras soluções que vi em estado selvagem:

  • ./configure --prefix=SOME_UNIQUE_VERY_LONG_STRING , em seguida, na hora da instalação, pesquise e substitua essa cadeia longa no binário (!!) com /path/to/actual/install/prefix/suffixed/by/enough/slashes////// e espere que o usuário nunca renomeie nada nesse caminho.
  • Virtualize o sistema de arquivos, seja por chroot() , montagem em loop, sistema de arquivos FUSE, libck hackeado (projeto Plash), máquina virtual, etc.
  • ./configure --prefix=.. e nunca chamará chdir() . Isso também quebrará as coisas se algum caminho vazar para fora do aplicativo e for para outro aplicativo, já que o outro aplicativo não poderá resolver corretamente o caminho relativo.
  • Inicialize por meio de um wrapper. Por exemplo. Aplicativos Java sempre conhecem seu caminho via getClass().getProtectionDomain().getCodeSource().getLocation() , C # tem Application.StartupPath entre outros, a maioria das linguagens de script tem alguma forma.

O POSIX deve realmente padronizar dladdr() .

    
por 12.04.2011 / 16:56
1

Unded Unix, não há maneira portátil de detectar de qual local o binário foi iniciado, ou seja, um prefixo de instalação variável é compilado.

    
por 19.01.2011 / 00:24