Beefy Boxes and Bandwidth Generously Provided by pair Networks
No such thing as a small change
 
PerlMonks  

CGI filename race

by songahji (Friar)
on Aug 27, 2007 at 18:00 UTC ( [id://635357]=perlquestion: print w/replies, xml ) Need Help??

songahji has asked for the wisdom of the Perl Monks concerning the following question:

Dear Monks,

If case there is a thread already discussing this issue, my apology and please redirect me and I'll read up.

Anyway, I am writing CGI form which creates a new file in a solaris box. Numbers is the filename. There is a history file which stores the last number used. What can I do to make sure that the filename will not get clobbered? I am using following routine:

$fn_number = get_latest_filename(); # read the history file while ( -e $fn_number ) { $fn_number++; update_fn_number(); # update the history file } write_thefile($fn_number);

I tested with 3 users at the submitting the form at same time (well, I tried to make sure three of us clicking the submit button at the same time) and 1 out of 5 testing the form clobbers.

TY,
songahji

Replies are listed 'Best First'.
Re: CGI filename race
by Joost (Canon) on Aug 27, 2007 at 18:38 UTC
Re: CGI filename race
by Fletch (Bishop) on Aug 27, 2007 at 18:40 UTC

    Because your check for the existence of the next file and the updating of the next number to use are not a single atomic action you've created the classic example of a race condition between your multiple processes. You want to look at either perldoc -q lock (in order to lock the history file, but remember you still would need to test for file existence while you have the history locked), or the discussion of the O_EXCL flag to sysopen in perlopentut (which would let the OS do the test-or-create in one atomic step). Or more preferably, read them both :).

Re: CGI filename race
by kyle (Abbot) on Aug 27, 2007 at 19:22 UTC

    Do the files have to be serial numbered? My usual way of making a unique filename is the time plus the PID (i.e., "sprintf '%d-%d', time(), $$"). You get names like "1188242388-16378", but they never collide.

      The problem with just using very-low-possibility-of-collision filenames alone is that the filename alone doesn't guarantee that nothing else can create the file with the same name. You still need to use sysopen and O_CREAT|O_EXCL to atomically test-and-create to be sure that you're creating the file you expect.

      If you'll learn and consistently use the secure idiom (or let mkstemp do it correctly for you) you'll save yourself from recreating any of the huge number of *NIX exploits of yore.

      (For those not familiar with exploits of olden days, it was quite common for setuid programs to use a predictable temp file name but not to check if the file was present before clobbering its contents. It was then possible to (for example) symlink that predictable temp file to something vital (/etc/passwd) and get the contents overwritten which then allowed some sort of privilege escalation afterwards.)

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://635357]
Approved by Joost
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others rifling through the Monastery: (9)
As of 2024-04-23 10:53 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found