Содержание статьи
- Что такое FUSE?
- Установка фреймворка
- Настройка проекта
- Подключим фреймворк
- Создадим Bridging Header
- Отключим Sandbox
- Hello world
- Описание файловой системы
- Инициализация файловой системы
- Установка собственной иконки для раздела
- Файловая система для фото из VK
- Модели данных
- Сервис для получения данных
- Описание файловой системы
- Что дальше?
- Выводы и предостережения
Что такое FUSE?
FUSE (Filesystem in Userspace) — это интерфейс для программ пространства пользователя, позволяющий экспортировать файловую систему ядру ОС. Этот механизм появился в Linux, и условно его можно разделить на два базовых компонента: модуль ядра (поддерживается разработчиками ядра) и библиотека пользовательского пространства (libfuse). Эта библиотека предоставляет методы для монтирования, размонтирования, отправки запросов к ядру и получения ответов от него. Также она реализует удобный верхнеуровневый API, в котором мы можем оперировать привычными понятиями имен файлов и путей, вместо работы с inode.
Проект FUSE for macOS представляет собой аналогичный набор API (а также Objective-C фреймворк), позволяющий реализовать полноценную файловую систему, которая будет работать в пространстве пользователя на macOS. Так как его API является надмножеством FUSE API из Linux, то существует теоретическая возможность завести многие из существующих файловых систем на macOS. В настоящее время этот проект остается единственной реализацией FUSE для macOS, которая развивается и поддерживается силами сообщества, хотя и активность на GitHub и в Google Groups сейчас довольно низкая.
Установка фреймворка
Установка не отличается сложностью: скачиваешь инсталлятор с сайта разработчика и запускаешь его. Если предпочитаешь собирать такие вещи из исходников, то это тоже не составит труда: достаточно установить зависимости через brew и запустить сборочный скрипт, все это подробно описано в Readme на GitHub.
Настройка проекта
Создадим новый проект в Xcode. Это должно быть Cocoa Application (в разделе macOS), я назвал его HelloFuse, язык выберем Swift, остальные параметры можно выбрать на свое усмотрение.
Подключим фреймворк
После установки фреймворк будет расположен по следующему пути: /Library/Frameworks/OSXFUSE.framework
. Чтобы добавить его в проект, достаточно просто перетащить его в раздел Linked Frameworks and Libraries на вкладке General настроек сборки.
Создадим Bridging Header
Так как мы пишем проект на Swift, а фреймворк реализован на Objective-C, то нам нужно создать и подключить так называемый Bridging Header. Создадим заголовочный файл (File → New → File → macOS → Source → Header File), назовем его HelloFuse-Bridging-Header.h
и добавим в него следующую строчку:
#import <OSXFUSE/OSXFUSE.h>
Теперь на панели навигации выбираем наш проект, выбираем сборку в разделе Targets, переходим на вкладку Build Settings, находим раздел Swift Compiler → General, в поле Objective-C Bridging Header добавляем
$(PROJECT_DIR)/$(TARGET_NAME)/HelloFuse-Bridging-Header.h
Отключим Sandbox
По умолчанию во всех приложениях включена песочница, которая ограничивает возможности приложения, но в отличие от iOS на macOS ее можно отключить. Этим ты потеряешь право распространять приложение через App Store (что тоже не будет проблемой в случае с macOS), но в нашем случае нам нужен полноценный доступ к файловой системе, поэтому выбора нет.
Перейдем на вкладку Capabilities в настройках сборки и поставим переключатель в пункте App Sandbox в положение OFF.
Hello world
Описание файловой системы
Поведение файловой системы описывается в отдельном классе. Создадим класс под названием HelloFS и унаследуем его от NSObject. В минимальном примере нам понадобится реализовать только два метода: получение списка файлов, который мы будем отображать, и содержимое каждого файла.
В методе, отвечающем за отображение файлов, нужно вернуть массив строк с именами файла. В качестве параметра туда приходит путь (path), в более сложных случаях нужно будет его обрабатывать, чтобы показывать контент соответствующей директории. Здесь я просто возвращаю один файл hello.txt
.
override func contentsOfDirectory(atPath path: String) throws → [Any] {
return ["hello.txt"]
}
В метод, который отвечает за отображение пути файла, аналогично приходит путь, в зависимости от которого мы должны решить, какое содержимое отдавать для файла. В нашем же примере мы будем для всех файлов возвращать строку «Hello world!».
override func contents(atPath path: String) → Data? {
return "Hello world!".data(using: .utf8)
}
В итоге файл HelloFS.swift
примет следующий вид:
import Foundation
final class HelloFS: NSObject {
override func contentsOfDirectory(atPath path: String) throws → [Any] {
return ["hello.txt"]
}
override func contents(atPath path: String) → Data? {
return "Hello world!".data(using: .utf8)
}
}
Продолжение доступно только участникам
Вариант 1. Присоединись к сообществу «Xakep.ru», чтобы читать все материалы на сайте
Членство в сообществе в течение указанного срока откроет тебе доступ ко ВСЕМ материалам «Хакера», позволит скачивать выпуски в PDF, отключит рекламу на сайте и увеличит личную накопительную скидку! Подробнее
Вариант 2. Открой один материал
Заинтересовала статья, но нет возможности стать членом клуба «Xakep.ru»? Тогда этот вариант для тебя! Обрати внимание: этот способ подходит только для статей, опубликованных более двух месяцев назад.
Я уже участник «Xakep.ru»