Однажды передо мной встала задача показать файлы с удаленного сервера нативно в Finder. Первое, что пришло на ум, — использовать WebDAV, но это был публичный сервис, к серверу которого у меня не было доступа, а в распоряжении имелся только REST API. В голове промелькнула мысль написать свою файловую систему, но она казалась слишком амбициозной. Однако мои сомнения развеялись, когда я обнаружил, что сообщество энтузиастов развивает проект FUSE for macOS, который сводит создание собственной файловой системы к нескольким сотням строк кода. А идущий в комплекте фреймворк не требует унылых разбирательств с API на голом C и вполне пригоден для использования в комплекте с современным и мощным Swift.
 

Что такое 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 сейчас довольно низкая.

Где еще используется FUSE?

Загрузка ... Загрузка ...
 

Установка фреймворка

Установка не отличается сложностью: скачиваешь инсталлятор с сайта разработчика и запускаешь его. Если предпочитаешь собирать такие вещи из исходников, то это тоже не составит труда: достаточно установить зависимости через brew и запустить сборочный скрипт, все это подробно описано в Readme на GitHub.

 

Настройка проекта

Создание нового проекта в Xcode
Создание нового проекта в Xcode

Создадим новый проект в Xcode. Это должно быть Cocoa Application (в разделе macOS), я назвал его HelloFuse, язык выберем Swift, остальные параметры можно выбрать на свое усмотрение.

 

Подключим фреймворк

Расположение фреймворка OSXFUSE
Расположение фреймворка OSXFUSE

После установки фреймворк будет расположен по следующему пути: /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
Подключаем Bridging Header в настройках проекта
Подключаем Bridging Header в настройках проекта
 

Отключим Sandbox

По умолчанию во всех приложениях включена песочница, которая ограничивает возможности приложения, но в отличие от iOS на macOS ее можно отключить. Этим ты потеряешь право распространять приложение через App Store (что тоже не будет проблемой в случае с macOS), но в нашем случае нам нужен полноценный доступ к файловой системе, поэтому выбора нет.

Перейдем на вкладку Capabilities в настройках сборки и поставим переключатель в пункте App Sandbox в положение OFF.

 

Hello world

 

Описание файловой системы

Поведение файловой системы описывается в отдельном классе. Создадим класс под названием HelloFS и унаследуем его от NSObject. В минимальном примере нам понадобится реализовать только два метода: получение списка файлов, который мы будем отображать, и содержимое каждого файла.

В методе, отвечающем за отображение файлов, нужно вернуть массив строк с именами файла. В качестве параметра туда приходит путь (path), в более сложных случаях нужно будет его обрабатывать, чтобы показывать контент соответствующей директории. Здесь я просто возвращаю один файл hello.txt.

override func contentsOfDirectory(atPath path: String) throws &rarr; [Any] {
    return ["hello.txt"]
}

В метод, который отвечает за отображение пути файла, аналогично приходит путь, в зависимости от которого мы должны решить, какое содержимое отдавать для файла. В нашем же примере мы будем для всех файлов возвращать строку «Hello world!».

override func contents(atPath path: String) &rarr; Data? {
    return  "Hello world!".data(using: .utf8)
}

В итоге файл HelloFS.swift примет следующий вид:

import Foundation

final class HelloFS: NSObject {

    override func contentsOfDirectory(atPath path: String) throws &rarr; [Any] {
        return ["hello.txt"]
    }

    override func contents(atPath path: String) &rarr; Data? {
        return  "Hello world!".data(using: .utf8)
    }

}

Продолжение доступно только подписчикам

Вариант 1. Оформи подписку на «Хакер», чтобы читать все материалы на сайте

Подписка позволит тебе в течение указанного срока читать ВСЕ платные материалы сайта. Мы принимаем оплату банковскими картами, электронными деньгами и переводами со счетов мобильных операторов. Подробнее о подписке

Вариант 2. Купи один материал

Заинтересовала информация, но нет возможности оплатить подписку? Тогда этот вариант для тебя! Обрати внимание: этот способ покупки доступен только для материалов, опубликованных более двух месяцев назад.


Оставить мнение

Check Also

Эхо кибервойны. Как NotPetya чуть не потопил крупнейшего морского перевозчика грузов

Российское кибероружие, построенное на утекших у АНБ эксплоитах, маскировалось под вирус-в…