it-swarm-pt.tech

Como alguém muda atomicamente um link simbólico para um diretório no busybox?

Estou tentando (o mais próximo possível) alterar atomicamente um link simbólico. Eu tentei:

ln -sf other_dir existing_symlink

Isso apenas coloca o novo link simbólico no diretório para o qual o link_do_sinal existente apontou.

ln -sf other_dir new_symlink
mv -f new_symlink existing_symlink

Isso fez a mesma coisa: moveu o link simbólico para o diretório.

cp -s other_dir existing_symlink

Ele se recusa porque é um diretório.

Eu li que mv -T foi feito para isso, mas o busybox não tem o -T flag.

18
Shawn J. Goff

Não vejo como você pode obter a operação atômica. A página de manual para symlink(2) diz que dá EEXIST se o destino já existe. Se o kernel não suporta operação atômica, suas limitações de usuário são irrelevantes.

Eu também não vejo como mv -T ajuda, mesmo se você tiver. Experimente em uma máquina Linux normal, uma com GNU mv:

$ mkdir a b
$ ln -s a z
$ mv -T b z
mv: cannot overwrite non-directory `z' with directory `b'

Acho que você terá que fazer isso em duas etapas: remover o link simbólico antigo e recriá-lo.

1
Warren Young

Isso pode de fato ser feito atomicamente com rename(2), criando primeiro o novo link simbólico com um nome temporário e, em seguida, substituindo o link antigo de forma limpa numa única tentativa. Como o página man afirma:

Se newpath refere-se a um link simbólico, o link será sobrescrito.

No Shell, você faria isso com mv -T Da seguinte maneira:

$ mkdir a b
$ ln -s a z
$ ln -s b z.new
$ mv -T z.new z

Você pode strace o último comando para ter certeza de que está realmente usando rename(2) sob o capô:

$ strace mv -T z.new z
lstat64("z.new", {st_mode=S_IFLNK|0777, st_size=1, ...}) = 0
lstat64("z", {st_mode=S_IFLNK|0777, st_size=1, ...}) = 0
rename("z.new", "z")                    = 0

Observe que acima, tanto mv -T E strace são específicos do Linux.

No FreeBSD, use mv -h Alternadamente.

43
Arto Bendiken

Continuando de onde Arto parou aqui, isso é perfeitamente possível, mesmo sem mv -T, você só precisa criar um novo link simbólico com o mesmo nome do diretório de destino e mv no diretório pai de seu destino:

mkdir -p tmp/real_dir1 tmp/real_dir2
touch tmp/real_dir1/a tmp/real_dir2/a
# start with ./target_dir pointing to tmp/real_dir1
ln -s tmp/real_dir1 target_dir
# create a symlink named target_dir in tmp, pointing to real_dir2
ln -sf tmp/real_dir2 tmp/target_dir
# atomically mv it into ./ replacing ./target_dir
mv tmp/target_dir ./

Exemplo de código obtido via ( http://axialcorps.wordpress.com/2013/07/03/atomically-replacing-files-and-directories/ )

8
mssaxm

Você tentou ln -snf?

A opção -n sobrescreve o destino em vez de escrever sob ele quando o destino é um link simbólico para um diretório.

Felicidades

3
sokai