Vendor the external cookbooks

Knife-Zero doesn't include Berkshelf support, so vendoring everything in
the repo is convenient again
This commit is contained in:
Greg Karékinian
2019-10-13 18:32:56 +02:00
parent aa66743166
commit 049d5dd006
1245 changed files with 100630 additions and 0 deletions

View File

@@ -0,0 +1,43 @@
# Poise-Archive Changelog
## v1.5.0
* Support for 7-Zip unpacking archives on drives other than the system root.
* Chef 13 support.
## v1.4.0
* Added support for using 7-Zip on Windows.
* Fixed handling of `.tar.xz` archives on RHEL and CentOS.
## v1.3.0
* Add support for unpacking directly from a URL.
## v1.2.1
* [#1](https://github.com/poise/poise-archive/issues/1) Restore file permissions
for ZIP files.
## v1.2.0
* Add back a tar-binary provider called `GnuTar`, used by default on Linux.
* Support for ZIP files via RubyZip.
* Full Windows support, including with the `user` and `group` properties.
## v1.1.2
* Fix compat with older Ruby that doesn't include `Entry#symlink?`.
## v1.1.1
* Fix GNU tar longlink extension.
## v1.1.0
* Scrap the original tar implementation in favor of a 100% pure-Ruby solution.
This should work on all platforms exactly the same. Hopefully.
## v1.0.0
* Initial release!

View File

@@ -0,0 +1,103 @@
# Poise-Archive Cookbook
[![Build Status](https://img.shields.io/travis/poise/poise-archive.svg)](https://travis-ci.org/poise/poise-archive)
[![Gem Version](https://img.shields.io/gem/v/poise-archive.svg)](https://rubygems.org/gems/poise-archive)
[![Cookbook Version](https://img.shields.io/cookbook/v/poise-archive.svg)](https://supermarket.chef.io/cookbooks/poise-archive)
[![Coverage](https://img.shields.io/codecov/c/github/poise/poise-archive.svg)](https://codecov.io/github/poise/poise-archive)
[![Gemnasium](https://img.shields.io/gemnasium/poise/poise-archive.svg)](https://gemnasium.com/poise/poise-archive)
[![License](https://img.shields.io/badge/license-Apache_2-blue.svg)](https://www.apache.org/licenses/LICENSE-2.0)
A [Chef](https://www.chef.io/) cookbook to unpack file archives.
It supports `.tar`, `.tar.gz`, `.tar.bz2`, and `.zip` archive files.
## Quick Start
To download an unpack and archive:
```ruby
poise_archive 'https://example.com/myapp.tgz' do
destination '/opt/myapp'
end
```
## Requirements
Chef 12.1 or newer is required.
## Platforms
This cookbook supports all platforms (including Windows) but some Unix platforms
(Solaris, AIX) may see very slow tar file unpacking when using the pure-Ruby fallback
implementation.
## Resources
### `poise_archive`
The `poise_archive` resource unpacks file archives.
```ruby
poise_archive '/tmp/myapp-1.2.0.tar' do
destination '/srv/myapp-1.2.0'
end
```
A URL can also be passed as the source path, optionally with extra properties to
be merged with `source_properties`.
```ruby
poise_archive 'http://example.com/myapp-1.2.0.zip' do
destination '/srv/myapp-1.2.0'
end
poise_archive ['http://example.com/myapp-1.2.0.zip', {headers: {'Authentication' => '...'}}] do
destination '/srv/myapp-1.2.0'
end
```
#### Actions
* `:unpack` Unpack the archive. *(default)*
#### Properties
* `path` Path to the archive. If relative, it is taken as a file inside
`Chef::Config[:file_cache_path]`. If a URL, it is downloaded to a cache file
first. *(name attribute)*
* `destination` Path to unpack the archive to. If not specified, the path of
the archive without the file extension is used. Required when unpacking from
a URL. *(default: auto)*
* `group` Group to run the unpack as.
* `keep_existing` Keep existing files in the destination directory when
unpacking. *(default: false)*
* `source_properties` Property key/value pairs to be applied to the
`remote_file` file resource when downloading a URL. *(default: {retries: 5})*
* `strip_components` Number of intermediary directories to skip when
unpacking. Works like GNU tar's `--strip-components`. *(default: 1)*
* `user` User to run the unpack as.
## Sponsors
Development sponsored by [Bloomberg](http://www.bloomberg.com/company/technology/).
The Poise test server infrastructure is sponsored by [Rackspace](https://rackspace.com/).
## License
Copyright 2016-2017, Noah Kantrowitz
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
BZip2 implementation is based on RBzip2. Copyright Sebastian Staudt, Brian Lopez.
RBzip2 code used under the terms of the new BSD license.

View File

@@ -0,0 +1,18 @@
#
# Copyright 2017, Noah Kantrowitz
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
default['poise-archive']['seven_zip']['version'] = '16.04'
default['poise-archive']['seven_zip']['url'] = 'http://www.7-zip.org/a/7z%{version_tag}%{arch_tag}.exe'

View File

@@ -0,0 +1,21 @@
#
# Copyright 2016-2017, Noah Kantrowitz
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
module PoiseArchive
autoload :Resources, 'poise_archive/resources'
autoload :VERSION, 'poise_archive/version'
end

View File

@@ -0,0 +1,38 @@
#
# Copyright 2016-2017, Noah Kantrowitz
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
require 'chef/platform/provider_priority_map'
require 'poise_archive/archive_providers/gnu_tar'
require 'poise_archive/archive_providers/seven_zip'
require 'poise_archive/archive_providers/tar'
require 'poise_archive/archive_providers/zip'
module PoiseArchive
# Providers for the poise_archive resource.
#
# @since 1.0.0
module ArchiveProviders
# Set up priority maps
Chef::Platform::ProviderPriorityMap.instance.priority(:poise_archive, [
PoiseArchive::ArchiveProviders::Zip,
PoiseArchive::ArchiveProviders::GnuTar,
PoiseArchive::ArchiveProviders::SevenZip,
PoiseArchive::ArchiveProviders::Tar,
])
end
end

View File

@@ -0,0 +1,132 @@
#
# Copyright 2016-2017, Noah Kantrowitz
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
require 'fileutils'
require 'chef/provider'
require 'poise'
module PoiseArchive
module ArchiveProviders
# The provider base class for `poise_archive`.
#
# @see PoiseArchive::Resources::PoiseArchive::Resource
# @provides poise_archive
class Base < Chef::Provider
include Poise
# Set the file extension this provider will handle.
#
# @param match [RegExp] Regular expression to match against the archive
# file name.
# @return [void]
# @example
# class MyProvider < Base
# provides_extension(/\.hqx$/)
# end
def self.provides_extension(match)
provides(:poise_archive)
@provides_extension = match
end
# Override normal provider resolution to also check file extension if one
# was specified in the provider.
#
# @api private
def self.provides?(node, resource)
super && (!@provides_extension || @provides_extension.match(resource.path))
end
# `unpack` action for `poise_archive`.
#
# @return [void]
def action_unpack
if new_resource.is_url?
download_resource = download_file
# Check if the download resource updated, if not don't run the rest
# of the unpack for idempotence. I could also check
# new_resource.updated? but this seems more future proof.
return if !download_resource.updated_by_last_action?
end
converge_by("unpack archive #{new_resource.path} to #{new_resource.destination}") do
notifying_block do
create_directory
end
empty_directory
unpack_archive
end
end
private
# Download the source file to a cache path.
#
# @return [Chef::Resource]
def download_file
# resource_state used for closure breaking on the notifying block.
resource_state = []
notifying_block do
# TODO handle cookbook:// for cookbook_file "downloads".
resource_state << remote_file(new_resource.absolute_path) do
source new_resource.path
retries 5 # As a default, could be overridden by source_properties.
new_resource.merged_source_properties.each do |key, value|
send(key, value)
end
end
end
# Return the download resource for state tracking.
resource_state.first
end
# Make sure the destination directory exists.
#
# @return [void]
def create_directory
directory new_resource.destination do
group new_resource.group if new_resource.group
owner new_resource.user if new_resource.user
# There is explicitly no mode being set here. If a non-default mode
# is needed, you should manage that outside of poise_archive.
end
end
# Remove all existing content from the destination so we can unpack the
# new content.
#
# @return [void]
def empty_directory
# If you want to keep it, not my problem.
return if new_resource.keep_existing
dest = new_resource.destination
Dir.entries(dest).each do |entry|
next if entry == '.' || entry == '..'
FileUtils.remove_entry_secure(::File.join(dest, entry))
end
end
# Run the provider-specific unpack behavior.
#
# @abstract
# @return [void]
def unpack_archive
raise NotImplementedError
end
end
end
end

View File

@@ -0,0 +1,88 @@
#
# Copyright 2016-2017, Noah Kantrowitz
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
require 'fileutils'
require 'tmpdir'
require 'poise_archive/archive_providers/base'
module PoiseArchive
module ArchiveProviders
# The `gnu_tar` provider class for `poise_archive` to install from TAR
# archives using GNU's tar executable.
#
# @see PoiseArchive::Resources::PoiseArchive::Resource
# @provides poise_archive
class GnuTar < Base
provides_extension(/\.t(ar|gz|bz|xz)/)
# Only use this if we are on Linux. Everyone else gets the slow Ruby code.
#
# @api private
def self.provides?(node, _resource)
super && node['os'] == 'linux'
end
private
def unpack_archive
notifying_block do
install_prereqs
end
unpack_tar
end
# Install any needed prereqs.
#
# @return [void]
def install_prereqs
utils = ['tar']
utils << 'bzip2' if new_resource.absolute_path =~ /\.t?bz/
if new_resource.absolute_path =~ /\.t?xz/
xz_package = node.value_for_platform_family(
debian: 'xz-utils',
rhel: 'xz',
)
utils << xz_package if xz_package
end
# This is a resource.
package utils
end
# Unpack the archive and process `strip_components`.
#
# @return [void]
def unpack_tar
# Build the tar command.
cmd = %w{tar}
cmd << "--strip-components=#{new_resource.strip_components}" if new_resource.strip_components && new_resource.strip_components > 0
cmd << if new_resource.absolute_path =~ /\.t?gz/
'-xzvf'
elsif new_resource.absolute_path =~ /\.t?bz/
'-xjvf'
elsif new_resource.absolute_path =~ /\.t?xz/
'-xJvf'
else
'-xvf'
end
cmd << new_resource.absolute_path
poise_shell_out!(cmd, cwd: new_resource.destination, group: new_resource.group, user: new_resource.user)
end
end
end
end

View File

@@ -0,0 +1,183 @@
#
# Copyright 2017, Noah Kantrowitz
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
require 'fileutils'
require 'tmpdir'
require 'poise_archive/archive_providers/base'
module PoiseArchive
module ArchiveProviders
# The `seven_zip` provider class for `poise_archive` to upack archives
# using 7-Zip.
#
# @since 1.4.0
# @see PoiseArchive::Resources::PoiseArchive::Resource
# @provides poise_archive
class SevenZip < Base
provides_extension(/\.(t(ar|gz|bz|xz)|zip|7z)/)
# Only works on Windows, because use less silly things elsewhere.
#
# @api private
def self.provides?(node, _resource)
super && node['platform_family'] == 'windows'
end
private
def unpack_archive
notifying_block do
install_seven_zip
end
# Create a temp directory to unpack in to. Do I want to try and force
# this to be on the same filesystem as the target?
self.class.mktmpdir do |tmpdir|
unpack_using_seven_zip(tmpdir)
chown_files(tmpdir) if new_resource.user || new_resource.group
move_files(tmpdir)
end
end
# Install 7-Zip to a cache folder.
#
# @api private
# @return [void]
def install_seven_zip
url = seven_zip_url
path = "#{Chef::Config[:file_cache_path]}/#{url.split(/\//).last}"
install = execute "#{windows_path(path)} /S /D=#{seven_zip_home}" do
action :nothing
end
remote_file path do
source url
notifies :run, install, :immediately
end
end
# Unpack the whole archive to a temp directory.
#
# @api private
# @param tmpdir [String] Temp directory to unpack to.
# @return [void]
def unpack_using_seven_zip(tmpdir)
if new_resource.absolute_path =~ /\.t(ar\.)?(gz|bz(2)?|xz)$/
# 7-Zip doesn't know to unpack both levels of the archive on its own
# so we need to handle this more explicitly.
shell_out!("#{seven_zip_home}\\7z.exe x -so \"#{windows_path(new_resource.absolute_path)}\" | #{seven_zip_home}\\7z.exe x -si -ttar -o\"#{windows_path(tmpdir)}\"")
else
shell_out!("#{seven_zip_home}\\7z.exe x -o\"#{windows_path(tmpdir)}\" \"#{windows_path(new_resource.absolute_path)}\"")
end
end
# Fix file ownership if requested.
#
# @api private
# @param tmpdir [String] Temp directory to change ownership in.
# @return [void]
def chown_files(tmpdir)
notifying_block do
Dir["#{tmpdir}/**/*"].each do |path|
declare_resource(::File.directory?(path) ? :directory : :file, path) do
owner new_resource.user if new_resource.user
group new_resource.group if new_resource.group
end
end
end
end
# Manual implementation of --strip-components since 7-Zip doesn't support
# it internally.
#
# @api private
# @param tmpdir [String] Temp directory to move from.
# @return [void]
def move_files(tmpdir)
entries_at_depth(tmpdir, new_resource.strip_components).each do |source|
target = ::File.join(new_resource.destination, ::File.basename(source))
FileUtils.mv(source, target, secure: true)
end
end
# Compute the URL to download the 7-Zip installer from.
#
# @api private
# @return [String]
def seven_zip_url
node['poise-archive']['seven_zip']['url'] % {
version: node['poise-archive']['seven_zip']['version'],
version_tag: node['poise-archive']['seven_zip']['version'].gsub(/\./, ''),
arch: node['kernel']['machine'],
arch_tag: node['kernel']['machine'] == 'x86_64' ? '-x64' : '',
}
end
# Path to install 7-Zip in to.
#
# @api private
# @return [String]
def seven_zip_home
"#{windows_path(Chef::Config[:file_cache_path])}\\seven_zip_#{node['poise-archive']['seven_zip']['version']}"
end
# Flip the slashes in a path because 7z wants "normal" paths.
#
# @api private
# @param path [String] Path to convert.
# @return [String]
def windows_path(path)
path.gsub(/\//, '\\')
end
# Find the absolute paths for entries under a path at a depth.
#
# @api private
# @param path [String] Base path to search under.
# @param depth [Integer] Number of intermediary directories to skip.
# @return [Array<String>]
def entries_at_depth(path, depth)
entries = [path]
current_depth = 0
while current_depth <= depth
entries.map! do |ent|
if ::File.directory?(ent)
Dir.entries(ent).select {|e| e != '.' && e != '..' }.map {|e| ::File.join(ent, e) }
else
[]
end
end
entries.flatten!
current_depth += 1
end
entries
end
# Indirection so I can stub this for testing without breaking RSpec.
#
# @api private
def self.mktmpdir(*args, &block)
# :nocov:
Dir.mktmpdir(*args, &block)
# :nocov:
end
end
end
end

View File

@@ -0,0 +1,158 @@
#
# Copyright 2016-2017, Noah Kantrowitz
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
require 'rubygems/package'
require 'zlib'
require 'poise_archive/archive_providers/base'
require 'poise_archive/bzip2'
module PoiseArchive
module ArchiveProviders
# The `tar` provider class for `poise_archive` to install from tar archives.
#
# @see PoiseArchive::Resources::PoiseArchive::Resource
# @provides poise_archive
class Tar < Base
provides_extension(/\.t(ar|gz|bz)/)
# Hack that GNU tar uses for paths over 100 bytes.
#
# @api private
# @see #unpack_tar
TAR_LONGLINK = '././@LongLink'
private
def unpack_archive
unpack_tar
chown_entries if new_resource.user || new_resource.group
end
# Unpack the archive.
#
# @return [void]
def unpack_tar
@tar_entry_paths = []
tar_each_with_longlink do |entry|
entry_name = entry.full_name.split(/\//).drop(new_resource.strip_components).join('/')
# If strip_components wiped out the name, don't process this entry.
next if entry_name.empty?
dest = ::File.join(new_resource.destination, entry_name)
if entry.directory?
Dir.mkdir(dest, entry.header.mode)
@tar_entry_paths << [:directory, dest]
elsif entry.file?
::File.open(dest, 'wb', entry.header.mode) do |dest_f|
while buf = entry.read(4096)
dest_f.write(buf)
end
end
@tar_entry_paths << [:file, dest]
elsif entry.header.typeflag == '2' # symlink? is new in Ruby 2.0, apparently.
::File.symlink(entry.header.linkname, dest)
@tar_entry_paths << [:link, dest]
else
raise RuntimeError.new("Unknown tar entry type #{entry.header.typeflag.inspect} in #{new_resource.path}")
end
end
end
def tar_each_with_longlink(&block)
entry_name = nil
tar_each do |entry|
if entry.full_name == TAR_LONGLINK
# Stash the longlink name so it will be used for the next entry.
entry_name = entry.read.strip
# And then skip forward because this isn't a real block.
next
end
# For entries not preceded by a longlink block, use the normal name.
entry_name ||= entry.full_name
# Make the entry return the correct name.
entry.define_singleton_method(:full_name) { entry_name }
block.call(entry)
# Reset entry_name for the next entry.
entry_name = nil
end
end
# Sequence the opening, iteration, and closing.
#
# @param block [Proc] Block to process each tar entry.
# @return [void]
def tar_each(&block)
# In case of extreme weirdness where this happens twice.
close_file!
open_file!
@tar_reader.each(&block)
ensure
close_file!
end
# Open a file handle of the correct flavor.
#
# @return [void]
def open_file!
@raw_file = ::File.open(new_resource.absolute_path, 'rb')
@file = case new_resource.absolute_path
when /\.tar$/
nil # So it uses @raw_file instead.
when /\.t?gz/
Zlib::GzipReader.wrap(@raw_file)
when /\.t?bz/
# This can't take a block, hence the gross non-block forms for everything.
PoiseArchive::Bzip2::Decompressor.new(@raw_file)
else
raise RuntimeError.new("Unknown or unsupported file extension for #{new_resource.path}")
end
@tar_reader = Gem::Package::TarReader.new(@file || @raw_file)
end
# Close all the various file handles.
#
# @return [void]
def close_file!
if @tar_reader
@tar_reader.close
@tar_reader = nil
end
if @file
@file.close
@file = nil
end
if @raw_file
@raw_file.close unless @raw_file.closed?
@raw_file = nil
end
end
def chown_entries
paths = @tar_entry_paths
notifying_block do
paths.each do |type, path|
send(type, path) do
group new_resource.group
owner new_resource.user
end
end
end
end
end
end
end

View File

@@ -0,0 +1,97 @@
#
# Copyright 2016-2017, Noah Kantrowitz
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
require 'poise_archive/archive_providers/base'
module PoiseArchive
module ArchiveProviders
# The `zip` provider class for `poise_archive` to install from ZIP archives.
#
# @see PoiseArchive::Resources::PoiseArchive::Resource
# @provides poise_archive
class Zip < Base
provides_extension(/\.zip$/)
private
def unpack_archive
check_rubyzip
unpack_zip
chown_entries if new_resource.user || new_resource.group
end
def check_rubyzip
require 'zip'
rescue LoadError
notifying_block do
install_rubyzip
end
require 'zip'
end
def install_rubyzip
chef_gem 'rubyzip'
end
def unpack_zip
@zip_entry_paths = []
::Zip::File.open(new_resource.absolute_path) do |zip_file|
zip_file.each do |entry|
entry_name = entry.name.split(/\//).drop(new_resource.strip_components).join('/')
# If strip_components wiped out the name, don't process this entry.
next if entry_name.empty?
entry_path = ::File.join(new_resource.destination, entry_name)
# Ensure parent directories exist because some ZIP files don't
# include those for some reason.
ensure_directory(entry_path)
entry.extract(entry_path)
# Make sure we restore file permissions. RubyZip won't do this
# unless we also turn on UID/GID restoration, which we don't want.
# Mask filters out setuid and setgid bits because no.
::File.chmod(entry.unix_perms & 01777, entry_path) if !node.platform_family?('windows') && entry.unix_perms
@zip_entry_paths << [entry.directory? ? :directory : entry.file? ? :file : :link, entry_path]
end
end
end
# Make sure all enclosing directories exist before writing a path.
#
# @param oath [String] Path to check.
def ensure_directory(path)
base = ::File.dirname(path)
unless ::File.exist?(base)
ensure_directory(base)
Dir.mkdir(base)
@zip_entry_paths << [:directory, base]
end
end
def chown_entries
paths = @zip_entry_paths
notifying_block do
paths.each do |type, path|
send(type, path) do
group new_resource.group
owner new_resource.user
end
end
end
end
end
end
end

View File

@@ -0,0 +1,16 @@
# This code is free software; you can redistribute it and/or modify it under
# the terms of the new BSD License.
#
# Copyright (c) 2013, Sebastian Staudt
module PoiseArchive::Bzip2
autoload :CRC, 'poise_archive/bzip2/crc'
autoload :Constants, 'poise_archive/bzip2/constants'
autoload :Decompressor, 'poise_archive/bzip2/decompressor'
autoload :IO, 'poise_archive/bzip2/io'
autoload :InputData, 'poise_archive/bzip2/input_data'
autoload :OutputData, 'poise_archive/bzip2/output_data'
end

View File

@@ -0,0 +1,25 @@
Copyright (c) 2011, Sebastian Staudt
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
* Neither the name of the author nor the names of its contributors
may be used to endorse or promote products derived from this software
without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

View File

@@ -0,0 +1,83 @@
# This code is free software; you can redistribute it and/or modify it under
# the terms of the new BSD License.
#
# Copyright (c) 2011-2013, Sebastian Staudt
module PoiseArchive::Bzip2::Constants
BASEBLOCKSIZE = 100000
MAX_ALPHA_SIZE = 258
MAX_CODE_LEN = 23
RUNA = 0
RUNB = 1
N_GROUPS = 6
G_SIZE = 50
N_ITERS = 4
MAX_SELECTORS = (2 + (900000 / G_SIZE))
NUM_OVERSHOOT_BYTES = 20
EOF = 0
START_BLOCK_STATE = 1
RAND_PART_A_STATE = 2
RAND_PART_B_STATE = 3
RAND_PART_C_STATE = 4
NO_RAND_PART_A_STATE = 5
NO_RAND_PART_B_STATE = 6
NO_RAND_PART_C_STATE = 7
RNUMS = [
619, 720, 127, 481, 931, 816, 813, 233, 566, 247, 985, 724, 205, 454, 863,
491, 741, 242, 949, 214, 733, 859, 335, 708, 621, 574, 73, 654, 730, 472,
419, 436, 278, 496, 867, 210, 399, 680, 480, 51, 878, 465, 811, 169, 869,
675, 611, 697, 867, 561, 862, 687, 507, 283, 482, 129, 807, 591, 733, 623,
150, 238, 59, 379, 684, 877, 625, 169, 643, 105, 170, 607, 520, 932, 727,
476, 693, 425, 174, 647, 73, 122, 335, 530, 442, 853, 695, 249, 445, 515,
909, 545, 703, 919, 874, 474, 882, 500, 594, 612, 641, 801, 220, 162, 819,
984, 589, 513, 495, 799, 161, 604, 958, 533, 221, 400, 386, 867, 600, 782,
382, 596, 414, 171, 516, 375, 682, 485, 911, 276, 98, 553, 163, 354, 666,
933, 424, 341, 533, 870, 227, 730, 475, 186, 263, 647, 537, 686, 600, 224,
469, 68, 770, 919, 190, 373, 294, 822, 808, 206, 184, 943, 795, 384, 383,
461, 404, 758, 839, 887, 715, 67, 618, 276, 204, 918, 873, 777, 604, 560,
951, 160, 578, 722, 79, 804, 96, 409, 713, 940, 652, 934, 970, 447, 318,
353, 859, 672, 112, 785, 645, 863, 803, 350, 139, 93, 354, 99, 820, 908,
609, 772, 154, 274, 580, 184, 79, 626, 630, 742, 653, 282, 762, 623, 680,
81, 927, 626, 789, 125, 411, 521, 938, 300, 821, 78, 343, 175, 128, 250,
170, 774, 972, 275, 999, 639, 495, 78, 352, 126, 857, 956, 358, 619, 580,
124, 737, 594, 701, 612, 669, 112, 134, 694, 363, 992, 809, 743, 168, 974,
944, 375, 748, 52, 600, 747, 642, 182, 862, 81, 344, 805, 988, 739, 511,
655, 814, 334, 249, 515, 897, 955, 664, 981, 649, 113, 974, 459, 893, 228,
433, 837, 553, 268, 926, 240, 102, 654, 459, 51, 686, 754, 806, 760, 493,
403, 415, 394, 687, 700, 946, 670, 656, 610, 738, 392, 760, 799, 887, 653,
978, 321, 576, 617, 626, 502, 894, 679, 243, 440, 680, 879, 194, 572, 640,
724, 926, 56, 204, 700, 707, 151, 457, 449, 797, 195, 791, 558, 945, 679,
297, 59, 87, 824, 713, 663, 412, 693, 342, 606, 134, 108, 571, 364, 631,
212, 174, 643, 304, 329, 343, 97, 430, 751, 497, 314, 983, 374, 822, 928,
140, 206, 73, 263, 980, 736, 876, 478, 430, 305, 170, 514, 364, 692, 829,
82, 855, 953, 676, 246, 369, 970, 294, 750, 807, 827, 150, 790, 288, 923,
804, 378, 215, 828, 592, 281, 565, 555, 710, 82, 896, 831, 547, 261, 524,
462, 293, 465, 502, 56, 661, 821, 976, 991, 658, 869, 905, 758, 745, 193,
768, 550, 608, 933, 378, 286, 215, 979, 792, 961, 61, 688, 793, 644, 986,
403, 106, 366, 905, 644, 372, 567, 466, 434, 645, 210, 389, 550, 919, 135,
780, 773, 635, 389, 707, 100, 626, 958, 165, 504, 920, 176, 193, 713, 857,
265, 203, 50, 668, 108, 645, 990, 626, 197, 510, 357, 358, 850, 858, 364,
936, 638
]
MIN_BLOCK_SIZE = 1
MAX_BLOCK_SIZE = 9
SETMASK = (1 << 21)
CLEARMASK = (~SETMASK)
GREATER_ICOST = 15
LESSER_ICOST = 0
SMALL_THRESH = 20
DEPTH_THRESH = 10
WORK_FACTOR = 30
QSORT_STACK_SIZE = 1000
INCS = [
1, 4, 13, 40, 121, 364, 1093, 3280, 9841, 29524, 88573, 265720, 797161,
2391484
]
end

View File

@@ -0,0 +1,73 @@
# This code is free software; you can redistribute it and/or modify it under
# the terms of the new BSD License.
#
# Copyright (c) 2011-2013, Sebastian Staudt
class PoiseArchive::Bzip2::CRC
CRC32_TABLE = [
0x00000000, 0x04c11db7, 0x09823b6e, 0x0d4326d9, 0x130476dc, 0x17c56b6b,
0x1a864db2, 0x1e475005, 0x2608edb8, 0x22c9f00f, 0x2f8ad6d6, 0x2b4bcb61,
0x350c9b64, 0x31cd86d3, 0x3c8ea00a, 0x384fbdbd, 0x4c11db70, 0x48d0c6c7,
0x4593e01e, 0x4152fda9, 0x5f15adac, 0x5bd4b01b, 0x569796c2, 0x52568b75,
0x6a1936c8, 0x6ed82b7f, 0x639b0da6, 0x675a1011, 0x791d4014, 0x7ddc5da3,
0x709f7b7a, 0x745e66cd, 0x9823b6e0, 0x9ce2ab57, 0x91a18d8e, 0x95609039,
0x8b27c03c, 0x8fe6dd8b, 0x82a5fb52, 0x8664e6e5, 0xbe2b5b58, 0xbaea46ef,
0xb7a96036, 0xb3687d81, 0xad2f2d84, 0xa9ee3033, 0xa4ad16ea, 0xa06c0b5d,
0xd4326d90, 0xd0f37027, 0xddb056fe, 0xd9714b49, 0xc7361b4c, 0xc3f706fb,
0xceb42022, 0xca753d95, 0xf23a8028, 0xf6fb9d9f, 0xfbb8bb46, 0xff79a6f1,
0xe13ef6f4, 0xe5ffeb43, 0xe8bccd9a, 0xec7dd02d, 0x34867077, 0x30476dc0,
0x3d044b19, 0x39c556ae, 0x278206ab, 0x23431b1c, 0x2e003dc5, 0x2ac12072,
0x128e9dcf, 0x164f8078, 0x1b0ca6a1, 0x1fcdbb16, 0x018aeb13, 0x054bf6a4,
0x0808d07d, 0x0cc9cdca, 0x7897ab07, 0x7c56b6b0, 0x71159069, 0x75d48dde,
0x6b93dddb, 0x6f52c06c, 0x6211e6b5, 0x66d0fb02, 0x5e9f46bf, 0x5a5e5b08,
0x571d7dd1, 0x53dc6066, 0x4d9b3063, 0x495a2dd4, 0x44190b0d, 0x40d816ba,
0xaca5c697, 0xa864db20, 0xa527fdf9, 0xa1e6e04e, 0xbfa1b04b, 0xbb60adfc,
0xb6238b25, 0xb2e29692, 0x8aad2b2f, 0x8e6c3698, 0x832f1041, 0x87ee0df6,
0x99a95df3, 0x9d684044, 0x902b669d, 0x94ea7b2a, 0xe0b41de7, 0xe4750050,
0xe9362689, 0xedf73b3e, 0xf3b06b3b, 0xf771768c, 0xfa325055, 0xfef34de2,
0xc6bcf05f, 0xc27dede8, 0xcf3ecb31, 0xcbffd686, 0xd5b88683, 0xd1799b34,
0xdc3abded, 0xd8fba05a, 0x690ce0ee, 0x6dcdfd59, 0x608edb80, 0x644fc637,
0x7a089632, 0x7ec98b85, 0x738aad5c, 0x774bb0eb, 0x4f040d56, 0x4bc510e1,
0x46863638, 0x42472b8f, 0x5c007b8a, 0x58c1663d, 0x558240e4, 0x51435d53,
0x251d3b9e, 0x21dc2629, 0x2c9f00f0, 0x285e1d47, 0x36194d42, 0x32d850f5,
0x3f9b762c, 0x3b5a6b9b, 0x0315d626, 0x07d4cb91, 0x0a97ed48, 0x0e56f0ff,
0x1011a0fa, 0x14d0bd4d, 0x19939b94, 0x1d528623, 0xf12f560e, 0xf5ee4bb9,
0xf8ad6d60, 0xfc6c70d7, 0xe22b20d2, 0xe6ea3d65, 0xeba91bbc, 0xef68060b,
0xd727bbb6, 0xd3e6a601, 0xdea580d8, 0xda649d6f, 0xc423cd6a, 0xc0e2d0dd,
0xcda1f604, 0xc960ebb3, 0xbd3e8d7e, 0xb9ff90c9, 0xb4bcb610, 0xb07daba7,
0xae3afba2, 0xaafbe615, 0xa7b8c0cc, 0xa379dd7b, 0x9b3660c6, 0x9ff77d71,
0x92b45ba8, 0x9675461f, 0x8832161a, 0x8cf30bad, 0x81b02d74, 0x857130c3,
0x5d8a9099, 0x594b8d2e, 0x5408abf7, 0x50c9b640, 0x4e8ee645, 0x4a4ffbf2,
0x470cdd2b, 0x43cdc09c, 0x7b827d21, 0x7f436096, 0x7200464f, 0x76c15bf8,
0x68860bfd, 0x6c47164a, 0x61043093, 0x65c52d24, 0x119b4be9, 0x155a565e,
0x18197087, 0x1cd86d30, 0x029f3d35, 0x065e2082, 0x0b1d065b, 0x0fdc1bec,
0x3793a651, 0x3352bbe6, 0x3e119d3f, 0x3ad08088, 0x2497d08d, 0x2056cd3a,
0x2d15ebe3, 0x29d4f654, 0xc5a92679, 0xc1683bce, 0xcc2b1d17, 0xc8ea00a0,
0xd6ad50a5, 0xd26c4d12, 0xdf2f6bcb, 0xdbee767c, 0xe3a1cbc1, 0xe760d676,
0xea23f0af, 0xeee2ed18, 0xf0a5bd1d, 0xf464a0aa, 0xf9278673, 0xfde69bc4,
0x89b8fd09, 0x8d79e0be, 0x803ac667, 0x84fbdbd0, 0x9abc8bd5, 0x9e7d9662,
0x933eb0bb, 0x97ffad0c, 0xafb010b1, 0xab710d06, 0xa6322bdf, 0xa2f33668,
0xbcb4666d, 0xb8757bda, 0xb5365d03, 0xb1f740b4
]
attr_accessor :global_crc
def initialize
initialize_crc
end
def initialize_crc
@global_crc = 0xffffffff
end
def final_crc
@global_crc ^ 0xffffffff
end
def update_crc(in_ch)
@global_crc = ((@global_crc << 8) & 0xffffffff) ^ CRC32_TABLE[(@global_crc >> 24) ^ in_ch]
end
end

View File

@@ -0,0 +1,704 @@
# This code is free software; you can redistribute it and/or modify it under
# the terms of the new BSD License.
#
# Copyright (c) 2011-2013, Sebastian Staudt
class PoiseArchive::Bzip2::Decompressor
include PoiseArchive::Bzip2::Constants
def initialize(io)
@buff = 0
@bytes_read = 0
@computed_combined_crc = 0
@crc = PoiseArchive::Bzip2::CRC.new
@current_char = -1
@io = io
@live = 0
@stored_combined_crc = 0
@su_t_pos = 0
init
end
def count(read)
@bytes_read += read if read != -1
end
# ADDED METHODS
def pos
@bytes_read
end
def eof?
@current_state == EOF
end
# /ADDED METHODS
def read(length = nil)
raise 'stream closed' if @io.nil?
if length == 1
r = read0
count (r < 0 ? -1 : 1)
r
else
r = ''
if length == nil
while true do
b = read0
break if b < 0
r << b.chr
end
count r.size # ADDED LINE
elsif length > 0
length.times do
b = read0
break if b < 0
r << b.chr
end
count r.size
end
r
end
end
def read0
ret_char = @current_char
if @current_state == RAND_PART_B_STATE
setup_rand_part_b
elsif @current_state == NO_RAND_PART_B_STATE
setup_no_rand_part_b
elsif @current_state == RAND_PART_C_STATE
setup_rand_part_c
elsif @current_state == NO_RAND_PART_C_STATE
setup_no_rand_part_c
elsif @current_state == EOF
return -1
else
raise 'illegal state'
end
ret_char
end
def make_maps
in_use = @data.in_use
seq_to_unseq = @data.seq_to_unseq
n_in_use_shadow = 0
256.times do |i|
if in_use[i]
seq_to_unseq[n_in_use_shadow] = i
n_in_use_shadow += 1
end
end
@n_in_use = n_in_use_shadow
end
def init
check_magic
block_size = @io.read(1).to_i
raise 'Illegal block size.' if block_size < 1 || block_size > 9
@block_size = block_size
init_block
setup_block
end
def check_magic
raise 'Magic number does not match "BZh".' unless @io.read(3) == 'BZh'
end
def init_block
magic = [ubyte, ubyte, ubyte, ubyte, ubyte, ubyte]
if magic == [0x17, 0x72, 0x45, 0x38, 0x50, 0x90]
complete
elsif magic != [0x31, 0x41, 0x59, 0x26, 0x53, 0x59]
@current_state = EOF
raise 'Bad block header.'
else
@stored_block_crc = int
@block_randomised = bit
@data = PoiseArchive::Bzip2::InputData.new @block_size if @data.nil?
get_and_move_to_front_decode
@crc.initialize_crc
@current_state = START_BLOCK_STATE
end
end
def end_block
@computed_block_crc = @crc.final_crc
if @stored_block_crc != @computed_block_crc
@computed_combined_crc = (@stored_combined_crc << 1) | (@stored_combined_crc >> 31)
@computed_combined_crc ^= @stored_block_crc
raise 'BZip2 CRC error'
end
@computed_combined_crc = (@computed_combined_crc << 1) | (@computed_combined_crc >> 31)
@computed_combined_crc ^= @computed_block_crc
end
def complete
@stored_combined_crc = int
@current_state = EOF
@data = nil
raise 'BZip2 CRC error' if @stored_combined_crc != @computed_combined_crc
end
def close
if @io != $stdin
@io = nil
@data = nil
end
end
def r(n)
live_shadow = @live
buff_shadow = @buff
if live_shadow < n
begin
thech = @io.readbyte
raise 'unexpected end of stream' if thech < 0
buff_shadow = (buff_shadow << 8) | thech
live_shadow += 8
end while live_shadow < n
@buff = buff_shadow
end
@live = live_shadow - n
(buff_shadow >> (live_shadow - n)) & ((1 << n) - 1)
end
def bit
r(1) != 0
end
def ubyte
r 8
end
def int
(((((r(8) << 8) | r(8)) << 8) | r(8)) << 8) | r(8)
end
def create_decode_tables(limit, base, perm, length, min_len, max_len, alpha_size)
pp = 0
(min_len..max_len).each do |i|
alpha_size.times do |j|
if length[j] == i
perm[pp] = j
pp += 1
end
end
end
MAX_CODE_LEN.downto 1 do |i|
base[i] = 0
limit[i] = 0
end
alpha_size.times do |i|
base[length[i] + 1] += 1
end
b = 0
1.upto(MAX_CODE_LEN - 1) do |i|
b += base[i]
base[i] = b
end
vec = 0
min_len.upto(max_len) do |i|
b = base[i]
nb = base[i + 1]
vec += nb - b
b = nb
limit[i] = vec - 1
vec = vec << 1
end
(min_len + 1).upto(max_len) do |i|
base[i] = ((limit[i - 1] + 1) << 1) - base[i]
end
end
def receive_decoding_tables
in_use = @data.in_use
pos = @data.receive_decoding_tables_pos
selector = @data.selector
selector_mtf = @data.selector_mtf
in_use16 = 0
16.times do |i|
in_use16 |= 1 << i if bit
end
255.downto(0) do |i|
in_use[i] = false
end
16.times do |i|
if (in_use16 & (1 << i)) != 0
i16 = i << 4
16.times do |j|
in_use[i16 + j] = true if bit
end
end
end
make_maps
alpha_size = @n_in_use + 2
groups = r 3
selectors = r 15
selectors.times do |i|
j = 0
while bit
j += 1
end
selector_mtf[i] = j
end
groups.downto(0) do |v|
pos[v] = v
end
selectors.times do |i|
v = selector_mtf[i] & 0xff
tmp = pos[v]
while v > 0 do
pos[v] = pos[v -= 1]
end
pos[0] = tmp
selector[i] = tmp
end
len = @data.temp_char_array_2d
groups.times do |t|
curr = r 5
len_t = len[t]
alpha_size.times do |i|
while bit
curr += bit ? -1 : 1
end
len_t[i] = curr
end
@data.temp_char_array_2d[t] = len_t
end
create_huffman_decoding_tables alpha_size, groups
end
def create_huffman_decoding_tables(alpha_size, groups)
len = @data.temp_char_array_2d
min_lens = @data.min_lens
limit = @data.limit
base = @data.base
perm = @data.perm
groups.times do |t|
min_len = 32
max_len = 0
len_t = len[t]
(alpha_size - 1).downto 0 do |i|
lent = len_t[i]
max_len = lent if lent > max_len
min_len = lent if lent < min_len
end
create_decode_tables limit[t], base[t], perm[t], len[t], min_len, max_len, alpha_size
min_lens[t] = min_len
end
end
def get_and_move_to_front_decode
@orig_ptr = r 24
receive_decoding_tables
ll8 = @data.ll8
unzftab = @data.unzftab
selector = @data.selector
seq_to_unseq = @data.seq_to_unseq
yy = @data.get_and_move_to_front_decode_yy
min_lens = @data.min_lens
limit = @data.limit
base = @data.base
perm = @data.perm
limit_last = @block_size * BASEBLOCKSIZE
256.downto(0) do |i|
yy[i] = i
unzftab[i] = 0
end
group_no = 0
group_pos = G_SIZE - 1
eob = @n_in_use + 1
next_sym = get_and_move_to_front_decode0 0
buff_shadow = @buff
live_shadow = @live
last_shadow = -1
zt = selector[group_no] & 0xff
base_zt = base[zt]
limit_zt = limit[zt]
perm_zt = perm[zt]
min_lens_zt = min_lens[zt]
while next_sym != eob
if (next_sym == RUNA) || (next_sym == RUNB)
s = -1
n = 1
while true do
if next_sym == RUNA
s += n
elsif next_sym == RUNB
s += n << 1
else
break
end
if group_pos == 0
group_pos = G_SIZE - 1
group_no += 1
zt = selector[group_no] & 0xff
base_zt = base[zt]
limit_zt = limit[zt]
perm_zt = perm[zt]
min_lens_zt = min_lens[zt]
else
group_pos -= 1
end
zn = min_lens_zt
while live_shadow < zn
thech = @io.readbyte
raise 'unexpected end of stream' if thech < 0
buff_shadow = ((buff_shadow << 8) & 0xffffffff) | thech
live_shadow += 8
end
zvec = ((buff_shadow >> (live_shadow - zn)) & 0xffffffff) & ((1 << zn) - 1)
live_shadow -= zn
while zvec > limit_zt[zn]
zn += 1
while live_shadow < 1
thech = @io.readbyte
raise 'unexpected end of stream' if thech < 0
buff_shadow = ((buff_shadow << 8) & 0xffffffff) | thech
live_shadow += 8
end
live_shadow -= 1
zvec = (zvec << 1) | ((buff_shadow >> live_shadow) & 1)
end
next_sym = perm_zt[zvec - base_zt[zn]]
n = n << 1
end
ch = seq_to_unseq[yy[0]]
unzftab[ch & 0xff] += s + 1
while s >= 0
last_shadow += 1
ll8[last_shadow] = ch
s -= 1
end
raise 'block overrun' if last_shadow >= limit_last
else
last_shadow += 1
raise 'block overrun' if last_shadow >= limit_last
tmp = yy[next_sym - 1]
unzftab[seq_to_unseq[tmp] & 0xff] += 1
ll8[last_shadow] = seq_to_unseq[tmp]
yy[1, next_sym - 1] = yy[0, next_sym - 1]
yy[0] = tmp
if group_pos == 0
group_pos = G_SIZE - 1
group_no += 1
zt = selector[group_no] & 0xff
base_zt = base[zt]
limit_zt = limit[zt]
perm_zt = perm[zt]
min_lens_zt = min_lens[zt]
else
group_pos -= 1
end
zn = min_lens_zt
while live_shadow < zn
thech = @io.readbyte
raise 'unexpected end of stream' if thech < 0
buff_shadow = ((buff_shadow << 8) & 0xffffffff) | thech
live_shadow += 8
end
zvec = (buff_shadow >> (live_shadow - zn)) & ((1 << zn) - 1)
live_shadow -= zn
while zvec > limit_zt[zn]
zn += 1
while live_shadow < 1
thech = @io.readbyte
raise 'unexpected end of stream' if thech < 0
buff_shadow = ((buff_shadow << 8) & 0xffffffff) | thech
live_shadow += 8
end
live_shadow -= 1
zvec = (zvec << 1) | ((buff_shadow >> live_shadow) & 1)
end
next_sym = perm_zt[zvec - base_zt[zn]]
end
end
@last = last_shadow
@live = live_shadow
@buff = buff_shadow
end
def get_and_move_to_front_decode0(group_no)
zt = @data.selector[group_no] & 0xff
limit_zt = @data.limit[zt]
zn = @data.min_lens[zt]
zvec = r zn
live_shadow = @live
buff_shadow = @buff
while zvec > limit_zt[zn]
zn += 1
while live_shadow < 1
thech = @io.readbyte
raise 'unexpected end of stream' if thech < 0
buff_shadow = ((buff_shadow << 8) & 0xffffffff) | thech
live_shadow += 8
end
live_shadow -=1
zvec = (zvec << 1) | ((buff_shadow >> live_shadow) & 1)
end
@live = live_shadow
@buff = buff_shadow
@data.perm[zt][zvec - @data.base[zt][zn]]
end
def setup_block
return if @data.nil?
cftab = @data.cftab
tt = @data.init_tt @last + 1
ll8 = @data.ll8
cftab[0] = 0
cftab[1, 256] = @data.unzftab[0, 256]
c = cftab[0]
1.upto(256) do |i|
c += cftab[i]
cftab[i] = c
end
last_shadow = @last
(last_shadow + 1).times do |i|
cftab_i = ll8[i] & 0xff
tt[cftab[cftab_i]] = i
cftab[cftab_i] += 1
end
raise 'stream corrupted' if @orig_ptr < 0 || @orig_ptr >= tt.size
@su_t_pos = tt[@orig_ptr]
@su_count = 0
@su_i2 = 0
@su_ch2 = 256
if @block_randomised
@su_r_n_to_go = 0
@su_r_t_pos = 0
setup_rand_part_a
else
setup_no_rand_part_a
end
end
def setup_rand_part_a
if @su_i2 <= @last
@su_ch_prev = @su_ch2
su_ch2_shadow = @data.ll8[@su_t_pos] & 0xff
@su_t_pos = @data.tt[@su_t_pos]
if @su_r_n_to_go == 0
@su_r_n_to_go = RNUMS[@su_r_t_pos] - 1
@su_r_t_pos += 1
@su_r_t_pos = 0 if @su_r_t_pos == 512
else
@su_r_n_to_go -= 1
end
@su_ch2 = su_ch2_shadow ^= (@su_r_n_to_go == 1) ? 1 : 0
@su_i2 += 1
@current_char = su_ch2_shadow
@current_state = RAND_PART_B_STATE
@crc.update_crc su_ch2_shadow
else
end_block
init_block
setup_block
end
end
def setup_no_rand_part_a
if @su_i2 <= @last
@su_ch_prev = @su_ch2
su_ch2_shadow = @data.ll8[@su_t_pos] & 0xff
@su_ch2 = su_ch2_shadow
@su_t_pos = @data.tt[@su_t_pos]
@su_i2 += 1
@current_char = su_ch2_shadow
@current_state = NO_RAND_PART_B_STATE
@crc.update_crc su_ch2_shadow
else
@current_state = NO_RAND_PART_A_STATE
end_block
init_block
setup_block
end
end
def setup_rand_part_b
if @su_ch2 != @su_ch_prev
@current_state = RAND_PART_A_STATE
@su_count = 1
setup_rand_part_a
else
@su_count += 1
if @su_count >= 4
@su_z = @data.ll8[@su_t_pos] & 0xff
@su_t_pos = @data.tt[@su_t_pos]
if @su_r_n_to_go == 0
@su_r_n_to_go = RNUMS[@su_r_t_pos] - 1
@su_r_t_pos += 1
@su_r_t_pos = 0 if @su_r_t_pos == 512
else
@su_r_n_to_go -= 1
end
@su_j2 = 0
@current_state = RAND_PART_C_STATE
@su_z ^= 1 if @su_r_n_to_go == 1
setup_rand_part_c
else
@current_state = RAND_PART_A_STATE
setup_rand_part_a
end
end
end
def setup_rand_part_c
if @su_j2 < @su_z
@current_char = @su_ch2
@crc.update_crc @su_ch2
@su_j2 += 1
else
@current_state = RAND_PART_A_STATE
@su_i2 += 1
@su_count = 0
setup_rand_part_a
end
end
def setup_no_rand_part_b
if @su_ch2 != @su_ch_prev
@su_count = 1
setup_no_rand_part_a
else
@su_count += 1
if @su_count >= 4
@su_z = @data.ll8[@su_t_pos] & 0xff
@su_t_pos = @data.tt[@su_t_pos]
@su_j2 = 0
setup_no_rand_part_c
else
setup_no_rand_part_a
end
end
end
def setup_no_rand_part_c
if @su_j2 < @su_z
su_ch2_shadow = @su_ch2
@current_char = su_ch2_shadow
@crc.update_crc su_ch2_shadow
@su_j2 += 1
@current_state = NO_RAND_PART_C_STATE
else
@su_i2 += 1
@su_count = 0
setup_no_rand_part_a
end
end
def size
if @io.is_a? StringIO
@io.size
elsif @io.is_a? File
@io.stat.size
end
end
def uncompressed
@last + 1
end
def inspect
"#<#{self.class}: @io=#{@io.inspect} size=#{size} uncompressed=#{uncompressed}>"
end
end

View File

@@ -0,0 +1,43 @@
# This code is free software; you can redistribute it and/or modify it under
# the terms of the new BSD License.
#
# Copyright (c) 2011-2013, Sebastian Staudt
class PoiseArchive::Bzip2::InputData
include PoiseArchive::Bzip2::Constants
attr_reader :base, :cftab, :get_and_move_to_front_decode_yy, :in_use,
:limit, :ll8, :min_lens, :perm, :receive_decoding_tables_pos,
:selector, :selector_mtf, :seq_to_unseq, :temp_char_array_2d,
:unzftab, :tt
def initialize(block_size)
@in_use = Array.new 256, false
@seq_to_unseq = Array.new 256, 0
@selector = Array.new MAX_SELECTORS, 0
@selector_mtf = Array.new MAX_SELECTORS, 0
@unzftab = Array.new 256, 0
@base = Array.new(N_GROUPS) { Array.new(MAX_ALPHA_SIZE, 0) }
@limit = Array.new(N_GROUPS) { Array.new(MAX_ALPHA_SIZE, 0) }
@perm = Array.new(N_GROUPS) { Array.new(MAX_ALPHA_SIZE, 0) }
@min_lens = Array.new N_GROUPS, 0
@cftab = Array.new 257, 0
@get_and_move_to_front_decode_yy = Array.new 256
@temp_char_array_2d = Array.new(N_GROUPS) { Array.new(MAX_ALPHA_SIZE, 0) }
@receive_decoding_tables_pos = Array.new N_GROUPS, 0
@ll8 = Array.new block_size * BASEBLOCKSIZE
end
def init_tt(size)
@tt = Array.new(size) if @tt.nil? || @tt.size < size
@tt
end
end

View File

@@ -0,0 +1,57 @@
# This code is free software; you can redistribute it and/or modify it under
# the terms of the new BSD License.
#
# Copyright (c) 2011-2013, Sebastian Staudt
class PoiseArchive::Bzip2::OutputData
include PoiseArchive::Bzip2::Constants
attr_reader :block, :ftab, :fmap, :generate_mtf_values_yy, :heap, :in_use,
:main_sort_big_done, :main_sort_copy, :main_sort_running_order,
:mtf_freq, :parent, :quadrant, :selector, :selector_mtf,
:send_mtf_values_code, :send_mtf_values_cost,
:send_mtf_values_fave, :send_mtf_values_len,
:send_mtf_values_rfreq, :send_mtf_values2_pos,
:send_mtf_values4_in_use_16, :sfmap, :stack_dd, :stack_hh,
:stack_ll, :unseq_to_seq, :weight
def initialize(block_size)
n = block_size * BASEBLOCKSIZE
@block = Array.new n + 1 + NUM_OVERSHOOT_BYTES, 0
@fmap = Array.new n, 0
@selector = Array.new MAX_SELECTORS
@selector_mtf = Array.new MAX_SELECTORS
@sfmap = Array.new 2 * n
@quadrant = @sfmap
@in_use = Array.new 256
@mtf_freq = Array.new MAX_ALPHA_SIZE, 0
@unseq_to_seq = Array.new 256
@generate_mtf_values_yy = Array.new 256
@send_mtf_values_code = Array.new(N_GROUPS) { Array.new MAX_ALPHA_SIZE }
@send_mtf_values_cost = Array.new N_GROUPS
@send_mtf_values_fave = Array.new N_GROUPS
@send_mtf_values_len = Array.new(N_GROUPS) { Array.new MAX_ALPHA_SIZE }
@send_mtf_values_rfreq = Array.new(N_GROUPS) { Array.new MAX_ALPHA_SIZE }
@send_mtf_values2_pos = Array.new N_GROUPS
@send_mtf_values4_in_use_16 = Array.new 16
@stack_dd = Array.new QSORT_STACK_SIZE
@stack_hh = Array.new QSORT_STACK_SIZE
@stack_ll = Array.new QSORT_STACK_SIZE
@main_sort_big_done = Array.new 256
@main_sort_copy = Array.new 256
@main_sort_running_order = Array.new 256
@heap = Array.new MAX_ALPHA_SIZE + 2
@parent = Array.new MAX_ALPHA_SIZE + 2
@weight = Array.new MAX_ALPHA_SIZE + 2
@ftab = Array.new 65537
end
end

View File

@@ -0,0 +1,18 @@
#
# Copyright 2016-2017, Noah Kantrowitz
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
require 'poise_archive/resources'
require 'poise_archive/archive_providers'

View File

@@ -0,0 +1,26 @@
#
# Copyright 2016-2017, Noah Kantrowitz
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
require 'poise_archive/resources/poise_archive'
module PoiseArchive
# Chef resources and providers for poise-archive.
#
# @since 1.0.0
module Resources
end
end

View File

@@ -0,0 +1,151 @@
#
# Copyright 2016-2017, Noah Kantrowitz
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
require 'base64'
require 'uri'
require 'chef/resource'
require 'poise'
module PoiseArchive
module Resources
# (see PoiseArchive::Resource)
# @since 1.0.0
module PoiseArchive
# A `poise_archive` resource to unpack archives.
#
# @provides poise_archive
# @action unpack
# @example
# poise_archive '/opt/myapp.tgz'
# @example Downloading from a URL with options
# poise_archive ['http://example.com/myapp.zip', {headers: {'Authentication' => '...'}}] do
# destination '/opt/myapp'
# end
class Resource < Chef::Resource
include Poise
provides(:poise_archive)
actions(:unpack)
# @!attribute path
# Path to the archive. If relative, it is taken as a file inside
# `Chef::Config[:file_cache_path]`. Can also be a URL to download the
# archive from.
# @return [String, Array]
attribute(:path, kind_of: String, default: lazy { @raw_name.is_a?(Array) ? @raw_name[0] : name }, required: true)
# @!attribute destination
# Path to unpack the archive to. If not specified, the path of the
# archive without the file extension is used.
# @return [String, nil, false]
attribute(:destination, kind_of: [String, NilClass, FalseClass], default: lazy { default_destination })
# @!attribute group
# Group to run the unpack as.
# @return [String, Integer, nil, false]
attribute(:group, kind_of: [String, Integer, NilClass, FalseClass])
# @!attribute keep_existing
# Keep existing files in the destination directory when unpacking.
# @return [Boolean]
attribute(:keep_existing, equal_to: [true, false], default: false)
# @!attribute source_properties
# Properties to pass through to the underlying download resource if
# using one. Merged with the array form of {#name}.
# @return [Hash]
attribute(:source_properties, option_collector: true, forced_keys: %i{retries})
# @!attribute strip_components
# Number of intermediary directories to skip when unpacking. Works
# like GNU tar's --strip-components.
# @return [Integer]
attribute(:strip_components, kind_of: Integer, default: 1)
# @!attribute user
# User to run the unpack as.
# @return [String, Integer, nil, false]
attribute(:user, kind_of: [String, Integer, NilClass, FalseClass])
# Alias for the forgetful.
# @api private
alias_method :owner, :user
def initialize(name, run_context)
@raw_name = name # Capture this before it gets coerced to a string.
super
end
# Regexp for URL-like paths.
# @api private
URL_PATHS = %r{^(\w+:)?//}
# Check if the source path is a URL.
#
# @api private
# @return [Boolean]
def is_url?
path =~ URL_PATHS
end
# Expand a relative file path against `Chef::Config[:file_cache_path]`.
# For URLs it returns the cache file path.
#
# @api private
# @return [String]
def absolute_path
if is_url?
# Use the last path component without the query string plus the name
# of the resource in Base64. This should be both mildly readable and
# also unique per invocation.
url_part = URI(path).path.split(/\//).last
base64_name = Base64.strict_encode64(name).gsub(/\=/, '')
::File.join(Chef::Config[:file_cache_path], "#{base64_name}_#{url_part}")
else
::File.expand_path(path, Chef::Config[:file_cache_path])
end
end
# Merge the explicit source properties with the array form of the name.
#
# @api private
# @return [Hash]
def merged_source_properties
if @raw_name.is_a?(Array) && @raw_name[1]
source_properties.merge(@raw_name[1])
else
source_properties
end
end
private
# Filename components to ignore.
# @api private
BASENAME_IGNORE = /(\.(t?(ar|gz|bz2?|xz)|zip))+$/
# Default value for the {#destination} property
#
# @api private
# @return [String]
def default_destination
if is_url?
raise ValueError.new("Destination for URL-based archive #{self} must be specified explicitly")
else
::File.join(::File.dirname(absolute_path), ::File.basename(path).gsub(BASENAME_IGNORE, ''))
end
end
end
# Providers can be found in archive_providers/.
end
end
end

View File

@@ -0,0 +1,20 @@
#
# Copyright 2016-2017, Noah Kantrowitz
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
module PoiseArchive
VERSION = '1.5.0'
end

View File

@@ -0,0 +1,19 @@
#
# Copyright 2016-2017, Noah Kantrowitz
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
raise 'Halite is not compatible with no_lazy_load false, please set no_lazy_load true in your Chef configuration file.' unless Chef::Config[:no_lazy_load]
$LOAD_PATH << File.expand_path('../../files/halite_gem', __FILE__)
require "poise_archive/cheftie"

View File

@@ -0,0 +1 @@
{"name":"poise-archive","version":"1.5.0","description":"A Chef cookbook for unpacking file archives like tar and zip.","long_description":"# Poise-Archive Cookbook\n\n[![Build Status](https://img.shields.io/travis/poise/poise-archive.svg)](https://travis-ci.org/poise/poise-archive)\n[![Gem Version](https://img.shields.io/gem/v/poise-archive.svg)](https://rubygems.org/gems/poise-archive)\n[![Cookbook Version](https://img.shields.io/cookbook/v/poise-archive.svg)](https://supermarket.chef.io/cookbooks/poise-archive)\n[![Coverage](https://img.shields.io/codecov/c/github/poise/poise-archive.svg)](https://codecov.io/github/poise/poise-archive)\n[![Gemnasium](https://img.shields.io/gemnasium/poise/poise-archive.svg)](https://gemnasium.com/poise/poise-archive)\n[![License](https://img.shields.io/badge/license-Apache_2-blue.svg)](https://www.apache.org/licenses/LICENSE-2.0)\n\nA [Chef](https://www.chef.io/) cookbook to unpack file archives.\n\nIt supports `.tar`, `.tar.gz`, `.tar.bz2`, and `.zip` archive files.\n\n## Quick Start\n\nTo download an unpack and archive:\n\n```ruby\npoise_archive 'https://example.com/myapp.tgz' do\n destination '/opt/myapp'\nend\n```\n\n## Requirements\n\nChef 12.1 or newer is required.\n\n## Platforms\n\nThis cookbook supports all platforms (including Windows) but some Unix platforms\n(Solaris, AIX) may see very slow tar file unpacking when using the pure-Ruby fallback\nimplementation.\n\n## Resources\n\n### `poise_archive`\n\nThe `poise_archive` resource unpacks file archives.\n\n```ruby\npoise_archive '/tmp/myapp-1.2.0.tar' do\n destination '/srv/myapp-1.2.0'\nend\n```\n\nA URL can also be passed as the source path, optionally with extra properties to\nbe merged with `source_properties`.\n\n```ruby\npoise_archive 'http://example.com/myapp-1.2.0.zip' do\n destination '/srv/myapp-1.2.0'\nend\n\npoise_archive ['http://example.com/myapp-1.2.0.zip', {headers: {'Authentication' => '...'}}] do\n destination '/srv/myapp-1.2.0'\nend\n```\n\n#### Actions\n\n* `:unpack` Unpack the archive. *(default)*\n\n#### Properties\n\n* `path` Path to the archive. If relative, it is taken as a file inside\n `Chef::Config[:file_cache_path]`. If a URL, it is downloaded to a cache file\n first. *(name attribute)*\n* `destination` Path to unpack the archive to. If not specified, the path of\n the archive without the file extension is used. Required when unpacking from\n a URL. *(default: auto)*\n* `group` Group to run the unpack as.\n* `keep_existing` Keep existing files in the destination directory when\n unpacking. *(default: false)*\n* `source_properties` Property key/value pairs to be applied to the\n `remote_file` file resource when downloading a URL. *(default: {retries: 5})*\n* `strip_components` Number of intermediary directories to skip when\n unpacking. Works like GNU tar's `--strip-components`. *(default: 1)*\n* `user` User to run the unpack as.\n\n## Sponsors\n\nDevelopment sponsored by [Bloomberg](http://www.bloomberg.com/company/technology/).\n\nThe Poise test server infrastructure is sponsored by [Rackspace](https://rackspace.com/).\n\n## License\n\nCopyright 2016-2017, Noah Kantrowitz\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\nhttp://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n\nBZip2 implementation is based on RBzip2. Copyright Sebastian Staudt, Brian Lopez.\nRBzip2 code used under the terms of the new BSD license.\n","maintainer":"Noah Kantrowitz","maintainer_email":"noah@coderanger.net","license":"Apache 2.0","platforms":{},"dependencies":{"poise":"~> 2.6"},"recommendations":{},"suggestions":{},"conflicting":{},"providing":{},"replacing":{},"attributes":{},"groupings":{},"recipes":{},"source_url":"https://github.com/poise/poise-archive","issues_url":"https://github.com/poise/poise-archive/issues","chef_version":[["< 14",">= 12.1"]],"ohai_version":[]}