Make a file read-only?

Hi, I can make a file writeable easy enough,

    mode = File.stat(file).mode
    File.chmod(mode | 0000200, file)

But how do I make a file read-only?

    mode = File.stat(file).mode
    File.chmod(mode - 0000222, file)

Subtraction doesn't work. And I've tried `&`, `|` and `^`. Do I have to do
some sort compliments operation here? What's the trick to this?

FYI, on the command line it's as easy as:

  $ chmod a-w file

More specifically, then, you want to remove the write permission from
the file, leaving it whatever other permissions were already set
(possibly none!). In other words, you want to /mask out/ the write bits
from whatever the current file mode is. Try the following:

mode = 0100664
mask = mode ^ 0222
new_mode = mode & mask

-Jeremy

···

On 02/06/2012 01:38 PM, Intransition wrote:

Hi, I can make a file writeable easy enough,

    mode = File.stat(file).mode
    File.chmod(mode | 0000200, file)

But how do I make a file read-only?

    mode = File.stat(file).mode
    File.chmod(mode - 0000222, file)

Subtraction doesn't work. And I've tried `&`, `|` and `^`. Do I have to
do some sort compliments operation here? What's the trick to this?

FYI, on the command line it's as easy as:

  $ chmod a-w file

Ruby 1.9.3:

FileUtils.chmod 'a-w', 'file'

···

On Mon, Feb 6, 2012 at 11:38 AM, Intransition <transfire@gmail.com> wrote:

$ chmod a-w file

--
Jos Backus
jos at catnook.com

Thanks. Seems almost obvious now that I see it.

Nice! Almost worth kicking 1.8 totally to the curb for! :slight_smile:

···

On Monday, February 6, 2012 3:34:07 PM UTC-5, Jos Backus wrote:

On Mon, Feb 6, 2012 at 11:38 AM, Intransition wrote:
> $ chmod a-w file

Ruby 1.9.3:

FileUtils.chmod 'a-w', 'file'

http://ruby-doc.org/&lt;http://ruby-doc.org/stdlib-1.9.3/libdoc/fileutils/rdoc/FileUtils.html#method-c-chmod&gt;

Interesting approach. I usually do it like this:

irb(main):038:0> mode = 0100664
=> 33204
irb(main):039:0> mask = 0222
=> 146
irb(main):040:0> new_mode = (mode | mask) ^ mask
=> 33060
irb(main):041:0> "%07o" % new_mode
=> "0100444"

Kind regards

robert

···

On Mon, Feb 6, 2012 at 9:14 PM, Jeremy Bopp <jeremy@bopp.net> wrote:

On 02/06/2012 01:38 PM, Intransition wrote:
More specifically, then, you want to remove the write permission from
the file, leaving it whatever other permissions were already set
(possibly none!). In other words, you want to /mask out/ the write bits
from whatever the current file mode is. Try the following:

mode = 0100664
mask = mode ^ 0222
new_mode = mode & mask

--
remember.guy do |as, often| as.you_can - without end
http://blog.rubybestpractices.com/

As far as I can tell, these approaches are functionally equivalent in
both result and efficiency. Folding the method I used all together
using your settings for mode and mask makes mine as follows:

new_mode = mode & (mode ^ mask)

I suspect that someone who more recently completed their college
philosophy of logic class than I might even remember how to derive one
of our solutions from the other using tidy boolean algebra. I'm too
rusty for it at the moment unfortunately, but I did give it a try. :frowning:

Maybe I'll pick at it more tomorrow...

-Jeremy

···

On 02/07/2012 04:20 PM, Robert Klemme wrote:

On Mon, Feb 6, 2012 at 9:14 PM, Jeremy Bopp <jeremy@bopp.net> wrote:

On 02/06/2012 01:38 PM, Intransition wrote:
More specifically, then, you want to remove the write permission from
the file, leaving it whatever other permissions were already set
(possibly none!). In other words, you want to /mask out/ the write bits
from whatever the current file mode is. Try the following:

mode = 0100664
mask = mode ^ 0222
new_mode = mode & mask

Interesting approach. I usually do it like this:

irb(main):038:0> mode = 0100664
=> 33204
irb(main):039:0> mask = 0222
=> 146
irb(main):040:0> new_mode = (mode | mask) ^ mask
=> 33060
irb(main):041:0> "%07o" % new_mode
=> "0100444"

More specifically, then, you want to remove the write permission from
the file, leaving it whatever other permissions were already set
(possibly none!). In other words, you want to /mask out/ the write bits
from whatever the current file mode is. Try the following:

mode = 0100664
mask = mode ^ 0222
new_mode = mode & mask

Interesting approach. I usually do it like this:

irb(main):038:0> mode = 0100664
=> 33204
irb(main):039:0> mask = 0222
=> 146
irb(main):040:0> new_mode = (mode | mask) ^ mask
=> 33060
irb(main):041:0> "%07o" % new_mode
=> "0100444"

As far as I can tell, these approaches are functionally equivalent in
both result and efficiency.

Yeah, for all practical purposes I believe this is absolutely correct.
In a compiled language like C there might be a difference though
since my version uses two times the same constant and only one input
variable while your folded version below uses the input twice. But
that is certainly microoptimization one should only do when
implementing a gigabit router or something with similar need for
speed. :slight_smile:

Folding the method I used all together
using your settings for mode and mask makes mine as follows:

new_mode = mode & (mode ^ mask)

I suspect that someone who more recently completed their college
philosophy of logic class than I might even remember how to derive one
of our solutions from the other using tidy boolean algebra. I'm too
rusty for it at the moment unfortunately, but I did give it a try. :frowning:

Maybe I'll pick at it more tomorrow...

:slight_smile:

Kind regards

robert

···

On Wed, Feb 8, 2012 at 7:46 AM, Jeremy Bopp <jeremy@bopp.net> wrote:

On 02/07/2012 04:20 PM, Robert Klemme wrote:

On Mon, Feb 6, 2012 at 9:14 PM, Jeremy Bopp <jeremy@bopp.net> wrote:

On 02/06/2012 01:38 PM, Intransition wrote:

--
remember.guy do |as, often| as.you_can - without end
http://blog.rubybestpractices.com/