Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

multiarc rearrangement #775

Open
unxed opened this issue Oct 7, 2020 · 52 comments
Open

multiarc rearrangement #775

unxed opened this issue Oct 7, 2020 · 52 comments

Comments

@unxed
Copy link
Contributor

unxed commented Oct 7, 2020

Consider using unar for archives unpacking in multiarc

Pros:

— support filenames charset specification for OEM archives (-e CHARSET) on ALL platforms (linux, macos, freebsd) — compare with unzip with unpredictable -I/-O options support per OS
— supports password protected archives
— with "retry logic" (doing "-e utf8" and, if it fails, retrying with "-e OEMCP") it processed all my test zips well
— supports .tar.gz correctly, without the need to unpack the whole archive to process single file
— supports bunch of legacy formats like ARJ, ACE, ARC, LZH — currently far2l is unable to unpack them without separate external tools for each
— unar is packaged for almost every OS in the world, including OpenWRT
— and yes, command line unar is LGPL licensed https://en.wikipedia.org/wiki/The_Unarchiver

Cons:

— new dependency (~1,2 Mb .deb size on Ubuntu) (but we can import its sources and build as static library)
— unpacker only, can not add or delete files to/from archives — leaves the need to use separate tools for that

Still with unar we at least can READ all archive formats correctly on ALL platforms without weird charsets problems.

https://theunarchiver.com/
https://theunarchiver.com/command-line
https://www.systutorials.com/docs/linux/man/1-unar/
https://formulae.brew.sh/formula/unar
https://www.freebsd.org/cgi/man.cgi?query=unar&apropos=0&sektion=1

PS: code page names need translation for unar: for example, it treats code page "cp932" as "windows-31j". this is also actual for oem cps 720 (ibm-720_P100-1997), 950 (ibm-950_P110-1999), 949 (windows-949-2000), 874 (windows-874-2000), 1258 (windows-1258). same translation may be needed for ansi CPs.

@elfmz
Copy link
Owner

elfmz commented Oct 7, 2020

see comment on #773

@unxed
Copy link
Contributor Author

unxed commented Oct 7, 2020

For archives creation/modification we can use:
— libarchive for 7z/tar/cpiogz/.tar.gz/ISO — it already does the job well
— zip (with "-d" workaround) for zips (or also libarchive if zip creation/modification using it is fixed)
— separate specific tools for all other formats (very, very rare cases... so user have to install additional software, ok)

btw, собрал в табличку поддержку .zip разным софтом вот. Помимо всего этого есть ещё libzip, она как minizip, но с поддержкой шифрованных зипов; возможности задавать свою кодировку для OEM архивов тоже нет.
Снимок экрана в 2020-10-07 23-48-14

@elfmz
Copy link
Owner

elfmz commented Oct 7, 2020

i guess bug can be closed now?

@unxed
Copy link
Contributor Author

unxed commented Oct 7, 2020

It's about unar, not unrar. It's two completely different tools :)

I suggested unar as general purpose unpacking solution with good charset support, not only to fix .rar problems.

@unxed
Copy link
Contributor Author

unxed commented Oct 8, 2020

btw, просьба глянуть ПР #766 — я там избавился от повторных вызовов zip/unzip, правильная кодировка сразу теперь задается (препроцессор-то зипный её ведь знает, раз файл смог показать правильно).

И ещё там удаление файлов из архивов в ANSI кодировке (редко, но встречаются) поправлено.

@elfmz
Copy link
Owner

elfmz commented Oct 8, 2020

Не нравится мне такая массированная инкостыляция.
Кроме того я тут обнаружил что если в libarchive в нужном месте в нужное время вызвать такую функцию...:
archive_read_set_options(_arc, "hdrcharset=CP866")
..то досовские зипы начинают волшебным образом открываться.

@unxed
Copy link
Contributor Author

unxed commented Oct 8, 2020

Кроме того я тут обнаружил что если в libarchive в нужном месте в нужное время вызвать такую функцию...:
archive_read_set_options(_arc, "hdrcharset=CP866")
..то досовские зипы начинают волшебным образом открываться.

