* lib/fileutils.rb (FileUtils.chmod{,_R}): Enhance the symbolic
mode parser to support the permission symbols u/g/o and multiple actions as defined in SUS, so that chmod("g=o+w", file) works as expected. Invalid symbolic modes are now rejected with ArgumentError. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@41782 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
parent
45116b6a6d
commit
a0011cd54d
@ -1,9 +1,15 @@
|
|||||||
Fri Jul 5 01:23:33 2013 Akinori MUSHA <knu@iDaemons.org>
|
Fri Jul 5 02:14:00 2013 Akinori MUSHA <knu@iDaemons.org>
|
||||||
|
|
||||||
* lib/fileutils.rb (FileUtils#symbolic_modes_to_i): Fix the wrong
|
* lib/fileutils.rb (FileUtils#symbolic_modes_to_i): Fix the wrong
|
||||||
character class [+-=], which happened to match all desired
|
character class [+-=], which happened to match all desired
|
||||||
characters but also match undesired characters.
|
characters but also match undesired characters.
|
||||||
|
|
||||||
|
* lib/fileutils.rb (FileUtils.chmod{,_R}): Enhance the symbolic
|
||||||
|
mode parser to support the permission symbols u/g/o and multiple
|
||||||
|
actions as defined in SUS, so that chmod("g=o+w", file) works as
|
||||||
|
expected. Invalid symbolic modes are now rejected with
|
||||||
|
ArgumentError.
|
||||||
|
|
||||||
Fri Jul 5 00:25:39 2013 Nobuyoshi Nakada <nobu@ruby-lang.org>
|
Fri Jul 5 00:25:39 2013 Nobuyoshi Nakada <nobu@ruby-lang.org>
|
||||||
|
|
||||||
* lib/mkmf.rb (have_framework): allow header file to check.
|
* lib/mkmf.rb (have_framework): allow header file to check.
|
||||||
|
@ -868,62 +868,78 @@ module FileUtils
|
|||||||
OPT_TABLE['install'] = [:mode, :preserve, :noop, :verbose]
|
OPT_TABLE['install'] = [:mode, :preserve, :noop, :verbose]
|
||||||
|
|
||||||
def user_mask(target) #:nodoc:
|
def user_mask(target) #:nodoc:
|
||||||
mask = 0
|
target.each_char.inject(0) do |mask, chr|
|
||||||
target.each_byte do |byte_chr|
|
case chr
|
||||||
case byte_chr.chr
|
|
||||||
when "u"
|
when "u"
|
||||||
mask |= 04700
|
mask | 04700
|
||||||
when "g"
|
when "g"
|
||||||
mask |= 02070
|
mask | 02070
|
||||||
when "o"
|
when "o"
|
||||||
mask |= 01007
|
mask | 01007
|
||||||
when "a"
|
when "a"
|
||||||
mask |= 07777
|
mask | 07777
|
||||||
|
else
|
||||||
|
raise ArgumentError, "invalid `who' symbol in file mode: #{chr}"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
mask
|
|
||||||
end
|
end
|
||||||
private_module_function :user_mask
|
private_module_function :user_mask
|
||||||
|
|
||||||
def mode_mask(mode, path) #:nodoc:
|
def apply_mask(mode, user_mask, op, mode_mask)
|
||||||
mask = 0
|
case op
|
||||||
mode.each_byte do |byte_chr|
|
when '='
|
||||||
case byte_chr.chr
|
(mode & ~user_mask) | (user_mask & mode_mask)
|
||||||
|
when '+'
|
||||||
|
mode | (user_mask & mode_mask)
|
||||||
|
when '-'
|
||||||
|
mode & ~(user_mask & mode_mask)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
private_module_function :apply_mask
|
||||||
|
|
||||||
|
def symbolic_modes_to_i(mode_sym, path) #:nodoc:
|
||||||
|
mode_sym.split(/,/).inject(File.stat(path).mode & 07777) do |current_mode, clause|
|
||||||
|
target, *actions = clause.split(/([=+-])/)
|
||||||
|
raise ArgumentError, "invalid file mode: #{mode_sym}" if actions.empty?
|
||||||
|
target = 'a' if target.empty?
|
||||||
|
user_mask = user_mask(target)
|
||||||
|
actions.each_slice(2) do |op, perm|
|
||||||
|
need_apply = op == '='
|
||||||
|
mode_mask = (perm || '').each_char.inject(0) do |mask, chr|
|
||||||
|
case chr
|
||||||
when "r"
|
when "r"
|
||||||
mask |= 0444
|
mask | 0444
|
||||||
when "w"
|
when "w"
|
||||||
mask |= 0222
|
mask | 0222
|
||||||
when "x"
|
when "x"
|
||||||
mask |= 0111
|
mask | 0111
|
||||||
when "X"
|
when "X"
|
||||||
mask |= 0111 if FileTest::directory? path
|
if FileTest.directory? path
|
||||||
when "s"
|
mask | 0111
|
||||||
mask |= 06000
|
else
|
||||||
when "t"
|
|
||||||
mask |= 01000
|
|
||||||
end
|
|
||||||
end
|
|
||||||
mask
|
mask
|
||||||
end
|
end
|
||||||
private_module_function :mode_mask
|
when "s"
|
||||||
|
mask | 06000
|
||||||
def symbolic_modes_to_i(modes, path) #:nodoc:
|
when "t"
|
||||||
current_mode = (File.stat(path).mode & 07777)
|
mask | 01000
|
||||||
modes.split(/,/).inject(0) do |mode, mode_sym|
|
when "u", "g", "o"
|
||||||
mode_sym = "a#{mode_sym}" if mode_sym =~ %r!^[=+-]!
|
if mask.nonzero?
|
||||||
target, mode = mode_sym.split %r![=+-]!
|
current_mode = apply_mask(current_mode, user_mask, op, mask)
|
||||||
user_mask = user_mask(target)
|
|
||||||
mode_mask = mode_mask(mode ? mode : "", path)
|
|
||||||
|
|
||||||
case mode_sym
|
|
||||||
when /=/
|
|
||||||
current_mode &= ~(user_mask)
|
|
||||||
current_mode |= user_mask & mode_mask
|
|
||||||
when /\+/
|
|
||||||
current_mode |= user_mask & mode_mask
|
|
||||||
when /-/
|
|
||||||
current_mode &= ~(user_mask & mode_mask)
|
|
||||||
end
|
end
|
||||||
|
need_apply = false
|
||||||
|
copy_mask = user_mask(chr)
|
||||||
|
(current_mode & copy_mask) / (copy_mask & 0111) * (user_mask & 0111)
|
||||||
|
else
|
||||||
|
raise ArgumentError, "invalid `perm' symbol in file mode: #{chr}"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
if mode_mask.nonzero? || need_apply
|
||||||
|
current_mode = apply_mask(current_mode, user_mask, op, mode_mask)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
current_mode
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
private_module_function :symbolic_modes_to_i
|
private_module_function :symbolic_modes_to_i
|
||||||
|
@ -932,6 +932,12 @@ class TestFileUtils
|
|||||||
check_singleton :chmod
|
check_singleton :chmod
|
||||||
|
|
||||||
touch 'tmp/a'
|
touch 'tmp/a'
|
||||||
|
chmod "u=wrx,g=rx,o=x", 'tmp/a'
|
||||||
|
assert_equal 0751, File.stat('tmp/a').mode & 07777
|
||||||
|
chmod "g+w-x", 'tmp/a'
|
||||||
|
assert_equal 0761, File.stat('tmp/a').mode & 07777
|
||||||
|
chmod "o+r,g=o+w,o-r,u-o", 'tmp/a' # 761 => 763 => 773 => 771 => 671
|
||||||
|
assert_equal 0671, File.stat('tmp/a').mode & 07777
|
||||||
chmod "u=wrx,g=,o=", 'tmp/a'
|
chmod "u=wrx,g=,o=", 'tmp/a'
|
||||||
assert_equal 0700, File.stat('tmp/a').mode & 0777
|
assert_equal 0700, File.stat('tmp/a').mode & 0777
|
||||||
chmod "u=rx,go=", 'tmp/a'
|
chmod "u=rx,go=", 'tmp/a'
|
||||||
@ -956,6 +962,26 @@ class TestFileUtils
|
|||||||
assert_equal 0500, File.stat('tmp/a').mode & 07777
|
assert_equal 0500, File.stat('tmp/a').mode & 07777
|
||||||
end
|
end
|
||||||
|
|
||||||
|
assert_raises_with_message(ArgumentError, /invalid\b.*\bfile mode/) {
|
||||||
|
chmod "a", 'tmp/a'
|
||||||
|
}
|
||||||
|
|
||||||
|
assert_raises_with_message(ArgumentError, /invalid\b.*\bfile mode/) {
|
||||||
|
chmod "x+a", 'tmp/a'
|
||||||
|
}
|
||||||
|
|
||||||
|
assert_raises_with_message(ArgumentError, /invalid\b.*\bfile mode/) {
|
||||||
|
chmod "u+z", 'tmp/a'
|
||||||
|
}
|
||||||
|
|
||||||
|
assert_raises_with_message(ArgumentError, /invalid\b.*\bfile mode/) {
|
||||||
|
chmod ",+x", 'tmp/a'
|
||||||
|
}
|
||||||
|
|
||||||
|
assert_raises_with_message(ArgumentError, /invalid\b.*\bfile mode/) {
|
||||||
|
chmod "755", 'tmp/a'
|
||||||
|
}
|
||||||
|
|
||||||
end if have_file_perm?
|
end if have_file_perm?
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user