minitar 0.9 → 0.12

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.
@@ -1,6 +1,6 @@
1
1
  # coding: utf-8
2
2
 
3
- require 'archive/tar/minitar/reader'
3
+ require "archive/tar/minitar/reader"
4
4
 
5
5
  module Archive::Tar::Minitar
6
6
  # Wraps a Archive::Tar::Minitar::Reader with convenience methods and wrapped
@@ -51,7 +51,7 @@ module Archive::Tar::Minitar
51
51
  def self.each_entry(input)
52
52
  return to_enum(__method__, input) unless block_given?
53
53
 
54
- open(input) do |stream|
54
+ Input.open(input) do |stream|
55
55
  stream.each do |entry|
56
56
  yield entry
57
57
  end
@@ -71,10 +71,10 @@ module Archive::Tar::Minitar
71
71
  # Archive::Tar::Minitar::Input.new(path) -> input
72
72
  def initialize(input)
73
73
  @io = if input.respond_to?(:read)
74
- input
75
- else
76
- ::Kernel.open(input, 'rb')
77
- end
74
+ input
75
+ else
76
+ ::Kernel.open(input, "rb")
77
+ end
78
78
 
79
79
  unless Archive::Tar::Minitar.seekable?(@io, :rewind)
80
80
  raise Archive::Tar::Minitar::NonSeekableStream
@@ -96,7 +96,7 @@ module Archive::Tar::Minitar
96
96
  ensure
97
97
  @tar.rewind
98
98
  end
99
- alias each each_entry
99
+ alias_method :each, :each_entry
100
100
 
101
101
  # Extracts the current +entry+ to +destdir+. If a block is provided, it
102
102
  # yields an +action+ Symbol, the full name of the file being extracted
@@ -119,9 +119,9 @@ module Archive::Tar::Minitar
119
119
  # Reader::EntryStream, with all methods thereof.
120
120
  def extract_entry(destdir, entry, options = {}, &block) # :yields action, name, stats:
121
121
  stats = {
122
- :current => 0,
123
- :currinc => 0,
124
- :entry => entry
122
+ :current => 0,
123
+ :currinc => 0,
124
+ :entry => entry
125
125
  }
126
126
 
127
127
  # extract_entry is not vulnerable to prefix '/' vulnerabilities, but it
@@ -133,10 +133,10 @@ module Archive::Tar::Minitar
133
133
  # leave +destdir+.
134
134
  #
135
135
  # However, squeeze consecutive '/' characters together.
136
- full_name = entry.full_name.squeeze('/')
136
+ full_name = entry.full_name.squeeze("/")
137
137
 
138
- if full_name =~ /\.{2}(?:\/|\z)/
139
- raise SecureRelativePathError, %q(Path contains '..')
138
+ if /\.{2}(?:\/|\z)/.match?(full_name)
139
+ raise SecureRelativePathError, "Path contains '..'"
140
140
  end
141
141
 
142
142
  if entry.directory?
@@ -164,7 +164,7 @@ module Archive::Tar::Minitar
164
164
 
165
165
  def fsync_dir(dirname)
166
166
  # make sure this hits the disc
167
- dir = open(dirname, 'rb')
167
+ dir = IO.open(dirname, "rb")
168
168
  dir.fsync
169
169
  rescue # ignore IOError if it's an unpatched (old) Ruby
170
170
  nil
@@ -184,7 +184,7 @@ module Archive::Tar::Minitar
184
184
  nil
185
185
  end
186
186
  else
187
- File.unlink(dest.chomp('/')) if File.symlink?(dest.chomp('/'))
187
+ File.unlink(dest.chomp("/")) if File.symlink?(dest.chomp("/"))
188
188
 
189
189
  FileUtils.mkdir_p(dest, :mode => entry.mode)
190
190
  FileUtils.chmod(entry.mode, dest)
@@ -192,7 +192,7 @@ module Archive::Tar::Minitar
192
192
 