Здорово, если это сработает :) btw, зипы ещё и ANSI'шные бывают. Нужно тогда смотреть, какую кодировку выбрал препарсер, и такую и выставлять. Кстати, в определении ANSI'шных архивов в препарсере сидит бага: вместо ZipHeader.PackVer>20 должно быть ZipHeader.PackVer>=20 (по крайней мере, современный винзип именно 20 использует, когда ему приходит в голову писать архив в ANSI).

Ещё кстати, преобразование локаль -> кодовая страница для ANSI в этом же PR лежит ;-)

UPD 2024-05-26: В архивах WinZip с ANSI есть и Unicode поля, там ANSI использовать не надо.

@unxed
Copy link
Contributor Author

unxed commented Oct 8, 2020

Ух ты! bsdtar x --option hdrcharset=cp866 -f windows_cyrillic.zip и правда работает :) Причем я знал об этом ещё в июле, но как-то вылетело из головы.

archive_read_set_options(_arc, "hdrcharset=CP866")

А это можно где-нибудь потрогать? Ну в бранче там ;)

@unxed
Copy link
Contributor Author

unxed commented Oct 8, 2020

hdrcharset=cp866 не прокатывает с macos.zip и new2.zip (это как раз в ansi) из моего тестового набора. То есть, надо именно запоминать, какую кодировку определил препарсер, и перед обращением к конкретному файлу (да, разные файлы могут быть в разных кодировках — архив мог один упаковщик создать, другой дописать и тд) выставлять конкретно её. Тогда ок

@elfmz
Copy link
Owner

elfmz commented Oct 8, 2020

или втянуть код определения кодировки в обработчик libarch
ветка https://github.com/elfmz/far2l/tree/improving-libarch

@unxed
Copy link
Contributor Author

unxed commented Oct 8, 2020

Погонял! Здорово :)

Обнаруженные проблемы:

— три файла из моего тестового набора пока что не распаковывает (23-10-2012-b-fasi-eaep_greek.zip, macos.zip и new2.zip)
— при попытке удаления файла из архива иногда портит вместо этого его кодировку (те же три файла)
— вместо создания зипов всё ещё создаются .zip.gz (судя по содержимому)

@unxed
Copy link
Contributor Author

unxed commented Oct 8, 2020

Для всех трех проблемных файлов отключение hdrcharset решает проблему. То есть вот комментишь LibArchCall(archive_read_set_options, _arc, (const char *)opt_hdrcharset); — и эти три начинают работать (но ожидаемо ломаются «досовские»).

То есть, простейшим решением тут будет в случае ненахода нужного файла в архиве делать retry с отключенной hdrcharset.

или втянуть код определения кодировки в обработчик libarch

Хотя так, конечно, было бы прикольнее.

@unxed
Copy link
Contributor Author

unxed commented Oct 8, 2020

Ещё: для .tar.gz вообще не надо по умолчанию OEM кодировку ставить))) Только для .zip'ов.

@unxed
Copy link
Contributor Author

unxed commented Oct 9, 2020

Сделал тут скриптик на Perl'e, повторяющий работу препарсера нашего, и показывающий, чего там живет внутри зипа и по какому принципу имя файла правильно выбирается и декодируется. Очень наглядная штука получилась. Вот, вдруг пригодится https://github.com/unxed/oemcp/blob/master/ziplist

И, да, бывают зипы, в которых у разных файлов имена в разных кодировках (на винде создали, на линуксе дописали, скажем). Например, win_and_linux_mixed.zip

@elfmz
Copy link
Owner

elfmz commented Oct 10, 2020

поддопилил improving-libarch ща мона серъезней тестить

@unxed
Copy link
Contributor Author

unxed commented Oct 10, 2020

поддопилил improving-libarch ща мона серъезней тестить

Погонял. Очень здорово! Кое-что странное всё ж нашел, отписался там в каментах к коммиту :)

@elfmz
Copy link
Owner

elfmz commented Oct 10, 2020

если это комент к тому комиту то оно уже не актуально, допилил я именно вот ща

@elfmz
Copy link
Owner

elfmz commented Oct 10, 2020

кстати выбранная на тот момент для чарсета %%S оказалась занята, теперь юзается %%T, то есть надо ресетнуть командлайны.

@unxed
Copy link
Contributor Author

unxed commented Oct 10, 2020

если это комент к тому комиту то оно уже не актуально, допилил я именно вот ща

Спасибо! Перепроверяю

