Elmord's Magic Valley

Computers, languages, and computer languages. Às vezes em Português, sometimes in English.

Posts com a tag: unix

Busybox e ssh no Android

2012-07-17 14:15 -0300. Tags: comp, unix, android, em-portugues

Há umas três semanas comecei a usar um smartphone. É um ótimo aparelho, até que se tenha que usá-lo como celular.

De qualquer forma, uma das grandes vantagens do Android é que o sistema operacional por baixo de tudo é um Linux mais ou menos normal (sem GNU, todavia), e portanto é possível rodar praticamente qualquer coisa que rode em Linux/ARM em um smartphone com Android.

[Imagem de um smartphone rodando o ssh]
E se não fosse pelo teclado virtual, já teria instalado o Nethack.

As condições mínimas para diversão são um terminal e os utilitários padrão (ls, cp, grep, etc.). Existe um pacote pronto com um emulador de terminal, Busybox, e cliente e servidor de ssh e rsync. Infelizmente, esse pacote requer o Android 2.3 ou superior (no meu brinquedo, que vem com um Android 2.2, ele inicia o terminal, dá três vibradas seguidas e congela). É possível, entretanto, obter as partes separadamente elsewhere e juntá-las.

O emulador de terminal pode ser encontrado no Android Market, mas se você é pagão e não tem conta no Google, pode obtê-lo diretamente da forja. A instalação é trivial e deixada como exercício para o leitor.

Tendo o terminal, podemos instalar o Busybox. Encontrei binários pré-compilados do Busybox para o Android neste site super-confiável. Esse binário deverá ser colocado na memória principal do aparelho, já que aparentemente o Android não dá permissão de execução a binários no /sdcard por padrão. Para tanto, você deverá se tornar root do mal, o que exige um equipamento rooteado. Obtive meu smartphone de segunda mão, e ele já veio rooteado, mas guias de como rootear não faltam. Assumindo um aparelho já rooteado:

  1. Abra o Terminal Emulator.
  2. Digite su. Talvez o sistema apresente uma janelinha pedindo confirmação para fornecer direitos de root ao su.
  3. mkdir /data/busybox
  4. mv /sdcard/onde-quer-que-você-tenha-baixado-o-busybox /data/busybox/busybox
  5. cd /data/busybox
  6. chmod 755 busybox
  7. Crie os links com os nomes dos utilitários padrão para o busybox. Em tese, ./busybox --install deveria fazer isso, mas para mim não funcionou. ./busybox --list aparentemente também não existe nessa versão do Busybox, então tive que apelar para a seguinte treta:
    for i in $(./busybox | ./busybox sed -n 's/,//gp' | ./busybox sed 1d); do ln -s busybox $i; done
  8. Pressione a tecla de menu, e selecione as Preferences do Terminal Emulator.
  9. Ajuste Initial command para: export PATH="/data/local/bin:/data/busybox:/data/dropbear:$PATH"
  10. Ajuste Command line para: /data/busybox/sh -

Pronto! A partir de agora, quando você iniciar o terminal, o Busybox abrirá automaticamente, e os comandos nele contidos estarão disponíveis.

Por último, instalemos o Dropbear, um cliente/servidor de ssh más pequeño del mundo. Os binários podem ser obtidos aqui (link no final do post). Baixe-o e faça o seguinte:

  1. Abra o Terminal Emulator.
  2. su
  3. cd /data
  4. mkdir dropbear
  5. cd dropbear
  6. unzip /sdcard/onde-quer-que-você-tenha-baixado-o-dropbear.zip
  7. chmod 755 *

E está feito! Agora você já pode derrubar a Internet de onde quer que você esteja.

1 comentário / comment

Rodando o VLC como root

2012-06-02 10:41 -0300. Tags: comp, unix, mundane, em-portugues

Por padrão, ao ser executado como root, o VLC prestativamente imprime a seguinte mensagem:

VLC is not supposed to be run as root. Sorry.
If you need to use real-time priorities and/or privileged TCP ports
you can use vlc-wrapper (make sure it is Set-UID root and
cannot be run by non-trusted users first).

"Sorry, Dave. I'm afraid you can't do that."