193
193
  if options.fetch(:fsync, true)
194
194
  fsync_dir(dest)
195
- fsync_dir(File.join(dest, '..'))
195
+ fsync_dir(File.join(dest, ".."))
196
196
  end
197
197
  end
198
198
 
@@ -211,7 +211,7 @@ module Archive::Tar::Minitar
211
211
 
212
212
  yield :file_start, full_name, stats if block_given?
213
213
 
214
- File.open(destfile, 'wb', entry.mode) do |os|
214
+ File.open(destfile, "wb", entry.mode) do |os|
215
215
  loop do
216
216
  data = entry.read(4096)
217
217
  break unless data
@@ -234,7 +234,7 @@ module Archive::Tar::Minitar
234
234
  yield :dir_fsync, full_name, stats if block_given?
235
235
 
236
236
  fsync_dir(File.dirname(destfile))
237
- fsync_dir(File.join(File.dirname(destfile), '..'))
237
+ fsync_dir(File.join(File.dirname(destfile), ".."))
238
238
  end
239
239
 
240
240
  yield :file_done, full_name, stats if block_given?
@@ -1,6 +1,6 @@
1
1
  # coding: utf-8
2
2
 
3
- require 'archive/tar/minitar/writer'
3
+ require "archive/tar/minitar/writer"
4
4
 
5
5
  module Archive::Tar::Minitar
6
6
  # Wraps a Archive::Tar::Minitar::Writer with convenience methods and wrapped
@@ -40,7 +40,7 @@ module Archive::Tar::Minitar
40
40
  def self.tar(output)
41
41
  return to_enum(__method__, output) unless block_given?
42
42
 
43
- open(output) do |stream|
43
+ Output.open(output) do |stream|
44
44
  yield stream.tar
45
45
  end
46
46
  end
@@ -55,10 +55,10 @@ module Archive::Tar::Minitar
55
55
  # Archive::Tar::Minitar::Output.new(path) -> output
56
56
  def initialize(output)
57
57
  @io = if output.respond_to?(:write)
58
- output
59
- else
60
- ::Kernel.open(output, 'wb')
61
- end
58
+ output
59
+ else
60
+ ::Kernel.open(output, "wb")
61
+ end
62
62
  @tar = Archive::Tar::Minitar::Writer.new(@io)
63
63
  end
64
64
 
@@ -2,8 +2,10 @@
2
2
 
3
3
  ##
4
4
  module Archive; end
5
+
5
6
  ##
6
7
  module Archive::Tar; end
8
+
7
9
  ##
8
10
  module Archive::Tar::Minitar; end
9
11
 
@@ -36,12 +38,12 @@ module Archive::Tar::Minitar; end
36
38
  # unrecognized typeflag value as a regular file."
37
39
  class Archive::Tar::Minitar::PosixHeader
38
40
  BLOCK_SIZE = 512
39
- MAGIC_BYTES = 'ustar'.freeze
41
+ MAGIC_BYTES = "ustar".freeze
40
42
 
41
- GNU_EXT_LONG_LINK = '././@LongLink'
43
+ GNU_EXT_LONG_LINK = "././@LongLink"
42
44
 
43
45
  # Fields that must be set in a POSIX tar(1) header.
44
- REQUIRED_FIELDS = [ :name, :size, :prefix, :mode ].freeze
46
+ REQUIRED_FIELDS = [:name, :size, :prefix, :mode].freeze
45
47
  # Fields that may be set in a POSIX tar(1) header.
