Class: Omnizip::Formats::Rar::Writer

Inherits:
Object
  • Object
show all
Includes:
Constants
Defined in:
lib/omnizip/formats/rar/writer.rb

Overview

Pure Ruby RAR archive writer

Writes RAR 1.5-4.x ("RAR4") archives per the on-disk layout unrar accepts: HEAD_CRC holds the low 16 bits of a CRC32 over the header bytes that follow it, HEAD_SIZE counts the whole block including the CRC field, and the 7-byte signature is itself the marker block (no second marker follows).

Only METHOD_STORE output is interoperable with official RAR tools; the LZ/PPMd encoders produce Omnizip-internal streams that Omnizip can read back but unrar cannot.

Examples:

Create a RAR archive

writer = Writer.new('archive.rar')
writer.add_file('document.pdf')
writer.add_directory('photos/')
writer.write

Create with options

writer = Writer.new('archive.rar',
  compression: :best
)

Constant Summary

Constants included from Constants

Constants::ARCHIVE_AUTH_INFO, Constants::ARCHIVE_COMMENT, Constants::ARCHIVE_ENCRYPTED, Constants::ARCHIVE_FIRST_VOLUME, Constants::ARCHIVE_LOCKED, Constants::ARCHIVE_NEW_NAMING, Constants::ARCHIVE_RECOVERY, Constants::ARCHIVE_SOLID, Constants::ARCHIVE_VOLUME, Constants::BLOCK_ARCHIVE, Constants::BLOCK_COMMENT, Constants::BLOCK_ENDARC, Constants::BLOCK_FILE, Constants::BLOCK_LONG, Constants::BLOCK_MARKER, Constants::BLOCK_OLD_AUTH, Constants::BLOCK_OLD_EXTRA, Constants::BLOCK_OLD_RECOVERY, Constants::BLOCK_OLD_SUBBLOCK, Constants::BLOCK_SUBBLOCK, Constants::FILE_COMMENT, Constants::FILE_DIRECTORY, Constants::FILE_ENCRYPTED, Constants::FILE_EXT_TIME, Constants::FILE_LARGE, Constants::FILE_SALT, Constants::FILE_SOLID, Constants::FILE_SPLIT_AFTER, Constants::FILE_SPLIT_BEFORE, Constants::FILE_UNICODE, Constants::FILE_VERSION, Constants::METHOD_BEST, Constants::METHOD_FAST, Constants::METHOD_FASTEST, Constants::METHOD_GOOD, Constants::METHOD_NORMAL, Constants::METHOD_STORE, Constants::OS_BEOS, Constants::OS_MACOS, Constants::OS_MSDOS, Constants::OS_OS2, Constants::OS_UNIX, Constants::OS_WIN32, Constants::RAR4_SIGNATURE, Constants::RAR5_FLAG_CHILD_BLOCKS, Constants::RAR5_FLAG_DATA_AREA, Constants::RAR5_FLAG_DATA_INHERITED, Constants::RAR5_FLAG_EXTRA_AREA, Constants::RAR5_FLAG_IS_DIR, Constants::RAR5_FLAG_MULTI_VOLUME, Constants::RAR5_FLAG_UNKNOWN_BLOCKS, Constants::RAR5_HEADER_ENCRYPTION, Constants::RAR5_HEADER_END, Constants::RAR5_HEADER_FILE, Constants::RAR5_HEADER_MAIN, Constants::RAR5_HEADER_SERVICE, Constants::RAR5_SIGNATURE

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(output_path, options = {}) ⇒ Writer

Initialize RAR writer

Parameters:

  • output_path (String)

    Output RAR file path

  • options (Hash) (defaults to: {})

    Compression options

Options Hash (options):

  • :compression (Symbol)

    Compression level (:store, :fastest, :fast, :normal, :good, :best)

  • :solid (Boolean)

    Create solid archive (not implemented; ignored with a warning)

  • :recovery (Integer)

    Recovery record percentage (not implemented; ignored with a warning)

  • :password (String)

    Archive password (RAR4 encryption is not implemented)

  • :volume_size (Integer)

    Split into volumes (not implemented; ignored with a warning)

  • :test_after_create (Boolean)

    Test archive after creation

