Как осмотреть полномочия группы файла

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

И затем, существует другой режим, где терминальному драйверу говорят не отозваться эхом, но приложение на этот раз производит что-то. Приложение (как те, которые используют readline как gdb, удар...), может отправить это на своем stdout или stderr, который будет трудным дифференцироваться от чего-то, что это производит для других вещей, чем реагирование на ввод данных пользователем.

Затем для дифференциации stdout приложения от его stderr существует несколько подходов.

Многие из них включают перенаправление команд stdout и stderr к каналам и тем каналам, считанным приложением для окраски его. Существует две проблемы с этим:

  • После того как stdout больше не является терминалом (как канал вместо этого), многие, приложение имеет тенденцию адаптировать их поведение, чтобы начать буферизовать их вывод, что означает, что производит, будет отображенным в больших блоках.
  • Даже если это - тот же процесс, который обрабатывает два канала, нет никакой гарантии, что порядок, текст, записанный приложением на stdout и stderr, будет сохранен как процесс считывания, не может знать (если существует что-то, чтобы быть считанным от обоих), начать ли читать из канала "stdout" или канала "stderr".

Другой подход должен изменить приложение так, чтобы это действительно окрасило свой stdout и stdin. Это часто не возможно или реалистично сделать.

Затем прием (для динамично связанных приложений) может быть должен угнать (использование $LD_PRELOAD как в ответе sickill) функции вывода, вызванные приложением, чтобы произвести что-то и включать код в них, который выбирает основной цвет на основе того, ли предназначены они для вывода чего-то на stderr или stdout. Однако это означает угонять каждую возможную функцию из библиотеки C и любой другой библиотеки, которая делает a write(2) syscall, непосредственно названный приложением, которое может потенциально закончить тем, что писало что-то на stdout или stderr (printf, помещает, perror...), и даже затем, который может изменить его поведение.

Другой подход мог быть должен использовать приемы PTRACE как strace или gdb сделайте для сцепления каждый раз write(2) системный вызов называют и установил цвет вывода на основе ли write(2) находится на дескрипторе файла 1 или 2.

Однако это - вполне большая вещь сделать.

Прием, с которым я просто играл, должен угнать strace самостоятельно (который делает грязную работу сцепления себя перед каждым системным вызовом) использующий LD_PRELOAD, чтобы сказать этому изменять цвет вывода на основе того, обнаружило ли это a write(2) на fd 1 или 2.

От взгляда на strace исходный код, мы видим, что все, что он производит, сделано через vfprintf функция. Все, что мы должны сделать, должно угнать ту функцию.

Обертка LD_PRELOAD была бы похожа:

#define _GNU_SOURCE
#include 
#include 
#include 
#include 
#include 

int vfprintf(FILE *outf, const char *fmt, va_list ap)
{
  static int (*orig_vfprintf) (FILE*, const char *, va_list) = 0;
  static int c = 0;
  va_list ap_orig;
  va_copy(ap_orig, ap);
  if (!orig_vfprintf) {
    orig_vfprintf = (int (*) (FILE*, const char *, va_list))
      dlsym (RTLD_NEXT, "vfprintf");
  }

  if (strcmp(fmt, "%ld, ") == 0) {
    int fd = va_arg(ap, long);
    switch (fd) {
    case 2:
      write(2, "\e[31m", 5);
      c = 1;
      break;
    case 1:
      write(2, "\e[32m", 5);
      c = 1;
      break;
    }
  } else if (strcmp(fmt, ") ") == 0) {
    if (c) write(2, "\e[m", 3);
    c = 0;
  }
  return orig_vfprintf(outf, fmt, ap_orig);
}

Затем мы компилируем его с:

cc -Wall -fpic -shared -o wrap.so wrap.c -ldl

И используйте его как:

LD_PRELOAD=/path/to/wrap.so strace -qfo /dev/null -e write -s 0 env -u LD_PRELOAD some-cmd

Вы заметите как, если Вы замените some-cmd с bash, подсказка удара и что Вы вводите, появляется в красном (stderr) в то время как с zsh это появляется в черном цвете (потому что zsh копирует stderr на новый fd для отображения его подсказки и эха).

Это, действительно кажется, работает удивительно хорошо даже на приложения, которые Вы ожидали бы не (как те, которые действительно используют цвета).

Окрашивающий режим производится на stracestderr, который, как предполагается, является терминалом. Если приложение перенаправит свой stdout или stderr, то наш угнанный strace будет продолжать писать окрашивающие escape-последовательности на терминале.

То решение имеет свои ограничения:

  • Свойственные к strace: проблемы производительности, Вы не можете выполнить другие команды PTRACE как strace или gdb в нем, или проблемы setuid/setgid
  • Это окрашивает на основе writes на stdout/stderr каждого отдельного процесса. Так, например, в sh -c 'echo error >&2', error было бы зеленым потому что echo производит его на его stdout (какой sh, перенаправленный к stderr sh, но весь strace видит, является a write(1, "error\n", 6)). И в sh -c 'seq 1000000 | wc', seq делает много или writes к ее stdout, таким образом, обертка закончится вывод много (невидимых) escape-последовательностей к терминалу.

