Archive::Tar::Minitar

Archive::Tar::Minitar 0.5.2

Archive::Tar::Minitar is a pure-Ruby library and command-line utility that provides the ability to deal with POSIX tar(1) archive files. The implementation is based heavily on Mauricio Ferna’ndez’s implementation in rpa-base, but has been reorganised to promote reuse in other projects.

This tar class performs a subset of all tar (POSIX tape archive) operations. We can only deal with typeflags 0, 1, 2, and 5 (see Archive::Tar::PosixHeader). All other typeflags will be treated as normal files.

NOTE:

support for typeflags 1 and 2 is not yet implemented in this version.

This release is version 0.5.2. The library can only handle files and directories at this point. A future version will be expanded to handle symbolic links and hard links in a portable manner. The command line utility, minitar, can only create archives, extract from archives, and list archive contents.

Synopsis

Using this library is easy. The simplest case is:

  require 'zlib'
  require 'archive/tar/minitar'
  include Archive::Tar

    # Packs everything that matches Find.find('tests')
  File.open('test.tar', 'wb') { |tar| Minitar.pack('tests', tar) }
    # Unpacks 'test.tar' to 'x', creating 'x' if necessary.
  Minitar.unpack('test.tar', 'x')

A gzipped tar can be written with:

  tgz = Zlib::GzipWriter.new(File.open('test.tgz', 'wb'))
    # Warning: tgz will be closed!
  Minitar.pack('tests', tgz)

  tgz = Zlib::GzipReader.new(File.open('test.tgz', 'rb'))
    # Warning: tgz will be closed!
  Minitar.unpack(tgz, 'x')

As the case above shows, one need not write to a file. However, it will sometimes require that one dive a little deeper into the API, as in the case of StringIO objects. Note that I’m not providing a block with Minitar::Output, as Minitar::Output#close automatically closes both the Output object and the wrapped data stream object.

  begin
    sgz = Zlib::GzipWriter.new(StringIO.new(""))
    tar = Output.new(sgz)
    Find.find('tests') do |entry|
      Minitar.pack_file(entry, tar)
    end
  ensure
      # Closes both tar and sgz.
    tar.close
  end

Copyright

Copyright 2004 Mauricio Julio Ferna’ndez Pradier and Austin Ziegler

This program is based on and incorporates parts of RPA::Package from rpa-base (lib/rpa/package.rb and lib/rpa/util.rb) by Mauricio and has been adapted to be more generic by Austin.

‘minitar’ contains an adaptation of Ruby/ProgressBar by Satoru Takabayashi , copyright 2001 - 2004.

This program is free software. It may be redistributed and/or modified under the terms of the GPL version 2 (or later) or Ruby’s licence.

Constants

VERSION

Public Class Methods

dir?(path) click to toggle source

Tests if path refers to a directory. Fixes an apparently corrupted stat() call on Windows.

     # File lib/archive/tar/minitar.rb, line 832
