Карта файловой системы macOS: где что лежит и почему
Начнём с того, что ты видишь как один диск "/", на самом деле два тома APFS, склеенных firmlink-ами. Со времён Catalina (10.15) система живёт на отдельном Signed System Volume (SSV) - read-only, криптографически запечатанном. Каждый байт системы покрыт деревом хешей, корневой хеш подписан Apple. Ты грузишься не с самого тома, а с его APFS-снапшота. Поэтому /System нельзя изменить в принципе - не "нет прав", а том примонтирован только на чтение и опечатан печатью (seal).
Рядом - твой Data-том (пользовательские данные, /Users, /Applications, /opt). Два тома сшиваются firmlink-ами: это особый механизм APFS (не симлинк и не bind-mount), который делает так, что /Users физически на Data-томе выглядит как обычная папка в корне read-only System-тома. Список firmlink-ов лежит в /usr/share/firmlinks.
Структура, которую надо знать как таблицу умножения:
- /System - ОС, фреймворки, /System/Library. Read-only SSV, защищён SIP. Сюда не пишут, точка.
- /Library - общесистемные ресурсы для ВСЕХ пользователей: шрифты, /Library/LaunchDaemons и /Library/LaunchAgents (службы), /Library/Preferences, конфиги. Сюда уже можно писать (с sudo).
- /Users - домашние каталоги. /Users/Shared - общая папка.
- /Applications - приложения для всех. ~/Applications - только для тебя.
- /private - сюда симлинками ведут классические BSD-пути: /etc -> /private/etc, /var -> /private/var, /tmp -> /private/tmp. Проверь: ls -l /etc покажет стрелку на /private/etc. Это наследие BSD, корень-то занят системным томом.
- /opt/homebrew - Homebrew на Apple Silicon (на старых Intel был /usr/local). Префикс вне SIP, поэтому brew ставит туда без sudo.
- ~/Library/Preferences - .plist с настройками приложений (с ними работает defaults из прошлых уроков).
- ~/Library/Application Support - рабочие данные приложений (базы, профили).
- ~/Library/Caches - кеши, можно сносить.
- ~/Library/Containers - песочницы sandboxed-приложений (каждое видит только своё).
- ~/Library/LaunchAgents - твои пользовательские службы launchd.

