Смонтировать блочное устройство как обычный файл

TL;DR не используют повторно «специальные встроенные параметры», такие как path, потому что они особенные.Или согласно Списку рассылки можно использовать флаг -h:

% () { local -hr path=42; echo $path }
42
% 

(Однако изменение pathна целое число может испортить последующий код, который забывает об этом переопределении и предполагает, что pathвместо path...)

Копаться дальше следует (, но я совершенно пропустил -hпрятки...)

% print ${(t)path}
array-special

Это функция свойства (? ошибка? )специальных переменных, но не подобных переменных, связанных пользователем:

% () { typeset -r PATH=/blah; echo $PATH }
(anon): read-only variable: PATH
% typeset -Tar FOO=bar foo
% print $foo
bar
% print ${(t)foo}
array-readonly-tag_local
% () { local -r foo=blah; echo $foo }
blah

Существуют различные другие параметры, которые демонстрируют такое поведение:

% for p in $parameters[(I)*]; do print $p $parameters[$p]; done | grep array-
cdpath array-special
...
% () { local -r cdpath=42 }
(anon): read-only variable: cdpath

Таким образом, некоторые переменные, как в Скотный двор , более особенные, чем другие. Это сообщение об ошибке приходит из разных мест в Src/params.c, которые, если они изменены для печати, какое сообщение является конкретным сообщением, которое мы компилируем, что zshнаходим:

% () { local -r path }
% () { local -r path=foo }
(anon): read-only variable (setarrvalue): path

Является довольно общим кодом

/**/
mod_export void
setarrvalue(Value v, char **val)
{
    if (unset(EXECOPT))
        return;
    if (v->pm->node.flags & PM_READONLY) {
        zerr("read-only variable (setarrvalue): %s", v->pm->node.nam);
        freearray(val);
        return;
    }

Это показывает, что проблема возникает в другом месте; не -специальные переменные, несомненно, не имеют PM_READONLYустановки, в то время как специальные переменные, которые не работают, имеют. Следующим очевидным местом для поиска является код local, который имеет множество имен(typesetexport... ). Все это встроенные функции, поэтому их можно найти в глубинах Src/builtin.c

.

% grep BUILTIN Src/builtin.c | grep local
    BUILTIN("local", BINF_PLUSOPTS | BINF_MAGICEQUALS | BINF_PSPECIAL | BINF_ASSIGN, (HandlerFunc)bin_typeset, 0, -1, 0, "AE:%F:%HL:%R:%TUZ:%ahi:%lp:%rtux", NULL),

Все они вызывают bin_typesetс различными установленными флагами, поэтому давайте изучим исходный код этой функции... ругань в комментариях, проверьте. Отмечает, что все сложно, проверьте. На самом деле ничего не выскакивает, хотя кроличья нора (для случая, когда параметр «рассматривать аргументы как шаблоны» -mустановлен , а не , что имеет место здесь ), по-видимому, приводит к typeset_single] функция...

Существует некоторый код для POSIXBUILTINS, связанный с readonly, но он отключен в моих тестовых оболочках

% print $options[POSIXBUILTINS]
off

так что я проигнорирую этот код (надеюсь. Могло ли это быть логовом шогготов, а не просто кроличьей норой? ). Тем временем!Некоторые отладки указывают на то, что флаг PM_READONLYвключается для pathследующей строкой

    /*
     * The remaining on/off flags should be harmless to use,
     * because we've checked for unpleasant surprises above.
     */
    pm->node.flags = (PM_TYPE(pm->node.flags) | on | PM_SPECIAL) & ~off;

Которая, в свою очередь, исходит из переменной on, которая, в свою очередь, уже включена при входе в функцию typeset_single, вздох, так что вернемся к bin_typesetмы идем... ладно, в основном есть TYPESET_OPTSTR, которая каким-то образом через некоторые макросы по умолчанию включается PM_READONLY; когда вместо этого пользовательская переменная -проходит через этот путь кода, PM_READONLYотключается, и все хорошо.

