On 17 March 2003, I said:
> Yuck. So here's another crack at patching this:
Oops, stupid error in that one. Third and final attempt -- this time I
actually tested the code on Linux, and it Works For Me (TM). Gonna
check it in shortly.
--- upload.py (revision 21160)
+++ upload.py (working copy)
@@ -11,6 +11,8 @@
__revision__ = "$Id$"
import os, string
+import errno
+from random import random
from cgi import parse_header
from rfc822 import Message
from time import time, strftime, localtime
@@ -149,13 +151,46 @@
def __repr__ (self):
return "<%s at %x: %s>" % (self.__class__.__name__, id(self), self)
+ def _open (self, dir):
+ """
+ Generate a unique filename in 'dir'. Open and return a
+ writeable file object from it.
+ """
+ while 1:
+ now = time()
+ tstamp = strftime("%Y%m%d.%H%M%S", localtime(now))
+
+ # Get 32 bits of fuzz -- don't use sys.maxint in case this
+ # is a 64-bit machine -- 32 bits is plenty.
+ # XXX random() not threadsafe!
+ fuzz = "%08x" % (random() * 2147483647)
+ filename = "upload.%s.%s.%s" % (tstamp, os.getpid(), fuzz)
+ filename = os.path.join(dir, filename)
+ flags = os.O_WRONLY|os.O_CREAT|os.O_EXCL
+ try:
+ flags |= os.O_BINARY # for Windows
+ except AttributeError:
+ pass
+ try:
+ fd = os.open(filename, flags)
+ except OSError, err:
+ if err.strerror == errno.EAGAIN:
+ # Filename collision -- try again on the
+ # next time through the loop.
+ pass
+ else:
+ # Bomb on any other error.
+ raise
+ else:
+ # Opened the file just fine; it now exists so no other
+ # process or thread will be able to grab that filename.
+ break
+
+ # Wrap a file object around the file descriptor.
+ return (os.fdopen(fd, "wb"), filename)
+
def receive (self, file, boundary, dir):
- now = time()
- tstamp = (strftime("%Y%m%d.%H%M%S", localtime(now)) +
- ("%.3f" % (now % 1))[1:])
- filename = "upload.%s.%s" % (tstamp, os.getpid())
- filename = os.path.join(dir, filename)
- ofile = open(filename, "wb")
+ (ofile, filename) = self._open(dir)
done = read_mime_part(file, boundary, ofile=ofile)
ofile.close()
self.tmp_filename = filename
--
Greg Ward - software developer gward@mems-exchange.org
MEMS Exchange http://www.mems-exchange.org