diff --git a/lib/rubygems/package.rb b/lib/rubygems/package.rb index f3c1cb2895d5..0816cb762d4b 100644 --- a/lib/rubygems/package.rb +++ b/lib/rubygems/package.rb @@ -448,13 +448,15 @@ def extract_tar_gz(io, destination_dir, pattern = "*") # :nodoc: end unless directories.include?(mkdir) - FileUtils.mkdir_p mkdir, mode: dir_mode ? 0o755 : (entry.header.mode if entry.directory?) + mkdir_mode = 0o755 if dir_mode + mkdir_mode ||= entry.header.mode if entry.directory? + mkdir_mode &= ~File.umask if mkdir_mode + FileUtils.mkdir_p mkdir, mode: mkdir_mode directories << mkdir end if entry.file? - File.open(destination, "wb") {|out| out.write entry.read } - FileUtils.chmod file_mode(entry.header.mode), destination + File.open(destination, "wb", file_mode(entry.header.mode)) {|out| out.write entry.read } end verbose destination diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index d4c307978e7c..8dc8563aaf64 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -161,13 +161,17 @@ def assert_self_install_permissions(format_executable: false) format_executable: format_executable, } Dir.chdir @tempdir do + # use chmod to set global permissions (so umask doesn't bypass our choice) to ensure they are masked on install Dir.mkdir "bin" + File.chmod 0o777, "bin" Dir.mkdir "data" + File.chmod 0o777, "data" File.write "bin/foo", "#!/usr/bin/env ruby\n" - File.chmod 0o755, "bin/foo" + File.chmod 0o777, "bin/foo" File.write "data/foo.txt", "blah\n" + File.chmod 0o666, "data/foo.txt" spec_fetcher do |f| f.gem "foo", 1 do |s| @@ -180,7 +184,7 @@ def assert_self_install_permissions(format_executable: false) prog_mode = (options[:prog_mode] & mask).to_s(8) dir_mode = (options[:dir_mode] & mask).to_s(8) - data_mode = (options[:data_mode] & mask).to_s(8) + data_mode = (options[:data_mode] & mask & (~File.umask)).to_s(8) prog_name = "foo" prog_name = RbConfig::CONFIG["ruby_install_name"].sub("ruby", "foo") if options[:format_executable] expected = { diff --git a/test/rubygems/test_gem_package.rb b/test/rubygems/test_gem_package.rb index 206586410771..7adbc695ec2f 100644 --- a/test/rubygems/test_gem_package.rb +++ b/test/rubygems/test_gem_package.rb @@ -523,7 +523,42 @@ def test_extract_file_permissions filepath = File.join @destination, "README.rdoc" assert_path_exist filepath - assert_equal 0o104444, File.stat(filepath).mode + assert_equal 0o100444.to_s(8), File.stat(filepath).mode.to_s(8) + end + + def test_extract_file_umask_global_permissions + pend "chmod not supported" if Gem.win_platform? + + package = Gem::Package.new @gem + + tgz_io = util_tar_gz do |tar| + tar.mkdir "lib", 0o777 + tar.add_file "bin/global", 0o777 do |io| + io.write "#!/bin/ruby\nputs 'hello world'" + end + tar.add_file "lib/global.rb", 0o666 do |io| + io.write "puts 'hello world'" + end + end + + package.extract_tar_gz tgz_io, @destination + + dirpath = File.join @destination, "lib" + assert_path_exist dirpath + mode = 0o40755 & (~File.umask) + assert_equal mode.to_s(8), File.stat(dirpath).mode.to_s(8) + + filepath = File.join @destination, "lib", "global.rb" + assert_path_exist filepath + assert_equal "puts 'hello world'", File.read(filepath) + mode = 0o100644 & (~File.umask) + assert_equal mode.to_s(8), File.stat(filepath).mode.to_s(8) + + filepath = File.join @destination, "bin", "global" + assert_path_exist filepath + assert_equal "#!/bin/ruby\nputs 'hello world'", File.read(filepath) + mode = 0o100755 & (~File.umask) + assert_equal mode.to_s(8), File.stat(filepath).mode.to_s(8) end def test_extract_tar_gz_absolute