Just for fun: symbolic chmod

H

Hal Fulton

I think Ruby's chmod should operate symbolically as the command line
version does.

To that end, I've been playing around. (Yes, I do have a TV, but
nothing is on.)

Here's some code. It only implements rwx on the righthand side so far.

I test it by calling the OS's chmod, so your mileage may vary.

In fact, I'm unsure why the last test case is failing. (I added these
more or less randomly.) But given the ugly nature of test12, I'm not
really concerned much.

If you feel like it: Add, refactor, critique.

It's a small thing, but I'd like to see this functionality added into
the core if Matz should see fit.


Cheers,
Hal


###############
def sym2oct(init,str)
left = {"u" => 0700, "g" => 0070, "o" => 0007, "a" => 0777}
right = {"r" => 0444, "w" => 0222, "x" => 0111}
reg = /([ugoa]+)([+-=])([rwx]+)/

cmds = str.split(",")
perm = init
cmds.each do |cmd|
match = cmd.match(reg)
junk,who,what,how = match.to_a
who = who.split(//).inject(num=0) {|num,b| num |= left; num }
how = how.split(//).inject(num=0) {|num,b| num |= right; num }
mask = who & how
case what
when "+"; perm = perm | mask
when "-"; perm = perm & ~mask
when "="; perm = mask
end
end
perm
end

if $0 == __FILE__

require "test/unit"

def try(str)
File.unlink("file1") if File.exist?("file1")
File.unlink("file2") if File.exist?("file2")
File.open("file1","w") { } # Create files
File.open("file2","w") { }
init = File.stat("file1").mode # Get initial perms (re umask)
perm = sym2oct(init,str)
File.chmod(perm,"file1") # chmod file1 thru Ruby
system("chmod #{str} file2") # chmod file2 thru OS
trial = File.stat("file1").mode # and check results
actual = File.stat("file2").mode
assert_equal(trial.to_s(8),actual.to_s(8))
end

class Tester < Test::Unit::TestCase

def test01; try("a+w"); end
def test02; try("a+rw"); end
def test03; try("a-w"); end
def test04; try("u+w"); end
def test05; try("u-r"); end
def test06; try("u-rx"); end
def test07; try("g+rx"); end
def test08; try("g-rw"); end
def test09; try("a+w,g+r,o+x"); end
def test10; try("ugo+w,a-w"); end
def test11; try("a=rwx"); end
def test12; try("g=rw,a+x,o-w"); end

end

end
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,772
Messages
2,569,593
Members
45,112
Latest member
VinayKumar Nevatia
Top