Некоторое время занимаюсь разбором игровых форматов. Одна из основных проблем заключается в тестировании и последующей эксплуатации инструментария, когда требуется вначале достать файл из архива (обычно, двойного уровня вложенности со сжатием и шифрованием), а затем упихать обратно после внесения изменений.
С недавних пор стал поглядывать в сторону dokany.
Уже написал обвязку для маунта архива на файловую систему и чтения из него. Но потребуется написать и отладить ещё много кода для поддержки многопоточной записи, дефрагментации и т.д.
И тут подумалось — а за каким лешим я реализую собственную файловую систему с поддержкой записи, когда мне нужно просто распаковать архив в папочку и перенаправить все обращения к оригинальному файлу на эти самые распакованные?
И вот встал вопрос — какими инструментами это можно сделать? На ум приходят в первую очередь Reparse Points с самописным драйвером.
Но есть минусы:
1) Это сложно.
2) Я этого никогда не делал.
В связи с чем вопросы:
1) Есть ли альтернативы?
2) Есть ли возможность описать всё средствами .NET (всевозможные фреймворки и сторонние драйверы с любой лицензией, подобные dokany, привествтуются).
3) Если всё-таки придётся идти сложным путём, может быть кто-нибудь поделится примером кода, который делает описанное выше? Например, первые пять байт из файла D:\archive.bin считываются из файла D:\archive\1.bin, а всё остальное из D:\archive\2.bin ?
Ограничения:
Платформа — Windows
Совместимость с Memory Mapped File
Поддержка многопоточного случайного доступа
Спасибо за любую помощь!
"Хаос всегда побеждает порядок, поскольку лучше организован." (с) Терри Пратчетт
Здравствуйте, Михаил Романов, Вы писали:
МР>Здравствуйте, Albeoris, Вы писали:
МР>А почему не подходит просто упаковка и распаковка файла через какую-нибудь библиотеку или утилиту? МР>Почему нужно обязательно это делать "на лету"?
Потому что файл весит 28 Гб и на данный момент приходится поддерживать много инфраструктурного кода в "какой-нибудь утилите", чтобы обеспечить чтение и вставку файлов.
"Хаос всегда побеждает порядок, поскольку лучше организован." (с) Терри Пратчетт
Re[3]: Перенаправление чтения из файла (Reparse Points?)
Здравствуйте, Albeoris, Вы писали:
A>Потому что файл весит 28 Гб и на данный момент приходится поддерживать много инфраструктурного кода в "какой-нибудь утилите", чтобы обеспечить чтение и вставку файлов.
Я не очень понял оба аргумента.
Что именно плохого в 28 Гб? Ну будет у вас лежать на диске 60Гб... Мне всё же кажется, что покупка винчестера выйдет дешевле человеко-часов на разработку драйвера вашей FS (а у вас в любом случае будет что-то сравнимое по сложности, если вы собираетесь перекрывать стандартный файловый ввод-вывод).
Какие еще сложности помимо удвоения объема?
И еще менее понятен тезис про поддержку инфраструктурного кода. У вас ведь в любом случае есть код для парсинга/создания этого файла. Неужели, утилита на основе этой библиотеки выполняющая всего 2 операции — выложить файл как структуру папок и собрать из структуры папок новый файл будет такой сложной в поддержке?
Может я просто не понимаю специфики вашего случая, но мне казалось что самое простое, это:
Разложить исходный файл на составные части. Если они будут еще и не слишком большими, то вы получите в качестве бонуса хотябы теоретическую возможность держать их в системе контроля версий (хотя имеет ли это смысл — зависит от того как идет работа с этими файлами).
Поработать с этими составными частями
В какой-то момент при сборке проекта собрать из этих составных частей новый общий файл (для ускорения, возможно, можно будет сделать инкрементальное обновление — т.е. занести в исходный файл только измененные части, а также новыее и удалить удаленные).
Я бы попытался остановиться на таком сценарии и никак не сложнее.
Re[4]: Перенаправление чтения из файла (Reparse Points?)
Здравствуйте, Михаил Романов, Вы писали:
МР>Я не очень понял оба аргумента.
Аргумент номер 0: Я спрашиваю как перенаправить вызов к файлу в другое место, а не как этого не делать.
Аргумент номер 1: Для того чтобы вытащить файл из зишфрованного сжатого архива, необходимо его расшифровать и разжать. Ждать по 5 минут для того чтобы получить один единственный файл — накладно.
Аргумент номер 2: Для того чтобы воткнуть файл в зашифрованный сжатый архив с механизмом контроля целостности, необходимо его расшифровать и разжать, посчитать контрольные суммы всех файлов, заменить один из них своим, если он не помещается в старое место — переложить его в конец архива, если это происходит в архиве второго уровня вложенности, проделать это ещё и с ним, после чего собрать все файлы в архив, сжать и зашифровать их, обновить индексы. Ждать по 40 минут и занимать по 60Гб места на диске для того чтобы добавить в архив один файл — очень накладно. Синхронизировать чтение и запись в это архив — ещё веселее.
Зачем делать это, если можно просто положить рядом новый файл, читать из него, если он есть, или из оригинала, если его нет?
МР>Что именно плохого в 28 Гб? Ну будет у вас лежать на диске 60Гб... Мне всё же кажется, что покупка винчестера выйдет дешевле человеко-часов на разработку драйвера вашей FS (а у вас в любом случае будет что-то сравнимое по сложности, если вы собираетесь перекрывать стандартный файловый ввод-вывод).
Я морально не готов покупать винчестер каждому пользователю. Как я писал ранее, мне не нужно перекрывать стандартный файловый ввод, только вывод, что упрощает задачу до примитивного уровня. Осталось лишь найти подходящий инструмент.
МР>И еще менее понятен тезис про поддержку инфраструктурного кода. У вас ведь в любом случае есть код для парсинга/создания этого файла. Неужели, утилита на основе этой библиотеки выполняющая всего 2 операции — выложить файл как структуру папок и собрать из структуры папок новый файл будет такой сложной в поддержке?
Эта утилита также представляет содержимое многомерного архива в виде файлового древа, умеет работать в режиме случайного доступа и параллельного чтения/записи. И, фактически, 80% кода, который сейчас написан (включая интерфейс — окна, диалоги) направлен на поддержку именно этой части.
МР>Может я просто не понимаю специфики вашего случая, но мне казалось что самое простое, это: МР>
МР>Разложить исходный файл на составные части. Если они будут еще и не слишком большими, то вы получите в качестве бонуса хотябы теоретическую возможность держать их в системе контроля версий (хотя имеет ли это смысл — зависит от того как идет работа с этими файлами). МР>Поработать с этими составными частями МР>В какой-то момент при сборке проекта собрать из этих составных частей новый общий файл (для ускорения, возможно, можно будет сделать инкрементальное обновление — т.е. занести в исходный файл только измененные части, а также новыее и удалить удаленные). МР>
Так происходит сейчас.
МР>Я бы попытался остановиться на таком сценарии и никак не сложнее.
Я пробовал, мне не понравилось.
"Хаос всегда побеждает порядок, поскольку лучше организован." (с) Терри Пратчетт
Re: Перенаправление чтения из файла (Reparse Points?)
Собственно, сейчас вернулся к dokany.
Он, к сожалению, не умеет монтировать виртуальные файлы на файловую ситсему, а примаунченая папка считается другим диском, на который NTFS не может создать hard link. Но если пропускать все обращения к конкретной папке через драйвер, то это работает.
http://i.imgur.com/FAGMC9y.png
Оригинальные файлы лежат в папочке "_sys". Все обращения к "sys" пропускаются через драйвер, который отдаёт то, что нужно мне.
Не самое красивое решение, так как при необходимости заменить 1-2 файла приходится виртуализировать всю папку.
Также был найден некий CallbackFilter, который делает примерно тоже самое, но уже за деньги.
Так что я всё ещё в поиске.
"Хаос всегда побеждает порядок, поскольку лучше организован." (с) Терри Пратчетт