832:     def dir?(path)
833:       File.directory?((path[1] == //) ? path : "#{path}/")
834:     end
open(dest, mode = "r", &block) click to toggle source

A convenience method for wrapping Archive::Tar::Minitar::Input.open (mode r) and Archive::Tar::Minitar::Output.open (mode w). No other modes are currently supported.

     # File lib/archive/tar/minitar.rb, line 839
839:     def open(dest, mode = "r", &block)
840:       case mode
841:       when "r"
842:         Input.open(dest, &block)
843:       when "w"
844:         Output.open(dest, &block)
845:       else
846:         raise "Unknown open mode for Archive::Tar::Minitar.open."
847:       end
848:     end
pack(src, dest, recurse_dirs = true, &block) click to toggle source

A convenience method to pack files specified by src into dest. If src is an Array, then each file detailed therein will be packed into the resulting Archive::Tar::Minitar::Output stream; if recurse_dirs is true, then directories will be recursed.

If src is an Array, it will be treated as the argument to Find.find; all files matching will be packed.

     # File lib/archive/tar/minitar.rb, line 941
941:     def pack(src, dest, recurse_dirs = true, &block)
942:       Output.open(dest) do |outp|
943:         if src.kind_of?(Array)
944:           src.each do |entry|
945:             pack_file(entry, outp, &block)
946:             if dir?(entry) and recurse_dirs
947:               Dir["#{entry}/**/**"].each do |ee|
948:                 pack_file(ee, outp, &block)
949:               end
950:             end
951:           end
952:         else
953:           Find.find(src) do |entry|
954:             pack_file(entry, outp, &block)
955:           end
956:         end
957:       end
958:     end
pack_file(entry, outputter) click to toggle source

A convenience method to packs the file provided. entry may either be a filename (in which case various values for the file (see below) will be obtained from File#stat(entry) or a Hash with the fields:

:name

The filename to be packed into the tarchive. REQUIRED.

:mode

The mode to be applied.

:uid

The user owner of the file. (Ignored on Windows.)

:gid

The group owner of the file. (Ignored on Windows.)

:mtime

The modification Time of the file.

During packing, if a block is provided, # yields an action Symol, the full name of the file being packed, and a Hash of statistical information, just as with Archive::Tar::Minitar::Input#extract_entry.

The action will be one of:

:dir

The entry is a directory.

:file_start

The entry is a file; the extract of the file is just beginning.

:file_progress

Yielded every 4096 bytes during the extract of the entry.

:file_done

Yielded when the entry is completed.

The stats hash contains the following keys:

:current

The current total number of bytes read in the entry.

:currinc

The current number of bytes read in this read cycle.

:name

The filename to be packed into the tarchive. REQUIRED.

:mode

The mode to be applied.

:uid

The user owner of the file. (nil on Windows.)

:gid

The group owner of the file. (nil on Windows.)

:mtime

The modification Time of the file.

     # File lib/archive/tar/minitar.rb, line 885
885:     def pack_file(entry, outputter) #:yields action, name, stats:
886:       outputter = outputter.tar if outputter.kind_of?(Archive::Tar::Minitar::Output)
887: 
888:       stats = {}
889: 
890:       if entry.kind_of?(Hash)
891:         name = entry[:name]
892: 
893:         entry.each { |kk, vv| stats[kk] = vv unless vv.nil? }
894:       else
895:         name = entry
896:       end
897:       
898:       name = name.sub(%{\./}, '')
899:       stat = File.stat(name)
900:       stats[:mode]   ||= stat.mode
901:       stats[:mtime]  ||= stat.mtime
902:       stats[:size]   = stat.size
903: 
904:       if RUBY_PLATFORM =~ /win32/
905:         stats[:uid]  = nil
906:         stats[:gid]  = nil
907:       else
908:         stats[:uid]  ||= stat.uid
909:         stats[:gid]  ||= stat.gid
910:       end
911: 
912:       case
913:       when File.file?(name)
914:         outputter.add_file_simple(name, stats) do |os|
915:           stats[:current] = 0
916:           yield :file_start, name, stats if block_given?
917:           File.open(name, "rb") do |ff|
918:             until ff.eof?
919:               stats[:currinc] = os.write(ff.read(4096))
920:               stats[:current] += stats[:currinc]
921:               yield :file_progress, name, stats if block_given?
922:             end
923:           end
924:           yield :file_done, name, stats if block_given?
925:         end
926:       when dir?(name)
927:         yield :dir, name, stats if block_given?
928:         outputter.mkdir(name, stats)
929:       else
930:         raise "Don't yet know how to pack this type of file."
931:       end
932:     end
unpack(src, dest, files = [], &block) click to toggle source

A convenience method to unpack files from src into the directory specified by dest. Only those files named explicitly in files will be extracted.

     # File lib/archive/tar/minitar.rb, line 963
963:     def unpack(src, dest, files = [], &block)
964:       Input.open(src) do |inp|
965:         if File.exist?(dest) and (not dir?(dest))
966:           raise "Can't unpack to a non-directory."
967:         elsif not File.exist?(dest)
968:           FileUtils.mkdir_p(dest)
969:         end
970: 
971:         inp.each do |entry|
972:           if files.empty? or files.include?(entry.full_name)
973:             inp.extract_entry(dest, entry, &block)
974:           end
975:         end
976:       end
977:     end

Disabled; run with --debug to generate this.

[Validate]

Generated with the Darkfish Rdoc Generator 1.1.6.