Как клонировать списки контроля доступа ZFS из одного файла в другой?

Как клонировать списки контроля доступа ZFS из одного файла в другой?

Я хотел бы клонировать все списки контроля доступа ZFS из одного файла в другой.

С помощью списков контроля доступа POSIX это можно сделать, перенаправив вывод getfaclв setfacl.

Есть ли простой и быстрый способ сделать это с помощью ACL в стиле NFSv4 в ZFS? Я знаю, что могу считать вывод ls -lVи затем ввести его как часть chmod, но я не могу найти функциональный эквивалент POSIX-способу копирования ACL.

решение1

Вместо этого ls -lVвы можете использовать ls -lv, который можно вставить в скрипт, чтобы преобразовать его в последовательность chmodкоманд для дублирования ACL.

Например, если ACl выглядит так:

$ 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

Его следует преобразовать в следующую последовательность 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

Недавно я оказался в ситуации, когда скрипт, подобный описанному выше, был бы полезен, поэтому вот небольшой скрипт Bash, который я создал (его также можно подключить к оболочке и запустить как функцию) для вывода списка команд chmod, необходимых для копирования списков контроля доступа ZFS из одного файла в другой:

#!/bin/баш

acl_as_chmods () {
# вывести список команд chmod для копирования записей ACL из '$1' в '$2'
 [[ -a "$1" ]] 2>/dev/null || {
   echo "Требуется действительный файл ссылки." >&2
   возврат 1
 }
 ls -vd "$1" | {
   прочитайте # первая строка не является информацией ACL; обойти
   прочитать ACL_entry
     echo -n "chmod A=${ACL_entry#*:}"
   # если целевой файл не указан как '$2', использовать переменную 'TARGET' во время выполнения
   при чтении ACL_entry || { echo " ${2-\$TARGET}"; false; }
   делать
     [[ "$ACL_entry" == [0-9]*:* ]] && \
       echo -en " ${2-\$TARGET}\nchmod A${ACL_entry%%:*}+${ACL_entry#*:}" || \
       echo -n "$ACL_entry"
   сделанный
 }
}

## запустить как скрипт или исходную функцию для оболочки?
__acl_as_chmods () {
 [[ "${FUNCNAME[1]}" == "источник" ]] || acl_as_chmods "$@"
}

__acl_as_chmods "$@"

Вот несколько примеров использования и их вывод дляфайл1сверху:

~$ ./acl_as_chmods.sh файл1 файл2
chmod A=владелец@::deny file2
chmod A1+владелец@: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

~$ источник acl_as_chmods.sh
~$ acl_as_chmods файл1
chmod A=владелец@::deny $TARGET
chmod A1+владелец@: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

Если мы захотим, мы даже можем оценить эти chmods напрямую, если оба файла доступны на этом хосте и мы хотим скопировать ACL сфайл1кфайл2немедленно:

~$ ls -Vd файл* #ПЕРЕД
-rwx--x--x 1 пользователь пользователь 0 июн 19 04:12 файл1
            владелец@:-------------:------:отказать
            владелец@:rwxp---AW-Co-:------:allow
            группа@:rw-p----------:------:отказать
            группа@:--x----------:------:разрешить
         все@:rw-p---AW-Co-:------:deny
         все@:--x---aRc--s:------:разрешить
---x------+ 1 пользователь пользователь 0 июн 19 04:12 file2
            владелец@:--x----------:------:разрешить

~$ eval "$(acl_as_chmods файл1 файл2)"

~$ ls -Vd файл* #ПОСЛЕ
-rwx--x--x 1 пользователь пользователь 0 июн 19 04:12 файл1
            владелец@:-------------:------:отказать
            владелец@:rwxp---AW-Co-:------:allow
            группа@:rw-p----------:------:отказать
            группа@:--x----------:------:разрешить
         все@:rw-p---AW-Co-:------:deny
         все@:--x---aRc--s:------:разрешить
-rwx--x--x 1 пользователь пользователь 0 июн 19 04:12 file2
            владелец@:-------------:------:отказать
            владелец@:rwxp---AW-Co-:------:allow
            группа@:rw-p----------:------:отказать
            группа@:--x----------:------:разрешить
         все@:rw-p---AW-Co-:------:deny
         все@:--x---aRc--s:------:разрешить

решение2

Я столкнулся с такой же проблемой. Мой код здесь:

https://gist.github.com/1021032

У меня все работает как часы. Надеюсь, это пригодится, если кто-то еще столкнется с этой проблемой.

решение3

Принимая то, чтоМартинпредполагает, что, применив немного Perl, вы можете получить что-то вроде:

#!/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: $?";
}

попробуйте сделать это перед тем, как раскомментировать строки system(@out).

решение4

Досадно, что это, похоже, не отображается должным образом на уровне оболочки. В C есть функции acl_get(3SEC)и acl_set(3SEC), которые можно использовать для извлечения ACL из одного файла и применения его к другому (среди прочих опций, очевидно). Они также будут, что полезно, переводить ACL из черновика POSIX в тип NFSv4; это то, что любят mvи cpиспользуют системные команды.

Я написал, в свое время, команду для копирования acl из исходного в целевой файл с использованием этой техники, но в настоящее время я не могу найти исходный код. Если я его найду, я добавлю его к этому ответу.

Связанный контент