Files
chromebrew/lib/deb_utils.rb
supechicken 80204ded10 lib/deb_utils.rb: Improve .deb unarchive algorithm (#6848)
* Fix `.deb` unarchive algorithm

* signal_desktop.rb: use source_url

* signal_desktop.rb: Remove alien dep

* Add color for error message

* Add color for error message
2022-03-11 09:12:05 -06:00

52 lines
2.2 KiB
Ruby

module DebUtils
def self.extract_deb(file, target)
# extract_deb: unarchive .deb files
# Usage: extract_deb(<file>, <target (optional)>)
# file: a .deb archive file
# target: (optional) a specified file to extract from archive, should be passed in regex or string
#
# Example:
# extract_deb('example.deb', 'test.txt') # extract `test.txt` from example.deb
# extract_deb('example.deb', /data\..*/) # extract files from example.deb with filenames matching the /data\..*/ regex
# extract_deb('example.deb', /*/) # extract all files from example.deb
#
file_found = false
src_fileIO = File.open(file, 'rb')
# get first line of the given file, should be a signature string (`!<arch>\n`) if it is a valid deb file
signature = src_fileIO.gets
abort 'Malformed archive :/'.lightred unless signature == "!<arch>\n"
# process each file in archive
while (line = src_fileIO.gets) do
# read file meta
name, modtime, uid, gid, mode, size, end_char = \
line.scan(/(.{16})(.{12})(.{6})(.{6})(.{8})(.{10})(.{1})/).flatten.map(&:strip)
# remove slash suffix from filename (if any)
# (a `.deb` ar archive does not support any directories, so we can confirm that all entries are normal files)
name.sub!(/\/$/, '')
# check ending byte
abort 'Malformed archive :/'.lightred unless end_char == '`'
# capture file in archive with given offset bytes (file size)
fileContent = src_fileIO.read(size.to_i)
# filter filename if a target file is specified
if target.is_a?(String) and name == target
# if target is passed as string, write matched file to filesyetem and exit function
# write to filesystem
return File.binwrite(name, fileContent, perm: mode.to_i(8))
elsif target.is_a?(Regexp) and name =~ target
# if target is passed as regex, write matched file to filesyetem and continue
# searching for another matched file until EOF
# write to filesystem
File.binwrite(name, fileContent, perm: mode.to_i(8))
file_found = true
end
end
abort "Target #{target.inspect} not found in archive. :/".lightred unless file_found
end
end