Como clonar ACLs do ZFS de um arquivo para outro?

Como clonar ACLs do ZFS de um arquivo para outro?

Gostaria de clonar todas as ACLs do ZFS de um arquivo para outro.

Com ACLs POSIX, isso pode ser feito canalizando a saída de getfaclto setfacl.

Existe uma maneira fácil e rápida de fazer isso com as ACLs do estilo NFSv4 no ZFS? Eu sei que posso ler a saída de ls -lVe inseri-la como parte de a chmod, mas não consigo encontrar um equivalente funcional para a maneira POSIX de copiar ACLs.

Responder1

Em vez de usar, ls -lVvocê pode usar ls -lvwhich pode ser inserido em um script para convertê-lo em uma sequência de chmodcomandos para duplicar as ACLs.

Por exemplo, se o ACl for assim:

$ ls -lv file1
     0:owner@::deny
     1:owner@:read_data/write_data/append_data/write_xattr/execute
         /write_attributes/write_acl/write_owner:allow
     2:group@:read_data/write_data/append_data:deny
     3:group@:execute:allow
     4:everyone@:read_data/write_data/append_data/write_xattr
        /write_attributes/write_acl/write_owner:deny
     5:everyone@:read_xattr/execute/read_attributes/read_acl/synchronize:allow

Deve ser entregue na seguinte sequência de chmodcomandos:

chmod A0=owner@::deny file2
chmod A1=owner@:read_data/write_data/append_data/write_xattr/execute/write_attributes/write_acl/write_owner:allow file2
chmod A2=group@:read_data/write_data/append_data:deny file2
chmod A3=group@:execute:allow file2
chmod A4=everyone@:read_data/write_data/append_data/write_xattr/write_attributes/write_acl/write_owner:deny file2
chmod A5=everyone@:read_xattr/execute/read_attributes/read_acl/synchronize:allow file2

Recentemente, me encontrei em uma situação em que um script como o descrito acima teria sido útil, então aqui está um pequeno script Bash que fiz (também pode ser originado no shell e executado como uma função) para imprimir a lista de comandos chmod necessários para copiar as ACLs do ZFS de um arquivo para outro:

#!/bin/bash

acl_as_chmods(){
# imprime lista de comandos chmod para copiar as entradas ACL de '$1' para '$2'
 [[ -a "$1" ]] 2>/dev/null || {
   echo "Arquivo de referência válido necessário." >&2
   retornar 1
 }
 ls -vd "$1" | {
   read # primeira linha não é informação ACL; desviar
   leia ACL_entry
     echo -n "chmod A=${ACL_entry#*:}"
   # se nenhum arquivo de destino foi especificado como '$2', use a variável 'TARGET' em tempo de execução
   enquanto lê ACL_entry || { echo "${2-\$TARGET}"; falso; }
   fazer
     [[ "$ACL_entry" == [0-9]*:* ]] && \
       echo -en "${2-\$TARGET}\nchmod A${ACL_entry%%:*}+${ACL_entry#*:}" || \
       eco -n "$ACL_entry"
   feito
 }
}

## executar como script ou função de origem para shell?
__acl_as_chmods(){
 [[ "${FUNCNAME[1]}" == "fonte" ]] || acl_as_chmods"$@"
}

__acl_as_chmods"$@"

Aqui estão alguns exemplos de uso e sua saída paraarquivo1de cima:

~$ ./acl_as_chmods.sh arquivo1 arquivo2
chmod A = proprietário@:: negar arquivo2
chmod A1+proprietário@:read_data/write_data/append_data/write_xattr/execute/write_attributes/write_acl/write_owner:allow file2
chmod A2+group@:read_data/write_data/append_data:deny file2
chmod A3+grupo@:executar:permitir arquivo2
chmod A4+todos@:read_data/write_data/append_data/write_xattr/write_attributes/write_acl/write_owner:deny file2
chmod A5+todos@:read_xattr/execute/read_attributes/read_acl/synchronize:allow file2

~$ fonte acl_as_chmods.sh
~$ acl_as_chmods arquivo1
chmod A=proprietário@::deny $TARGET
chmod A1+proprietário@:read_data/write_data/append_data/write_xattr/execute/write_attributes/write_acl/write_owner:allow $TARGET
chmod A2+group@:read_data/write_data/append_data:deny $TARGET
chmod A3+grupo@:executar:permitir $TARGET
chmod A4+todos@:read_data/write_data/append_data/write_xattr/write_attributes/write_acl/write_owner:deny $TARGET
chmod A5+todos@:read_xattr/execute/read_attributes/read_acl/synchronize:allow $TARGET

Se quisermos, podemos até avaliar esses chmods diretamente, se ambos os arquivos estiverem acessíveis neste host e desejarmos copiar as ACLs dearquivo1paraarquivo2imediatamente:

~$ ls -Vd arquivo* #BEFORE
-rwx--x--x 1 usuário usuário 0 19 de junho 04:12 arquivo1
            proprietário@:--------------:------:negar
            proprietário@:rwxp---AW-Co-:------:permitir
            grupo@:rw-p----------:------:negar
            grupo@:--x-----------:------:permitir
         todos@:rw-p---AW-Co-:------:negar
         todos@:--x---aRc--s:------:permitir
---x------+ 1 usuário usuário 0 19 de junho 04:12 arquivo2
            proprietário@:--x-----------:------:permitir

~$ avaliação "$(acl_as_chmods arquivo1 arquivo2)"

~$ ls -Vd arquivo* #AFTER
-rwx--x--x 1 usuário usuário 0 19 de junho 04:12 arquivo1
            proprietário@:--------------:------:negar
            proprietário@:rwxp---AW-Co-:------:permitir
            grupo@:rw-p----------:------:negar
            grupo@:--x-----------:------:permitir
         todos@:rw-p---AW-Co-:------:negar
         todos@:--x---aRc--s:------:permitir
-rwx--x--x 1 usuário usuário 0 19 de junho 04:12 arquivo2
            proprietário@:--------------:------:negar
            proprietário@:rwxp---AW-Co-:------:permitir
            grupo@:rw-p----------:------:negar
            grupo@:--x-----------:------:permitir
         todos@:rw-p---AW-Co-:------:negar
         todos@:--x---aRc--s:------:permitir

Responder2

Eu me deparei com esse mesmo problema. Meu código está aqui:

https://gist.github.com/1021032

Funciona perfeitamente para mim. Espero que seja útil se alguém mais tiver esse problema.

Responder3

Pegando o queMartinhosugere e aplicando um pouco de perl você pode obter algo como:

#!/usr/bin/perl
use warnings;
use strict;

my $state = 0;
if ($#ARGV < 1 || $#ARGV > 2) {
  print "\n\tUsage: $0 srcFile destFile\n";
}
my $acl=`ls -lv "${ARGV[0]}"`;
my @out="chmod", "arg", $ARGV[1];
foreach my $line ($acl) {
  chomp $line;
  if ($line =~ m/^\s+(\d+):(.*)$/) {
    if ($state > 0) {
      print join(" ",@out)."\n";
      #system(@out) or die "system @args failed: $?";
    }
    $state = 1;
    $out[1] = "A$1=$2";
  } else {
    $line =~ m/^\s+(.*)$/;
    $state = 2;
    $out[1] .= $1;
  }
}
if ($state > 0) {
  print join(" ",@out)."\n";
  #system(@out) or die "system @args failed: $?";
}

experimente antes de descomentar as linhas system(@out).

Responder4

Irritantemente, isso não parece estar devidamente exposto no nível do shell. Em C, existem funções acl_get(3SEC)que acl_set(3SEC)podem ser usadas para pegar a ACL de um arquivo e aplicá-la a outro (entre outras opções, obviamente). Eles também irão, de forma útil, traduzir uma ACL do rascunho POSIX para o tipo NFSv4; é isso que os comandos do sistema gostam mve cpusam.

Certa vez, escrevi um comando para copiar uma acl de um arquivo de origem para um arquivo de destino usando essa técnica, mas atualmente não consigo encontrar o código-fonte. Se eu encontrar, vou anexá-lo a esta resposta.

informação relacionada