¿Cómo clono ACL de ZFS de un archivo a otro?

¿Cómo clono ACL de ZFS de un archivo a otro?

Me gustaría clonar todas las ACL de ZFS de un archivo a otro.

Con las ACL POSIX, esto se puede hacer canalizando la salida de getfacla setfacl.

¿Existe una manera fácil y rápida de hacer esto con las ACL de estilo NFSv4 en ZFS? Sé que puedo leer el resultado ls -lVy luego ingresarlo como parte de a chmod, pero parece que no puedo encontrar un equivalente funcional a la forma POSIX de copiar ACL.

Respuesta1

En lugar de usar, ls -lVpuede usar ls -lvel cual se puede introducir en un script para convertirlo en una secuencia de chmodcomandos para duplicar las ACL.

Por ejemplo, si el ACl tiene este aspecto:

$ 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

Debe entregarse a la siguiente secuencia 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

Recientemente me encontré en una situación en la que un script como el descrito anteriormente habría sido útil, así que aquí hay un pequeño script Bash que hice (también puede obtenerse en el shell y ejecutarse como una función) para imprimir la lista de comandos chmod necesarios. para copiar las ACL de ZFS de un archivo a otro:

#!/bin/bash

acl_as_chmods () {
# imprimir la lista de comandos chmod para copiar las entradas de ACL de '$1' a '$2'
 [[ -a "$1" ]] 2>/dev/null || {
   echo "Se requiere un archivo de referencia válido". >&2
   regresar 1
 }
 ls -vd "$1" | {
   leer # la primera línea no es información de ACL; derivación
   leer ACL_entry
     echo -n "chmod A=${ACL_entry#*:}"
   # si no se especificó ningún archivo de destino como '$2', use la variable 'TARGET' en tiempo de ejecución
   mientras se lee ACL_entry || { echo " ${2-\$TARGET}"; FALSO; }
   hacer
     [[ "$ACL_entry" == [0-9]*:* ]] && \
       echo -en " ${2-\$TARGET}\nchmod A${ACL_entry%%:*}+${ACL_entry#*:}" || \
       echo -n "$ACL_entrada"
   hecho
 }
}

## ¿ejecutar como script o función fuente al shell?
__acl_as_chmods () {
 [[ "${FUNCNAME[1]}" == "fuente" ]] || acl_as_chmods "$@"
}

__acl_as_chmods "$@"

Aquí hay un par de usos de ejemplo y su resultado paraarchivo1desde arriba:

~$ ./acl_as_chmods.sh archivo1 archivo2
chmod A=propietario@::denegar archivo2
chmod A1+propietario@:read_data/write_data/append_data/write_xattr/execute/write_attributes/write_acl/write_owner:permitir archivo2
chmod A2+grupo@:read_data/write_data/append_data:denegar archivo2
chmod A3+grupo@:ejecutar:permitir archivo2
chmod A4+todos@:read_data/write_data/append_data/write_xattr/write_attributes/write_acl/write_owner:denegar archivo2
chmod A5+todos@:read_xattr/execute/read_attributes/read_acl/synchronize:permitir archivo2

~$ fuente acl_as_chmods.sh
~$ acl_as_chmods archivo1
chmod A=propietario@::denegar $OBJETIVO
chmod A1+propietario@:read_data/write_data/append_data/write_xattr/execute/write_attributes/write_acl/write_owner:permitir $OBJETIVO
chmod A2+grupo@:read_data/write_data/append_data:deny $OBJETIVO
chmod A3+grupo@:ejecutar:permitir $OBJETIVO
chmod A4+todos@:read_data/write_data/append_data/write_xattr/write_attributes/write_acl/write_owner:deny $OBJETIVO
chmod A5+todos@:read_xattr/execute/read_attributes/read_acl/synchronize:allow $OBJETIVO

Si lo deseamos, incluso podemos evaluar estos chmods directamente, si ambos archivos son accesibles en este host y deseamos copiar las ACL dearchivo1aarchivo2inmediatamente:

~$ ls -Vd archivo* #ANTES
-rwx--x--x 1 usuario usuario 0 19 de junio 04:12 archivo1
            propietario@:--------------:------:negar
            propietario@:rwxp---AW-Co-:------:permitir
            grupo@:rw-p----------:--------------:denegar
            grupo@:--x-----------:------:permitir
         todos@:rw-p---AW-Co-:------:negar
         todos@:--x---aRc--s:------:permitir
---x------+ 1 usuario usuario 0 19 de junio 04:12 archivo2
            propietario@:--x-----------:------:permitir

~$ eval "$(acl_as_chmods archivo1 archivo2)"

~$ ls -Vd archivo* #DESPUÉS
-rwx--x--x 1 usuario usuario 0 19 de junio 04:12 archivo1
            propietario@:--------------:------:negar
            propietario@:rwxp---AW-Co-:------:permitir
            grupo@:rw-p----------:--------------:denegar
            grupo@:--x-----------:------:permitir
         todos@:rw-p---AW-Co-:------:negar
         todos@:--x---aRc--s:------:permitir
-rwx--x--x 1 usuario usuario 0 19 de junio 04:12 archivo2
            propietario@:--------------:------:negar
            propietario@:rwxp---AW-Co-:------:permitir
            grupo@:rw-p----------:--------------:denegar
            grupo@:--x-----------:------:permitir
         todos@:rw-p---AW-Co-:------:negar
         todos@:--x---aRc--s:------:permitir

Respuesta2

Me encontré con este mismo problema. Mi código está aquí:

https://gist.github.com/1021032

Funciona como un encanto para mí. Espero que sea útil si alguien más alguna vez se encuentra con este problema.

Respuesta3

tomando lo queMartínsugiere y aplicando un poco de perl podrías obtener 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: $?";
}

Pruébelo antes de descomentar las líneas del sistema (@out).

Respuesta4

Es molesto que esto no parezca estar expuesto adecuadamente a nivel del caparazón. En C existen funciones acl_get(3SEC)y acl_set(3SEC)que se pueden usar para tomar la ACL de un archivo y aplicarla a otro (entre otras opciones, obviamente). También traducirán, de manera útil, una ACL del borrador POSIX al tipo NFSv4; esto es lo que les gusta mvy cpusan los comandos del sistema.

En un momento, escribí un comando para copiar una ACL de un archivo de origen a un archivo de destino usando esta técnica, pero actualmente no puedo encontrar el código fuente. Si lo encuentro, lo agregaré a esta respuesta.

información relacionada