[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.ruby

Obtaining mode information on a File object

Jos Backus

12/4/2004 7:51:00 PM

Another question... How do I access the File open mode ("w" in this case) on a
File object? Example:

class Foo
def initialize(file)
begin
yield self
ensure
# We only want to call finalize when the file was opened for writing;
# The following doesn't work, but how _do_ you do this?
finalize(file) if file.mode.writable? # file was opened with mode "w"
end
end
def finalize(file)
file.puts "END"
end
end

File.open("foo", "w") do |file|
a = Foo.new(file) do
# ... Use a ...
end
end

--
Jos Backus _/ _/_/_/ Sunnyvale, CA
_/ _/ _/
_/ _/_/_/
_/ _/ _/ _/
jos at catnook.com _/_/ _/_/_/ require 'std/disclaimer'


5 Answers

Robert Klemme

12/5/2004 2:30:00 PM

0


"Jos Backus" <jos@catnook.com> schrieb im Newsbeitrag
news:20041204195115.GA83981@lizzy.catnook.com...
> Another question... How do I access the File open mode ("w" in this case)
> on a
> File object? Example:
>
> class Foo
> def initialize(file)
> begin
> yield self
> ensure
> # We only want to call finalize when the file was opened for writing;
> # The following doesn't work, but how _do_ you do this?
> finalize(file) if file.mode.writable? # file was opened with mode "w"
> end
> end
> def finalize(file)
> file.puts "END"
> end
> end
>
> File.open("foo", "w") do |file|
> a = Foo.new(file) do
> # ... Use a ...
> end
> end

First of all, I know no other way than to just try to write to the file and
see what happens. Maybe writing an empty string is a solution on some
(all?) platforms.

But I think usually you don't need that info: if a method requires an IO
object open for writing then it simply uses it that way and you get bitten
by an exception if it's not open for writing. Similar applies for files
needed for reading.

What is the scenario where you need that?

Kind regards

robert

Jos Backus

12/6/2004 6:58:00 AM

0

On Sun, Dec 05, 2004 at 11:32:36PM +0900, Robert Klemme wrote:
>
> "Jos Backus" <jos@catnook.com> schrieb im Newsbeitrag
> news:20041204195115.GA83981@lizzy.catnook.com...
> >Another question... How do I access the File open mode ("w" in this case)
> >on a
> >File object? Example:
> >
> >class Foo
> > def initialize(file)
> > begin
> > yield self
> > ensure
> > # We only want to call finalize when the file was opened for writing;
> > # The following doesn't work, but how _do_ you do this?
> > finalize(file) if file.mode.writable? # file was opened with mode "w"
> > end
> > end
> > def finalize(file)
> > file.puts "END"
> > end
> >end
> >
> >File.open("foo", "w") do |file|
> > a = Foo.new(file) do
> > # ... Use a ...
> > end
> >end
>
> First of all, I know no other way than to just try to write to the file and
> see what happens. Maybe writing an empty string is a solution on some
> (all?) platforms.

I hadn't thought of that. It seems... wrong. This information is available
already, it's a matter of making it accessible using an attribute reader.

> But I think usually you don't need that info: if a method requires an IO
> object open for writing then it simply uses it that way and you get bitten
> by an exception if it's not open for writing. Similar applies for files
> needed for reading.
>
> What is the scenario where you need that?

I'm writing a class to handle CPIO archives. Iff the file passed in was opened
for writing I want to call a finalizer that appends a trailer, as in the above
code snippet.

I'm currently looking at io.c to see if the vmode variable in rb_open_file
can't be exported somehow, like filename. One issue is that the mode argument
can be either a String or Fixnum (things like O_RDONLY), which complicates
matters.

Thanks,
--
Jos Backus _/ _/_/_/ Sunnyvale, CA
_/ _/ _/
_/ _/_/_/
_/ _/ _/ _/
jos at catnook.com _/_/ _/_/_/ require 'std/disclaimer'


Tanaka Akira

12/6/2004 7:08:00 AM

0

In article <20041204195115.GA83981@lizzy.catnook.com>,
Jos Backus <jos@catnook.com> writes:

> Another question... How do I access the File open mode ("w" in this case) on a
> File object? Example:

% ruby -rfcntl -e '
open("/dev/null") {|f| p f.fcntl(Fcntl::F_GETFL) & Fcntl::O_ACCMODE }
open("/dev/null", "w") {|f| p f.fcntl(Fcntl::F_GETFL) & Fcntl::O_ACCMODE }
open("/dev/null", "r+") {|f| p f.fcntl(Fcntl::F_GETFL) & Fcntl::O_ACCMODE }
'
0
1
2

0 means O_RDONLY. 1 means O_WRONLY. 2 means O_RDWR.

I don't know this is portable enough.

Note that this doesn't work for duplex pipe.

% ruby -rfcntl -e '
open("|echo", "r+") {|f| p f.fcntl(Fcntl::F_GETFL) & Fcntl::O_ACCMODE }
'
0
--
Tanaka Akira


Jos Backus

12/6/2004 4:59:00 PM

0

On Mon, Dec 06, 2004 at 04:08:29PM +0900, Tanaka Akira wrote:
> In article <20041204195115.GA83981@lizzy.catnook.com>,
> Jos Backus <jos@catnook.com> writes:
>
> > Another question... How do I access the File open mode ("w" in this case) on a
> > File object? Example:
>
> % ruby -rfcntl -e '
> open("/dev/null") {|f| p f.fcntl(Fcntl::F_GETFL) & Fcntl::O_ACCMODE }
> open("/dev/null", "w") {|f| p f.fcntl(Fcntl::F_GETFL) & Fcntl::O_ACCMODE }
> open("/dev/null", "r+") {|f| p f.fcntl(Fcntl::F_GETFL) & Fcntl::O_ACCMODE }
> '
> 0
> 1
> 2
>
> 0 means O_RDONLY. 1 means O_WRONLY. 2 means O_RDWR.
>
> I don't know this is portable enough.

This is good enough for my purposes (it only needs to run on Linux), thanks.

Otoh, how about creating an IO.mode instance method that returns the opposite
of what rb_io_mode_flags() produces? rb_io_mode_flags() turns a mode string
into a flags value which OR's some FMODE_* constants. What if we would have a
method which would take fptr->mode and return this as a String? It would be
as portable as Ruby's idea of the file's mode. If there's interest, I can whip
up a patch which should be pretty small.

> Note that this doesn't work for duplex pipe.
>
> % ruby -rfcntl -e '
> open("|echo", "r+") {|f| p f.fcntl(Fcntl::F_GETFL) & Fcntl::O_ACCMODE }
> '
> 0

Okay. I also notice this asymmetry:

irb(main):001:0> require 'fcntl'
=> true
irb(main):002:0> open("|echo", "r") {|f| p f.fcntl(Fcntl::F_GETFL) & Fcntl::O_ACCMODE }
2
=> nil
irb(main):003:0> open("|echo", "w") {|f| p f.fcntl(Fcntl::F_GETFL) & Fcntl::O_ACCMODE }
2

=> nil
irb(main):004:0> open("echo|", "r") {|f| p f.fcntl(Fcntl::F_GETFL) & Fcntl::O_ACCMODE }
0
=> nil
irb(main):005:0> open("echo|", "w") {|f| p f.fcntl(Fcntl::F_GETFL) & Fcntl::O_ACCMODE }
1
=> nil
irb(main):006:0>

Thanks!

--
Jos Backus _/ _/_/_/ Sunnyvale, CA
_/ _/ _/
_/ _/_/_/
_/ _/ _/ _/
jos at catnook.com _/_/ _/_/_/ require 'std/disclaimer'


Jos Backus

12/6/2004 7:24:00 PM

0

On Tue, Dec 07, 2004 at 01:59:27AM +0900, Jos Backus wrote:
> I can whip up a patch which should be pretty small.

Fyi: I just submitted a small patch to ruby-core.

--
Jos Backus _/ _/_/_/ Sunnyvale, CA
_/ _/ _/
_/ _/_/_/
_/ _/ _/ _/
jos at catnook.com _/_/ _/_/_/ require 'std/disclaimer'