/usr/lib/ruby/vendor_ruby/mixlib/archive/tar.rb is in ruby-mixlib-archive 0.4.1-1.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 | require "rubygems/package"
require "zlib"
module Mixlib
class Archive
class Tar
TAR_LONGLINK = "././@LongLink"
attr_reader :options
attr_reader :archive
def initialize(archive, options = {})
@archive = archive
@options = options
end
# Extracts the archive to the given +destination+
#
# === Parameters
# perms<Boolean>:: should the extracter use permissions from the archive.
# ignore[Array]:: an array of matches of file paths to ignore
def extract(destination, perms: true, ignore: [])
# (http://stackoverflow.com/a/31310593/506908)
ignore_re = Regexp.union(ignore)
reader do |tar|
dest = nil
tar.each do |entry|
if entry.full_name == TAR_LONGLINK
dest = File.join(destination, entry.read.strip)
next
end
if entry.full_name =~ ignore_re
Mixlib::Archive::Log.warn "ignoring entry #{entry.full_name}"
next
end
dest ||= File.join(destination, entry.full_name)
parent = File.dirname(dest)
FileUtils.mkdir_p(parent)
if entry.directory? || (entry.header.typeflag == "" && entry.full_name.end_with?("/"))
File.delete(dest) if File.file?(dest)
if perms
FileUtils.mkdir_p(dest, mode: entry.header.mode, verbose: false)
else
FileUtils.mkdir_p(dest, verbose: false)
end
elsif entry.file? || (entry.header.typeflag == "" && !entry.full_name.end_with?("/"))
FileUtils.rm_rf(dest) if File.directory?(dest)
File.open(dest, "wb") do |f|
f.print(entry.read)
end
FileUtils.chmod(entry.header.mode, dest, verbose: false) if perms
elsif entry.header.typeflag == "2"
# handle symlink
File.symlink(entry.header.linkname, dest)
else
Mixlib::Archive::Log.warn "unknown tar entry: #{entry.full_name} type: #{entry.header.typeflag}"
end
dest = nil
end
end
end
# Creates an archive with the given set of +files+
#
# === Parameters
# gzip<Boolean>:: should the archive be gzipped?
def create(files, gzip: false)
tgt_dir = File.dirname(archive)
target = Tempfile.new(File.basename(archive), tgt_dir)
Gem::Package::TarWriter.new(target) do |tar|
files.each do |fn|
mode = File.stat(fn).mode
file = File.open(fn, "rb")
tar.add_file(fn, mode) do |io|
io.write(file)
end
file.close
end
end
target.close
if gzip
Zlib::GzipWriter.open(archive) do |gz|
gz.mtime = File.mtime(target.path)
gz.orig_name = File.basename(archive)
gz.write IO.binread(target.path)
end
else
FileUtils.mv(target.path, archive)
end
ensure
target.close unless target.closed?
end
private
def is_gzip_file?(path)
# You cannot write "\x1F\x8B" because the default encoding of
# ruby >= 1.9.3 is UTF-8 and 8B is an invalid in UTF-8.
IO.binread(path, 2) == [0x1F, 0x8B].pack("C*")
end
def reader(&block)
raw = File.open(archive, "rb")
file = if is_gzip_file?(archive)
Mixlib::Archive::Log.debug "gzip file detected"
Zlib::GzipReader.wrap(raw)
else
raw
end
Gem::Package::TarReader.new(file, &block)
ensure
if file
file.close unless file.closed?
file = nil
end
if raw
raw.close unless raw.closed?
raw = nil
end
end
end
end
end
|