Há duas soluções para esse problema. A solução limpa é recompilar o VLC passando --enable-run-as-root para o ./configure. A solução suja é a sacada genial desse cara: substituir na mão a chamada de geteuid por getppid no binário do VLC. A idéia por trás disso é que os nomes geteuid e getppid têm o mesmo tamanho, e portanto é possível sobrescrever um com o outro no binário sem alterar as posições das coisas no resto do arquivo. geteuid retorna o UID efetivo do processo, que é 0 para o root. getppid retorna o PID do processo pai do processo atual, que nunca é zero, exceto para o /sbin/init [citation needed]. A treta é enganar o VLC fazendo-o pensar que o UID do processo atual é um número qualquer diferente de zero. O artigo original usa o Vim para isso, mas qualquer editor que não estrague binários serve – inclusive o sed sem locale Unicode:

# LC_ALL=C sed 's/geteuid/getppid/g' /usr/bin/vlc >/usr/bin/vlc-hacked
# chmod 755 /usr/bin/vlc-hacked

Pronto! Agora você tem um vlc-hacked, que aceita rodar como root. Você pode apagar/mover o vlc original e colocar o vlc-hacked no lugar, mas eu não recomendaria; melhor que para rodar o vlc como root você tenha que expressar explicitamente o desejo chamando o binário alternativo.

Caveat: Procurando por soluções para esse problema, encontrei um camarada dizendo que o VLC tem mil falhas de segurança, permitindo inclusive a execução de código arbitrário dependendo da fase da lua. (O que eu concluo dessa afirmação é que eu não deveria rodar o VLC at all, mas enfim.) Use por sua conta e risco.

Comentários / Comments

Mandando o processador/fan se acalmar

2012-05-12 01:03 -0300. Tags: comp, unix, mundane, em-portugues

Antes de destruir a máquina à minha frente e morrer de desgosto, compartilho com vocês o que eu descobri tentando fazer o cooler do PC parar de fazer barulho de espremedor de laranja.

Algumas máquinas permitem controlar a velocidade do fan, por meio dos arquivos pwm1 e pwm1_enable nos diretórios/sys/class/hwmon/hwmon*. echo 1 >pwm1_enable habilita o controle do fan por software (ao invés de deixar o firmware trabalhar sozinho), e echo N >pwm1, onde N costuma ser um valor entre 0 e 255, controla a velocidade do fan. No EeePC, a configuração funcionava temporariamente até o firmware resolver que era melhor que o OS e ligar o fan de novo; para desligar o fan, era necessário então setá-lo de novo para a velocidade máxima e de volta para zero (ou o valor que se quisesse; o EeePC só tinha o modo "ligado" e "desligado" por software, entretanto). Os arquivos se chamavam fan1 e fan1_enable no kernel 2.6.159265358979 e anteriores.

Outras máquinas não têm suporte ao PWM, mas possuem alguns controles interessantes nos diretórios /sys/class/thermal/cooling_device*. Cada um desses diretórios contém, entre outros, os arquivos: type, que diz o tipo do dispositivo em questão; cur_state, o estado atual do dispositivo; e max_state, o valor máximo que o estado pode assumir. Na máquina que estou usando agora (um Toshiba Satellite de uns cinco ou seis anos atrás), aparecem cinco dispositivos dos seguintes tipos:

# grep '' /sys/class/thermal/cooling_device*/type
/sys/class/thermal/cooling_device0/type:Processor
/sys/class/thermal/cooling_device1/type:Processor
/sys/class/thermal/cooling_device2/type:Fan
/sys/class/thermal/cooling_device3/type:LCD
/sys/class/thermal/cooling_device4/type:LCD

Você pode dar echo N >/sys/class/thermal/cooling_devicex/cur_state para alterar o estado do dispositivo.

Nesta máquina, o estado do fan fica sempre em 1 (ligado), e o valor não pode ser alterado. Os processadores/cores, porém, possuem um estado padrão 0 e um valor máximo 7; alterando esse valor, os processadores diminuem de velocidade, conseqüentemente aquecendo menos (e possivelmente gastando menos bateria, mas não cheguei a testar). Com um core desativado e o outro no estado máximo de economia, a máquina levou uns dez minutos para subir a temperatura (verificável em /sys/class/hwmon/hwmon*/temp*_input) de 50 a 80 graus (versus um minuto com dois cores no estado normal).