46
48
  OPTIONAL_FIELDS = [
47
49
  :uid, :gid, :mtime, :checksum, :typeflag, :linkname, :magic, :version,
@@ -60,9 +62,9 @@ class Archive::Tar::Minitar::PosixHeader
60
62
  attr_accessor :name
61
63
 
62
64
  # The pack format passed to Array#pack for encoding a header.
63
- HEADER_PACK_FORMAT = 'a100a8a8a8a12a12a7aaa100a6a2a32a32a8a8a155'.freeze
65
+ HEADER_PACK_FORMAT = "a100a8a8a8a12a12a7aaa100a6a2a32a32a8a8a155".freeze
64
66
  # The unpack format passed to String#unpack for decoding a header.
65
- HEADER_UNPACK_FORMAT = 'Z100A8A8A8A12A12A8aZ100A6A2Z32Z32A8A8Z155'.freeze
67
+ HEADER_UNPACK_FORMAT = "Z100A8A8A8A12A12A8aZ100A6A2Z32Z32A8A8Z155".freeze
66
68
 
67
69
  class << self
68
70
  # Creates a new PosixHeader from a data stream.
@@ -79,23 +81,23 @@ class Archive::Tar::Minitar::PosixHeader
79
81
 
80
82
  # Creates a new PosixHeader from a BLOCK_SIZE-byte data buffer.
81
83
  def from_data(data)
82
- fields = data.unpack(HEADER_UNPACK_FORMAT)
83
- name = fields.shift
84
- mode = fields.shift.oct
85
- uid = fields.shift.oct
86
- gid = fields.shift.oct
87
- size = strict_oct(fields.shift)
88
- mtime = fields.shift.oct
89
- checksum = fields.shift.oct
90
- typeflag = fields.shift
91
- linkname = fields.shift
92
- magic = fields.shift
93
- version = fields.shift.oct
94
- uname = fields.shift
95
- gname = fields.shift
96
- devmajor = fields.shift.oct
97
- devminor = fields.shift.oct
98
- prefix = fields.shift
84
+ fields = data.unpack(HEADER_UNPACK_FORMAT)
85
+ name = fields.shift
86
+ mode = fields.shift.oct
87
+ uid = fields.shift.oct
88
+ gid = fields.shift.oct
89
+ size = strict_oct(fields.shift)
90
+ mtime = fields.shift.oct
91
+ checksum = fields.shift.oct
92
+ typeflag = fields.shift
93
+ linkname = fields.shift
94
+ magic = fields.shift
95
+ version = fields.shift.oct
96
+ uname = fields.shift
97
+ gname = fields.shift
98
+ devmajor = fields.shift.oct
99
+ devminor = fields.shift.oct
100
+ prefix = fields.shift
99
101
 
100
102
  empty = !data.each_byte.any?(&:nonzero?)
101
103
 
@@ -123,7 +125,7 @@ class Archive::Tar::Minitar::PosixHeader
123
125
  private
124
126
 
125
127
  def strict_oct(string)
126
- return string.oct if string =~ /\A[0-7 ]*\z/
128
+ return string.oct if /\A[0-7 ]*\z/.match?(string)
127
129
  raise ArgumentError, "#{string.inspect} is not a valid octal string"
128
130
  end
129
131
  end
@@ -136,13 +138,13 @@ class Archive::Tar::Minitar::PosixHeader
136
138
  end
137
139
 
138
140
  v[:mtime] = v[:mtime].to_i
139
- v[:checksum] ||= ''
140
- v[:typeflag] ||= '0'
141
- v[:magic] ||= MAGIC_BYTES
142
- v[:version] ||= '00'
141
+ v[:checksum] ||= ""
142
+ v[:typeflag] ||= "0"
143
+ v[:magic] ||= MAGIC_BYTES
144
+ v[:version] ||= "00"
143
145
 
144
146
  FIELDS.each do |f|
145
- instance_variable_set("@#{f}", v[f])
147
+ instance_variable_set(:"@#{f}", v[f])
146
148
  end
147
149
 
148
150
  @empty = v[:empty]
@@ -161,7 +163,7 @@ class Archive::Tar::Minitar::PosixHeader
161
163
  # Returns +true+ if the header is a long name special header which indicates
162
164
  # that the next block of data is the filename.
163
165
  def long_name?
164
- typeflag == 'L' && name == GNU_EXT_LONG_LINK
166
+ typeflag == "L" && name == GNU_EXT_LONG_LINK
165
167
  end
166
168
 
167
169
  # A string representation of the header.
@@ -169,11 +171,11 @@ class Archive::Tar::Minitar::PosixHeader
169
171
  update_checksum
170
172
  header(@checksum)
171
173
  end
172
- alias to_str to_s
174
+ alias_method :to_str, :to_s
173
175
 
174
176
  # Update the checksum field.
175
177
  def update_checksum
176
- hh = header(' ' * 8)
178
+ hh = header(" " * 8)
177
179
  @checksum = oct(calculate_checksum(hh), 6)
178
180
  end
179
181
 
@@ -190,13 +192,13 @@ class Archive::Tar::Minitar::PosixHeader
190
192
  end
191
193
 
192
194
  def calculate_checksum(hdr)
193
- hdr.unpack('C*').inject { |a, e| a + e }
195
+ hdr.unpack("C*").inject { |a, e| a + e }
194
196
  end
195
197
 
196
198
  def header(chksum)
197
199
  arr = [name, oct(mode, 7), oct(uid, 7), oct(gid, 7), oct(size, 11),
198
- oct(mtime, 11), chksum, ' ', typeflag, linkname, magic, version,
199
- uname, gname, oct(devmajor, 7), oct(devminor, 7), prefix]
200
+ oct(mtime, 11), chksum, " ", typeflag, linkname, magic, version,
201
+ uname, gname, oct(devmajor, 7), oct(devminor, 7), prefix]
200
202
  str = arr.pack(HEADER_PACK_FORMAT)