@unxed
Copy link
Contributor Author

unxed commented Oct 10, 2020

Ура, проблемы с удалением файлов из zip архивов ушли!

А вот что осталось:
— far2l показывает "Read error" после удаления последнего файла из .tar.gz
— вместо создания .zip создаются .zip.gz

И ещё, при удалении (по факту - перепаковке, как я вижу) создаются новые архивы, которые будут не читабельны штатным архиватором винды, потому что OEM-версии имен файлов там нету. Гуманно было бы всё ж писать туда и OEM и UTF8 (0x7075) версии имен файлов, если они пролезают в OEM кодировку (поставив PackOS в 0; если не пролезают в OEM, но пролезают в ANSI, можно использовать её, поставив PackOS в 11 и PackerVer в 20). Собственно, многие современные архиваторы с винды так и делают.

А вообще, очень здоровская штука получается!

@elfmz
Copy link
Owner

elfmz commented Oct 10, 2020

  • .zip.gz - это было смешно, но пофиксил.
  • попробовал эти новые архивы (с русскими именами файлов внутри) под виндой 2008r2 (да я такой) - распаковываются как штатным распаковщиком, так и внештатными, в лице FAR Manager и WinRAR. Возможно какой нить Norton Commander их и не поймет, но оно того не стоит. Я вообще не уверен что могу настроить либархив на таком уровне.

@elfmz
Copy link
Owner

elfmz commented Oct 10, 2020

ошибку на пустых архивах тож пофиксил

@unxed
Copy link
Contributor Author

unxed commented Oct 10, 2020

попробовал эти новые архивы (с русскими именами файлов внутри) под виндой 2008r2 (да я такой) - распаковываются как штатным распаковщиком, так и внештатными, в лице FAR Manager и WinRAR

А, ок! Если современная винда с настройками по умолчанию и правда в состоянии нормально открывать такое, то, конечно, можно так и оставить. А пользователи XP пускай сами заботятся о том, чтобы поставить себе 7-zip, который тоже всё прекрасно съест :)

Создание .zip.gz и пустые .tar.gz — подтверждаю, исправлено!

Круть. Неужели на *nix будет первый менеджер архивов, который правильно обращается с зипами из коробки? Даже не верится :) Надеюсь, по крайней мере, libarchive на всех платформах ведет себя одинаково, а то могут быть неожиданные сюрпризы.

@elfmz
Copy link
Owner

elfmz commented Oct 10, 2020

Думаю на ХР тоже все будет ок, она юникодная внутри - было бы глупо не понимать юникодные зипы.
Жоские OEM/ANSI - это из области Win9x

@unxed
Copy link
Contributor Author

unxed commented Oct 11, 2020

Ну что же, зипы классно теперь работают, по-моему :)

Workaround для "zip -d" только там остался в коде (для систем со старой libarchive, видимо), и в нём остался баг: WINPORT(WideCharToMultiByte)(CP_OEMCP, 0, wstr.c_str(), когда не может декодировать какой-то символ, возвращает вместо него "?", который zip понимает как wildcard. В результате если локаль не соответствует кодировке архива, вместо одного файла могут удалиться несколько. Пример: ставим локаль el_GR.UTF-8 и удаляем "абвгде" отсюда winzip.zip, "жзийкл" удалится тоже.

Ещё автоопределение ANSI кодировки стоит добавить (табличка тут есть), а то иначе в нерусских локалях в редакторе выбор кодировки выглядит странно: для OEM (DOS) предлагается системная, а для ANSI — всегда кириллическая 1251. Ну и ещё из-за отсутствия учёта ANSI workaround для "zip -d" не может удалить файл отсюда new2.zip.

@unxed
Copy link
Contributor Author

unxed commented Oct 11, 2020

Видел последние коммиты, ура!

Для "unzip" и "zip -d", кстати, лучше использовать определенную кодировку, а не всегда предполагать OEM. Это исправит удаление из того же new2.zip. То есть, вместо
WINPORT(WideCharToMultiByte)(CP_OEMCP, 0, wstr.c_str(),
делаем
WINPORT(WideCharToMultiByte)(Info->Codepage, 0, wstr.c_str(),
Ну и:
CommandRetry.insert(6, StrPrintf("-I CP%u -O CP%u ", actual_oemcp, actual_oemcp));
->
CommandRetry.insert(6, StrPrintf("-I CP%u -O CP%u ", Info->Codepage, Info->Codepage));

Кстати, а почему условие для определения ANSI именно такое:

  } else if (ZipHeader.PackOS==11 && ZipHeader.PackVer>20) { // && ZipHeader.PackVer<25

?

@elfmz
Copy link
Owner

elfmz commented Oct 11, 2020

Хз почему оно такое изначально - не я писал, а убрал верхнее ограничение потому что это показалось неправильным. Чисто интуитивно :)

@unxed
Copy link
Contributor Author

unxed commented Oct 11, 2020

Чисто интуитивно :)

Чисто интуитивно из всех моих тестовых зипов PackOS == 11 есть только в одном, и в нём единственном как раз ANSI. Вот в этом самом new2.zip как раз :) То есть, возможно, там вообще одной проверки на PackOS достаточно. Но хз, как там себя древние архиваторы вели и что куда писали.