POSIX-права: chmod mac, chown и почему этого мало
Базовый слой - классические права доступа mac в стиле Unix: три набора (владелец/группа/остальные) по три бита (rwx). Смотрим:
Код: Выделить всё
$ ls -l ~/Documents/report.txt
-rw-r--r--@ 1 ivan staff 10240 13 июн 14:02 report.txt
Меняем права привычно:
Код: Выделить всё
chmod 640 report.txt # rw-r----- числом
chmod u+x deploy.sh # добавить флаг выполнения владельцу
chmod -R go-w ~/project # рекурсивно снять запись у группы и остальных
chown ivan:staff report.txt # сменить владельца и группу (нужен sudo для чужих)
Почему POSIX мало? Три набора прав не выражают "Ане можно читать, Боре писать, а группе дизайнеров - только смотреть". Для этого есть второй слой.
ACL: тонкие права через chmod +a и ls -le
ACL (списки контроля доступа) дают точечные разрешения конкретным пользователям и группам поверх POSIX. macOS использует ACL в стиле NFSv4 - богаче, чем rwx. Смотреть их обычным ls -l нельзя, нужен флаг -e:
Код: Выделить всё
$ ls -le report.txt
-rw-r--r--+ 1 ivan staff 10240 13 июн 14:02 report.txt
0: user:anna allow read,write
1: group:designers deny write
Добавляем и снимаем правила синтаксисом chmod +a:
Код: Выделить всё
chmod +a "anna allow read,write" report.txt # дать Анне чтение и запись
chmod +a "designers deny write" report.txt # запретить группе запись
chmod -a "anna allow read,write" report.txt # снять конкретную ACE
chmod -a# 0 report.txt # снять ACE по номеру (нулевую)
chmod -N report.txt # снести ВСЕ ACL с файла
Код: Выделить всё
chmod +a "everyone deny writeextattr" config.plist
xattr: расширенные атрибуты и карантин com.apple.quarantine
Третий слой - xattr, метаданные, пришитые к файлу сбоку от его содержимого. Тот самый @ в ls -l. Смотрим, что висит:
Код: Выделить всё
$ xattr -l ~/Downloads/tool.dmg
com.apple.quarantine: 0083;6650a1b2;Safari;1A2B3C4D-...
com.apple.metadata:kMDItemWhereFroms: ...
Снять карантин (когда ты доверяешь источнику и понимаешь, что делаешь):
Код: Выделить всё
xattr -d com.apple.quarantine ~/Downloads/tool.app # снять один атрибут
xattr -dr com.apple.quarantine ~/Downloads/MyApp.app # рекурсивно по бандлу
xattr -cr ~/Downloads/MyApp.app # снести ВСЕ xattr рекурсивно
Что ещё прячется в xattr: resource forks (com.apple.ResourceFork) - наследие классической Mac OS, где у файла была "вилка ресурсов"; сейчас редко, но встречается. com.apple.FinderInfo, метки Finder (теги), kMDItemWhereFroms (откуда скачано), com.apple.macl (привязка приватности TCC). Когда копируешь файлы на не-APFS (FAT32, сетевые шары), xattr и resource fork выгружаются в файлы-спутники с префиксом ._ - те самые надоедливые ._filename. Утилита dot_clean их схлопывает обратно.
Флаги файлов chflags, симлинки и SIP
Четвёртый слой - флаги файлов через chflags, фишка BSD/macOS, которой в обычном Linux нет. Это не права доступа, а свойства поведения. Видны через ls с заглавной O:
Код: Выделить всё
$ ls -lO important.txt
-rw-r--r-- 1 ivan staff uchg 4096 13 июн important.txt
- hidden - скрыть из Finder (но не из ls). Так Apple прячет ~/Library. chflags nohidden ~/Library её показывает.
- uchg (uchange/uimmutable) - запрет любых изменений; снять может владелец или админ через nouchg. Удобно "залочить" важный файл от случайной правки.
- schg - системный immutable; снять можно только в single-user mode, жёстче uchg.
- uappnd - только дописывание (для логов).
- restricted - помечает путь как защищённый SIP. Именно этот флаг (вместе с com.apple.rootless xattr) делает каталог неприкасаемым даже для root.
Код: Выделить всё
chflags uchg important.txt # залочить файл
chflags nouchg important.txt # разлочить
chflags hidden secret_dir # спрятать из Finder
chflags nohidden ~/Library # показать Библиотеку
Симлинки, алиасы и firmlinks - не путай три разных зверя:
- Симлинк (ln -s) - файловая ссылка по пути, как в Unix. Ломается, если цель переименовали. Работает в терминале.
- Алиас Finder - объект уровня GUI, хранит inode цели и умеет находить её после переезда/переименования. В терминале как обычная ссылка НЕ работает.
- Firmlink - системный механизм APFS, сшивающий System и Data тома (см. начало урока). Ты их не создаёшь руками.
Код: Выделить всё
$ csrutil status
System Integrity Protection status: enabled.
Мини-лаба: пощупать все четыре слоя руками
Безопасно, в своём домашнем каталоге:
Код: Выделить всё
cd ~/Desktop && mkdir lab && cd lab
echo "secret" > file.txt
# 1) POSIX
ls -l file.txt
chmod 600 file.txt && ls -l file.txt # стало rw-------
# 2) ACL
chmod +a "$(whoami) allow read,write" file.txt
ls -le file.txt # появился + и строка ACE
chmod -N file.txt # снесли ACL, + пропал
# 3) xattr (имитируем карантин)
xattr -w com.apple.quarantine "test" file.txt
ls -l file.txt # появился @
xattr -l file.txt
xattr -d com.apple.quarantine file.txt # сняли, @ пропал
# 4) флаги
chflags uchg file.txt
ls -lO file.txt # видно uchg
rm file.txt # Operation not permitted!
chflags nouchg file.txt && rm file.txt # теперь удалится
cd .. && rmdir lab
Контрольные вопросы
- Чем отличается символ @ от символа + в выводе ls -l, и какой командой смотреть каждый из них?
- Почему файл с правами rw-r--r-- не удаляется даже владельцем, и как это исправить одной командой?
- Что такое com.apple.quarantine, кто его навешивает и чем рискуешь, снимая его вручную?
- Почему sudo rm не работает в /System, и какой командой проверить причину?
Права в macOS - это стек: POSIX (грубо), ACL (точечно, ls -le / chmod +a), xattr (метаданные и карантин, ls -l @, xattr), флаги (поведение, ls -lO / chflags) и поверх всего SIP. Когда что-то "не пускает", не долби chmod - определи СЛОЙ: проверь +, @, uchg и csrutil. Знаешь карту /System, /Library, ~/Library и четыре слоя прав - и загадочные "permission denied" превращаются в понятную диагностику за тридцать секунд.