I’ve seen a few examples of binaries concatenated with zip files (the three line single binary compiler free blog or https://code.rosaelefanten.org/zb/dir?ci=tip) and I was wondering if it can be done in Crystal too.
I expected it to just work, but seems it doesn’t.
$ echo foo >a.txt
$ echo bar >b.txt
$ zip archive.zip *.txt
adding: a.txt (stored 0%)
adding: b.txt (stored 0%)
$ cat >test.cr
require "compress/zip"
Compress::Zip::File.open("test") do |zip|
zip["b.txt"].open do |io|
p io.gets_to_end
end
end
$ cr build test.cr
Using compiled compiler at ~/repos/crystal/.build/crystal
$ cat archive.zip >>test
$ ./test
Unhandled exception: Expected end of central directory header signature, not 0xd5d00000 (Compress::Zip::Error)
from ~/repos/crystal/src/compress/zip/file.cr:121:7 in 'read_directory_end'
from ~/repos/crystal/src/compress/zip/file.cr:40:38 in 'initialize'
from ~/repos/crystal/src/compress/zip/file.cr:38:3 in 'new:sync_close'
from ~/repos/crystal/src/compress/zip/file.cr:48:5 in 'new'
from ~/repos/crystal/src/compress/zip/file.cr:61:5 in '__crystal_main'
from ~/repos/crystal/src/crystal/main.cr:115:5 in 'main_user_code'
from ~/repos/crystal/src/crystal/main.cr:101:7 in 'main'
from ~/repos/crystal/src/crystal/main.cr:127:3 in 'main'
from /usr/lib/libc.so.6 in '??'
from /usr/lib/libc.so.6 in '__libc_start_main'
from ./test in '_start'
from ???
Probably lines such as this one would need to somehow seek relative to the end of the IO, rather than the beginning of the IO.
1 Like
One approach:
require "datapack"
require "compress/zip"
Datapack.add "./foo.zip"
Compress::Zip::File.open(IO::Memory.new(Datapack::Data.find("foo.zip").data)) do |file|
file.entries.each do |entry|
p entry.filename
end
end
This uses this shard:
3 Likes