UPD 2024-05-26: В new2.zip есть и UnicodePath, там поля для однобайтных кодировок вообще использовать не надо.

@elfmz
Copy link
Owner

elfmz commented Oct 11, 2020

то есть вместо >20 поставить >=20?

@unxed
Copy link
Contributor Author

unxed commented Oct 11, 2020

ага

@unxed
Copy link
Contributor Author

unxed commented Oct 11, 2020

а о верхнем ограничении будем думать, если попадутся примеры, оправдывающие его необходимость :))

@unxed
Copy link
Contributor Author

unxed commented Oct 11, 2020

Во, класс!

Теперь, если уж происходит большое наведение порядка в multiarc, осталось разобраться со всякими ace/arc/arj/lhz/ha. Сейчас из них ничего толком не работает. Варианты тут видятся такие:
— вообще выпилить
— актуализировать командные строки (актуальные убунтовые пакеты, которые могут пригодиться — unace, nomarch, arj, lhasa или jlha-utils, но как ними со всеми на макоси и бсд — не понятно)
— прописать в распаковку командные строки для unar, который это всё (кроме ha) умеет и точно есть для всех платформ, ha выпилить, на упаковку забить
— для lha/lhz заюзать libarchive, которая его уметь должна

@elfmz
Copy link
Owner

elfmz commented Oct 11, 2020

либархив наверное многое умеет распаковывать, да, но нужны живые экземпляры архивов для вивесекции

@unxed
Copy link
Contributor Author

unxed commented Oct 11, 2020

  1. Собираем с ZIP_LIBARCHIVE 0
  2. Пробуем удалить файл из new2.zip
  3. Удивляемся тому, как far2l вылетает

@elfmz
Copy link
Owner

elfmz commented Oct 11, 2020

..когданить в светлом будущем, когда илон маск будет похоронен на Фобосе, у far2l появятся функциональные автотесты..

@unxed
Copy link
Contributor Author

unxed commented Oct 11, 2020

либархив наверное многое умеет распаковывать, да, но нужны живые экземпляры архивов для вивесекции

arj убунтовый согласился создать архивчик. русские имена файлов сунул туда в utf8, уж не знаю, по стандарту так положено или он просто использует системну кодировку, не разбираясь. lha из jlha-utils согласился создать .lha, но русские буквы упрямо писал туда как ????, поэтому сделал только с английскими пока. остальное искать в сети надо, видимо - попробую сейчас

exotic.zip

@unxed
Copy link
Contributor Author

unxed commented Oct 11, 2020

@unxed
Copy link
Contributor Author

unxed commented Oct 11, 2020

ha более-менее собирается и работает, http://www.ibiblio.org/pub/Linux/utils/compress/ha0999p-linux.tar.gz
пример архива (всё пакую сверху в .zip, иначе гитхаб не прикрепляет) test.zip

@unxed
Copy link
Contributor Author

unxed commented Oct 11, 2020

ace: создаётся вот этой тулзой (работает под wine). имена файлов пишет в OEM. пример WinAce.zip

@unxed
Copy link
Contributor Author

unxed commented Oct 11, 2020