Raises:

  • (NotImplementedError)

    if :password or :encrypt_headers is given



82
83
84
85
86
87
88
89
90
91
92
93
94
# File 'lib/omnizip/formats/rar/writer.rb', line 82

def initialize(output_path, options = {})
  @output_path = output_path
  @options = default_options.merge(options)
  @files = []
  @directories = []

  if @options[:password] || @options[:encrypt_headers]
    raise NotImplementedError,
          "RAR4 encryption is not implemented"
  end

  warn_unimplemented_options
end

Instance Attribute Details

#directoriesArray<Hash> (readonly)

Returns Directories to add.

Returns:

  • (Array<Hash>)

    Directories to add



46
47
48
# File 'lib/omnizip/formats/rar/writer.rb', line 46

def directories
  @directories
end

#filesArray<Hash> (readonly)

Returns Files to add.

Returns:

  • (Array<Hash>)

    Files to add



43
44
45
# File 'lib/omnizip/formats/rar/writer.rb', line 43

def files
  @files
end

#optionsHash (readonly)

Returns Compression options.

Returns:

  • (Hash)

    Compression options



40
41
42
# File 'lib/omnizip/formats/rar/writer.rb', line 40

def options
  @options
end

#output_pathString (readonly)

Returns Output archive path.

Returns:

  • (String)

    Output archive path



37
38
39
# File 'lib/omnizip/formats/rar/writer.rb', line 37

def output_path
  @output_path
end

Class Method Details

.available?Boolean

Check if RAR creation is available

Returns:

  • (Boolean)

    always true for pure Ruby implementation



51
52
53
# File 'lib/omnizip/formats/rar/writer.rb', line 51

def self.available?
  true
end

.infoHash

Get RAR writer information

Returns:

  • (Hash)

    Writer type and version



58
59
60
61
62
63
64
# File 'lib/omnizip/formats/rar/writer.rb', line 58

def self.info
  {
    available: true,
    type: :pure_ruby,
    version: "4.0",
  }
end

Instance Method Details

#add_directory(dir_path, recursive: true, archive_path: nil) ⇒ Object

Add directory to archive

Parameters:

  • dir_path (String)

    Path to directory

  • recursive (Boolean) (defaults to: true)

    Include subdirectories

  • archive_path (String, nil) (defaults to: nil)

    Path within archive

Raises:

  • (ArgumentError)

    if directory does not exist



117
118
119
120
121
122
123
124
125
126
# File 'lib/omnizip/formats/rar/writer.rb', line 117

def add_directory(dir_path, recursive: true, archive_path: nil)
  raise ArgumentError, "Directory not found: #{dir_path}" unless
    Dir.exist?(dir_path)

  @directories << {
    source: File.expand_path(dir_path),
    recursive: recursive,
    archive_path: archive_path,
  }
end

#add_file(file_path, archive_path = nil) ⇒ Object

Add file to archive

Parameters:

  • file_path (String)

    Path to file

  • archive_path (String, nil) (defaults to: nil)

    Path within archive

Raises:

  • (ArgumentError)

    if file does not exist



101
102
103
104
105
106
107
108
109
# File 'lib/omnizip/formats/rar/writer.rb', line 101

def add_file(file_path, archive_path = nil)
  raise ArgumentError, "File not found: #{file_path}" unless
    File.exist?(file_path)

  @files << {
    source: File.expand_path(file_path),
    archive_path: archive_path,
  }
end

#writeString

Create RAR archive

Returns:

  • (String)

    Path to created archive



131
132
133
134
135
136
137
138
139
140
141
142
# File 'lib/omnizip/formats/rar/writer.rb', line 131

def write
  File.open(@output_path, "wb") do |io|
    write_signature(io)
    write_archive_header(io)
    write_file_entries(io)
    write_end_block(io)
  end

  test_archive if @options[:test_after_create]

  @output_path
end