201
203
  str + "\0" * ((BLOCK_SIZE - bytesize(str)) % BLOCK_SIZE)
202
204
  end
@@ -11,14 +11,21 @@ module Archive::Tar::Minitar
11
11
  # This marks the EntryStream closed for reading without closing the
12
12
  # actual data stream.
13
13
  module InvalidEntryStream
14
- # rubocop:disable Style/SingleLineMethods
15
- # rubocop:disable Style/EmptyLineBetweenDefs
16
- def read(*); raise ClosedStream; end
17
- def getc; raise ClosedStream; end
18
- def rewind; raise ClosedStream; end
19
- def closed?; true; end
20
- # rubocop:enable Style/EmptyLineBetweenDefs
21
- # rubocop:enable Style/SingleLineMethods Style/EmptyLineBetweenDefs
14
+ def read(*)
15
+ raise ClosedStream
16
+ end
17
+
18
+ def getc
19
+ raise ClosedStream
20
+ end
21
+
22
+ def rewind
23
+ raise ClosedStream
24
+ end
25
+
26
+ def closed?
27
+ true
28
+ end
22
29
  end
23
30
 
24
31
  # EntryStreams are pseudo-streams on top of the main data stream.
@@ -30,24 +37,24 @@ module Archive::Tar::Minitar
30
37
  end
31
38
 
32
39
  def initialize(header, io)
33
- @io = io
34
- @name = header.name
35
- @mode = header.mode
36
- @uid = header.uid
37
- @gid = header.gid
38
- @size = header.size
39
- @mtime = header.mtime
40
+ @io = io
41
+ @name = header.name
42
+ @mode = header.mode
43
+ @uid = header.uid
44
+ @gid = header.gid
45
+ @size = header.size
46
+ @mtime = header.mtime
40
47
  @checksum = header.checksum
41
48
  @typeflag = header.typeflag
42
49
  @linkname = header.linkname
43
- @magic = header.magic
44
- @version = header.version
45
- @uname = header.uname
46
- @gname = header.gname
50
+ @magic = header.magic
51
+ @version = header.version
52
+ @uname = header.uname
53
+ @gname = header.gname
47
54
  @devmajor = header.devmajor
48
55
  @devminor = header.devminor
49
- @prefix = header.prefix
50
- @read = 0
56
+ @prefix = header.prefix
57
+ @read = 0
51
58
  @orig_pos =
52
59
  if Archive::Tar::Minitar.seekable?(@io)
