Tempfile : delete problem


#1

(Ruby 1.8.6 under Windows)

My application creates a series of temporary files. I decided to use
the tempfile module of Ruby, but I needed to control the file extension
of the generated temporary file (should end in .xml). I came up with
the following solution:

file=Tempfile.new('.tempreq','/thome/requests')
file << '....' # populate the file
path=file.path # remember the generated filename
file.close
result=path+'.xml' # add desired extension to the filename
File.rename(path,result) # rename file
at_exit { File::delete(result) } # remove file at exit

When the exit handler jumps into action, I get however the following
error:

H:\thome\grubylib/TfwCommon.rb:433:in `delete’: Permission denied -
/thome/requests/.tempr
eq.3176.0.xml (Errno::EACCES)

After the program has ended, I can however erase the file from the
command line with
no problems. Why do I get a “permission denied” here? Is there a better
way to
achieve my goal?

Ronald


#2

I’d just use the block form:

ruby -r tempfile -e ‘Tempfile.open(“foo”, “.”) {|io| io.puts 123}’

Hmmm… I don’t see how this solves my file rename problem. Don’t forget
that I need to rename the temporary file, so that it has the extension
.xml, before I continue processing it. The logic basically should go
like this (pseudocode):

  1. create temporary file
  2. fill temporary file and close it
  3. rename it, so that it ends in .xml
  4. pass its file name to some library function, which processes the
    file
  5. when my application exits, delete that xml file

Tempfile::open with block argument performs steps 1 and 2 above, but
doesn’t
tell me the name of the temporary file:

x=Tempfile.open(“foo”, “.”) {|io| io.puts 123}
x.class
=> NilClass


#3

2007/7/12, Ronald F. removed_email_address@domain.invalid:

I’d just use the block form:

ruby -r tempfile -e ‘Tempfile.open(“foo”, “.”) {|io| io.puts 123}’

Hmmm… I don’t see how this solves my file rename problem.

Ah, my bad: I overread that one. File renaming is a bad idea with
tempfiles.

  1. when my application exits, delete that xml file

Tempfile::open with block argument performs steps 1 and 2 above, but
doesn’t
tell me the name of the temporary file:

x=Tempfile.open(“foo”, “.”) {|io| io.puts 123}
x.class
=> NilClass

In that case rather use your own mechanism. That’s too far away from
tempfile’s functionality. For example

def tmp_xml(base, dir, mode)
file_name = File.join(dir, “#{base}-#{rand 1000}.xml”)
begin
File.open(file_name, mode) do |io|
yield io, file_name
end
ensure
File.unlink file_name if File.exists? file_name
end
end

Then you can do

tmp_xml “.”, “foo”, “rw” do |io, name|
puts “file is #{name}”

end

Kind regards

robert


#4

the following

error:

H:\thome\grubylib/TfwCommon.rb:433:in `delete’:
Permission denied -

/thome/requests/.tempr
eq.3176.0.xml (Errno::EACCES)

In that case rather use your own mechanism. That’s too far away from
tempfile’s functionality.

I found a solution based on an idea posted at

http://marsorange.com/articles/2006/07/17/of-mogrify-ruby-tempfile-dynam
ic-class-definitions

which allowed me to use most of Tempfile functionality with only
providing
minimal own code:

require ‘tempfile’
class XMLTempfile <Tempfile
def make_tmpname(basename, n)
sprintf(’%s%d-%d.xml’, basename, $$, n)
end
end

file=XMLTempfile.new('.tempreq',TFW_REQDIR)
file << '.....'
result=file.path
file.close

Ronald


#5

2007/7/12, Ronald F. removed_email_address@domain.invalid:

file.close

After the program has ended, I can however erase the file from the
command line with
no problems. Why do I get a “permission denied” here? Is there a better
way to
achieve my goal?

I’d just use the block form:

ruby -r tempfile -e ‘Tempfile.open(“foo”, “.”) {|io| io.puts 123}’

After that there is no file prefixed “foo” in “.”.

Kind regards

robert


#6

2007/7/16, Florian Aßmann removed_email_address@domain.invalid:

Hi Ronald,

clarification: accessing a path of an IO can be done through
Tempfile#path, it’s standard for File…

Thanks for catching that! I looked for something like this but
apparently /over/looked it. :slight_smile:

Cheers

robert


#7

renamed the file.
Thank you, this makes things clear now.

Why do you need the .xml suffix?

Because I have an application which accepts a basename for a file,
and implicitly assumes its extension .xml.

Ronald


#8

Hi Ronald,

clarification: accessing a path of an IO can be done through
Tempfile#path, it’s standard for File…

require ‘tempfile’
Tempfile.open(’’) { |tempfile| puts tempfile.path }

and since tempfile is per default deleted when the object becomes
finalized it fails because the path is invalid after you renamed the
file.

Why do you need the .xml suffix?

Regards
Florian