Outra regulagem de freqüência que pode ser feita independentemente é através do cpufreq. cpufreq-info mostra a freqüência atual e a "política de freqüência" em vigor. As configurações podem ser alteradas com cpufreq-set: cpufreq-set -c 0 -u 1G seta a velocidade máxima do core 0 para 1GHz, por exemplo. (Cada modelo de processador aceita apenas certos valores de freqüência; este aqui, por exemplo, aceita 1GHz, 1.33GHz e 1.66GHz. O cpufreq seleciona o valor mais próximo que satisfaz o limite de velocidade especificado, ou retorna um erro.)

Mais uma coisa: é possível desligar um core executando echo 0 >/sys/devices/system/cpu/cpuN/online (e reativá-lo trocando 0 por 1). Não testei o que acontece mandando desligar todos.

Se sua máquina é capaz de ligar e desligar o fan, o que você pode fazer é criar um script para ligar o fan sempre que a temperatura passar de um certo limite (e.g., 80 graus) e desligá-lo quando ela voltar a uma temperatura baixa (e.g., 50 graus). Assim, você só vai ter que ouvir o fan de vez em quando. Na verdade, aparentemente existe um pacote chamado fancontrol que faz basicamente isso. Aqui, entretanto, o fan tem vontade própria e escolhe a velocidade que quer; para pará-lo, tive que impedi-lo de girar. A máquina esquenta igual, apenas mais devagar, com as configurações alteradas, o que não me resolve nada. Obviously it is Allah's will that I throw the Unix box out the window. I submit to the will of Allah.

P.S.: Não, o Unix não tem nada que ver com o problema.

P.P.S.: Aparentemente leitores prospectivos do blog esperam alguma coisa mais interessante da tag mundane. Ela apenas marca os posts sobre "arrumar PC" (i.e., o que sua família pensa que você faz quando diz que estuda Ciência da Computação) e resolução de problemas de mortal (por oposição aos posts sobre programação, por exemplo). Além disso, há uma tag mundane e uma worldly, completamente não-relacionadas, embora as palavras sejam sinônimos. There are no rules anywhere. The Goddess Prevails.

Comentários / Comments

The art of the prompt string

2012-05-06 03:49 -0300. Tags: comp, unix, bash, em-portugues

Ofereço este post com conteúdo útil como sacrifício aos leitores, de modo a ter crédito para escrever posts reclamando da vida mais tarde.

O prompt padrão do bash na maior parte das distribuições de GNU/Linux costuma ser algo do tipo username@hostname diretório$ . Esse prompt pode ser customizado alterando-se o valor das variáveis PS1 ("prompt string 1") e companhia:

vitor@eukleides ~$ PS1='oi? '
oi? pwd
/home/vitor
oi? 

Você pode experimentar prompts diferentes alterando essa variável até achar um que seja do seu agrado, e então alterar um dos arquivos de configuração do bash (e.g., ~/.bashrc) para setar a variável para o valor desejado na inicialização do shell.

Backslash sequences

Como você pode imaginar, o conteúdo de PS1 não precisa ser texto estático. O bash substitui certas seqüências de \ seguido de um caractere (e.g., \u) na definição do prompt por valores específicos (e.g., o nome do usuário). O prompt padrão apresentado acima pode ser obtido pela string \u@\h \W\$ :

Uma lista completa das seqüências expandidas pelo bash no prompt pode ser obtida procurando por PROMPTING no manual (man bash). Outras seqüências úteis incluem \w (caminho completo do diretório atual) e \! (número do comando atual no histórico; útil para quem gosta de usar os comandos de recuperação do histórico, e.g., !42 para reexecutar o comando de número 42).

Escape sequences

