<commit_before>#
# Test tpkg's ability to unpack packages
#

require "./#{File.dirname(__FILE__)}/tpkgtest"
require 'find'

# Give ourself access to some Tpkg variables
class Tpkg
  attr_reader :metadata_directory
end

class TpkgUnpackTests < Test::Unit::TestCase
  include TpkgTests
  
  def setup
    Tpkg::set_prompt(false)
    
    # temp dir that will automatically get deleted at end of test run, can be
    # used for storing packages
    @tempoutdir = Dir.mktmpdir('tempoutdir')
    # Make up a package with both relocatable and non-relocatable
    # directory trees so that we can ensure both types are unpacked
    # properly.
    Dir.mktmpdir('srcdir') do |srcdir|
      # The stock test package has a reloc directory we can use
      system("#{Tpkg::find_tar} -C #{TESTPKGDIR} --exclude .svn -cf - . | #{Tpkg::find_tar} -C #{srcdir} -xf -")
      # Then add a root directory
      FileUtils.mkdir_p(File.join(srcdir, 'root', 'etc'))
      File.open(File.join(srcdir, 'root', 'etc', 'rootfile'), 'w') do |file|
        file.puts "Hello"
      end
      @pkgfile = make_package(:output_directory => @tempoutdir, :source_directory => srcdir, :files => {'/etc/rootfile' => {'perms' => '0666'}}, :remove => ['posix_acl', 'windows_acl'])
    end
  end
  
  def test_unpack
    Dir.mktmpdir('testroot') do |testroot|
      FileUtils.mkdir_p(File.join(testroot, 'home', 'tpkg'))
      tpkg = Tpkg.new(:file_system_root => testroot, :base => File.join('home', 'tpkg'), :sources => [@pkgfile])
      assert_nothing_raised { tpkg.unpack(@pkgfile, :passphrase => <PASSWORD>) }
      # This file should have the default 0444 perms
      assert(File.exist?(File.join(testroot, 'home', 'tpkg', 'file')))
      assert_equal(0444, File.stat(File.join(testroot, 'home', 'tpkg', 'file')).mode & 07777)
      # This file should have the 0400 perms specified specifically for it in the stock test tpkg.xml
      assert(File.exist?(File.join(testroot, 'home', 'tpkg', 'encfile')))
      assert_equal(0400, File.stat(File.join(testroot, 'home', 'tpkg', 'encfile')).mode & 07777)
      assert_equal(IO.read(File.join(TESTPKGDIR, 'reloc', 'encfile')), IO.read(File.join(testroot, 'home', 'tpkg', 'encfile')))
      # This file should have the 0666 perms we specified above
      assert(File.exist?(File.join(testroot, 'etc', 'rootfile')))
      assert_equal(0666, File.stat(File.join(testroot, 'etc', 'rootfile')).mode & 07777)
    end
      
    # Change the package base and unpack
    Dir.mktmpdir('testroot2') do |testroot2|
      tpkg2 = Tpkg.new(:file_system_root => testroot2, :base => File.join('home', 'tpkg'), :sources => [@pkgfile])
      assert_nothing_raised { tpkg2.unpack(@pkgfile, :passphrase => <PASSWORD>) }
      # Check that the files from the package ended up in the right place
      assert(File.exist?(File.join(testroot2, 'home', 'tpkg', 'file')))
    end
    
    # Pass a nil passphrase to unpack and verify that it installs the
    # package, skipping the unencrypted files
    Dir.mktmpdir('testroot') do |testroot|
      tpkg = Tpkg.new(:file_system_root => testroot, :base => File.join('home', 'tpkg'), :sources => [@pkgfile])
      assert_nothing_raised { tpkg.unpack(@pkgfile) }
      # Check that the files from the package ended up in the right place
      assert(File.exist?(File.join(testroot, 'home', 'tpkg', 'file')))
      assert(!File.exist?(File.join(testroot, 'home', 'tpkg', 'encfile')))
    end
    
    # Test permissions with no default permissions specified in tpkg.xml
    # The stock test package has default permissions specified, so start
    # with the -nofiles template which doesn't have default permissions.
    pkg = nil
    Dir.mktmpdir('srcdir') do |srcdir|
      FileUtils.cp(File.join(TESTPKGDIR, 'tpkg-nofiles.xml'), File.join(srcdir, 'tpkg.xml'))
      FileUtils.mkdir_p(File.join(srcdir, 'reloc', 'etc'))
      # Set non-standard permissions on the directory so that we can
      # ensure that the default permissions are applied by tpkg
      File.chmod(0775, File.join(srcdir, 'reloc', 'etc'))
      File.open(File.join(srcdir, 'reloc', 'etc', '666file'), 'w') do |file|
        file.puts "Hello"
      end
      File.open(File.join(srcdir, 'reloc', 'etc', '400file'), 'w') do |file|
        file.puts "Hello"
      end
      File.open(File.join(srcdir, 'reloc', 'etc', 'nopermsfile'), 'w') do |file|
        file.puts "Hello"
      end
      # Set some crazy perms on this file so that we can be sure they
      # are preserved (there are no default permissions for files)
      File.chmod(0666, File.join(srcdir, 'reloc', 'etc', 'nopermsfile'))
      pkg = make_package(:change => { 'name' => 'a' }, :output_directory => @tempoutdir, :source_directory => srcdir, :files => {'etc/666file' => {'perms' => '0666'}, 'etc/400file' => {'perms' => '0400'}}, :remove => ['posix_acl', 'windows_acl'])
    end
    Dir.mktmpdir('testroot') do |testroot|
      tpkg = Tpkg.new(:file_system_root => testroot, :base => File.join('home', 'tpkg'), :sources => [pkg])
      # Standard umask settings are likely to be the same as the default
      # permissions, which would mask failure here.  Set an extreme umask
      # so that we know tpkg is enforcing the desired permissions.
      oldumask = File.umask
      File.umask(0)
      assert_nothing_raised { tpkg.unpack(pkg) }
      File.umask(oldumask)
      # This file should have the 0666 perms we specified above
      assert_equal(0666, File.stat(File.join(testroot, 'home', 'tpkg', 'etc', '666file')).mode & 07777)
      # This file should have the default 0400 perms we specified above
      assert_equal(0400, File.stat(File.join(testroot, 'home', 'tpkg', 'etc', '400file')).mode & 07777)
      # This file should have the 0666 perms we set on the file itself
      assert_equal(0666, File.stat(File.join(testroot, 'home', 'tpkg', 'etc', 'nopermsfile')).mode & 07777)
      # This directory should have the default 0755 tpkg directory perms
      assert_equal(0755, File.stat(File.join(testroot, 'home', 'tpkg', 'etc')).mode & 07777)
    end
    FileUtils.rm_f(pkg)

    # Test perms for default directory setting
    pkg = nil
    Dir.mktmpdir('srcdir') do |srcdir|
      FileUtils.cp(File.join(TESTPKGDIR, 'tpkg-dir-default.xml'), File.join(srcdir, 'tpkg.xml'))
      FileUtils.mkdir_p(File.join(srcdir, 'reloc'))
      FileUtils.mkdir_p(File.join(srcdir, 'reloc', 'dir1'))
      FileUtils.mkdir_p(File.join(srcdir, 'reloc', 'dir1', 'subdir1'))
      pkg = make_package(:output_directory => @tempoutdir, :change => { 'name' => 'dir_default' }, :source_directory => srcdir, :remove => ['operatingsystem', 'architecture', 'posix_acl', 'windows_acl'])
    end
   
    Dir.mktmpdir('testroot') do |testroot|
      testbase = File.join(testroot, 'home', 'tpkg')
      FileUtils.mkdir_p(testbase)
      tpkg = Tpkg.new(:file_system_root => testroot, :base => File.join('home', 'tpkg'), :sources => [pkg])
      # Standard umask settings are likely to be the same as the default
      # permissions, which would mask failure here.  Set an extreme umask
      # so that we know tpkg is enforcing the desired permissions.
      oldumask = File.umask
      File.umask(0)
      assert_nothing_raised { tpkg.unpack(pkg) }
      File.umask(oldumask)
      # This dir should have the 0555 perms we specified in the tpkg-dir-default.xml file
      assert_equal(0555, File.stat(File.join(testbase, 'dir1')).mode & 07777)
      assert_equal(0555, File.stat(File.join(testbase, 'dir1', 'subdir1')).mode & 07777)
      # The mktmpdir cleanup process doesn't seem to like cleaning up
      # non-writeable directories
      Find.find(testroot) do |f|
        File.chmod(0700, f) if File.directory?(f)
      end
    end
    FileUtils.rm_f(pkg)
    
    # Test that applying default permissions works in the face of symlinks in
    # the package
    pkg = nil
    Dir.mktmpdir('srcdir') do |srcdir|
      FileUtils.cp(File.join(TESTPKGDIR, 'tpkg-nofiles.xml'), File.join(srcdir, 'tpkg.xml'))
      FileUtils.mkdir_p(File.join(srcdir, 'reloc'))
      # Broken link to ensure that nothing attempts to traverse the link and
      # fails as a result
      File.symlink('/path/to/nowhere', File.join(srcdir, 'reloc', 'brokenlink'))
      FileUtils.mkdir_p(File.join(srcdir, 'reloc', 'dir'))
      File.symlink(File.join(srcdir, 'reloc', 'dir'), File.join(srcdir, 'reloc', 'dirlink'))
      File.open(File.join(srcdir, 'reloc', 'file'), 'w') do |file|
        file.puts 'Hello'
      end
      File.chmod(0777, File.join(srcdir, 'reloc', 'file'))
      File.symlink(File.join(srcdir, 'reloc', 'file'), File.join(srcdir, 'reloc', 'filelink'))
      pkg = make_package(:output_directory => @tempoutdir, :change => { 'name' => 'unpacklinks' }, :source_directory => srcdir, :remove => ['operatingsystem', 'architecture', 'posix_acl', 'windows_acl'])
    end
    Dir.mktmpdir('testroot') do |testroot|
      testbase = File.join(testroot, 'home', 'tpkg')
      FileUtils.mkdir_p(testbase)
      tpkg = Tpkg.new(:file_system_root => testroot, :base => File.join('home', 'tpkg'), :sources => [pkg])
      assert_nothing_raised { tpkg.unpack(pkg) }
      assert_equal(0777, File.stat(File.join(testbase, 'file')).mode & 07777)
      assert_equal(Tpkg::DEFAULT_DIR_PERMS, File.stat(File.join(testbase, 'dir')).mode & 07777)
    end
    FileUtils.rm_f(pkg)
    
    # Test that symlinks are not followed when applying permissions to
    # specific files
    pkg = nil
    Dir.mktmpdir('srcdir') do |srcdir|
      FileUtils.cp(File.join(TESTPKGDIR, 'tpkg-nofiles.xml'), File.join(srcdir, 'tpkg.xml'))
      FileUtils.mkdir_p(File.join(srcdir, 'reloc'))
      FileUtils.mkdir_p(File.join(srcdir, 'reloc', 'dir'))
      File.symlink(File.join(srcdir, 'reloc', 'dir'), File.join(srcdir, 'reloc', 'dirlink'))
      File.open(File.join(srcdir, 'reloc', 'file'), 'w') do |file|
        file.puts 'Hello'
      end
      File.chmod(0400, File.join(srcdir, 'reloc', 'file'))
      File.symlink(File.join(srcdir, 'reloc', 'file'), File.join(srcdir, 'reloc', 'filelink'))
      pkg = make_package(:change => { 'name' => 'unpacklinkperms' }, :files => {'dirlink' => {'perms' => '0777'}, 'filelink' => {'perms' => '0666'}}, :source_directory => srcdir, :output_directory => @tempoutdir, :remove => ['operatingsystem', 'architecture', 'posix_acl', 'windows_acl'])
    end
    Dir.mktmpdir('testroot') do |testroot|
      testbase = File.join(testroot, 'home', 'tpkg')
      FileUtils.mkdir_p(testbase)
      tpkg = Tpkg.new(:file_system_root => testroot, :base => File.join('home', 'tpkg'), :sources => [pkg])
      assert_nothing_raised { tpkg.unpack(pkg) }
      assert_equal(Tpkg::DEFAULT_DIR_PERMS, File.stat(File.join(testbase, 'dir')).mode & 07777)
      assert_equal(0400, File.stat(File.join(testbase, 'file')).mode & 07777)
    end
    FileUtils.rm_f(pkg)
    
    # Test that preinstall/postinstall are run at the right points
    #   Make up a package with scripts that create files so we can check timestamps
    # Also, test that tpkg will chdir to package unpack directory before
    # calling pre/post/install/remove scripts<commit_msg>Add tests for file_defaults in package metadata.<commit_after>#