Вроде, для всех примеры нашёл или смог создать (но вот русские примеры получились не для всех, увы). Тут, конечно, не будет такого многообразия тестовых файлов, как для .zip'ов — с разных систем, с разных упаковщиков. Ну так и форматы не столь популярные — хоть как-нибудь распаковывались бы, а для особых случаев есть convmv.

@unxed
Copy link
Contributor Author

unxed commented Oct 11, 2020

А, блин! :)) Понял, почему из new2.zip не удаляется с ZIP_LIBARCHIVE 0. Там же есть вторая версия имени файла, в 0x7075. И этот факт сбрасывает Info->Codepage в 0. А консольный zip имена файлов в 0x7075 понимать не хочет, и ждёт имя файла в данном случае в ANSI.

UPD: Исправлено в ea8fddc, ура!

@unxed unxed changed the title Consider using unar for archives unpacking in multiarc multiarc rearrangement Oct 11, 2020
@unxed
Copy link
Contributor Author

unxed commented Oct 11, 2020

Примеры ace, arc, arj, ha, lha (= lzh) одним архивом
exotic_full.zip

И ещё, сюда же. Может быть, стоит чтение/запись 7z и чтение rar на libarch тоже перевести тогда? Чтоб не тащить дополнительный код и не следить за его актуальностью в дальшнейшем.

И ещё попытка создать архив .lzh не работает, надо command lines переписать под jlha-utils, он умеет создавать архивы.

И ещё извлечение из arj не-корневой папки извлекает всё поддерево. Например, если извлечь "тестовая папка 1" из моего тестового архива, извлечется "test" и уже в ней "тестовая папка 1".

@elfmz
Copy link
Owner

elfmz commented Oct 11, 2020

"чтение/запись 7z и чтение rar на libarch тоже перевести тогда?" не самые древние версии либархивы не умеют в запароленные архиве и думаю другие проблемы могут быть. Пока явных причин переделать нету - пускай остается

@unxed
Copy link
Contributor Author

unxed commented Oct 13, 2020

А зачем при создании зипа добавляется вот такое?

/home/unxed/runcity/current/2020/1$ "/usr/lib/far2l/far2l" --libexec "/usr/lib/far2l/Plugins/multiarc/plug/multiarc.far-plug
-mb" BuiltinMain libarch a:zip rst5.zip -@ -cs=CP21871 -- "rst5.sql"

@unxed
Copy link
Contributor Author

unxed commented Oct 20, 2020

Оу, странность какая. При попытке создать .zip архив multiarc передает в ^libarch какую-то дичь вместо кодировки:

/home/unxed/12345$ "/usr/lib/far2l/far2l" --libexec "/usr/lib/far2l/Plugins/multiarc/plug/multiarc.far-plug-mb" BuiltinMain libarch A:zip test.zip -@ -cs=CP110 -- "test/"

Локаль ru_RU.UTF-8

На работоспособность это не влияет, но выглядит странно.

@Nomad1
Copy link

Nomad1 commented Dec 4, 2020

Может не в ту тему, но все же:

  • если архивы созданы libarch, то не показывается содержимое вложенных папок. для сторонних архивов все ок
  • дата в архивах libarch теперь 1 января 1980 года.

Наблюдается на OSX 11.0.1.

Файл Temp.zip - создан libarch
Файл MacTemp.zip - создан маковским встроенным архиватором

Стало заметно с переходом от какой-то дремучей версии на HEAD-4766014

Скрины:
Screen mac
Screen libarch

@elfmz
Copy link
Owner

elfmz commented Dec 7, 2020

2Nomad1 в тему, вроде починил

@Nomad1
Copy link

Nomad1 commented Dec 8, 2020

@elfmz
Невидимые папки исправились с коммитом 075daea , спасибо.
Все еще смущает дата 01/01/80. При этом атрибуты (rwx) сохраняются верно.

@elfmz
Copy link
Owner

elfmz commented Dec 9, 2020

fixed вродь

@Nomad1
Copy link

Nomad1 commented Dec 9, 2020

@elfmz
Работает, спасибо!

@unxed
Copy link
Contributor Author

unxed commented Mar 12, 2021

@unxed
Copy link
Contributor Author

unxed commented Oct 8, 2021

I looked through all the issues for problems with all sorts of archives, found a bunch of fixed ones, closed or wrote a status request there.

And here are the ones that still remain:
#783
#718
#191
#702
#714

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants