Como eu clonei as ACLs do ZFS de um arquivo para outro?

4

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

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

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

    
por Kamil Kisiel 10.07.2009 / 08:48

4 respostas

4

Em vez de usar ls -lV , você pode usar ls -lv , que pode ser alimentado em um script para convertê-lo em uma sequência de comandos chmod para duplicar as ACLs.

Por exemplo se a ACl se parece com isso:

$ 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

Ele deve ser ativado para a seguinte sequência de comandos chmod :

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

Eu recentemente me encontrei em uma situação onde um script como o descrito acima teria sido útil, então aqui está um pequeno script Bash que eu 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 () {
# print list of chmod commands to copy the ACL entries from '$1' to '$2'
 [[ -a "$1" ]] 2>/dev/null || {
   echo "Valid reference file required." >&2
   return 1
 }
 ls -vd "$1" | {
   read # first line is not ACL information; bypass
   read ACL_entry
     echo -n "chmod A=${ACL_entry#*:}"
   # if no target file was specified as '$2', use 'TARGET' variable at runtime
   while read ACL_entry || { echo " ${2-\$TARGET}"; false; }
   do
     [[ "$ACL_entry" == [0-9]*:* ]] && \
       echo -en " ${2-\$TARGET}\nchmod A${ACL_entry%%:*}+${ACL_entry#*:}" || \
       echo -n "$ACL_entry"
   done
 }
}

## run as script or source function to shell?
__acl_as_chmods () {
 [[ "${FUNCNAME[1]}" == "source" ]] || acl_as_chmods "$@"
}

__acl_as_chmods "$@"

Aqui estão alguns exemplos de uso e sua saída para file1 acima:

~$ ./acl_as_chmods.sh file1 file2
chmod A=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

~$ source acl_as_chmods.sh
~$ acl_as_chmods file1
chmod A=owner@::deny $TARGET
chmod A1+owner@: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+group@:execute:allow $TARGET
chmod A4+everyone@:read_data/write_data/append_data/write_xattr/write_attributes/write_acl/write_owner:deny $TARGET
chmod A5+everyone@: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 quisermos copiar as ACLs de arquivo1 para arquivo2 imediatamente:

~$ ls -Vd file*  #BEFORE
-rwx--x--x   1 user user       0 Jun 19 04:12 file1
            owner@:--------------:------:deny
            owner@:rwxp---A-W-Co-:------:allow
            group@:rw-p----------:------:deny
            group@:--x-----------:------:allow
         everyone@:rw-p---A-W-Co-:------:deny
         everyone@:--x---a-R-c--s:------:allow
---x------+  1 user user       0 Jun 19 04:12 file2
            owner@:--x-----------:------:allow

~$ eval "$(acl_as_chmods file1 file2)"

~$ ls -Vd file*  #AFTER 
-rwx--x--x   1 user user       0 Jun 19 04:12 file1
            owner@:--------------:------:deny
            owner@:rwxp---A-W-Co-:------:allow
            group@:rw-p----------:------:deny
            group@:--x-----------:------:allow
         everyone@:rw-p---A-W-Co-:------:deny
         everyone@:--x---a-R-c--s:------:allow
-rwx--x--x   1 user user       0 Jun 19 04:12 file2
            owner@:--------------:------:deny
            owner@:rwxp---A-W-Co-:------:allow
            group@:rw-p----------:------:deny
            group@:--x-----------:------:allow
         everyone@:rw-p---A-W-Co-:------:deny
         everyone@:--x---a-R-c--s:------:allow
    
por 17.07.2009 / 12:45
2

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

link

Funciona como um encanto para mim. Espero que seja útil se alguém mais tiver problemas com isso.

    
por 12.06.2011 / 00:29
1

Tomando o que Martin sugere 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: $?";
}

tente antes de descomentar as linhas do sistema (@out).

    
por 03.08.2009 / 23:38
1

Irritantemente, isso não parece estar adequadamente exposto no nível do shell. Em C, existem funções acl_get(3SEC) e acl_set(3SEC) que podem ser usadas para tirar a ACL de um arquivo e aplicá-lo a outro (entre outras opções, obviamente). Eles também, de maneira útil, traduzem uma ACL do rascunho POSIX para o tipo NFSv4; isto é o que o sistema comanda como mv e cp use.

Eu escrevi, ao mesmo tempo, um comando para copiar um acl de uma fonte para um arquivo de destino usando essa técnica, mas atualmente não consigo encontrar o código-fonte. Devo encontrá-lo, vou anexá-lo a esta resposta.

    
por 17.09.2009 / 22:37