Uma das maravilhas do terminal (que talvez seja digna de um post a respeito no futuro) são as escape sequences: seqüências de caracteres especiais que podem produzir toda sorte de firula, desde cores e outros efeitos de texto até alterações no título da janela de terminal. Por exemplo, a seqüência ESC [ 3 número m, onde ESC é o caractere ASCII número 27, seleciona a cor de texto com o número especificado (que varia de 0 a 7); a seqüência ESC [ 0 m retorna as cores e outros atributos para seus valores padrão. O caractere ESC pode ser representado no prompt pela seqüência \e. Assim:

PS1='\e[34m\u@\h \W\$ \e[0m'

lhe dará um prompt idêntico ao padrão, mas em azul. Existe uma manpage (man console_codes) com uma lista de seqüências ESC suportadas por diversos terminais.

Só tem um problema: o bash usa o tamanho da string de prompt expandida para calcular o tamanho que o prompt ocupa na tela; ele precisa dessa informação para determinar onde ocorre a quebra de linha, caso o comando digitado possua mais de uma linha, e para saber onde posicionar o cursor caso você tecle Home, entre outras coisas. O problema é que os caracteres de uma seqüência ESC não ocupam espaço na tela, mas aumentam o tamanho da prompt string. Para o bash poder calcular corretamente o tamanho do prompt, é necessário demarcar os trechos de seqüências ESC no prompt entre \[ e \]:

PS1='\[\e[34m\]u@\h \W\$ \[\e[0m\]'

Provavelmente a coisa mais útil que se costuma fazer com seqüências ESC no prompt é setar o título da janela de terminal para conter o diretório atual:

PS1='\[\e]0;\w\a\]\u@\h \W\$ '

ESC ] 0 ; título BEL é a seqüência que muda o título da janela do xterm e outros terminais gráficos. (BEL, representado no prompt por \a, é o caractere ASCII número 7; em situações normais, ele é o caractere que faz o terminal emitir um beep.)

Se você nem sempre acessa o terminal via interface gráfica, pode ser uma boa idéia testar se o terminal atual é gráfico antes de adicionar seqüências ESC no prompt:

case "$TERM" in
    xterm*|gnome*|konsole*) PS1='\[\e]0;\w\a\]\u@\h \W\$ ' ;;
    *) PS1='\u@\h \W\$ ' ;;
esac

Ou, alternativamente, para evitar duplicação:

# Primeiro adiciona a seqüência ESC.
case "$TERM" in
    xterm*|gnome*|konsole*) PS1='\[\e]0;\w\a\]' ;;
    *) PS1='' ;;
esac

# Depois, o resto do prompt (igual em ambos os casos).
PS1+='\u@\h \W\$ '

Variáveis

Além de backslash sequences, o bash substitui variáveis presentes na prompt string. Por exemplo, PS1='$USER@$HOSTNAME $PWD\$ ' tem mais ou menos o mesmo efeito que PS1='\u@\h \w\$ '. Ao se usar variáveis no prompt, é importante usar aspas simples em volta do valor que está sendo atribuído a PS1:

O bash também expande comandos (usando a sintaxe $(comando) ou `comando`) presentes na string de prompt. Novamente, é importante cuidar para usar aspas simples caso se queira que o comando execute toda vez que o prompt é impresso, e não apenas uma vez durante a definição do prompt. De modo geral, executar um comando (criar um processo) cada vez que o prompt é impresso não me parece uma boa idéia; normalmente, executar o comando uma vez só resolve a maior parte dos problemas e é menos custoso computacionalmente. (Se bem que hoje em dia criar um processo provavelmente não vai fazer uma diferença palpável na execução do shell ou do sistema; eu recomendaria não fazer isso com o prompt do root, entretanto. A gente nunca sabe quando vai ter que matar uma fork bomb ou um processo mal-comportado no sistema.)

Uma utilidade de usar variáveis e/ou comandos é incluir nome da tty atual no prompt. Isso é particularmente útil quando se está trabalhando no modo texto, pois pelo nome da tty sabe-se o número do console virtual (e lembrando o número pode-se rapidamente voltar para o console em questão teclando Alt-Fn).

