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
, который имеет множество имен(typeset
export
... ). Все это встроенные функции, поэтому их можно найти в глубинах 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 -? )в противном случае пока не возитесь со специальными переменными.
Как поясняется в комментарии, резервное копирование на основе блочных устройств обычно является неправильной идеей.
На незашифрованном -устройстве это обычно делается с помощью следующих шагов:
dd if=/dev/zero of=<mountpoint>/tmp_zero_file bs=1M
), чтобы свободное пространство сжималось с лучшим коэффициентом. dd if=<your block device> |gzip -9 | ssh backup_host "cat > backup.gz"
rm <mountpoint>/tmp_zero_file
. Проблема здесь в том, что, поскольку ваш диск зашифрован, запись 0 в файл не приведет к обнулению блоков из-за уровня шифрования.
В вашем случае -я настоятельно рекомендую использовать duplicity , который представляет собой инструмент резервного копирования на основе rsync -, реализующий шифрование и инкрементное резервное копирование.
Пока вы смотрите на весь раздел, вы должны прочитать его целиком, чтобы найти, что изменилось. На самом деле вам нужно прочитать новую версию и старую версию, чтобы найти изменения, поэтому вам лучше просто скопировать все заново. С Gigabit Ethernet и хорошими дисками вы получаете 100 МБ/с, поэтому ваш терабайт займет 10000 с или примерно 3 часа, так что ночное резервное копирование выполнимо. OTOH, если целью является SSD, вы быстро изнашиваете его.
Обратите внимание, что вы делаете не резервное копирование, а зеркало. Пользователям, удаляющим файлы по ошибке, не очень помогает, если они обнаружат это после того, как произошло одно зеркалирование.
Вы можете пропатчить 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 отказывается использовать блочные устройства.)