# Test tpkg's ability to unpack packages
#

require "./#{File.dirname(__FILE__)}/tpkgtest"
require 'find'

# Give ourself access to some Tpkg variables
class Tpkg
  attr_reader :metadata_directory
end

class TpkgUnpackTests < Test::Unit::TestCase
  include TpkgTests
  
  def setup
    Tpkg::set_prompt(false)
    
    # temp dir that will automatically get deleted at end of test run, can be
    # used for storing packages
    @tempoutdir = Dir.mktmpdir('tempoutdir')
    # Make up a package with both relocatable and non-relocatable
    # directory trees so that we can ensure both types are unpacked
    # properly.
    Dir.mktmpdir('srcdir') do |srcdir|
      # The stock test package has a reloc directory we can use
      system("#{Tpkg::find_tar} -C #{TESTPKGDIR} --exclude .svn -cf - . | #{Tpkg::find_tar} -C #{srcdir} -xf -")
      # Then add a root directory
      FileUtils.mkdir_p(File.join(srcdir, 'root', 'etc'))
      File.open(File.join(srcdir, 'root', 'etc', 'rootfile'), 'w') do |file|
        file.puts "Hello"
      end
      @pkgfile = make_package(:output_directory => @tempoutdir, :source_directory => srcdir, :files => {'/etc/rootfile' => {'perms' => '0666'}}, :remove => ['posix_acl', 'windows_acl'])
    end
  end
  
  def test_unpack
    Dir.mktmpdir('testroot') do |testroot|
      FileUtils.mkdir_p(File.join(testroot, 'home', 'tpkg'))
      tpkg = Tpkg.new(:file_system_root => testroot, :base => File.join('home', 'tpkg'), :sources => [@pkgfile])
      assert_nothing_raised { tpkg.unpack(@pkgfile, :passphrase => PASSPHRASE) }
      # This file should have the default 0444 perms
      assert(File.exist?(File.join(testroot, 'home', 'tpkg', 'file')))
      assert_equal(0444, File.stat(File.join(testroot, 'home', 'tpkg', 'file')).mode & 07777)
      # This file should have the 0400 perms specified specifically for it in the stock test tpkg.xml
      assert(File.exist?(File.join(testroot, 'home', 'tpkg', 'encfile')))
      assert_equal(0400, File.stat(File.join(testroot, 'home', 'tpkg', 'encfile')).mode & 07777)
      assert_equal(IO.read(File.join(TESTPKGDIR, 'reloc', 'encfile')), IO.read(File.join(testroot, 'home', 'tpkg', 'encfile')))
      # This file should have the 0666 perms we specified above
      assert(File.exist?(File.join(testroot, 'etc', 'rootfile')))
      assert_equal(0666, File.stat(File.join(testroot, 'etc', 'rootfile')).mode & 07777)
    end
      
    # Change the package base and unpack
    Dir.mktmpdir('testroot2') do |testroot2|
      tpkg2 = Tpkg.new(:file_system_root => testroot2, :base => File.join('home', 'tpkg'), :sources => [@pkgfile])
      assert_nothing_raised { tpkg2.unpack(@pkgfile, :passphrase => <PASSWORD>) }
      # Check that the files from the package ended up in the right place
      assert(File.exist?(File.join(testroot2, 'home', 'tpkg', 'file')))
    end
    
    # Pass a nil passphrase to unpack and verify that it installs the
    # package, skipping the unencrypted files
    Dir.mktmpdir('testroot') do |testroot|
      tpkg = Tpkg.new(:file_system_root => testroot, :base => File.join('home', 'tpkg'), :sources => [@pkgfile])
      assert_nothing_raised { tpkg.unpack(@pkgfile) }
      # Check that the files from the package ended up in the right place
      assert(File.exist?(File.join(testroot, 'home', 'tpkg', 'file')))
      assert(!File.exist?(File.join(testroot, 'home', 'tpkg', 'encfile')))
    end
    
    # Test permissions with no default permissions specified in tpkg.xml
    # The stock test package has default permissions specified, so start
    # with the -nofiles template which doesn't have default permissions.
    pkg = nil
    Dir.mktmpdir('srcdir') do |srcdir|
      FileUtils.cp(File.join(TESTPKGDIR, 'tpkg-nofiles.xml'), File.join(srcdir, 'tpkg.xml'))
      FileUtils.mkdir_p(File.join(srcdir, 'reloc', 'etc'))
      # Set non-standard permissions on the directory so that we can
      # ensure that the default permissions are applied by tpkg
      File.chmod(0775, File.join(srcdir, 'reloc', 'etc'))
      File.open(File.join(srcdir, 'reloc', 'etc', '666file'), 'w') do |file|
        file.puts "Hello"
      end
      File.open(File.join(srcdir, 'reloc', 'etc', '400file'), 'w') do |file|
        file.puts "Hello"
      end
      File.open(File.join(srcdir, 'reloc', 'etc', 'nopermsfile'), 'w') do |file|
        file.puts "Hello"
      end
      # Set some crazy perms on this file so that we can be sure they
      # are preserved (there are no default permissions for files)
      File.chmod(0666, File.join(srcdir, 'reloc', 'etc', 'nopermsfile'))
      pkg = make_package(:change => { 'name' => 'no-default-perms' }, :output_directory => @tempoutdir, :source_directory => srcdir, :files => {'etc/666file' => {'perms' => '0666'}, 'etc/400file' => {'perms' => '0400'}}, :remove => ['posix_acl', 'windows_acl'])
    end
    Dir.mktmpdir('testroot') do |testroot|
      tpkg = Tpkg.new(:file_system_root => testroot, :base => File.join('home', 'tpkg'), :sources => [pkg])
      # Standard umask settings might be the same as the default permissions,
      # which would mask failure here.  Set an extreme umask so that we know
      # tpkg is enforcing the desired permissions.
      oldumask = File.umask
      File.umask(0)
      assert_nothing_raised { tpkg.unpack(pkg) }
      File.umask(oldumask)
      # This file should have the 0666 perms we specified above
      assert_equal(0666, File.stat(File.join(testroot, 'home', 'tpkg', 'etc', '666file')).mode & 07777)
      # This file should have the default 0400 perms we specified above
      assert_equal(0400, File.stat(File.join(testroot, 'home', 'tpkg', 'etc', '400file')).mode & 07777)
      # This file should have the 0666 perms we set on the file itself
      assert_equal(0666, File.stat(File.join(testroot, 'home', 'tpkg', 'etc', 'nopermsfile')).mode & 07777)
      # This directory should have the default 0755 tpkg directory perms
      assert_equal(0755, File.stat(File.join(testroot, 'home', 'tpkg', 'etc')).mode & 07777)
    end
    FileUtils.rm_f(pkg)
    
    # Test file_defaults and dir_defaults usage in a package
    pkg = nil
    Dir.mktmpdir('srcdir') do |srcdir|
      FileUtils.cp(File.join(TESTPKGDIR, 'tpkg-default-perms.xml'), File.join(srcdir, 'tpkg.xml'))
      FileUtils.mkdir_p(File.join(srcdir, 'reloc'))
      FileUtils.mkdir_p(File.join(srcdir, 'reloc', 'dir1'))
      File.open(File.join(srcdir, 'reloc', 'dir1', 'file1'), 'w') do |file|
        file.puts 'Testing file_defaults'
      end
      # Ensure that the file goes into the package with permissions different
      # from what we specify in the metadata so that we know tpkg set the
      # permissions requested by the metadata and not that the file just came
      # out of tar with the right permissions already.
      File.chmod(0640, File.join(srcdir, 'reloc', 'dir1', 'file1'))
      FileUtils.mkdir_p(File.join(srcdir, 'reloc', 'dir1', 'subdir1'))
      File.chmod(0750, File.join(srcdir, 'reloc', 'dir1', 'subdir1'))
      pkg = make_package(:output_directory => @tempoutdir, :change => { 'name' => 'default-perms' }, :source_directory => srcdir, :remove => ['operatingsystem', 'architecture', 'posix_acl', 'windows_acl'])
    end
    Dir.mktmpdir('testroot') do |testroot|
      testbase = File.join(testroot, 'home', 'tpkg')
      FileUtils.mkdir_p(testbase)
      tpkg = Tpkg.new(:file_system_root => testroot, :base => File.join('home', 'tpkg'), :sources => [pkg])
      # Standard umask settings might be the same as the default permissions,
      # which would mask failure here.  Set an extreme umask so that we know
      # tpkg is enforcing the desired permissions.
      oldumask = File.umask
      File.umask(0)
      assert_nothing_raised { tpkg.unpack(pkg) }
      File.umask(oldumask)
      # This file should have the 0444 perms we specified in the
      # tpkg-default-perms.xml file
      assert_equal(0444, File.stat(File.join(testbase, 'dir1', 'file1')).mode & 07777)
      # These directories should have the 0555 perms we specified
      assert_equal(0555, File.stat(File.join(testbase, 'dir1')).mode & 07777)
      assert_equal(0555, File.stat(File.join(testbase, 'dir1', 'subdir1')).mode & 07777)
      # The mktmpdir cleanup process doesn't seem to like cleaning up
      # non-writeable directories and links.  Note that any assertion failures
      # will cause this to get skipped.  So if you start getting permission
      # errors from the cleanup process look to see if you might have caused
      # an assertion to fail.
      Find.find(testroot) do |f|
        if File.symlink?(f)
          begin
            File.lchmod(0700, f)
          rescue NotImplementedError
          end
        else
          File.chmod(0700, f)
        end
      end
    end
    FileUtils.rm_f(pkg)
    
    # Test that applying standard default permissions works in the face of
    # symlinks in the package
    pkg = nil
    Dir.mktmpdir('srcdir') do |srcdir|
      FileUtils.cp(File.join(TESTPKGDIR, 'tpkg-nofiles.xml'), File.join(srcdir, 'tpkg.xml'))
      FileUtils.mkdir_p(File.join(srcdir, 'reloc'))
      # Broken link to ensure that nothing attempts to traverse the link and
      # fails as a result
      File.symlink('/path/to/nowhere', File.join(srcdir, 'reloc', 'brokenlink'))
      FileUtils.mkdir_p(File.join(srcdir, 'reloc', 'dir'))
      File.symlink('dir', File.join(srcdir, 'reloc', 'dirlink'))
      File.open(File.join(srcdir, 'reloc', 'file'), 'w') do |file|
        file.puts 'Hello'
      end
      # Set some crazy perms on this file so that we can be sure they
      # are preserved (there are no default permissions for files)
      File.chmod(0777, File.join(srcdir, 'reloc', 'file'))
      File.symlink('file', File.join(srcdir, 'reloc', 'filelink'))
      pkg = make_package(:output_directory => @tempoutdir, :change => { 'name' => 'no-default-perms-with-links' }, :source_directory => srcdir, :remove => ['operatingsystem', 'architecture', 'posix_acl', 'windows_acl'])
    end
    Dir.mktmpdir('testroot') do |testroot|
      testbase = File.join(testroot, 'home', 'tpkg')
      FileUtils.mkdir_p(testbase)
      tpkg = Tpkg.new(:file_system_root => testroot, :base => File.join('home', 'tpkg'), :sources => [pkg])
      assert_nothing_raised { tpkg.unpack(pkg) }
      assert_equal(0777, File.stat(File.join(testbase, 'file')).mode & 07777)
      assert_equal(Tpkg::DEFAULT_DIR_PERMS, File.stat(File.join(testbase, 'dir')).mode & 07777)
    end
    FileUtils.rm_f(pkg)
    
    # Test that applying specified default permissions works in the face of
    # symlinks in the package
    pkg = nil
    Dir.mktmpdir('srcdir') do |srcdir|
      FileUtils.cp(File.join(TESTPKGDIR, 'tpkg-default-perms.xml'), File.join(srcdir, 'tpkg.xml'))
      FileUtils.mkdir_p(File.join(srcdir, 'reloc'))
      # Broken link to ensure that nothing attempts to traverse the link and
      # fails as a result
      File.symlink('/path/to/nowhere', File.join(srcdir, 'reloc', 'brokenlink'))
      FileUtils.mkdir_p(File.join(srcdir, 'reloc', 'dir'))
      File.symlink('dir', File.join(srcdir, 'reloc', 'dirlink'))
      File.open(File.join(srcdir, 'reloc', 'file'), 'w') do |file|
        file.puts 'Hello'
      end
      File.chmod(0777, File.join(srcdir, 'reloc', 'file'))
      File.symlink('file', File.join(srcdir, 'reloc', 'filelink'))
      pkg = make_package(:output_directory => @tempoutdir, :change => { 'name' => 'default-perms-with-links' }, :source_directory => srcdir, :remove => ['operatingsystem', 'architecture', 'posix_acl', 'windows_acl'])
    end
    Dir.mktmpdir('testroot') do |testroot|
      testbase = File.join(testroot, 'home', 'tpkg')
      FileUtils.mkdir_p(testbase)
      tpkg = Tpkg.new(:file_system_root => testroot, :base => File.join('home', 'tpkg'), :sources => [pkg])
      assert_nothing_raised { tpkg.unpack(pkg) }
      assert_equal(0444, File.stat(File.join(testbase, 'file')).mode & 07777)
      assert_equal(0555, File.stat(File.join(testbase, 'dir')).mode & 07777)
      begin
        # Test to see if lchmod is implemented on this platform.  If not then
        # tpkg won't have been able to use it and we can't check if it worked.
        lchmodtestfile = Tempfile.new('lchmodtest')
        File.lchmod(0555, lchmodtestfile.path)
        # If that didn't raise an exception then we can proceed with
        # assertions related to lchmod
        assert_equal(0444, File.lstat(File.join(testbase, 'brokenlink')).mode & 07777)
        assert_equal(0444, File.lstat(File.join(testbase, 'filelink')).mode & 07777)
        assert_equal(0444, File.lstat(File.join(testbase, 'dirlink')).mode & 07777)
      rescue NotImplementedError
        warn "lchmod not available on this platform, link permissions not tested"
      end
      # The mktmpdir cleanup process doesn't seem to like cleaning up
      # non-writeable directories and links.  Note that any assertion failures
      # will cause this to get skipped.  So if you start getting permission
      # errors from the cleanup process look to see if you might have caused
      # an assertion to fail.
      Find.find(testroot) do |f|
        if File.symlink?(f)
          begin
            File.lchmod(0700, f)
          rescue NotImplementedError
          end
        else
          File.chmod(0700, f)
        end
      end
    end
    FileUtils.rm_f(pkg)
    
    # Test that symlinks are not followed when applying permissions to
    # specific files
    pkg = nil
    Dir.mktmpdir('srcdir') do |srcdir|
      FileUtils.cp(File.join(TESTPKGDIR, 'tpkg-nofiles.xml'), File.join(srcdir, 'tpkg.xml'))
      FileUtils.mkdir_p(File.join(srcdir, 'reloc'))
      # Broken link to ensure that nothing attempts to traverse the link and
      # fails as a result
      File.symlink('/path/to/nowhere', File.join(srcdir, 'reloc', 'brokenlink'))
      FileUtils.mkdir_p(File.join(srcdir, 'reloc', 'dir'))
      File.symlink('dir', File.join(srcdir, 'reloc', 'dirlink'))
      File.open(File.join(srcdir, 'reloc', 'file'), 'w') do |file|
        file.puts 'Hello'
      end
      File.chmod(0400, File.join(srcdir, 'reloc', 'file'))
      File.symlink('file', File.join(srcdir, 'reloc', 'filelink'))
      pkg = make_package(:change => { 'name' => 'specific-perms-with-links' }, :files => {'brokenlink' => {'perms' => '0555'}, 'dirlink' => {'perms' => '0770'}, 'filelink' => {'perms' => '0666'}}, :source_directory => srcdir, :output_directory => @tempoutdir, :remove => ['operatingsystem', 'architecture', 'posix_acl', 'windows_acl'])
    end
    Dir.mktmpdir('testroot') do |testroot|
      testbase = File.join(testroot, 'home', 'tpkg')
      FileUtils.mkdir_p(testbase)
      tpkg = Tpkg.new(:file_system_root => testroot, :base => File.join('home', 'tpkg'), :sources => [pkg])
      assert_nothing_raised { tpkg.unpack(pkg) }
      assert_equal(Tpkg::DEFAULT_DIR_PERMS, File.stat(File.join(testbase, 'dir')).mode & 07777)
      assert_equal(0400, File.stat(File.join(testbase, 'file')).mode & 07777)
      begin
        # Test to see if lchmod is implemented on this platform.  If not then
        # tpkg won't have been able to use it and we can't check if it worked.
        lchmodtestfile = Tempfile.new('lchmodtest')
        File.lchmod(0555, lchmodtestfile.path)
        # If that didn't raise an exception then we can proceed with
        # assertions related to lchmod
        assert_equal(0555, File.lstat(File.join(testbase, 'brokenlink')).mode & 07777)
        assert_equal(0666, File.lstat(File.join(testbase, 'filelink')).mode & 07777)
        assert_equal(0770, File.lstat(File.join(testbase, 'dirlink')).mode & 07777)
      rescue NotImplementedError
        warn "lchmod not available on this platform, link permissions not tested"
      end
    end
    FileUtils.rm_f(pkg)
    
    # Test that preinstall/postinstall are run at the right points
    #   Make up a package with scripts that create files so we can check timestamps
    # Also, test that tpkg will chdir to package unpack directory before
    # calling pre/post/install/remove scripts
{'fraction_non_alphanumeric': 0.14093713278495887, 'fraction_numerical': 0.020380434782608696, 'mean_word_length': 3.4680885972108286, 'pattern_counts': {'":': 0, '<': 8, '<?xml version=': 0, '>': 134, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 24}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6581611', 'n_tokens_mistral': 9413, 'n_tokens_neox': 9123, 'n_words': 2408}