tty="$(tty)"                # Recupera o nome completo da tty (e.g., /dev/tty1)
if [[ $tty == */pts/* ]]; then
    ttybase="pts${tty##*/}" # Transforma /dev/pts/0 em pts0
else
    ttybase="${tty##*/}"    # Transforma /dev/tty1 em tty1
fi

PS1='\u@$ttybase \W\$ '     # Usa o nome da tty ao invés do hostname.

Ganhamos o nome da tty, mas perdemos o hostname. Uma possibilidade é testar se a conexão atual é via ssh, e usar o hostname nesse caso:

tty="$(tty)"
if [[ $SSH_CONNECTION ]]; then
    ttybase="$HOSTNAME"
elif [[ $tty == */pts/* ]]; then
    ttybase="pts${tty##*/}"
else
    ttybase="${tty##*/}"
fi

PS1='\u@$ttybase \W\$ '

Outra informação útil de se incluir no prompt (uma que eu já não consigo viver sem, a ponto de alterar o prompt de outras máquinas quando vou usá-las por mais do que alguns minutos) é o exit status do último comando. O exit status é um valor ente 0 e 255 que cada processo retorna ao terminar. (É por isso que a main() retorna int, e não void, em C.) Por convenção, um programa retorna 0 se foi bem-sucedido, e um valor diferente de zero caso tenha ocorrido um erro (valores diferentes podem ser usados para erros diferentes). O exit status do último comando vive na pseudo-variável $?:

PS1='\u@$ttybase \W($?)\$ '

A presença do exit status no prompt é útil por mil razões. Primeiro, se você costuma escrever shell scripts, freqüentemente deseja saber que valor um comando retorna em certa situação. Além disso, o exit status presente no prompt dá um feedback imediato quanto ao sucesso ou falha do último comando, sem ter que ler toda a saída do comando. Por exemplo, ao copiar um diretório com muitos arquivos com cp -v, pode ser que uma mensagem de erro passe desapercebida no meio da saída normal do cp; com o exit status no prompt, o erro é imediatamente visível. Com o tempo, verificar o exit status é um ato inconsciente; para mim, hoje em dia, ele é um feedback tão importante quanto a saída do comando. Finalmente, existem alguns programas cretinos que não imprimem mensagens de erro, apenas retornam 1 para indicar que falharam. (Lamentavelmente, com o exit status no prompt, você possivelmente se sentirá inclinado a escrever programas que fazem o mesmo. Eu não tenho o direito de atirar pedras.)

The prompt command

A última maravilha promptística que tenho a apresentar é a variável PROMPT_COMMAND: se essa variável for setada, seu valor é interpretado como um comando a ser executado antes de imprimir o prompt. Você pode usá-la para chamar alguma função que seta uma variável usada na string do prompt.

Eis uma possibilidade: nos doces tempos do bash 1.14, o comportamento do \W era diferente: não havia abreviação do diretório home para ~; além disso, se o diretório estivesse diretamente abaixo do raiz (e.g., /mnt), o bash imprimia a / no início do nome, e não apenas mnt. O comportamento mudou no bash 2, e me foi a mi mui mal. Felizmente, é possível corrigir esse problema usando o PROMPT_COMMAND e uma variável no prompt:

reduced_pwd() {
    case "$PWD" in
        /*/*) REDPWD="${PWD##*/}" ;;
        *) REDPWD="$PWD" ;;
    esac
}

PROMPT_COMMAND="reduced_pwd"
PS1='\u@$ttybase $REDPWD($?)\$ '

Pode-se adaptar a reduced_pwd, com uma pequena dose de falcatrua, para mostrar os últimos dois itens do diretório atual, ao invés do caminho completo ou do último item:

reduced_pwd() {
    local prefix
    case "$PWD" in
        /*/*/*)
            # Se PWD = /mnt/foo/bar/baz/quux:
            prefix="${PWD%/*/*}"        # prefix = /mnt/foo/bar
            REDPWD="${PWD#"$prefix"/}"  # REDPWD = baz/quux
            ;;
        *)
            REDPWD="$PWD"
            ;;
    esac
}

Pode-se obter a temperatura da CPU, ou a carga da bateria da máquina, a partir dos arquivos em /sys. Pode-se baixar periodicamente informação climática de algum site e adicionar a temperatura ao prompt, mudando a cor dependendo de se o tempo está ensolarado ou nublado ou chuvoso. As possibilidades são infinitas.

Comentários / Comments

