class Archive::Tar::Minitar::Writer

The class that writes a tar format archive to a data stream.

Public Class Methods

new(anIO) click to toggle source

Creates and returns a new Writer object.

# File lib/archive/tar/minitar.rb, line 312
def initialize(anIO)
  @io     = anIO
  @closed = false
end
open(anIO) { |writer| ... } click to toggle source

With no associated block, +Writer::open+ is a synonym for +Writer::new+. If the optional code block is given, it will be passed the new writer as an argument and the Writer object will automatically be closed when the block terminates. In this instance, +Writer::open+ returns the value of the block.

# File lib/archive/tar/minitar.rb, line 297
def self.open(anIO)
  writer = Writer.new(anIO)

  return writer unless block_given?

  begin
    res = yield writer
  ensure
    writer.close
  end

  res
end

Public Instance Methods

add_file(name, opts = {}) { |restricted_stream, opts| ... } click to toggle source

Adds a file to the archive as name. opts must contain the following value:

:mode

The Unix file permissions mode value.

opts may contain the following values:

:uid: The Unix file owner user ID number. :gid: The Unix file owner group ID number.

:mtime

The integer modification time value.

The file's size will be determined from the amount of data written to the stream.

For add_file to be used, the Archive::Tar::Minitar::Writer must be wrapping a stream object that is seekable (e.g., it responds to pos=). Otherwise, add_file_simple must be used.

opts may be modified during the writing to the stream.

# File lib/archive/tar/minitar.rb, line 372
def add_file(name, opts = {}) # :yields RestrictedStream, +opts+:
  raise Archive::Tar::Minitar::BlockRequired unless block_given?
  raise Archive::Tar::Minitar::ClosedStream if @closed
  raise Archive::Tar::Minitar::NonSeekableStream unless @io.respond_to?(:pos=)

  name, prefix = split_name(name)
  init_pos = @io.pos
  @io.write("\00"" * 512) # placeholder for the header

  yield RestrictedStream.new(@io), opts
    # FIXME: what if an exception is raised in the block?

  size      = @io.pos - (init_pos + 512)
  remainder = (512 - (size % 512)) % 512
  @io.write("\00"" * remainder)

  final_pos = @io.pos
  @io.pos   = init_pos

  header = { :name => name, :mode => opts[:mode], :mtime => opts[:mtime],
             :size => size, :gid => opts[:gid], :uid => opts[:uid],
             :prefix => prefix }
  header = Archive::Tar::PosixHeader.new(header).to_s
  @io.write(header)
  @io.pos = final_pos
end
add_file_simple(name, opts = {}) { |os| ... } click to toggle source

Adds a file to the archive as name. opts must contain the following values:

:mode

The Unix file permissions mode value.

:size

The size, in bytes.

opts may contain the following values:

:uid: The Unix file owner user ID number. :gid: The Unix file owner group ID number.

:mtime

The integer modification time value.

It will not be possible to add more than opts[:size] bytes to the file.

# File lib/archive/tar/minitar.rb, line 331
def add_file_simple(name, opts = {}) # :yields BoundedStream:
  raise Archive::Tar::Minitar::BlockRequired unless block_given?
  raise Archive::Tar::ClosedStream if @closed

  name, prefix = split_name(name)

  header = { :name => name, :mode => opts[:mode], :mtime => opts[:mtime],
    :size => opts[:size], :gid => opts[:gid], :uid => opts[:uid],
    :prefix => prefix }
  header = Archive::Tar::PosixHeader.new(header).to_s 
  @io.write(header)

  os = BoundedStream.new(@io, opts[:size])
  yield os
    # FIXME: what if an exception is raised in the block?

  min_padding = opts[:size] - os.written
  @io.write("\00"" * min_padding)
  remainder = (512 - (opts[:size] % 512)) % 512
  @io.write("\00"" * remainder)
end
close() click to toggle source

Closes the Writer.

# File lib/archive/tar/minitar.rb, line 419
def close
  return if @closed
  @io.write("\00"" * 1024)
  @closed = true
end
flush() click to toggle source

Passes the flush method to the wrapped stream, used for buffered streams.

# File lib/archive/tar/minitar.rb, line 413
def flush
  raise ClosedStream if @closed
  @io.flush if @io.respond_to?(:flush)
end
mkdir(name, opts = {}) click to toggle source

Creates a directory in the tar.

# File lib/archive/tar/minitar.rb, line 400
def mkdir(name, opts = {})
  raise ClosedStream if @closed
  name, prefix = split_name(name)
  header = { :name => name, :mode => opts[:mode], :typeflag => "5",
             :size => 0, :gid => opts[:gid], :uid => opts[:uid],
             :mtime => opts[:mtime], :prefix => prefix }
  header = Archive::Tar::PosixHeader.new(header).to_s
  @io.write(header)
  nil
end

Private Instance Methods

split_name(name) click to toggle source
# File lib/archive/tar/minitar.rb, line 426
def split_name(name)
  raise FileNameTooLong if name.size > 256
  if name.size <= 100
    prefix = ""
  else
    parts = name.split(/\//)
    newname = parts.pop

    nxt = ""

    loop do
      nxt = parts.pop
      break if newname.size + 1 + nxt.size > 100
      newname = "#{nxt}/#{newname}"
    end

    prefix = (parts + [nxt]).join("/")

    name = newname

    raise FileNameTooLong if name.size > 100 || prefix.size > 155
  end
  return name, prefix
end