minitar 1.0.2 → 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (53) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +285 -0
  3. data/CONTRIBUTING.md +273 -0
  4. data/CONTRIBUTORS.md +27 -0
  5. data/LICENCE.md +39 -0
  6. data/Manifest.txt +29 -6
  7. data/README.md +70 -0
  8. data/Rakefile +74 -19
  9. data/SECURITY.md +64 -0
  10. data/docs/ruby.txt +3 -3
  11. data/lib/minitar/input.rb +69 -56
  12. data/lib/minitar/output.rb +34 -22
  13. data/lib/minitar/pax_header.rb +111 -0
  14. data/lib/minitar/posix_header.rb +96 -57
  15. data/lib/minitar/reader.rb +65 -70
  16. data/lib/minitar/version.rb +5 -0
  17. data/lib/minitar/writer.rb +50 -88
  18. data/lib/minitar.rb +60 -64
  19. data/licenses/bsdl.txt +20 -0
  20. data/licenses/dco.txt +34 -0
  21. data/licenses/ruby.txt +52 -0
  22. data/test/fixtures/issue_46.tar.gz +0 -0
  23. data/test/fixtures/issue_62.tar.gz +0 -0
  24. data/test/fixtures/tar_input.tgz +0 -0
  25. data/test/fixtures/test_input_non_strict_octal.tgz +0 -0
  26. data/test/fixtures/test_input_relative.tgz +0 -0
  27. data/test/fixtures/test_input_space_octal.tgz +0 -0
  28. data/test/fixtures/test_minitar.tar.gz +0 -0
  29. data/test/minitest_helper.rb +12 -1
  30. data/test/support/minitar_test_helpers/fixtures.rb +38 -0
  31. data/test/support/minitar_test_helpers/header.rb +130 -0
  32. data/test/support/minitar_test_helpers/tarball.rb +324 -0
  33. data/test/support/minitar_test_helpers.rb +36 -0
  34. data/test/test_filename_boundary_conditions.rb +74 -0
  35. data/test/test_gnu_tar_compatibility.rb +92 -0
  36. data/test/test_integration_pack_unpack_cycle.rb +38 -0
  37. data/test/test_issue_46.rb +5 -23
  38. data/test/test_issue_62.rb +50 -0
  39. data/test/test_minitar.rb +168 -39
  40. data/test/test_pax_header.rb +104 -0
  41. data/test/test_pax_support.rb +66 -0
  42. data/test/test_tar_header.rb +289 -75
  43. data/test/test_tar_input.rb +14 -61
  44. data/test/test_tar_output.rb +7 -9
  45. data/test/test_tar_reader.rb +17 -18
  46. data/test/test_tar_writer.rb +105 -126
  47. metadata +95 -89
  48. data/Contributing.md +0 -94
  49. data/History.md +0 -236
  50. data/Licence.md +0 -15
  51. data/README.rdoc +0 -92
  52. data/test/support/tar_test_helpers.rb +0 -134
  53. /data/{Code-of-Conduct.md → CODE_OF_CONDUCT.md} +0 -0