Logar como root: por que não?

2012-03-27 23:14 -0300. Tags: comp, unix, security, em-portugues

Há um bom tempo atrás eu li um cara argumentando que logar como root não é necessariamente ruim. Na época não pensei muito sobre o assunto, mas agora acho que o camarada tem razão. Em uma máquina com múltiplos usuários, ou um servidor, é importante proteger os dados de um usuário dos outros, e proteger o sistema dos usuários. Mas em um sistema com um único usuário, as vantagens de usar um usuário comum ao invés do root são de mínimas a nulas.

Ameaças à segurança do sistema incluem:

O que isso nos demonstra é que os mecanismos de segurança tradicionais do Unix são largamente inúteis nos ambientes atuais. Eles não me permitem dar direito a um programa de ler seus arquivos de configuração sem também dar direito de apagar meus arquivos pessoais, nem dar direito a um programa de alterar o relógio do sistema sem também dar direito de formatar o disco. Em um mundo ideal, quando eu dou um comando do tipo cp whatever.txt /home/docs/text/, o programa cp deveria receber não strings, mas sim handlers referindo-se ao arquivo e ao diretório em questão, e só teria acesso a esses dois itens, através dos handlers, e a mais nada. (Integrar isso em uma interface gráfica e garantir acesso a arquivos de configuração e outros recursos implícitos sem causar a loucura do usuário é deixado como um exercício para o leitor.) Essa é a idéia de segurança por capabilities (não confundir com as capabilities de mortal do POSIX).

Ainda não me convenci a me logar sempre como root, mas estou em vias de. Contrapontos são bem-vindos.

Unix is dead. Long live Unix.

[* Ok, um possível objetivo de adulterar o sistema é tornar futuros ataques invisíveis, coisa que não é em princípio possível sem acesso de root. Hmmrgh.]

[P.S.: O primeiro que reclamar do "há um tempo atrás" será sumariamente apedrejado.]

1 comentário / comment

Ubuntu vs. MTU

2012-03-17 13:35 -0300. Tags: comp, unix, mundane, em-portugues

Um camarada estava tendo problemas para acessar um certo livro de faces, entre outras páginas, no Ubuntu 10.10 e 11.04, tanto no Firefox quanto no Chromium. Solução? Diminuir o MTU da interface de rede em questão:

sudo ifconfig wlan0 mtu 1492

substituindo wlan0 pela interface usada para acessar a Internet. Se não funcionar, você pode experimentar valores menores para o MTU. Se alguém souber explicar por que alguns sites funcionam com o valor de MTU errado e outros não, tenha a bondade.

Quem me contou foi esse cara.

Comentários / Comments

Evitando morrer nas mãos do gcc

2012-03-04 11:35 -0300. Tags: comp, unix, em-portugues

Há um tempo atrás, em um momento de distração, dei um comando do tipo:

$ gcc -o h[Tab] h[Tab]

que os tabs completaram para:

$ gcc -o hello.c hello.c

Em situações normais, o gcc compila fonte e o sobrescreve com o executável nesse caso, o que definitivamente não é o que eu queria e me faria ter perdido umas boas linhas de código. Para minha surpresa, entretanto, a máquina pareceu ter criado consciência própria e me respondeu:

$ gcc -o hello.c hello.c
gcc -o hello.c?
$ _

Levei alguns segundos para entender o que estava acontecendo.

Meu eu do passado é um cara muito legal.

Mais ou menos um ano antes, eu tinha adicionado as seguintes linhas ao meu /etc/bash.bashrc:

# Preventing chaos.

gcc() {
    local args=("$@") out=""
    while [[ $# -gt 0 ]]; do
        case "$1" in
            -o) out="$2" ;;
            -o*) out="${1#-o}" ;;
        esac
        shift
    done
    if [[ $out == *.c ]]; then
        echo "gcc -o $out?" >&2
        return 1
    else
        command gcc "${args[@]}"
    fi
}

