From 5bd757a60bd5427af4b9725899fefbb7b4c4bc33 Mon Sep 17 00:00:00 2001 From: Pete Fritchman Date: Tue, 3 Mar 2015 12:11:07 -0500 Subject: [PATCH] Add symlink support, closes #8 --- lib/archive/tar/minitar/writer.rb | 22 ++++++++++++++++++++++ test/minitest_helper.rb | 2 +- test/support/tar_test_helpers.rb | 13 +++++++++---- test/test_tar_writer.rb | 20 +++++++++++++++++--- 4 files changed, 49 insertions(+), 8 deletions(-) diff --git a/lib/archive/tar/minitar/writer.rb b/lib/archive/tar/minitar/writer.rb index 5998628..1486344 100644 --- a/lib/archive/tar/minitar/writer.rb +++ b/lib/archive/tar/minitar/writer.rb @@ -258,6 +258,28 @@ def mkdir(name, opts = {}) nil end + # Creates a symbolic link entry in the tar. + def symlink(name, link_target, opts = {}) + raise ClosedStream if @closed + + raise FileNameTooLong if link_target.size > 100 + + name, prefix = split_name(name) + header = { + :name => name, + :mode => opts[:mode], + :typeflag => "2", + :size => 0, + :linkname => link_target, + :gid => opts[:gid], + :uid => opts[:uid], + :mtime => opts[:mtime], + :prefix => prefix + } + @io.write(PosixHeader.new(header)) + nil + end + # Passes the #flush method to the wrapped stream, used for buffered # streams. def flush diff --git a/test/minitest_helper.rb b/test/minitest_helper.rb index 45d0467..71c853b 100644 --- a/test/minitest_helper.rb +++ b/test/minitest_helper.rb @@ -1,4 +1,4 @@ -# -*- ruby encoding: utf-8 -*- +# frozen_string_literal: true require "fileutils" require "minitar" diff --git a/test/support/tar_test_helpers.rb b/test/support/tar_test_helpers.rb index 261ddc0..e082464 100644 --- a/test/support/tar_test_helpers.rb +++ b/test/support/tar_test_helpers.rb @@ -73,19 +73,24 @@ def tar_dir_header(name, prefix, mode) update_checksum(header("5", name, prefix, 0, mode)) end - def header(type, fname, dname, length, mode) + def tar_symlink_header(name, prefix, mode, target) + update_checksum(header("2", name, prefix, 0, mode, target)) + end + + def header(type, fname, dname, length, mode, link_name = "") raw_header(type, asciiz(fname, 100), asciiz(dname, 155), z(to_oct(length, 11)), - z(to_oct(mode, 7))) + z(to_oct(mode, 7)), + asciiz(link_name, 100)) end - def raw_header(type, fname, dname, length, mode) + def raw_header(type, fname, dname, length, mode, link_name = "") arr = [ fname, mode, z(to_oct(nil, 7)), z(to_oct(nil, 7)), length, z(to_oct(0, 11)), BLANK_CHECKSUM, type, - NULL_100, USTAR, DOUBLE_ZERO, asciiz("", 32), asciiz("", 32), + asciiz(link_name, 100), USTAR, DOUBLE_ZERO, asciiz("", 32), asciiz("", 32), z(to_oct(nil, 7)), z(to_oct(nil, 7)), dname ] diff --git a/test/test_tar_writer.rb b/test/test_tar_writer.rb index 0ed2d73..abc9c75 100644 --- a/test/test_tar_writer.rb +++ b/test/test_tar_writer.rb @@ -73,10 +73,9 @@ def test_write_operations_fail_after_closed @os.add_file_simple("sadd", :mode => 0o644, :size => 20) { |f| } @os.close assert_raises(Minitar::ClosedStream) { @os.flush } - assert_raises(Minitar::ClosedStream) { - @os.add_file("dfdsf", :mode => 0o644) {} - } + assert_raises(Minitar::ClosedStream) { @os.add_file("dfdsf", :mode => 0o644) {} } assert_raises(Minitar::ClosedStream) { @os.mkdir "sdfdsf", :mode => 0o644 } + assert_raises(Minitar::ClosedStream) { @os.symlink "a", "b", :mode => 0o644 } end def test_file_name_is_split_correctly @@ -261,4 +260,19 @@ def test_file_size_is_checked end @os.add_file_simple("lib/foo/bar", :mode => 0o644, :size => 10) { |f| } end + + def test_symlink + @dummyos.reset + @os.symlink("lib/foo/bar", "lib/foo/baz", :mode => 0o644) + @os.flush + assert_headers_equal(tar_dir_header("lib/foo", "", 0o644), + @dummyos.data[0, 512]) + end + + def test_symlink_target_size_is_checked + @dummyos.reset + assert_raises(Minitar::FileNameTooLong) do + @os.symlink("lib/foo/bar", "x" * 101) + end + end end