53
60
  @io.pos
@@ -79,25 +86,25 @@ module Archive::Tar::Minitar
79
86
  # Returns +true+ if the entry represents a directory.
80
87
  def directory?
81
88
  case @typeflag
82
- when '5'
89
+ when "5"
83
90
  true
84
- when '0', "\0"
91
+ when "0", "\0"
85
92
  # If the name ends with a slash, treat it as a directory.
86
93
  # This is what other major tar implementations do for
87
94
  # interoperability and compatibility with older tar variants
88
95
  # and some new ones.
89
- @name.end_with?('/')
96
+ @name.end_with?("/")
90
97
  else
91
98
  false
92
99
  end
93
100
  end
94
- alias directory directory?
101
+ alias_method :directory, :directory?
95
102
 
96
103
  # Returns +true+ if the entry represents a plain file.
97
104
  def file?
98
- (@typeflag == '0' || @typeflag == "\0") && !@name.end_with?('/')
105
+ (@typeflag == "0" || @typeflag == "\0") && !@name.end_with?("/")
99
106
  end
100
- alias file file?
107
+ alias_method :file, :file?
101
108
 
102
109
  # Returns +true+ if the current read pointer is at the end of the
103
110
  # EntryStream data.
@@ -125,7 +132,7 @@ module Archive::Tar::Minitar
125
132
 
126
133
  # Returns the full and proper name of the entry.
127
134
  def full_name
128
- if @prefix != ''
135
+ if @prefix != ""
129
136
  File.join(@prefix, @name)
130
137
  else
131
138
  @name
@@ -185,7 +192,7 @@ module Archive::Tar::Minitar
185
192
  def self.each_entry(io)
186
193
  return to_enum(__method__, io) unless block_given?
187
194
 
188
- open(io) do |reader|
195
+ Input.open(io) do |reader|
189
196
  reader.each_entry do |entry|
190
197
  yield entry
191
198
  end
@@ -195,7 +202,11 @@ module Archive::Tar::Minitar
195
202
  # Creates and returns a new Reader object.
196
203
  def initialize(io)
197
204
  @io = io
198
- @init_pos = io.pos rescue nil
205
+ @init_pos = begin
206
+ io.pos
207
+ rescue
208
+ nil
209
+ end
199
210
  end
200
211
 
201
212
  # Resets the read pointer to the beginning of data stream. Do not call
@@ -229,14 +240,17 @@ module Archive::Tar::Minitar
229
240
  raise Archive::Tar::Minitar::InvalidTarStream if header.size < 0
230
241
 
231
242
  if header.long_name?
232
- name = @io.read(512).rstrip
243
+ name_block = (header.size / 512.0).ceil * 512
244
+
245
+ name = @io.read(name_block).rstrip
233
246
  header = PosixHeader.from_stream(@io)
247
+
234
248
  return if header.empty?
235
249
  header.name = name
236
250
  end
237
251
 
238
252
  entry = EntryStream.new(header, @io)
239
- size = entry.size
253
+ size = entry.size
240
254
 
241
255
  yield entry
242
256
 
@@ -259,7 +273,7 @@ module Archive::Tar::Minitar
259
273
  entry.close
260
274
  end
261
275
  end
262
- alias each each_entry
276
+ alias_method :each, :each_entry
263
277
 
264
278
  # Returns false if the reader is open (it never closes).
265
279
  def closed?
@@ -30,8 +30,8 @@ module Archive::Tar::Minitar
30
30
  def self.const_missing(c)
31
31
  case c
32
32
  when :FileOverflow
33
- warn 'Writer::BoundedWriteStream::FileOverflow has been renamed ' \
34
- 'to Writer::WriteBoundaryOverflow'
33
+ warn "Writer::BoundedWriteStream::FileOverflow has been renamed " \
34
+ "to Writer::WriteBoundaryOverflow"
35
35
  const_set :FileOverflow,