9
26.10.2013, 03:15
4 ответа

Я закончил ls- парсинг:

is_group_writable() {
  local ls="$(ls -ld "$1")"
  [ "${ls:5:1}" = "w" ]
}

Я благодарен за обширный ответ @slm, но ни один из других методов не так прост. stat метод потребовал бы, чтобы я записал по крайней мере два различных вызова для покрытия OS X, и даже после этого он возвращает восьмеричное представление, к которому я все еще должен применить арифметику. Метод Perl в порядке, но требует, чтобы я запустил интерпретатор для такой простой задачи, и я хотел бы сохранить это простым и использующим только posix utils.

1
27.01.2020, 20:06
  • 1
    Вы используете удар, не просто POSIX. В POSIX: perms=$(ls -ld -- "$1"); perms=${perms%% *}; case $perms in ?????w????) … –  Gilles 'SO- stop being evil' 30.10.2013, 01:14

Метод № 1 - статистика

Вы могли использовать stat команда для получения битов полномочий. stat доступно на большей части Unixes (OSX, BSD, не AIX от того, что я могу найти). Это должно работать над большей частью Unixes, кроме OSX & BSD от того, что я могу найти.

$ stat -c "%a" <file>

Пример

$ ls -l a
-rw-rw-r-- 1 saml saml 155 Oct  6 14:16 afile.txt

Используйте эту команду:

$ stat -c "%a" afile.txt
664

И используйте простое grep видеть, является ли режим полномочий групп 6 или 7.

$ stat -c "%a" afile.txt | grep ".[67]."

Для OSX и BSD необходимо было бы использовать эту форму stat, stat -f (или возможно stat -x), и синтаксический анализ соответственно. Начиная с опций к stat отличаются, Вы могли перенести эту команду в lsb_release -a управляйте и назовите соответствующую версию на основе ОС. Не идеальный, но осуществимый. Поймите это lsb_release только доступно для дистрибутивов Linux, таким образом, другая альтернатива должна была бы быть создана для тестирования других Ose Unix.

Метод № 2 - находит

Я думаю, что эта команда могла бы обслуживать Вас лучше все же. Я использую find и printf переключатель.

Пример

$ find a -prune -printf '%m\n'
664

Метод № 3 - Perl

Perl мог бы быть более портативным способом сделать это в зависимости от Ose, которые Вы пытаетесь покрыть.

$ perl -le '@pv=stat("afile.txt"); printf "%04o", $pv[2] & 07777;'
0664

Примечание: Вышеупомянутое использует Perl stat() функционируйте для запросов битов файловой системы.

Можно сделать это более компактным путем воздержания от использования массива, @pv, и имея дело с выводом stat() непосредственно:

$ perl -le 'printf "%04o", (stat("a"))[2] & 07777;'
0664
8
27.01.2020, 20:06
  • 1
    я думаю, что Вы упустили его суть 4. stat команда значительно различается среди различных систем и не является портативной. –  jordanm 26.10.2013, 04:34
  • 2
    @jordanm - благодарит, я видел его, искал альтернативу. Я думаю find . -printf может сделать это, но не может определить, доступно ли это на OSX', находят. –  slm♦ 26.10.2013, 04:40
  • 3
    я не мог найти его, сослался в руководстве POSIX2008 также, таким образом, я склонен согласиться. Я не уверен ни в каких других методах. Я думаю, что необходимо стиснуть зубы здесь и обнаружить, который ОС и называют командой approp., казалось бы, был бы лучшим подходом. –  slm♦ 26.10.2013, 04:45
  • 4
    я не мог думать о методе с помощью стандартной утилиты оболочки также. Вот почему мой ответ использует жемчуг. –  jordanm 26.10.2013, 04:49
  • 5
    @jordanm - великие умы. Я работал над решением для жемчуга также 8-) –  slm♦ 26.10.2013, 04:58

Одна опция состоит в том, чтобы использовать perl, который будет портативным везде perl доступно. Трудно найти систему Unix без него. Вот пример того, как он может быть интегрирован в сценарий оболочки:

if perl -e 'use Fcntl ":mode"; exit( ((stat("file.txt"))[2] & S_IWGRP) >> 3)'; then
    echo "file is group writable"
else
    echo "file is not group witeable"
fi

Подобный perl примеры могут быть найдены в статистике perldoc.

1
27.01.2020, 20:06
FILE="filename";G=$(stat -c '%a' ${FILE} | cut -c2);
if [ $G -gt 5 ];then   echo "Group write is set on ${FILE}";fi

Все стандартные инструменты Unix/Linux.

Я полагаю, что ВОЗМОЖНО иметь групповую запись, но не групповое чтение. В этом случае это будет либо оператор case 2|3|6|7 ), либо grep '[2|3|6|7]'

.
0
27.01.2020, 20:06

Теги

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