data/README.rdoc DELETED
@@ -1,92 +0,0 @@
1
- = minitar
2
-
3
- home :: https://github.com/halostatue/minitar/
4
- code :: https://github.com/halostatue/minitar/
5
- bugs :: https://github.com/halostatue/minitar/issues
6
- rdoc :: https://rdoc.info/gems/minitar/
7
- cli :: https://github.com/halostatue/minitar-cli
8
-
9
- == Description
10
-
11
- The minitar library is a pure-Ruby library that provides the ability to deal
12
- with POSIX tar(1) archive files.
13
-
14
- This is release 0.12. This is likely the last revision before 1.0.
15
-
16
- minitar (previously called Archive::Tar::Minitar) is based heavily on code
17
- originally written by Mauricio Julio Fernández Pradier for the rpa-base
18
- project.
19
-
20
- == Synopsis
21
-
22
- Using minitar is easy. The simplest case is:
23
-
24
- require 'minitar'
25
-
26
- # Packs everything that matches Find.find('tests').
27
- # test.tar will automatically be closed by Minitar.pack.
28
- Minitar.pack('tests', File.open('test.tar', 'wb'))
29
-
30
- # Unpacks 'test.tar' to 'x', creating 'x' if necessary.
31
- Minitar.unpack('test.tar', 'x')
32
-
33
- A gzipped tar can be written with:
34
-
35
- require 'zlib'
36
- # test.tgz will be closed automatically.
37
- Minitar.pack('tests', Zlib::GzipWriter.new(File.open('test.tgz', 'wb'))
38
-
39
- # test.tgz will be closed automatically.
40
- Minitar.unpack(Zlib::GzipReader.new(File.open('test.tgz', 'rb')), 'x')
41
-
42
- As the case above shows, one need not write to a file. However, it will
43
- sometimes require that one dive a little deeper into the API, as in the case of
44
- StringIO objects. Note that I'm not providing a block with Minitar::Output, as
45
- Minitar::Output#close automatically closes both the Output object and the
46
- wrapped data stream object.
47
-
48
- begin
49
- sgz = Zlib::GzipWriter.new(StringIO.new(String.new))
50
- tar = Output.new(sgz)
51
- Find.find('tests') do |entry|
52
- Minitar.pack_file(entry, tar)
53
- end
54
- ensure
55
- # Closes both tar and sgz.
56
- tar.close
57
- end
58
-
59
- == Minitar and Security
60
-
61
- Minitar aims to be secure by default for the data *inside* of a tarfile. If
62
- there are any security issues discovered, please feel free to open an issue.
63
- Should you wish to make a more confidential report, you can find my PGP key
64
- information at {Keybase}[https://keybase.io/halostatue]. Bear with me: I do not
65
- use PGP regularly, so it may take some time to remember the command invocations
66
- required to successfully handle this.
67
-
68
- Minitar does *not* perform validation of path names provided to the convenience
69
- calsses Minitar::Output and Minitar::Input, which use Kernel.open for their
70
- underlying implementations when not given an IO-like object.
71
-
72
- Improper use of these classes with arbitrary input filenames may leave your
73
- your software to the same class of vulnerability as reported for Net::FTP
74
- ({CVE-2017-17405}[https://nvd.nist.gov/vuln/detail/CVE-2017-17405]). Of
75
- particular note, "if the localfile argument starts with the '|' pipe character,
76
- the command following the pipe character is executed."
77
-
78
- Additionally, the use of the `open-uri` library (which extends Kernel.open with
79
- transparent implementations of Net::HTTP, Net::HTTPS, and Net::FTP), there are
80
- other possible vulnerabilities when accepting arbitrary input, as
81
- {detailed}[https://sakurity.com/blog/2015/02/28/openuri.html] by Egor Homakov.
82
-
83
- These security vulnerabilities may be avoided, even with the Minitar::Output
84
- and Minitar::Input convenience classes, by providing IO-like objects instead of
85
- pathname-like objects as the source or destination of these classes.
86
-
87
- == minitar Semantic Versioning
88
-
89
- The minitar library uses a {Semantic Versioning}[http://semver.org/] scheme
90
- with one change:
91
-
92
- * When PATCH is zero (+0+), it will be omitted from version references.
@@ -1,134 +0,0 @@
1
- module TarTestHelpers
2
- Field = Struct.new(:name, :offset, :length)
3
- def self.Field(name, length)
4
- # standard:disable ThreadSafety/InstanceVariableInClassMethod
5
- @offset ||= 0
6
- field = Field.new(name, @offset, length)
7
- @offset += length
8
- # standard:enable ThreadSafety/InstanceVariableInClassMethod
9
-
10
- FIELDS[name] = field
11
- FIELD_ORDER << name
12
- field
13
- end
14
-
15
- private
16
-
17
- FIELDS = {}
18
- FIELD_ORDER = []
19
-
20
- Field("name", 100)
21
- Field("mode", 8)
22
- Field("uid", 8)
23
- Field("gid", 8)
24
- Field("size", 12)
25
- Field("mtime", 12)
26
- Field("checksum", 8)
27
- Field("typeflag", 1)
28
- Field("linkname", 100)
29
- Field("magic", 6)
30
- Field("version", 2)
31
- Field("uname", 32)
32
- Field("gname", 32)
33
- Field("devmajor", 8)
34
- Field("devminor", 8)
35
- Field("prefix", 155)
36
-
37
- BLANK_CHECKSUM = " " * 8
38
- NULL_100 = "\0" * 100
39
- USTAR = "ustar\0"
40
- DOUBLE_ZERO = "00"
41
-
42
- def assert_headers_equal(expected, actual)
43
- FIELD_ORDER.each do |field|
44
- message = if field == "checksum"
45
- "Header checksums are expected to match."
46
- else
47
- "Header field #{field} is expected to match."
48
- end
49
-
50
- offset = FIELDS[field].offset
51
- length = FIELDS[field].length
52
-
53
- assert_equal expected[offset, length], actual[offset, length], message
54
- end
55
- end
56
-
57
- def assert_modes_equal(expected, actual, name)
58
- return if Minitar.windows?
59
-
60
- assert_equal(
61
- mode_string(expected),
62
- mode_string(actual),
63
- "Mode for #{name} does not match"
64
- )
65
- end
66
-
67
- def tar_file_header(fname, dname, mode, length)
68
- update_checksum(header("0", fname, dname, length, mode))
69
- end
70
-
71
- def tar_dir_header(name, prefix, mode)
72
- update_checksum(header("5", name, prefix, 0, mode))
73
- end
74
-
75
- def tar_symlink_header(name, prefix, mode, target)
76
- update_checksum(header("2", name, prefix, 0, mode, target))
77
- end
78
-
79
- def header(type, fname, dname, length, mode, link_name = "")
80
- raw_header(type,
81
- asciiz(fname, 100),
82
- asciiz(dname, 155),
83
- z(to_oct(length, 11)),
84
- z(to_oct(mode, 7)),
85
- asciiz(link_name, 100))
86
- end
87
-
88
- def raw_header(type, fname, dname, length, mode, link_name = "")
89
- arr = [
90
- fname, mode, z(to_oct(nil, 7)), z(to_oct(nil, 7)),
91
- length, z(to_oct(0, 11)), BLANK_CHECKSUM, type,
92
- asciiz(link_name, 100), USTAR, DOUBLE_ZERO, asciiz("", 32), asciiz("", 32),
93
- z(to_oct(nil, 7)), z(to_oct(nil, 7)), dname
94
- ]
95
-
96
- h = arr.join.bytes.to_a.pack("C100C8C8C8C12C12C8CC100C6C2C32C32C8C8C155")
97
- ret = h + "\0" * (512 - h.bytesize)
98
- assert_equal 512, ret.bytesize
99
- ret
100
- end
101
-
102
- def update_checksum(header)
103
- header[FIELDS["checksum"].offset, FIELDS["checksum"].length] =
104
- # inject(:+) was introduced in which version?
105
- sp(z(to_oct(header.unpack("C*").inject { |a, e| a + e }, 6)))
106
- header
107
- end
108
-
109
- def to_oct(n, pad_size)
110
- if n.nil?
111
- "\0" * pad_size
112
- else
113
- "%0#{pad_size}o" % n
114
- end
115
- end
116
-
117
- def asciiz(str, length)
118
- str + "\0" * (length - str.bytesize)
119
- end
120
-
121
- def sp(s)
122
- s + " "
123
- end
124
-
125
- def z(s)
126
- s + "\0"
127
- end
128
-
129
- def mode_string(value)
130
- "%04o" % (value & 0o777)
131
- end
132
-
133
- Minitest::Test.send(:include, self)
134
- end
File without changes