36
36
  Archive::Tar::Minitar::Writer::WriteBoundaryOverflow
37
37
  else
@@ -46,9 +46,9 @@ module Archive::Tar::Minitar
46
46
  attr_reader :written
47
47
 
48
48
  def initialize(io, limit)
49
- @io = io
50
- @limit = limit
51
- @written = 0
49
+ @io = io
50
+ @limit = limit
51
+ @written = 0
52
52
  end
53
53
 
54
54
  def write(data)
@@ -65,7 +65,7 @@ module Archive::Tar::Minitar
65
65
  def self.const_missing(c)
66
66
  case c
67
67
  when :BoundedStream
68
- warn 'BoundedStream has been renamed to BoundedWriteStream'
68
+ warn "BoundedStream has been renamed to BoundedWriteStream"
69
69
  const_set(:BoundedStream, BoundedWriteStream)
70
70
  else
71
71
  super
@@ -101,7 +101,7 @@ module Archive::Tar::Minitar
101
101
 
102
102
  # Creates and returns a new Writer object.
103
103
  def initialize(io)
104
- @io = io
104
+ @io = io
105
105
  @closed = false
106
106
  end
107
107
 
@@ -139,10 +139,10 @@ module Archive::Tar::Minitar
139
139
  raise ClosedStream if @closed
140
140
 
141
141
  header = {
142
- :mode => opts.fetch(:mode, 0o644),
143
- :mtime => opts.fetch(:mtime, nil),
144
- :gid => opts.fetch(:gid, nil),
145
- :uid => opts.fetch(:uid, nil)
142
+ :mode => opts.fetch(:mode, 0o644),
143
+ :mtime => opts.fetch(:mtime, nil),
144
+ :gid => opts.fetch(:gid, nil),
145
+ :uid => opts.fetch(:uid, nil)
146
146
  }
147
147
 
148
148
  data = opts.fetch(:data, nil)
@@ -151,12 +151,12 @@ module Archive::Tar::Minitar
151
151
  if block_given?
152
152
  if data
153
153
  raise ArgumentError,
154
- 'Too much data (opts[:data] and block_given?).'
154
+ "Too much data (opts[:data] and block_given?)."
155
155
  end
156
156
 
157
- raise ArgumentError, 'No size provided' unless size
157
+ raise ArgumentError, "No size provided" unless size
158
158
  else
159
- raise ArgumentError, 'No data provided' unless data
159
+ raise ArgumentError, "No data provided" unless data
160
160
 
161
161
  bytes = bytesize(data)
162
162
  size = bytes if size.nil? || size < bytes
@@ -164,7 +164,8 @@ module Archive::Tar::Minitar
164
164
 
165
165
  header[:size] = size
166
166
 
167
- write_header(name, header)
167
+ short_name, prefix, needs_long_name = split_name(name)
168
+ write_header(header, name, short_name, prefix, needs_long_name)
168
169
 
169
170
  os = BoundedWriteStream.new(@io, size)
170
171
  if block_given?
@@ -211,12 +212,15 @@ module Archive::Tar::Minitar
211
212
  raise Archive::Tar::Minitar::NonSeekableStream
212
213
  end
213
214
 
215
+ short_name, prefix, needs_long_name = split_name(name)
216
+
217
+ data_offset = needs_long_name ? 3 * 512 : 512
214
218
  init_pos = @io.pos
215
- @io.write("\0" * 512) # placeholder for the header
219
+ @io.write("\0" * data_offset) # placeholder for the header
216
220
 
217
221
  yield WriteOnlyStream.new(@io), opts
218
222
 
219
- size = @io.pos - (init_pos + 512)
223
+ size = @io.pos - (init_pos + data_offset)
220
224
  remainder = (512 - (size % 512)) % 512
221
225
  @io.write("\0" * remainder)
222
226
 
@@ -227,9 +231,11 @@ module Archive::Tar::Minitar
227
231
  :mtime => opts[:mtime],
228
232
  :size => size,