Можно ли изменить это так, чтобы специальные переменные, такие как path, можно было сделать доступными только для чтения, это вопрос к разработчику ZSH (попробовать список рассылки рабочих zsh -? )в противном случае пока не возитесь со специальными переменными.

0
13.01.2020, 17:38
3 ответа

Как поясняется в комментарии, резервное копирование на основе блочных устройств обычно является неправильной идеей.

На незашифрованном -устройстве это обычно делается с помощью следующих шагов:

  1. Заполнить пустое пространство нулями (dd if=/dev/zero of=<mountpoint>/tmp_zero_file bs=1M), чтобы свободное пространство сжималось с лучшим коэффициентом.
  2. Тогдаdd if=<your block device> |gzip -9 | ssh backup_host "cat > backup.gz"
  3. Тогда rm <mountpoint>/tmp_zero_file.

Проблема здесь в том, что, поскольку ваш диск зашифрован, запись 0 в файл не приведет к обнулению блоков из-за уровня шифрования.

В вашем случае -я настоятельно рекомендую использовать duplicity , который представляет собой инструмент резервного копирования на основе rsync -, реализующий шифрование и инкрементное резервное копирование.

0
28.01.2020, 02:56

Пока вы смотрите на весь раздел, вы должны прочитать его целиком, чтобы найти, что изменилось. На самом деле вам нужно прочитать новую версию и старую версию, чтобы найти изменения, поэтому вам лучше просто скопировать все заново. С Gigabit Ethernet и хорошими дисками вы получаете 100 МБ/с, поэтому ваш терабайт займет 10000 с или примерно 3 часа, так что ночное резервное копирование выполнимо. OTOH, если целью является SSD, вы быстро изнашиваете его.

Обратите внимание, что вы делаете не резервное копирование, а зеркало. Пользователям, удаляющим файлы по ошибке, не очень помогает, если они обнаружат это после того, как произошло одно зеркалирование.

0
28.01.2020, 02:56

Вы можете пропатчить passthrough _fh libfuse demo fs следующим образом:

diff --git a/example/passthrough_fh.c b/example/passthrough_fh.c
index 13eb41e..146cb03 100644
--- a/example/passthrough_fh.c
+++ b/example/passthrough_fh.c
@@ -72,6 +72,21 @@ static void *xmp_init(struct fuse_conn_info *conn,
    return NULL;
 }

+
+static void b2r(int devfd, struct stat *stbuf)
+{
+   off_t disk_size;
+
+   disk_size = lseek(devfd, 0, SEEK_END);
+   if (disk_size == -1)
+       return;
+
+   stbuf->st_size = disk_size;
+   stbuf->st_blocks = disk_size / stbuf->st_blksize;
+   stbuf->st_mode &= ~S_IFBLK;
+   stbuf->st_mode |= S_IFREG;
+}
+
 static int xmp_getattr(const char *path, struct stat *stbuf,
            struct fuse_file_info *fi)
 {
@@ -85,6 +100,16 @@ static int xmp_getattr(const char *path, struct stat *stbuf,
        res = lstat(path, stbuf);
    if (res == -1)
        return -errno;
+   if (S_ISBLK(stbuf->st_mode)) {
+       int fd;
+       if (fi)
+           fd = fi->fh;
+       else
+           fd = open(path, O_RDONLY);
+       b2r(fd, stbuf);
+       if (!fi)
+           close(fd);
+   }

    return 0;
 }

Если смонтировать его как root, он представит вам зеркало вашей файловой системы с блочными устройствами, которые выглядят как обычные файлы. Передайте -omodules=subdir,subdir=/devтолько для зеркалирования /dev.

(Я использую вариант этого патча на своей машине Mac/Linux с двойной загрузкой, чтобы иметь возможность загрузить свою установку Linux как виртуальную машину Xhyve в OS X, поскольку Xhyve отказывается использовать блочные устройства.)

1
13.02.2020, 13:56

Теги

Похожие вопросы