Essa rica função intercepta as chamadas ao gcc e, se o argumento da opção -o tiver a extensão .c, impede que o gcc seja executado. Também seria possível escrever um script independente ao invés de uma função, colocando-o em algum lugar antes do gcc real no PATH (e.g., /usr/local/bin/gcc), com o conteúdo da função (o trecho entre chaves), substituindo o command gcc pelo caminho do gcc real (e.g., /usr/bin/gcc) e o return por exit. Porém, a função tem a vantagem de afetar apenas shells interativos, deixando em paz scripts, Makefiles e afins.

De brinde, você pode aproveitar para adicionar -Wall automaticamente à linha de comando do gcc (o que teria me economizado mais de oito mil horas de debugging durante a vida).

Comentários / Comments

Inodes, hard links, symlinks

2010-11-23 21:30 -0200. Tags: comp, unix, em-portugues

Muitas pessoas já me perguntaram qual é a diferença entre um hard link e um link simbólico. No intuito de elucidar este duradouro mistério sobre a natureza do Unix, apresento-vos este singelo post.

No Unix, cada arquivo é associado a um inode. O inode é uma estrutura que contém diversas meta-informações sobre o arquivo, tais como seu tamanho, dono, grupo, permissões, datas de acesso e modificação, e ponteiros para o conteúdo do arquivo do disco. O inode, entretanto, não contém o nome do arquivo. Cada inode possui um número que o identifica dentro de um dado sistema de arquivos.

Um diretório é um arquivo que contém uma lista de nomes de arquivos e os números de seus respectivos inodes. Cada entrada dessa lista é um hard link para o arquivo em questão. É possível que haja mais de uma entrada, no mesmo diretório ou não, para o mesmo arquivo; o inode contém uma contador de referências (o valor na segunda coluna do ls -l, conhecido como link count), que indica quantas entradas apontam para ele. Enquanto houver referências para o arquivo, ele continuará existindo, mesmo que a referência "original" seja apagada. Apenas quando o contador de referências atingir zero (e nenhum processo estiver com o arquivo aberto), ele será removido do sistema de arquivos. Isso explica por que a syscall que "apaga" um arquivo no Unix se chama unlink.

Enquanto um hard link é uma referência direta ao arquivo, um link simbólico, ou symlink, é uma referência a um nome de arquivo. Essencialmente, um symlink é como um "atalho" em um suposto sistema operacional, com a diferença de que o symlink é tratado transparentemente pelo sistema. Se a entrada para a qual um symlink aponta for apagada, o symlink fica quebrado. É possível criar symlinks entre sistemas de arquivos (pois apenas o nome é usado), mas não um hard link (pois o inode deve estar no mesmo sistema de arquivos que a referência).

Uma observação interessante é que o link count de um diretório é igual ao número de subdiretórios que possui mais 2. Isso acontece porque, além da entrada no diretório que o contém, o diretório contém uma entrada . apontando para si mesmo, e cada subdiretório possui uma entrada .. apontando para o diretório pai. A maior parte dos sistemas não permite a criação de novos hard links para um diretório, para evitar ciclos na "árvore" de diretórios.

E termina assim o conto.

Comentários / Comments

Main menu

Recent posts

Recent comments

Tags

em-portugues (213) comp (148) prog (71) in-english (62) life (49) unix (38) pldesign (37) lang (32) random (28) about (28) mind (26) lisp (25) fenius (22) mundane (22) web (20) ramble (18) img (13) rant (12) hel (12) scheme (10) privacy (10) freedom (8) esperanto (7) music (7) lash (7) bash (7) academia (7) copyright (7) home (6) mestrado (6) shell (6) android (5) conlang (5) misc (5) emacs (5) latex (4) editor (4) etymology (4) php (4) worldly (4) book (4) politics (4) network (3) c (3) tour-de-scheme (3) security (3) kbd (3) film (3) wrong (3) cook (2) treta (2) poem (2) physics (2) x11 (2) audio (2) comic (2) lows (2) llvm (2) wm (2) philosophy (2) perl (1) wayland (1) ai (1) german (1) en-esperanto (1) golang (1) translation (1) kindle (1) pointless (1) old-chinese (1)

Elsewhere

Quod vide


Copyright © 2010-2024 Vítor De Araújo
O conteúdo deste blog, a menos que de outra forma especificado, pode ser utilizado segundo os termos da licença Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International.

Powered by Blognir.