229
233
  :gid => opts[:gid],
230
- :uid => opts[:uid],
234
+ :uid => opts[:uid]
231
235
  }
232
- write_header(name, header)
236
+
237
+ write_header(header, name, short_name, prefix, needs_long_name)
238
+
233
239
  @io.pos = final_pos
234
240
  end
235
241
 
@@ -239,13 +245,38 @@ module Archive::Tar::Minitar
239
245
 
240
246
  header = {
241
247
  :mode => opts[:mode],
242
- :typeflag => '5',
248
+ :typeflag => "5",
249
+ :size => 0,
250
+ :gid => opts[:gid],
251
+ :uid => opts[:uid],
252
+ :mtime => opts[:mtime]
253
+ }
254
+
255
+ short_name, prefix, needs_long_name = split_name(name)
256
+ write_header(header, name, short_name, prefix, needs_long_name)
257
+
258
+ nil
259
+ end
260
+
261
+ # Creates a symbolic link entry in the tar.
262
+ def symlink(name, link_target, opts = {})
263
+ raise ClosedStream if @closed
264
+
265
+ raise FileNameTooLong if link_target.size > 100
266
+
267
+ name, prefix = split_name(name)
268
+ header = {
269
+ :name => name,
270
+ :mode => opts[:mode],
271
+ :typeflag => "2",
243
272
  :size => 0,
273
+ :linkname => link_target,
244
274
  :gid => opts[:gid],
245
275
  :uid => opts[:uid],
246
276
  :mtime => opts[:mtime],
277
+ :prefix => prefix
247
278
  }
248
- write_header(name, header)
279
+ @io.write(PosixHeader.new(header))
249
280
  nil
250
281
  end
251
282
 
@@ -271,47 +302,45 @@ module Archive::Tar::Minitar
271
302
 
272
303
  private
273
304
 
274
- def write_header(long_name, header)
275
- short_name, prefix, needs_long_name = split_name(long_name)
276
-
305
+ def write_header(header, long_name, short_name, prefix, needs_long_name)
277
306
  if needs_long_name
278
307
  long_name_header = {
279
- :prefix => '',
308
+ :prefix => "",
280
309
  :name => PosixHeader::GNU_EXT_LONG_LINK,
281
- :typeflag => 'L',
282
- :size => long_name.length,
283
- :mode => 0,
310
+ :typeflag => "L",
311
+ :size => long_name.length + 1,
312
+ :mode => 0
284
313
  }
285
314
  @io.write(PosixHeader.new(long_name_header))
286
315
  @io.write(long_name)
287
316
  @io.write("\0" * (512 - (long_name.length % 512)))
288
317
  end
289
318
 
290
- new_header = header.merge({ :name => short_name, :prefix => prefix })
319
+ new_header = header.merge({:name => short_name, :prefix => prefix})
291
320
  @io.write(PosixHeader.new(new_header))
292
321
  end
293
322
 
294
323
  def split_name(name)
295
324
  if bytesize(name) <= 100
296
- prefix = ''
325
+ prefix = ""
297
326
  else
298
- parts = name.split(/\//)
327
+ parts = name.split("/")
299
328
  newname = parts.pop
300
329
 
301
- nxt = ''
330
+ nxt = ""
302
331
 
303
332
  loop do
304
- nxt = parts.pop || ''
333
+ nxt = parts.pop || ""
305
334
  break if bytesize(newname) + 1 + bytesize(nxt) >= 100
306
335
  newname = "#{nxt}/#{newname}"
307
336
  end
308
337
 
309
- prefix = (parts + [nxt]).join('/')
338
+ prefix = (parts + [nxt]).join("/")
310
339
 
311
340
  name = newname
312
341
  end
313
342
 
314
- [ name, prefix, (bytesize(name) > 100 || bytesize(prefix) > 155) ]
343
+ [name, prefix, bytesize(name) > 100 || bytesize(prefix) > 155]
315
344
  end
316
345
  end
317
346
  end